最近我开始使用基于JWT的身份验证.在用户登录之后,生成用户令牌,其看起来像"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ".
它由三个部分组成,每个部分用点(.)分隔.第一部分是Base64编码的标题.解码后我们会得到类似{"alg":"HS256",//使用的算法"typ":"JWT"}
第二部分是索赔和Base64编码.解码后,我们会得到类似{"sub":"1234567890","name":"John Doe","admin":true}
第三部分是签名并生成
HMACSHA256(base64UrlEncode(header)+"."+ base64UrlEncode(payload), secret base64编码 )
现在这个密钥是什么以及如何生成这个密钥?
我尝试了一些在线生成器,如" http://kjur.github.io/jsjws/tool_jwt.html ",但dint得到了很多帮助.
Lor*_*ord 88
一个 Json Web Token 由三部分组成。标头、有效载荷和签名 现在标头只是关于令牌本身的一些元数据,有效载荷是我们可以编码到令牌中的数据,任何我们真正想要的数据。所以我们想要在这里编码的数据越多,JWT 就越大。无论如何,这两部分只是将被编码但未加密的纯文本。
所以任何人都可以解码和阅读它们,我们不能在这里存储任何敏感数据。但这根本不是问题,因为在第三部分,所以在签名中,事情才真正变得有趣。签名是使用标头、有效负载和保存在服务器上的秘密创建的。
然后整个过程称为签署 Json Web Token。签名算法采用标头、有效载荷和秘密来创建唯一的签名。所以只有这些数据加上秘密才能创建这个签名,好吗?然后与标头和有效负载一起,这些签名形成 JWT,然后将其发送到客户端。

一旦服务器收到 JWT 以授予对受保护路由的访问权限,它需要对其进行验证以确定用户是否真的是他所声称的人。换句话说,它将验证是否没有人更改令牌的标头和有效载荷数据。同样,此验证步骤将检查是否没有第三方实际更改 Json Web 令牌的标头或有效负载。
那么,这种验证实际上是如何工作的呢?嗯,它实际上很简单。收到 JWT 后,验证将获取其标头和有效载荷,并与仍保存在服务器上的机密一起,基本上创建一个测试签名。
但是最初创建 JWT 时生成的原始签名仍在令牌中,对吗?这就是这个验证的关键。因为现在我们要做的就是将测试签名与原始签名进行比较。如果测试签名与原始签名相同,则说明payload和header没有被修改。

因为如果它们被修改了,那么测试签名就必须不同。因此,在没有更改数据的情况下,我们可以对用户进行身份验证。当然,如果两个签名实际上不同,那么这意味着有人篡改了数据。通常通过尝试更改有效负载。但是,操纵有效载荷的第三方当然无权访问秘密,因此他们无法签署 JWT。所以原始签名永远不会对应于被操纵的数据。因此,在这种情况下,验证将始终失败。这是使整个系统工作的关键。正是这种魔力使 JWT 如此简单,但又极其强大。
现在让我们用nodejs做一些实践:
配置文件非常适合存储 JWT SECRET 数据。使用标准 HSA 256 加密进行签名,密钥长度至少应为 32 个字符,但越长越好。
配置文件:
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
Run Code Online (Sandbox Code Playgroud)
现在使用命令安装 JWT
npm i jsonwebtoken
Run Code Online (Sandbox Code Playgroud)
用户注册后的示例向他传递 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,
},
});
});
Run Code Online (Sandbox Code Playgroud)
在我看来,不要求助于第三方来生成你的超级密钥,因为你不能再说它是秘密了。只需使用您的键盘。
Sur*_*gch 37
密钥与标头和有效载荷相结合以创建唯一的哈希。如果您拥有密钥,则只能验证此哈希。
您可以选择一个好的、长的密码。或者你可以从喜欢的网站生成它这个。
示例(但现在不要使用这个):
8Zz5tw0Ionm3XPZZfN0NOml3z9FMfmpgXwovR9fp6ryDIoGRM8EPHAB6iHsc0fb
Run Code Online (Sandbox Code Playgroud)
Han*_* Z. 29
HS256用于对JWT进行签名的算法()意味着该秘密是发送者和接收者都知道的对称密钥.它是在带外协商和分发的.因此,如果您是令牌的预期收件人,发件人应该已经为您提供了带外秘密.
如果您是发件人,则可以使用任意字节串作为秘密,可以生成或有意选择.您必须确保向带外的目标收件人提供秘密.
为了记录,JWT中的3个元素不是base64编码的,而是base64url编码的,它是base64编码的变体,可以产生URL安全值.
小智 13
要生成 64 字节的唯一密钥,请在节点中运行以下命令:
crypto.randomBytes(64).toString("hex");
Run Code Online (Sandbox Code Playgroud)
Dan*_*son 12
对于 JWT,常用的签名算法是HMAC SHA256 。对于该算法,32 个字节就足够了。
32 字节数组可以表示为 64 个字符长的十六进制字符串,因为 2 个十六进制字符等于 1 个字节。可以使用以下终端命令生成 32 个随机字节(以十六进制字符串表示):
$ openssl rand -hex 32
Run Code Online (Sandbox Code Playgroud)
它输出的示例:
4f1feeca525de4cdb064656007da3edac7895a87ff0ea865693300fb8b6e8f9c
Run Code Online (Sandbox Code Playgroud)
通过使用上面的命令,密钥将在您的计算机上本地生成。使用网站生成密码可能很危险,因此最好在本地进行。
根据您使用的语言,后续步骤可能会有所不同。但在 C# 中,您可以使用以下函数将十六进制字符串转换为字节数组:
4f1feeca525de4cdb064656007da3edac7895a87ff0ea865693300fb8b6e8f9c
Run Code Online (Sandbox Code Playgroud)
在 C# 中,可以通过以下方式生成 JWT 令牌:
public static byte[] FromHexStringToByteArray(string hexString)
{
var byteArray = new byte[hexString.Length / 2];
for (var i = 0; i < hexString.Length; i += 2)
{
byteArray[i / 2] = Convert.ToByte(hexString.Substring(i, 2), 16);
}
return byteArray;
}
Run Code Online (Sandbox Code Playgroud)
在上面的示例中,密钥采用十六进制字符串的形式,并转换为字节数组。SigningCredentials接下来,使用设置为 HMAC SHA256 的密钥和算法创建 的实例。随后,将使用凭据创建令牌。
你可以编写自己的发电机.密钥本质上是一个字节数组.确保转换为字节数组的字符串是base64编码的.在Java中你可以做这样的事情.
String key = "random_secret_key";
String base64Key = DatatypeConverter.printBase64Binary(key.getBytes());
byte[] secretBytes = DatatypeConverter.parseBase64Binary(base64Key);
Run Code Online (Sandbox Code Playgroud)
小智 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
秘钥的作用是什么,你可能已经知道了。它基本上是 HMAC SH256(安全哈希)。Secret 是一个对称的密钥。
使用相同的密钥,您可以生成、重新验证、编辑等。
为了更安全,您可以使用私钥、公钥(非对称方式)。私钥用于创建令牌,公钥用于在客户端级别进行验证。
来到密钥什么给你你可以给任何东西,“sudsif”,“sdfn2173”,任何长度
您可以使用在线生成器,或手动编写
我更喜欢使用 openssl
C:\Users\xyz\Desktop>openssl rand -base64 12
65JymYzDDqqLW8Eg
Run Code Online (Sandbox Code Playgroud)
生成,然后用 base 64 编码
C:\Users\xyz\Desktop>openssl rand -out openssl-secret.txt -hex 20
Run Code Online (Sandbox Code Playgroud)
生成的值保存在名为“openssl-secret.txt”的文件中
生成并存储到文件中。
一件事是生成 12 个字符,仅生成 12 个字符,但由于它是 base 64 编码的,因此它将是 (4/3*n) 上限值。
我推荐阅读这篇文章
| 归档时间: |
|
| 查看次数: |
38225 次 |
| 最近记录: |