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

基于JWT的身份验证的密钥是什么?如何生成?,jwt,Jwt,最近,我开始使用基于JWT的身份验证。用户登录后,将生成一个用户令牌,如下所示 "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ". 它由三个部分组成,每个部分用一个点(.)分隔。第一部分是Base64编码的报头。解码后,我们将得到类似 {

最近,我开始使用基于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*
  )  
现在这个密钥是什么,如何生成这个密钥

我尝试了一些在线生成器,如“” 但是Din没有得到太多帮助。

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

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


对于该记录,JWT中的3个元素不是base64编码的,而是base64url编码的,这是base64编码的一个变体,可产生URL安全值。

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

在Java中,您可以这样做

String key=“随机密钥”;
字符串base64Key=DatatypeConverter.printBase64Binary(key.getBytes());
byte[]secretBytes=DatatypeConverter.parseBase64Binary(base64Key);
什么是密钥 密钥与报头和有效负载组合以创建唯一的哈希。只有在拥有密钥的情况下,才能验证此哈希

如何生成密钥 您可以选择一个好的长密码。或者,您也可以从类似的网站生成它

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


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

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

然后整个过程被称为对Json Web令牌进行签名。签名算法使用报头、有效负载和机密创建唯一签名。所以只有这些数据加上秘密才能创建这个签名,好吗? 然后,这些签名与报头和有效载荷一起构成JWT, 然后发送到客户端。

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

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

但是JWT第一次创建时生成的原始签名仍然在令牌中,对吗?这是验证的关键。因为现在我们要做的就是比较测试签名和原始签名。 如果测试签名与原始签名相同,则表示有效负载和报头未被修改。

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

现在,让我们对nodejs进行一些实践:

配置文件非常适合存储JWT机密数据。使用标准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,
    },
  });
});
输出:


在我看来,不要从第三方获得帮助来生成您的超级密钥,因为您不能再说它是机密了。只需使用键盘。

秘钥的作用是什么,你可能到现在为止已经知道了。 它基本上是HMAC SH256(安全哈希)。 秘密是一把对称的钥匙

使用相同的密钥,您可以生成、重新制作、编辑等

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

来看看秘钥要送什么 你可以给任何东西,“泡沫”,“sdfn2173”
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,
    },
  });
});
C:\Users\xyz\Desktop>openssl rand -base64 12
65JymYzDDqqLW8Eg
C:\Users\xyz\Desktop>openssl rand -out openssl-secret.txt -hex 20