使express.js中的所有单个用户会话无效 [英] Invalidating all of a single user's sessions in express.js
问题描述
出于安全原因,我们希望能够使用户的所有活动会话均无效,例如,如果他们更改了密码,或者只是希望能够强制注销其他会话.我们正在使用Node.js,Express,express-sessions和Redis会话存储.在我们的应用中,我们有(CoffeeScript):
For security reasons we want to be able to invalidate all of a user's active sessions, for example if they change their password, or just want to be able to force log out their other sessions. We're using Node.js, Express, express-sessions and the Redis session store. In our app we have (CoffeeScript):
app.use express.session
cookie:
maxAge: 5 * 24 * 60 * 60 * 1000 # 5 days in ms
store: new RedisStore(client: rclient)
key: "secret-key"
Redis存储通过将唯一的会话ID映射到您存储在会话中的任何数据来工作.例如:
The Redis store works by mapping the unique session id to whatever data you store in the session. For example:
# In an HTTP request
req.session.user = { _id: "user-id" }
在Redis中变为:
> get "sess:<session-id>"
'{ "user": { "_id": "user-id" } } '
我们需要的是一种跟踪与每个用户ID对应的所有会话的方法,以便在我们希望使用户的会话无效时可以将它们从Redis中删除.需要注意以下几点:
What we need is a way to track all sessions that correspond to each user id, so that we can remove these from Redis if we want to invalidate a user's sessions. The following caveats apply:
- 在Redis中为会话赋予TTL,该TTL等于 曲奇饼.每个会话的跟踪机制也应该过期 在这段时间之后,以避免过时的数据.
- 并非所有会话都必须与用户相关联.有些只是用来跟踪匿名会话的详细信息.
- The sessions are given a TTL in Redis equal to the maxAge of the cookie. The tracking mechanism for each session should also expire after this time to avoid stale data.
- Not all sessions will necessarily be associate to a user. Some are just used to track anonymous session details.
涉及警告(1)时,在Redis中添加另一个反向查找键(例如将user_id映射到用户的一组会话ID)的幼稚方法失败.
The naive approach of adding another reverse look up key in Redis (for example mapping user_id to a set of session ids for the user) fails when it comes to caveat (1).
这是其他使用Express的站点必定遇到的问题,因为这是一种非常常见的安全模式.有人对如何跟踪用户会话然后按需使用户会话无效有任何建议吗?
This feels like a problem that other sites using Express must have encountered, since it's a very common security pattern. Does anyone have any suggestions for how to track the user sessions and then invalidate them on demand?
谢谢!
推荐答案
在类似情况下,我要做的是使用自定义会话ID,该ID在密钥名称中包含用户ID.也许现在有一种更简单的方法可以做到这一点,但是基本上这是我设置自定义会话ID所要做的:
What I did for a similar situation is to use a custom session ID that includes the user id in the key name. Maybe there's an easier way to do this now, but here's basically what I had to do to set a custom session 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);
});
};
};
这篇关于使express.js中的所有单个用户会话无效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!