关于 JSON Web 令牌 (JWT) 的安全性和可靠性问题

Posted

技术标签:

【中文标题】关于 JSON Web 令牌 (JWT) 的安全性和可靠性问题【英文标题】:Security and reliability concerns about JSON Web Tokens (JWT) 【发布时间】:2016-12-20 19:23:50 【问题描述】:

我正在为个人项目创建一个 API 和一个 SPA,我在以下用于验证用户身份的解决方案之间犹豫不决(注意:通过 HTTPS):

    HTTP 基本身份验证(发送每个请求的用户名/密码) 基于令牌的身份验证(将经过 SHA1 的用户令牌存储在数据库中) JSON Web 令牌 (JWT) 身份验证

我什至不考虑 OAuth,因为它看起来真的很痛苦,而且我不需要使用其他应用进行身份验证,我只关心对用户进行身份验证。

据我所知,JWT 似乎是一个不断发展的标准。它基本上保存了调用者的数据,因此每次他使用encrypt(base64(header) + "." + base64(payload)) 向您发出 API 请求时,您都将其与令牌本身最后一部分中提供的签名进行比较。它避免了执行数据库事务。

问题是,如果我使用 JWT 1),我无法手动撤销特定令牌,最重要的是 2)如果我更改用户的权限,先前授予的 JWT 仍将拥有具有旧权限的旧数据,只要他没有获得具有新权限的新令牌,就可以授予/限制他对某些数据的连续访问,即真的有问题,我很惊讶我还没有看到有人提到这个问题。此外,3) JWT 声称允许服务器在无需访问数据库的情况下验证访问权限,但我无法想象任何不涉及数据库的 API 请求,即使只是为了向用户返回数据要求。所以这个论点对我来说没有任何意义。

对我来说,我现在最好的选择是选项 2。网站的流量有限且流量较小,因此将令牌存储在数据库中似乎是一个小而值得的权衡,并允许我对这些令牌做任何我想做的事情,包括管理它们的生命周期和权限。它还可以避免像选项 1 那样暴露用户的凭据,以防他们将相同的凭据用于其他在线服务。

我只是想知道我对 JWT 的担忧是否正确,或者我是否误解了它的功能?此外,即使我已经阅读了很多关于这些不同选项的内容,请随意链接任何可以启发我并帮助我做出更好选择的内容。谢谢。

【问题讨论】:

【参考方案1】:

您是对的,在过期时间之前使令牌无效是常见的 JWT 问题。有几个原因需要考虑:帐户删除/阻止/暂停、密码更改、权限更改、管理员注销的用户。

使用 JWT,您还可以设置 令牌黑名单 来存储在注销和过期时间之间的令牌,标记过期并在每个请求中检查它。您可以仅包含 ID(JWT 的jti 声明)或使用上次登录日期和 iat 声明(发布于)

当用户更改密码/权限时使令牌无效的其他技术是使用这些字段的哈希对令牌进行签名。如果字段值发生更改,任何以前的令牌都会自动验证失败。

见https://***.com/a/37520125/6371459

最后,请注意令牌是用服务器私钥签名的(未加密)

sign(base64(header) + "." + base64(payload))

【讨论】:

使用用户配置文件字段的哈希签名听起来是个好主意,并且解决了问题 2)。感谢您的解释。 关于 token blacklist,我认为如果您要在 dabatase 上存储任何内容,然后存储生成的令牌,因为它可以让您更好地控制它们(而且您不能将其列入黑名单如果您在生成时没有将其保存在某个地方,则为先前生成的令牌)。 如果您不希望撤销太多令牌,您也可以使用内存中的黑名单。您只需要在更新用户和currentTime - maxExpiryTime <lastLoginDate(iat) 的关键数据后设置一个条目。当currentTime - maxExpiryTime> lastModified 时可以丢弃该条目(不再发送未过期的令牌)。在这种情况下,您不需要存储整个令牌。只是subiat,也许还有jti

以上是关于关于 JSON Web 令牌 (JWT) 的安全性和可靠性问题的主要内容,如果未能解决你的问题,请参考以下文章

了解 Web 身份验证上下文中的 JSON Web 令牌 (JWT)

如何以安全的方式为客户提供 JSON Web 令牌(JWT)?

JSON Web Token

登录令牌JWT一文详解 — JSON WEB TOKEN#yyds干货盘点#

为啥要使用环境变量对 JSON Web 令牌 (JWT) 进行签名?

JSON Web 令牌(JWT)是如何保护 API 的?