一、JsonWebToken
(一)JsonWebToken是什么?
JSON Web Token 是一个开放标准协议,它定义了一种“紧凑”和“自包含”的方式,它用于各方之间作为JSON对象安全地传输信息。
紧凑:数据量较少,并且能通过url参数,http请求提交的数据以及http header的方式来传递。
自包含:这个串可以包含很多信息,比如用户ID,订单号ID等,如果被其他人拿到该信息,也就可以拿到关键业务信息。
(二)优点:
1. 可以适用于分布式的单点登录场景。
2. 可以使用跨域认证解决方案。
3. jwt实现自动刷新token的方案。
(三)基本原理
1. 客户端使用账号和密码请求登录接口。
2. 登录成功后服务器使用签名密钥生成JWT,并返回JWT给客户端。
3. 客户端再次向服务端请求其他接口时,请求头会带上JWT。
4. 服务器接收到JWT后验证签名的有效性,对客户端做出相应的响应。
(四)基本数据结构
1.基本的JWT的数据结构
如下:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoia29uZ3poaSIsImlhdCI6MTU0Mzc1MzczNX0.h1XmQo017udxlFsH-8US9Lg8dJ0IDsSbRbjEN5Nq0l4
它是由三部分组成的,中间使用 . 分割成三个部分:
Header(头部),
PayLoad(负载),
Signature(签名)
例如:Header.Payload.Signature
(1)Header
Header部分是一个JSON对象,描述JWT的元数据。
{ "typ": "JWT", "alg": "HS256" }
alg属性表示签名的算法,默认是 HMAC SHA256 (缩写为:HS256);
typ属性表示这个令牌(token)的类型为JWT,最后将上面的JSON对象使用 Base64URL的算法转成字符串。
base64在线调试
http://tool.oschina.net/encrypt?type=3如下所示:
alg 部分表示默认加密的算法是 HMAC SHA256, 当然我们也可以选择下面的加密算法,加密算法有如下:
(2)Payload
Payload部分也是一个JSON对象,用来存放实际需要传递的数据,官方提供了7个字段,如下:
iss(issuer): 签发人
exp (expiration time): 过期时间
sub (subject): 主题
aud (audience): 受众
nbf (Not Before): 生效时间
iat (Issued At): 签发时间
jti (JWT ID): 编号
- iss(issuer): 签发人
- exp (expiration time): 过期时间
- sub (subject): 主题
- aud (audience): 受众
- nbf (Not Before): 生效时间
- iat (Issued At): 签发时间
- jti (JWT ID): 编号
payload中文含义是载荷,它可以理解为存放有效信息的地方。这些有效信息一般包含如下三个部分:
- 标准中注册的声明:(如上就是官方提供的7个字段)。
- 公共的声明:公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息,但是不建议添加敏感信息,因为该部分在客户单可解密。
- 私有的声明:私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,该部分信息可以理解为明文信息。
简单的 payload 如下结构:
{ "sub": '123456', "name": "liyinchi", "admin": true }
我们还是使用如上的base64编码,会编码成如下所示:
(3)Signature
Signature 是对前面两部分的签名,防止数据被篡改。
签名原理:Header和payload对应的json结构进行base64 编码之后得到的两个串用英文句点号拼接起来的,然后根据header里面的alg指定的前面算法(默认算法是 HMAC SHA256)生成出来的。
如上header部分使用的是 HS256(即HMAC和SHA256),HMAC是用于生成摘要的,SHA256是用于对摘要进行数字签名的。因此使用HMACSHA256实现signature实现的算法如下:
HMACSHA256( base64UrlEncode(header) + '.' + base64UrlEncode(payload), secret )
如上是 Signature 签名算法,最后一个 secret 是加密的密钥的含义。
因此通过如上的用法我们就可以拿到JWT了。
JWT在线调试工具:
可以快速生成一个JWT,如下HEADER和PLAYLOAD是我前面定义的部分数据