JWT(JSON Web Token) 原理介绍

自从 RESTful 架构兴起后,越来越多的人提倡使用 JWT 来取代传统 Session 的场景,究竟什么是 JWT 呢,来了解下吧~

JWT 介绍

  1. JWT 是 JSON Web Token 的缩写,是一种开放标准(RFC 7519),即基于 JSON 对象的编码,并通过这个编码传递信息。
  2. JWT 会通过 HMAC、RSA、ECDSA 等算法进行加密。
  3. 通常利用 JWT 来对用户进行验证,也就是说用户会先请求身份凭证服务器拿到该JWT,然后,只要用户携带这个 JWT 向业务服务器请求资源,如果这个 JWT 是有效的,那么就能获取资源。

JWT 的组成

JWT 的结构可以看作是三个 JSON 对象,并且用点(.)来分隔,这三个部分会各自进行编码,组成一个 JWT 字符串。也就是变成:xxxxx.yyyyy.zzzzz

Header(头部)

由两部分组成:

  1. alg(算法) 也就是 token 被加密的算法,如 HMAC、SHA256、RSA。
  2. typ(类型) 也就是 token 的类型,基本上就是 JWT。

示例:

{
    "alg""HS256",
    "typ""JWT"
}

然后进行 Base64 进行编码。Base64 是通过 64 个字符来表示二进制数据的一种方法,编码的方式是固定的而且可以逆向解码的,并不是那种安全的加密算法。

Payload(负载)

这里放的是声明(Claim)内容,也就是用来传递消息的地方,在定义上有三种声明:

1. Registered claims

可以看作是标准公认的一些消息,建议放,但并不强迫,例如:

  • iss(Issuer):JWT 签发者
  • exp(Expiration Time):JWT 的过期时间,过期时间必须大于签发 JWT 时间
  • sub(Subject):JWT 所面向的用户
  • aud(Audience):接收 JWT 的一方
  • nbf(Not Before):也就是定义拟发放 JWT 之后,的某段时间点前该 JWT 仍旧是不可用的
  • iat(Issued At):JWT 签发时间
  • jti(JWT Id):JWT 的身份标识,每个 JWT 的 Id 都应该是不重复的,避免重复发放

2. Public claims

这个,可以看作是传递的字段必须与上面的 Registered claims 字段不能冲突,然后可以向官方申请定义公开声明,会进行审核等步骤,实际上在开发上是不太会用这部分的。

3. Private claims

这是发放 JWT 服务器可以自定义的部分,例如实际上会放 User Account、User Name、User Role 等不敏感的数据。

所谓不敏感的数据就是不会放用户的密码等敏感数据,因为该 Payload 传递的消息最后也是通过 Base64 进行编码,所以是可以被破解的,因此放用户密码会有安全性的问题。

示例:

{
  "sub""1234567890",
  "account""kenny@example.com",
  "role""admin"
}

个人感觉通常都会放 iat、exp 等标准字段,因为通常需要检查 JWT 发送时间及是否过期,以及还有用户账号,为了方便查询用户的一些数据,通常以前的做法是 Session 里面存放用户账号,现在改用 JWT 的 payload 上存放,以及角色身份的定义,可以用来看该用户是否有权限获取后端 API 的数据。

Signature(签名)

由三大部分組成:

  • base64UrlEncode(header)
  • base64UrlEncode(payload)
  • secret

也就是:

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

header 和 payload 中间用点(.)来连接,secret 是存放在服务器端的加密字符串,最后将这三个部分串接再一起的字符串进行加密算法进行加密。

secret 是要保存在服务器端的,这个 secret 一旦泄露给客户端,客户端就可以自己生成 JWT,并通过该 JWT 访问资源,因此 secret 是永远不该泄露的。

最后将 Header、Payload、Signature 三者用点(.)拼接在一起,就是一个合法签发的 JWT 字符串。在 JWT 官网:https://jwt.io/ 有提供现成的 JWT 签发工具,可以使用该工具来看产生的 JWT 字符串长什么样:

JWT(JSON Web Token)  原理介绍

我使用上面我写的三个部分的内容各自填上去,左边就会出现正确的 JWT 字符串出来。红色部分就是编码后的 Header、紫色部分就是编码后的 Payload,蓝色部分就是将 Header、Payload、Secret 合在一起并进行加密算法加密后的编码。最后就是用点(.)将三个部分串联在一起。

客户端如何用 JWT 来访问资源?

  1. 前端会先通过访问后端的登录 API,后端验证用户账号密码成功后,就会发放合法 JWT 字符串。
  2. 前端拿到 JWT 字符串就会将 JWT 存放在 Local Storage 里面。
  3. 而后当前端要访问受保护的资源 API 时,只要在 Header 的填写以下内容:
Authorization: Bearer <JWT token>
  1. 后端收到后,会去检查 Authorization 的 JWT token 是否有效,如果有效,则允许前端访问受保护的资源。在以前的 Session 的设计上,Session 会存放在 Redis 等这种缓存数据库,每当用户访问受保护的资源时,会先去存储数据库的 Session 进行比对,有效则让用户访问,以 JWT 的方式可以降低查询数据库的需求。

JWT 的优缺点

优点:

  • 采用 JSON 对象的形式,大部分的编程语言都支持
  • 可以存放一些用户信息,但并非是敏感的信息
  • 整个 JWT,只要 Payload 不要放过多的信息,其实 Size 是相当小的
  • 不用在 Server 的数据库存放 Session,特别适合多台 Server 的场景下,使得扩展性容易,因为多台 Server 要使用 Session 的话,会有共享 Session 的问题发生
  • 对于现在手机上的 APP 的应用特别好,用户不用每次打开 APP 都要重新输入账号与密码
  • 支持跨域请求,不会有传统用 Cookie 进行跨域请求等的问题

缺点:

  • JWT 没办法主动失效,也就是说不能像 Session 一样被强制无效,但是个人觉得这有很多方式可以避免
  • JWT 一旦泄露会有很严重的安全性问题,但是泄露通常可以通过两种方式:
    1. 黑客使用你的电脑,并得知 JWT 这…你电脑都被攻陷了…那就不好说了
    2. 使用中间人攻击的方式,截取客户端传服务器端的数据包,并获取 JWT,但使用 HTTPS 传输可以大幅度降低该攻击,只要定期更换 SSL 证书就可以了

总结

JWT 之所以会兴起,除了因为 RESTful 架构出现,加上现在微服务的架构的关系,一般来说上线的系统,不太可能用单台服务器来处理一切,多台服务器处理 Session 会有其局限性,虽然可以用统一的数据库进行存放 Session 来控制,但是会有性能的问题。

不过其实这还有很多探讨的空间,在这篇文章没有去说,Session/Cookie 的架构其实也是可以跟 JWT 并行。但就我两者都使用过的经验来看,我觉得 JWT 的方式的确很简洁易懂,Session 的机制有时候的确很繁琐。


原文始发于微信公众号(程序猿技术充电站):JWT(JSON Web Token) 原理介绍

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/285219.html

(0)
葫芦侠五楼的头像葫芦侠五楼

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!