JWT(JSON Web Token)是比较流行的跨域认证解决方案。
一般来说做单点登录见常的方式是将登录凭证持久化,各服务都向持久层请求数据,这样内部多个应用系统就可以共享登录状态。另一种方式是服务端只生成相关凭证但不保存,客户端先请求生成凭证,然后每次请求时将这个凭证带上,由服务端校验这个凭证是否有效。JWT就是这种方案
JWT原理
JWT原理是,服务器认证以后,生成一个JSON对象,返给用户
{
"姓名":"张三",
"角色":"管理员",
"到期时间":"2018/7/1 12:30"
}
以后用户与服务端通信时,都要带上这个数据(该会进行加密处理)服务端对这个数据进行校验来判断这个数据的有效性。
以下是JWT认证方式的一个简图
JWT的数据结构
实际的JWT类似下面的数据:
eyJhbGciOiJIUzI1NiJ9.eyJ2YWx1ZSI6eyJuYW1lIjoiIiwidXNlcklkIjoiNTkxMTciLCJhdmF0YXJVcmwiOiIifSwiZWZmIjoxNzE5NDgyMTg0NTY5fQ.tE5PntqYNJOs0LPWM-aslmL4XAgXdADMgwuJy7-qPk8
它是一个很长的字符中,中间使用.分隔成三部分,三部分内容依次如下:
- Header(头部)
- Payload(负载)
- Signature(签名)
Header部分
Header部分是一个JSON对象,描述JWT的元数据,示例:
{
"alg":"HS256",
"typ":"JWT"
}
alt属性表示签名的算法(algorithm),默认是HMAC SHA256;typ属性表示这个令牌的类型,最后将上面的JSON对象使用Base64URL算法转成字符串。
Payload
Payload部分也是一个JSON对象,用来存放实际需要传递的数据。JWT的7个官方字段:
iss(issuer):签发人
exp(expiration time):过期时间
sub(subject):主题
aud(audience):受众
nbf(Not Before):生效时间
iat(Issued At):签发时间
jti(JWT ID):编号
除了上面的官方字段外,我们在这个部分还可以定义私有字段:
{
"sub":"123",
"name":"John Doe",
"admin":true
}
需要注意的是,JWT默认是不加密的,任何人都有可能读取到,所以不要将秘密信息放在这个部分。
这个JSON对象也要使用Base64URL算法转成字符串
Signature
Signature部分是对前两部分的签名,防止数据篡改
首先,需要指定一个密钥,这个密钥只有服务器才知道,不能泄露给用户,然后,使用Header里指定的签名算法(默认是HMAC SHA256)按照下面的公司生产签名:
HMACSHA25(
base64UrlEncode(header)+"."+
base64UrlEncode(payload),
secret
)
算出签名后,将Header、Payload、Signature三个部分拼成一个字符串,每个部分之间用.分隔,就可以返回给用户。
JWT的使用方式
客户端收到服务器返回的JWT,可以储存在Cookie里面,也可以储存在localStorage,此后,客户端每次与服务器通信,都要带上这个JWT。
JWT的几个特点
- JWT不存储任何数据,可使服务器免除session存取的压力,同时在集群机或多子站上面,也免除了session需要同步的烦恼。
- JWT默认是不加密的,但也可以在生成Token以后,再使用密钥加密一次
- JWT的缺点是,由于服务端不保存session状态,因此无法在使用过程中废止某个token,或者更改token的权限,也就是说,一旦JWT签发了,在到期之前就会始终有效,除非服务端部署额外逻辑
- JWT本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限,所以JWT的有效期应该设置得比较短
- 为了安全,JWT不建议使用HTTP协议明码传输,要使用HTTPS传输
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。