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认证原理
- 前端 post发送用户名和密码到服务端,服务端对用户名和密码进行校验
- 校验成功后,将用户名或用户id等信息作为 payload载荷,与 header做 base64编码,形成 jwt
- 以点分割的字符串,生成的秘钥,也需要 base64编码
- 用户认证成功后,服务端将这个字符串作为 token返回给前端
- 前端将 token保存在 localStorage,或 SessionStorage里面
- 设置 Header请求头,每次请求都要携带这个
Authorization:Bearer Token
,表示当前用户的身份 - 退出登录,前端删除这个token
- 设置 Header请求头,每次请求都要携带这个
- 后端用 jwt解析 token,获取 payload的用户信息
认证
- 让JWT认证与鉴权来保护你的API,jwt用户鉴权
- 用户认证:让服务器知道你是谁?
- 授权:让服务器告诉你能做什么?不能做什么?
jwt和 session
jwt & session都是为了解决:存储登录用户的信息
jwt用户信息加密存储在客户端,不依赖 cookie,跨域用的最多
jwt更适合服务节点多,跨域比较多的系统
session依赖 cookie,用户信息存储在服务端,默认不能跨域
session适合统一的web服务,server要严格管理用户信息
jwt的构成
- 头部 Header
- 有效载荷 Payload
- 签名 Signature
- 每部分用点 . 分割
Header
- typ:token的类型,这里固定为 jwt
- alg:使用的 hash算法,例如:HMAC,SHA256,或 RSA
- 使用了 base64编码,缩短了长度
// 编码前
{"alg": "HS256", "typ": 'jwt'}
// 编码后
eyJhbGiOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9
Payload
- 存储需要传递的信息,例如:用户id,用户名
- 还包含元数据,如:过期时间,发布人等
- Payload可以加密的
- Header是 base64 URL编码,忽略 =等号,把中划线变为下划线
// 编码前
{"username": "lucy", "id": 23}
// 编码后
eyJ1c2VbGiOiAiSFMyNTYiLCAidHlwIjogImdzYW4ifQ==
// base64 URL编码后,忽略等号
eyJ1c2VbGiOiAiSFMyNTYiLCAidHlwIjogImdzYW4ifQ
Signature
- 对 Header和 Payload进行签名,加密
- 保证 token在传输过程中没有被篡改或损坏
// 签名后也需要 base64URL编码
Signature = HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload), secret
)
jwt的3种实现
- nodejs实现 jwt
- koa2实现 jwt
- koa-jwt中间件
koa-jwt
- 使用中间件保护接口,获取用户信息
- https://github.com/koajs/jwt
yarn add koa-jwt
const jwt = require('koa-jwt')
const { secret } = require('../config/default.config')
const auth = jwt({ secret })