JSON Web Token 是一个开放标准(RFC 7519)

  • jwt定义了一种紧凑且独立的方式,可以将各方之间的信息作为 JSON对象进行安全传输
  • jwt的信息可以验证和信任,因为是经过数字签名的
  • 选择 jwt,放弃 session

https://juejin.im/book/6844733825164148744/section/6844733825222705159

egg中间件 https://juejin.im/book/6844733825164148744/section/6844733825214332942

jwt认证原理

  1. 前端 post发送用户名和密码到服务端,服务端对用户名和密码进行校验
  2. 校验成功后,将用户名或用户id等信息作为 payload载荷,与 header做 base64编码,形成 jwt
    1. 以点分割的字符串,生成的秘钥,也需要 base64编码
    2. 用户认证成功后,服务端将这个字符串作为 token返回给前端
  3. 前端将 token保存在 localStorage,或 SessionStorage里面
    1. 设置 Header请求头,每次请求都要携带这个 Authorization:Bearer Token,表示当前用户的身份
    2. 退出登录,前端删除这个token
  4. 后端用 jwt解析 token,获取 payload的用户信息

认证

  1. 让JWT认证与鉴权来保护你的API,jwt用户鉴权
  2. 用户认证:让服务器知道你是谁?
  3. 授权:让服务器告诉你能做什么?不能做什么?

jwt和 session

jwt & session都是为了解决:存储登录用户的信息
jwt用户信息加密存储在客户端,不依赖 cookie,跨域用的最多
jwt更适合服务节点多,跨域比较多的系统

session依赖 cookie,用户信息存储在服务端,默认不能跨域
session适合统一的web服务,server要严格管理用户信息

jwt的构成

  1. 头部 Header
  2. 有效载荷 Payload
  3. 签名 Signature
    1. 每部分用点 . 分割

Header

  1. typ:token的类型,这里固定为 jwt
  2. alg:使用的 hash算法,例如:HMAC,SHA256,或 RSA
    1. 使用了 base64编码,缩短了长度
  1. // 编码前
  2. {"alg": "HS256", "typ": 'jwt'}
  3. // 编码后
  4. eyJhbGiOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9

Payload

  1. 存储需要传递的信息,例如:用户id,用户名
  2. 还包含元数据,如:过期时间,发布人等
  3. Payload可以加密的
  4. Header是 base64 URL编码,忽略 =等号,把中划线变为下划线
  1. // 编码前
  2. {"username": "lucy", "id": 23}
  3. // 编码后
  4. eyJ1c2VbGiOiAiSFMyNTYiLCAidHlwIjogImdzYW4ifQ==
  5. // base64 URL编码后,忽略等号
  6. eyJ1c2VbGiOiAiSFMyNTYiLCAidHlwIjogImdzYW4ifQ

Signature

  1. 对 Header和 Payload进行签名,加密
  2. 保证 token在传输过程中没有被篡改或损坏
  1. // 签名后也需要 base64URL编码
  2. Signature = HMACSHA256(
  3. base64UrlEncode(header) + "." +
  4. base64UrlEncode(payload), secret
  5. )

jwt的3种实现

  1. nodejs实现 jwt
  2. koa2实现 jwt
  3. koa-jwt中间件

koa-jwt

  1. 使用中间件保护接口,获取用户信息
  2. https://github.com/koajs/jwt
  1. yarn add koa-jwt
  1. const jwt = require('koa-jwt')
  2. const { secret } = require('../config/default.config')
  3. const auth = jwt({ secret })