JWT 英文名是 Json Web Token ,是一种用于通信双方之间传递安全信息的简洁的、URL安全的表述性声明规范,经常用在跨域身份验证。
JWT 以 JSON 对象的形式安全传递信息。因为存在数字签名,因此所传递的信息是安全的。
在讲解 JWT 之前我们先来看一个问题。我们都知道 Internet 服务的身份验正过程是这样的,客户端向服务器发送登录名和登录密码,服务器验证后将对应的相关信息保存到当前会话中,这些信息包括权限、角色等数据。
服务器向客户端返回 Session ,Session 信息都会写入到客户端的 Cookie 中,后面的请求都会从 Cookie 中读取 Session 发送给服务器,服务器在收到 Session 后会对比保存的数据来确认客户端身份。
但是上述模式存在一个问题,无法横向扩展。在服务器集群或者面向服务且跨域的结构中,需要数据库来保存 Session 会话,实现服务器之间的会话数据共享。
在单点登录中我们会遇到上述问题,当有多个网站提供同一拨服务,那么我们该怎么实现在甲网站登陆后其他网站也同时登录呢?
其中一种方法是持久化 Session 数据,也就是上面所说的将 Session 会话存到数据库中。这个方法的优点是架构清晰明了。
但是缺点也非常明显,就是架构修改很困难,验证逻辑需要重写,并且整体依赖于数据库,如果存储 Session 会话的数据库挂掉那么整个身份认证就无法使用,进而导致系统无法登录。要解决这个问题我们就用到了 JWT 。
JWT 简述
客户端身份经过服务器验证通过后,会生成带有签名的 JSON 对象并将它返回给客户端。客户端在收到这个 JSON 对象后存储起来。
在以后的请求中客户端将 JSON 对象连同请求内容一起发送给服务器,服务器收到请求后通过 JSON 对象标识用户,如果验证不通过则不返回请求的数据。
验证不通过的情况有很多,比如签名不正确、无权限等。在 JWT 中服务器不保存任何会话数据,使得服务器更加容易扩展。
Base64URL 算法
在讲解 JWT 的组成结构前我们先来讲解一下 Base64URL 算法。这个算法和 Base64 算法类似,但是有一点区别。
我们通过名字可以得知这个算法使用于 URL 的,因此它将 Base64 中的 + 、 / 、 = 三个字符替换成了 - 、 _ ,删除掉了 = 。因为这个三个字符在 URL 中有特殊含义。
JWT 组成结构
JWT 是由三段字符串和两个 . 组成,每个字符串和字符串之间没有换行(类似于这样:xxxxxx.yyyyyy.zzzzzz),每个字符串代表了不同的功能,我们将这三个字符串的功能按顺序列出来并讲解:
1. JWT 头
JWT 头描述了 JWT 元数据,是一个 JSON 对象,它的格式如下:
json{"alg":"HS256","typ":"JWT"}
这里的 alg 属性表示签名所使用的算法,JWT 签名默认的算法为 HMAC SHA256 , alg 属性值 HS256 就是 HMAC SHA256 算法。typ 属性表示令牌类型,这里就是 JWT。
2. 有效载荷
有效载荷是 JWT 的主体,同样也是个 JSON 对象。有效载荷包含三个部分:
标准注册声明标准注册声明不是强制使用是的,但是我建议使用。它一般包括以下内容:
iss:jwt的签发者/发行人;
sub:主题;
aud:接收方;
exp:jwt过期时间;
nbf:jwt生效时间;
iat:签发时间
jti:jwt唯一身份标识,可以避免重放攻击
公共声明:可以在公共声明添加任何信息,我们一般会在里面添加用户信息和业务信息,但是不建议添加敏感信息,因为公共声明部分可以在客户端解密。
私有声明:私有声明是服务器和客户端共同定义的声明,同样这里不建议添加敏感信息。
下面这个代码段就是定义了一个有效载荷:
json{"exp":"201909181230","role":"admin","isShow":false}