【问题标题】:Set individual maxAge for sessions when using cookieSession() in connect/express在 connect/express 中使用 cookieSession() 时为会话设置单独的 maxAge
【发布时间】: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();
});

【问题讨论】:

    标签: node.js express session-cookies connect


    【解决方案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 - 当我关闭浏览器并再次打开它时,我被注销了。
          猜你喜欢
          • 2012-03-31
          • 2013-07-15
          • 1970-01-01
          • 2012-07-27
          • 1970-01-01
          • 1970-01-01
          • 2012-12-20
          • 2015-09-16
          • 2012-02-15
          相关资源
          最近更新 更多