从零搭建开发脚⼿架集成认证授权sa-token(尝鲜)
⽂章⽬录
⽬前我仅以学习和尝鲜为⽬的来集成,不建议⽤于公司等正式环境,公司还是建议 Shiro和 Spring Security那⼀套。(等我实战⼀波看看效果再说)
为什么要尝鲜Sa-Token
之前我还是挺排斥国产⼩作坊的开源作品,毕竟不是根红苗正,但是随着近⼏年国内开源社区的⼤⼒发展,以及在平时⼯作中⼜接触了解很多,慢慢改变了我的看法,其实国⼈开源作品还是很⾹的,其Api简单易⽤,源码和官⽅⽂档都是中⽂的,功能丰富且能满⾜很多中国式需求,各种QQ、交流活跃度⾮常⾼,总之就是极⼤程度满⾜中国式需求。
在权限认证框架领域,使⽤最多的莫过于Shiro和Spring Security,但是⼀天在逛同性交友⽹站(github)的时候,赫然发现了Sa-Token其竟然有2K的star数量,看其中⽂介绍竟然是轻量级Java权限认证框架,看了下其特性和功能点,就唤起了我强烈的好奇⼼,于是乎就有了今天的尝鲜。
Sa-Token是什么?
sa-token是⼀个轻量级Java权限认证框架,主要解决:登录认证、权限认证、Session会话、单点登录、OAuth2.0 等⼀系列权限相关问题
框架针对踢⼈下线、⾃动续签、前后台分离、分布式会话……等常见业务进⾏N多适配,通过sa-token,你可以以⼀种极简的⽅式实现系统的权限认证部分
与其它权限认证框架相⽐,sa-token 具有以下优势:
1. 简单 :可零配置启动框架,真正的开箱即⽤,低成本上⼿
2. 强⼤ :⽬前已集成⼏⼗项权限相关特性,涵盖了⼤部分业务场景的解决⽅案
3. 易⽤ :如丝般顺滑的API调⽤,⼤量⾼级特性统统只需⼀⾏代码即可实现
4. ⾼扩展 :⼏乎所有组件都提供了扩展接⼝,90%以上的逻辑都可以按需重写
Sa-Token 能做什么?
登录验证 —— 轻松登录鉴权,并提供五种细分场景值
权限验证 —— 适配RBAC权限模型,不同⾓⾊不同授权
Session会话 —— 专业的数据缓存中⼼
踢⼈下线 —— 将违规⽤户⽴刻清退下线
持久层扩展 —— 可集成Redis、Memcached等专业缓存中间件,重启数据不丢失
分布式会话 —— 提供jwt集成和共享数据中⼼两种分布式会话⽅案
单点登录 —— ⼀处登录,处处通⾏
模拟他⼈账号 —— 实时操作任意⽤户状态数据
临时⾝份切换 —— 将会话⾝份临时切换为其它账号
⽆Cookie模式 —— APP、⼩程序等前后台分离场景
同端互斥登录 —— 像QQ⼀样⼿机电脑同时在线,但是两个⼿机上互斥登录
多账号认证体系 —— ⽐如⼀个商城项⽬的user表和admin表分开鉴权
花式token⽣成 —— 内置六种token风格,还可⾃定义token⽣成策略
注解式鉴权 —— 优雅的将鉴权与业务代码分离
路由拦截式鉴权 —— 根据路由拦截鉴权,可适配restful模式
⾃动续签 —— 提供两种token过期策略,灵活搭配使⽤,还可⾃动续签
会话治理 —— 提供⽅便灵活的会话查询接⼝
记住我模式 —— 适配[记住我]模式,重启浏览器免验证
密码加密 —— 提供密码加密模块,可快速MD5、SHA1、SHA256、AES、RSA加密组件⾃动注⼊ —— 零配置与Spring等框架集成
快速集成
依赖导⼊
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>1.15.2</version>
</dependency>
最新版本去maven中央库⾃⼰查询下,当前是1.15.2。
配置⽂件
你可以零配置启动项⽬
但同时你也可以在l中增加如下配置,定制性使⽤框架:
spring:
# sa-token配置
sa-token:
# token名称 (同时也是cookie名称)
token-name: satoken
# token有效期,单位s 默认30天, -1代表永不过期
timeout:2592000
# token临时有效期 (指定时间内⽆操作就视为token过期) 单位: 秒
activity-timeout:-1
# 是否允许同⼀账号并发登录 (为true时允许⼀起登录, 为false时新登录挤掉旧登录)
allow-concurrent-login:true
# 在多⼈登录同⼀账号时,是否共⽤⼀个token (为true时所有登录共⽤⼀个token, 为false时每次登录新建⼀个token) is-share:false
# token风格
token-style: uuid
登录
@PostMapping("/api/v1/login")
@ApiOperationSupport(order =1)
@ApiOperation(value ="登录")
public Response login(String userName, String pwd){
log.info("login,username:{},pwd:{}", userName, pwd);
// 模拟校验⽤户名密码
Long userId =check(userName,pwd);
StpUtil.setLoginId(userId);
return Response.TokenInfo());
}
核⼼就⼀⾏StpUtil.setLoginId(userId),来看看它帮我们做了什么?
源码及其简单,还有很多中⽂注释,跟着读就⾏了,直接贴结论。
创建token
创建SaSession
在session上记录token签名
创建token、loginId映射
token写⼊cookie
底层会话等存储使⽤的是Map
源码如下:
/**
* 数据集合
*/
public Map<String, Object> dataMap =new ConcurrentHashMap<String, Object>();
/
**
* 过期时间集合 (单位: 毫秒) , 记录所有key的到期时间 [注意不是剩余存活时间]
*/
public Map<String, Long> expireMap =new ConcurrentHashMap<String, Long>();
调⽤结果如下:
Response Heards
Connection: keep-alive
Content-Type: application/json
Date: Fri, 09 Apr 2021 07:33:59 GMT
Keep-Alive: timeout=60
// 重点
Set-Cookie: LakerToken=da14afd3f4b648a889a1e51ac3ec53d7; Max-Age=1800; Expires=Fri, 09-Apr-2021 08:03:59 GMT; Path=/
Transfer-Encoding: chunked
Response Body
{
"code":200,
"msg":"",
"data":{
"tokenName":"LakerToken",
"tokenValue":"da14afd3f4b648a889a1e51ac3ec53d7",
"isLogin":true,
"loginId":"1",
"loginKey":"login",
"tokenTimeout":1784,
"sessionTimeout":1784,
"tokenSessionTimeout":-2,
"tokenActivityTimeout":30,
"loginDevice":"default-device"
}
}
可以看到返回heards中已⾃动设置:Set-Cookie: LakerToken=da14afd3f4b648a889a1e51ac3ec53d7; Max-Age=1800; Expires=Fri, 09-Apr-2021 08:03:59 GMT; Path=/
登出
@PostMapping("/api/v1/loginOut")
@ApiOperationSupport(order =3)
@ApiOperation(value ="登出")
@SaCheckLogin
public Response loginOut(){
StpUtil.logout();
return Response.ok();
}
核⼼也是⼀⾏StpUtil.logout(),来看看它帮我们做了什么?
获取HttpRequest
尝试从request⾥读取token
尝试从请求体⾥⾯读取token
尝试从header⾥读取token
尝试从cookie⾥读取token
删除cookie
删除token、loginId映射
注销session
请求拦截鉴权
第⼀步:配置全局
@Configuration
public class MySaTokenConfig implements WebMvcConfigurer {
/**
* 注册sa-token的,打开注解式鉴权功能 (如果您不需要此功能,可以删除此类)
*/
@Override
public void addInterceptors(InterceptorRegistry registry){
registry.addInterceptor(new SaAnnotationInterceptor()).addPathPatterns("/**");
}
}
第⼆步:在需要拦截的类或者⽅法上加注解
@SaCheckLogin: 标注在⽅法或类上,当前会话必须处于登录状态才可通过校验
@SaCheckRole("admin"): 标注在⽅法或类上,当前会话必须具有指定⾓⾊标识才能通过校验@SaCheckPermission("user:add"): 标注在⽅法或类上,当前会话必须具有指定权限才能通过校验
例如:
@GetMapping("/api/v1/tokenInfo")
@ApiOperationSupport(order =2)
@ApiOperation(value ="获取当前会话的token信息")
@SaCheckLogin
public Response tokenInfo(){
return Response.TokenInfo());
}
加上@SaCheckLogin则该接⼝必须处于登录状态才可通过校验。
这⾥核⼼拦截校验⼜是如何⼯作的呢?
可以看下SaAnnotationInterceptor.java源码,基于SpringMvc的实现的拦截校验。
实现功能如下:
验证登录
验证⾓⾊
验证权限
实现流程原理如下:
获取HttpRequest中的token
尝试从request⾥读取token
尝试从请求体⾥⾯读取token
session如何设置和读取尝试从header⾥读取token
尝试从cookie⾥读取token
判断token
⽆效token
过期
被顶下线
被踢下线
⾃动续期
权限和⾓⾊扩展
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论