JWT(JSON Web Token)使用方法详解

JWT(JSON Web Token)是目前比较流行的一种身份认证解决方式,下面详细的介绍下原理和用法。

用户认证问题

需要登录后才能使用的互联网服务离不开用户认证。
传统的流程如下:

1. 客户端向服务器发送用户名和密码;
2. 服务器端验证通过后,在当前对话(session)里面保存相关数据,比如用户ID、登录时间等等;
3. 服务器端向客户端返回一个 session_id,客户端随后的每一次请求都会将 session_id 传给服务器;
4. 服务器端接收到 session_id,找到相应的数据来获得用户的身份。

这种方式的问题是扩展性不好。单机当然没有问题,如果是服务器集群的话就需要 session 数据共享。不但很难做到,方法也不够优雅,目前一般不会采取这种很传统的方式。
上面的方案是服务端需要报错session数据,相应的也有服务器端不保存 session 数据的方案,JWT 就是这种方案的一个代表。

JWT 原理

JWT本质上就是一个字符串,服务器认证以后根据一些规则生成的一个字符串返回给客户端,客户端随后的每次请求都会将这个字符串传给服务端,服务端拿到这个字符串后经过解析校验,最终获取到用户的身份,服务端不需要保存这个字符串。

下面是一个常规的JWT

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.cThIIoDvwdueQB468K5xDc5633seEFoqwxjF_xSJyQQ

可以看出JWT是被点.分隔成三个部分的字符串。JWT 的三个部分依次如下:

Header(头部)
Payload(负载)
Signature(签名)

基本结构就是Header.Payload.Signature

Header

Header 部分经过解析后是一个 JSON 对象,描述 JWT 的元数据,通常是下面的样子。

{
  "alg": "HS256",
  "typ": "JWT"
}

alg属性表示签名的算法(algorithm),默认是 HMAC SHA256;typ属性表示token的类型(type)。
将 JSON 对象使用 Base64URL 算法转成字符串。

Payload

Payload 部分经过解析后也是一个 JSON 对象,用来存放用户身份相关数据。例如

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

将 JSON 对象使用 Base64URL 算法转成字符串。

Signature

Signature 部分是对前两部分的签名,防止数据被篡改。
首先需要指定一个密钥(这个密钥必须要存放在服务器端,不能泄露给客户端),然后使用 Header 里面指定的签名算法(默认是 HMAC SHA256)按照下面的公式计算出签名。

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串(每个部分之间用点.分隔)后返回给客户端。

使用JWT需要注意的点
  1. JWT 默认是不加密的,在生产最好做加密;
  2. JWT由于服务器端不保存 session 状态,因此无法在使用过程中废止某个 token,或者更改 token 的权限。即JWT一旦签发,在到期之前就会始终有效,除非服务器端针对某个token做特殊处理;
  3. JWT 本身包含了认证信息,为了保证安全起见,JWT 的有效期应该设置得比较短。

Base64URL和Base64

Base64后可能会有三个字符+、/和=,而Base64URL会讲这三个字符做如下转换:

=被省略
+替换成-
/替换成_
微信公众号
关注36nu微信公众账号
获取最新编程知识及经验