小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
在一个项目中,后端告诉我,登录成功后只返回一个token给我,没有额外返回用户信息,用户信息都在token中,自己去取。我看一下token,一堆乱码,这如何获取用户信息?一头雾水,再次询问后端,后端告诉我token是使用JSON Web Token生成,前端应该有解析这类token的JS库,下文将此类token称为JWT TOKEN。
既然后端都这么说了,去研究一下JSON Web Token技术。
JSON Web Token 是什么
JSON web token 可以理解为客户端向服务端发起登录请求后,后端把一些信息用 JSON 来表达,然后把 JSON 用算法加密后生成一个JWT TOKEN发送给客户端,随后客户端每次向服务端请求时,要在请求头中带上JWT TOKEN,服务端在把JWT解密进行认证,认证通过才给客户端返回数据。
咋一看,JWT TOKEN是在服务端用算法加密的,客户端应该不能用算法解密,否则不安全。其实不是这样,缘由先从JWT TOKEN的构成来说起。
JWT TOKEN的结构
其结构如上图所示分为三个部分:
- 头部-Header (红色部分)
- 载荷-Payload(粉红色部分)
- 签名-Signature (天蓝色部分)
每个部分之间用.分开,就如Header.Payload.Signature,下面依次介绍着几个部分。
头部 Header
Header 部分是使用 Base64URL 算法将一个 JSON 对象转成字符串。
这个 JSON 对象描述 JWT TOKEN 的元数据,通常是下面的样子。
{
'typ': 'JWT',
'alg': 'HS256'
}
其中typ表示TOKEN的类型,alg表示签名-Signature的加密方式,HS256表示用HmacSHA256算法加密。
载荷-Payload
Payload 部分也是使用 Base64URL 算法将一个 JSON 对象转成字符串。
在这个 JSON 对象中用来存放实际需要传递的数据。JWT 规定了7个官方字段。
- iss :签发人
- exp :过期时间
- sub :主题
- aud :受众
- nbf :生效时间
- iat :签发时间
- jti :编号
这个7个官方字段,无需全部使用,其中exp比较有用,可以和当前时间比较得出该 JWT TOKEN 是否过期。
除了官方字段,还可以定义一些私有字段,但是注意,Payload 部分是不加密的,任何人都可以读到,所以不要把不需要保密的信息放在这个部分。
那么就可以把一些不需要保密的用户信息添加进去,例如:
{
"id": "1234567890",
"name": "小明",
"depId": "1124587"
}
签名-Signature
Signature 部分是对前两部分的签名,防止数据篡改,按如下方法进行签名生成一个字符串。
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
其中secret就是HMACSHA256加密算法的密钥,这个密钥只能存放在服务端,当客户端把JWT TOKEN 放在请求头中给服务端发送过来,服务端通过secret密钥进行解密,然后进行认证。
解码载荷-Payload
从上面对JWT TOKEN每个部分的介绍,得知用户信息会存放在JWT TOKEN的第二部分,要对其解码才能获取用户信息。
前面介绍到载荷-Payload的 JSON 对象是用 Base64URL 编码成一个字符串。
这里介绍一个JS库进行解码Payload(载荷),就是jsonwebtoken。
执行命令npm install jsonwebtoken --save安装。
使用import jwt from 'jsonwebtoken';引入。
执行以下代码进行解码
const tokenDate = jwt.decode(token);
console.log(tokenDate.name);// 小明