使JSON Web令牌无效
对于我正在开发的一个新的node.js项目,我正在考虑从基于cookie的会话方法切换(我的意思是,将id存储到包含用户浏览器中的用户会话的键值存储)转换为使用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});
});
}
-
会话存储方法的注销(或无效)需要使用指定的令牌更新KeyValueStore数据库。
似乎这种机制在基于令牌的方法中不存在,因为令牌本身将包含通常存在于键值存储中的信息。
我也一直在研究这个问题,尽管下面的想法都不是完整的解决方案,但它们可能会帮助其他人排除想法,或者提供更多的想法。
1)只需从客户端删除令牌
显然,这对服务器端安全性没有任何帮助,但它确实通过从存在中删除令牌来阻止攻击者(也就是说,他们必须在注销之前窃取令牌)。
2)创建一个令牌黑名单
您可以存储无效令牌,直到它们的初始失效日期,并将它们与传入的请求进行比较。 这似乎抵消了首先完全实现令牌的原因,因为您需要为每个请求触摸数据库。 虽然存储大小可能会更低,因为您只需存储注销和到期时间之间的令牌(这是一种直觉,而且绝对依赖于上下文)。
3)将令牌过期时间缩短并经常旋转
如果您保持令牌到期时间的时间间隔足够短,并且正在运行的客户端会在必要时跟踪并请求更新,则号码1将有效地用作完整的注销系统。 这种方法的问题在于,它使得用户无法在客户端代码的关闭之间保持登录(取决于您到期时间的长短)。
临时计划
如果遇到紧急情况,或者用户令牌被盗用,您可以做的一件事就是允许用户使用其登录凭据更改基础用户查找ID。 这将使所有相关的令牌无效,因为关联的用户将不能再被找到。
我还想指出,将最后一次登录日期与令牌包含在一起是一个好主意,以便在一段时间后能够执行重新登录。
就使用标记的攻击方面的相似性/差异而言,这篇文章解决了以下问题:http://blog.auth0.com/2014/01/07/angularjs-authentication-with-cookies-vs-token/
上面提到的想法很好,但是使现有的所有JWT失效的一个非常简单和简单的方法就是改变秘密。
如果您的服务器创建JWT,请使用秘密(JWS)对其进行签名,然后将其发送给客户端,只需更改秘密即可使所有现有令牌失效,并要求所有用户获得新令牌以进行身份验证,因为旧令牌突然变得无效到服务器。
它不需要对实际标记内容(或查找标识)进行任何修改。
显然这只适用于紧急情况,当你想要所有现有令牌到期时,对于每个令牌到期,需要上述解决方案之一(例如短令牌到期时间或令令牌内存储的密钥无效)。
这主要是一个长期的评论,支持和建立@mattway的答案
鉴于:
该页面上的其他一些建议的解决方案主张在每次请求时都触发数据存储。 如果您点击主数据存储以验证每个认证请求,那么我看不到使用JWT的原因,而不是其他建立的令牌认证机制。 您基本上使JWT成为有状态的,而不是每次访问数据存储时的无状态。
(如果您的网站收到大量的未经授权的请求,那么JWT会拒绝它们,而不会触及数据存储区,这很有帮助。可能还有其他用例。)
鉴于:
真正的无状态JWT认证无法实现典型的真实世界Web应用程序,因为无状态的JWT无法为以下重要用例提供即时和安全的支持:
用户的帐户被删除/阻止/暂停。
用户的密码已更改。
用户的角色或权限已更改。
用户由管理员注销。
网站管理员更改了JWT令牌中的任何其他应用程序关键数据。
在这些情况下,您不能等待令牌过期。 令牌失效必须立即发生。 此外,您不能相信客户端不会保留和使用旧令牌的副本,无论是否有恶意。
因此:我认为来自@ matt-way,#2 TokenBlackList的答案是向JWT基础认证添加所需状态的最有效方式。
你有一个黑名单持有这些令牌,直到他们的到期日期被击中。 与用户总数相比,令牌列表将相当小,因为它只需保留列入黑名单的权限,直到其到期。 我通过将无效令牌放入redis,memcached或其他支持在密钥上设置过期时间的内存数据存储中实现。
对于每个通过初始JWT验证的验证请求,您仍然需要对内存数据库进行调用,但是您不必为整个用户组存储密钥。 (对于一个给定的网站,这可能会或可能不是什么大问题。)
链接地址: http://www.djcxy.com/p/60571.html