PYTHON - 如何使JWT令牌无效?

8 浏览
0 Comments

PYTHON - 如何使JWT令牌无效?

对于我正在开发的一个新的node.js项目,我正在考虑从基于cookie的会话方式(即在用户浏览器中存储包含用户会话的键值存储的id)转换为基于令牌的会话方式(无键值存储),并使用JSON Web Tokens(JWT)。\n该项目是一个利用socket.io的游戏,使用基于令牌的会话对于在单个会话中存在多个通信渠道(Web和socket.io)的场景非常有用。\n如何使用jwt方法从服务器提供令牌/会话失效?\n我还想了解在这种范式中应该注意哪些常见(或不常见)的陷阱/攻击。例如,如果这种范式容易受到与会话存储/基于cookie的方法相同/不同类型的攻击。\n因此,假设我有以下内容(改编自这个这个):\n基于会话存储的登录:\n

app.get('/login', function(request, response) {
    var user = {username: request.body.username, password: request.body.password };
    // 验证
    validate(user, function(isValid, profile) {
        // 创建会话令牌
        var token= createSessionToken();
        // 添加到键值数据库
        KeyValueStore.add({token: {userid: profile.id, expiresInMinutes: 60}});
        // 客户端应该将此会话令牌保存在cookie中
        response.json({sessionToken: token});
    });
}

\n基于令牌的登录:\n

var jwt = require('jsonwebtoken');
app.get('/login', function(request, response) {
    var user = {username: request.body.username, password: request.body.password };
    // 验证
    validate(user, function(isValid, profile) {
        var token = jwt.sign(profile, 'My Super Secret', {expiresInMinutes: 60});
        response.json({token: token});
    });
}

\n--\n基于会话存储的注销(或失效)需要更新KeyValueStore数据库中指定令牌的内容。\n似乎在基于令牌的方法中不需要这样的机制,因为令牌本身包含了通常存在于键值存储中的信息。

0
0 Comments

在使用JWT令牌时,可能会遇到无效的JWT令牌的问题。这个问题的出现主要是因为真正的无状态JWT无法提供对一些重要用例的立即和安全的支持,比如用户的账户被删除/阻止/暂停、用户的密码被更改、用户的角色或权限被更改、用户被管理员登出、站点管理员更改了JWT令牌中的任何其他应用关键数据等。在这些情况下,不能等待令牌过期,令牌必须立即失效。此外,不能相信客户端不会保留和使用旧令牌的副本,无论是出于恶意目的还是其他原因。

解决这个问题的方法是创建一个黑名单,将这些令牌保存在其中,直到它们到达过期日期。令牌的数量将相对较小,因为它只需要保留失效的令牌直到其过期。可以通过将失效的令牌放入Redis、Memcached或其他支持在键上设置过期时间的内存数据存储来实现。虽然仍然需要为每个通过初始JWT认证的身份验证请求调用内存数据库,但不需要在其中存储整个用户集的密钥。

JWT的作用是解决身份验证和信息交换两个问题。在身份验证方面,用户登录后,每个后续请求都会包含JWT令牌,允许用户访问受该令牌允许的路由、服务和资源。在信息交换方面,JWT可以安全地在各方之间传输信息,因为JWT可以被签名,可以确保发送方的身份真实可信。然而,JWT并不能解决访问管理的问题,因为访问信息(角色、权限)是实时编辑的,而JWT令牌是无状态的,无法被编辑,因此在这方面是无用的。每当第三方使用Google的令牌代表用户执行某个操作时,该令牌必须在数据库中进行验证,否则无法撤销。因此,数据库不能从方案中移除。

此外,JWT的目的是为了解决在负载均衡的Web应用程序中管理会话的复杂性。使用JWT可以获取用户的信息,如姓名和电子邮件,而不需要使用粘性会话。但是,仅使用JWT是不足以创建一个安全可靠的系统的。无论如何,解决这个问题的方法是将失效的令牌放入黑名单,以确保令牌的立即失效,并在需要时进行数据库验证。

0
0 Comments

问题出现的原因:在JWT验证过程中,当需要使所有现有的JWT token失效时,一种简单的方法是更改密钥(secret)。服务器创建JWT并使用密钥进行签名后发送给客户端,只需更改密钥即可使所有现有的token失效,需要用户获取新的token进行身份验证,因为服务器认为旧的token已经无效。

解决方法:更改密钥是使所有现有JWT token失效的一种方法,但这只适用于紧急情况,当你希望所有现有的token过期时使用。对于每个token的过期,可以使用上述解决方案之一,例如设置短的token过期时间或使token中存储的密钥无效。

然而,这种方法并不理想。想象一种情况,你正在使用公钥,你不希望每次需要使单个token无效时都要重新创建公钥。

对于使用公共/私有密钥对来验证签名的情况,可以使用公钥作为RS256算法中的密钥。在这个例子中,他提到了更改密钥来使JWT失效。可以通过引入一个不匹配签名的伪公钥或生成一个新的公钥来实现。但在这种情况下,这并不理想,因为可能有其他人依赖于公钥来验证签名。

另一种不好的解决方法是使用动态密钥,这将引入状态。如果服务在多个节点上进行集群,每次发放新的token时都需要同步密钥。必须将密钥存储在受保护的资源上,如果密钥泄露,就必须更改密钥并将更改分发给每个节点。大多数托管提供商通常允许在其服务中存储密钥,以便轻松可靠地分发这些密钥。

对于已经拥有大量现有客户的应用程序,这不是一个可行的选择。大多数用户根本不记得他们的密码,强制将他们无差别地注销将损害用户体验。

此外,无法通过注销来使单个token失效,这被认为是最糟糕的想法。按照这种方法,用户需要拥有唯一的密钥,这并不理想。总之,这是一种简单的原始方法,但并不实用。

0
0 Comments

问题:如何使JWT令牌无效?

出现原因:

1) 从客户端删除令牌可以阻止攻击者使用令牌,但不能提供服务器端的安全性。

2) 创建一个令牌黑名单,将无效的令牌存储起来,并与传入的请求进行比较,但这样做需要在每个请求中访问数据库。

3) 将令牌的过期时间设置得很短,并经常更换,这样可以实现完整的注销系统,但这会导致用户在关闭客户端代码后无法保持登录状态。

解决方法:

1) 从客户端删除令牌。

2) 创建一个令牌黑名单,将无效的令牌存储起来,并与传入的请求进行比较。

3) 将令牌的过期时间设置得很短,并经常更换。

4) 允许用户使用登录凭据更改底层用户查找ID,这样可以使所有相关令牌无效。

其他建议:

1) 包括令牌的最后登录日期,以便在一段时间后强制重新登录。

2) 将令牌与用户的密码哈希进行签名,这样如果密码更改,之前的令牌将无法验证。

3) 在内存中保持黑名单,只在服务器启动时读取数据库,使黑名单的访问更高效。

4) 实现账户锁定期限,使账户在令牌过期后无法访问。

不同解决方案的优缺点:

1) 解决方案1无法提供服务器端的安全性。

2) 解决方案2需要每个请求访问数据库。

3) 解决方案3可能会导致前端/客户端频繁刷新令牌。

4) 解决方案4可能在MYSQL等基于数据库的解决方案中引起问题。

要使JWT令牌无效,可以通过从客户端删除令牌、创建令牌黑名单、设置短暂的过期时间和经常更换令牌等方式来实现。此外,还可以使用密码哈希和账户锁定期限来增加令牌的安全性。然而,不同的解决方案各有优缺点,需要根据具体情况选择合适的方法。

0