1. 为什么要用 JWT ?
认证
在谈起 JWT 之前,我们先了解一下什么是认证。
在登录淘宝、微博等软件或者网站之前,我们需要通过填写账号和密码来校验身份。认证是用来验证用户身份合法性的一种方式。
那我们登录成功之后,网站如何记录我们的身份信息呢?
前面我们在学习 servlet 的时候,知道了传统的系统主要是通过 session 来存储用户的信息。session 将用户的信息存储在服务端。
但是随着用户数量的增多,服务端就需要存一堆用户的认证信息,这种方式会不断增加服务端的压力。
如果是分布式系统,用 session 存储用户信息就太拘束了。因为分布式系统一般都会做负载均衡,如果这次认证成功了,那么意味着下次请求必须仍要访问这台服务器才能认证成功。
如果是前后端分离的系统就更难受了,因为前端代码和后端代码放在不同的服务器上,除了会增加服务器的压力,还会产生跨域等一系列问题,有点得不偿失。
那有没有一种工具能帮我们解决这些认证问题?
- 服务端不需要存储用户的认证信息
- 避免跨域
- 保证数据的安全性
JWT闪亮登场。
2.什么是 JWT
JWT 简称: JSON Web Token,又叫做 web 应用中的令牌。它可以帮助我们完成用户的认证、存储信息、加密数据等功能。
那什么是令牌呢?令牌就相当于古代的虎符。
古代将军要想调兵遣将,必须手持虎符。
而用户要想访问系统中的某些页面,在发起的请求中必须携带使用 JWT 生成的令牌。令牌校验通过了,方可访问系统。这里的令牌简称为 token。
3. JWT 的结构
注:这里所说的 JWT 的结构,指的是用 JWT 生成令牌的结构,也就是 token 的结构。
令牌的结构组成:
- 标头(Header)
- 载荷(Payload)
- 签名(Signature)
令牌最终的样子是由这三部分组成的字符串:
Header.Payload.Signature
复制代码
例如:
hjYGH1dajUU.dajhjksfiu2h27jjghg2.kjbhjkf982bhh2lk2
复制代码
3.1 标头
标头是使用 Base64 编码将令牌类型和签名算法经过加工后生成的一段字符串。
标头包含两部分:
- 令牌的类型:JWT(一般是默认的)
- 签名算法:例如 SHA256、HMAC等
{
"alg": "HS256",
"typ": "JWT"
}
复制代码
3.2 载荷
载荷主要存储一些自定义信息。它也是使用 Base64 编码加工后生成的一段字符串。
3.3 签名
签名是通过一个秘钥和标头中提供的算法再将标头和载荷进行加工后生成的一段字符串。例如:
4. JWT 的认证流程
- 用户点击登录,后台接收用户请求并根据账号和密码从数据库查询用户信息。用户若存在,则使用 JWT 生成 token 并返回给前台。用户若不存在,则返回错误信息。
- 前端在请求其他资源时将 token 放到请求头中。
- 后台从请求头中获取 token 信息,如果 token 校验失败,则返回错误信