jwt
是什么
- JSON Web Token,
- 是一种客户端session;
- 这个token就是一个加密的、缓存了用户信息的 票据;
结构
结构: header.payload.signature
header = JSON格式的base64编码
{
type: "JWT",
alg: "SH256"
}
payload = JSON格式的base64编码
{
<内置>, <公共>, <私有>
}
header, payload 是明文
signature = 对`header.payload`的一次加盐摘要, 摘要由 header.alg 指定
流程
服务端: 存salt, 对 jwt 签发, 验证;
客户端: 存jwt, 每次请求都带上 jwt;
server 签发:
// 用户登录后, 生成jwt, 然后发送响应报文
header = '...'
payload = '...'
signature = sha256(header+'.'+payload, salt)
jwt = header + '.' + payload + '.' + signature
response_with(jwt)
server 校验:
jwt = request.headers['Authorization']
(header, payload, signature) = parse(jwt)
sha256(header+'.'+payload, salt) == signature
client 每次请求带上jwt:
- 在http请求头设置字段:
Authorization: 'Bearer <JWT>'
- Bearer 是固定的标识符
分析
优点
stateless,无状态,不用在服务端维护状态
安全问题
replay攻击
- 原理:中间者录制请求,然后重发
- 解决:
csrf_token
封装成中间件,但这个破坏了 stateless
局限性
登录相关的需求有:
- session 持久化
- session 共享
- 异地登录
- 重复登录
- 单点登录
- 注销
对于<3, 4, 6>,仅靠 stateless 无法实现
改密码,踢下线的思路:
- 服务端维护一个过期时间较长的refreshtoken
- 在下一次token过期时用refreshtoken去刷新
- 如果改了密码,那么重置这个refreshtoken,间接实现踢下线
payload 的考虑
payload 可以缓存用户信息:nickname, avatar
缓存都会面临过期问题,需要重新签发token
- 更新昵称头像就重新签发新token
- 客户端发现是新token就替换旧的
ref
http://tools.ietf.org/html/rfc7518#section-3.1
http://blog.leapoahead.com/2015/09/07/user-authentication-with-jwt