mirror of
https://github.moeyy.xyz/https://github.com/GeWuYou/forgeboot
synced 2025-10-27 16:24:22 +08:00
build: 删除安全认证模块的自动配置
- 移除了安全认证模块的所有自动配置类 - 删除了相关的配置属性、处理程序、策略等类 - 清除了构建脚本中的依赖引用 - 移除了.gitattributes和.gitignore文件
This commit is contained in:
parent
b9da8bf395
commit
5f3e078e0f
3
forgeboot-security/.gitattributes
vendored
3
forgeboot-security/.gitattributes
vendored
@ -1,3 +0,0 @@
|
||||
/gradlew text eol=lf
|
||||
*.bat text eol=crlf
|
||||
*.jar binary
|
||||
40
forgeboot-security/.gitignore
vendored
40
forgeboot-security/.gitignore
vendored
@ -1,40 +0,0 @@
|
||||
HELP.md
|
||||
.gradle
|
||||
build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Kotlin ###
|
||||
.kotlin
|
||||
@ -1,5 +0,0 @@
|
||||
extra{
|
||||
setProperty(ProjectFlags.IS_ROOT_MODULE,true)
|
||||
}
|
||||
dependencies {
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
/gradlew text eol=lf
|
||||
*.bat text eol=crlf
|
||||
*.jar binary
|
||||
@ -1,40 +0,0 @@
|
||||
HELP.md
|
||||
.gradle
|
||||
build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Kotlin ###
|
||||
.kotlin
|
||||
@ -1,3 +0,0 @@
|
||||
/gradlew text eol=lf
|
||||
*.bat text eol=crlf
|
||||
*.jar binary
|
||||
@ -1,40 +0,0 @@
|
||||
HELP.md
|
||||
.gradle
|
||||
build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Kotlin ###
|
||||
.kotlin
|
||||
@ -1,8 +0,0 @@
|
||||
|
||||
dependencies {
|
||||
api(project(Modules.Webmvc.DTO))
|
||||
compileOnly(project(Modules.Security.CORE))
|
||||
compileOnly(libs.springBootStarter.web)
|
||||
compileOnly(libs.springBootStarter.security)
|
||||
kapt(libs.springBoot.configuration.processor)
|
||||
}
|
||||
@ -1,75 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.api.config
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties
|
||||
import org.springframework.http.HttpMethod
|
||||
|
||||
/**
|
||||
* 安全身份验证属性配置类
|
||||
*
|
||||
* 该类用于定义安全认证相关的配置属性,包含路径权限设置、异常响应信息和基础URL配置。
|
||||
* 属性值通过@ConfigurationProperties绑定前缀"forgeboot.security.authenticate"的配置项。
|
||||
*
|
||||
* @since 2025-06-11 15:20:27
|
||||
* @author gewuyou
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "forgeboot.security.authenticate")
|
||||
class SecurityAuthenticateProperties {
|
||||
/**
|
||||
* 登录请求的HTTP方法,默认为POST
|
||||
*/
|
||||
var loginHttpMethod: String = HttpMethod.POST.name()
|
||||
|
||||
/**
|
||||
* 默认认证异常响应内容,当请求缺少认证时返回此字符串
|
||||
*/
|
||||
var defaultExceptionResponse = "Full authentication is required to access this resource"
|
||||
|
||||
/**
|
||||
* 默认认证失败响应内容,当认证失败时返回此字符串
|
||||
*/
|
||||
var defaultAuthenticationFailureResponse = "If the authentication fails, please report the request ID for more information!"
|
||||
|
||||
/**
|
||||
* 认证模块的基础URL前缀
|
||||
*/
|
||||
var baseUrl = "/api/auth"
|
||||
|
||||
/**
|
||||
* 登录接口的URL路径
|
||||
*/
|
||||
var loginUrl = "/login"
|
||||
|
||||
/**
|
||||
* 登出接口的URL路径
|
||||
*/
|
||||
var logoutUrl = "/logout"
|
||||
|
||||
/**
|
||||
* 是否启用单 token 登录认证(如登录接口、token 生成器)
|
||||
*/
|
||||
var singleToken: SingleTokenAuthenticationProperties = SingleTokenAuthenticationProperties()
|
||||
|
||||
/**
|
||||
* 配置单 Token 认证相关属性
|
||||
*
|
||||
* 提供一个嵌套类来管理单 Token 认证的启用状态,这种设计模式允许在不改变主配置类的情况下,
|
||||
* 独立扩展单 Token 相关的更多配置项。
|
||||
*/
|
||||
class SingleTokenAuthenticationProperties {
|
||||
var enabled: Boolean = false
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否启用双 token 登录认证
|
||||
*/
|
||||
var dualToken: DualTokenAuthenticationProperties = DualTokenAuthenticationProperties()
|
||||
|
||||
/**
|
||||
* 配置双 Token 认证相关属性
|
||||
*
|
||||
* 嵌套类用于封装双 Token 认证机制的启用状态,保持配置结构清晰并支持未来扩展。
|
||||
*/
|
||||
class DualTokenAuthenticationProperties {
|
||||
var enabled: Boolean = false
|
||||
}
|
||||
}
|
||||
@ -1,24 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.api.customizer
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
|
||||
/**
|
||||
* 登录过滤器定制器接口
|
||||
*
|
||||
* 该函数式接口用于自定义Spring Security的登录过滤器配置。
|
||||
* 实现此接口的类或lambda表达式可用于调整安全配置中的HttpSecurity设置,
|
||||
* 特别是在登录认证流程中对请求的安全策略进行定制化处理。
|
||||
*
|
||||
* @since 2025-06-11 18:53:25
|
||||
* @author gewuyou
|
||||
*/
|
||||
fun interface LoginFilterCustomizer {
|
||||
/**
|
||||
* 自定义方法,用于配置或修改HttpSecurity对象。
|
||||
*
|
||||
* 此方法将被调用以应用特定的安全性规则到登录过滤器上。
|
||||
*
|
||||
* @param http HttpSecurity对象,提供了配置Web安全性的API
|
||||
*/
|
||||
fun customize(http: HttpSecurity)
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.api.customizer
|
||||
|
||||
|
||||
/**
|
||||
* 接口用于支持登录过滤器扩展器的排序功能。
|
||||
*
|
||||
* 此接口继承自 [LoginFilterCustomizer],通过提供一个 order 属性来定义实现类的执行顺序,
|
||||
* 确保多个 [LoginFilterCustomizer] 实现类能够按照预期的顺序被调用。
|
||||
*
|
||||
* @since 2025-06-27 07:58:46
|
||||
* @author gewuyou
|
||||
*/
|
||||
interface OrderedLoginFilterCustomizer : LoginFilterCustomizer {
|
||||
/**
|
||||
* 定义当前定制器的执行顺序。
|
||||
*
|
||||
* 数值越小,优先级越高,即会越早被执行。
|
||||
*/
|
||||
val order: Int
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.api.enums
|
||||
|
||||
/**
|
||||
*登录类型
|
||||
*
|
||||
* @since 2025-06-12 21:11:02
|
||||
* @author gewuyou
|
||||
*/
|
||||
object LoginTypes {
|
||||
/**
|
||||
* 默认登录类型标识
|
||||
*/
|
||||
const val DEFAULT = "default"
|
||||
/**
|
||||
* 用户名密码登录类型标识
|
||||
*/
|
||||
const val USERNAME_PASSWORD = "username_password"
|
||||
|
||||
/**
|
||||
* OAuth2 认证登录类型标识
|
||||
*/
|
||||
const val OAUTH2 = "oauth2"
|
||||
|
||||
/**
|
||||
* 短信验证码登录类型标识
|
||||
*/
|
||||
const val SMS = "sms"
|
||||
}
|
||||
@ -1,18 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.api.exception
|
||||
|
||||
import org.springframework.security.core.AuthenticationException
|
||||
|
||||
|
||||
/**
|
||||
*Forge Boot身份验证异常
|
||||
*
|
||||
* @since 2025-06-11 15:49:33
|
||||
* @author gewuyou
|
||||
*/
|
||||
open class ForgeBootAuthenticationException(
|
||||
msg: String,
|
||||
cause: Throwable? = null
|
||||
): AuthenticationException(
|
||||
msg,
|
||||
cause
|
||||
)
|
||||
@ -1,27 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.api.handler
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
|
||||
/**
|
||||
* 委派处理程序接口,用于定义委派处理器的行为规范。
|
||||
*
|
||||
* 该接口设计为泛型函数式接口,要求实现类提供一个方法,
|
||||
* 将给定的 HTTP 请求解析为指定类型的委派对象。
|
||||
*
|
||||
* @param <T> 委派对象的类型,必须是非空类型
|
||||
*
|
||||
* @since 2025-06-11 14:51:48
|
||||
* @author gewuyou
|
||||
*/
|
||||
fun interface DelegatingHandler<T: Any> {
|
||||
/**
|
||||
* 根据提供的 HTTP 请求解析出对应的委派对象。
|
||||
*
|
||||
* 此方法通常用于从请求中提取认证信息或上下文数据,
|
||||
* 并将其转换为具体的业务对象以供后续处理使用。
|
||||
*
|
||||
* @param request 要解析的 HTTP 请求对象,不能为 null
|
||||
* @return 返回解析得到的委派对象,具体类型由接口泛型 T 决定
|
||||
*/
|
||||
fun resolveDelegate(request: HttpServletRequest): T
|
||||
}
|
||||
@ -1,30 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.api.registry
|
||||
|
||||
import com.gewuyou.forgeboot.security.core.authenticate.entities.request.LoginRequest
|
||||
|
||||
/**
|
||||
* 登录请求类型注册表
|
||||
*
|
||||
* 用于管理不同登录类型的请求类,支持注册和查询操作。
|
||||
*
|
||||
* @since 2025-06-26 22:06:00
|
||||
* @author gewuyou
|
||||
*/
|
||||
interface LoginRequestTypeRegistry {
|
||||
|
||||
/**
|
||||
* 注册一个新的登录类型及其对应的请求类。
|
||||
*
|
||||
* @param loginType 登录类型的标识字符串
|
||||
* @param clazz 继承自LoginRequest的具体请求类
|
||||
*/
|
||||
fun register(loginType: String, clazz: Class<out LoginRequest>): LoginRequestTypeRegistry
|
||||
|
||||
/**
|
||||
* 根据登录类型获取对应的请求类。
|
||||
*
|
||||
* @param loginType 登录类型的标识字符串
|
||||
* @return 返回与登录类型关联的请求类,如果未找到则返回null
|
||||
*/
|
||||
fun getTypeForLoginType(loginType: String): Class<out LoginRequest>?
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.api.resolver
|
||||
|
||||
import com.gewuyou.forgeboot.security.core.authenticate.entities.request.LoginRequest
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
|
||||
/**
|
||||
* 登录请求解析器接口
|
||||
* 用于定义处理登录请求的通用规范,包括内容类型支持判断和请求参数解析功能
|
||||
*
|
||||
* @since 2025-06-10 16:32:32
|
||||
* @author gewuyou
|
||||
*/
|
||||
interface LoginRequestResolver {
|
||||
|
||||
/**
|
||||
* 判断当前解析器是否支持指定的内容类型
|
||||
*
|
||||
* @param contentType 请求内容类型
|
||||
* @return Boolean 返回true表示支持该内容类型,否则不支持
|
||||
*/
|
||||
fun supports(contentType: String): Boolean
|
||||
|
||||
/**
|
||||
* 解析HTTP请求为具体的登录请求对象
|
||||
* 该方法应从HttpServletRequest中提取并封装登录所需参数
|
||||
*
|
||||
* @param request HTTP请求对象
|
||||
* @return LoginRequest 解析后的登录请求实体对象
|
||||
*/
|
||||
fun resolve(request: HttpServletRequest): LoginRequest
|
||||
}
|
||||
@ -1,47 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.api.service
|
||||
|
||||
import com.gewuyou.forgeboot.security.core.common.entities.TokenPair
|
||||
|
||||
/**
|
||||
* 双令牌认证服务
|
||||
*
|
||||
* 提供基于访问令牌和刷新令牌的认证机制相关功能接口,包含令牌生成与刷新逻辑。
|
||||
*
|
||||
* @since 2025-06-26 20:43:14
|
||||
* @author gewuyou
|
||||
*/
|
||||
interface DualTokenAuthenticationService {
|
||||
|
||||
/**
|
||||
* 刷新令牌并生成新的一对令牌
|
||||
*
|
||||
* 使用旧访问令牌(可能已过期)和有效刷新令牌生成新的 TokenPair。
|
||||
* 刷新过程中会验证刷新令牌的有效性,并作废旧的令牌组合。
|
||||
*
|
||||
* @param accessToken 旧访问令牌(可能已过期)
|
||||
* @param refreshToken 有效刷新令牌
|
||||
* @return 新的 TokenPair(accessToken + refreshToken)
|
||||
*/
|
||||
fun refreshTokenPair(accessToken: String, refreshToken: String): TokenPair
|
||||
|
||||
/**
|
||||
* 生成新刷新令牌
|
||||
*
|
||||
* 根据系统策略生成一个安全的、唯一的刷新令牌字符串。
|
||||
* 该令牌通常具有较长的有效期且用于获取新访问令牌。
|
||||
*
|
||||
* @return 生成的刷新令牌字符串
|
||||
*/
|
||||
fun generateRefreshToken(): String
|
||||
|
||||
/**
|
||||
* 生成访问令牌
|
||||
*
|
||||
* 基于用户详细信息生成一个访问令牌,用于临时认证请求。
|
||||
* 该令牌通常具有较短的有效期,且不能直接用于刷新操作。
|
||||
*
|
||||
* @param userDetails 用户详细信息对象
|
||||
* @return 生成的访问令牌字符串
|
||||
*/
|
||||
fun generateAccessToken(userDetails: Any): String
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.api.service
|
||||
|
||||
import org.springframework.security.core.userdetails.UserDetails
|
||||
|
||||
|
||||
/**
|
||||
*用户缓存服务
|
||||
*
|
||||
* @since 2025-02-15 17:15:17
|
||||
* @author gewuyou
|
||||
*/
|
||||
interface UserCacheService {
|
||||
/**
|
||||
* 从缓存中获取用户信息
|
||||
* @param principal 用户标识
|
||||
* @return 用户信息 返回null表示缓存中没有该用户信息或信息已过期
|
||||
*/
|
||||
fun getUserFromCache(principal: String): UserDetails?
|
||||
|
||||
/**
|
||||
* 将用户信息缓存到缓存中 注意,请将过期时间设置得尽可能短,以防止缓存与数据库出现数据不一致
|
||||
* @param userDetails 用户信息
|
||||
*/
|
||||
fun putUserToCache(userDetails: UserDetails)
|
||||
|
||||
/**
|
||||
* 从缓存中移除用户信息
|
||||
* @param principal 用户标识
|
||||
*/
|
||||
fun removeUserFromCache(principal: String)
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.api.spec
|
||||
|
||||
import com.gewuyou.forgeboot.security.core.common.entities.TokenPair
|
||||
import com.gewuyou.forgeboot.webmvc.dto.R
|
||||
|
||||
/**
|
||||
* 双令牌身份验证控制器规格
|
||||
*
|
||||
* 定义了基于双令牌(访问令牌和刷新令牌)的身份验证机制操作规范。
|
||||
* 主要用于处理令牌刷新等核心安全认证交互流程。
|
||||
*
|
||||
* @since 2025-06-26 20:24:40
|
||||
* @author gewuyou
|
||||
*/
|
||||
fun interface DualTokenAuthenticationControllerSpec {
|
||||
/**
|
||||
* 刷新访问令牌
|
||||
*
|
||||
* 当访问令牌过期时,通过有效刷新令牌获取一组新的令牌对。
|
||||
* 此方法应校验刷新令牌的有效性,并生成新访问令牌。
|
||||
* 根据实现策略,刷新令牌也可能被更新并返回。
|
||||
*
|
||||
* @param accessToken 过期的访问令牌(通常通过 Authorization 头或请求体传入)
|
||||
* @param refreshToken 有效刷新令牌(用于验证并生成新令牌)
|
||||
* @return 包含新令牌对的响应对象,通常包括新访问令牌和可能更新刷新令牌
|
||||
*/
|
||||
fun refresh(accessToken: String, refreshToken: String): R<TokenPair>
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.api.strategy
|
||||
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler
|
||||
|
||||
/**
|
||||
* 身份验证失败策略接口,用于定义不同登录类型的身份验证失败处理机制。
|
||||
*
|
||||
* @since 2025-06-10 23:43:43
|
||||
* @author gewuyou
|
||||
*/
|
||||
interface AuthenticationFailureStrategy : AuthenticationHandlerSupportStrategy, AuthenticationFailureHandler
|
||||
@ -1,23 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.api.strategy
|
||||
|
||||
/**
|
||||
* 身份验证处理程序支持策略
|
||||
*
|
||||
* 该函数式接口定义了身份验证策略需要实现的基本规范,用于标识当前策略支持的登录类型。
|
||||
* 实现类应当通过返回特定的登录类型集合来表明该策略的应用范围。
|
||||
*
|
||||
* @since 2025-06-11 00:03:28
|
||||
* @author gewuyou
|
||||
*/
|
||||
fun interface AuthenticationHandlerSupportStrategy {
|
||||
/**
|
||||
* 获取当前策略支持的登录类型标识符。
|
||||
*
|
||||
* 此方法用于判断当前身份验证策略能够处理的登录请求类型。
|
||||
* 例如:可以基于不同的认证方式(如密码、短信验证码、OAuth等)进行区分。
|
||||
*
|
||||
* @return 返回当前策略支持的登录类型字符串集合
|
||||
* 集合中的每个字符串代表一种支持的登录类型标识符
|
||||
*/
|
||||
fun supportedLoginTypes(): Set<String>
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.api.strategy
|
||||
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler
|
||||
|
||||
/**
|
||||
* 身份验证成功策略接口,用于定义不同登录类型的成功处理策略。
|
||||
*
|
||||
* @since 2025-06-10 23:42:54
|
||||
* @author gewuyou
|
||||
*/
|
||||
interface AuthenticationSuccessStrategy : AuthenticationHandlerSupportStrategy, AuthenticationSuccessHandler
|
||||
@ -1,26 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.api.strategy
|
||||
|
||||
import com.gewuyou.forgeboot.security.core.authenticate.entities.request.LoginRequest
|
||||
import org.springframework.security.core.Authentication
|
||||
|
||||
/**
|
||||
*登录请求转换器策略
|
||||
* 请注意,该接口仅用于定义转换器的接口只负责转换登录请求为认证对象,不负责提供认证逻辑。
|
||||
* 具体的认证逻辑由具体的认证提供类实现。因此当需要自定义认证逻辑时,请实现具体的认证提供类。
|
||||
* @since 2025-02-15 03:23:34
|
||||
* @author gewuyou
|
||||
*/
|
||||
interface LoginRequestConverterStrategy {
|
||||
/**
|
||||
* 转换登录请求为认证对象
|
||||
* @param loginRequest 登录请求
|
||||
* @return 认证对象
|
||||
*/
|
||||
fun convert(loginRequest: LoginRequest): Authentication
|
||||
|
||||
/**
|
||||
* 获取支持的登录类型
|
||||
* @return 请求的登录类型
|
||||
*/
|
||||
fun getSupportedLoginType(): String
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.api.strategy
|
||||
|
||||
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler
|
||||
|
||||
/**
|
||||
* 注销成功策略接口,用于定义在用户注销成功后的处理逻辑。
|
||||
*
|
||||
* 实现此类的策略应当提供具体地登出后操作,例如清理会话、记录日志等。
|
||||
*
|
||||
* @since 2025-06-10 23:49:35
|
||||
* @author gewuyou
|
||||
*/
|
||||
interface LogoutSuccessStrategy : AuthenticationHandlerSupportStrategy, LogoutSuccessHandler
|
||||
@ -1,3 +0,0 @@
|
||||
/gradlew text eol=lf
|
||||
*.bat text eol=crlf
|
||||
*.jar binary
|
||||
@ -1,40 +0,0 @@
|
||||
HELP.md
|
||||
.gradle
|
||||
build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Kotlin ###
|
||||
.kotlin
|
||||
@ -1,9 +0,0 @@
|
||||
plugins {
|
||||
alias(libs.plugins.kotlin.plugin.spring)
|
||||
}
|
||||
dependencies {
|
||||
compileOnly(libs.springBootStarter.security)
|
||||
compileOnly(libs.springBootStarter.web)
|
||||
compileOnly(project(Modules.Security.Authenticate.IMPL))
|
||||
implementation(project(Modules.Security.CORE))
|
||||
}
|
||||
@ -1,89 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.autoconfigure
|
||||
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.config.SecurityAuthenticateProperties
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.customizer.LoginFilterCustomizer
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.customizer.OrderedLoginFilterCustomizer
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.filter.UnifiedAuthenticationFilter
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.handler.CompositeLogoutSuccessHandler
|
||||
import com.gewuyou.forgeboot.security.core.common.extension.cleanUnNeedConfig
|
||||
import org.springframework.beans.factory.ObjectProvider
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.web.AuthenticationEntryPoint
|
||||
import org.springframework.security.web.SecurityFilterChain
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher
|
||||
|
||||
/**
|
||||
* 安全身份验证自动配置
|
||||
*
|
||||
* 主要用于配置与安全认证相关的 Bean 和 Spring Security 的过滤器链。
|
||||
*
|
||||
* @since 2025-06-11 15:04:58
|
||||
* @author gewuyou
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties(SecurityAuthenticateProperties::class)
|
||||
class SecurityAuthenticateAutoConfiguration {
|
||||
|
||||
/**
|
||||
* Spring Security 认证流程的自动配置类。
|
||||
*
|
||||
* 该内部类负责构建主要的安全过滤器链,处理登录、登出以及异常入口点等核心功能。
|
||||
*
|
||||
* @property logoutSuccessHandler 处理登出成功的处理器
|
||||
* @property authenticationExceptionHandler 处理认证异常的入口点
|
||||
* @property unifiedAuthenticationFilter 统一的身份验证过滤器
|
||||
* @property customizers 可选的登录过滤器定制器集合
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(SecurityFilterChain::class)
|
||||
class SpringSecurityAuthenticateAutoConfiguration(
|
||||
private val logoutSuccessHandler: CompositeLogoutSuccessHandler,
|
||||
private val authenticationExceptionHandler: AuthenticationEntryPoint,
|
||||
private val unifiedAuthenticationFilter: UnifiedAuthenticationFilter,
|
||||
private val customizers: ObjectProvider<List<LoginFilterCustomizer>>,
|
||||
) {
|
||||
|
||||
/**
|
||||
* 构建并返回一个自定义的安全过滤器链。
|
||||
*
|
||||
* 该方法配置了:
|
||||
* - 清除不必要地默认安全配置
|
||||
* - 登出功能及其成功处理器
|
||||
* - 异常处理(认证失败入口点)
|
||||
* - 请求匹配规则和访问控制策略
|
||||
* - 添加统一的身份验证过滤器到过滤器链中
|
||||
* - 对可排序的登录过滤器定制器进行排序并应用
|
||||
*
|
||||
* @param http HttpSecurity 实例,用于构建安全过滤器链
|
||||
* @param properties 安全认证属性配置对象
|
||||
* @return 构建完成的 SecurityFilterChain 实例
|
||||
*/
|
||||
@Bean(name = ["forgebootSecurityAuthenticationChain"])
|
||||
fun loginFilterChain(
|
||||
http: HttpSecurity,
|
||||
properties: SecurityAuthenticateProperties,
|
||||
): SecurityFilterChain {
|
||||
return http
|
||||
.cleanUnNeedConfig()
|
||||
.logout {
|
||||
it.logoutUrl(properties.logoutUrl)
|
||||
.logoutSuccessHandler(logoutSuccessHandler)
|
||||
}
|
||||
.exceptionHandling {
|
||||
it.authenticationEntryPoint(authenticationExceptionHandler)
|
||||
}
|
||||
.securityMatcher(AntPathRequestMatcher(properties.baseUrl))
|
||||
.addFilterBefore(unifiedAuthenticationFilter, UsernamePasswordAuthenticationFilter::class.java)
|
||||
.also {
|
||||
customizers.ifAvailable?.sortedBy { c -> (c as? OrderedLoginFilterCustomizer)?.order ?: 0 }
|
||||
?.forEach { it.customize(http) }
|
||||
}
|
||||
.build()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,256 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.autoconfigure
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.config.SecurityAuthenticateProperties
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.registry.LoginRequestTypeRegistry
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.resolver.LoginRequestResolver
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.service.UserCacheService
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.strategy.AuthenticationFailureStrategy
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.strategy.AuthenticationSuccessStrategy
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.strategy.LogoutSuccessStrategy
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.filter.UnifiedAuthenticationFilter
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.handler.AuthenticationExceptionHandler
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.handler.CompositeAuthenticationFailureHandler
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.handler.CompositeAuthenticationSuccessHandler
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.handler.CompositeLogoutSuccessHandler
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.registry.SimpleLoginRequestTypeRegistry
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.resolver.CompositeLoginRequestResolver
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.strategy.context.AuthenticationFailureHandlerContext
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.strategy.context.AuthenticationSuccessHandlerContext
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.strategy.context.LoginRequestConverterContext
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.strategy.context.LogoutSuccessHandlerContext
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||
import org.springframework.context.ApplicationContext
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.context.annotation.Primary
|
||||
import org.springframework.security.authentication.AuthenticationManager
|
||||
import org.springframework.security.authentication.AuthenticationProvider
|
||||
import org.springframework.security.authentication.ProviderManager
|
||||
import org.springframework.security.core.userdetails.UserDetails
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
|
||||
import org.springframework.security.crypto.password.PasswordEncoder
|
||||
import org.springframework.security.web.AuthenticationEntryPoint
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher
|
||||
|
||||
/**
|
||||
*安全核心自动配置
|
||||
*
|
||||
* @since 2025-06-27 07:54:04
|
||||
* @author gewuyou
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
class SecurityCoreAutoConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
fun bCryptPasswordEncoder(): PasswordEncoder {
|
||||
return BCryptPasswordEncoder()
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
fun nullUserCacheService(): UserCacheService {
|
||||
return object : UserCacheService {
|
||||
override fun getUserFromCache(principal: String): UserDetails? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun putUserToCache(userDetails: UserDetails) {
|
||||
//ignore
|
||||
}
|
||||
|
||||
override fun removeUserFromCache(principal: String) {
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建并返回一个登录请求类型注册器。
|
||||
*
|
||||
* 用于注册和管理不同类型的登录请求,确保系统中所有登录方式能够被统一识别和处理。
|
||||
* 如果上下文中不存在该类型的 Bean,则会使用默认实现 SimpleLoginRequestTypeRegistry。
|
||||
*
|
||||
* @return 实现 LoginRequestTypeRegistry 接口的 Bean 实例
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
fun loginRequestTypeRegistry(): LoginRequestTypeRegistry {
|
||||
return SimpleLoginRequestTypeRegistry()
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建并返回一个组合式的登录请求解析器。
|
||||
*
|
||||
* 将多个 LoginRequestResolver 实现组合成一个统一的接口调用入口。
|
||||
*
|
||||
* @param resolvers 所有可用的 LoginRequestResolver 实例列表
|
||||
* @return 组合后的 CompositeLoginRequestResolver 实例
|
||||
*/
|
||||
@Bean
|
||||
fun compositeLoginRequestResolver(
|
||||
resolvers: List<LoginRequestResolver>,
|
||||
) = CompositeLoginRequestResolver(resolvers)
|
||||
|
||||
/**
|
||||
* 创建并返回一个登出成功处理的上下文实例。
|
||||
*
|
||||
* 用于根据注册的策略动态选择合适的 LogoutSuccessStrategy。
|
||||
*
|
||||
* @param strategies 所有可用的 LogoutSuccessStrategy 实例列表
|
||||
* @return 初始化好的 LogoutSuccessHandlerContext 实例
|
||||
*/
|
||||
@Bean
|
||||
fun logoutSuccessHandlerContext(
|
||||
strategies: List<LogoutSuccessStrategy>,
|
||||
) = LogoutSuccessHandlerContext(strategies)
|
||||
|
||||
/**
|
||||
* 创建并返回一个组合式的登出成功处理器。
|
||||
*
|
||||
* 使用解析器和上下文来决定最终使用的登出成功策略。
|
||||
*
|
||||
* @param resolver 登录请求解析器
|
||||
* @param context 登出成功处理上下文
|
||||
* @return 初始化好的 CompositeLogoutSuccessHandler 实例
|
||||
*/
|
||||
@Bean(name = ["logoutSuccessHandler"])
|
||||
fun compositeLogoutSuccessHandler(
|
||||
resolver: CompositeLoginRequestResolver,
|
||||
context: LogoutSuccessHandlerContext,
|
||||
) = CompositeLogoutSuccessHandler(resolver, context)
|
||||
|
||||
/**
|
||||
* 创建并返回一个认证异常处理器。
|
||||
*
|
||||
* 当用户未认证或认证失败时,通过此处理器响应客户端。
|
||||
*
|
||||
* @param objectMapper JSON 序列化工具
|
||||
* @param properties 安全认证属性配置
|
||||
* @return 初始化好的 AuthenticationExceptionHandler 实例
|
||||
*/
|
||||
@Bean
|
||||
fun authenticationExceptionHandler(
|
||||
objectMapper: ObjectMapper,
|
||||
properties: SecurityAuthenticateProperties,
|
||||
): AuthenticationEntryPoint = AuthenticationExceptionHandler(objectMapper, properties)
|
||||
|
||||
/**
|
||||
* 创建并返回一个认证管理器。
|
||||
*
|
||||
* 使用一组 AuthenticationProvider 来支持多种认证方式。
|
||||
*
|
||||
* @param authenticationProviders 所有可用的认证提供者
|
||||
* @return 初始化好的 ProviderManager 实例
|
||||
*/
|
||||
@Bean(name = ["authenticationManager"])
|
||||
@Primary
|
||||
fun authenticationManager(
|
||||
authenticationProviders: List<AuthenticationProvider>,
|
||||
): AuthenticationManager = ProviderManager(authenticationProviders)
|
||||
|
||||
/**
|
||||
* 创建并返回一个认证成功处理的上下文。
|
||||
*
|
||||
* 根据当前请求上下文动态选择合适的认证成功策略。
|
||||
*
|
||||
* @param strategies 所有可用的 AuthenticationSuccessStrategy 实例列表
|
||||
* @return 初始化好的 AuthenticationSuccessHandlerContext 实例
|
||||
*/
|
||||
@Bean
|
||||
fun authenticationSuccessHandlerContext(
|
||||
strategies: List<AuthenticationSuccessStrategy>,
|
||||
) = AuthenticationSuccessHandlerContext(strategies)
|
||||
|
||||
/**
|
||||
* 创建并返回一个组合式的认证成功处理器。
|
||||
*
|
||||
* 委托给具体的策略实现来进行响应。
|
||||
*
|
||||
* @param resolver 登录请求解析器
|
||||
* @param context 认证成功处理上下文
|
||||
* @return 初始化好的 CompositeAuthenticationSuccessHandler 实例
|
||||
*/
|
||||
@Bean(name = ["authenticationSuccessHandler"])
|
||||
fun authenticationSuccessHandler(
|
||||
resolver: CompositeLoginRequestResolver,
|
||||
context: AuthenticationSuccessHandlerContext,
|
||||
): AuthenticationSuccessHandler = CompositeAuthenticationSuccessHandler(resolver, context)
|
||||
|
||||
/**
|
||||
* 创建并返回一个认证失败处理的上下文。
|
||||
*
|
||||
* 根据当前请求上下文动态选择合适的认证失败策略。
|
||||
*
|
||||
* @param strategies 所有可用的 AuthenticationFailureStrategy 实例列表
|
||||
* @return 初始化好的 AuthenticationFailureHandlerContext 实例
|
||||
*/
|
||||
@Bean
|
||||
fun authenticationFailureHandlerContext(
|
||||
strategies: List<AuthenticationFailureStrategy>,
|
||||
) = AuthenticationFailureHandlerContext(strategies)
|
||||
|
||||
/**
|
||||
* 创建并返回一个组合式的认证失败处理器。
|
||||
*
|
||||
* 委托给具体的策略实现来进行响应。
|
||||
*
|
||||
* @param resolver 登录请求解析器
|
||||
* @param context 认证失败处理上下文
|
||||
* @return 初始化好的 CompositeAuthenticationFailureHandler 实例
|
||||
*/
|
||||
@Bean(name = ["authenticationFailureHandler"])
|
||||
fun authenticationFailureHandler(
|
||||
resolver: CompositeLoginRequestResolver,
|
||||
context: AuthenticationFailureHandlerContext,
|
||||
): AuthenticationFailureHandler = CompositeAuthenticationFailureHandler(resolver, context)
|
||||
|
||||
/**
|
||||
* 创建并返回一个登录请求转换上下文。
|
||||
*
|
||||
* 用于根据当前请求上下文动态选择合适的登录请求转换逻辑。
|
||||
*
|
||||
* @param applicationContext Spring 应用上下文
|
||||
* @return 初始化好的 LoginRequestConverterContext 实例
|
||||
*/
|
||||
@Bean
|
||||
fun loginRequestConverterContext(
|
||||
applicationContext: ApplicationContext,
|
||||
) = LoginRequestConverterContext(applicationContext)
|
||||
|
||||
/**
|
||||
* 创建并返回一个统一的身份验证过滤器。
|
||||
*
|
||||
* 该过滤器是整个认证流程的核心,处理登录请求并触发相应的成功/失败处理器。
|
||||
*
|
||||
* @param properties 安全认证属性配置
|
||||
* @param authenticationManager 认证管理器
|
||||
* @param authenticationSuccessHandler 成功认证处理器
|
||||
* @param authenticationFailureHandler 失败认证处理器
|
||||
* @param compositeLoginRequestResolver 组合登录请求解析器
|
||||
* @param loginRequestConverterContext 登录请求转换上下文
|
||||
* @return 初始化好的 UnifiedAuthenticationFilter 实例
|
||||
*/
|
||||
@Bean
|
||||
fun unifiedAuthenticationFilter(
|
||||
properties: SecurityAuthenticateProperties,
|
||||
authenticationManager: AuthenticationManager,
|
||||
authenticationSuccessHandler: AuthenticationSuccessHandler,
|
||||
authenticationFailureHandler: AuthenticationFailureHandler,
|
||||
compositeLoginRequestResolver: CompositeLoginRequestResolver,
|
||||
loginRequestConverterContext: LoginRequestConverterContext,
|
||||
): UnifiedAuthenticationFilter =
|
||||
UnifiedAuthenticationFilter(
|
||||
AntPathRequestMatcher(
|
||||
properties.baseUrl + properties.loginUrl,
|
||||
properties.loginHttpMethod
|
||||
),
|
||||
authenticationManager,
|
||||
authenticationSuccessHandler,
|
||||
authenticationFailureHandler,
|
||||
compositeLoginRequestResolver,
|
||||
loginRequestConverterContext
|
||||
)
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.autoconfigure
|
||||
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.service.UserCacheService
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.provider.impl.UsernamePasswordAuthenticationProvider
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.security.authentication.AuthenticationProvider
|
||||
import org.springframework.security.core.userdetails.UserDetailsService
|
||||
import org.springframework.security.crypto.password.PasswordEncoder
|
||||
|
||||
/**
|
||||
*安全提供程序自动配置
|
||||
*
|
||||
* @since 2025-06-26 22:33:53
|
||||
* @author gewuyou
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
class SecurityProviderAutoConfiguration {
|
||||
@Bean("usernamePasswordAuthenticationProvider")
|
||||
@ConditionalOnMissingBean
|
||||
fun usernamePasswordAuthenticationProvider(
|
||||
userCacheService: UserCacheService,
|
||||
userDetailsService: UserDetailsService,
|
||||
passwordEncoder: PasswordEncoder
|
||||
): AuthenticationProvider {
|
||||
return UsernamePasswordAuthenticationProvider(
|
||||
userCacheService,
|
||||
userDetailsService,
|
||||
passwordEncoder
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,91 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.autoconfigure
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.config.SecurityAuthenticateProperties
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.strategy.AuthenticationFailureStrategy
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.strategy.AuthenticationSuccessStrategy
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.strategy.LoginRequestConverterStrategy
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.strategy.LogoutSuccessStrategy
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.strategy.impl.DefaultAuthenticationFailureStrategy
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.strategy.impl.DefaultAuthenticationSuccessStrategy
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.strategy.impl.DefaultLogoutSuccessStrategy
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.strategy.impl.UsernamePasswordLoginRequestConverterStrategy
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
|
||||
/**
|
||||
* 安全策略自动配置类
|
||||
*
|
||||
* 该类定义了多个Bean用于注册认证相关的策略实现,确保系统中存在默认的安全策略处理逻辑。
|
||||
* 所有Bean都使用@ConditionalOnMissingBean注解,表示只有在没有手动定义相应Bean时才会创建默认实例。
|
||||
*
|
||||
* @since 2025-06-27 08:02:26
|
||||
* @author gewuyou
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
class SecurityStrategyAutoConfiguration {
|
||||
|
||||
/**
|
||||
* 创建默认的认证成功策略Bean
|
||||
*
|
||||
* 如果上下文中不存在AuthenticationSuccessStrategy类型的Bean,则注册一个默认的实现。
|
||||
* 依赖于ObjectMapper用于序列化/反序列化操作。
|
||||
*
|
||||
* @param objectMapper Jackson的ObjectMapper实例,用于处理JSON数据
|
||||
* @return 默认的认证成功策略实例
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
fun defaultAuthenticationSuccessStrategy(objectMapper: ObjectMapper): AuthenticationSuccessStrategy {
|
||||
return DefaultAuthenticationSuccessStrategy(objectMapper)
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建默认的认证失败策略Bean
|
||||
*
|
||||
* 如果上下文中不存在AuthenticationFailureStrategy类型的Bean,则注册一个默认的实现。
|
||||
* 依赖于ObjectMapper和SecurityAuthenticateProperties,用于定制失败响应和配置参数。
|
||||
*
|
||||
* @param objectMapper Jackson的ObjectMapper实例,用于处理JSON数据
|
||||
* @param properties 安全认证相关配置属性,用于定制行为
|
||||
* @return 默认的认证失败策略实例
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
fun defaultAuthenticationFailureStrategy(
|
||||
objectMapper: ObjectMapper,
|
||||
properties: SecurityAuthenticateProperties
|
||||
): AuthenticationFailureStrategy {
|
||||
return DefaultAuthenticationFailureStrategy(objectMapper, properties)
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建默认的登出成功策略Bean
|
||||
*
|
||||
* 如果上下文中不存在LogoutSuccessStrategy类型的Bean,则注册一个默认的实现。
|
||||
* 依赖于ObjectMapper用于序列化/反序列化操作。
|
||||
*
|
||||
* @param objectMapper Jackson的ObjectMapper实例,用于处理JSON数据
|
||||
* @return 默认的登出成功策略实例
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
fun defaultLogoutSuccessStrategy(objectMapper: ObjectMapper): LogoutSuccessStrategy {
|
||||
return DefaultLogoutSuccessStrategy(objectMapper)
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建默认的登录请求转换策略Bean
|
||||
*
|
||||
* 如果上下文中不存在LoginRequestConverterStrategy类型的Bean,则注册一个基于用户名密码的默认实现。
|
||||
* 该Bean指定了名称"usernamePasswordLoginRequestConverterStrategy",以便通过名称引用。
|
||||
*
|
||||
* @return 默认的登录请求转换策略实例
|
||||
*/
|
||||
@Bean("usernamePasswordLoginRequestConverterStrategy")
|
||||
@ConditionalOnMissingBean
|
||||
fun defaultLoginRequestConverterStrategy(): LoginRequestConverterStrategy {
|
||||
return UsernamePasswordLoginRequestConverterStrategy()
|
||||
}
|
||||
}
|
||||
@ -1,4 +0,0 @@
|
||||
com.gewuyou.forgeboot.security.authenticate.autoconfigure.SecurityAuthenticateAutoConfiguration
|
||||
com.gewuyou.forgeboot.security.authenticate.autoconfigure.SecurityProviderAutoConfiguration
|
||||
com.gewuyou.forgeboot.security.authenticate.autoconfigure.SecurityStrategyAutoConfiguration
|
||||
com.gewuyou.forgeboot.security.authenticate.autoconfigure.SecurityCoreAutoConfiguration
|
||||
@ -1,6 +0,0 @@
|
||||
extra{
|
||||
setProperty(ProjectFlags.IS_ROOT_MODULE,true)
|
||||
}
|
||||
dependencies {
|
||||
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
/gradlew text eol=lf
|
||||
*.bat text eol=crlf
|
||||
*.jar binary
|
||||
@ -1,40 +0,0 @@
|
||||
HELP.md
|
||||
.gradle
|
||||
build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Kotlin ###
|
||||
.kotlin
|
||||
@ -1,11 +0,0 @@
|
||||
plugins{
|
||||
alias(libs.plugins.kotlin.plugin.spring)
|
||||
}
|
||||
dependencies {
|
||||
api(project(Modules.Security.Authenticate.API))
|
||||
implementation(project(Modules.Security.CORE))
|
||||
implementation(project(Modules.Core.EXTENSION))
|
||||
implementation(project(Modules.Webmvc.DTO))
|
||||
compileOnly(libs.springBootStarter.web)
|
||||
compileOnly(libs.springBootStarter.security)
|
||||
}
|
||||
@ -1,49 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.impl.constants
|
||||
|
||||
/**
|
||||
* Forge Boot安全身份验证响应信息
|
||||
*
|
||||
* 该对象包含用于身份验证过程中的各种预定义错误响应消息。
|
||||
* 每个属性代表一种特定的身份验证失败或系统错误情况,供在认证流程中抛出或返回给调用者。
|
||||
*
|
||||
* @since 2025-06-11 17:05:09
|
||||
* @author gewuyou
|
||||
*/
|
||||
object ForgeBootSecurityAuthenticationResponseInformation {
|
||||
const val INCORRECT_USERNAME_OR_PASSWORD: String = "the username or password is incorrect"
|
||||
|
||||
/**
|
||||
* 当用户未提供密码时使用的响应消息。
|
||||
*/
|
||||
const val PASSWORD_NOT_PROVIDED: String = "the password cannot be empty"
|
||||
|
||||
/**
|
||||
* 当用户的凭证已过期时使用的响应消息。
|
||||
*/
|
||||
const val ACCOUNT_CREDENTIALS_HAVE_EXPIRED: String = "the account credentials have expired"
|
||||
|
||||
/**
|
||||
* 当用户账户被禁用时使用的响应消息。
|
||||
*/
|
||||
const val ACCOUNT_IS_DISABLED: String = "the account is disabled"
|
||||
|
||||
/**
|
||||
* 当用户账户被锁定时使用的响应消息。
|
||||
*/
|
||||
const val ACCOUNT_IS_LOCKED: String = "the account is locked"
|
||||
|
||||
/**
|
||||
* 当发生内部服务器错误时使用的通用错误响应消息。
|
||||
*/
|
||||
const val INTERNAL_SERVER_ERROR: String = "internal server error occurred"
|
||||
|
||||
/**
|
||||
* 当认证主体(principal)未提供时使用的常量字符串。
|
||||
* 这通常意味着认证请求缺少必要的身份标识信息。
|
||||
*/
|
||||
const val PRINCIPAL_NOT_PROVIDED = "the authentication principal cannot be empty"
|
||||
|
||||
const val LOGIN_SUCCESS: String = "login success"
|
||||
|
||||
const val LOGOUT_SUCCESS: String = "logout success"
|
||||
}
|
||||
@ -1,42 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.impl.controller
|
||||
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.service.DualTokenAuthenticationService
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.spec.DualTokenAuthenticationControllerSpec
|
||||
import com.gewuyou.forgeboot.security.core.common.constants.SecurityConstants
|
||||
import com.gewuyou.forgeboot.security.core.common.entities.TokenPair
|
||||
import com.gewuyou.forgeboot.webmvc.dto.R
|
||||
import org.springframework.web.bind.annotation.PostMapping
|
||||
import org.springframework.web.bind.annotation.RequestHeader
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
|
||||
/**
|
||||
*双令牌身份验证控制器
|
||||
*
|
||||
* @since 2025-06-26 20:40:12
|
||||
* @author gewuyou
|
||||
*/
|
||||
@RestController
|
||||
class DualTokenAuthenticationController(
|
||||
private val dualTokenAuthenticationService: DualTokenAuthenticationService,
|
||||
): DualTokenAuthenticationControllerSpec {
|
||||
/**
|
||||
* 刷新访问令牌
|
||||
*
|
||||
* 当访问令牌过期时,通过有效刷新令牌获取一组新的令牌对。
|
||||
* 此方法应校验刷新令牌的有效性,并生成新访问令牌。
|
||||
* 根据实现策略,刷新令牌也可能被更新并返回。
|
||||
*
|
||||
* @param accessToken 过期的访问令牌(通常通过 Authorization 头或请求体传入)
|
||||
* @param refreshToken 有效刷新令牌(用于验证并生成新令牌)
|
||||
* @return 包含新令牌对的响应对象,通常包括新访问令牌和可能更新刷新令牌
|
||||
*/
|
||||
@PostMapping("/auth/refresh")
|
||||
override fun refresh(
|
||||
@RequestHeader(SecurityConstants.AUTHORIZATION_HEADER)
|
||||
accessToken: String,
|
||||
@RequestHeader(SecurityConstants.REFRESH_TOKEN_HEADER)
|
||||
refreshToken: String,
|
||||
): R<TokenPair> {
|
||||
return R.success(dualTokenAuthenticationService.refreshTokenPair(accessToken, refreshToken))
|
||||
}
|
||||
}
|
||||
@ -1,69 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.impl.filter
|
||||
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.resolver.CompositeLoginRequestResolver
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.strategy.context.LoginRequestConverterContext
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import jakarta.servlet.http.HttpServletResponse
|
||||
import org.springframework.security.authentication.AuthenticationManager
|
||||
import org.springframework.security.core.Authentication
|
||||
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher
|
||||
|
||||
/**
|
||||
* 统一的身份验证过滤器
|
||||
*
|
||||
* 该类实现了身份验证流程的核心逻辑,通过组合不同的解析策略和转换上下文,
|
||||
* 来支持多种登录请求的处理方式。
|
||||
*
|
||||
* @param pathRequestMatcher 请求路径匹配器,用于判断当前请求是否需要处理
|
||||
* @param authenticationManager 身份验证管理器,用于执行实际的身份验证操作
|
||||
* @param authenticationSuccessHandler 认证成功处理器,用于处理认证成功后的响应
|
||||
* @param authenticationFailureHandler 认证失败处理器,用于处理认证失败后的响应
|
||||
* @param compositeLoginRequestResolver 组合登录请求解析器,用于解析不同类型的登录请求
|
||||
* @param loginRequestConverterContext 登录请求转换上下文,用于选择合适地转换策略
|
||||
*
|
||||
* @since 2025-06-10 20:28:08
|
||||
* @author gewuyou
|
||||
*/
|
||||
class UnifiedAuthenticationFilter(
|
||||
pathRequestMatcher: AntPathRequestMatcher,
|
||||
authenticationManager: AuthenticationManager,
|
||||
authenticationSuccessHandler: AuthenticationSuccessHandler,
|
||||
authenticationFailureHandler: AuthenticationFailureHandler,
|
||||
private val compositeLoginRequestResolver: CompositeLoginRequestResolver,
|
||||
private val loginRequestConverterContext: LoginRequestConverterContext,
|
||||
) : AbstractAuthenticationProcessingFilter(pathRequestMatcher) {
|
||||
|
||||
init {
|
||||
// 初始化身份验证管理器、成功处理器和失败处理器
|
||||
setAuthenticationManager(authenticationManager)
|
||||
setAuthenticationSuccessHandler(authenticationSuccessHandler)
|
||||
setAuthenticationFailureHandler(authenticationFailureHandler)
|
||||
}
|
||||
|
||||
/**
|
||||
* 尝试进行身份验证
|
||||
*
|
||||
* 此方法负责从请求中提取登录信息,并使用组合解析器和转换上下文来构建认证请求。
|
||||
* 最终调用身份验证管理器执行认证操作。
|
||||
*
|
||||
* @param request HTTP请求对象
|
||||
* @param response HTTP响应对象
|
||||
* @return 返回经过认证的Authentication对象
|
||||
*/
|
||||
override fun attemptAuthentication(
|
||||
request: HttpServletRequest,
|
||||
response: HttpServletResponse,
|
||||
): Authentication {
|
||||
// 尝试认证:通过组合解析器解析请求内容,再根据转换上下文选择合适的策略进行认证
|
||||
return authenticationManager.authenticate(
|
||||
// 通过上下文执行转换策略
|
||||
loginRequestConverterContext.executeStrategy(
|
||||
// 使用组合解析器解析HTTP请求
|
||||
compositeLoginRequestResolver.resolve(request)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.impl.handler
|
||||
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.handler.DelegatingHandler
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.resolver.CompositeLoginRequestResolver
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
|
||||
/**
|
||||
* 抽象委派处理程序
|
||||
*
|
||||
* 该类为泛型抽象类,用于实现委派处理逻辑,通过解析请求获取登录类型,并使用上下文解析器获取对应的处理上下文。
|
||||
*
|
||||
* @param resolver 用于解析请求并获取登录类型的组件,不可为空
|
||||
* @param contextResolver 根据登录类型生成对应上下文对象的函数式接口,不可为空
|
||||
*
|
||||
* @since 2025-06-11 14:53:46
|
||||
* @author gewuyou
|
||||
*/
|
||||
abstract class AbstractDelegatingHandler<T : Any>(
|
||||
private val resolver: CompositeLoginRequestResolver,
|
||||
private val contextResolver: (String) -> T,
|
||||
): DelegatingHandler<T> {
|
||||
/**
|
||||
* 解析请求并获取对应的处理上下文
|
||||
*
|
||||
* 该方法会调用注入的 [resolver] 来解析传入的 HTTP 请求,获取当前请求的登录类型,
|
||||
* 然后通过 [contextResolver] 函数将登录类型转换为具体地处理上下文对象。
|
||||
*
|
||||
* @param request HTTP 请求对象,用于解析登录类型
|
||||
* @return 返回与登录类型对应的处理上下文对象
|
||||
*/
|
||||
override fun resolveDelegate(request: HttpServletRequest): T {
|
||||
// 解析请求获取登录类型
|
||||
val loginType = resolver.resolve(request).getType()
|
||||
// 使用上下文解析器生成对应类型的处理上下文
|
||||
return contextResolver(loginType)
|
||||
}
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.impl.handler
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.gewuyou.forgeboot.core.extension.log
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.config.SecurityAuthenticateProperties
|
||||
import com.gewuyou.forgeboot.webmvc.dto.R
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import jakarta.servlet.http.HttpServletResponse
|
||||
import org.springframework.http.HttpStatus
|
||||
import org.springframework.http.MediaType
|
||||
import org.springframework.security.core.AuthenticationException
|
||||
import org.springframework.security.web.AuthenticationEntryPoint
|
||||
|
||||
/**
|
||||
*身份验证异常处理程序
|
||||
*
|
||||
* @since 2025-01-03 14:50:46
|
||||
* @author gewuyou
|
||||
*/
|
||||
class AuthenticationExceptionHandler(
|
||||
private val objectMapper: ObjectMapper,
|
||||
private val securityAuthenticateProperties: SecurityAuthenticateProperties
|
||||
) : AuthenticationEntryPoint {
|
||||
override fun commence(
|
||||
request: HttpServletRequest,
|
||||
response: HttpServletResponse,
|
||||
authException: AuthenticationException
|
||||
) {
|
||||
log.error("身份验证异常: ", authException)
|
||||
response.status = HttpStatus.OK.value()
|
||||
response.contentType = MediaType.APPLICATION_JSON_VALUE
|
||||
val writer = response.writer
|
||||
writer.print(objectMapper.writeValueAsString(R.failure<String>(HttpStatus.UNAUTHORIZED.value(), authException.message?:securityAuthenticateProperties.defaultExceptionResponse)))
|
||||
writer.flush()
|
||||
writer.close()
|
||||
}
|
||||
}
|
||||
@ -1,43 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.impl.handler
|
||||
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.resolver.CompositeLoginRequestResolver
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.strategy.context.AuthenticationFailureHandlerContext
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import jakarta.servlet.http.HttpServletResponse
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler
|
||||
|
||||
/**
|
||||
* 组合身份验证故障处理程序
|
||||
*
|
||||
* 该类通过组合不同的身份验证失败处理器来处理认证失败场景,利用解析器和上下文策略来动态选择实际的处理器。
|
||||
*
|
||||
* @property resolver 用于解析请求并确定适用的身份验证失败处理器的组件
|
||||
* @property context 提供身份验证失败处理策略的上下文对象
|
||||
*
|
||||
* @since 2025-06-11 00:11:52
|
||||
* @author gewuyou
|
||||
*/
|
||||
class CompositeAuthenticationFailureHandler(
|
||||
private val resolver: CompositeLoginRequestResolver,
|
||||
private val context: AuthenticationFailureHandlerContext,
|
||||
) : AbstractDelegatingHandler<AuthenticationFailureHandler>(
|
||||
resolver, context::resolve
|
||||
), AuthenticationFailureHandler {
|
||||
|
||||
/**
|
||||
* 在身份验证失败时调用的方法
|
||||
*
|
||||
* 此方法会解析出适用于当前请求的具体身份验证失败处理器,并委托其进行失败处理。
|
||||
*
|
||||
* @param request 来自客户端的 HTTP 请求
|
||||
* @param response 发送回客户端的 HTTP 响应
|
||||
* @param exception 身份验证过程中抛出的异常信息
|
||||
*/
|
||||
override fun onAuthenticationFailure(
|
||||
request: HttpServletRequest,
|
||||
response: HttpServletResponse,
|
||||
exception: org.springframework.security.core.AuthenticationException,
|
||||
) {
|
||||
resolveDelegate(request).onAuthenticationFailure(request, response, exception)
|
||||
}
|
||||
}
|
||||
@ -1,45 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.impl.handler
|
||||
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.resolver.CompositeLoginRequestResolver
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.strategy.context.AuthenticationSuccessHandlerContext
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import jakarta.servlet.http.HttpServletResponse
|
||||
import org.springframework.security.core.Authentication
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler
|
||||
|
||||
/**
|
||||
* 统一身份验证成功处理程序
|
||||
*
|
||||
* 该类实现了 [AuthenticationSuccessHandler] 接口,用于在身份验证成功后执行相应的处理逻辑。
|
||||
* 它通过组合多个具体的处理器来实现灵活的身份验证成功响应策略。
|
||||
*
|
||||
* @property resolver 用于解析登录请求并确定使用哪个具体的成功处理器
|
||||
* @property context 提供处理上下文信息,用于解析和执行成功处理逻辑
|
||||
*
|
||||
* @since 2025-06-10 23:48:32
|
||||
* @author gewuyou
|
||||
*/
|
||||
class CompositeAuthenticationSuccessHandler(
|
||||
private val resolver: CompositeLoginRequestResolver,
|
||||
private val context: AuthenticationSuccessHandlerContext,
|
||||
) : AbstractDelegatingHandler<AuthenticationSuccessHandler>(
|
||||
resolver, context::resolve
|
||||
), AuthenticationSuccessHandler {
|
||||
/**
|
||||
* 身份验证成功时的回调方法
|
||||
*
|
||||
* 此方法会在用户成功通过身份验证后被调用。它使用 [resolveDelegate] 方法根据当前请求解析出
|
||||
* 合适的具体处理器,并委托给该处理器执行后续操作。
|
||||
*
|
||||
* @param request HTTP 请求对象,提供客户端的请求信息
|
||||
* @param response HTTP 响应对象,用于向客户端发送响应
|
||||
* @param authentication 包含身份验证成功的用户信息和权限等数据的对象
|
||||
*/
|
||||
override fun onAuthenticationSuccess(
|
||||
request: HttpServletRequest,
|
||||
response: HttpServletResponse,
|
||||
authentication: Authentication,
|
||||
) {
|
||||
resolveDelegate(request).onAuthenticationSuccess(request, response, authentication)
|
||||
}
|
||||
}
|
||||
@ -1,44 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.impl.handler
|
||||
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.resolver.CompositeLoginRequestResolver
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.strategy.context.LogoutSuccessHandlerContext
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import jakarta.servlet.http.HttpServletResponse
|
||||
import org.springframework.security.core.Authentication
|
||||
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler
|
||||
|
||||
/**
|
||||
* 组合注销成功处理程序
|
||||
*
|
||||
* 该类通过组合多种注销成功处理器实现统一的注销成功处理逻辑。
|
||||
*
|
||||
* @property resolver 用于解析请求并确定适用的注销成功处理器的解析器实例
|
||||
* @property context 提供具体地注销成功处理上下文,用于动态获取处理器
|
||||
*
|
||||
* @since 2025-06-11 00:13:04
|
||||
* @author gewuyou
|
||||
*/
|
||||
class CompositeLogoutSuccessHandler(
|
||||
private val resolver: CompositeLoginRequestResolver,
|
||||
private val context: LogoutSuccessHandlerContext,
|
||||
) : AbstractDelegatingHandler<LogoutSuccessHandler>(
|
||||
resolver, context::resolve
|
||||
), LogoutSuccessHandler {
|
||||
|
||||
/**
|
||||
* 在用户成功注销时执行的具体操作
|
||||
*
|
||||
* 该方法通过解析当前请求获取对应的注销成功处理器,并委托其执行实际的注销后操作。
|
||||
*
|
||||
* @param request HTTP请求对象,提供客户端发送的请求信息
|
||||
* @param response HTTP响应对象,用于向客户端发送响应
|
||||
* @param authentication 包含认证信息的对象,在注销时通常表示已认证的用户信息
|
||||
*/
|
||||
override fun onLogoutSuccess(
|
||||
request: HttpServletRequest,
|
||||
response: HttpServletResponse,
|
||||
authentication: Authentication,
|
||||
) {
|
||||
resolveDelegate(request).onLogoutSuccess(request, response, authentication)
|
||||
}
|
||||
}
|
||||
@ -1,148 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.impl.provider
|
||||
|
||||
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.exception.ForgeBootAuthenticationException
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.service.UserCacheService
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.constants.ForgeBootSecurityAuthenticationResponseInformation
|
||||
import org.springframework.security.authentication.AuthenticationProvider
|
||||
import org.springframework.security.core.Authentication
|
||||
import org.springframework.security.core.AuthenticationException
|
||||
import org.springframework.security.core.userdetails.UserDetails
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
/**
|
||||
* 通用主体凭据认证提供器(抽象类)
|
||||
* 负责封装认证流程中通用的逻辑,凭据校验和构建成功认证对象由子类完成。
|
||||
*
|
||||
* @author gewuyou
|
||||
* @since 2025-06-11
|
||||
*/
|
||||
abstract class AbstractPrincipalCredentialsAuthenticationProvider(
|
||||
private val userCacheService: UserCacheService,
|
||||
) : AuthenticationProvider {
|
||||
|
||||
/**
|
||||
* 执行认证的核心方法
|
||||
*
|
||||
* @param authentication 待认证的 Authentication 对象
|
||||
* @return 成功认证后的 Authentication 对象
|
||||
* @throws ForgeBootAuthenticationException 认证失败时抛出异常
|
||||
*/
|
||||
override fun authenticate(authentication: Authentication): Authentication {
|
||||
val principal = getPrincipal(authentication)
|
||||
val fromCache = AtomicBoolean(true)
|
||||
|
||||
// Step 1: 获取用户(缓存优先)
|
||||
var user = userCacheService.getUserFromCache(principal) ?: run {
|
||||
fromCache.set(false)
|
||||
retrieveUser(principal)
|
||||
}
|
||||
|
||||
try {
|
||||
preAuthenticationCheck(user)
|
||||
verifyCredentials(user, authentication)
|
||||
postAuthenticationCheck(user)
|
||||
} catch (e: AuthenticationException) {
|
||||
if (fromCache.get()) {
|
||||
// 如果缓存失败则尝试数据库
|
||||
user = retrieveUser(principal)
|
||||
preAuthenticationCheck(user)
|
||||
verifyCredentials(user, authentication)
|
||||
postAuthenticationCheck(user)
|
||||
} else {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
if (!fromCache.get()) {
|
||||
userCacheService.putUserToCache(user)
|
||||
}
|
||||
|
||||
return createSuccessAuthentication(authentication, user)
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断该 Provider 是否支持指定类型的认证对象
|
||||
*
|
||||
* @param authentication 需要判断的认证类型
|
||||
* @return Boolean 表示是否支持该类型认证
|
||||
*/
|
||||
abstract override fun supports(authentication: Class<*>): Boolean
|
||||
|
||||
/**
|
||||
* 从数据源获取用户信息
|
||||
*
|
||||
* @param principal 用户标识
|
||||
* @return UserDetails 用户详细信息
|
||||
* @throws ForgeBootAuthenticationException 当 principal 为空或加载失败时抛出异常
|
||||
*/
|
||||
abstract fun retrieveUser(principal: String): UserDetails
|
||||
|
||||
/**
|
||||
* 在验证凭据前进行账户状态检查
|
||||
*
|
||||
* @param user 用户详情对象
|
||||
* @throws ForgeBootAuthenticationException 当账户锁定或禁用时抛出异常
|
||||
*/
|
||||
protected open fun preAuthenticationCheck(user: UserDetails) {
|
||||
if (!user.isAccountNonLocked) {
|
||||
throw ForgeBootAuthenticationException(ForgeBootSecurityAuthenticationResponseInformation.ACCOUNT_IS_LOCKED)
|
||||
}
|
||||
if (!user.isEnabled) {
|
||||
throw ForgeBootAuthenticationException(ForgeBootSecurityAuthenticationResponseInformation.ACCOUNT_IS_DISABLED)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 在验证凭据后进行凭证有效期检查
|
||||
*
|
||||
* @param user 用户详情对象
|
||||
* @throws ForgeBootAuthenticationException 当凭证已过期时抛出异常
|
||||
*/
|
||||
protected open fun postAuthenticationCheck(user: UserDetails) {
|
||||
if (!user.isCredentialsNonExpired) {
|
||||
throw ForgeBootAuthenticationException(ForgeBootSecurityAuthenticationResponseInformation.ACCOUNT_CREDENTIALS_HAVE_EXPIRED)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查凭证是否为 null
|
||||
*
|
||||
* @param credentials 待检查的凭证对象
|
||||
* @throws ForgeBootAuthenticationException 当凭证为 null 时抛出异常
|
||||
*/
|
||||
protected fun checkCredentialsNotNull(credentials: Any?) {
|
||||
credentials
|
||||
?: ForgeBootAuthenticationException(ForgeBootSecurityAuthenticationResponseInformation.PASSWORD_NOT_PROVIDED)
|
||||
}
|
||||
|
||||
/**
|
||||
* 提取认证对象中的用户标识
|
||||
*
|
||||
* @param authentication Authentication 对象
|
||||
* @return String 用户标识字符串
|
||||
*/
|
||||
protected fun getPrincipal(authentication: Authentication): String =
|
||||
authentication.principal.toString()
|
||||
|
||||
/**
|
||||
* 验证用户凭据的具体实现,由子类完成
|
||||
*
|
||||
* @param user 用户详情对象
|
||||
* @param authentication 待验证的 Authentication 对象
|
||||
* @throws ForgeBootAuthenticationException 凭据错误时抛出异常
|
||||
*/
|
||||
protected abstract fun verifyCredentials(user: UserDetails, authentication: Authentication)
|
||||
|
||||
/**
|
||||
* 构建成功认证后的 Authentication 对象,由子类实现
|
||||
*
|
||||
* @param authentication 原始的 Authentication 对象
|
||||
* @param user 用户详情对象
|
||||
* @return 成功认证后的 Authentication 对象
|
||||
*/
|
||||
protected abstract fun createSuccessAuthentication(
|
||||
authentication: Authentication,
|
||||
user: UserDetails,
|
||||
): Authentication
|
||||
}
|
||||
@ -1,98 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.impl.provider.impl
|
||||
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.exception.ForgeBootAuthenticationException
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.service.UserCacheService
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.constants.ForgeBootSecurityAuthenticationResponseInformation
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.provider.AbstractPrincipalCredentialsAuthenticationProvider
|
||||
import com.gewuyou.forgeboot.security.core.common.token.UsernamePasswordAuthenticationToken
|
||||
import org.springframework.security.core.Authentication
|
||||
import org.springframework.security.core.userdetails.UserDetails
|
||||
import org.springframework.security.core.userdetails.UserDetailsService
|
||||
import org.springframework.security.crypto.password.PasswordEncoder
|
||||
|
||||
/**
|
||||
* 用户名密码身份验证提供商
|
||||
*
|
||||
* 该类用于处理基于用户名和密码的身份验证流程,继承自 AbstractPrincipalCredentialsAuthenticationProvider。
|
||||
* 提供了验证凭证、创建成功认证对象以及判断支持的认证类型的功能。
|
||||
*
|
||||
* @property userCacheService 用户缓存服务,用于获取用户缓存信息
|
||||
* @property userDetailsService 用户详情服务,用于加载用户详细信息
|
||||
* @property passwordEncoder 密码编码器,用于密码匹配校验
|
||||
*
|
||||
* @since 2025-06-11 17:12:30
|
||||
* @author gewuyou
|
||||
*/
|
||||
class UsernamePasswordAuthenticationProvider(
|
||||
userCacheService: UserCacheService,
|
||||
private val userDetailsService: UserDetailsService,
|
||||
private val passwordEncoder: PasswordEncoder
|
||||
) : AbstractPrincipalCredentialsAuthenticationProvider(userCacheService) {
|
||||
|
||||
/**
|
||||
* 验证用户提供的凭证是否有效。
|
||||
*
|
||||
* 此方法会检查认证对象中的凭证是否为空,并使用密码编码器对原始密码和编码后的密码进行比对。
|
||||
*
|
||||
* @param user 已加载的用户详情对象
|
||||
* @param authentication 当前的认证对象,包含用户提交的凭证信息
|
||||
* @throws com.gewuyou.forgeboot.security.authenticate.api.exception.ForgeBootAuthenticationException 如果凭证不匹配或为空
|
||||
*/
|
||||
override fun verifyCredentials(user: UserDetails, authentication: Authentication) {
|
||||
checkCredentialsNotNull(authentication.credentials)
|
||||
val raw = authentication.credentials.toString()
|
||||
val encoded = user.password.toString()
|
||||
if (!passwordEncoder.matches(raw, encoded)) {
|
||||
throw ForgeBootAuthenticationException(ForgeBootSecurityAuthenticationResponseInformation.INCORRECT_USERNAME_OR_PASSWORD)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个成功的认证对象。
|
||||
*
|
||||
* 在验证通过后,此方法将生成一个新的认证对象,表示已认证的用户状态。
|
||||
*
|
||||
* @param authentication 原始的认证请求对象
|
||||
* @param user 已验证的用户详情对象
|
||||
* @return 返回一个表示成功认证的新 Authentication 实例
|
||||
*/
|
||||
override fun createSuccessAuthentication(
|
||||
authentication: Authentication,
|
||||
user: UserDetails
|
||||
): Authentication {
|
||||
return UsernamePasswordAuthenticationToken(user, null, user.authorities)
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前提供者是否支持给定的认证类型。
|
||||
*
|
||||
* 此方法确保只处理 UsernamePasswordAuthenticationToken 类型的认证请求。
|
||||
*
|
||||
* @param authentication 认证类类型
|
||||
* @return Boolean 表示是否支持该认证类型
|
||||
*/
|
||||
override fun supports(authentication: Class<*>): Boolean {
|
||||
return UsernamePasswordAuthenticationToken::class.java.isAssignableFrom(authentication)
|
||||
}
|
||||
|
||||
/**
|
||||
* 从数据源获取用户信息
|
||||
*
|
||||
* @param principal 用户标识
|
||||
* @return UserDetails 用户详细信息
|
||||
* @throws ForgeBootAuthenticationException 当 principal 为空或加载失败时抛出异常
|
||||
*/
|
||||
override fun retrieveUser(principal: String): UserDetails {
|
||||
if (principal.isBlank()) {
|
||||
ForgeBootAuthenticationException(ForgeBootSecurityAuthenticationResponseInformation.PRINCIPAL_NOT_PROVIDED)
|
||||
}
|
||||
return try {
|
||||
userDetailsService.loadUserByUsername(principal)
|
||||
} catch (e: Exception) {
|
||||
throw ForgeBootAuthenticationException(
|
||||
ForgeBootSecurityAuthenticationResponseInformation.INTERNAL_SERVER_ERROR,
|
||||
e
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,69 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.impl.registry
|
||||
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.registry.LoginRequestTypeRegistry
|
||||
import com.gewuyou.forgeboot.security.core.authenticate.entities.request.LoginRequest
|
||||
|
||||
/**
|
||||
* 简单登录请求类型注册表
|
||||
*
|
||||
* 用于管理不同登录类型的请求类映射关系,支持动态注册和获取登录请求类型。
|
||||
*
|
||||
* 示例代码(Kotlin):
|
||||
* ```kt
|
||||
* @Bean
|
||||
* fun loginRequestTypeRegistry(): LoginRequestTypeRegistry {
|
||||
* return LoginRequestTypeRegistry().apply {
|
||||
* register("default", DefaultLoginRequest::class.java)
|
||||
* register("sms", SmsLoginRequest::class.java)
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* 示例代码(Java):
|
||||
* ```java
|
||||
* @Bean
|
||||
* public LoginRequestTypeRegistry loginRequestTypeRegistry() {
|
||||
* return new DefaultLoginRequestTypeRegistry()
|
||||
* .register("default", DefaultLoginRequest.class)
|
||||
* .register("sms", SmsLoginRequest.class);
|
||||
* }
|
||||
* ```
|
||||
* ⚠️ 注意:此注册表不是线程安全的,建议仅用于应用启动期间进行注册,不适合运行时动态变更
|
||||
* @since 2025-06-10 16:33:43
|
||||
* @author gewuyou
|
||||
*/
|
||||
class SimpleLoginRequestTypeRegistry : LoginRequestTypeRegistry {
|
||||
|
||||
/**
|
||||
* 内部使用可变Map保存登录类型与对应LoginRequest子类的映射关系
|
||||
*/
|
||||
private val mapping = mutableMapOf<String, Class<out LoginRequest>>()
|
||||
|
||||
/**
|
||||
* 注册指定登录类型对应的请求类
|
||||
*
|
||||
* 此方法允许将特定的登录类型字符串与相应的LoginRequest实现类进行绑定,
|
||||
* 以便后续可以通过登录类型标识符动态解析出对应的请求类。
|
||||
*
|
||||
* @param loginType 登录类型的标识字符串
|
||||
* @param clazz 继承自LoginRequest的具体请求类
|
||||
* @return 返回当前注册表实例,以支持链式调用
|
||||
*/
|
||||
override fun register(loginType: String, clazz: Class<out LoginRequest>): LoginRequestTypeRegistry {
|
||||
mapping[loginType] = clazz
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据登录类型获取对应的请求类
|
||||
*
|
||||
* 此方法用于查找之前通过register方法注册的登录类型所对应的LoginRequest子类。
|
||||
* 如果未找到匹配的登录类型,则返回null。
|
||||
*
|
||||
* @param loginType 登录类型的标识字符串
|
||||
* @return 返回对应的LoginRequest子类,若未找到则返回null
|
||||
*/
|
||||
override fun getTypeForLoginType(loginType: String): Class<out LoginRequest>? {
|
||||
return mapping[loginType]
|
||||
}
|
||||
}
|
||||
@ -1,38 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.impl.resolver
|
||||
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.resolver.LoginRequestResolver
|
||||
import com.gewuyou.forgeboot.security.core.authenticate.entities.request.LoginRequest
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import kotlin.collections.find
|
||||
|
||||
/**
|
||||
* 复合登录请求解析器
|
||||
*
|
||||
* 该类用于根据请求的内容类型(contentType)动态选择合适的登录请求解析器。
|
||||
* 它通过组合多种 LoginRequestResolver实现,支持不同格式的登录请求解析。
|
||||
*
|
||||
* @property resolvers 提供支持的各种登录请求解析器列表
|
||||
*
|
||||
* @since 2025-06-10 16:46:57
|
||||
* @author gewuyou
|
||||
*/
|
||||
class CompositeLoginRequestResolver(
|
||||
private val resolvers: List<LoginRequestResolver>
|
||||
) {
|
||||
/**
|
||||
* 解析登录请求
|
||||
*
|
||||
* 根据给定的 HTTP 请求中的内容类型(contentType),查找支持该类型的解析器,
|
||||
* 并使用该解析器解析登录请求。
|
||||
*
|
||||
* @param request 需要解析的 HTTP 请求
|
||||
* @return 解析后的登录请求对象(LoginRequest)
|
||||
* @throws IllegalArgumentException 如果没有找到支持当前内容类型的解析器
|
||||
*/
|
||||
fun resolve(request: HttpServletRequest): LoginRequest {
|
||||
val contentType = request.contentType ?: ""
|
||||
val resolver = resolvers.find { it.supports(contentType) }
|
||||
?: throw IllegalArgumentException("Unsupported content type: $contentType")
|
||||
return resolver.resolve(request)
|
||||
}
|
||||
}
|
||||
@ -1,64 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.impl.resolver
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.registry.LoginRequestTypeRegistry
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.resolver.LoginRequestResolver
|
||||
import com.gewuyou.forgeboot.security.core.authenticate.entities.request.AuthenticationRequest
|
||||
import com.gewuyou.forgeboot.security.core.authenticate.entities.request.LoginRequest
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import org.springframework.http.MediaType
|
||||
|
||||
/**
|
||||
* JSON登录请求解析器
|
||||
*
|
||||
* 该解析器用于处理JSON格式的登录请求数据,通过两次反序列化过程来支持动态类型的登录请求。
|
||||
* 首先读取请求中的type字段以确定具体的登录类型,然后根据该类型再次反序列化为对应的对象。
|
||||
*
|
||||
* @property objectMapper 用于JSON序列化和反序列化的Jackson ObjectMapper实例
|
||||
* @property loginRequestTypeRegistry 登录请求类型的注册表,用于根据登录类型获取实际类
|
||||
*
|
||||
* @since 2025-06-10 16:37:22
|
||||
* @author gewuyou
|
||||
*/
|
||||
class JsonLoginRequestResolver(
|
||||
private val objectMapper: ObjectMapper,
|
||||
private val loginRequestTypeRegistry: LoginRequestTypeRegistry, // 动态注册哪些类型
|
||||
) : LoginRequestResolver {
|
||||
|
||||
/**
|
||||
* 判断是否支持给定的内容类型
|
||||
*
|
||||
* 该方法检查内容类型字符串中是否包含JSON媒体类型(application/json),
|
||||
* 表示当前解析器可以处理该类型的内容。
|
||||
*
|
||||
* @param contentType 请求的内容类型字符串
|
||||
* @return 如果支持返回true,否则返回false
|
||||
*/
|
||||
override fun supports(contentType: String): Boolean {
|
||||
return contentType.contains(MediaType.APPLICATION_JSON_VALUE)
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析登录请求
|
||||
*
|
||||
* 从HttpServletRequest中读取JSON输入流,并进行两次反序列化操作:
|
||||
* 1. 首次反序列化为AuthenticationRequest以提取type字段;
|
||||
* 2. 根据type字段从注册表中查找对应的实际类;
|
||||
* 3. 再次反序列化为实际类的对象。
|
||||
*
|
||||
* @param request HTTP请求对象
|
||||
* @return 解析后的登录请求对象
|
||||
* @throws IllegalArgumentException 如果不支持的登录类型
|
||||
*/
|
||||
override fun resolve(request: HttpServletRequest): LoginRequest {
|
||||
val json = request.inputStream.reader().readText()
|
||||
// 1. 先反序列化为 AuthenticationRequest,读取 type 字段
|
||||
val tempRequest = objectMapper.readValue(json, AuthenticationRequest::class.java)
|
||||
val loginType = tempRequest.type
|
||||
// 2. 从注册表中获取真正对应的类型
|
||||
val clazz = loginRequestTypeRegistry.getTypeForLoginType(loginType)
|
||||
?: throw IllegalArgumentException("Unsupported login type: $loginType")
|
||||
// 3. 再次反序列化为真正请求体类型
|
||||
return objectMapper.readValue(json, clazz)
|
||||
}
|
||||
}
|
||||
@ -1,67 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.impl.strategy
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.config.SecurityAuthenticateProperties
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.strategy.AuthenticationFailureStrategy
|
||||
import com.gewuyou.forgeboot.webmvc.dto.R
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import jakarta.servlet.http.HttpServletResponse
|
||||
import org.springframework.http.HttpStatus
|
||||
import org.springframework.http.MediaType
|
||||
import org.springframework.security.core.AuthenticationException
|
||||
|
||||
/**
|
||||
* 抽象验证失败策略基类
|
||||
* 提供统一的认证失败处理机制实现模板
|
||||
*
|
||||
* @property objectMapper 用于JSON序列化响应结果
|
||||
* @property properties 安全认证配置属性
|
||||
* @author gewuyou
|
||||
* @since 2025-06-14 20:14:14
|
||||
*/
|
||||
abstract class AbstractAuthenticationFailureStrategy(
|
||||
private val objectMapper: ObjectMapper,
|
||||
private val properties: SecurityAuthenticateProperties
|
||||
) : AuthenticationFailureStrategy {
|
||||
|
||||
/**
|
||||
* 处理认证失败的通用实现
|
||||
* 将认证失败结果转换为JSON格式的HTTP响应
|
||||
*
|
||||
* @param request HTTP请求对象
|
||||
* @param response HTTP响应对象
|
||||
* @param exception 认证异常信息
|
||||
*/
|
||||
override fun onAuthenticationFailure(
|
||||
request: HttpServletRequest,
|
||||
response: HttpServletResponse,
|
||||
exception: AuthenticationException,
|
||||
) {
|
||||
// 设置响应内容类型为JSON
|
||||
response.contentType = MediaType.APPLICATION_JSON_VALUE
|
||||
|
||||
// 获取响应输出流并写入序列化后的失败结果
|
||||
val writer = response.writer
|
||||
writer.print(
|
||||
objectMapper.writeValueAsString(buildFailureResult(exception))
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建认证失败的响应数据
|
||||
* 可被子类重写以提供自定义失败响应
|
||||
*
|
||||
* @param authenticationException 认证异常信息
|
||||
* @return 序列化为JSON的响应数据
|
||||
*/
|
||||
protected open fun buildFailureResult(authenticationException: AuthenticationException): Any {
|
||||
// 获取异常消息,若为空则使用默认配置的失败响应
|
||||
val message = authenticationException.message
|
||||
return R.failure<String>(
|
||||
HttpStatus.UNAUTHORIZED.value(),
|
||||
message?.let {
|
||||
message
|
||||
} ?: properties.defaultAuthenticationFailureResponse
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1,63 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.impl.strategy
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.strategy.AuthenticationSuccessStrategy
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.constants.ForgeBootSecurityAuthenticationResponseInformation
|
||||
import com.gewuyou.forgeboot.webmvc.dto.R
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import jakarta.servlet.http.HttpServletResponse
|
||||
import org.springframework.http.HttpStatus
|
||||
import org.springframework.http.MediaType
|
||||
import org.springframework.security.core.Authentication
|
||||
|
||||
/**
|
||||
* 抽象认证成功策略
|
||||
*
|
||||
* 该基础类为认证成功后的处理提供统一模板
|
||||
*
|
||||
* @property objectMapper 用于将响应对象序列化为 JSON 字符串
|
||||
* @since 2025-06-12 21:26:11
|
||||
* @author gewuyou
|
||||
*/
|
||||
abstract class AbstractAuthenticationSuccessStrategy(
|
||||
private val objectMapper: ObjectMapper,
|
||||
) : AuthenticationSuccessStrategy {
|
||||
|
||||
/**
|
||||
* 认证成功时触发的方法
|
||||
*
|
||||
* 处理 HTTP 响应的设置,包括状态码、内容类型和写入响应数据
|
||||
*
|
||||
* @param request 本次请求的 HttpServletRequest 对象
|
||||
* @param response 本次响应的 HttpServletResponse 对象
|
||||
* @param authentication 包含认证信息的对象
|
||||
*/
|
||||
override fun onAuthenticationSuccess(
|
||||
request: HttpServletRequest,
|
||||
response: HttpServletResponse,
|
||||
authentication: Authentication,
|
||||
) {
|
||||
// 构建认证成功响应数据
|
||||
val result = buildSuccessResponse(authentication)
|
||||
// 设置响应状态码为 200 OK
|
||||
response.status = HttpStatus.OK.value()
|
||||
// 设置响应内容类型为 application/json
|
||||
response.contentType = MediaType.APPLICATION_JSON_VALUE
|
||||
// 将响应结果序列化为 JSON 并写入响应输出流
|
||||
response.writer.write(objectMapper.writeValueAsString(result))
|
||||
response.writer.flush()
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建认证成功响应体对象
|
||||
*
|
||||
* @param authentication 包含认证信息的对象
|
||||
* @return 返回准备序列化并发送给客户端的响应对象
|
||||
*/
|
||||
protected open fun buildSuccessResponse(authentication: Authentication): Any {
|
||||
return R.success(
|
||||
HttpStatus.OK.value(),
|
||||
ForgeBootSecurityAuthenticationResponseInformation.LOGIN_SUCCESS, authentication.principal
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1,59 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.impl.strategy
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.strategy.LogoutSuccessStrategy
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.constants.ForgeBootSecurityAuthenticationResponseInformation
|
||||
import com.gewuyou.forgeboot.webmvc.dto.R
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import jakarta.servlet.http.HttpServletResponse
|
||||
import org.springframework.http.HttpStatus
|
||||
import org.springframework.http.MediaType
|
||||
import org.springframework.security.core.Authentication
|
||||
|
||||
/**
|
||||
* 抽象注销成功策略
|
||||
*
|
||||
* 该抽象类为注销成功时的响应处理提供了统一的策略框架。
|
||||
* 子类应继承此类并根据需要定制具体注销成功逻辑。
|
||||
*
|
||||
* @property objectMapper 用于将响应结果序列化为 JSON 格式
|
||||
* @constructor 接收一个 ObjectMapper 实例作为参数
|
||||
*
|
||||
* @since 2025-06-14 20:29:25
|
||||
* @author gewuyou
|
||||
*/
|
||||
abstract class AbstractLogoutSuccessStrategy(
|
||||
private val objectMapper: ObjectMapper,
|
||||
): LogoutSuccessStrategy {
|
||||
/**
|
||||
* 注销成功回调方法
|
||||
*
|
||||
* 当用户成功注销时,该方法会被调用以处理响应。默认实现会返回一个包含成功状态码和消息的 JSON 响应。
|
||||
*
|
||||
* @param request 表示 HTTP 请求对象,提供有关客户端请求的信息
|
||||
* @param response 表示 HTTP 响应对象,用于向客户端发送响应
|
||||
* @param authentication 包含认证信息的对象,在注销时提供额外上下文数据
|
||||
*/
|
||||
override fun onLogoutSuccess(
|
||||
request: HttpServletRequest,
|
||||
response: HttpServletResponse,
|
||||
authentication: Authentication,
|
||||
) {
|
||||
// 创建表示注销成功响应数据对象
|
||||
val result = R.success<String>(
|
||||
HttpStatus.OK.value(),
|
||||
ForgeBootSecurityAuthenticationResponseInformation.LOGOUT_SUCCESS
|
||||
)
|
||||
|
||||
// 设置响应状态码为 200 OK
|
||||
response.status = HttpStatus.OK.value()
|
||||
|
||||
// 设置响应内容类型为 application/json
|
||||
response.contentType = MediaType.APPLICATION_JSON_VALUE
|
||||
|
||||
// 将响应结果序列化为 JSON 并写入响应输出流
|
||||
response.writer.write(objectMapper.writeValueAsString(result))
|
||||
response.writer.flush()
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,81 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.impl.strategy.context
|
||||
|
||||
import com.gewuyou.forgeboot.core.extension.log
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.enums.LoginTypes
|
||||
|
||||
/**
|
||||
* 抽象处理程序上下文
|
||||
* 用于构建策略处理器的通用框架,支持通过类型解析对应的处理器实例
|
||||
*
|
||||
* @since 2025-06-11 21:59:40
|
||||
* @author gewuyou
|
||||
*/
|
||||
abstract class AbstractHandlerContext<T : Any, H : Any>(
|
||||
/**
|
||||
* 策略对象列表,用于从中提取类型和对应的处理器
|
||||
*/
|
||||
strategies: List<T>,
|
||||
/**
|
||||
* 当前处理器类型的名称,用于日志输出时标识处理器种类
|
||||
*/
|
||||
private val typeName: String,
|
||||
/**
|
||||
* 提取策略对应类型的函数,用于确定每个策略的标识
|
||||
*/
|
||||
extractType: (T) -> Set<String>,
|
||||
/**
|
||||
* 提取策略对应处理器的函数,用于获取实际可执行的处理器逻辑
|
||||
*/
|
||||
extractHandler: (T) -> H
|
||||
) {
|
||||
/**
|
||||
* 默认处理器,用于处理未指定登录类型的请求
|
||||
*/
|
||||
private var defaultStrategy: T? = null
|
||||
/**
|
||||
* 存储登录类型与处理器之间的映射关系
|
||||
*/
|
||||
private val handlerMap: Map<String, H>
|
||||
|
||||
init {
|
||||
val map = mutableMapOf<String, H>()
|
||||
for (strategy in strategies) {
|
||||
// 提取当前策略的登录类型标识
|
||||
val loginTypes = extractType(strategy)
|
||||
if (loginTypes.contains(LoginTypes.DEFAULT)) {
|
||||
defaultStrategy = strategy
|
||||
continue
|
||||
}
|
||||
// 获取当前策略对应的处理器实例
|
||||
val handler = extractHandler(strategy)
|
||||
log.info("注册${typeName}策略: $loginTypes -> ${strategy::class.java.name}")
|
||||
loginTypes.forEach { loginType ->
|
||||
if (map.containsKey(loginType)) {
|
||||
log.warn("已存在 loginType 为 [$loginType] 的$typeName,将覆盖")
|
||||
}
|
||||
// 注册或覆盖处理器映射
|
||||
map[loginType] = handler
|
||||
}
|
||||
}
|
||||
// 不可变化处理器映射表
|
||||
this.handlerMap = map.toMap()
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据指定的登录类型解析对应的处理器实例
|
||||
*
|
||||
* 该方法首先尝试通过给定的登录类型从处理器映射中查找对应的策略处理器。
|
||||
* 如果找不到匹配项,则尝试使用默认类型的处理器。
|
||||
* 如果仍然无法找到,默认处理器也不存在,则抛出异常。
|
||||
*
|
||||
* @param loginType 登录类型标识,用于查找对应的处理器
|
||||
* @return H 类型的处理器实例,与给定的登录类型或默认类型匹配
|
||||
* @throws IllegalArgumentException 如果既没有找到与登录类型匹配的处理器,也没有定义默认处理器
|
||||
*/
|
||||
fun resolve(loginType: String): H {
|
||||
return handlerMap[loginType]
|
||||
?: handlerMap[LoginTypes.DEFAULT]
|
||||
?: throw IllegalArgumentException("未找到 loginType 为 [$loginType] 的$typeName,且未定义默认$typeName")
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.impl.strategy.context
|
||||
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.strategy.AuthenticationFailureStrategy
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler
|
||||
|
||||
/**
|
||||
*身份验证故障处理程序上下文
|
||||
*
|
||||
* @since 2025-06-10 23:48:02
|
||||
* @author gewuyou
|
||||
*/
|
||||
class AuthenticationFailureHandlerContext(
|
||||
strategies: List<AuthenticationFailureStrategy>
|
||||
) : AbstractHandlerContext<AuthenticationFailureStrategy, AuthenticationFailureHandler>(
|
||||
strategies,
|
||||
"认证失败处理器",
|
||||
{ it.supportedLoginTypes() },
|
||||
{ it }
|
||||
)
|
||||
@ -1,20 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.impl.strategy.context
|
||||
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.strategy.AuthenticationSuccessStrategy
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler
|
||||
|
||||
/**
|
||||
*身份验证成功处理程序上下文
|
||||
*
|
||||
* @since 2025-06-10 23:45:40
|
||||
* @author gewuyou
|
||||
*/
|
||||
class AuthenticationSuccessHandlerContext(
|
||||
strategies: List<AuthenticationSuccessStrategy>,
|
||||
) : AbstractHandlerContext<AuthenticationSuccessStrategy, AuthenticationSuccessHandler>(
|
||||
strategies,
|
||||
"认证成功处理器"
|
||||
,
|
||||
{ it.supportedLoginTypes() },
|
||||
{ it }
|
||||
)
|
||||
@ -1,65 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.impl.strategy.context
|
||||
|
||||
import com.gewuyou.forgeboot.core.extension.log
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.strategy.LoginRequestConverterStrategy
|
||||
import com.gewuyou.forgeboot.security.core.authenticate.entities.request.LoginRequest
|
||||
import jakarta.annotation.PostConstruct
|
||||
import org.springframework.context.ApplicationContext
|
||||
import org.springframework.security.core.Authentication
|
||||
import kotlin.collections.component1
|
||||
import kotlin.collections.component2
|
||||
import kotlin.collections.iterator
|
||||
import kotlin.jvm.java
|
||||
|
||||
/**
|
||||
* 登录请求转换器上下文
|
||||
* 负责管理不同登录类型的请求转换策略,实现策略模式的上下文类
|
||||
*
|
||||
* @since 2025-06-10 20:48:09
|
||||
* @author gewuyou
|
||||
*/
|
||||
class LoginRequestConverterContext(
|
||||
private val applicationContext: ApplicationContext
|
||||
) {
|
||||
/**
|
||||
* 存储登录类型与对应转换策略的映射关系
|
||||
*/
|
||||
private val converterStrategies = mutableMapOf<String, LoginRequestConverterStrategy>()
|
||||
|
||||
/**
|
||||
* 初始化转换器策略
|
||||
* 通过Spring容器获取所有LoginRequestConverterStrategy实例
|
||||
* 并根据支持的登录类型注册到converterStrategies中
|
||||
*/
|
||||
@PostConstruct
|
||||
fun initConverterStrategies() {
|
||||
val strategies = applicationContext.getBeansOfType(LoginRequestConverterStrategy::class.java).toMap()
|
||||
for ((_, strategy) in strategies) {
|
||||
val loginType = strategy.getSupportedLoginType()
|
||||
addConverter(loginType, strategy)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加登录请求转换器策略
|
||||
* @param loginType 登录类型标识符
|
||||
* @param strategy 转换器策略实现
|
||||
*/
|
||||
private fun addConverter(loginType: String, strategy: LoginRequestConverterStrategy) {
|
||||
converterStrategies[loginType] = strategy
|
||||
log.info("为登录类型: $loginType 添加登录请求转换器策略 ${strategy::class.java.name}")
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行对应的转换策略
|
||||
* 根据登录请求类型查找并执行对应的转换器策略
|
||||
*
|
||||
* @param loginRequest 登录请求对象
|
||||
* @return Authentication 认证对象
|
||||
* @throws IllegalArgumentException 当找不到匹配的转换策略时抛出异常
|
||||
*/
|
||||
fun executeStrategy(loginRequest: LoginRequest): Authentication {
|
||||
return converterStrategies[loginRequest.getType()]?.convert(loginRequest)
|
||||
?: throw IllegalArgumentException("No converter strategy found for login type ${loginRequest.getType()}")
|
||||
}
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.impl.strategy.context
|
||||
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.strategy.LogoutSuccessStrategy
|
||||
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler
|
||||
|
||||
/**
|
||||
*注销成功处理程序上下文
|
||||
*
|
||||
* @since 2025-06-11 00:12:33
|
||||
* @author gewuyou
|
||||
*/
|
||||
class LogoutSuccessHandlerContext(
|
||||
strategies: List<LogoutSuccessStrategy>,
|
||||
) : AbstractHandlerContext<LogoutSuccessStrategy, LogoutSuccessHandler>(
|
||||
strategies,
|
||||
"登出处理器",
|
||||
{ it.supportedLoginTypes() },
|
||||
{ it }
|
||||
)
|
||||
@ -1,30 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.impl.strategy.impl
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.config.SecurityAuthenticateProperties
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.enums.LoginTypes
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.strategy.AbstractAuthenticationFailureStrategy
|
||||
|
||||
/**
|
||||
*默认身份验证失败策略
|
||||
*
|
||||
* @since 2025-06-14 20:26:46
|
||||
* @author gewuyou
|
||||
*/
|
||||
class DefaultAuthenticationFailureStrategy(
|
||||
objectMapper: ObjectMapper,
|
||||
properties: SecurityAuthenticateProperties
|
||||
): AbstractAuthenticationFailureStrategy(objectMapper,properties) {
|
||||
/**
|
||||
* 获取当前策略支持的登录类型标识符。
|
||||
*
|
||||
* 此方法用于判断当前身份验证策略能够处理的登录请求类型。
|
||||
* 例如:可以基于不同的认证方式(如密码、短信验证码、OAuth等)进行区分。
|
||||
*
|
||||
* @return 返回当前策略支持的登录类型字符串集合
|
||||
* 集合中的每个字符串代表一种支持的登录类型标识符
|
||||
*/
|
||||
override fun supportedLoginTypes(): Set<String> {
|
||||
return setOf(LoginTypes.DEFAULT)
|
||||
}
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.impl.strategy.impl
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.enums.LoginTypes
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.strategy.AbstractAuthenticationSuccessStrategy
|
||||
|
||||
/**
|
||||
* 默认身份验证成功策略
|
||||
*
|
||||
* 该类实现了一个基础的身份验证成功处理策略,用于处理默认类型的登录认证。
|
||||
* 继承自 [AbstractAuthenticationSuccessStrategy],提供具体的登录类型标识。
|
||||
*
|
||||
* @property objectMapper 用于序列化/反序列化 JSON 数据的对象
|
||||
* @since 2025-06-12 22:13:42
|
||||
* @author gewuyou
|
||||
*/
|
||||
class DefaultAuthenticationSuccessStrategy(
|
||||
objectMapper: ObjectMapper,
|
||||
) : AbstractAuthenticationSuccessStrategy(objectMapper) {
|
||||
/**
|
||||
* 获取当前策略支持的登录类型标识符。
|
||||
*
|
||||
* @return 返回当前策略支持的登录类型字符串
|
||||
*/
|
||||
override fun supportedLoginTypes(): Set<String> {
|
||||
return setOf(LoginTypes.DEFAULT)
|
||||
}
|
||||
}
|
||||
@ -1,32 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.impl.strategy.impl
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.enums.LoginTypes
|
||||
import com.gewuyou.forgeboot.security.authenticate.impl.strategy.AbstractLogoutSuccessStrategy
|
||||
|
||||
/**
|
||||
* 默认注销成功策略
|
||||
*
|
||||
* 该类实现了一个默认的注销成功处理策略,用于在用户成功注销时执行相关逻辑。
|
||||
* 继承自 [AbstractLogoutSuccessStrategy],并使用 [objectMapper] 进行 JSON 处理。
|
||||
*
|
||||
* @property objectMapper 用于序列化/反序列化的 Jackson ObjectMapper 实例
|
||||
* @since 2025-06-14 20:38:16
|
||||
* @author gewuyou
|
||||
*/
|
||||
class DefaultLogoutSuccessStrategy(
|
||||
objectMapper: ObjectMapper
|
||||
) : AbstractLogoutSuccessStrategy(objectMapper) {
|
||||
/**
|
||||
* 获取当前策略支持的登录类型标识符。
|
||||
*
|
||||
* 此方法用于判断当前身份验证策略能够处理的登录请求类型。
|
||||
* 例如:可以基于不同的认证方式(如密码、短信验证码、OAuth等)进行区分。
|
||||
*
|
||||
* @return 返回当前策略支持的登录类型字符串集合
|
||||
* 集合中的每个字符串代表一种支持的登录类型标识符
|
||||
*/
|
||||
override fun supportedLoginTypes(): Set<String> {
|
||||
return setOf(LoginTypes.DEFAULT)
|
||||
}
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authenticate.impl.strategy.impl
|
||||
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.enums.LoginTypes
|
||||
import com.gewuyou.forgeboot.security.authenticate.api.strategy.LoginRequestConverterStrategy
|
||||
import com.gewuyou.forgeboot.security.core.authenticate.entities.request.LoginRequest
|
||||
import com.gewuyou.forgeboot.security.core.authenticate.entities.request.UsernamePasswordAuthenticationRequest
|
||||
import com.gewuyou.forgeboot.security.core.common.token.UsernamePasswordAuthenticationToken
|
||||
import org.springframework.security.core.Authentication
|
||||
|
||||
/**
|
||||
* 用户名 密码 认证 Token 转换器策略
|
||||
* @since 2025-02-15 03:25:14
|
||||
* @author gewuyou
|
||||
*/
|
||||
class UsernamePasswordLoginRequestConverterStrategy : LoginRequestConverterStrategy {
|
||||
/**
|
||||
* 转换登录请求为认证对象
|
||||
* @param loginRequest 登录请求
|
||||
* @return 认证对象
|
||||
*/
|
||||
override fun convert(loginRequest: LoginRequest): Authentication {
|
||||
if (loginRequest is UsernamePasswordAuthenticationRequest) {
|
||||
return UsernamePasswordAuthenticationToken.unauthenticated(loginRequest.username, loginRequest.password)
|
||||
}
|
||||
throw IllegalArgumentException("Unsupported login request type: ${loginRequest.javaClass.name}")
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取支持的登录类型
|
||||
* @return 请求的登录类型
|
||||
*/
|
||||
override fun getSupportedLoginType(): String {
|
||||
return LoginTypes.USERNAME_PASSWORD
|
||||
}
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
/gradlew text eol=lf
|
||||
*.bat text eol=crlf
|
||||
*.jar binary
|
||||
@ -1,40 +0,0 @@
|
||||
HELP.md
|
||||
.gradle
|
||||
build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Kotlin ###
|
||||
.kotlin
|
||||
@ -1,3 +0,0 @@
|
||||
/gradlew text eol=lf
|
||||
*.bat text eol=crlf
|
||||
*.jar binary
|
||||
@ -1,37 +0,0 @@
|
||||
HELP.md
|
||||
.gradle
|
||||
build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
@ -1,7 +0,0 @@
|
||||
|
||||
dependencies {
|
||||
api(project(Modules.Security.CORE))
|
||||
compileOnly(libs.springBootStarter.web)
|
||||
compileOnly(libs.springBootStarter.security)
|
||||
kapt(libs.springBoot.configuration.processor)
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.api.core.annotations
|
||||
|
||||
/**
|
||||
* 权限校验注解,用于标记需要特定权限才能访问的方法
|
||||
*
|
||||
* @property value 需要校验的权限字符串,例如:"user:read"
|
||||
* @property dynamic 是否为动态权限,默认为 false。若为 true 表示该权限需要在运行时动态解析
|
||||
*
|
||||
* 注解作用于方法级别,运行时生效,常用于接口权限控制。
|
||||
*/
|
||||
@Target(AnnotationTarget.FUNCTION)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
annotation class RequiresPermission(
|
||||
val value: String,
|
||||
val dynamic: Boolean = false
|
||||
)
|
||||
@ -1,49 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.api.core.config
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties
|
||||
|
||||
/**
|
||||
* Security 授权配置属性类,用于定义安全相关的可配置项
|
||||
*
|
||||
* 该类通过@ConfigurationProperties绑定配置前缀"forgeboot.security.authorize",
|
||||
* 提供了默认异常响应消息、单Token控制及相关路径模式的配置支持。
|
||||
*
|
||||
* @property defaultExceptionResponse 当访问被拒绝时返回的默认提示信息
|
||||
* @property singleToken 单Token配置属性对象,包含启用状态、匹配路径及是否使用授权管理器
|
||||
*
|
||||
* @since 2025-06-15 19:26:20
|
||||
* @author gewuyou
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "forgeboot.security.authorize")
|
||||
class SecurityAuthorizeProperties {
|
||||
/**
|
||||
* 默认的访问拒绝响应消息,用于在未授权访问时返回给客户端
|
||||
*/
|
||||
var defaultExceptionResponse: String = "Sorry, you don't have access to the resource!"
|
||||
|
||||
/**
|
||||
* 单Token配置属性实例,用于定义Token相关的行为和路径匹配规则
|
||||
*/
|
||||
var singleToken: SingleTokenProperties = SingleTokenProperties()
|
||||
|
||||
/**
|
||||
* 单Token配置内部类,封装与Token验证行为相关的配置项
|
||||
*
|
||||
* 用于控制特定路径下的Token验证行为,包括启用状态、路径匹配模式以及是否使用授权管理器。
|
||||
*/
|
||||
class SingleTokenProperties {
|
||||
/**
|
||||
* 控制是否启用API密钥验证功能,默认值为false
|
||||
*/
|
||||
var enabled: Boolean = false
|
||||
/**
|
||||
* 指定是否通过Spring Security的AuthorizationManager进行权限决策,默认为true
|
||||
*/
|
||||
var useAuthorizationManager: Boolean = true
|
||||
|
||||
/**
|
||||
* 定义需要应用Token验证的请求路径模式列表
|
||||
*/
|
||||
var pathPatterns: List<String> = listOf("/api/**")
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.api.core.manager
|
||||
|
||||
import org.springframework.security.core.Authentication
|
||||
|
||||
/**
|
||||
* 访问管理器接口,用于定义鉴权逻辑
|
||||
*
|
||||
* @since 2025-06-15 18:38:07
|
||||
* @author gewuyou
|
||||
*/
|
||||
fun interface AccessManager {
|
||||
/**
|
||||
* 判断用户是否具有指定权限
|
||||
*
|
||||
* @param authentication Spring Security提供的身份认证信息
|
||||
* @param permission 需要验证的权限字符串
|
||||
* @return Boolean 返回是否有权限的布尔值
|
||||
*/
|
||||
fun hasPermission(authentication: Authentication, permission: String): Boolean
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.api.core.provider
|
||||
|
||||
import org.springframework.security.core.Authentication
|
||||
|
||||
/**
|
||||
* 权限提供程序接口,用于定义权限集合的生成逻辑。
|
||||
*
|
||||
* @since 2025-06-15 13:08:18
|
||||
* @author gewuyou
|
||||
*/
|
||||
fun interface PermissionProvider {
|
||||
|
||||
/**
|
||||
* 提供基于认证信息的权限集合。
|
||||
*
|
||||
* @param authentication 包含用户认证信息的对象,用于权限判断
|
||||
* @return 返回与当前认证信息关联的权限字符串集合
|
||||
*/
|
||||
fun listPermissions(authentication: Authentication): Collection<String>
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.api.core.resolver
|
||||
|
||||
/**
|
||||
* 权限解析程序接口,用于将请求路径和HTTP方法转换为具体的权限标识符。
|
||||
*
|
||||
* @since 2025-06-24 13:23:29
|
||||
* @author gewuyou
|
||||
*/
|
||||
fun interface PermissionResolver {
|
||||
|
||||
/**
|
||||
* 解析给定的请求路径和HTTP方法,生成对应的权限标识字符串。
|
||||
*
|
||||
* 此方法通常用于安全框架中,用来判断用户是否拥有执行特定操作的权限。
|
||||
*
|
||||
* @param path 请求的URL路径,例如 "/api/users"
|
||||
* @param method HTTP请求方法,如 GET, POST 等
|
||||
* @return 返回一个表示权限的字符串,如 "user:read", "user:write" 等
|
||||
*/
|
||||
fun resolve(path: String, method: String): String
|
||||
}
|
||||
@ -1,32 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.api.core.strategy
|
||||
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.provider.PermissionProvider
|
||||
import org.springframework.security.core.Authentication
|
||||
|
||||
/**
|
||||
* 授权策略接口
|
||||
*
|
||||
* 定义了实现授权逻辑的统一接口,所有具体授权策略都需要实现该接口。
|
||||
* 该接口设计为函数式接口,便于通过Lambda表达式或函数引用实现简洁的策略定义。
|
||||
*
|
||||
* @since 2025-06-15 13:01:27
|
||||
* @author gewuyou
|
||||
*/
|
||||
fun interface AuthorizationStrategy {
|
||||
|
||||
/**
|
||||
* 执行授权判断
|
||||
*
|
||||
* 根据提供的认证信息、权限标识和权限提供者列表,判断当前认证是否具备指定权限。
|
||||
*
|
||||
* @param authentication 当前用户的认证信息,包含主体身份和凭证等
|
||||
* @param permission 需要验证的权限标识,通常为特定资源的操作权限字符串
|
||||
* @param providers 权限提供者列表,用于获取与权限相关的数据源或校验逻辑
|
||||
* @return Boolean 返回授权结果,true表示授权通过,false表示拒绝访问
|
||||
*/
|
||||
fun authorize(
|
||||
authentication: Authentication,
|
||||
permission: String,
|
||||
providers: List<PermissionProvider>
|
||||
): Boolean
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.api.core.validator
|
||||
|
||||
/**
|
||||
*单令牌验证器
|
||||
*
|
||||
* @since 2025-06-26 15:55:34
|
||||
* @author gewuyou
|
||||
*/
|
||||
interface SingleTokenValidator<SingleTokenPrincipal>: TokenValidator<SingleTokenPrincipal>
|
||||
@ -1,21 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.api.core.validator
|
||||
|
||||
/**
|
||||
* 令牌验证器接口,用于定义通用的令牌验证逻辑
|
||||
*
|
||||
* 该接口设计为泛型接口,支持不同类型的令牌验证结果。
|
||||
*
|
||||
* @since 2025-06-26 15:54:14
|
||||
* @author gewuyou
|
||||
*/
|
||||
fun interface TokenValidator<T> {
|
||||
/**
|
||||
* 验证指定的令牌字符串并返回解析后的结果对象
|
||||
*
|
||||
* @param token 待验证的令牌字符串,通常由客户端在请求头中提供
|
||||
* @return 返回解析后的泛型对象 T,可能是用户信息、权限列表或其他业务相关的数据结构
|
||||
* @throws IllegalArgumentException 如果令牌格式不正确或为空
|
||||
* @throws SecurityException 如果令牌无效或已过期
|
||||
*/
|
||||
fun validate(token: String): T
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.api.servlet.manager
|
||||
|
||||
import org.springframework.security.authorization.AuthorizationManager
|
||||
|
||||
/**
|
||||
* 动态授权管理器接口
|
||||
*
|
||||
* 该接口用于处理请求级别的动态权限控制逻辑,基于Spring Security的AuthorizationManager接口进行扩展。
|
||||
* 通过泛型类型T定义需要处理的授权上下文类型,例如Web请求或方法调用等。
|
||||
*
|
||||
* @param <T> 授权操作涉及的具体上下文类型,如RequestAuthorizationContext或其他自定义上下文对象
|
||||
*
|
||||
* @since 2025-06-24 15:52:01
|
||||
* @author gewuyou
|
||||
*/
|
||||
interface DynamicAuthorizationManager<T> : AuthorizationManager<T>
|
||||
@ -1,11 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.api.webflux.manager
|
||||
|
||||
import org.springframework.security.authorization.ReactiveAuthorizationManager
|
||||
|
||||
/**
|
||||
*动态反应式授权管理器
|
||||
*
|
||||
* @since 2025-06-24 13:16:25
|
||||
* @author gewuyou
|
||||
*/
|
||||
fun interface DynamicReactiveAuthorizationManager<T> : ReactiveAuthorizationManager<T>
|
||||
@ -1,3 +0,0 @@
|
||||
/gradlew text eol=lf
|
||||
*.bat text eol=crlf
|
||||
*.jar binary
|
||||
@ -1,40 +0,0 @@
|
||||
HELP.md
|
||||
.gradle
|
||||
build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Kotlin ###
|
||||
.kotlin
|
||||
@ -1,12 +0,0 @@
|
||||
plugins {
|
||||
alias(libs.plugins.kotlin.plugin.spring)
|
||||
}
|
||||
dependencies {
|
||||
compileOnly(libs.springBootStarter.web)
|
||||
// webflux
|
||||
compileOnly(libs.springBootStarter.webflux)
|
||||
compileOnly(libs.springBootStarter.security)
|
||||
compileOnly(project(Modules.Security.Authorize.IMPL))
|
||||
compileOnly(project(Modules.Security.Authorize.API))
|
||||
implementation(project(Modules.Security.CORE))
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.autoconfigure
|
||||
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.config.SecurityAuthorizeProperties
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties
|
||||
import org.springframework.context.annotation.Configuration
|
||||
|
||||
/**
|
||||
*forge security 授权自动配置
|
||||
*
|
||||
* @since 2025-06-15 19:28:11
|
||||
* @author gewuyou
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(SecurityAuthorizeProperties::class)
|
||||
class ForgeSecurityAuthorizeAutoConfiguration
|
||||
@ -1,77 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.autoconfigure.core
|
||||
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.manager.AccessManager
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.provider.PermissionProvider
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.resolver.PermissionResolver
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.strategy.AuthorizationStrategy
|
||||
import com.gewuyou.forgeboot.security.authorize.impl.core.manager.DefaultAccessManager
|
||||
import com.gewuyou.forgeboot.security.authorize.impl.core.resolver.DefaultPermissionResolver
|
||||
import com.gewuyou.forgeboot.security.authorize.impl.core.strategy.AnyMatchStrategy
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
|
||||
/**
|
||||
* Forge Security Authorize 核心配置
|
||||
*
|
||||
* 该配置类定义了权限控制所需的核心组件Bean,包括权限解析器、授权策略和访问管理器。
|
||||
* 这些Bean用于实现基于权限表达式的访问控制机制。
|
||||
*
|
||||
* @since 2025-06-24 16:49:37
|
||||
* @author gewuyou
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
class ForgeSecurityAuthorizeCoreConfiguration {
|
||||
/**
|
||||
* 权限解析器Bean,用于将权限表达式解析为具体的权限对象。
|
||||
*
|
||||
* 权限解析器是访问控制的基础组件,负责解析配置中的权限表达式,
|
||||
* 将其转换为系统可识别和处理的权限对象。
|
||||
*
|
||||
* @return 返回一个具体的权限解析器实例,此处为DefaultPermissionResolver。
|
||||
* 该实例实现了基本的权限解析功能。
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnBean
|
||||
fun permissionResolver(): PermissionResolver {
|
||||
return DefaultPermissionResolver()
|
||||
}
|
||||
|
||||
/**
|
||||
* 授权策略Bean,用于定义权限匹配的策略。
|
||||
*
|
||||
* 授权策略决定了如何根据用户权限与资源所需权限进行匹配,
|
||||
* 是决定访问是否被允许的关键逻辑所在。
|
||||
*
|
||||
* @return 返回一个具体授权策略实例,此处为AnyMatchStrategy(任意匹配策略)。
|
||||
* 该策略表示只要存在任意一个匹配的权限即可允许访问。
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnBean
|
||||
fun authorizationStrategy(): AuthorizationStrategy {
|
||||
return AnyMatchStrategy()
|
||||
}
|
||||
|
||||
/**
|
||||
* 访问管理器Bean,负责处理访问控制决策。
|
||||
*
|
||||
* 访问管理器是整个权限控制的核心组件,它整合了权限提供者和授权策略,
|
||||
* 在访问请求到来时,使用权限提供者获取权限信息,并通过策略进行决策。
|
||||
*
|
||||
* @param providers 权限提供者列表,用于获取不同资源所需的权限信息。
|
||||
* 每个Provider通常对应一种资源类型或数据来源。
|
||||
* @param strategy 授权策略实例,用于决定是否允许访问。
|
||||
* 该策略将影响最终访问控制决策。
|
||||
*
|
||||
* @return 返回一个AccessManager的具体实现,此处为DefaultAccessManager。
|
||||
* 该实现组合了权限提供者和授权策略,完成了完整的访问控制流程。
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnBean
|
||||
fun accessManager(
|
||||
providers: List<PermissionProvider>,
|
||||
strategy: AuthorizationStrategy,
|
||||
): AccessManager {
|
||||
return DefaultAccessManager(providers, strategy)
|
||||
}
|
||||
}
|
||||
@ -1,62 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.autoconfigure.core
|
||||
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.validator.SingleTokenValidator
|
||||
import com.gewuyou.forgeboot.security.authorize.impl.core.provider.SingleTokenAuthenticationProvider
|
||||
import com.gewuyou.forgeboot.security.core.authorize.entities.SingleTokenPrincipal
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.security.authentication.AuthenticationProvider
|
||||
|
||||
/**
|
||||
* 配置类,用于自动配置单点令牌(Single Token)认证相关的核心组件。
|
||||
*
|
||||
* @since 2025-06-25 15:49:50
|
||||
* @author gewuyou
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
class SingleTokenSecurityCoreAutoConfiguration {
|
||||
/**
|
||||
* 提供一个默认的 SingleTokenValidator Bean,用于验证单点登录令牌。
|
||||
*
|
||||
* 如果上下文中尚未定义此类 Bean,则使用此默认实现。
|
||||
* 默认实现会在调用 validate 方法时抛出 UnsupportedOperationException,
|
||||
* 提示使用者应提供自定义的 SingleTokenValidator 实现。
|
||||
*
|
||||
* @return 返回一个 SingleTokenValidator 接口的默认实现
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
fun singleTokenValidator(): SingleTokenValidator<SingleTokenPrincipal> {
|
||||
return object : SingleTokenValidator<SingleTokenPrincipal> {
|
||||
/**
|
||||
* 验证给定的 token 并返回对应的用户主体信息。
|
||||
*
|
||||
* @param token 要验证的令牌字符串
|
||||
* @return 返回包含用户信息的 SingleTokenPrincipal 对象
|
||||
* @throws UnsupportedOperationException 始终抛出异常,提示需要自定义实现
|
||||
*/
|
||||
override fun validate(token: String): SingleTokenPrincipal {
|
||||
throw UnsupportedOperationException("请提供 SingleTokenService 实现")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 注册 SingleTokenAuthenticationProvider Bean,用于 Spring Security 的认证流程。
|
||||
*
|
||||
* 该方法创建并返回一个 SingleTokenAuthenticationProvider 实例,
|
||||
* 用于在 Spring Security 框架中处理基于单点令牌的认证逻辑。
|
||||
* 如果上下文中尚未定义同名 Bean,则进行注册。
|
||||
*
|
||||
* @param singleTokenValidator 提供的 SingleTokenValidator 实例,
|
||||
* 用于执行具体的令牌验证逻辑
|
||||
* @return 返回配置好的 AuthenticationProvider 实现类实例
|
||||
*/
|
||||
@Bean("singleTokenAuthenticationProvider")
|
||||
@ConditionalOnMissingBean
|
||||
fun singleTokenAuthenticationProvider(singleTokenValidator: SingleTokenValidator<SingleTokenPrincipal>): AuthenticationProvider {
|
||||
return SingleTokenAuthenticationProvider(singleTokenValidator)
|
||||
}
|
||||
}
|
||||
@ -1,129 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.autoconfigure.servlet
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.config.SecurityAuthorizeProperties
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.manager.AccessManager
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.resolver.PermissionResolver
|
||||
import com.gewuyou.forgeboot.security.authorize.impl.servlet.adapter.DynamicAuthorizationManagerAdapter
|
||||
import com.gewuyou.forgeboot.security.authorize.impl.servlet.handler.AuthorizationExceptionHandler
|
||||
import com.gewuyou.forgeboot.security.authorize.impl.servlet.registrar.StatelessSecurityFilterChainRegistrar
|
||||
import com.gewuyou.forgeboot.security.core.common.constants.SecurityConstants
|
||||
import com.gewuyou.forgeboot.security.core.common.customizer.HttpSecurityCustomizer
|
||||
import com.gewuyou.forgeboot.security.core.common.registrar.SecurityFilterChainRegistrar
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.context.annotation.Primary
|
||||
import org.springframework.security.authentication.AuthenticationManager
|
||||
import org.springframework.security.authentication.AuthenticationProvider
|
||||
import org.springframework.security.authentication.ProviderManager
|
||||
import org.springframework.security.authorization.AuthorizationManager
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.web.SecurityFilterChain
|
||||
import org.springframework.security.web.access.AccessDeniedHandler
|
||||
import org.springframework.security.web.access.intercept.RequestAuthorizationContext
|
||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher
|
||||
|
||||
/**
|
||||
*servlet authorize 安全配置
|
||||
*
|
||||
* @since 2025-06-24 16:54:19
|
||||
* @author gewuyou
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
|
||||
class ServletAuthorizeSecurityConfiguration(
|
||||
private val accessManager: AccessManager,
|
||||
private val permissionResolver: PermissionResolver,
|
||||
) {
|
||||
/**
|
||||
* 创建并返回一个认证管理器。
|
||||
*
|
||||
* 初始化一个基于提供的认证提供者的认证管理器,用于支持多种认证方式。
|
||||
*
|
||||
* @param authenticationProviders 所有可用的认证提供者列表
|
||||
* @return 返回初始化好的 AuthenticationManager 实例,具体实现为 ProviderManager
|
||||
*/
|
||||
@Bean
|
||||
@Primary
|
||||
@ConditionalOnBean
|
||||
fun authenticationManager(
|
||||
authenticationProviders: List<AuthenticationProvider>,
|
||||
): AuthenticationManager = ProviderManager(authenticationProviders)
|
||||
|
||||
/**
|
||||
* 创建默认的安全过滤链,适用于 Servlet 编程模型
|
||||
*
|
||||
* @param registrar 安全过滤链注册器
|
||||
* @param http HttpSecurity 配置对象
|
||||
* @return 构建后的安全过滤链实例
|
||||
* @throws Exception 构建过程中可能抛出的异常
|
||||
*/
|
||||
@Bean(name = ["defaultSecurityFilterChain"])
|
||||
@ConditionalOnBean
|
||||
@Throws(Exception::class)
|
||||
fun defaultSecurityFilterChain(
|
||||
registrar: SecurityFilterChainRegistrar,
|
||||
http: HttpSecurity,
|
||||
): SecurityFilterChain = registrar.buildChain(
|
||||
SecurityConstants.DEFAULT_CHAIN_ID,
|
||||
http,
|
||||
AnyRequestMatcher.INSTANCE
|
||||
) { config ->
|
||||
config.authorizeHttpRequests {
|
||||
it.anyRequest().denyAll()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册授权异常处理器
|
||||
*
|
||||
* @param objectMapper 用于序列化错误响应的对象映射器
|
||||
* @param securityAuthorizeProperties 授权配置属性
|
||||
* @return AccessDeniedHandler 实例
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnClass(AccessDeniedHandler::class)
|
||||
@ConditionalOnBean
|
||||
fun authorizationExceptionHandler(
|
||||
objectMapper: ObjectMapper,
|
||||
securityAuthorizeProperties: SecurityAuthorizeProperties,
|
||||
): AccessDeniedHandler {
|
||||
return AuthorizationExceptionHandler(objectMapper, securityAuthorizeProperties)
|
||||
}
|
||||
|
||||
/**
|
||||
* 动态授权管理器适配器
|
||||
*
|
||||
* @return 适配后的授权管理器实例
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnBean
|
||||
fun dynamicAuthorizationManager(): AuthorizationManager<RequestAuthorizationContext> {
|
||||
return DynamicAuthorizationManagerAdapter(accessManager, permissionResolver)
|
||||
}
|
||||
|
||||
/**
|
||||
* 无状态安全过滤链注册器
|
||||
*
|
||||
* @param authorizationManager 授权管理器
|
||||
* @param accessDeniedHandler 授权失败处理器
|
||||
* @param httpSecurityCustomizer HTTP 安全配置定制器列表
|
||||
* @return 安全过滤链注册器实例
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnBean
|
||||
fun statelessSecurityWebFilterChainRegistrar(
|
||||
authorizationManager: AuthorizationManager<RequestAuthorizationContext>,
|
||||
accessDeniedHandler: AccessDeniedHandler,
|
||||
httpSecurityCustomizer: List<HttpSecurityCustomizer>,
|
||||
): SecurityFilterChainRegistrar {
|
||||
return StatelessSecurityFilterChainRegistrar(
|
||||
httpSecurityCustomizer,
|
||||
authorizationManager,
|
||||
accessDeniedHandler
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1,134 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.autoconfigure.servlet
|
||||
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.config.SecurityAuthorizeProperties
|
||||
import com.gewuyou.forgeboot.security.authorize.impl.servlet.customizer.SingleTokenHttpSecurityCustomizer
|
||||
import com.gewuyou.forgeboot.security.authorize.impl.servlet.filter.SingleTokenAuthenticationFilter
|
||||
import com.gewuyou.forgeboot.security.core.common.constants.SecurityConstants
|
||||
import com.gewuyou.forgeboot.security.core.common.customizer.HttpSecurityCustomizer
|
||||
import com.gewuyou.forgeboot.security.core.common.registrar.SecurityFilterChainRegistrar
|
||||
import jakarta.servlet.Filter
|
||||
import org.springframework.beans.factory.annotation.Qualifier
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.security.authorization.AuthorizationManager
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.web.SecurityFilterChain
|
||||
import org.springframework.security.web.access.intercept.RequestAuthorizationContext
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher
|
||||
import org.springframework.security.web.util.matcher.OrRequestMatcher
|
||||
|
||||
/**
|
||||
* Single Token安全自动配置类,用于在 Servlet Web 应用中自动装配与 Single Token相关的安全组件。
|
||||
*
|
||||
* 此配置仅在以下条件下生效:
|
||||
* 1. 应用类型为 Servlet;
|
||||
* 2. 配置项 "forgeboot.security.authorize.single-token.enabled" 为 true。
|
||||
*
|
||||
* @property securityAuthorizeProperties 安全授权配置属性,用于获取 Single Token相关路径等信息
|
||||
* @since 2025-06-25 13:41:56
|
||||
* @author gewuyou
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
|
||||
@ConditionalOnProperty(
|
||||
prefix = "forgeboot.security.authorize.single-token",
|
||||
name = ["enabled"],
|
||||
havingValue = "true",
|
||||
matchIfMissing = false
|
||||
)
|
||||
class ServletSingleTokenSecurityAutoConfiguration(
|
||||
private val securityAuthorizeProperties: SecurityAuthorizeProperties,
|
||||
) {
|
||||
/**
|
||||
* 创建 Single Token认证过滤器 Bean。
|
||||
*
|
||||
* 构建一个 SingleTokenAuthenticationFilter 实例作为 Spring Bean,
|
||||
* 该过滤器用于处理基于 Single Token 的身份验证逻辑。
|
||||
*
|
||||
* @return 返回构建完成的 Filter 接口实现对象(即 SingleTokenAuthenticationFilter)
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(name = ["singleTokenAuthenticationFilter"])
|
||||
fun singleTokenAuthenticationFilter(): Filter {
|
||||
return SingleTokenAuthenticationFilter()
|
||||
}
|
||||
|
||||
/**
|
||||
* 提供一个用于自定义 HTTP 安全配置的 Single Token安全自定义器 Bean。
|
||||
*
|
||||
* 如果容器中尚不存在同名 Bean,则创建并返回 SingleTokenHttpSecurityCustomizer 实例。
|
||||
* 此自定义器将注入的认证过滤器用于构建定制化的安全配置,实现对 HttpSecurity 的扩展。
|
||||
*
|
||||
* @param singleTokenAuthenticationFilter 注入已配置的认证过滤器,用于请求处理
|
||||
* @return 返回 HttpSecurityCustomizer 的具体实现对象
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
fun singleTokenHttpSecurityCustomizer(
|
||||
@Qualifier("singleTokenAuthenticationFilter")
|
||||
singleTokenAuthenticationFilter: Filter,
|
||||
): HttpSecurityCustomizer {
|
||||
return SingleTokenHttpSecurityCustomizer(singleTokenAuthenticationFilter)
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建默认的安全过滤链,适用于 Servlet 编程模型。
|
||||
*
|
||||
* 此方法基于配置的路径模式构建一个复合请求匹配器,并通过注册器创建对应的 SingleToken 安全过滤链。
|
||||
* 过滤链根据配置决定是否使用授权管理器进行访问控制,提供两种模式:
|
||||
* - 使用授权管理器时:所有请求通过指定的 authorizeManager 进行访问控制
|
||||
* - 不使用授权管理器时:要求所有请求必须经过身份验证
|
||||
*
|
||||
* @param registrar 安全过滤链注册器,用于构建和管理过滤链
|
||||
* @param http Spring Security 的 HttpSecurity 配置对象
|
||||
* @param authorizeManager 授权管理器,用于在启用授权管理时定义访问策略
|
||||
* @return 构建完成的安全过滤链实例
|
||||
*/
|
||||
@Bean(name = ["defaultSingleTokenSecurityFilterChain"])
|
||||
fun defaultSingleTokenSecurityFilterChain(
|
||||
registrar: SecurityFilterChainRegistrar,
|
||||
http: HttpSecurity,
|
||||
authorizeManager: AuthorizationManager<RequestAuthorizationContext>
|
||||
): SecurityFilterChain {
|
||||
// 从配置中获取 singleToken 适用的路径模式(如:["/api/**", "/open/**"])
|
||||
val patterns = securityAuthorizeProperties.singleToken.pathPatterns
|
||||
|
||||
/**
|
||||
* 将每个路径模式转换为 AntPathRequestMatcher 实例
|
||||
*/
|
||||
val matchers = patterns.map { AntPathRequestMatcher(it) }
|
||||
|
||||
/**
|
||||
* 使用 OrRequestMatcher 组合所有路径匹配规则,实现多路径匹配支持
|
||||
*/
|
||||
val combinedMatcher = OrRequestMatcher(matchers)
|
||||
|
||||
/**
|
||||
* 调用注册器构建安全链,指定链 ID、HttpSecurity 对象和请求匹配器
|
||||
*/
|
||||
return registrar.buildChain(
|
||||
SecurityConstants.SINGLE_TOKEN_CHAIN_ID,
|
||||
http,
|
||||
combinedMatcher
|
||||
) { config ->
|
||||
if (securityAuthorizeProperties.singleToken.useAuthorizationManager) {
|
||||
/**
|
||||
* 启用授权管理器时,配置请求通过指定的 authorizeManager 进行访问控制
|
||||
*/
|
||||
config.authorizeHttpRequests {
|
||||
it.anyRequest().access(authorizeManager)
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* 禁用授权管理器时,要求所有请求必须经过身份验证
|
||||
*/
|
||||
config.authorizeHttpRequests {
|
||||
it.anyRequest().authenticated()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,149 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.autoconfigure.webflux
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.config.SecurityAuthorizeProperties
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.manager.AccessManager
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.resolver.PermissionResolver
|
||||
import com.gewuyou.forgeboot.security.authorize.impl.webflux.adapter.DynamicReactiveAuthorizationManagerAdapter
|
||||
import com.gewuyou.forgeboot.security.authorize.impl.webflux.handler.ReactiveAuthorizationExceptionHandler
|
||||
import com.gewuyou.forgeboot.security.authorize.impl.webflux.registrar.StatelessSecurityWebFilterChainRegistrar
|
||||
import com.gewuyou.forgeboot.security.core.common.constants.SecurityConstants
|
||||
import com.gewuyou.forgeboot.security.core.common.customizer.ServerHttpSecurityCustomizer
|
||||
import com.gewuyou.forgeboot.security.core.common.registrar.SecurityWebFilterChainRegistrar
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.context.annotation.Primary
|
||||
import org.springframework.security.authentication.AuthenticationProvider
|
||||
import org.springframework.security.authentication.ProviderManager
|
||||
import org.springframework.security.authentication.ReactiveAuthenticationManager
|
||||
import org.springframework.security.authentication.ReactiveAuthenticationManagerAdapter
|
||||
import org.springframework.security.authorization.ReactiveAuthorizationManager
|
||||
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity
|
||||
import org.springframework.security.config.web.server.ServerHttpSecurity
|
||||
import org.springframework.security.web.server.SecurityWebFilterChain
|
||||
import org.springframework.security.web.server.authorization.AuthorizationContext
|
||||
import org.springframework.security.web.server.authorization.ServerAccessDeniedHandler
|
||||
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers
|
||||
|
||||
/**
|
||||
* 反应式授权配置
|
||||
* 配置响应式安全过滤链和相关组件,用于处理WebFlux环境下的安全控制。
|
||||
*
|
||||
* @since 2025-06-24 16:48:11
|
||||
* @author gewuyou
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableWebFluxSecurity
|
||||
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
|
||||
class ReactiveAuthorizeSecurityConfiguration(
|
||||
private val accessManager: AccessManager,
|
||||
private val permissionResolver: PermissionResolver,
|
||||
) {
|
||||
|
||||
/**
|
||||
* 创建默认的安全过滤链,适用于响应式编程模型
|
||||
* 使用给定的注册器和配置构建一个默认的安全过滤链,该链拒绝所有请求。
|
||||
*
|
||||
* @param registrar 安全过滤链注册器,用于注册新的安全过滤链
|
||||
* @param http ServerHttpSecurity配置对象,用于定义安全规则
|
||||
* @return 构建后的安全过滤链实例
|
||||
* @throws Exception 构建过程中可能抛出的异常
|
||||
*/
|
||||
@Bean(name = ["defaultSecurityWebFilterChain"])
|
||||
@ConditionalOnBean
|
||||
@Throws(Exception::class)
|
||||
fun defaultSecurityWebFilterChain(
|
||||
registrar: SecurityWebFilterChainRegistrar,
|
||||
http: ServerHttpSecurity,
|
||||
): SecurityWebFilterChain = registrar
|
||||
.buildChain(
|
||||
SecurityConstants.DEFAULT_CHAIN_ID,
|
||||
http,
|
||||
ServerWebExchangeMatchers.anyExchange()
|
||||
) { it: ServerHttpSecurity ->
|
||||
it.authorizeExchange {
|
||||
it.anyExchange().denyAll()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册响应式授权异常处理器
|
||||
* 创建并返回一个用于处理授权失败情况的异常处理器。
|
||||
*
|
||||
* @param objectMapper 用于序列化错误响应的对象映射器
|
||||
* @param securityAuthorizeProperties 授权配置属性,包含自定义的授权设置
|
||||
* @return ServerAccessDeniedHandler 实例,用于处理访问被拒绝的情况
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnClass(ServerAccessDeniedHandler::class)
|
||||
@ConditionalOnBean
|
||||
fun reactiveAuthorizationExceptionHandler(
|
||||
objectMapper: ObjectMapper,
|
||||
securityAuthorizeProperties: SecurityAuthorizeProperties,
|
||||
): ServerAccessDeniedHandler {
|
||||
return ReactiveAuthorizationExceptionHandler(objectMapper, securityAuthorizeProperties)
|
||||
}
|
||||
|
||||
/**
|
||||
* 动态响应式授权管理器适配器
|
||||
* 创建并返回一个适配后的响应式授权管理器实例,用于动态评估访问请求。
|
||||
*
|
||||
* @return 适配后的响应式授权管理器实例
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnBean
|
||||
fun dynamicReactiveAuthorizationManager(): ReactiveAuthorizationManager<AuthorizationContext> {
|
||||
return DynamicReactiveAuthorizationManagerAdapter(accessManager, permissionResolver)
|
||||
}
|
||||
|
||||
/**
|
||||
* 反应式认证管理器
|
||||
* 创建并返回一个主认证管理器实例,用于处理响应式编程环境中的身份验证请求。
|
||||
* 该管理器基于提供的认证提供者列表进行初始化。
|
||||
*
|
||||
* 此方法通过将传统的 ProviderManager 包装在 ReactiveAuthenticationManagerAdapter 中,
|
||||
* 实现了对响应式编程模型的支持。ProviderManager 被构造为使用给定的认证提供者列表,
|
||||
* 并作为适配器的一部分来完成异步的身份验证逻辑。
|
||||
*
|
||||
* @param authenticationProviders 认证提供者列表,用于执行具体的身份验证逻辑。
|
||||
* 每个提供者负责特定类型的身份验证机制。
|
||||
* @return 初始化后的 ReactiveAuthenticationManager 实例,用于响应式环境下的身份验证流程。
|
||||
* 返回的对象是 ReactiveAuthenticationManagerAdapter 的实例,其内部封装了同步的 ProviderManager。
|
||||
*/
|
||||
@Bean
|
||||
@Primary
|
||||
@ConditionalOnBean
|
||||
fun reactiveAuthenticationManager(
|
||||
authenticationProviders: List<AuthenticationProvider>
|
||||
): ReactiveAuthenticationManager {
|
||||
return ReactiveAuthenticationManagerAdapter(
|
||||
ProviderManager(authenticationProviders)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 无状态安全过滤链注册器
|
||||
* 创建并返回一个无状态的安全过滤链注册器,用于注册需要无状态处理的安全过滤链。
|
||||
*
|
||||
* @param reactiveAuthorizationManager 响应式授权管理器,用于评估访问请求
|
||||
* @param reactiveAccessDeniedHandler 授权失败处理器,用于处理访问被拒绝的情况
|
||||
* @param serverHttpSecurityCustomizer 安全配置定制器列表,用于自定义安全配置
|
||||
* @return 安全过滤链注册器实例,用于注册无状态安全过滤链
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnBean
|
||||
fun statelessSecurityWebFilterChainRegistrar(
|
||||
reactiveAuthorizationManager: ReactiveAuthorizationManager<AuthorizationContext>,
|
||||
reactiveAccessDeniedHandler: ServerAccessDeniedHandler,
|
||||
serverHttpSecurityCustomizer: List<ServerHttpSecurityCustomizer>,
|
||||
): SecurityWebFilterChainRegistrar {
|
||||
return StatelessSecurityWebFilterChainRegistrar(
|
||||
serverHttpSecurityCustomizer,
|
||||
reactiveAuthorizationManager,
|
||||
reactiveAccessDeniedHandler
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1,132 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.autoconfigure.webflux
|
||||
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.config.SecurityAuthorizeProperties
|
||||
import com.gewuyou.forgeboot.security.authorize.impl.webflux.customizer.SingleTokenServerHttpSecurityCustomizer
|
||||
import com.gewuyou.forgeboot.security.authorize.impl.webflux.filter.ReactiveSingleTokenAuthenticationFilter
|
||||
import com.gewuyou.forgeboot.security.core.common.constants.SecurityConstants
|
||||
import com.gewuyou.forgeboot.security.core.common.customizer.ServerHttpSecurityCustomizer
|
||||
import com.gewuyou.forgeboot.security.core.common.registrar.SecurityWebFilterChainRegistrar
|
||||
import org.springframework.beans.factory.annotation.Qualifier
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
|
||||
import org.springframework.security.authentication.ReactiveAuthenticationManager
|
||||
import org.springframework.security.authorization.ReactiveAuthorizationManager
|
||||
import org.springframework.security.config.web.server.ServerHttpSecurity
|
||||
import org.springframework.security.web.server.SecurityWebFilterChain
|
||||
import org.springframework.security.web.server.authorization.AuthorizationContext
|
||||
import org.springframework.security.web.server.util.matcher.PathPatternParserServerWebExchangeMatcher
|
||||
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher
|
||||
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers
|
||||
import org.springframework.web.server.WebFilter
|
||||
|
||||
/**
|
||||
* 配置类,用于在满足条件时自动配置基于 Single Token 的反应式安全机制。
|
||||
*
|
||||
* 仅在满足以下条件时生效:
|
||||
* - 应用类型为 REACTIVE(反应式应用)
|
||||
* - 配置项 `forgeboot.security.authorize.single-token.enabled` 被设置为 true
|
||||
*
|
||||
* @property securityAuthorizeProperties 安全授权配置属性,用于获取 Single Token 的路径匹配规则等信息
|
||||
* @since 2025-06-25 21:04:37
|
||||
* @author gewuyou
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
|
||||
@ConditionalOnProperty(
|
||||
prefix = "forgeboot.security.authorize.single-token",
|
||||
name = ["enabled"],
|
||||
havingValue = "true",
|
||||
matchIfMissing = false
|
||||
)
|
||||
class ReactiveSingleTokenSecurityAutoConfiguration(
|
||||
private val securityAuthorizeProperties: SecurityAuthorizeProperties
|
||||
) {
|
||||
|
||||
/**
|
||||
* 创建并注册名为 reactiveSingleTokenAuthenticationFilter 的 WebFilter Bean。
|
||||
*
|
||||
* 该过滤器负责处理基于 Single Token 的认证逻辑,确保请求携带有效的 Token。
|
||||
* 仅当容器中尚未存在同名的 Bean 时才会创建此实例。
|
||||
*
|
||||
* @param reactiveAuthenticationManager 反应式认证管理器,用于执行认证操作
|
||||
* @return 构建完成的 WebFilter 实例
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(name = ["reactiveSingleTokenAuthenticationFilter"])
|
||||
fun singleTokenAuthenticationFilter(
|
||||
reactiveAuthenticationManager: ReactiveAuthenticationManager
|
||||
): WebFilter {
|
||||
return ReactiveSingleTokenAuthenticationFilter(reactiveAuthenticationManager)
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建并注册 ServerHttpSecurityCustomizer 的 Bean,用于定制 Single Token 安全配置。
|
||||
*
|
||||
* 此自定义器用于在构建 Spring Security 过滤器链时插入 Single Token 认证逻辑。
|
||||
* 仅当容器中尚未存在相同类型的 Bean 时才会创建此实例。
|
||||
*
|
||||
* @param reactiveSingleTokenAuthenticationFilter 使用指定名称从 Spring 容器中注入的 Single Token 反应式认证过滤器 Bean。
|
||||
* 该过滤器负责处理实际的 Single Token 认证逻辑。
|
||||
*
|
||||
* @return 构建完成的 ServerHttpSecurityCustomizer 实例,用于在安全配置中添加 Single Token 相关逻辑。
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
fun singleTokenServerHttpSecurityCustomizer(
|
||||
@Qualifier("reactiveSingleTokenAuthenticationFilter")
|
||||
reactiveSingleTokenAuthenticationFilter: WebFilter,
|
||||
): ServerHttpSecurityCustomizer {
|
||||
return SingleTokenServerHttpSecurityCustomizer(reactiveSingleTokenAuthenticationFilter)
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建并注册基于 Single Token 认证的 WebFlux 安全过滤器链。
|
||||
*
|
||||
* 该方法利用 SecurityWebFilterChainRegistrar 注册一个具有路径匹配规则的安全过滤器链,
|
||||
* 仅对符合配置中指定路径模式的请求生效,并要求通过 Single Token 认证。
|
||||
*
|
||||
* @param registrar 用于注册和构建安全过滤器链的核心工具类,负责链的组装过程。
|
||||
* @param http Spring Security 提供的 ServerHttpSecurity 实例,用于构建 HTTP 安全配置。
|
||||
* @param reactiveAuthorizationManager 反应式授权管理器,用于在使用授权管理逻辑时提供访问控制。
|
||||
* @return 构建完成的 SecurityWebFilterChain 实例,表示定义好的安全过滤器链。
|
||||
*
|
||||
* 关键逻辑总结:
|
||||
* 1. 获取配置中的路径模式列表 patterns;
|
||||
* 2. 将每个路径转换为 ServerWebExchangeMatcher 实例,形成 matchers 列表;
|
||||
* 3. 合并所有 matcher 形成 combinedMatcher 复合匹配规则;
|
||||
* 4. 利用 registrar 构建过滤器链,并根据 useAuthorizationManager 配置决定采用何种认证方式:
|
||||
* - 若启用 authorizationManager,则通过 access 方法设置自定义的授权逻辑;
|
||||
* - 否则直接要求请求必须经过认证。
|
||||
*/
|
||||
@Bean(name = ["defaultSingleTokenSecurityWebFilterChain"])
|
||||
fun defaultSingleTokenSecurityWebFilterChain(
|
||||
registrar: SecurityWebFilterChainRegistrar,
|
||||
http: ServerHttpSecurity,
|
||||
reactiveAuthorizationManager: ReactiveAuthorizationManager<AuthorizationContext>
|
||||
): SecurityWebFilterChain {
|
||||
val patterns = securityAuthorizeProperties.singleToken.pathPatterns
|
||||
val matchers = patterns.map { PathPatternParserServerWebExchangeMatcher(it) }
|
||||
val combinedMatcher: ServerWebExchangeMatcher =
|
||||
ServerWebExchangeMatchers.matchers(*matchers.toTypedArray())
|
||||
return registrar.buildChain(
|
||||
SecurityConstants.SINGLE_TOKEN_CHAIN_ID,
|
||||
http,
|
||||
combinedMatcher
|
||||
) { config ->
|
||||
if (securityAuthorizeProperties.singleToken.useAuthorizationManager) {
|
||||
config.authorizeExchange {
|
||||
it.anyExchange().access(reactiveAuthorizationManager)
|
||||
}
|
||||
} else {
|
||||
config.authorizeExchange {
|
||||
it.anyExchange().authenticated()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
com.gewuyou.forgeboot.security.authorize.autoconfigure.ForgeSecurityAuthorizeAutoConfiguration
|
||||
com.gewuyou.forgeboot.security.authorize.autoconfigure.core.ForgeSecurityAuthorizeCoreConfiguration
|
||||
com.gewuyou.forgeboot.security.authorize.autoconfigure.core.SingleTokenSecurityCoreAutoConfiguration
|
||||
com.gewuyou.forgeboot.security.authorize.autoconfigure.webflux.ReactiveAuthorizeSecurityConfiguration
|
||||
com.gewuyou.forgeboot.security.authorize.autoconfigure.webflux.ReactiveSingleTokenSecurityAutoConfiguration
|
||||
com.gewuyou.forgeboot.security.authorize.autoconfigure.servlet.ServletAuthorizeSecurityConfiguration
|
||||
com.gewuyou.forgeboot.security.authorize.autoconfigure.servlet.ServletSingleTokenSecurityAutoConfiguration
|
||||
@ -1,6 +0,0 @@
|
||||
extra{
|
||||
setProperty(ProjectFlags.IS_ROOT_MODULE,true)
|
||||
}
|
||||
dependencies {
|
||||
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
/gradlew text eol=lf
|
||||
*.bat text eol=crlf
|
||||
*.jar binary
|
||||
@ -1,40 +0,0 @@
|
||||
HELP.md
|
||||
.gradle
|
||||
build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Kotlin ###
|
||||
.kotlin
|
||||
@ -1,14 +0,0 @@
|
||||
plugins {
|
||||
alias(libs.plugins.kotlin.plugin.spring)
|
||||
}
|
||||
dependencies {
|
||||
implementation(libs.springBootStarter.aop)
|
||||
implementation(libs.springExpression)
|
||||
implementation(project(Modules.Core.EXTENSION))
|
||||
implementation(project(Modules.Cache.STARTER))
|
||||
implementation(project(Modules.Webmvc.DTO)) // webflux
|
||||
compileOnly(libs.springBootStarter.webflux)
|
||||
compileOnly(project(Modules.Security.Authorize.API))
|
||||
compileOnly(libs.springBootStarter.web)
|
||||
compileOnly(libs.springBootStarter.security)
|
||||
}
|
||||
@ -1,85 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.core.aspect
|
||||
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.annotations.RequiresPermission
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.manager.AccessManager
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.strategy.AuthorizationStrategy
|
||||
import com.gewuyou.forgeboot.security.authorize.impl.core.resolver.SpELResolver
|
||||
import org.aspectj.lang.ProceedingJoinPoint
|
||||
import org.aspectj.lang.annotation.Around
|
||||
import org.aspectj.lang.annotation.Aspect
|
||||
import org.aspectj.lang.reflect.MethodSignature
|
||||
import org.springframework.security.access.AccessDeniedException
|
||||
import org.springframework.security.core.context.SecurityContextHolder
|
||||
|
||||
/**
|
||||
* 授权切面
|
||||
*
|
||||
* 该切面用于处理带有 [RequiresPermission] 注解的方法,执行权限校验逻辑。
|
||||
* 通过查找适用的 [AuthorizationStrategy] 来决定是否允许当前用户执行目标方法。
|
||||
*
|
||||
* @property spELResolver SpEL 表达式解析器,用于动态解析权限字符串。
|
||||
* @property accessManager 访问控制管理器,用于最终的权限判断。
|
||||
*
|
||||
* @since 2025-06-15 13:17:18
|
||||
* @author gewuyou
|
||||
*/
|
||||
@Aspect
|
||||
class RequiresPermissionAspect(
|
||||
private val spELResolver: SpELResolver,
|
||||
private val accessManager: AccessManager
|
||||
) {
|
||||
|
||||
/**
|
||||
* 环绕通知方法,处理带有 [RequiresPermission] 注解的方法调用。
|
||||
*
|
||||
* 执行流程:
|
||||
* 1. 获取当前用户的认证信息;
|
||||
* 2. 获取目标方法及其参数;
|
||||
* 3. 根据注解配置决定是否解析 SpEL 表达式获取实际权限标识;
|
||||
* 4. 查找适用的授权策略并执行授权逻辑;
|
||||
* 5. 如果授权成功,则继续执行目标方法。
|
||||
*
|
||||
* @param joinPoint ProceedingJoinPoint,代表被拦截的方法执行连接点。
|
||||
* @param permission 方法上标注的 [RequiresPermission] 注解实例。
|
||||
* @return 目标方法的返回值。
|
||||
*/
|
||||
@Around("@annotation(permission)")
|
||||
fun around(joinPoint: ProceedingJoinPoint, permission: RequiresPermission): Any {
|
||||
// 获取当前用户的安全上下文认证信息
|
||||
val auth = SecurityContextHolder.getContext().authentication
|
||||
|
||||
// 根据 dynamic 配置决定是否解析 SpEL 表达式,得到最终权限标识
|
||||
val perm = if (permission.dynamic) {
|
||||
resolveSpEl(permission.value, joinPoint)
|
||||
} else permission.value
|
||||
|
||||
// 使用 accessManager 进行权限校验,失败时抛出访问拒绝异常
|
||||
if (!accessManager.hasPermission(auth, perm))
|
||||
throw AccessDeniedException("权限不足,需要 [$perm]")
|
||||
|
||||
// 权限校验通过,继续执行目标方法
|
||||
return joinPoint.proceed()
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析 SpEL 表达式,形参名可直接用 #变量 方式引用
|
||||
*
|
||||
* 例:@RequiresPermission(dynamic = true, value = "'article:read:' + #articleId")
|
||||
*
|
||||
* @param expression 要解析的 SpEL 表达式。
|
||||
* @param joinPoint ProceedingJoinPoint,从中提取方法参数。
|
||||
* @return 解析后的实际权限字符串。
|
||||
*/
|
||||
private fun resolveSpEl(expression: String, joinPoint: ProceedingJoinPoint): String {
|
||||
val methodSignature = joinPoint.signature as MethodSignature
|
||||
val paramNames = methodSignature.parameterNames // ["articleId", "commentId", …]
|
||||
val args = joinPoint.args // [123L, 456L, …]
|
||||
|
||||
// 组装成 Map<String, Any?>
|
||||
val argsMap = paramNames
|
||||
.mapIndexed { index, name -> name to args[index] }
|
||||
.toMap()
|
||||
|
||||
return spELResolver.parse(expression, argsMap)
|
||||
}
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.core.manager
|
||||
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.manager.AccessManager
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.provider.PermissionProvider
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.strategy.AuthorizationStrategy
|
||||
import org.springframework.security.core.Authentication
|
||||
|
||||
/**
|
||||
*默认 Access Manager
|
||||
*
|
||||
* @since 2025-06-15 18:41:22
|
||||
* @author gewuyou
|
||||
*/
|
||||
class DefaultAccessManager(
|
||||
private val providers: List<PermissionProvider>,
|
||||
private val strategy : AuthorizationStrategy
|
||||
) : AccessManager {
|
||||
/**
|
||||
* 判断用户是否具有指定权限
|
||||
*
|
||||
* @param authentication Spring Security提供的身份认证信息
|
||||
* @param permission 需要验证的权限字符串
|
||||
* @return Boolean 返回是否有权限的布尔值
|
||||
*/
|
||||
override fun hasPermission(authentication: Authentication, permission: String): Boolean =
|
||||
strategy.authorize(authentication, permission, providers)
|
||||
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.core.provider
|
||||
|
||||
import com.gewuyou.forgeboot.core.extension.log
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.provider.PermissionProvider
|
||||
import org.springframework.security.core.Authentication
|
||||
|
||||
/**
|
||||
*抽象权限提供程序
|
||||
*
|
||||
* @since 2025-06-23 21:45:49
|
||||
* @author gewuyou
|
||||
*/
|
||||
abstract class AbstractPermissionProvider : PermissionProvider {
|
||||
|
||||
/**
|
||||
* 获取权限集合模板方法
|
||||
*/
|
||||
override fun listPermissions(authentication: Authentication): Collection<String> {
|
||||
if (!supports(authentication)) return emptySet()
|
||||
return try {
|
||||
doProvide(authentication).toSet()
|
||||
} catch (ex: Exception) {
|
||||
log.error("获取权限失败", ex)
|
||||
emptySet()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 子类实现:获取权限的具体逻辑
|
||||
*/
|
||||
protected abstract fun doProvide(authentication: Authentication): Collection<String>
|
||||
|
||||
/**
|
||||
* 是否支持当前 Authentication 类型
|
||||
*/
|
||||
protected open fun supports(authentication: Authentication): Boolean = true
|
||||
}
|
||||
@ -1,59 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.core.provider
|
||||
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.validator.SingleTokenValidator
|
||||
import com.gewuyou.forgeboot.security.core.authorize.entities.SingleTokenPrincipal
|
||||
import com.gewuyou.forgeboot.security.core.common.token.SingleTokenAuthenticationToken
|
||||
import org.springframework.security.authentication.AuthenticationProvider
|
||||
import org.springframework.security.core.Authentication
|
||||
|
||||
/**
|
||||
* 单例 Token 认证提供者,实现 Spring Security 的 AuthenticationProvider 接口。
|
||||
*
|
||||
* 用于处理基于 SingleToken 的身份验证流程。
|
||||
*
|
||||
* @property singleTokenValidator 用于执行 Token 校验的服务组件。
|
||||
* @author gewuyou
|
||||
* @since 2025-06-25 13:09:43
|
||||
*/
|
||||
class SingleTokenAuthenticationProvider(
|
||||
private val singleTokenValidator: SingleTokenValidator<SingleTokenPrincipal>
|
||||
) : AuthenticationProvider {
|
||||
|
||||
/**
|
||||
* 执行身份验证操作。
|
||||
*
|
||||
* 将传入的身份验证对象转换为 SingleTokenAuthenticationToken 类型,
|
||||
* 然后通过 singleTokenService 验证 Token 的有效性,并返回认证后的 Authentication 对象。
|
||||
*
|
||||
* 该方法的主要流程包括:
|
||||
* 1. 强制类型转换输入的 Authentication 对象为 SingleTokenAuthenticationToken;
|
||||
* 2. 使用 Token 的 principal 值调用 singleTokenService 进行 Token 校验;
|
||||
* 3. 构建并返回已认证的 Authentication 实例。
|
||||
*
|
||||
* @param authentication 需要被验证的 Authentication 实例,必须是 SingleTokenAuthenticationToken 类型。
|
||||
* @return 返回一个已认证的 Authentication 对象,表示身份验证成功的结果。
|
||||
*/
|
||||
override fun authenticate(authentication: Authentication): Authentication {
|
||||
// 转换 Authentication 为 SingleTokenAuthenticationToken 类型
|
||||
val token = authentication as SingleTokenAuthenticationToken
|
||||
|
||||
// 使用 Token 的 principal 值进行校验,获取 Token 信息
|
||||
val tokenInfo = singleTokenValidator.validate(token.principal.toString())
|
||||
|
||||
// 创建已认证的 Authentication 实例并返回
|
||||
return SingleTokenAuthenticationToken.authenticated(tokenInfo, tokenInfo.authorities)
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前 Provider 是否支持给定的身份验证类型。
|
||||
*
|
||||
* 此方法检查传入的身份验证类是否是 SingleTokenAuthenticationToken 或其子类。
|
||||
*
|
||||
* @param authentication 要检查的身份验证类。
|
||||
* @return 如果支持该类型则返回 true,否则返回 false。
|
||||
*/
|
||||
override fun supports(authentication: Class<*>): Boolean {
|
||||
// 检查传入的身份验证类是否是 SingleTokenAuthenticationToken 或其子类
|
||||
return SingleTokenAuthenticationToken::class.java.isAssignableFrom(authentication)
|
||||
}
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.core.resolver
|
||||
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.resolver.PermissionResolver
|
||||
|
||||
/**
|
||||
* 默认权限解析程序
|
||||
*
|
||||
* @since 2025-06-24 13:42:20
|
||||
* @author gewuyou
|
||||
*/
|
||||
class DefaultPermissionResolver : PermissionResolver {
|
||||
|
||||
/**
|
||||
* 将请求路径和HTTP方法解析为标准化的权限标识符
|
||||
*
|
||||
* 此方法会对原始路径进行标准化处理,替换其中的动态参数部分为统一占位符,
|
||||
* 然后将HTTP方法和标准化后的路径组合成最终的权限标识符。
|
||||
*
|
||||
* @param path 请求路径
|
||||
* @param method HTTP请求方法
|
||||
* @return 标准化的权限标识符,格式为"METHOD:/path/template"
|
||||
*/
|
||||
override fun resolve(path: String, method: String): String {
|
||||
// 对路径进行标准化处理:
|
||||
// 1. 转换为小写
|
||||
// 2. 替换数字ID为{id}通配符
|
||||
// 3. 替换MongoDB ObjectId为{objectId}
|
||||
// 4. 替换UUID为{uuid}
|
||||
val normalizedPath = path
|
||||
.lowercase()
|
||||
.replace(Regex("/\\d+"), "/{id}")
|
||||
.replace(Regex("/[a-f0-9]{24}"), "/{objectId}")
|
||||
.replace(Regex("/[a-z0-9\\-]{36}"), "/{uuid}")
|
||||
|
||||
return "${method}:$normalizedPath"
|
||||
}
|
||||
}
|
||||
@ -1,50 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.core.resolver
|
||||
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory
|
||||
import org.springframework.context.expression.BeanFactoryResolver
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext
|
||||
|
||||
/**
|
||||
* SpEL 解析器,用于解析和执行 Spring Expression Language (SpEL) 表达式。
|
||||
*
|
||||
* 该类封装了 SpEL 的解析和求值过程,结合 Spring 的 BeanFactory 支持表达式中对 Bean 的引用。
|
||||
*
|
||||
* @property beanFactory 提供 Spring 容器的 Bean 工厂,用于解析表达式中的 Bean 引用。
|
||||
* @since 2025-06-15 13:32:31
|
||||
* @author gewuyou
|
||||
*/
|
||||
class SpELResolver(private val beanFactory: ConfigurableBeanFactory) {
|
||||
// 初始化 SpEL 表达式解析器
|
||||
private val parser = SpelExpressionParser()
|
||||
// 初始化 SpEL 求值上下文,并设置 Bean 解析器
|
||||
private val context = StandardEvaluationContext()
|
||||
|
||||
/**
|
||||
* 在初始化阶段配置上下文,使其能够通过 BeanFactory 解析表达式中的 Bean。
|
||||
*/
|
||||
init {
|
||||
context.beanResolver = BeanFactoryResolver(beanFactory)
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析并计算给定的 SpEL 表达式,返回结果作为字符串。
|
||||
*
|
||||
* @param expression 表达式字符串,例如 `#user.name` 或 `'Hello ' + #name`
|
||||
* @param rootObject 根对象,表达式中的属性访问将基于此对象进行解析
|
||||
* @return 解析后的字符串结果,如果表达式结果为 null,则返回空字符串
|
||||
*/
|
||||
fun parse(expression: String, rootObject: Any): String {
|
||||
context.setRootObject(rootObject)
|
||||
|
||||
// 如果是 Map,则把每个键当作变量注入,支持 #varName 直接取值
|
||||
if (rootObject is Map<*, *>) {
|
||||
rootObject.forEach { (k, v) ->
|
||||
if (k is String) context.setVariable(k, v)
|
||||
}
|
||||
}
|
||||
return parser
|
||||
.parseExpression(expression)
|
||||
.getValue(context, String::class.java) ?: ""
|
||||
}
|
||||
}
|
||||
@ -1,29 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.core.strategy
|
||||
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.provider.PermissionProvider
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.strategy.AuthorizationStrategy
|
||||
import org.springframework.security.core.Authentication
|
||||
|
||||
/**
|
||||
* 任何匹配策略 - 实现授权策略接口,采用任意权限匹配机制
|
||||
*
|
||||
* @since 2025-06-15 18:51:23
|
||||
* @author gewuyou
|
||||
*/
|
||||
class AnyMatchStrategy : AuthorizationStrategy {
|
||||
/**
|
||||
* 执行授权验证
|
||||
*
|
||||
* @param authentication 当前用户身份认证信息
|
||||
* @param permission 需要验证的权限标识
|
||||
* @param providers 权限提供者列表
|
||||
* @return Boolean 返回授权结果,true表示授权通过,false表示拒绝访问
|
||||
*
|
||||
* 该方法通过遍历所有权限提供者,只要有一个提供者包含目标权限即视为授权成功
|
||||
*/
|
||||
override fun authorize(
|
||||
authentication: Authentication,
|
||||
permission: String,
|
||||
providers: List<PermissionProvider>
|
||||
) = providers.any { permission in it.listPermissions(authentication) }
|
||||
}
|
||||
@ -1,54 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.servlet.adapter
|
||||
|
||||
import com.gewuyou.forgeboot.core.extension.log
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.manager.AccessManager
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.resolver.PermissionResolver
|
||||
import com.gewuyou.forgeboot.security.authorize.api.servlet.manager.DynamicAuthorizationManager
|
||||
import org.springframework.security.authorization.AuthorizationDecision
|
||||
import org.springframework.security.core.Authentication
|
||||
import org.springframework.security.web.access.intercept.RequestAuthorizationContext
|
||||
import java.util.function.Supplier
|
||||
|
||||
/**
|
||||
* 授权管理器适配器,用于将 AccessManager 适配为 Spring Security 的 AuthorizationManager。
|
||||
*
|
||||
* @property accessManager 提供权限判断的访问管理器实例
|
||||
* @property permissionResolver 用于解析请求路径和方法对应的权限需求
|
||||
* @since 2025-06-23 21:42:19
|
||||
* @author gewuyou
|
||||
*/
|
||||
class DynamicAuthorizationManagerAdapter(
|
||||
private val accessManager: AccessManager,
|
||||
private val permissionResolver: PermissionResolver,
|
||||
) : DynamicAuthorizationManager<RequestAuthorizationContext> {
|
||||
|
||||
/**
|
||||
* 执行权限校验的核心方法。
|
||||
*
|
||||
* @param authentication 提供认证信息的 Supplier,从中获取当前用户的身份认证对象
|
||||
* @param context 请求上下文,包含请求相关的额外信息(未在此实现中使用)
|
||||
* @return 返回一个 AuthorizationDecision 对象,表示是否通过授权
|
||||
*/
|
||||
override fun check(
|
||||
authentication: Supplier<Authentication>,
|
||||
context: RequestAuthorizationContext,
|
||||
): AuthorizationDecision {
|
||||
try {
|
||||
// 获取 HTTP 请求的基本信息
|
||||
val request = context.request
|
||||
val method = request.method
|
||||
val path = request.requestURI
|
||||
// 解析当前请求所需的权限
|
||||
val requiredPermission = permissionResolver.resolve(path, method)
|
||||
|
||||
// 校验用户是否拥有该权限
|
||||
val granted = accessManager.hasPermission(authentication.get(), requiredPermission)
|
||||
|
||||
// 返回授权决策结果
|
||||
return AuthorizationDecision(granted)
|
||||
} catch (e: Exception) {
|
||||
log.error("权限校验异常", e)
|
||||
return AuthorizationDecision(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,50 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.servlet.customizer
|
||||
|
||||
import com.gewuyou.forgeboot.security.core.common.constants.SecurityConstants
|
||||
import com.gewuyou.forgeboot.security.core.common.customizer.HttpSecurityCustomizer
|
||||
import jakarta.servlet.Filter
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
|
||||
|
||||
/**
|
||||
* 基于单 Token 认证的安全配置定制器
|
||||
*
|
||||
* 该类用于在 Spring Security 的过滤器链中注册并配置 API 密钥身份验证逻辑,
|
||||
* 仅当当前安全链标识符匹配 SINGLE_TOKEN_CHAIN_ID 时生效。
|
||||
*
|
||||
* @property singleTokenAuthenticationFilter 处理 API 密钥身份验证请求的过滤器实例
|
||||
* @since 2025-06-25 16:09:38
|
||||
* @author gewuyou
|
||||
*/
|
||||
class SingleTokenHttpSecurityCustomizer(
|
||||
private val singleTokenAuthenticationFilter: Filter
|
||||
) : HttpSecurityCustomizer {
|
||||
|
||||
/**
|
||||
* 判断当前定制器是否支持处理指定的安全链配置
|
||||
*
|
||||
* 此方法用于标识该定制器是否适用于特定的安全链配置。
|
||||
* 实现类应根据 chainId 参数决定是否启用此定制器的逻辑。
|
||||
*
|
||||
* @param chainId 安全链的唯一标识符,用于区分不同的安全配置场景
|
||||
* @return Boolean 返回 true 表示支持该 chainId,否则不支持
|
||||
*/
|
||||
override fun supports(chainId: String): Boolean {
|
||||
return SecurityConstants.SINGLE_TOKEN_CHAIN_ID == chainId
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行安全配置的定制逻辑
|
||||
*
|
||||
* 将 API 密钥身份验证过滤器添加到 Spring Security 的过滤器链中,
|
||||
* 置于 UsernamePasswordAuthenticationFilter 之前以确保优先处理 Token 请求。
|
||||
*
|
||||
* @param http 用于构建 HTTP 安全策略的 HttpSecurity 实例
|
||||
* 通过此参数可添加或修改安全规则,如认证、授权等
|
||||
*/
|
||||
override fun customize(http: HttpSecurity) {
|
||||
// 配置安全逻辑:注册认证提供者并将 API 密钥过滤器插入到过滤器链中的合适位置
|
||||
http
|
||||
.addFilterBefore(singleTokenAuthenticationFilter, UsernamePasswordAuthenticationFilter::class.java)
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user