mirror of
https://github.moeyy.xyz/https://github.com/GeWuYou/forgeboot
synced 2025-10-28 05:14:25 +08:00
refactor(security): 重构单令牌认证体系
- 重构 SingleTokenService 为 SingleTokenValidator,优化令牌验证流程 - 新增 TokenValidator 接口,用于定义通用令牌验证逻辑 - 更新 SingleTokenSecurityCoreAutoConfiguration,适配新的验证器 - 重构 SingleTokenAuthenticationProvider,使用新的验证器进行令牌验证 - 更新过滤器和认证令牌类,以适应新的认证流程
This commit is contained in:
parent
aa9bd66259
commit
21542adfcc
@ -1,22 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.api.core.service
|
||||
|
||||
import com.gewuyou.forgeboot.security.core.authorize.entities.SingleTokenPrincipal
|
||||
|
||||
/**
|
||||
* 单一令牌验证服务接口
|
||||
*
|
||||
* 该接口用于定义对单一令牌的验证操作,通过提供的令牌字符串返回对应的主体信息。
|
||||
*
|
||||
* @since 2025-06-25 13:10:38
|
||||
* @author gewuyou
|
||||
*/
|
||||
fun interface SingleTokenService {
|
||||
|
||||
/**
|
||||
* 验证给定的令牌字符串并返回对应的主体信息。
|
||||
*
|
||||
* @param token 要验证的令牌字符串
|
||||
* @return 返回与令牌关联的主体信息对象 [SingleTokenPrincipal]
|
||||
*/
|
||||
fun validate(token: String): SingleTokenPrincipal
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.api.core.validator
|
||||
|
||||
/**
|
||||
*单令牌验证器
|
||||
*
|
||||
* @since 2025-06-26 15:55:34
|
||||
* @author gewuyou
|
||||
*/
|
||||
interface SingleTokenValidator<SingleTokenPrincipal>: TokenValidator<SingleTokenPrincipal>
|
||||
@ -0,0 +1,21 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.api.core.validator
|
||||
|
||||
/**
|
||||
* 令牌验证器接口,用于定义通用的令牌验证逻辑
|
||||
*
|
||||
* 该接口设计为泛型接口,支持不同类型的令牌验证结果。
|
||||
*
|
||||
* @since 2025-06-26 15:54:14
|
||||
* @author gewuyou
|
||||
*/
|
||||
fun interface TokenValidator<T> {
|
||||
/**
|
||||
* 验证指定的令牌字符串并返回解析后的结果对象
|
||||
*
|
||||
* @param token 待验证的令牌字符串,通常由客户端在请求头中提供
|
||||
* @return 返回解析后的泛型对象 T,可能是用户信息、权限列表或其他业务相关的数据结构
|
||||
* @throws IllegalArgumentException 如果令牌格式不正确或为空
|
||||
* @throws SecurityException 如果令牌无效或已过期
|
||||
*/
|
||||
fun validate(token: String): T
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.autoconfigure.core
|
||||
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.service.SingleTokenService
|
||||
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
|
||||
@ -16,20 +16,19 @@ import org.springframework.security.authentication.AuthenticationProvider
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
class SingleTokenSecurityCoreAutoConfiguration {
|
||||
|
||||
/**
|
||||
* 提供一个默认的 SingleTokenService Bean,用于验证令牌并返回用户主体信息。
|
||||
* 提供一个默认的 SingleTokenValidator Bean,用于验证单点登录令牌。
|
||||
*
|
||||
* 如果上下文中尚未定义此类 Bean,则使用此默认实现。
|
||||
* 默认实现会在调用 validate 方法时抛出 UnsupportedOperationException,
|
||||
* 提示使用者应提供自定义的 SingleTokenService 实现。
|
||||
* 提示使用者应提供自定义的 SingleTokenValidator 实现。
|
||||
*
|
||||
* @return 返回一个 SingleTokenService 接口的默认实现
|
||||
* @return 返回一个 SingleTokenValidator 接口的默认实现
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
fun singleTokenService(): SingleTokenService {
|
||||
return object : SingleTokenService {
|
||||
fun singleTokenValidator(): SingleTokenValidator<SingleTokenPrincipal> {
|
||||
return object : SingleTokenValidator<SingleTokenPrincipal> {
|
||||
/**
|
||||
* 验证给定的 token 并返回对应的用户主体信息。
|
||||
*
|
||||
@ -43,18 +42,21 @@ class SingleTokenSecurityCoreAutoConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 注册 SingleTokenAuthenticationProvider Bean,用于 Spring Security 的认证流程。
|
||||
*
|
||||
* 该认证提供者依赖于 SingleTokenService 来完成实际的令牌验证工作。
|
||||
* 如果上下文中尚未定义同名 Bean,则注册该 Bean。
|
||||
* 该方法创建并返回一个 SingleTokenAuthenticationProvider 实例,
|
||||
* 用于在 Spring Security 框架中处理基于单点令牌的认证逻辑。
|
||||
* 如果上下文中尚未定义同名 Bean,则进行注册。
|
||||
*
|
||||
* @param singleTokenService 用于令牌验证的服务实例
|
||||
* @return 返回配置好的 SingleTokenAuthenticationProvider 实例
|
||||
* @param singleTokenValidator 提供的 SingleTokenValidator 实例,
|
||||
* 用于执行具体的令牌验证逻辑
|
||||
* @return 返回配置好的 AuthenticationProvider 实现类实例
|
||||
*/
|
||||
@Bean("singleTokenAuthenticationProvider")
|
||||
@ConditionalOnMissingBean
|
||||
fun singleTokenAuthenticationProvider(singleTokenService: SingleTokenService): AuthenticationProvider {
|
||||
return SingleTokenAuthenticationProvider(singleTokenService)
|
||||
fun singleTokenAuthenticationProvider(singleTokenValidator: SingleTokenValidator<SingleTokenPrincipal>): AuthenticationProvider {
|
||||
return SingleTokenAuthenticationProvider(singleTokenValidator)
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.core.provider
|
||||
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.service.SingleTokenService
|
||||
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
|
||||
@ -10,34 +11,37 @@ import org.springframework.security.core.Authentication
|
||||
*
|
||||
* 用于处理基于 SingleToken 的身份验证流程。
|
||||
*
|
||||
* @property singleTokenService 用于执行 Token 校验的服务组件。
|
||||
* @property singleTokenValidator 用于执行 Token 校验的服务组件。
|
||||
* @author gewuyou
|
||||
* @since 2025-06-25 13:09:43
|
||||
*/
|
||||
class SingleTokenAuthenticationProvider(
|
||||
private val singleTokenService: SingleTokenService
|
||||
private val singleTokenValidator: SingleTokenValidator<SingleTokenPrincipal>
|
||||
) : AuthenticationProvider {
|
||||
|
||||
/**
|
||||
* 执行身份验证操作。
|
||||
*
|
||||
* 将传入的身份验证对象转换为 SingleTokenAuthenticationToken,
|
||||
* 将传入的身份验证对象转换为 SingleTokenAuthenticationToken 类型,
|
||||
* 然后通过 singleTokenService 验证 Token 的有效性,并返回认证后的 Authentication 对象。
|
||||
*
|
||||
* @param authentication 需要被验证的 Authentication 实例。
|
||||
* @return 返回已认证的 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
|
||||
val tokenInfo = singleTokenService.validate(token.singleToken)
|
||||
|
||||
return SingleTokenAuthenticationToken(
|
||||
token.singleToken,
|
||||
tokenInfo.principal,
|
||||
tokenInfo.authorities
|
||||
).apply {
|
||||
isAuthenticated = true
|
||||
}
|
||||
// 使用 Token 的 principal 值进行校验,获取 Token 信息
|
||||
val tokenInfo = singleTokenValidator.validate(token.principal.toString())
|
||||
|
||||
// 创建已认证的 Authentication 实例并返回
|
||||
return SingleTokenAuthenticationToken.authenticated(tokenInfo, tokenInfo.authorities)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -49,6 +53,7 @@ class SingleTokenAuthenticationProvider(
|
||||
* @return 如果支持该类型则返回 true,否则返回 false。
|
||||
*/
|
||||
override fun supports(authentication: Class<*>): Boolean {
|
||||
// 检查传入的身份验证类是否是 SingleTokenAuthenticationToken 或其子类
|
||||
return SingleTokenAuthenticationToken::class.java.isAssignableFrom(authentication)
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@ class SingleTokenAuthenticationFilter() : OncePerRequestFilter() {
|
||||
if (header?.startsWith(SecurityConstants.BEARER_PREFIX) == true) {
|
||||
val token = header.removePrefix(SecurityConstants.BEARER_PREFIX).trim()
|
||||
// 构造未认证的 token 放入上下文
|
||||
val authentication = SingleTokenAuthenticationToken(token, null)
|
||||
val authentication = SingleTokenAuthenticationToken.unauthenticated(token)
|
||||
SecurityContextHolder.getContext().authentication = authentication
|
||||
}
|
||||
chain.doFilter(request, response)
|
||||
|
||||
@ -56,8 +56,8 @@ class ReactiveSingleTokenAuthenticationFilter(
|
||||
override fun convert(exchange: ServerWebExchange): Mono<Authentication>? {
|
||||
val headerValue = exchange.request.headers.getFirst(HttpHeaders.AUTHORIZATION)
|
||||
return if (headerValue?.startsWith(SecurityConstants.BEARER_PREFIX, ignoreCase = true) == true) {
|
||||
val apiKey = headerValue.removePrefix(SecurityConstants.BEARER_PREFIX).trim()
|
||||
Mono.just(SingleTokenAuthenticationToken(apiKey, null))
|
||||
val singleToken = headerValue.removePrefix(SecurityConstants.BEARER_PREFIX).trim()
|
||||
Mono.just(SingleTokenAuthenticationToken(singleToken, null))
|
||||
} else {
|
||||
Mono.empty()
|
||||
}
|
||||
|
||||
@ -14,6 +14,11 @@ object SecurityConstants {
|
||||
*/
|
||||
const val AUTHORIZATION_HEADER = "Authorization"
|
||||
|
||||
/**
|
||||
* HTTP请求头中用于携带刷新令牌的字段名称
|
||||
*/
|
||||
const val REFRESH_TOKEN_HEADER="X-Refresh-Token"
|
||||
|
||||
/**
|
||||
* Bearer Token前缀,用于在请求头中标识Token类型
|
||||
*/
|
||||
|
||||
@ -7,37 +7,78 @@ import org.springframework.security.core.GrantedAuthority
|
||||
* 用于单令牌认证的认证令牌实现类。该类扩展了 Spring Security 的 AbstractAuthenticationToken,
|
||||
* 用于表示基于单一令牌(如 API Key)的认证请求。
|
||||
*
|
||||
* @param singleToken 存储认证凭据(如API密钥或令牌),不可为 null。
|
||||
* @param principal 表示经过认证的主体,可以是用户对象或其他形式的身份标识。
|
||||
* @param principal 表示经过认证的主体,可以是用户对象或其他形式的身份标识,不可为 null。
|
||||
* @param authorities 用户所拥有的权限集合,默认为空列表。
|
||||
*
|
||||
* @author gewuyou
|
||||
* @since 2025-06-25 13:06:54
|
||||
*/
|
||||
class SingleTokenAuthenticationToken(
|
||||
val singleToken: String,
|
||||
private val principal: Any?,
|
||||
authorities: Collection<GrantedAuthority> = listOf()
|
||||
private val principal: Any,
|
||||
authorities: Collection<GrantedAuthority>? = null,
|
||||
) : AbstractAuthenticationToken(authorities) {
|
||||
|
||||
/**
|
||||
* 获取认证凭据。
|
||||
*
|
||||
* @return 返回存储在 [singleToken] 中的认证凭据。
|
||||
* 初始化方法,根据是否提供权限信息设置认证状态。
|
||||
* 如果权限信息为 null,则认证状态设为未认证;否则设为已认证。
|
||||
*/
|
||||
override fun getCredentials(): Any = singleToken
|
||||
init {
|
||||
if (authorities == null) {
|
||||
super.setAuthenticated(false)
|
||||
} else {
|
||||
super.setAuthenticated(true)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* 创建一个未认证的 SingleTokenAuthenticationToken 实例。
|
||||
*
|
||||
* @param token 认证凭据(如 API 密钥或令牌),不可为 null。
|
||||
* @return 返回未认证的 SingleTokenAuthenticationToken 实例。
|
||||
*/
|
||||
@JvmStatic
|
||||
fun unauthenticated(token: String): SingleTokenAuthenticationToken {
|
||||
return SingleTokenAuthenticationToken(token)
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个已认证的 SingleTokenAuthenticationToken 实例。
|
||||
*
|
||||
* @param principal 表示经过认证的主体,不可为 null。
|
||||
* @param authorities 用户所拥有的权限集合,不可为 null。
|
||||
* @return 返回已认证的 SingleTokenAuthenticationToken 实例。
|
||||
*/
|
||||
@JvmStatic
|
||||
fun authenticated(
|
||||
principal: Any,
|
||||
authorities: Collection<GrantedAuthority>,
|
||||
): SingleTokenAuthenticationToken {
|
||||
return SingleTokenAuthenticationToken(principal.toString(), authorities)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取认证主体。
|
||||
* 获取认证凭据。对于单令牌认证来说,凭证通常不适用,因此返回 null。
|
||||
*
|
||||
* @return 返回认证主体对象,可能为 null。
|
||||
* @return 始终返回 null。
|
||||
*/
|
||||
override fun getPrincipal(): Any? = principal
|
||||
override fun getCredentials(): Any? = null
|
||||
|
||||
/**
|
||||
* 判断当前认证是否已完成。
|
||||
* 获取认证的主体信息。
|
||||
*
|
||||
* @return 如果认证成功则返回 true;否则返回 false。
|
||||
* @return 返回认证的主体对象。
|
||||
*/
|
||||
override fun isAuthenticated(): Boolean = super.isAuthenticated
|
||||
override fun getPrincipal(): Any = principal
|
||||
|
||||
/**
|
||||
* 禁止直接设置认证状态。应使用工厂方法创建已认证或未认证的实例。
|
||||
*
|
||||
* @param authenticated 认证状态,此参数将被忽略。
|
||||
* @throws IllegalArgumentException 总是抛出此异常以防止直接修改认证状态。
|
||||
*/
|
||||
override fun setAuthenticated(authenticated: Boolean) {
|
||||
throw IllegalArgumentException("请使用 factory 方法设置认证状态")
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user