基于Token机制鉴权架构
一、登录:
服务端校验密码,成功后返回access_token及refresh_token
客户端记录上述token
二、访问api
在访问api之前解析access_token,并查看是否过期,如果不过期则请求api
如果过期,则要先刷新令牌,再请求api
三、刷新token
携带有效期的refresh_token换回有效token
如果refresh_token过期,则需要用户重新登录
四、注销
请求注销api,服务器端和客户端应同时删除token的存储
参数规范
一、token在header中的传输规范
"Authorization":"token值"
二、uuid在header中的传输规范
"uuid":"uuid值"
三、防重放攻击传输规范:
uid={value}×tamp={value}&nonce={nonce}&sign={sign}
四、权限校验失败返回值
http status:401
{"code":"001","message":"无权访问"}"
各流程架构
-
登录流程
逻辑说明
一、当用户需要登录时,客户端引导用户进行登录
二、登录发送用户名及密码至认证服务(passport)
三、认证服务验证用户名及密码,如果通过,通过jwt工具生成token
同时生成两种token:access_token和refresh_token
token的格式为:{ uid:1 username:"kingapex", role:"seller" }
access_token有效期为15分钟,refresh_token有效期为30分钟(以上时间应为可配置的常量)
四、将生成的token写入redis
分别 以ACCESSTOKEN*{uid}和REFRESHTOKEN*{uid} 为key存储
有效期为别为各token的有效期+60s
五、返回token
将token:access_token和refresh_token 、userid同时都返回,格式如下:
{ uid:1, access_token:"xxxxx", refresh_token:"xxxxx" }
-
验权流程
1、客户端请求api
携带access_token信息
如果是生产环境不会直接携带access_token信息,详见这里
2、获取token
根据环境不同而有不同的获取token方式,参考这里
3、解析token
通过jwt工具将token解析
4、由redis中读取token
根据uid拼接key读取出access_token
如果不存在这个用户的token说明用户已经登出
5、验证token
判断此token是否属于此uid
判断token是否已经过期,如果过期,则进行刷新token流程
6、注入权限
如果token验证成功,根据user信息生成权限注入到spring安全上下文中
用户禁用架构
需求说明
当用户遭禁时,该用户应如果已经登录,也该立刻被禁止访问。
难点在于禁用操作无法操作已经登录的客户端
架构思路
如果将已禁用的用户标识在redis中,每次访问都要读取这个reids,但这个总体来讲是小概率事件,影响性能了。
比较好的办法是:在每个app示例中存储一份被禁用户名单,当禁用操作发生时,通知所有运行的示例。
这个思路采用redis订阅事件:
刷新token流程
逻辑说明
1、客户端请求api
携带refresh_token信息
如果是生产环境不会直接携带refresh_token信息,详见这里
2、获取token
根据环境不同而有不同的获取token方式,参考这里
3、解析token
通过jwt工具将token解析
4、由redis中读取token
根据uid拼接key读取出access_token
如果不存在这个用户的token说明用户已经登出
5、验证token
判断此token是否属于此uid
判断token是否已经过期,如果过期,则返回refresh_token过期错误,此时用户需要重新登录
6、刷新token
如果refresh_token 验证成功,则重新生成access_token和refresh_token
上述有效期以当前时间向后计算
替换此用户在redis中的token
并将token返回给客户端