JWT 如何消除对每个请求进行数据库查找的需要?

Posted

技术标签:

【中文标题】JWT 如何消除对每个请求进行数据库查找的需要?【英文标题】:How does JWT eliminate the need for database lookups on every request? 【发布时间】:2017-05-22 11:08:17 【问题描述】:

我读到有一个 JWT 系统与一个简单的基于令牌的系统 eliminates token lookups in a database。但我不明白这怎么可能。如果它使用 HMAC 进行签名,服务器是否不需要为每个客户端查找密钥以验证其签名?还是所有客户端都使用相同的密钥? (听起来很不安全)。如果它使用非对称算法,是否还需要查找其中一个密钥来验证签名?

【问题讨论】:

【参考方案1】:

JWT 主要用于授权。每当用户成功使用他的密码(需要数据库查找)进行身份验证时,就会创建 JWT。此 JWT 将包含主要包含 UserIdentification 的有效负载。因此,每当用户向服务器发送子序列请求时,他都会将此 JWT 附加到标头。使用此 JWT,服务器将发现此用户已通过身份验证。但是仍然有授权。假设用户请求了服务 A。现在我们知道用户已通过身份验证,因此我们可以转到访问控制表并查看该用户是否有资格进行此服务调用。或者,如果我们在身份验证步骤将用户授权服务详细信息添加到 JWT 有效负载中,现在我们可以使用有效负载信息来做出授权决策,而不是查找数据库。这取决于开发人员。您可以使用这两种方式来授权用户。

【讨论】:

【参考方案2】:

在通常情况下,服务器需要凭据来验证用户身份(即用户和密码)。如果身份验证成功,则服务器发出一个 JWT,该 JWT 使用服务器的私钥而不是客户端签名。

签名保护内容并识别签名者。验证签名的服务器可以检测到对有效负载或签名的任何更改,并将拒绝 JWT。因此服务器可以依赖 JWT 中包含的数据

服务器可以在有效负载中包含身份验证所需的声明,例如用户 ID subexp 和其他感兴趣的声明,如 usernameemail 或授权 roles。见What to store in a JWT?。


    "sub": "joe",
    "iat": 1300819370,
    "exp": 1300819380,
    "email": "joe@***.com",
    "roles":["admin","finaluser"]

验证签名后,服务器可以直接使用包含的声明,而不是查询数据库。

使用对称密钥 (HMAC),签名和验证是使用相同的密钥完成的。非对称密钥对 (RSA) 由私钥和公钥组成。使用私钥进行签名并与公众进行验证。当您需要客户端验证 JWT 时使用非对称密钥。

【讨论】:

【参考方案3】:

您可以为每个客户端使用相同的密钥。而且是安全的!客户永远不会看到您的密钥。 JWT 允许您做的是验证负载是使用密钥签名的,只要它保持机密,您就会知道只有您可以对负载进行签名。

【讨论】:

如果客户端永远看不到密钥,他们如何签署自己的 JWT 消息?他们不需要钥匙来签名吗?谢谢 @Cyber​​Flower 重点是验证服务器是否发送了某些内容。例如,您可以将令牌保存在 cookie 中。

以上是关于JWT 如何消除对每个请求进行数据库查找的需要?的主要内容,如果未能解决你的问题,请参考以下文章

JWT 有效负载中的令牌

使用 JWT 进行身份验证时是不是可以消除私钥攻击向量?

Kubernetes集群中微服务之间如何进行JWT认证

如何使用 Socketio-jwt node.js 对用户进行身份验证

使用 JWT 对 json-server 进行授权

如何验证请求标头、JWT 令牌