在 connect/express 中使用 cookieSession() 时为会话设置单独的 maxAge
Posted
技术标签:
【中文标题】在 connect/express 中使用 cookieSession() 时为会话设置单独的 maxAge【英文标题】:Set individual maxAge for sessions when using cookieSession() in connect/express 【发布时间】:2013-03-08 10:47:33 【问题描述】:我正在尝试使用 connect/express cookieSession()
将我的 node.js 会话存储在 cookie 中(从而避免使用服务器端会话存储)。这将帮助我在用户登录时“记住”用户,即使在服务器重新启动后也能保持会话处于活动状态。
我想用cookieSession()
来做这件事:
app.use( express.cookieSession( secret: 'secret_key' ) );
app.use( function (req, res, next)
if ( req.method == 'POST' && req.url == '/login' )
if ( req.body.remember )
req.session.cookie.maxAge = 30*24*60*60*1000; // Rememeber 'me' for 30 days
else
req.session.cookie.expires = false;
next();
);
但是,这不起作用,因为 req.session.cookie 未定义。我也尝试了以下方法,但似乎没有用:
app.use( express.session( secret: 'secret_key' ) );
app.use( function (req, res, next)
if ( req.method == 'POST' && req.url == '/login' )
if ( req.body.remember )
req.cookies['connect.sess'].maxAge = 30*24*60*60*1000; // Rememeber 'me' for 30 days
else
rreq.cookies['connect.sess'].expires = false;
next();
);
【问题讨论】:
【参考方案1】:这也很晚,但它可能会帮助其他人。
在我看来,保持会话数据的最佳方式是将其存储在 redis 之类的东西中。该问题要求一种不使用服务器存储的方式,但我认为他更多地指的是 MemoryStore。也许不是,但不管怎样,这就是我所做的。
我使用了 express-session 和 connect-redis
npm install -g connect-redis
npm install -g express-session
然后你配置东西。
// session modules
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session')
var redisStore = require('connect-redis')(session); // this sets up Redis to work with your session cookies
var app = express();
然后您只需将 store 选项设置为您的 redisStore 即可启动会话。 maxAge 部分将每个会话的生命周期设置为一小时,会话中间件在访问时将其重置。
app.use(bodyParser.json());
app.use(bodyParser.urlencoded( extended: false ));
app.use(cookieParser());
app.use(session(
store: new RedisStore(
host:'127.0.0.1',
port:6380,
prefix:'sess'
),
cookie: maxAge: 3600000 ,
secret: 'session_secret'
));
现在当客户端连接时,express 应该自动将会话数据存储在 Redis 数据结构中。由于它不只是缓存在内存中,因此您的服务器可能会崩溃,并且在指定的 IP 地址和端口上仍然可以使用所有相关的会话数据。
【讨论】:
【参考方案2】:有点晚了,但我认为这个答案可能会帮助人们继续前进......
我使用的是 cookie-session,它不会在 request.session
上创建 cookie 对象。为了使用 request.session.cookie
正确实现 rememberMe 功能,我将 cookie-session 切换到 express-session 并解决了所有问题。所以现在会话上有一个 cookie 对象,并且可以在请求中执行此操作...
npm install express-session
app.post('/login', function(request, response, next)
passport.authenticate('local', function(err, user, info)
if(err) return next(err);
if(!user)
request.flash('loginMessage', info.message);
return response.redirect('/account/login');
request.login(user, function(err)
if(err) return next(err);
if(request.body.rememberMe)
request.session.cookie.maxAge = 2592000000;
else
request.session.cookie.expires = false;
return response.redirect(options.redirect);
);
)(request, response, next);
);
【讨论】:
【参考方案3】:开始
app.use(express.cookieSession( secret: config.server.cookieSecret ));
并将其更改为
app.use(function(req, res, next)
express.cookieSession(
secret: config.server.cookieSecret,
cookie:
maxAge: req.param('remember') ? 20000 : 3000
,
)(req, res, next);
)
所以,我们创建自己的中间件,包裹在 cookieSession 中间件上,根据参数更改 maxAge。
因此,每当您更改会话时,您都需要在body
、query
或params
中传递remember
(这就是req.param()
的外观)。在大多数情况下,您只需在登录时为会话设置一次user_id
。
测试并确保其正常工作需要 3 秒或 20 秒。
同样,如果您在会话中设置了很多东西,这可能不是很有帮助,但是如果您只是在登录时将 user_id 设置为会话,这就是您所需要的。
如果您在会话中设置了很多东西,您应该知道每次请求都会传递数据,并且您应该只将最少的数据保存到会话中,例如 user_id,然后查找每个请求所需的数据, 以降低用户的开销。
【讨论】:
我不知道cookieSession
中间件,但请注意,如果您尝试使用 express-session
这样做,您将泄漏 EventEmitters,因为对 session(..)
的调用设置每次调用时的监听器。
@Sam 你确定这仍然是真的吗?
我最近没有检查过,但那是在 12 月发生的。
是的,回想起来,这似乎不是一个好主意。我可能会为每个参数创建一个新的expresss.router
,然后根据参数路由到每个参数【参考方案4】:
Yummy 似乎允许修改创建后过期的 cookie。
【讨论】:
【参考方案5】:我认为这可以满足您的要求:
// Using express.session instead of express.cookieSession
app.use(express.session( secret : 'secret_key' ));
app.use( function (req, res, next)
if ( req.method === 'POST' && req.url === '/login' )
if ( req.body.remember )
req.session.cookie.maxAge = 30*24*60*60*1000;
// needed to make the session `dirty` so the session middleware re-sets the cookie
req.session.random = Math.random();
else
req.session.cookie.expires = false;
next();
);
cookieSession
做了一些时髦的事情,比如del req.session.cookie
(不知道为什么)。
【讨论】:
我实际上已经尝试过了,但是会话没有保存到 cookie 中(服务器重新启动时会话被破坏)。另一方面,cookieSession 即使在服务器重新启动之间也会保持不变。 你说得对,我误解了我的测试用例的结果。express.session
默认会使用 MemoryStore,它会在服务器重启时重置。【参考方案6】:
你必须先设置req.session.cookie
,这样你才能设置maxAge
。在设置之前尝试使用它会给出req.session.cookie is undefined
express.cookieSession
具有它接受的默认值,请参阅here。您应该提及您将要使用的所有参数。您可以通过以下方式设置 cookie:
app.use(express.cookieSession( secret: 'secret_key', cookie : path: '/', httpOnly: true, maxAge: 30*24*60*60*1000 );
【讨论】:
设置所有会话 cookie 的 maxAge,但我不希望这样。我希望仅在选中登录表单上的记住我选项时才设置 maxAge。 设置使用 req.session.cookie= secret: 'secret_key', cookie : path: '/', httpOnly: true, maxAge: 30*24*60*60*1000 那行不通。我尝试在我的if (req.body.remember)
块中使用req.session.cookie= secret: 'secret_key', cookie : path: '/', httpOnly: true, maxAge: 30*24*60*60*1000
,但它没有正确设置cookie - 当我关闭浏览器并再次打开它时,我被注销了。以上是关于在 connect/express 中使用 cookieSession() 时为会话设置单独的 maxAge的主要内容,如果未能解决你的问题,请参考以下文章
Stripe Connect Express Webhook - 如何在用户完成 Stripe Connect Express 表单并被重定向后触发 Stripe Webhook
Connect/Express 中的“session”和“cookieSession”中间件有啥区别?
node.js + express.js:使用 mongodb/mongoose 处理会话