ChatGPT解决这个技术问题 Extra ChatGPT

基于 JWT 的身份验证的密钥是什么以及如何生成它?

jwt

最近我开始使用基于 JWT 的身份验证。用户登录后,会生成一个用户令牌,如下所示

"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ".

它由三个部分组成,每个部分用一个点(。)分隔。第一部分是 Base64 编码的标头。解码后我们会得到类似的东西

{
  "alg": "HS256", //Algorithm used
  "typ": "JWT"
}

第二部分是声明和 Base64 编码。解码后我们会得到类似的东西

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

第三部分是签名,由

HMACSHA256(
    base64UrlEncode(header) + "." +
    base64UrlEncode(payload),
    *secret base64 encoded*
  )  

现在这个密钥是什么以及如何生成这个密钥?

我尝试了一些在线生成器,例如“http://kjur.github.io/jsjws/tool_jwt.html”,但得到了很多帮助。


R
Rafiq

由三部分组成的 Json Web Token。标头、有效负载和签名 现在,标头只是关于令牌本身的一些元数据,有效负载是我们可以编码到令牌中的数据,是我们真正想要的任何数据。所以我们想要在这里编码的数据越多,JWT 就越大。无论如何,这两个部分只是将被编码但未加密的纯文本。

所以任何人都可以解码并阅读它们,我们不能在这里存储任何敏感数据。但这根本不是问题,因为在第三部分,所以在签名中,才是真正有趣的地方。签名是使用标头、有效负载和保存在服务器上的秘密创建的。

https://i.stack.imgur.com/bOHqZ.png

一旦服务器接收到 JWT 以授予对受保护路由的访问权限,它需要对其进行验证以确定用户是否真的是他声称的那个人。换句话说,它将验证是否没有人更改令牌的标头和有效负载数据。同样,此验证步骤将检查是否没有第三方实际更改 Json Web 令牌的标头或有效负载。

那么,这种验证实际上是如何工作的呢?嗯,它实际上很简单。收到 JWT 后,验证将获取其标头和有效负载,并与仍保存在服务器上的秘密一起,基本上创建一个测试签名。

https://i.stack.imgur.com/b2dzI.png

因为如果它们已被修改,那么测试签名将必须不同。因此,在这种数据没有更改的情况下,我们可以对用户进行身份验证。当然,如果这两个签名实际上不同,那么这意味着有人篡改了数据。通常通过尝试更改有效负载。但是操纵有效载荷的第三方当然无法访问机密,因此他们无法签署 JWT。所以原始签名永远不会对应于被操纵的数据。因此,在这种情况下,验证总是会失败。这是使整个系统正常工作的关键。正是这种魔力让 JWT 变得如此简单,但也非常强大。

现在让我们用nodejs做一些练习:

配置文件非常适合存储 JWT SECRET 数据。对签名使用标准 HSA 256 加密,密钥长度至少应为 32 个字符,但越长越好。

配置.env:

JWT_SECRET = my-32-character-ultra-secure-and-ultra-long-secret
//after 90days JWT will no longer be valid, even the signuter is correct and everything is matched.
JWT_EXPIRES_IN=90

现在使用命令安装 JWT

npm i jsonwebtoken

用户注册后的示例,将 JWT 令牌传递给他,这样他就可以保持登录状态并访问资源。

exports.signup = catchAsync(async (req, res, next) => {
  const newUser = await User.create({
    name: req.body.name,
    email: req.body.email,
    password: req.body.password,
    passwordConfirm: req.body.passwordConfirm,
  });
  const token = jwt.sign({ id: newUser._id }, process.env.JWT_SECRET, {
    expiresIn: process.env.JWT_EXPIRES_IN,
  });

  res.status(201).json({
    status: 'success',
    token,
    data: {
      newUser,
    },
  });
});

https://i.stack.imgur.com/yC6hV.png

在我看来,不要求助于第三方来生成你的超级密钥,因为你不能再说它是秘密的了。只需使用您的键盘。


这应该是公认的答案,因为它包含更详细的信息
如果你也添加签名验证码块,那就更酷了。
H
Hans Z.

用于签署 JWT 的算法 (HS256) 意味着密钥是发送方和接收方都知道的对称密钥。它是在带外协商和分发的。因此,如果您是令牌的预期接收者,则发送者应该已经向您提供了带外秘密。

如果您是发送者,您可以使用任意字节字符串作为秘密,它可以生成或有意选择。您必须确保将秘密提供给带外的预期接收者。

作为记录,JWT 中的 3 个元素不是 base64 编码的,而是 base64url 编码的,它是 base64 编码的一种变体,可生成 URL 安全值。


有没有办法通过一个工作示例来看待这一点?同样,在 javascript 中已经考虑了答案,这是一个很好的观点,因为问题是关于 jwt。
请注意,如果您正在使用 JWT,则不应与任何人共享您的密钥,即使是接收者(通常是您的应用程序的用户)也不应
在任何情况下,我都不会向收件人发送密钥的副本。然后通过这种估计,他们可以生成自己的有效密钥哈希并自己伪造令牌。密钥应该是安全的并且只有发送者知道,以便在返回时验证令牌的内容是有效的。密钥到期和轮换也是一种很好的做法。
对称意味着更具体地说,相同的密钥用于生成和验证签名。对于 Web 应用程序,Web 服务器既是生成器又是验证器。客户端只是存储令牌。在任何情况下,您都不应与任何人共享密钥,尤其是您的网络应用程序的用户。
C
Community

什么是秘钥

密钥与标头和有效负载相结合以创建唯一的散列。如果您拥有密钥,您只能验证此哈希。

如何生成密钥

您可以选择一个好的长密码。或者,您可以从像 this 这样的网站生成它。

示例(但现在不要使用这个):

8Zz5tw0Ionm3XPZZfN0NOml3z9FMfmpgXwovR9fp6ryDIoGRM8EPHAB6iHsc0fb

在不知道密钥的情况下,您如何利用 JWT 中的自愿性? (此处用于教育目的的示例:web.cryptohack.org/no-way-jose
在线生成密码是一个非常非常糟糕的主意 :-) 只需使用 /dev/urandom 在本地进行:unix.stackexchange.com/questions/230673/…
P
Pang

您可以编写自己的生成器。密钥本质上是一个字节数组。确保您转换为字节数组的字符串是 base64 编码的。

在 Java 中,你可以做这样的事情。

String key = "random_secret_key";
String base64Key = DatatypeConverter.printBase64Binary(key.getBytes());
byte[] secretBytes = DatatypeConverter.parseBase64Binary(base64Key);

S
Satish Patro

密钥是做什么的,你可能已经知道了。它基本上是 HMAC SH256(安全哈希)。 Secret 是对称密钥。

使用相同的密钥,您可以生成、重新验证、编辑等。

为了更安全,您可以使用私钥、公钥(非对称方式)。用于创建令牌的私钥,用于在客户端级别验证的公钥。

来到秘密密钥给什么你可以给任何东西,“sudsif”,“sdfn2173”,任何长度

您可以使用在线生成器,或手动编写

我更喜欢使用 openssl

C:\Users\xyz\Desktop>openssl rand -base64 12
65JymYzDDqqLW8Eg

生成,然后使用 base 64 编码

C:\Users\xyz\Desktop>openssl rand -out openssl-secret.txt -hex 20

生成的值保存在名为“openssl-secret.txt”的文件中

生成并存储到文件中。

一件事是给 12 将生成,仅 12 个字符,但由于它是 base 64 编码,它将是 (4/3*n) 上限值。

我推荐阅读这篇文章

https://auth0.com/blog/brute-forcing-hs256-is-possible-the-importance-of-using-strong-keys-to-sign-jwts/


您可以运行 openssl rand <...args> | clip 将其复制到剪贴板而不是将其写入文件
5
5enid

如果您正在寻找 JWT_AUTH_SECRET_KEY 的密钥,那么您可以使用此处生成的任何密钥:

https://api.wordpress.org/secret-key/1.1/salt/

这通常用于“WP REST API 的 JWT 身份验证”( https://wordpress.org/plugins/jwt-authentication-for-wp-rest-api/

也许你是像我一样来这里寻找那个的人:D


P
Prateek kumar rai

要生成 64 字节的唯一密钥,请在节点中运行以下命令:

crypto.randomBytes(64).toString("hex");

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅