Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准。该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。也就是说JWT是Token的一种表述性声明规范。
JWT(Json Web Token)
- 官网地址:https://jwt.io/
- jwt github:https://github.com/jwtk/jjwt
JWT生成编码后的样子
- 结构类似 xxx.yyy.zzz
1 | eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhZG1pbiIsImF1ZCI6IuWkqeihjOWBpeeuoeeQhueUqOaItyIsImF1ZGllbmNlIjoid2ViIiwibmJmIjoxNTA3Njg0OTQyLCJpc3MiOiJ3d3cuMW9uZS5jbiIsImV4cCI6MTUwNzY4Njc0MiwiaWF0IjoxNTA3Njg0OTQyLCJqdGkiOjEwMDB9.GGF0kFbxNk2ezzuXEJVBZyyL4e4BYMdpse73cSDrUut7cbVyYuLG1CNr8RI7eI3VHz9sdCB14Kesi8rP-v3VJA |
- base64解析之后
1 | { |
JWT的构成
- 第一部分我们称它为头部(header),第二部分我们称其为载荷(body),第三部分是签证(signature)。
header
- jwt的头部承载两部分信息:
- 声明类型,这里是jwt
- 声明加密的算法 通常直接使用 HMAC HS512
- 完整的头部就像下面这样的JSON:
1 | { |
- 然后将头部进行base64加密(该加密是可以对称解密的),构成了第一部分.
1 | eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9 |
body
载荷就是存放有效信息的地方。这个名字像是特指飞机上承载的货品,这些有效信息包含三个部分
标准中注册的声明
- 公共的声明
- 私有的声明
- 标准中注册的声明 (建议但不强制使用) :
iss: jwt签发者
sub: jwt所面向的用户
aud: 接收jwt的一方
exp: jwt的过期时间,这个过期时间必须要大于签发时间
nbf: 定义在什么时间之前,该jwt都是不可用的.
iat: jwt的签发时间
jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
eyJzdWIiOiJhZG1pbiIsImF1ZCI6IuWkqeihjOWBpeeuoeeQhueUqOaItyIsImF1ZGllbmNlIjoid2ViIiwibmJmIjoxNTA3Njg0OTQyLCJpc3MiOiJ3d3cuMW9uZS5jbiIsImV4cCI6MTUwNzY4Njc0MiwiaWF0IjoxNTA3Njg0OTQyLCJqdGkiOjEwMDB9
1
2
3
4
5
6
7
8
9
10
11
12
```json
"body":{
"sub":"admin",
"aud":"xx用户",
"audience":"web",
"nbf":1507684942,
"iss":"www.xxx.cn",
"exp":1507686742,
"iat":1507684942,
"jti":1000
}
signature
- jwt的第三部分是一个签证信息,这个签证信息由三部分组成:
- header (base64后的)
- body(base64后的)
- secret
- 这个部分需要base64加密后的header和base64加密后的body使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第三部分。
1 | GGF0kFbxNk2ezzuXEJVBZyyL4e4BYMdpse73cSDrUut7cbVyYuLG1CNr8RI7eI3VHz9sdCB14Kesi8rP-v3VJA |
- 密钥secret是保存在服务端的,服务端会根据这个密钥进行生成token和验证,所以需要保护好。
JWT注意事项
- body不要存放敏感信息,因为该部分用base64编码,在客户端是可解的;
- 服务端保护好secret私钥,一旦客户端得带私匙就可以自己签发 JWT 了;
jwt扩展
- 因为token是保留到客户端,所以服务端secret保护变得额外重要,建议将配置信息中secret加密后使用。不建议全局使用同一secret加密。
- REST风格推荐使用json传输数据,所以可以采用signature进行数据加密后提交。signature每次刷新都会更新所以安全级别将提高很多。