服务器端处理 JWT 令牌的最佳实践 [英] Best practices for server-side handling of JWT tokens

查看:33
本文介绍了服务器端处理 JWT 令牌的最佳实践的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(源自这个线程,因为这个这真的是一个它自己的问题,而不是 NodeJS 等特有的)

(spawned from this thread since this is really a question of its own and not specific to NodeJS etc)

我正在实施带有身份验证的 REST API 服务器,并且我已成功实施 JWT 令牌处理,以便用户可以使用用户名/密码通过/login 端点登录,然后从服务器密钥生成 JWT 令牌并返回给客户.然后,令牌在每个经过身份验证的 API 请求中从客户端传递到服务器,服务器机密用于验证令牌.

I'm implementing a REST API server with authentication, and I have successfully implemented JWT token handling so that a user can login through a /login endpoint with username/password, upon which a JWT token is generated from a server secret and returned to the client. The token is then passed from the client to the server in each authenticated API request, upon which the server secret is used to verify the token.

但是,我试图了解有关如何以及在多大程度上验证令牌的最佳实践,以构建一个真正安全的系统.验证"令牌到底应该涉及什么?可以使用服务器机密验证签名是否足够,或者我还应该根据存储在服务器中的某些数据交叉检查令牌和/或令牌有效负载吗?

However, I am trying to understand the best practices for exactly how and to what extent the token should be validated, to make a truly secure system. Exactly what should be involved in "validating" the token? Is it enough that the signature can be verified using the server-secret, or should I also cross-check the token and/or token payload against some data stored in the server?

基于令牌的身份验证系统将仅与在每个请求中传递用户名/密码一样安全,前提是获取令牌的难度与获取用户密码的难度相同或更难.但是,在我看到的示例中,生成令牌所需的唯一信息是用户名和服务器端机密.这是否意味着假设恶意用户一分钟了解服务器机密,他现在可以代表任何用户生成令牌,从而不仅可以访问给定用户如果获得了密码,但实际上是所有用户帐户吗?

A token based authentication system will only be as safe as passing username/password in each request provided that it's equally or more difficult to obtain a token than to obtain a user's password. However, in the examples I've seen, the only information required to produce a token is the username and the server-side secret. Doesn't this mean that assuming for a minute that a malicious user gains knowledge of the server secret, he can now produce tokens on behalf of any user, thereby having access not only to one given user as would be the fact if a password was obtained, but in fact to all user accounts?

这让我想到了问题:

1) JWT 令牌验证是否应该仅限于验证令牌本身的签名,单独依赖服务器机密的完整性,还是伴随着单独的验证机制?

1) Should JWT token validation be limited to verifying the signature of the token itself, relying on the integrity of the server secret alone, or accompanied by a separate validation mechanism?

  • 在某些情况下,我看到了令牌和服务器会话的组合使用,在通过/login 端点成功登录后,会建立一个会话.API 请求验证令牌,并将令牌中找到的解码数据与会话中存储的一些数据进行比较.然而,使用会话意味着使用 cookie,并且在某种意义上它违背了使用基于令牌的方法的目的.它还可能会给某些客户带来问题.

  • In some cases I've seen the combined use of tokens and server sessions where upon successful login through the /login endpoint a session is established. API requests validate the token, and also compare the decoded data found in the token with some data stored in the session. However, using sessions means using cookies, and in some sense it defeats the purpose of using a token based approach. It also may cause problems for certain clients.

可以想象服务器将所有当前正在使用的令牌保存在内存缓存或类似的地方,以确保即使服务器机密被泄露,攻击者可能会产生有效"令牌,只有准确的令牌是通过/login 端点生成的将被接受.这是合理的还是只是多余/矫枉过正?

One could imagine the server keeping all tokens currently in use in a memcache or similar, to ensure that even if the server secret is compromised so that an attacker may produce "valid" tokens, only the exact tokens that were generated through the /login endpoint would be accepted. Is this reasonable or just redundant/overkill?

2) 如果 JWT 签名验证是验证令牌的唯一方法,这意味着服务器机密的完整性是突破点,那么服务器机密应该如何管理?从环境变量中读取并为每个部署的堆栈创建(随机?)一次?定期更新或轮换(如果是这样,如何处理轮换前创建但需要在轮换后验证的现有有效令牌,如果服务器在任何给定时间保持当前和前一个秘密就足够了)?还有什么?

2) If JWT signature verification is the only means of validating tokens, meaning the integrity of the server secret is the breaking point, how should server secrets be managed? Read from an environment variable and created (randomized?) once per deployed stack? Re-newed or rotated periodically (and if so, how to handle existing valid tokens that were created before rotation but needs to be validated after rotation, perhaps it's enough if the server holds on to the current and the previous secret at any given time)? Something else?

当谈到服务器机密被泄露的风险时,也许我只是过于偏执了,这当然是一个更普遍的问题,需要在所有加密情况下解决......

Maybe I'm simply being overly paranoid when it comes to the risk of the server secret being compromised, which is of course a more general problem that needs to be addressed in all cryptographic situations...

推荐答案

我也一直在为我的应用程序使用令牌.虽然我绝不是专家,但我可以分享我对此事的一些经验和想法.

I've been playing with tokens for my application as well. While I'm not an expert by any means, I can share some of my experiences and thoughts on the matter.

JWT 的本质是完整性.它为您的服务器提供了一种机制,用于验证提供给它的令牌是真实的并且是由您的服务器提供的.通过您的秘密生成的签名就是为此提供的.所以,是的,如果你的秘密以某种方式泄露,那个人可以生成你的服务器认为是它自己的令牌.仅仅因为签名验证,基于令牌的系统仍然比您的用户名/密码系统更安全.在这种情况下,如果有人拥有您的秘密,那么您的系统除了有人制作虚假令牌之外还有其他安全问题需要处理(即使如此,只需更改秘密即可确保使用旧秘密制作的任何令牌现在都无效).

The point of JWTs is essentially integrity. It provides a mechanism for your server verify that the token that was provided to it is genuine and was supplied by your server. The signature generated via your secret is what provides for this. So, yes, if your secret is leaked somehow, that individual can generate tokens that your server would think are its own. A token based system would still be more secure than your username/password system simply because of the signature verification. And in this case, if someone has your secret anyway, your system has other security issues to deal with than someone making fake tokens (and even then, just changing the secret ensures that any tokens made with the old secret are now invalid).

至于有效载荷,签名只会告诉您提供给您的令牌与您的服务器发送时完全相同.验证负载内容是否有效或适合您的应用程序显然取决于您.

As for payload, the signature will only tell you that the token provided to you was exactly as it was when your server sent it out. verifying the that the payloads contents are valid or appropriate for your application is obviously up to you.

对于您的问题:

1.) 以我有限的经验,最好使用第二个系统验证您的令牌.简单地验证签名仅意味着令牌是用您的秘密生成的.将任何创建的令牌存储在某种数据库(redis、memcache/sql/mongo 或其他一些存储)中是确保您只接受服务器创建的令牌的绝妙方法.在这种情况下,即使您的秘密被泄露,也没有太大关系,因为任何生成的令牌无论如何都是无效的.这是我对我的系统采取的方法 - 所有生成的令牌都存储在一个数据库(redis)中,并且在每个请求中,我在接受它之前验证令牌是否在我的数据库中.通过这种方式令牌可以因任何原因被撤销,例如以某种方式发布到野外的令牌、用户注销、密码更改、秘密更改等.

1.) In my limited experience, it's definitely better to verify your tokens with a second system. Simply validating the signature just means that the token was generated with your secret. Storing any created tokens in some sort of DB (redis, memcache/sql/mongo, or some other storage) is a fantastic way of assuring that you only accept tokens that your server has created. In this scenario, even if your secret is leaked, it won't matter too much as any generated tokens won't be valid anyway. This is the approach I'm taking with my system - all generated tokens are stored in a DB (redis) and on each request, I verify that the token is in my DB before I accept it. This way tokens can be revoked for any reason, such as tokens that were released into the wild somehow, user logout, password changes, secret changes, etc.

2.) 这是我没有太多经验的事情,我仍在积极研究,因为我不是安全专家.如果您找到任何资源,请随时在此处发布!目前,我只是使用从磁盘加载的私钥,但这显然不是最好或最安全的解决方案.

2.) This is something I don't have much experience in and is something I'm still actively researching as I'm not a security professional. If you find any resources, feel free to post them here! Currently, I'm just using a private key that I load from disk, but obviously that is far from the best or most secure solution.

这篇关于服务器端处理 JWT 令牌的最佳实践的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆