build: 删除安全认证模块的自动配置

- 移除了安全认证模块的所有自动配置类
- 删除了相关的配置属性、处理程序、策略等类
- 清除了构建脚本中的依赖引用
- 移除了.gitattributes和.gitignore文件
This commit is contained in:
gewuyou 2025-07-16 12:13:18 +08:00
parent b9da8bf395
commit 5f3e078e0f
133 changed files with 0 additions and 5301 deletions

View File

@ -1,3 +0,0 @@
/gradlew text eol=lf
*.bat text eol=crlf
*.jar binary

View File

@ -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

View File

@ -1,5 +0,0 @@
extra{
setProperty(ProjectFlags.IS_ROOT_MODULE,true)
}
dependencies {
}

View File

@ -1,3 +0,0 @@
/gradlew text eol=lf
*.bat text eol=crlf
*.jar binary

View File

@ -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

View File

@ -1,3 +0,0 @@
/gradlew text eol=lf
*.bat text eol=crlf
*.jar binary

View File

@ -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

View File

@ -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)
}

View File

@ -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
}
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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"
}

View File

@ -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
)

View File

@ -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
}

View File

@ -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>?
}

View File

@ -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
}

View File

@ -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 新的 TokenPairaccessToken + refreshToken
*/
fun refreshTokenPair(accessToken: String, refreshToken: String): TokenPair
/**
* 生成新刷新令牌
*
* 根据系统策略生成一个安全的唯一的刷新令牌字符串
* 该令牌通常具有较长的有效期且用于获取新访问令牌
*
* @return 生成的刷新令牌字符串
*/
fun generateRefreshToken(): String
/**
* 生成访问令牌
*
* 基于用户详细信息生成一个访问令牌用于临时认证请求
* 该令牌通常具有较短的有效期且不能直接用于刷新操作
*
* @param userDetails 用户详细信息对象
* @return 生成的访问令牌字符串
*/
fun generateAccessToken(userDetails: Any): String
}

View File

@ -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)
}

View File

@ -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>
}

View File

@ -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

View File

@ -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>
}

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -1,3 +0,0 @@
/gradlew text eol=lf
*.bat text eol=crlf
*.jar binary

View File

@ -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

View File

@ -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))
}

View File

@ -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()
}
}
}

View File

@ -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
)
}

View File

@ -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
)
}
}

View File

@ -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()
}
}

View File

@ -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

View File

@ -1,6 +0,0 @@
extra{
setProperty(ProjectFlags.IS_ROOT_MODULE,true)
}
dependencies {
}

View File

@ -1,3 +0,0 @@
/gradlew text eol=lf
*.bat text eol=crlf
*.jar binary

View File

@ -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

View File

@ -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)
}

View File

@ -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"
}

View File

@ -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))
}
}

View File

@ -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)
)
)
}
}

View File

@ -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)
}
}

View File

@ -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()
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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
}

View File

@ -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
)
}
}
}

View File

@ -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]
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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
)
}
}

View File

@ -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
)
}
}

View File

@ -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()
}
}

View File

@ -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")
}
}

View File

@ -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 }
)

View File

@ -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 }
)

View File

@ -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()}")
}
}

View File

@ -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 }
)

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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
}
}

View File

@ -1,3 +0,0 @@
/gradlew text eol=lf
*.bat text eol=crlf
*.jar binary

View File

@ -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

View File

@ -1,3 +0,0 @@
/gradlew text eol=lf
*.bat text eol=crlf
*.jar binary

View File

@ -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/

View File

@ -1,7 +0,0 @@
dependencies {
api(project(Modules.Security.CORE))
compileOnly(libs.springBootStarter.web)
compileOnly(libs.springBootStarter.security)
kapt(libs.springBoot.configuration.processor)
}

View File

@ -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
)

View File

@ -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/**")
}
}

View File

@ -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
}

View File

@ -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>
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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>

View File

@ -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
}

View File

@ -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>

View File

@ -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>

View File

@ -1,3 +0,0 @@
/gradlew text eol=lf
*.bat text eol=crlf
*.jar binary

View File

@ -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

View File

@ -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))
}

View File

@ -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

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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
)
}
}

View File

@ -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)
/**
* 调用注册器构建安全链指定链 IDHttpSecurity 对象和请求匹配器
*/
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()
}
}
}
}
}

View File

@ -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
)
}
}

View File

@ -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()
}
}
}
}
}

View File

@ -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

View File

@ -1,6 +0,0 @@
extra{
setProperty(ProjectFlags.IS_ROOT_MODULE,true)
}
dependencies {
}

View File

@ -1,3 +0,0 @@
/gradlew text eol=lf
*.bat text eol=crlf
*.jar binary

View File

@ -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

View File

@ -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)
}

View File

@ -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)
}
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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)
}
}

View File

@ -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"
}
}

View File

@ -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) ?: ""
}
}

View File

@ -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) }
}

View File

@ -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)
}
}
}

View File

@ -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