diff --git a/lib/context.js b/lib/context.js index ccb8d5c..0595b3b 100644 --- a/lib/context.js +++ b/lib/context.js @@ -226,6 +226,11 @@ class ContextSession { await this.remove(); return; } + if (session._requireRegenerate) { + await this.remove(); + if (this.opts.store) this.externalKey = uid.sync(24); + session.save(); + } const reason = this._shouldSaveSession(); debug('should save session: %s', reason); diff --git a/lib/session.js b/lib/session.js index 6961e3b..2f0ccec 100644 --- a/lib/session.js +++ b/lib/session.js @@ -113,6 +113,10 @@ class Session { this._requireSave = true; } + regenerate() { + this._requireRegenerate = true; + } + /** * commit this session's headers if autoCommit is set to false * diff --git a/test/cookie.test.js b/test/cookie.test.js index 568d2b1..efee7cf 100644 --- a/test/cookie.test.js +++ b/test/cookie.test.js @@ -672,6 +672,48 @@ describe('Koa Session Cookie', () => { }); }); + describe('ctx.session.regenerate', () => { + it('should change the session key, but not content', done => { + const app = new App(); + const message = 'hi'; + app.use(async function(ctx, next) { + ctx.session = { message: 'hi' }; + await next(); + }); + + app.use(async function(ctx, next) { + const sessionKey = ctx.cookies.get('koa:sess'); + if (sessionKey) { + await ctx.session.regenerate(); + } + await next(); + }); + + app.use(async function(ctx) { + ctx.session.message.should.equal(message); + ctx.body = ''; + }); + let koaSession = null; + request(app.callback()) + .get('/') + .expect(200, (err, res) => { + should.not.exist(err); + koaSession = res.headers['set-cookie'][0]; + koaSession.should.containEql('koa:sess='); + request(app.callback()) + .get('/') + .set('Cookie', koaSession) + .expect(200, (err, res) => { + should.not.exist(err); + const cookies = res.headers['set-cookie'][0]; + cookies.should.containEql('koa:sess='); + cookies.should.not.equal(koaSession); + done(); + }); + }); + }); + }); + describe('when get session before enter session middleware', () => { it('should work', done => { const app = new Koa(); diff --git a/test/store.test.js b/test/store.test.js index d1bbf93..66d802e 100644 --- a/test/store.test.js +++ b/test/store.test.js @@ -542,6 +542,48 @@ describe('Koa Session External Store', () => { }); }); + describe('ctx.session.regenerate', () => { + it('should change the session key, but not content', done => { + const app = new App(); + const message = 'hi'; + app.use(async function(ctx, next) { + ctx.session = { message: 'hi' }; + await next(); + }); + + app.use(async function(ctx, next) { + const sessionKey = ctx.cookies.get('koa:sess'); + if (sessionKey) { + await ctx.session.regenerate(); + } + await next(); + }); + + app.use(async function(ctx) { + ctx.session.message.should.equal(message); + ctx.body = ''; + }); + let koaSession = null; + request(app.callback()) + .get('/') + .expect(200, (err, res) => { + should.not.exist(err); + koaSession = res.headers['set-cookie'][0]; + koaSession.should.containEql('koa:sess='); + request(app.callback()) + .get('/') + .set('Cookie', koaSession) + .expect(200, (err, res) => { + should.not.exist(err); + const cookies = res.headers['set-cookie'][0]; + cookies.should.containEql('koa:sess='); + cookies.should.not.equal(koaSession); + done(); + }); + }); + }); + }); + describe('when store return empty', () => { it('should create new Session', done => { done = pedding(done, 2);