diff --git a/lib/context.js b/lib/context.js index 95681a0..8eb6a85 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.store) this.externalKey = opts.genid && opts.genid(ctx); + session.save(); + } const reason = this._shouldSaveSession(); debug('should save session: %s', reason); diff --git a/lib/session.js b/lib/session.js index c9019af..13a50fe 100644 --- a/lib/session.js +++ b/lib/session.js @@ -134,6 +134,9 @@ class Session { await this._sessCtx.commit(); } + regenerate() { + this._requireRegenerate = true; + } } module.exports = Session; diff --git a/test/cookie.test.js b/test/cookie.test.js index 462e56b..d771029 100644 --- a/test/cookie.test.js +++ b/test/cookie.test.js @@ -674,6 +674,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 caf5375..be3a5fe 100644 --- a/test/store.test.js +++ b/test/store.test.js @@ -544,6 +544,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);