1 Star 0 Fork 1

公子羽 / 计划管理后台

forked from zeta-zrg / 计划管理后台 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

Plan 后端接口开发

SpringBoot结合JWT+Shiro+Redis实现token无状态登录授权

一、引言 ​ 在微服务中我们一般采用的是无状态登录,而传统的session方式,在前后端分离的微服务架构下,如继续使用则必将要解决跨域sessionId问题、集群session共享问题等等。这显然是费力不讨好的,而整合shiro,却很不恰巧的与我们的期望有所违背,原因:   

(1)shiro默认的拦截跳转都是跳转url页面,而前后端分离后,后端并无权干涉页面跳转。   

(2)shiro默认使用的登录拦截校验机制恰恰就是使用的session。   

这当然不是我们想要的,因此如需使用shiro,我们就需要对其进行改造,那么要如何改造呢?我们可以在整合shiro的基础上自定义登录校验,继续整合JWT,或者oauth2.0等,使其成为支持服务端无状态登录,即token登录。

二、相关说明 2.1. Shiro + JWT实现无状态鉴权机制

  1. 首先post用户名与密码到login进行登入,如果成功在请求头Header返回一个加密的Authorization,失败的话直接返回未登录,以后访问都带上这个Authorization即可。

  2. 鉴权流程主要是要重写shiro的入口过滤器BasicHttpAuthenticationFilter,在此基础上进行拦截、token验证授权等操作

2.2. 关于AccessToken及RefreshToken概念说明

  1. AccessToken:用于接口传输过程中的用户授权标识,客户端每次请求都需携带,出于安全考虑通常有效时长较短。

  2. RefreshToken:与AccessToken为共生关系,一般用于刷新AccessToken,保存于服务端,客户端不可见,有效时长较长。

2.3. 关于Redis中保存RefreshToken信息(做到JWT的可控性)

  1. 登录认证通过后返回AccessToken信息(在AccessToken中保存当前的时间戳和帐号),同时在Redis中设置一条以帐号为Key,Value为当前时间戳(登录时间)的RefreshToken,现在认证时必须AccessToken没失效以及Redis存在所对应的RefreshToken,且RefreshToken时间戳和AccessToken信息中时间戳一致才算认证通过,这样可以做到JWT的可控性,如果重新登录获取了新的AccessToken,旧的AccessToken就认证不了,因为Redis中所存放的的RefreshToken时间戳信息只会和最新的AccessToken信息中携带的时间戳一致,这样每个用户就只能使用最新的AccessToken认证。

  2. Redis的RefreshToken也可以用来判断用户是否在线,如果删除Redis的某个RefreshToken,那这个RefreshToken所对应的AccessToken之后也无法通过认证了,就相当于控制了用户的登录,可以剔除用户

2.4. 关于根据RefreshToken自动刷新AccessToken

  1. 本身AccessToken的过期时间为5分钟,RefreshToken过期时间为30分钟,当登录后时间过了5分钟之后,当前AccessToken便会过期失效,再次带上AccessToken访问JWT会抛出TokenExpiredException异常说明Token过期,开始判断是否要进行AccessToken刷新,首先redis查询RefreshToken是否存在,以及时间戳和过期AccessToken所携带的时间戳是否一致,如果存在且一致就进行AccessToken刷新。
  2. 刷新后新的AccessToken过期时间依旧为5分钟,时间戳为当前最新时间戳,同时也设置RefreshToken中的时间戳为当前最新时间戳,刷新过期时间重新为30分钟过期,最终将刷新的AccessToken存放在Response的Header中的Authorization字段返回。
  3. 同时前端进行获取替换,下次用新的AccessToken进行访问即可。

项目亮点

  • 项目中用到redis做数据缓存,并使用延迟双删来解决缓存与数据库不一致
  • 由于本项目是前后端分离,所以在使用shiro时,整合了jwt,并实现了token过期时间的自刷新
  • 对于需要缓存的对象,由于有的字段经常变化,而有的字段基本上不变,所以在进行Redis缓存时,我又对对象进行了拆分缓存
  • 考虑到安全,用户密码加密时都加了随机盐,并hash多次
  • 考虑到接口的响应时间,根据自己写的sql,创建了索引,并修改了部分sql来使用索引
  • 对于项目中头像这类图片存储时,选择的是第三方的对象存储,这样能够减轻数据库的存储压力
  • 考虑到接口的幂等性,对于insert操作的处理是,插入前先select,对于update操作的处理是,在表中新增一个字段version,使用乐观锁去更新
  • 使用了布隆过滤器来减轻不必要的对数据库的访问

空文件

简介

暂无描述 展开 收起
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/gzla/plan.git
git@gitee.com:gzla/plan.git
gzla
plan
计划管理后台
master

搜索帮助

344bd9b3 5694891 D2dac590 5694891