【问题标题】:What is secret key for JWT based authentication and how to generate it?基于 JWT 的身份验证的密钥是什么以及如何生成它?
【发布时间】:2015-09-27 08:56:19
【问题描述】:

最近我开始使用基于 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” 但也能得到很多帮助。

【问题讨论】:

    标签: jwt


    【解决方案1】:

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

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

    然后将整个过程称为签署 Json Web 令牌。签名算法采用标头、有效负载和秘密来创建唯一签名。所以只有这个数据加上秘密才能创建这个签名,好吗? 然后与标头和有效负载一起,这些签名形成 JWT, 然后将其发送给客户端。

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

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

    但是当初创建 JWT 时生成的原始签名还在令牌中,对吧?这就是验证的关键。因为现在我们要做的就是将测试签名与原始签名进行比较。 而如果测试签名与原始签名相同,则说明payload和header没有被修改。

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

    现在让我们用 nodejs 做一些实践:

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

    config.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,
        },
      });
    });
    

    输出:

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

    【讨论】:

    • 这应该是公认的答案,因为它包含更详细的信息
    • 如果加上签名验证码块就更酷了。
    【解决方案2】:

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

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

    郑重声明,JWT 中的 3 个元素不是 base64 编码的,而是 base64url 编码的,这是 base64 编码的一种变体,可生成 URL 安全值。

    【讨论】:

    • 有没有办法通过一个工作示例来查看这一点?另外,在 javascript 中已经考虑了答案,这是一个很好的观点,因为问题是在询问 jwt。
    • 请注意,如果您正在使用 JWT,则不应与任何人共享您的密钥,即使是接收者(通常是您的应用程序的用户)也不应共享
    【解决方案3】:

    什么是秘钥

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

    如何生成密钥

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

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

    8Zz5tw0Ionm3XPZZfN0NOml3z9FMfmpgXwovR9fp6ryDIoGRM8EPHAB6iHsc0fb
    

    【讨论】:

    【解决方案4】:

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

    在 Java 中,你可以这样做。

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

    【讨论】:

      【解决方案5】:

      秘钥是做什么的,你现在可能已经知道了。 它基本上是 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 将其复制到剪贴板而不是将其写入文件
      【解决方案6】:

      如果您正在寻找 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

      【讨论】:

        【解决方案7】:

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

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

        【讨论】:

          猜你喜欢
          • 2013-02-15
          • 1970-01-01
          • 2018-04-05
          • 2016-04-03
          • 2017-09-24
          • 2016-07-29
          • 2012-12-12
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多