ShiroJwt
前端地址:https://github.com/wang926454/VueStudy/tree/master/VueStudy08-JWT
疑问查看
有疑问请扫码加QQ群交流: 779168604
项目相关
- JavaDoc:https://apidoc.gitee.com/dolyw/ShiroJwt
- 接口文档:https://note.dolyw.com/shirojwt/ShiroJwt-Interface.html
- 教程目录:https://note.dolyw.com/shirojwt
- 改为数据库形式(MySQL):https://note.dolyw.com/shirojwt/ShiroJwt02-MySQL.html
- 解决无法直接返回401错误:https://note.dolyw.com/shirojwt/ShiroJwt03-401.html
- 实现Shiro的Cache(Redis)功能:https://note.dolyw.com/shirojwt/ShiroJwt04-Redis.html
项目介绍
- RESTful API
- Maven集成Mybatis Generator(逆向工程)
- Shiro + Java-JWT实现无状态鉴权机制(Token)
- 密码加密(采用AES-128 + Base64的方式)
- 集成Redis(Jedis)
- 重写Shiro缓存机制(Redis)
- Redis中保存RefreshToken信息(做到JWT的可控性)
- 根据RefreshToken自动刷新AccessToken
关于Shiro + Java-JWT实现无状态鉴权机制(Token)
- 首先Post用户名与密码到user/login登入,成功返回加密的AccessToken,失败直接返回401错误(帐号或密码不正确)
- 以后访问都带上这个AccessToken即可
- 鉴权流程主要是重写了Shiro的入口过滤器JWTFilter(BasicHttpAuthenticationFilter),判断请求Header里面是否包含Authorization字段
- 有就进行Shiro的Token登录认证授权(用户访问每一个需要权限的请求必须在Header中添加Authorization字段存放AccessToken),没有就以游客直接访问(有权限管控的话,以游客访问就会被拦截)
关于AES-128 + Base64当两个用户的明文密码相同时进行加密,会发现数据库中存在相同结构的暗文密码
大部分是以MD5 + 盐的形式解决了这个问题(详细自己百度),我采用AES-128 + Base64是以帐号+密码的形式进行加密密码,因为帐号具有唯一性,所以也不会出现相同结构的暗文密码这个问题
关于将Jedis工具类与SpringBoot整合
本来是直接将JedisUtil注入为Bean,每次使用直接
@Autowired
注入使用即可,但是在重写Shiro的CustomCache无法注入JedisUtil,所以就改成静态注入JedisPool连接池,JedisUtil工具类还是直接调用静态方法,无需@Autowired
注入
关于Redis中保存RefreshToken信息(做到JWT的可控性)
- 登录认证通过后返回AccessToken信息(在AccessToken中保存当前的时间戳和帐号)
- 同时在Redis中设置一条以帐号为Key,Value为当前时间戳(登录时间)的RefreshToken
- 现在认证时必须AccessToken没失效以及Redis存在所对应的RefreshToken,且RefreshToken时间戳和AccessToken信息中时间戳一致才算认证通过,这样可以做到JWT的可控性
- 如果重新登录获取了新的AccessToken,旧的AccessToken就认证不了,因为Redis中所存放的的RefreshToken时间戳信息只会和最新生成的AccessToken信息中携带的时间戳一致,这样每个用户就只能使用最新的AccessToken认证
- Redis的RefreshToken也可以用来判断用户是否在线,如果删除Redis的某个RefreshToken,那这个RefreshToken所对应的AccessToken之后也无法通过认证了,就相当于控制了用户的登录,可以剔除用户
关于根据RefreshToken自动刷新AccessToken
- 本身AccessToken的过期时间为5分钟(配置文件可配置),RefreshToken过期时间为30分钟(配置文件可配置)
- 当登录后时间过了5分钟之后,当前AccessToken便会过期失效,再次带上AccessToken访问JWT会抛出TokenExpiredException异常说明Token过期
- 开始判断是否要进行AccessToken刷新,Redis查询当前用户的RefreshToken是否存在,以及这个RefreshToken所携带时间戳和过期AccessToken所携带的时间戳是否一致
- 如果存在且一致就进行AccessToken刷新,设置过期时间为5分钟(配置文件可配置),时间戳为当前最新时间戳,同时也设置RefreshToken中的时间戳为当前最新时间戳,刷新过期时间重新为30分钟过期(配置文件可配置)
- 最终将刷新的AccessToken存放在Response的Header中的Authorization字段返回(前端进行获取替换,下次用新的AccessToken进行访问)
软件架构
- SpringBoot + Mybatis核心框架
- PageHelper插件 + 通用Mapper插件
- Shiro + Java-JWT无状态鉴权认证机制
- Redis(Jedis)缓存框架
安装教程
- 数据库帐号密码默认为root,如有修改,请自行修改配置文件application.yml
- 解压后执行src\main\resources\sql\MySQL.sql脚本创建数据库和表
- Redis需要自行安装Redis服务,端口密码默认
- SpringBoot直接启动即可,测试工具PostMan
使用说明
https://github.com/wang926454/ViewGenerator)
Mybatis Generator使用(可视化自定义模板快速生成基础代码:先配置src\main\resources\generator\generatorConfig.xml文件(默认配置都在原来包的下一级reverse包下),在pom.xml这一级目录(即项目根目录下)的命令行窗口执行(前提是配置了mvn)(IDEA可以直接在Maven窗口Plugins中双击执行)
mvn mybatis-generator:generate
PostMan使用(Token获取及使用)
先设置Content-Type为application/json
然后填写请求参数帐号密码信息
进行请求访问,请求访问成功
点击查看Header信息的Authorization属性即是Token字段
访问需要权限的请求将Token字段放在Header信息的Authorization属性访问即可
Token的自动刷新也是在Token失效时返回新的Token在Header信息的Authorization属性
搭建参考
- 感谢SmithCruise的Shiro+JWT+Spring Boot Restful简易教程:https://www.jianshu.com/p/f37f8c295057
- 感谢王洪玉的[Shiro入门](一)使用Redis作为缓存管理器:https://blog.csdn.net/why15732625998/article/details/78729254
- 感谢袋🐴饲养员的springboot(七).springboot整合jedis实现redis缓存:http://www.cnblogs.com/GodHeng/p/9301330.html
- 感谢W_Z_W_888的spring注入静态变量的三种方法及其注意事项:https://blog.csdn.net/W_Z_W_888/article/details/79979103
- 感谢天降风云的Vue2.0+ElementUI+PageHelper实现的表格分页:https://blog.csdn.net/u012907049/article/details/70237457
- 感谢yaxx的Vuejs之axios获取Http响应头:https://segmentfault.com/a/1190000009125333
- 感谢Twilight的解决使用jwt刷新token带来的问题:https://segmentfault.com/a/1190000013151506
- 感谢chuhx的shiro拦截器,返回json数据:https://blog.csdn.net/chuhx/article/details/51148877
- 感谢yidao620c的Shiro自带拦截器配置规则:https://github.com/yidao620c/SpringBootBucket/tree/master/springboot-jwt
参与贡献
- Fork 本项目
- 新建 Feat_xxx 分支
- 提交代码
- 新建 Pull Request