在 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。

因此,每当您更改会话时,您都需要在bodyqueryparams 中传递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 处理会话

AttributeError:“系列”对象没有属性“to_coo”

COO,CFO,CTO,CXO各是啥职位?

Coo_matrix和其他矩阵示例