Node.js 使所有单个用户无效';express.js中的会话

Node.js 使所有单个用户无效';express.js中的会话,node.js,session,express,Node.js,Session,Express,出于安全原因,我们希望能够使用户的所有活动会话无效,例如,如果用户更改了密码,或者只是希望能够强制注销其其他会话。我们正在使用Node.js、Express、Express会话和Redis会话存储。在我们的应用程序中,我们有(CoffeeScript): Redis存储通过将唯一会话id映射到会话中存储的任何数据来工作。例如: # In an HTTP request req.session.user = { _id: "user-id" } 在Redis中变成: > get "sess

出于安全原因,我们希望能够使用户的所有活动会话无效,例如,如果用户更改了密码,或者只是希望能够强制注销其其他会话。我们正在使用Node.js、Express、Express会话和Redis会话存储。在我们的应用程序中,我们有(CoffeeScript):

Redis存储通过将唯一会话id映射到会话中存储的任何数据来工作。例如:

# In an HTTP request
req.session.user = { _id: "user-id" }
在Redis中变成:

> get "sess:<session-id>"
'{ "user": { "_id": "user-id" } } '
>获取“sess:
“{”用户“:{”用户id“}”
我们需要的是一种跟踪与每个用户id对应的所有会话的方法,这样,如果我们想使用户的会话无效,就可以从Redis中删除这些会话。以下注意事项适用:

  • 在Redis中,会话的TTL等于 曲奇每个会话的跟踪机制也应该过期 在此时间之后,可避免过时的数据
  • 并非所有会话都必须与用户关联。有些只是用来跟踪匿名会话的详细信息
  • 在Redis中添加另一个反向查找键(例如,将用户id映射到用户的一组会话id)的简单方法在涉及警告(1)时失败

    这感觉像是使用Express的其他站点必须遇到的问题,因为这是一种非常常见的安全模式。有没有人对如何跟踪用户会话并在需要时使其失效有任何建议


    谢谢大家!

    对于类似的情况,我所做的是使用自定义会话ID,该ID在密钥名中包含用户ID。也许现在有一种更简单的方法来实现这一点,但我基本上要做的是设置自定义会话id:

    main.js:

    var uid = require('uid'),
        redis = require('redis'),
        session = require('express-session'),
        RedisStore = require('connect-redis')(session),
        Session = session.Session,
        Cookie = session.Cookie;
    
    var utils = require('./utils');
    
    var COOKIE_SECRET = 'somethingrandom',
        COOKIE_KEY = 'mycustomsession';
    
    var redisClient = redis.createClient(),
        redisStore = new RedisStore({
          client: redisClient,
          ttl: 24 * 60 * 60, // 1 day session expiration
          prefix: 'sess:'
        });
    
    // ... then inside the login route after user was successfully authenticated ...
    req.sessionStore = redisStore;
    req.sessionID = 'sess:' + user.id + ':' + uid(24);
    req.session = new Session(req);
    req.session.cookie = new Cookie({});
    req.session.user = user;
    utils.createSession(req, res, COOKIE_KEY, COOKIE_SECRET);
    
    utils.js:

    var onHeaders = require('on-headers'),
        signature = require('cookie-signature');
    exports.createSession = function(req, res, name, secret) {
      var trustProxy = true;
      // ripped from express-session
      onHeaders(res, function() {
        if (!req.session)
          return;
    
        var cookie = req.session.cookie
          , proto = (req.headers['x-forwarded-proto'] || '').split(',')[0].toLowerCase().trim()
          , tls = req.connection.encrypted || (trustProxy && 'https' == proto);
    
        // only send secure cookies via https
        if (cookie.secure && !tls)
          return;
    
        var val = 's:' + signature.sign(req.sessionID, secret);
        res.cookie(name, val, cookie.data);
      });
    
      // proxy end() to commit the session
      var end = res.end;
      res.end = function(data, encoding) {
        res.end = end;
        if (!req.session) return res.end(data, encoding);
        req.session.resetMaxAge();
        req.session.save(function(err) {
          if (err) console.error(err.stack);
          res.end(data, encoding);
        });
      };
    };
    

    谢谢然后如何使用户的所有会话过期?我们在Redis中存储了大量其他数据,使用
    键或
    扫描
    进行完全扫描实际上是不可行的。我想,我们需要能够进行某种直接查找。我使用带有模式的
    SCAN
    ,没有任何问题。但是,您可以使用单独的数据库进行会话和
    SCAN
    ,或者使redis键不唯一(键入前缀+用户id)以及包含该用户会话JSON数组的值?谢谢,我认为单独的数据库和
    SCAN
    的组合在这种情况下确实可以工作。谢谢你的回答!
    var onHeaders = require('on-headers'),
        signature = require('cookie-signature');
    exports.createSession = function(req, res, name, secret) {
      var trustProxy = true;
      // ripped from express-session
      onHeaders(res, function() {
        if (!req.session)
          return;
    
        var cookie = req.session.cookie
          , proto = (req.headers['x-forwarded-proto'] || '').split(',')[0].toLowerCase().trim()
          , tls = req.connection.encrypted || (trustProxy && 'https' == proto);
    
        // only send secure cookies via https
        if (cookie.secure && !tls)
          return;
    
        var val = 's:' + signature.sign(req.sessionID, secret);
        res.cookie(name, val, cookie.data);
      });
    
      // proxy end() to commit the session
      var end = res.end;
      res.end = function(data, encoding) {
        res.end = end;
        if (!req.session) return res.end(data, encoding);
        req.session.resetMaxAge();
        req.session.save(function(err) {
          if (err) console.error(err.stack);
          res.end(data, encoding);
        });
      };
    };