1. 什么是JWT
- JSON Web Token 是一个开放标准(RFC 7519)
- 定义了一种紧凑且独立的方式,可以将各方之间的信息作为JSON对象进行安全传输
- 该信息可以验证和信任,因为是经过数字签名的
2. JWT构成
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiemoiLCJpYXQiOjE1NjY1Mjc1ODB9.zp0xQbQQcK-xn7wDXFBEi64sNPqnhDCNCLh0QyqP8zI'
- 头部(Header)
- 有效载荷(Payload)
- 签名(Signature)
使用的是base64UrlEncode编码
2.1 头部
- typ: token的类型,这里固定位JWT
- alg:使用的hash算法,例如:HMAC SHA256 或者RSA
2.2 有效载荷
- 存储需要传递的信息,例如用户名
- 还包含元数据,如过期时间,发布人
- 与Header不同,Payload可以加密
2.3 签名
- 对Header和Payload部分进行签名(加密 )
- 保证Token在传输的过程中没有被篡改或者损坏
3 koa中操作jwt
3.1 安装jsonwebtoken
npm i jsonwebtoken -S
3.2 jsonwebtoken签名
const jwt = require('jsonwebtoken')
const token = jwt.sign({name: 'zj'}, 'secret')
// 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiemoiLCJpYXQiOjE1NjY1Mjc1ODB9.zp0xQbQQcK-xn7wDXFBEi64sNPqnhDCNCLh0QyqP8zI'
3.3 jsonwebtoken验证
const sign = jwt.verify(token, 'secret')
// { name: 'zj', iat: 1566527580 }
3.4 自定义jwt中间件
const jsonwebtoken = require('jsonwebtoken')
const auth = async (ctx, next) => {
const { authorization = '' } = ctx.request.header
const token = authorization.replace('Bearer ', '')
try {
const user = jsonwebtoken.verify(token, secret)
ctx.state.user = user
} catch (e) {
ctx.throw(401, e.message)
}
await next()
}
...
router.del('/:id', auth, del)
3.5 使用koa-jwt中间件代替自定义jwt中间件
const jwt = require('koa-jwt')
const auth = jwt({secret})
...
router.del('/:id', auth, del)
3.6 登录返回token
// 登录接口
...
const token = jsonwebtoken.sign({name, _id}, secret, {expiresIn: '1d'}) // expiresIn 过期时间1天
ctx.body = { token }
3.7 验证登录人与jwt信息是否一致
async checkOwner (ctx, next) {
if (ctx.params.id !== ctx.state.user._id) {
ctx.throw(403, '没有权限')
}
await next()
}
...
router.del('/:id', auth, checkOwner, del)