Java JWT 中的“秘密”应该是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/42826251/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 00:26:26  来源:igfitidea点击:

What should be the "Secret" in JWT?

javarestjwtsecret-key

提问by Lemon Juice

I am going to apply JWT into my REST API developed using Java-Jersey. I am using this library for JWT - https://github.com/auth0/java-jwt

我打算将 JWT 应用到我使用 Java-Jersey 开发的 REST API 中。我正在将此库用于 JWT - https://github.com/auth0/java-jwt

I have few questions about the JWT - Secret

我有几个关于 JWT 的问题 - 秘密

  1. Does this Secrethas to be unique?
  2. Shall I use the hashed version of user's password for secret? (Then it is not unique anyway) This is because then when user changed his password, his token will be automatically invalid.
  1. Secret必须是独一无二的吗?
  2. 我应该使用用户密码的散列版本作为秘密吗?(无论如何它都不是唯一的)这是因为当用户更改密码时,他的令牌将自动失效。

回答by Jochen Bedersdorfer

Use RSA256 i.e. a private/public key-pair (no 'secret' required). That way you can keep the private key secret and safe (it will only be used to sign the token) and you can use the public key to verify that the signature is correct.

使用 RSA256 即私人/公共密钥对(不需要“秘密”)。这样您就可以保持私钥的秘密和安全(它只会用于对令牌进行签名),并且您可以使用公钥来验证签名是否正确。

You can give the public key to anyone or any service that needs to verify that the token's signature is correct.

您可以将公钥提供给需要验证令牌签名是否正确的任何人或任何服务。

回答by ruakh

  1. Does this Secrethas to be unique?
  1. Secret必须是独一无二的吗?

It should be unique to your application — it needs to be a secret, after all — but it won't be unique for each token. Rather, you should have a relatively small number of secret keys at any given time (e.g., usually having just one key, but having brief periods where you have two keys as you rotate from one to the next).

它对于您的应用程序应该是唯一的——毕竟它需要是一个秘密——但它不会对每个令牌都是唯一的。相反,您应该在任何给定时间拥有相对较少数量的密钥(例如,通常只有一个密钥,但在您从一个轮换到下一个时有两个密钥的短暂时期)。

  1. Shall I use the hashed version of user's password for secret?
  1. 我应该使用用户密码的散列版本作为秘密吗?

No, for two reasons:

不,有两个原因:

  1. Suppose that your user has a relatively insecure password, like GoPackers123. Using the password in your secret then means that someone can easily test a given potential password to see if it results in the right signature; and, more to the point, they can easily test huge numbers of potential passwords to see if any of them gives the right signature. This is an offline attack, so you would never even know it happened.
  2. This would require you to distribute all of your users' password hashes to every system that needs to hold the secret. If you have more than a trivial number of users, this can become a pretty serious burden on your secret-distribution mechanism.
  1. 假设您的用户有一个相对不安全的密码,例如GoPackers123. 在你的秘密中使用密码意味着有人可以轻松地测试给定的潜在密码,看看它是否会产生正确的签名;更重要的是,他们可以轻松测试大量潜在密码,看看其中是否有任何一个提供了正确的签名。这是一次离线攻击,因此您甚至永远不会知道它发生了。
  2. 这将要求您将所有用户的密码散列分发到需要保密的每个系统。如果您的用户数量很少,这可能会成为您的秘密分发机制的一个相当严重的负担。

回答by cassiomolin

JWT and the java-jwtlibrary support both symmetricand asymmetricalgorithms for the signature:

JWT 和java-jwt库支持对称非对称签名算法:

  • If you go for symmetric algorithmssuch as HS256, you will have only a single key to be used to sign and verify the signature.

  • If you consider asymmetric algorithmssuch as RS256, you will have a private and a public key. Keep the private key safe on the server and use it to sign the token. Use the public key to verify the signature (it also can be shared with whoever needs to verify the signature).

  • 如果您使用HS256 等对称算法,您将只有一个密钥可用于签名和验证签名。

  • 如果您考虑RS256 等非对称算法,您将拥有一个私钥和一个公钥。将私钥安全地保存在服务器上并使用它来签署令牌。使用公钥来验证签名(也可以与需要验证签名的人共享)。

Never evershare the key used to sign the token!

永远不要共享用于签署令牌的密钥!

And nothing stops you from having a set of different keys for signing your tokens. In this situation, the kidheader parameter can be used to indicate which key was used to sign the token. This claim is supposed to carry a key identifier and not the key itself.

没有什么能阻止您拥有一组不同的密钥来签署您的令牌。在这种情况下,kidheader 参数可用于指示使用哪个密钥对令牌进行签名。这个声明应该携带一个密钥标识符而不是密钥本身。

Refer to this answerfor more details on the kidclaim.

有关索赔的更多详细信息,请参阅此答案kid