From 86c72bdded6b3c1c4f9ca37656341f0fc6b85a77 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Mon, 1 Apr 2013 10:55:49 -0700 Subject: [PATCH] session: add long expires check and prevent set-cookie --- examples/session.js | 34 ++++++++++++++++++++++++++++---- lib/middleware/session.js | 6 +++++- lib/middleware/session/cookie.js | 20 +++++++++++++++---- 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/examples/session.js b/examples/session.js index 5069b4c01..3db8a59ef 100644 --- a/examples/session.js +++ b/examples/session.js @@ -2,8 +2,34 @@ var connect = require('../') , http = require('http'); +var year = 31557600000; + +// large max-age, delegate expiry to the session store. +// for example with connect-redis's .ttl option. + +http.createServer(connect() + .use(connect.cookieParser()) + .use(connect.session({ secret: 'keyboard cat', cookie: { maxAge: year }})) + .use(connect.favicon()) + .use(function(req, res, next){ + var sess = req.session; + if (sess.views) { + sess.views++; + res.setHeader('Content-Type', 'text/html'); + res.write('

views: ' + sess.views + '

'); + res.write('

expires in: ' + (sess.cookie.maxAge / 1000) + 's

'); + res.end(); + } else { + sess.views = 1; + res.end('welcome to the session demo. refresh!'); + } + })).listen(3007); + +console.log('port 3007: 1 minute expiration demo'); + + // expire sessions within a minute -// /favicon.ico is ignored, and will not +// /favicon.ico is ignored, and will not // receive req.session http.createServer(connect() @@ -22,9 +48,9 @@ http.createServer(connect() sess.views = 1; res.end('welcome to the session demo. refresh!'); } - })).listen(3000); + })).listen(3006); -console.log('port 3000: 1 minute expiration demo'); +console.log('port 3006: 1 minute expiration demo'); // $ npm install connect-redis @@ -49,7 +75,7 @@ try { res.end('welcome to the redis demo. refresh!'); } })).listen(3001); - + console.log('port 3001: redis example'); } catch (err) { console.log('\033[33m'); diff --git a/lib/middleware/session.js b/lib/middleware/session.js index ec1ddccca..9be6c8b6e 100644 --- a/lib/middleware/session.js +++ b/lib/middleware/session.js @@ -256,6 +256,9 @@ function session(options){ // only send secure cookies via https if (cookie.secure && !secured) return debug('not secured'); + // long expires, handle expiry server-side + if (!isNew && cookie.hasLongExpires) return debug('already set cookie'); + // browser-session length cookie if (null == cookie.expires) { if (!isNew) return debug('already set browser-session cookie'); @@ -277,7 +280,8 @@ function session(options){ if (!req.session) return res.end(data, encoding); debug('saving'); req.session.resetMaxAge(); - req.session.save(function(){ + req.session.save(function(err){ + if (err) console.error(err.stack); debug('saved'); res.end(data, encoding); }); diff --git a/lib/middleware/session/cookie.js b/lib/middleware/session/cookie.js index e8ff86259..cdce2a5e6 100644 --- a/lib/middleware/session/cookie.js +++ b/lib/middleware/session/cookie.js @@ -43,7 +43,7 @@ Cookie.prototype = { * @param {Date} date * @api public */ - + set expires(date) { this._expires = date; this.originalMaxAge = this.maxAge; @@ -59,14 +59,14 @@ Cookie.prototype = { get expires() { return this._expires; }, - + /** * Set expires via max-age in `ms`. * * @param {Number} ms * @api public */ - + set maxAge(ms) { this.expires = 'number' == typeof ms ? new Date(Date.now() + ms) @@ -104,6 +104,18 @@ Cookie.prototype = { } }, + /** + * Check if the cookie has a reasonably large max-age. + * + * @return {Boolean} + * @api private + */ + + get hasLongExpires() { + var week = 604800000; + return this.maxAge > (4 * week); + }, + /** * Return a serialized cookie string. * @@ -121,7 +133,7 @@ Cookie.prototype = { * @return {Object} * @api private */ - + toJSON: function(){ return this.data; }