对于我正在从事的一个新的node.js项目,我正在考虑从基于cookie的会话方法(我的意思是,将id存储到用户浏览器中包含用户会话的键值存储中)切换到使用JSON Web Tokens (jwt)的基于令牌的会话方法(没有键值存储)。
这个项目是一个利用socket的游戏。IO——在一个会话(web和socket.io)中有多个通信通道的情况下,有一个基于令牌的会话会很有用。
如何使用jwt方法从服务器提供令牌/会话失效?
我还想了解使用这种范例应该注意哪些常见的(或不常见的)陷阱/攻击。例如,如果这种模式容易受到与基于会话存储/cookie的方法相同/不同类型的攻击。
所以,假设我有以下内容(改编自this和this):
会话存储登录:
app.get('/login', function(request, response) {
var user = {username: request.body.username, password: request.body.password };
// Validate somehow
validate(user, function(isValid, profile) {
// Create session token
var token= createSessionToken();
// Add to a key-value database
KeyValueStore.add({token: {userid: profile.id, expiresInMinutes: 60}});
// The client should save this session token in a cookie
response.json({sessionToken: token});
});
}
口令登录:
var jwt = require('jsonwebtoken');
app.get('/login', function(request, response) {
var user = {username: request.body.username, password: request.body.password };
// Validate somehow
validate(user, function(isValid, profile) {
var token = jwt.sign(profile, 'My Super Secret', {expiresInMinutes: 60});
response.json({token: token});
});
}
--
会话存储方法的注销(或失效)需要更新KeyValueStore
使用指定的令牌创建数据库。
在基于令牌的方法中似乎不存在这样的机制,因为令牌本身将包含通常存在于键值存储中的信息。
---------------- 这个答案一点迟到但可能会帮助别人 ----------------
从客户端,最简单的方法是从浏览器的存储中删除令牌。
但是,如果您想销毁节点服务器上的令牌-
JWT包的问题是它没有提供任何方法或方法来销毁令牌。
您可以使用上面提到的关于JWT的不同方法。但是这里我用的是jwt-redis。
所以为了在服务器端销毁令牌,你可以使用JWT -redis包而不是JWT
这个库(jwt-redis)完全重复了库jsonwebtoken的全部功能,只增加了一个重要的功能。Jwt-redis允许您将tokenIdentifier存储在redis中以验证有效性。redis中缺少tokenIdentifier使得令牌无效。要销毁jwt-redis中的令牌,有一个destroy方法
它是这样工作的:
从npm安装jwt-redis
创建:
Var redis = require('redis');
var JWTR = require('jwt-redis').default;
var redisClient = redis.createClient();
var jwtr = new jwtr (redisClient);
Const secret = 'secret';
const tokenIdentifier = 'test';
const payload = {jti: tokenIdentifier};//你也可以在payload中放入其他数据
jwtr。号(载荷、秘密)
不要犹豫((令牌)= > {
//你的代码
})
.catch((错误)= > {
//错误处理
});
验证:
jwtr。验证(令牌,秘密);
摧毁:
//如果jti在token的签名过程中传递,那么tokenIdentifier else token
jwtr.destroy(tokenIdentifier或token)
注意:
1).你可以在token的登录过程中提供expiresIn,就像JWT中提供的一样。
2).如果在token的签名过程中没有传递jti,那么jti将由库随机生成。
也许这能帮到你或其他人。谢谢。
I ended up with access-refresh tokens, where refresh tokens uuids stored in database and access tokens uuids stored in cache server as a whitelist of valid access tokens. For example, I have critical changes in user data, for example, his access rights, next thing I do - I remove his access token from cache server whitelist and by the next access to any resource of my api, auth service will be asked for token's validity, then, if it isn't present in cache server whitelist, I will reject user's access token and force him to reauthorize by refresh token. If I want to drop user's session or all of his sessions, I simply drop all his tokens from whitelist and remove refresh tokens from database, so he musts re-enter credentials to continue accessing resources.
我知道,我的身份验证不再是无状态的,但公平地说,我为什么还要无状态的身份验证呢?