JWT 用于无状态 API,但会话控制用于安全性

Posted

技术标签:

【中文标题】JWT 用于无状态 API,但会话控制用于安全性【英文标题】:JWT for stateless API, but session control for security 【发布时间】:2016-03-25 04:07:00 【问题描述】:

我真的很想使用 JWT 进行 API 访问,以使其保持无状态。但同时我需要有强大的安全资源来拒绝尚未过期的令牌。

对于更敏感的用户信息 API,我可以依靠强制重新登录、比较 IP 地址等。但我仍然希望能够在需要时撤销用户令牌。我不介意支付间接费用。

我的设想是让每个用户根据他们的密码创建自己的密钥,并将其存储在会话中。我不介意用开销换取更简单的方法来处理被盗代币。这样一来,简单的密码重置就会使旧令牌失效。

承认权衡,这种方法有意义吗?有没有更好的方法来解决这个问题?

【问题讨论】:

【参考方案1】:

您应该在您的服务器上创建一个“黑名单”。如果需要撤销某个令牌,请将其放入黑名单,并在令牌到期时将其设置为从列表中过期。对于每次身份验证尝试,您将验证传入的 JWT 是否不在黑名单中。 Redis 可以让这变得非常简单。

或者,考虑使用第三方服务,例如 Stormpath。免责声明:我为Stormpath 工作。我们有一个 Oauth2 api,可让您发出访问 + 刷新令牌(用于密码授予流程)。只要您不介意 REST 调用验证令牌状态的开销,我们就会为您处理撤销。请参阅Using Stormpath for OAuth 2.0 and Access/Refresh Token Management。我们的Express-Stormpath.library 对此提供了轻松的支持

【讨论】:

我很想听到 Stormpath 对相关安全问题的回应:破坏基于 JWT 的服务器的破坏性有多大? ***.com/questions/37495362/…【参考方案2】:

好吧,我只是有同样的实现。将哈希密码添加到令牌中,当客户端返回令牌时,在验证期间检查用户密码是否已在数据库中更改,如果用户的哈希密码与您放入令牌的密码不同,则拒绝令牌。这样,您就不需要在服务器上保留任何有关用户和/或令牌的信息。

【讨论】:

【参考方案3】:

我不喜欢白名单/黑名单令牌的想法,所以我最终使用用户散列密码 + 另一个随机密钥作为他们令牌的密钥:

+---------------+------------------------------------+-----------+
|     email     |              password              |    key    |
+---------------+------------------------------------+-----------+
| user@mail.com | asfsifj2fij4f4f4f8d9dfhs.8f8fhsd8h | r4nd0Mk3Y |
+---------------+------------------------------------+-----------+

然后,我在用户id=>password+key 的内存中保留一个缓存,以验证每个用户令牌。这种方式可以在以下情况下丢弃令牌:1)用户重置密码; 2)应用程序更改用户key

这几乎违背了 JWT 的目的,但我的用例需要这层安全性。

【讨论】:

【参考方案4】:

JSON 网络令牌

JSON Web Token (JWT) 由 RFC 7519 定义。

这是在两方之间安全地表示索赔的标准方法。 JWT 是一个自包含的令牌,使您能够在有效负载中存储用户标识符、到期日期和任何您想要的(但不存储密码),这是一个编码为JSON Base64.

客户端可以读取负载,并且可以通过在服务器上验证其签名来轻松检查令牌的完整性。

跟踪您的令牌

如果您不需要跟踪 JWT 令牌,则无需保留它们。

尽管如此,通过持久化令牌,您将有可能使它们无效并撤销它们的访问权限。要跟踪 JWT 令牌,而不是保留整个令牌,您可以根据需要保留令牌标识符(jti 声明)和一些元数据(您为其颁发令牌的用户、到期日期等)。

您的应用程序可以提供一些功能来撤销令牌,但始终考虑在用户更改密码时撤销令牌。

在持久化令牌时,请始终考虑删除旧令牌,以防止您的数据库无限增长。

其他信息

通过网络发送敏感数据时,您最好的朋友是 HTTPS,它可以保护您的应用程序免受 man-in-the-middle attack 的攻击。

要找到一些与 JWT 合作的重要资源,请查看 http://jwt.io。

【讨论】:

以上是关于JWT 用于无状态 API,但会话控制用于安全性的主要内容,如果未能解决你的问题,请参考以下文章

Spring Cloud Zuul API 网关不会为无状态会话转发 JWT 令牌

Springboot + JWT +OAuth2 + AngularJS 无状态会话

ASP.Net Core 2.1 API JWT 无 cookie 会话?

新的无状态 JWT 认证理念!它真的安全吗?

springCloud-依赖Spring Security使用 JWT实现无状态的分布式会话

基于 JWT + Refresh Token 的用户认证实践