无效化JSON Web Tokens
无效化JSON Web Tokens
我在开发一个新的node.js项目时,考虑从基于cookie的session方式(这意味着在用户浏览器中存储用户session id到一个键值存储中)转换为基于令牌的session方式(无键值存储)使用JSON Web Tokens(jwt)。
该项目是一个利用socket.io的游戏 - 在这种情况下,基于令牌的会话对于存在单个会话中的多个通信频道(Web和socket.io)将是有用的。
如何使用jwt方法从服务器提供令牌/会话失效?
我还想了解使用这种范例时应该注意什么常见(或不常见)的陷阱/攻击。例如,如果该范例与会话存储/基于cookie的方式受到相同/不同种类的攻击威胁。
Session Store登录:
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}); }); }
--
Session Store方法的注销(或失效)需要在KeyValueStore数据库中使用指定的令牌更新。
由于令牌本身包含通常存在于键值存储中的信息,因此似乎在基于令牌的方式中不会存在这样的机制。
我也一直在研究这个问题,虽然下面的想法都不是完全的解决方案,但它们可能有助于排除某些想法或提供更多的想法。
1) 简单地从客户端中删除令牌
显然,这对于服务器端的安全没有任何帮助,但它可以通过从存在中删除令牌(即攻击者必须在注销之前窃取令牌)来阻止攻击者。
2) 创建令牌黑名单
你可以存储无效的令牌,直到它们的初始过期日期,并将它们与传入的请求进行比较。然而,这似乎抵消了完全基于令牌的原因,因为你需要为每个请求访问数据库。但存储大小可能会较低,因为你只需要存储在注销和过期时间之间的令牌(这是一种直觉,具体情况依赖于上下文)。
3) 保持令牌过期时间短并经常轮换
如果你将令牌过期时间保持在足够短的时间间隔内,并让正在运行的客户端跟踪并在必要时请求更新,那么第一种方法将有效地作为完整的注销系统。然而,这种方法的问题在于,它使得不可能在客户端代码关闭之间保持用户登录(取决于你设置的过期间隔时间的长度)。
应急计划
如果有紧急情况或用户令牌被攻击,则可以让用户使用其登录凭据更改底层用户查找ID。这会使所有关联的令牌无效,因为无法再找到关联的用户。
我还想指出,将上次登录日期与令牌一起包含是一个好主意,这样你就能够在一段时间后强制重新登录。
关于使用令牌进行攻击方面的相似性/差异,这篇帖子回答了这个问题: https://github.com/dentarg/auth0-blog/blob/master/_posts/2014-01-07-angularjs-authentication-with-cookies-vs-token.markdown