feat(security): 实现双 token 认证机制并优化安全配置

- 在 SecurityAuthenticateProperties 中添加双 token 认证相关配置- 新增 DualTokenAuthenticationService接口和实现类,支持双 token 认证
- 添加 DualTokenAuthenticationController 实现双 token认证控制器
- 重构 SecurityAuthenticateAutoConfiguration,拆分为多个更细粒度的配置类
- 新增 SecurityCoreAutoConfiguration,集中处理安全核心配置
- 添加 SecurityProviderAutoConfiguration,自动配置认证提供者
- 新增 SecurityStrategyAutoConfiguration,自动配置安全策略
- 更新 UsernamePasswordAuthenticationProvider,支持多用户详情服务
This commit is contained in:
gewuyou 2025-06-27 08:12:51 +08:00
parent 3eb5ba6239
commit b9da8bf395
25 changed files with 730 additions and 332 deletions

View File

@ -28,6 +28,7 @@ class SecurityAuthenticateProperties {
* 默认认证失败响应内容当认证失败时返回此字符串
*/
var defaultAuthenticationFailureResponse = "If the authentication fails, please report the request ID for more information!"
/**
* 认证模块的基础URL前缀
*/
@ -42,4 +43,33 @@ class SecurityAuthenticateProperties {
* 登出接口的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

@ -0,0 +1,20 @@
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

@ -5,43 +5,26 @@ import com.gewuyou.forgeboot.security.core.authenticate.entities.request.LoginRe
/**
* 登录请求类型注册表
*
* 用于管理不同登录类型的请求类映射关系支持动态注册和获取登录请求类型
* 用于管理不同登录类型的请求类支持注册和查询操作
*
* ```kt
* @Bean
* fun loginRequestTypeRegistry(): LoginRequestTypeRegistry {
* return LoginRequestTypeRegistry().apply {
* register("default", DefaultLoginRequest::class.java)
* register("sms", SmsLoginRequest::class.java)
* }
* }
* ```
* @since 2025-06-10 16:33:43
* @since 2025-06-26 22:06:00
* @author gewuyou
*/
class LoginRequestTypeRegistry {
/**
* 内部使用可变Map保存登录类型与对应LoginRequest子类的映射关系
*/
private val mapping = mutableMapOf<String, Class<out LoginRequest>>()
interface LoginRequestTypeRegistry {
/**
* 注册指定登录类型对应的请求类
* 注册一个新的登录类型及其对应的请求类
*
* @param loginType 登录类型的标识字符串
* @param clazz 继承自LoginRequest的具体请求类
* @param clazz 继承自LoginRequest的具体请求类
*/
fun register(loginType: String, clazz: Class<out LoginRequest>) {
mapping[loginType] = clazz
}
fun register(loginType: String, clazz: Class<out LoginRequest>): LoginRequestTypeRegistry
/**
* 根据登录类型获取对应的请求类
* 根据登录类型获取对应的请求类
*
* @param loginType 登录类型的标识字符串
* @return 返回对应的LoginRequest子类未找到则返回null
* @return 返回与登录类型关联的请求类如果未找到则返回null
*/
fun getTypeForLoginType(loginType: String): Class<out LoginRequest>? {
return mapping[loginType]
}
fun getTypeForLoginType(loginType: String): Class<out LoginRequest>?
}

View File

@ -0,0 +1,47 @@
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,19 +0,0 @@
package com.gewuyou.forgeboot.security.authenticate.api.service
import org.springframework.security.core.userdetails.UserDetails
/**
* 用户详情服务
*
* @author gewuyou
* @since 2024-11-05 19:34:50
*/
fun interface UserDetailsService {
/**
* 根据用户身份标识获取用户
* @param principal 用户身份标识 通常为用户名 手机号 邮箱等
* @return 用户详情 不能为空
*/
fun loadUserByPrincipal(principal: Any): UserDetails
}

View File

@ -0,0 +1,28 @@
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,16 +1,23 @@
package com.gewuyou.forgeboot.security.authenticate.api.strategy
/**
*身份验证处理程序支持策略
* 身份验证处理程序支持策略
*
* 该函数式接口定义了身份验证策略需要实现的基本规范用于标识当前策略支持的登录类型
* 实现类应当通过返回特定的登录类型集合来表明该策略的应用范围
*
* @since 2025-06-11 00:03:28
* @author gewuyou
*/
fun interface AuthenticationHandlerSupportStrategy{
fun interface AuthenticationHandlerSupportStrategy {
/**
* 获取当前策略支持的登录类型标识符
*
* @return 返回当前策略支持的登录类型字符串
* 此方法用于判断当前身份验证策略能够处理的登录请求类型
* 例如可以基于不同的认证方式如密码短信验证码OAuth等进行区分
*
* @return 返回当前策略支持的登录类型字符串集合
* 集合中的每个字符串代表一种支持的登录类型标识符
*/
fun supportedLoginType(): String
fun supportedLoginTypes(): Set<String>
}

View File

@ -1,39 +1,19 @@
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.customizer.LoginFilterCustomizer
import com.gewuyou.forgeboot.security.authenticate.api.resolver.LoginRequestResolver
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.core.common.extension.cleanUnNeedConfig
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.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.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 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.ApplicationContext
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.ComponentScan
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.config.annotation.web.builders.HttpSecurity
import org.springframework.security.web.AuthenticationEntryPoint
import org.springframework.security.web.SecurityFilterChain
import org.springframework.security.web.authentication.AuthenticationFailureHandler
import org.springframework.security.web.authentication.AuthenticationSuccessHandler
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
import org.springframework.security.web.util.matcher.AntPathRequestMatcher
@ -45,7 +25,7 @@ import org.springframework.security.web.util.matcher.AntPathRequestMatcher
* @since 2025-06-11 15:04:58
* @author gewuyou
*/
@Configuration
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(SecurityAuthenticateProperties::class)
class SecurityAuthenticateAutoConfiguration {
@ -106,204 +86,4 @@ class SecurityAuthenticateAutoConfiguration {
.build()
}
}
/**
* ForgeBoot安全组件的自动配置类
*
* 负责注册多个用于处理身份验证流程的组合式组件如解析器上下文处理器等
*/
@Configuration(proxyBeanMethods = false)
class ForgeBootSecurityAuthenticateAutoConfiguration {
/**
* 创建并返回一个组合式的登录请求解析器
*
* 将多个 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
)
}
@Configuration(proxyBeanMethods = false)
@ComponentScan(
basePackages = [
"com.gewuyou.forgeboot.security.authenticate.impl.strategy.impl",
"com.gewuyou.forgeboot.security.authenticate.impl.provider.impl",
]
)
class ForgeBootDefaultSecurityAuthenticateAutoConfiguration
}
/**
* 用于支持登录过滤器扩展器排序
*
* 通过 order 属性为 LoginFilterCustomizer 提供排序能力确保其按预期顺序执行
*/
interface OrderedLoginFilterCustomizer : LoginFilterCustomizer {
val order: Int
}

View File

@ -0,0 +1,256 @@
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

@ -0,0 +1,34 @@
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

@ -0,0 +1,91 @@
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 +1,4 @@
com.gewuyou.forgeboot.security.authenticate.autoconfigure.SecurityAuthenticateAutoConfiguration
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

@ -0,0 +1,42 @@
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

@ -3,12 +3,10 @@ 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.api.service.UserDetailsService
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
@ -21,7 +19,6 @@ import java.util.concurrent.atomic.AtomicBoolean
*/
abstract class AbstractPrincipalCredentialsAuthenticationProvider(
private val userCacheService: UserCacheService,
private val userDetailsService: UserDetailsService
) : AuthenticationProvider {
/**
@ -79,19 +76,7 @@ abstract class AbstractPrincipalCredentialsAuthenticationProvider(
* @return UserDetails 用户详细信息
* @throws ForgeBootAuthenticationException principal 为空或加载失败时抛出异常
*/
protected open fun retrieveUser(principal: String): UserDetails {
if (principal.isBlank()) {
ForgeBootAuthenticationException(ForgeBootSecurityAuthenticationResponseInformation.PRINCIPAL_NOT_PROVIDED)
}
return try {
userDetailsService.loadUserByPrincipal(principal)
} catch (e: Exception) {
throw ForgeBootAuthenticationException(
ForgeBootSecurityAuthenticationResponseInformation.INTERNAL_SERVER_ERROR,
e
)
}
}
abstract fun retrieveUser(principal: String): UserDetails
/**
* 在验证凭据前进行账户状态检查
@ -127,7 +112,8 @@ abstract class AbstractPrincipalCredentialsAuthenticationProvider(
* @throws ForgeBootAuthenticationException 当凭证为 null 时抛出异常
*/
protected fun checkCredentialsNotNull(credentials: Any?) {
credentials ?: ForgeBootAuthenticationException(ForgeBootSecurityAuthenticationResponseInformation.PASSWORD_NOT_PROVIDED)
credentials
?: ForgeBootAuthenticationException(ForgeBootSecurityAuthenticationResponseInformation.PASSWORD_NOT_PROVIDED)
}
/**
@ -157,6 +143,6 @@ abstract class AbstractPrincipalCredentialsAuthenticationProvider(
*/
protected abstract fun createSuccessAuthentication(
authentication: Authentication,
user: UserDetails
user: UserDetails,
): Authentication
}

View File

@ -2,12 +2,12 @@ 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.api.service.UserDetailsService
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
/**
@ -25,9 +25,9 @@ import org.springframework.security.crypto.password.PasswordEncoder
*/
class UsernamePasswordAuthenticationProvider(
userCacheService: UserCacheService,
userDetailsService: UserDetailsService,
private val userDetailsService: UserDetailsService,
private val passwordEncoder: PasswordEncoder
) : AbstractPrincipalCredentialsAuthenticationProvider(userCacheService, userDetailsService) {
) : AbstractPrincipalCredentialsAuthenticationProvider(userCacheService) {
/**
* 验证用户提供的凭证是否有效
@ -74,4 +74,25 @@ class UsernamePasswordAuthenticationProvider(
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

@ -0,0 +1,69 @@
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

@ -22,7 +22,7 @@ abstract class AbstractHandlerContext<T : Any, H : Any>(
/**
* 提取策略对应类型的函数用于确定每个策略的标识
*/
extractType: (T) -> String,
extractType: (T) -> Set<String>,
/**
* 提取策略对应处理器的函数用于获取实际可执行的处理器逻辑
*/
@ -41,22 +41,21 @@ abstract class AbstractHandlerContext<T : Any, H : Any>(
val map = mutableMapOf<String, H>()
for (strategy in strategies) {
// 提取当前策略的登录类型标识
val loginType = extractType(strategy)
if (loginType == LoginTypes.DEFAULT) {
val loginTypes = extractType(strategy)
if (loginTypes.contains(LoginTypes.DEFAULT)) {
defaultStrategy = strategy
continue
}
// 获取当前策略对应的处理器实例
val handler = extractHandler(strategy)
// 检查是否已存在相同类型的处理器
val existingHandlerName = map[loginType]?.javaClass?.name
existingHandlerName?.let {
log.warn("重复注册登录类型 [$loginType] 的$typeName,已存在 $existingHandlerName,被 ${strategy::class.java.name} 覆盖")
}?.run {
log.info("注册${typeName}策略: $loginType -> ${strategy::class.java.name}")
log.info("注册${typeName}策略: $loginTypes -> ${strategy::class.java.name}")
loginTypes.forEach { loginType ->
if (map.containsKey(loginType)) {
log.warn("已存在 loginType 为 [$loginType] 的$typeName,将覆盖")
}
// 注册或覆盖处理器映射
map[loginType] = handler
}
// 注册或覆盖处理器映射
map[loginType] = handler
}
// 不可变化处理器映射表
this.handlerMap = map.toMap()

View File

@ -14,6 +14,6 @@ class AuthenticationFailureHandlerContext(
) : AbstractHandlerContext<AuthenticationFailureStrategy, AuthenticationFailureHandler>(
strategies,
"认证失败处理器",
{ it.supportedLoginType() },
{ it.supportedLoginTypes() },
{ it }
)

View File

@ -15,6 +15,6 @@ class AuthenticationSuccessHandlerContext(
strategies,
"认证成功处理器"
,
{ it.supportedLoginType() },
{ it.supportedLoginTypes() },
{ it }
)

View File

@ -14,6 +14,6 @@ class LogoutSuccessHandlerContext(
) : AbstractHandlerContext<LogoutSuccessStrategy, LogoutSuccessHandler>(
strategies,
"登出处理器",
{ it.supportedLoginType() },
{ it.supportedLoginTypes() },
{ it }
)

View File

@ -4,7 +4,6 @@ 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
import org.springframework.stereotype.Component
/**
*默认身份验证失败策略
@ -12,7 +11,6 @@ import org.springframework.stereotype.Component
* @since 2025-06-14 20:26:46
* @author gewuyou
*/
@Component("defaultAuthenticationFailureStrategy")
class DefaultAuthenticationFailureStrategy(
objectMapper: ObjectMapper,
properties: SecurityAuthenticateProperties
@ -20,9 +18,13 @@ class DefaultAuthenticationFailureStrategy(
/**
* 获取当前策略支持的登录类型标识符
*
* @return 返回当前策略支持的登录类型字符串
* 此方法用于判断当前身份验证策略能够处理的登录请求类型
* 例如可以基于不同的认证方式如密码短信验证码OAuth等进行区分
*
* @return 返回当前策略支持的登录类型字符串集合
* 集合中的每个字符串代表一种支持的登录类型标识符
*/
override fun supportedLoginType(): String {
return LoginTypes.DEFAULT
override fun supportedLoginTypes(): Set<String> {
return setOf(LoginTypes.DEFAULT)
}
}

View File

@ -3,7 +3,6 @@ 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
import org.springframework.stereotype.Component
/**
* 默认身份验证成功策略
@ -15,17 +14,15 @@ import org.springframework.stereotype.Component
* @since 2025-06-12 22:13:42
* @author gewuyou
*/
@Component("defaultAuthenticationSuccessStrategy")
class DefaultAuthenticationSuccessStrategy(
objectMapper: ObjectMapper,
) : AbstractAuthenticationSuccessStrategy(objectMapper) {
/**
* 获取当前策略支持的登录类型标识
* 获取当前策略支持的登录类型标识
*
* 此方法返回 "default" 字符串表示该策略适用于默认登录类型
* 在多策略环境下通过此标识来匹配相应的处理逻辑
*
* @return 返回支持的登录类型标识字符串
* @return 返回当前策略支持的登录类型字符串
*/
override fun supportedLoginType(): String = LoginTypes.DEFAULT
override fun supportedLoginTypes(): Set<String> {
return setOf(LoginTypes.DEFAULT)
}
}

View File

@ -3,25 +3,30 @@ 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
import org.springframework.stereotype.Component
/**
*默认注销成功策略
* 默认注销成功策略
*
* 该类实现了一个默认的注销成功处理策略用于在用户成功注销时执行相关逻辑
* 继承自 [AbstractLogoutSuccessStrategy]并使用 [objectMapper] 进行 JSON 处理
*
* @property objectMapper 用于序列化/反序列化的 Jackson ObjectMapper 实例
* @since 2025-06-14 20:38:16
* @author gewuyou
*/
@Component("defaultLogoutSuccessStrategy")
class DefaultLogoutSuccessStrategy(
objectMapper: ObjectMapper
): AbstractLogoutSuccessStrategy(objectMapper) {
) : AbstractLogoutSuccessStrategy(objectMapper) {
/**
* 获取当前策略支持的登录类型标识符
*
* @return 返回当前策略支持的登录类型字符串
* 此方法用于判断当前身份验证策略能够处理的登录请求类型
* 例如可以基于不同的认证方式如密码短信验证码OAuth等进行区分
*
* @return 返回当前策略支持的登录类型字符串集合
* 集合中的每个字符串代表一种支持的登录类型标识符
*/
override fun supportedLoginType(): String {
return LoginTypes.DEFAULT
override fun supportedLoginTypes(): Set<String> {
return setOf(LoginTypes.DEFAULT)
}
}

View File

@ -6,14 +6,12 @@ import com.gewuyou.forgeboot.security.core.authenticate.entities.request.LoginRe
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
import org.springframework.stereotype.Component
/**
* 用户名 密码 认证 Token 转换器策略
* @since 2025-02-15 03:25:14
* @author gewuyou
*/
@Component("usernamePasswordLoginRequestConverterStrategy")
class UsernamePasswordLoginRequestConverterStrategy : LoginRequestConverterStrategy {
/**
* 转换登录请求为认证对象
@ -22,7 +20,7 @@ class UsernamePasswordLoginRequestConverterStrategy : LoginRequestConverterStrat
*/
override fun convert(loginRequest: LoginRequest): Authentication {
if (loginRequest is UsernamePasswordAuthenticationRequest) {
return UsernamePasswordAuthenticationToken.Companion.unauthenticated(loginRequest.username, loginRequest.password)
return UsernamePasswordAuthenticationToken.unauthenticated(loginRequest.username, loginRequest.password)
}
throw IllegalArgumentException("Unsupported login request type: ${loginRequest.javaClass.name}")
}

View File

@ -0,0 +1,19 @@
package com.gewuyou.forgeboot.security.core.common.entities
/**
* 令牌对
*
* 该类用于封装访问令牌和刷新令牌及其有效期
*
* @property accessToken 访问令牌用于身份验证
* @property refreshToken 刷新令牌用于获取新访问令牌
* @property expiresIn 访问令牌的有效期单位为秒
*
* @since 2025-06-16 13:28:33
* @author gewuyou
*/
data class TokenPair(
val accessToken: String,
val refreshToken: String,
val expiresIn: Long
)