Springboot 整合Sa-Token

文档:https://sa-token.cc

根据自己选择的版本来进入不同的文档

这是当前文档选择的版本文档:https://sa-token.cc/v/v1.34.0/doc.html#/

什么是Sa-Token?

Sa-Token 是一个轻量级 Java 权限认证框架,主要解决:登录认证权限认证单点登录OAuth2.0分布式Session会话微服务网关鉴权 等一系列权限相关问题。

Sa-Token 旨在以简单、优雅的方式完成系统的权限认证部分

为什么用它呢?

简单开箱即用,文档详细,简单易上手,功能丰富。

缺点:个人感觉封装的东西太多,导致丧失一定的灵活性,可能在碰到一些问题解决的成本也比较高。

SpringBoot 整合Sa-Token

pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
      <!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- Sa-Token 权限认证,在线文档:https://sa-token.cc/v/v1.34.0/doc.html#/ -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>${saToken.version}</version>
</dependency>
<!-- 引入这个的Redis的前提是先引入Redis 本身的依赖 -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-dao-redis</artifactId>
<version>${saToken.version}</version>
</dependency>

yml配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
 spring:
# redis配置
redis:
# Redis数据库索引(默认为0)
database: 3
# Redis服务器地址
host: 127.0.0.1
# Redis服务器连接端口
port: 6379
# Redis服务器连接密码(默认为空)
# password: root
# 连接超时时间
timeout: 10s
lettuce:
pool:
# 连接池最大连接数
max-active: 200
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1ms
# 连接池中的最大空闲连接
max-idle: 10
# 连接池中的最小空闲连接
min-idle: 0
############## Sa-Token 配置 (文档: https://sa-token.cc/v/v1.34.0/doc.html#/use/config) 比配置文件更加灵活 ##############
sa-token:
# token前缀
token-prefix: Bearer
# token名称 (同时也是cookie名称)
token-name: Authorization
# token有效期,单位s 默认30天, -1代表永不过期
timeout: 2592000
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒 半个小时
activity-timeout: 1800
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
is-share: true
# token风格
token-style: uuid
# 是否输出操作日志
is-log: false
# jwt秘钥
jwt-secret-key: asdsdaeuiwstarac123
# 是否读取cookie
is-read-cookie: false

实现Stp接口

该接口主要是用于saToken在查询用户权限或者角色时进行调用的实现类

StpInterfaceImpl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@Component
public class StpInterfaceImpl implements StpInterface {
@Resource
private UserMapper userMapper;

/**
* 返回一个用户所拥有的权限集合
*/
@Override
public List<String> getPermissionList(Object loginId, String loginKey) {
Long userId = Long.parseLong(loginId.toString());
// 根据用户Id去查询用户对应的权限
List<String> list = userMapper.searchUserPermissions(userId);
return list;
}


/**
* 返回一个用户所拥有的角色标识集合
*/
@Override
public List<String> getRoleList(Object loginId, String loginKey) {
Long userId = Long.parseLong(loginId.toString());
// 根据用户ID去查询对应角色的角色
userMapper.searchUserRole(userId);
return null;
}

}

开启注解并配置拦截器

SaTokenInterceptor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
@Log4j2
@Configuration
public class SaTokenInterceptor implements WebMvcConfigurer {

// 注册Sa-Token的注解拦截器,打开注解式鉴权功能 这样的话就可以进行注解校验了
@Override
public void addInterceptors(InterceptorRegistry registry) {
log.info("sa-token拦截器");
registry.addInterceptor(new SaInterceptor(handler -> {
// 指定一条 match 规则
SaRouter
.match("/**") // 拦截的 path 列表,可以写多个 */
// 排除掉的 path 列表
// 排除指定url 获取的方法
.notMatch("/**/login/**", "/**/outLogin/**", "/**/error/**",
"/**/register/**", "/**/verify/**", "/**/monitorLogin/**", "/**/enterprise/get",
"/**/enterprise/getLogo", "/**/getSAStoken/**", "/**/favicon.ico")
.notMatch("/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**", "/doc.html")
.check(r -> {
// 先判断是否登录
try {
StpUtil.checkLogin();
} catch (NotLoginException e) {
log.error(e.getMessage());
throw new BizException(ResultCode.RC403);
}
// 查看token是否要过期
long tokenSessionTimeout = StpUtil.getTokenTimeout();// 获取当前 Token 剩余有效时间 (单位: 秒)
log.info("tokenSessionTimeout剩余时间{}:", tokenSessionTimeout);
// 如果小于一天 那么就进行续期
if (tokenSessionTimeout < (60 * 60 * 24)) {
// 续期10天
StpUtil.renewTimeout(60 * 60 * 24 * 10);
}
}
); // 校验是否登录了
// 根据路由划分模块,不同模块不同鉴权
SaRouter.notMatch("/**/login/**","/**/outLogin/**").match("/user/**", r -> StpUtil.checkPermission("user"));
SaRouter.match("/role/**", r -> StpUtil.checkPermission("role"));
SaRouter.match("/func/**", r -> StpUtil.checkPermission("func"));
}))
.addPathPatterns("/**");
}

/**
* 注册 [Sa-Token全局过滤器]
*/
@Bean
public SaServletFilter getSaServletFilter() {
return new SaServletFilter()
// 拦截与排除 path
.addInclude("/**").addExclude("/favicon.ico")

// 全局认证函数
.setAuth(obj -> {
// ...
})

// 异常处理函数
.setError(e -> {
return AjaxJson.getError(e.getMessage());
})

// 前置函数:在每次认证函数之前执行
.setBeforeAuth(obj -> {
// ---------- 设置跨域响应头 ----------
SaHolder.getResponse()
// 允许指定域访问跨域资源
.setHeader("Access-Control-Allow-Origin", "*")
// 允许所有请求方式
.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE")
// 有效时间
.setHeader("Access-Control-Max-Age", "3600")
// 允许的header参数
.setHeader("Access-Control-Allow-Headers", "*");

// 如果是预检请求,则立即返回到前端
SaRouter.match(SaHttpMethod.OPTIONS)
.free(r -> System.out.println("--------OPTIONS预检请求,不做处理"))
.back();
})
;
}
}

整合gitHub地址: https://github.com/clollipop/springbootInit

到这里实际已经完成了整个的配置

如果要实现其他的操作可以参看官方文档,官方文档写的更加详细。