JWT一览

435 阅读2分钟

事情是这样的:我们做了一个小程序,在与后端 Api 交互的过程中总要带上个token。然而这个token过了两小时就失效,so 我们虽然做了处理了失效的逻辑,但是怎么模拟失效的token呢,这一切都要从JWT说起...

定义

JWT,JSON Web Token。一般用于 OAuth 2.0 鉴权系统中,由三部分组成,用 . 拼接:

  • header 定义 jwt 以及算法类型
  • payload 真正发送的数据
  • signature 由 header 与 payload 用算法生成的签名

你看到的一个jwt可能是这样的:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NTM1MDQzNTc5MTgsInVzZXIiOiJ0YW8iLCJzZXgiOjB9.Rg6jvDV2EMqtPQc2d4krpAUYC-hMtc54vSsZAuCxuKQ

header格式:

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

type 固定为JWT;algorithm 表示使用的算法,常用的有HS256(sha-256)、RS256(rsa-256)等等

payload(无格式,推荐 json 形式)

{
  "exp": 1553504357918,
  "user": "tao"
}

expire 指明了此 token 的有效时间,除此之外 RFC 还规范了其它几个字段比如说iss(issuer 生成者)、iat(issued at 生成时间)、jti(JWT ID 唯一标识)

signature生成方式:headerpayload编码成 base64,再用.拼接成一个字符串,最后通过 Hmac(hash-based message authentication code) 算法生成

hmac 与哈希算法的区别就是多了个 secret key,所以它也叫 keyed-hasing
注意:payload 中不应该放入敏感数据,诸如用户密码之类。因为它能直接被解码

简单的例子

const crypto = require('crypto');

// 固定格式
const header = {
  typ: 'JWT',
  alg: 'HS256',
};
// 需要传输的数据,也可以是一段字符串
const payload = {
  exp: 1553504357918,
  user: tao
};
const arr = [];
// 签名所用秘钥
const secret = 'Zeus';

// 编码 header 与 payload
arr.push(Buffer.from(JSON.stringify(header)).toString('base64'));
arr.push(Buffer.from(JSON.stringify(payload)).toString('base64'));

// 用 . 拼接,得到:
// eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NTM1MDQzNTc5MTgsInVzZXIiOiJ0YW8ifQ
const encodeStr = arr.join('.');

// 生成 signature
const signature = crypto
  .createHmac('sha256', secret)
  .update(encodeStr)
  .digest('base64');

arr.push(signature);
// 最后生成的 JWT:
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NTM1MDQzNTc5MTgsInVzZXIiOiJ0YW8iLCJzZXgiOjB9.Rg6jvDV2EMqtPQc2d4krpAUYC-hMtc54vSsZAuCxuKQ
arr.join('.');

目前 OAuth 2.0 以 JWT 形式生成的 token 比较主流,可以了解一下~

参考

  1. RFC 7519 - JSON Web Token (JWT)
  2. Base64
  3. 在线 jwt 生成与校验