Json Web Token介绍

250 阅读4分钟

Json Web Token是目前最流行的跨域流行的认证解决方案。

跨域认证的问题

互联网服务离不开用户认证,一般流程如下
1.用户向服务器发送用户名和密码
2.服务器验证通过后,在当前对话里面保存相关数据,比如用户角色、登陆时间等等
3.服务器向用户返回一个session_id,写入用户的Cookie.
4.用户随后的每一次请求,都会通过Cookie将session_id传回服务器。
5.服务器收到session_id,找到前期保存的数据,得知用户的身份。

这种模式的问题在于,扩展性不好。单机当然没有问题,如果是服务器集群,或者是跨域的服务导向架构,就要求session数据共享,每台服务器能够读取session。

举例来说,A网站和B网站是相关联的服务。现在要求,用户只要在其中一个网站登陆,在访问另一个网站就会自动登陆。

一般解决方案是session数据持久化,写入数据库或者别的持久层。各种服务收到请求后,都去持久层请求数据。这种方案的优点是架构清晰,缺点是工程量比较大。如果持久层挂了,就会单点失败。

另一种方案是服务器就不存session数据了,所有数据都保存在客户端,每次请求都发回服务器。JWT就是这种解决方案。

JWT的原理

Jwt的原理是,服务器认证后,生成一个Json对象,发送给用户。
就像这样。
{
  "姓名": "张三",
  "角色": "管理员",
  "到期时间": "2018年7月1日0点0分"
}
以后,用户与服务端通信的时候,都要发回这个JSON对象。服务器完全只靠这个对象认定用户身份。为了防止篡改数据,服务器在生成这个对象的时候,会加上签名。

服务器就不保存任何session数据了,服务器就无状态了,容易拓展。

JWT的数据结构

JWT的三个部分依次是:Header(头部)、Payload(负载)、Signature(签名)

Header:
    Header部分是一个JSON对象,描述JWT的元数据,通常是下面的样子。
    {
    "alg": "HS256",
    "typ": "JWT"
    }
alg属性黛代表签名的算法,默认是HMAC SHA256;typ属性表示这个令牌的类型,JWT的令牌统一写为JWT

Payload部分也是一个json对象,用来存放实际需要传递的数据。JWT规定了7个官方字段,如下图所示。

Signature:

它是对前两部分的签名,防止数据篡改。
首先,需要指定一个密钥secret。这个密钥只有服务器才知道,不能泄漏给用户。然后,使用Header里面指定的签名算法进行加密&解密

Base64URL

前面提到,Header和Payload串型化的算法是Base64URL.这个算法跟Base64算法基本类似。

Jwt作为一个令牌(token),有些场合可能会放到url。Base64有三个字符+、/和=,在URL里面有特殊含义,所以要被替换掉:=被省略、+替换为-、/替换为_。这就是Base64URL算法。

JWT的使用方式

客户端收到服务器返回的JWT,可以存储在Cookie里面,也可以存储在localStorage里面。
此后,客户端每次与服务器通信,都要带上JWT。可以把它放在Cookie里面自动发送,但是这样不能跨域,更好的做法是放在http的请求头Authorization字段里面。

Authorization:Bear<token>

JWT的几个特点

1.JWT默认是不加密的,但也是可以加密的。生成原始token以后,可以用密钥再加密一次。
2.JWT不加密的情况下,不能讲秘密数据写入JWT。
3.JWT不仅可以用于认证,也可以用于交互信息。有效使用JWT,可以降低服务器查询数据库的次数.
4.JWT的最大缺点是,由于服务器不保存session状态,因为无法在使用过程中废止某个token,或者更改token权限。也就是说,一旦JWT签发了,在到期之前就会始终有效,除非服务器增加额外的逻辑。
5.JWT本身包含了认证信息,一旦泄漏,任何人都可以获得该令牌的权限。为了减少盗用,JWT的有效期应该设置的比较短。对于一些比较重要的权限,使用时应该再次对用户进行认真。
6.为了减少盗用,JWT不应该使用HTTP协议明码传输,而使用HTTPS进行传输。