由三部分组成的 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,
},
});
});
输出:
在我看来,不要求助于第三方来生成你的超级密钥,因为你不能再说它是秘密了。只需使用您的键盘即可。