关于 JWT 网上有很多介绍,这里就不多做介绍了,简而言之 JWT 就是一个身份证,证明你是你。
结构和实现
e2FsZyI6ICJIUzI1NiIsInR5cCI6ICJKV1QifQ.
eyJzdWIiOiAidXNlciB0b2tlbiIsICJpc3MiOiAiIiwgImF1ZCI6ICIxMTExIiwgInV1aWQiOi
AiMTExMSIsICJpYXQiOiAxNTg4Njc3NTA1Mjc3LCAiZXhwIjogMTU4ODY3NzUwNjI3N30.
zZrdD_mVLIEHtUubrd25SvGiFd-nD2sutam7Apzq0ZA
以上就是一个简单的 JWT。
很容易就可以看出来,JWT 由三个部分组成,这三个部分由「 . 」分隔开。
- 第一个部分:第一个部分是 JWT 的 head(头部),包含加密方式和类型(类型始终为 JWT)。头是一个 JSON,就像下面列举的这样。然后对这个 JSON 字符串进行 Base64 编码就得到了咱们的头部,当然由于咱们可能要在网页中使用它,所以咱们不能单纯地使用 Base64 而是要使用 Base64 的变种 Base64URL。(由于加密方式是写在 head 中的,而它又基本上是明文,这就导致了一个问题,在下文会讲到)
{ "alg": "HS256", "typ": "JWT" }
- 第二个部分:第二个部分是 JWT 的payload(载荷)也就承载你的数据的地方,它也是一个 JSON,就像下面列举的这样,不必理解咱写了什么内容,咱们只需要知道把这个 JSON 字符串做和头部一样的操作就可以得到 JWT 的 payload 了。至于细节部分网上有很多教程。(同理 payload 也基本上是明文,所以不能存放任何敏感信息)
{ "sub": "user token", "iss": server, "aud": u_username, "uuid": u_uuid, "iat": u_time, "exp": u_time + exp * 1000 }
- 第三个部分:第三个部分是 JWT 的灵魂所在,他是 JWT 的 sig(签名),说是签名,咱更愿意称它为检验信息,它可以保证 JWT 的内容不被修改。sig 的生成很简单咱这里只列举 HS256 的实现,也就是 HMACSHA256,第一步,把咱们的 head 和 payload 用「 . 」连接起来然后使用 SHA256 算法对其摘要,然后用 HMAC 算法对其加密,最后用 Base64URL 对其编码,就得到了咱们的 sig,当然你也可以用其他的算法进行摘要和加密。(注:key、msg 都是 bytes 类型)
msg = f'{head}.{payload}'.encode() sig = base64.b64encode(hmac.new(key, msg, digestmod=sha256).digest())
关于隐患
- JWT 不会对信息做任何加密,所有信息都是可以轻松查看的。
- 如果你的项目中使用了非对称加密,那么 JWT 的头很有可能成为重大的漏洞,攻击者可能会在头中声明加密方式是 HS256,但你使用的是 RS256,你的程序会尝试使用你的 RSA 公钥去解密签名,而公钥是大家都知道的,由此攻击者就可以自己签发 JWT,以任何身份登录。
咱能想到的只有这些了,大家可以在评论区补充