目录
概述
什么是JWT?
JWT全称JSON Web Token是一个开放标准。而今天要学习的是如何使用JWT来做单点登录,也就是跨域认证的实现。
认证的过程
- 首先用户向服务器发送用户名和密码。
- 然后服务器将数据保存再,session里面。
- 服务器向用户返回一个session_id,写入给用户的Cookie。
- 用户之后的每一次请求,都会将通过Cookie将session_id返回到服务器。
- 服务器收到了session_id,找到前期保存的数据,从而得到用户的身份。
优点:简单容易实现。
缺点:扩展性不好,如果是服务器集群,或者是跨域的服务导向架构,就要求session共享,每台服务器都能够读取session。
可以解决session共享不了的问题吗?
是可以的。
1. 可以使用session数据持久化,写入数据库或者别的持久层。当各种服务请求收到后,都向持久层请求数据。
优点:架构清晰,就像普通的数据保存一样。
缺点:工程量大,当持久层出现异常,就会跨域(单点)登录失败。
2. 由客户端来保存数据,每次请求都将数据发回服务器,session是没有数据的(JWT也是这样实现的)。
JWT原理
服务器认证以后,生成一个JSON对象,发送给用户端。
以后,用户端与服务端通信的时候,就都要发回这个JSON对象。服务端完全只靠这个来认定用户的身份。为了防止用户篡改数据,会加上签名。
这样服务器就不保存任何的session对象了,就解决了session数据持久化的缺点了。
JWT数据结构
JWT的样子
这就是签名之后的JWT,每一段都是很长的字符串,这些字符串用 . 隔开,实际显示当中并没有分行。
三个部分
- Header(头部)
- Payload(负载)
- Signature(签名)
实际如下:
Header.Payload.Signature
分别介绍三个部分
Header
Header部分是一个JSON对象,描述JWT的元数据。
{
"alg": "HS256",
"typ": "JWT"
}
alg表示签名的算法,默认是HMAC SHA256,typ属性表示这个令牌的类型。
最后使用Base64URL算法将JSON对象,转化为字符串。
Payload
Payload部分也是一个JSON对象,用来存放实际需要传递的数据。
- iss (issuer):签发人
- exp (expiration time):过期时间
- sub (subject):主题
- aud (audience):受众
- nbf (Not Before):生效时间
- iat (Issued At):签发时间
- jti (JWT ID):编号
当然也可以定义私有字段
{
"name" : "Mark"
"age" : "18"
}
ps:JWT是默认不加密的,所以重要的信息不能放在这里。
JSON对象也要使用Base64URL算法转换成字符串。
Signature
Signature是对前面的两个部分进行签名,防止用户篡改数据。
首先,需要指定一个密钥。这个密钥只有服务器才知道,然后在Header里指定签名算法,按照一定的公式产生签名。
算出签名以后,把Header,Payload,Signature三个部分都拼成一个字符串,每个部分之间用 . 分隔开,然后返还给用户。
Base64URL
Header和Payload算法是Base64URL。跟基本的Base64算法有一些不同。
JWT作为令牌,需要在URL当中放入字符。例如+,/,=,在URL里面有特殊的含义,所以被替换掉。
- =被取消
- +替换成-
- /替换成_
JWT的使用方式
客户端收到服务器返回的JWT,可以存储在Cookie当中,也可以存储在本地数据库。
以后的每次与服务器通信,都要带上这个JWT。
- 可以放在Cookie当中自动发送,但是这样不能够跨域。
- 可以放在HTTP头信息当中会更好。
- 可以放在POST请求的数据体当中。
总结
JWT主要是为了解决跨域认证的问题。
JWT默认是不加密的,但也可以加密。生成原始的Token以后,可以使用密钥在进行一次加密。
JWT可以用于认证,也可以用于交换信息。
JWT最大的不便就是,一旦生成就无法更改。
JWT本身包含了一些认证信息,泄露之后,任何人都拥有该令牌的权限。
JWT最好不要使用HTTP裸奔,需要使用HTTPS穿上衣服。
那么HTTP和HTTPS的整个流程和规范,也是需要今后了解的,待补充。
参考