用户认证
功能描述
blade-auth-spring-boot-starter 是基于 SpringBoot 的身份认证启动器,提供了对身份认证服务的集成和封装。
更新记录
v3.0.0
- 初次实现
GAV 坐标
blade 全模块 2.2.5+ 版本,支持 SpringBoot 2.0+、jdk11+
<dependency>
<groupId>team.aikero.blade</groupId>
<artifactId>blade-auth-spring-boot-starter</artifactId>
</dependency># 2.2.5-SNAPSHOT
implementation(commonLibs.blade.auth.spring.boot.starter)blade 全模块 3.0.0+ 版本,支持 SpringBoot 3.0+、jdk21+
<dependency>
<groupId>team.aikero.blade</groupId>
<artifactId>blade-auth-spring-boot-starter</artifactId>
</dependency># 3.0.0-SNAPSHOT
implementation(commonLibs.blade.auth.spring.boot.starter)快速集成
选择合适的 GAV,在项目中的 pom.xml 添加依赖。
<dependency> <groupId>team.aikero.blade</groupId> <artifactId>blade-auth-spring-boot-starter</artifactId> </dependency>在项目的
application.yaml中添加下方代码。spring: config: import: - optional:nacos:blade-config <--- 在项目配置之前引入此配置 - optional:nacos:${spring.application.name}
详细说明
配置示例
默认情况下,blade-config 提供全局公共配置
若有特殊定制需求可以在application.yml文件中,可以进行以下配置:
blade:
auth:
# 是否启用认证拦截器
enabled: true
# token 相关配置,保持和 身份认证服务 一致
token:
# 用户权限加载方式(当前仅支持 redis),None(接口实时获取)、Local(接口+caffeine)
cache: local
# 系统用户信息
systemUser:
id: 1
name: 系统
code: SYSTEM
tenantId: 1
superAdmin: true
# 用户路径模式配置
urlPattern:
exclude-patterns:
- "/**/openapi/**"
# 权限加载路径
server:
host: ${domain.nest-api}/uacs代码示例
集成 starter 后,默认开启登录校验。
另外,可通过注解进行权限控制:
@PreCheckPermission权限码预校验注解,检查用户是否具有某权限码.
权限编码全局唯一,建议按照服务名.模块名.功能名进行编码,例如:aut.test.example。@PreCheckRole角色预校验注解,检查用户是否具有某角色@PreCheckIgnore忽略预校验,忽略登录态及权限检查
@PreAuth("test.example")
@RestController
public class TestController {
// 权限码实际为:test.example.get
@PreCheckPermission(name = "[auth_1.0.0]权限示例", value="{}.get")
@GetMapping("/get")
public String get() {
return "Hello, World!";
}
@PreCheckPermission(name = "[auth_1.0.0]权限示例", value="test.exmple.post")
@PostMapping("/post")
public String post() {
return "Hello, World!";
}
@PreCheckRole("admin")
@GetMapping("/admin")
public String test() {
return "Hello, World!";
}
@PreCheckIgnore
@GetMapping("/ignore")
public String test() {
return "Hello, World!";
}
}提示
基于配置和基于注解的权限放行,稍有不同:
- 配置文件
blade.auth.urlPattern.exclude-patterns属性:跳过拦截器执行的路径,所排除路径的用户上下文(CurrentUserHolder)一定为空。 - 注解方式
@PreCheckIgnore、@OpenAPI、@InnerAPI,跳过拦截器中 Token 校验逻辑,若 HTTP 请求存在有效 Token 时,用户上下文不为空,若 Token 失效,用户上下文为空。
获取用户上下文示例:
// 获取当前用户信息
CurrentUser user = CurrentUserHolder.get()
// 获取当前用户 id
Long id = CurrentUserHolder.getCurrentUserId()异步时使用用户上下文:
注意
进行异步编程时,若需要传递线程上下文,务必使用TransmittableThreadLocal进行包装。 对于不需要跨线程传递的上下文,使用 ThreadLocal。
引入
TransmittableThreadLocal依赖手动包装
Ruannable、Callable、ExecutorService
balde-util内提供了便于操作和转换的 API, 支持在 Kotlin 和 Java 中简化 TTL 操作。
// 在默认的 ForkJoin.commonPool 中执行,获取用户上下文
TtlWrapper.runAsync(() -> log.info(String.valueOf(CurrentUserHolder.get().getId())));
// 在手动管理的线程池中,获取用户上下文
TtlWrapper.runAsync(Executors.newSingleThreadExecutor(),
() -> log.info(String.valueOf(CurrentUserHolder.get().getId())));
// 在默认的 ForkJoin.commonPool 中执行,获取用户上下文,异步执行并返回结果
TtlWrapper.callAsync(CurrentUserHolder::getCurrentUserId).get();
// 在手动管理的线程池中,获取用户上下文,异步执行并返回结果
TtlWrapper.callAsync(Executors.newSingleThreadExecutor(), CurrentUserHolder::getCurrentUserId).get();// 在默认的 ForkJoin.commonPool 中执行,获取用户上下文
runAsync {
println(CurrentUserHolder.get().getId())
}
// 在手动管理的线程池中,获取用户上下文
runAsync(Executors.newSingleThreadExecutor()) {
println(CurrentUserHolder.get().getId())
}
// 在默认的 ForkJoin.commonPool 中执行,获取用户上下文,异步执行并返回结果
callAsync {
println(CurrentUserHolder.get().getId())
CurrentUserHolder.get().getId()
}.get()
// 在手动管理的线程池中,获取用户上下文,异步执行并返回结果
callAsync(Executors.newSingleThreadExecutor()) {
println(CurrentUserHolder.get().getId())
CurrentUserHolder.get().getId()
}.get()临时切换用户上下文:
// 切换至系统用户执行
UserContexts.withSystemUser(() -> {})
// 切换至指定用户执行
UserContexts.withUser(new CurrentUser(),() -> {})withSystemUser {
// do something
}
withUser(CurrentUser()) {
// do something
}实现方案
核心功能
权限拦截器 基于拦截器,拦截所有请求,对请求进行 Token 认证,认证通过后,将用户信息放入上下文。 校验权限时,从上下文获取用户信息,判断用户是否拥有该权限。
权限码上报
解析项目中 @PreCheckPermission 注解,启动时上报到身份认证服务,每个权限码为一条记录,便于配置管理。
