mirror of
https://github.moeyy.xyz/https://github.com/GeWuYou/forgeboot
synced 2025-10-27 13:26:40 +08:00
feat(security): 实现 API密钥安全控制并重构授权模块
- 新增 API 密钥安全核心配置和自动配置 - 重构授权模块,支持动态授权管理 - 更新权限解析器、授权策略和访问管理器的实现 - 新增 API 密钥认证过滤器和异常处理器 - 改进安全过滤链的构建和管理
This commit is contained in:
parent
5f3ae7a5cd
commit
ec326e5a1d
@ -1,14 +0,0 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.api.config
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties
|
||||
|
||||
/**
|
||||
*security 授权属性
|
||||
*
|
||||
* @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!"
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.api.annotations
|
||||
package com.gewuyou.forgeboot.security.authorize.api.core.annotations
|
||||
|
||||
/**
|
||||
* 权限校验注解,用于标记需要特定权限才能访问的方法
|
||||
@ -0,0 +1,42 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.api.core.config
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties
|
||||
|
||||
/**
|
||||
* Security 授权配置属性类,用于定义安全相关的可配置项
|
||||
*
|
||||
* 该类通过@ConfigurationProperties绑定配置前缀"forgeboot.security.authorize",
|
||||
* 提供了默认异常响应消息和API密钥启用状态的配置支持。
|
||||
*
|
||||
* @property defaultExceptionResponse 当访问被拒绝时返回的默认提示信息
|
||||
* @property apiKey API密钥相关配置属性对象
|
||||
*
|
||||
* @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!"
|
||||
|
||||
/**
|
||||
* API密钥相关配置属性对象,包含是否启用API密钥验证的开关
|
||||
*/
|
||||
var apiKey: ApiKeyProperties = ApiKeyProperties()
|
||||
|
||||
/**
|
||||
* API密钥功能的子配置类,用于控制API密钥验证的启用状态
|
||||
*
|
||||
* @property enabled 是否启用API密钥验证功能,默认为false
|
||||
*/
|
||||
class ApiKeyProperties {
|
||||
/**
|
||||
* 控制是否启用API密钥验证功能,默认值为false
|
||||
*/
|
||||
var enabled: Boolean = false
|
||||
var pathPatterns: List<String> = listOf("/api/**")
|
||||
var useAuthorizationManager: Boolean = true
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.api.manager
|
||||
package com.gewuyou.forgeboot.security.authorize.api.core.manager
|
||||
|
||||
import org.springframework.security.core.Authentication
|
||||
|
||||
@ -17,4 +17,4 @@ fun interface AccessManager {
|
||||
* @return Boolean 返回是否有权限的布尔值
|
||||
*/
|
||||
fun hasPermission(authentication: Authentication, permission: String): Boolean
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.api.provider
|
||||
package com.gewuyou.forgeboot.security.authorize.api.core.provider
|
||||
|
||||
import org.springframework.security.core.Authentication
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.api.resolver
|
||||
package com.gewuyou.forgeboot.security.authorize.api.core.resolver
|
||||
|
||||
/**
|
||||
* 权限解析程序接口,用于将请求路径和HTTP方法转换为具体的权限标识符。
|
||||
@ -0,0 +1,13 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.api.core.service
|
||||
|
||||
import com.gewuyou.forgeboot.security.core.authorize.entities.ApiKeyPrincipal
|
||||
|
||||
/**
|
||||
*API 密钥服务
|
||||
*
|
||||
* @since 2025-06-25 13:10:38
|
||||
* @author gewuyou
|
||||
*/
|
||||
fun interface ApiKeyService {
|
||||
fun validate(apiKey: String): ApiKeyPrincipal // 负责验证与解析
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.api.strategy
|
||||
package com.gewuyou.forgeboot.security.authorize.api.core.strategy
|
||||
|
||||
import com.gewuyou.forgeboot.security.authorize.api.provider.PermissionProvider
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.provider.PermissionProvider
|
||||
import org.springframework.security.core.Authentication
|
||||
|
||||
/**
|
||||
@ -1,16 +1,16 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.api.manager
|
||||
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>
|
||||
interface DynamicAuthorizationManager<T> : AuthorizationManager<T>
|
||||
@ -1,4 +1,4 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.api.manager
|
||||
package com.gewuyou.forgeboot.security.authorize.api.webflux.manager
|
||||
|
||||
import org.springframework.security.authorization.ReactiveAuthorizationManager
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.autoconfigure
|
||||
|
||||
import com.gewuyou.forgeboot.security.authorize.api.config.SecurityAuthorizeProperties
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.config.SecurityAuthorizeProperties
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties
|
||||
import org.springframework.context.annotation.Configuration
|
||||
|
||||
|
||||
@ -0,0 +1,58 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.autoconfigure.core
|
||||
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.service.ApiKeyService
|
||||
import com.gewuyou.forgeboot.security.authorize.impl.core.provider.ApiKeyAuthenticationProvider
|
||||
import com.gewuyou.forgeboot.security.core.authorize.entities.ApiKeyPrincipal
|
||||
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
|
||||
|
||||
/**
|
||||
* API 密钥安全核心自动配置类。
|
||||
*
|
||||
* 该配置类用于注册与 API 密钥相关的 Bean,确保在 Spring 容器中存在必要的服务和认证提供者。
|
||||
* 主要作用包括:
|
||||
* - 提供默认的 ApiKeyService Bean(未实现时)。
|
||||
* - 提供 ApiKeyAuthenticationProvider Bean 以支持基于 API 密钥的身份验证。
|
||||
*
|
||||
* @since 2025-06-25 15:49:50
|
||||
* @author gewuyou
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
class ApiKeySecurityCoreAutoConfiguration {
|
||||
|
||||
/**
|
||||
* 提供一个默认的 ApiKeyService Bean 实现。
|
||||
*
|
||||
* 如果容器中不存在 ApiKeyService 的实现,则会使用此默认 Bean。
|
||||
* 默认实现的 validate 方法始终抛出 UnsupportedOperationException,
|
||||
* 提示用户需要自定义并注册自己的 ApiKeyService 实现。
|
||||
*
|
||||
* @return 返回一个未实现的 ApiKeyService 对象
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
fun apiKeyService(): ApiKeyService {
|
||||
return object : ApiKeyService {
|
||||
override fun validate(apiKey: String): ApiKeyPrincipal {
|
||||
throw UnsupportedOperationException("请提供 ApiKeyService 实现")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 提供一个用于认证的 ApiKeyAuthenticationProvider Bean。
|
||||
*
|
||||
* 如果容器中尚不存在同名 Bean,则创建并返回 ApiKeyAuthenticationProvider 实例。
|
||||
* 该 Provider 使用传入的 apiKeyService 来处理具体的 API 密钥验证逻辑。
|
||||
*
|
||||
* @param apiKeyService 用于处理 API 密钥逻辑的服务实现
|
||||
* @return AuthenticationProvider 的具体实现对象
|
||||
*/
|
||||
@Bean("apiKeyAuthenticationProvider")
|
||||
@ConditionalOnMissingBean
|
||||
fun apiKeyAuthenticationProvider(apiKeyService: ApiKeyService): AuthenticationProvider {
|
||||
return ApiKeyAuthenticationProvider(apiKeyService)
|
||||
}
|
||||
}
|
||||
@ -1,12 +1,12 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.autoconfigure
|
||||
package com.gewuyou.forgeboot.security.authorize.autoconfigure.core
|
||||
|
||||
import com.gewuyou.forgeboot.security.authorize.api.manager.AccessManager
|
||||
import com.gewuyou.forgeboot.security.authorize.api.provider.PermissionProvider
|
||||
import com.gewuyou.forgeboot.security.authorize.api.resolver.PermissionResolver
|
||||
import com.gewuyou.forgeboot.security.authorize.api.strategy.AuthorizationStrategy
|
||||
import com.gewuyou.forgeboot.security.authorize.impl.manager.DefaultAccessManager
|
||||
import com.gewuyou.forgeboot.security.authorize.impl.resolver.DefaultPermissionResolver
|
||||
import com.gewuyou.forgeboot.security.authorize.impl.strategy.AnyMatchStrategy
|
||||
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
|
||||
@ -20,7 +20,7 @@ import org.springframework.context.annotation.Configuration
|
||||
* @since 2025-06-24 16:49:37
|
||||
* @author gewuyou
|
||||
*/
|
||||
@Configuration
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
class ForgeSecurityAuthorizeCoreConfiguration {
|
||||
/**
|
||||
* 权限解析器Bean,用于将权限表达式解析为具体的权限对象。
|
||||
@ -0,0 +1,127 @@
|
||||
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.ApiKeyHttpSecurityCustomizer
|
||||
import com.gewuyou.forgeboot.security.authorize.impl.servlet.filter.ApiKeyAuthenticationFilter
|
||||
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.authentication.AuthenticationManager
|
||||
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
|
||||
|
||||
/**
|
||||
* API 密钥安全自动配置类,用于在 Servlet Web 应用中自动装配与 API 密钥相关的安全组件。
|
||||
*
|
||||
* 此配置仅在以下条件下生效:
|
||||
* 1. 应用类型为 Servlet;
|
||||
* 2. 配置项 "forgeboot.security.authorize.api-key.enabled" 为 true。
|
||||
*
|
||||
* @property securityAuthorizeProperties 安全授权配置属性,用于获取 API 密钥相关路径等信息
|
||||
* @since 2025-06-25 13:41:56
|
||||
* @author gewuyou
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
|
||||
@ConditionalOnProperty(
|
||||
prefix = "forgeboot.security.authorize.api-key",
|
||||
name = ["enabled"],
|
||||
havingValue = "true",
|
||||
matchIfMissing = false
|
||||
)
|
||||
class ServletApiKeySecurityAutoConfiguration(
|
||||
private val securityAuthorizeProperties: SecurityAuthorizeProperties,
|
||||
) {
|
||||
/**
|
||||
* 创建 API 密钥认证过滤器 Bean。
|
||||
*
|
||||
* 该方法在 Spring 容器中尚不存在同名 Bean 的情况下,
|
||||
* 构建一个使用指定认证管理器的 ApiKeyAuthenticationFilter 实例。
|
||||
*
|
||||
* @param authenticationManager 认证管理器,用于执行认证逻辑
|
||||
* @return 返回构建完成的 ApiKeyAuthenticationFilter 实例
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(name = ["apiKeyAuthenticationFilter"])
|
||||
fun apiKeyAuthenticationFilter(
|
||||
authenticationManager: AuthenticationManager,
|
||||
): Filter {
|
||||
return ApiKeyAuthenticationFilter(authenticationManager)
|
||||
}
|
||||
|
||||
/**
|
||||
* 提供一个用于自定义 HTTP 安全配置的 API 密钥安全自定义器 Bean。
|
||||
*
|
||||
* 如果容器中尚不存在同名 Bean,则创建并返回 ApiKeyHttpSecurityCustomizer 实例。
|
||||
* 此自定义器将注入的认证提供者和过滤器用于构建定制化的安全配置。
|
||||
*
|
||||
* @param apiKeyAuthenticationProvider 注入已配置的认证提供者,用于安全链构建
|
||||
* @param apiKeyAuthenticationFilter 注入已配置的认证过滤器,用于请求处理
|
||||
* @return 返回 HttpSecurityCustomizer 的具体实现对象
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
fun apiKeyHttpSecurityCustomizer(
|
||||
@Qualifier("apiKeyAuthenticationFilter")
|
||||
apiKeyAuthenticationFilter: Filter,
|
||||
): HttpSecurityCustomizer {
|
||||
return ApiKeyHttpSecurityCustomizer(apiKeyAuthenticationFilter)
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建默认的安全过滤链,适用于 Servlet 编程模型。
|
||||
*
|
||||
* 此方法基于配置的路径模式构建一个复合请求匹配器,并通过注册器创建对应的安全过滤链。
|
||||
* 过滤链根据配置决定是否使用授权管理器进行访问控制。
|
||||
*
|
||||
* @param registrar 安全过滤链注册器,用于构建和管理过滤链
|
||||
* @param http Spring Security 的 HttpSecurity 配置对象
|
||||
* @param authorizeManager 授权管理器,用于在启用授权管理时定义访问策略
|
||||
* @return 构建完成的安全过滤链实例
|
||||
*/
|
||||
@Bean(name = ["defaultApiKeySecurityFilterChain"])
|
||||
fun defaultApiKeySecurityFilterChain(
|
||||
registrar: SecurityFilterChainRegistrar,
|
||||
http: HttpSecurity,
|
||||
authorizeManager: AuthorizationManager<RequestAuthorizationContext>
|
||||
): SecurityFilterChain {
|
||||
// 从配置中获取 API 密钥适用的路径模式(如:["/api/**", "/open/**"])
|
||||
val patterns = securityAuthorizeProperties.apiKey.pathPatterns
|
||||
|
||||
// 将每个路径模式转换为 AntPathRequestMatcher 实例
|
||||
val matchers = patterns.map { AntPathRequestMatcher(it) }
|
||||
|
||||
// 使用 OrRequestMatcher 组合所有路径匹配规则,实现多路径匹配支持
|
||||
val combinedMatcher = OrRequestMatcher(matchers)
|
||||
|
||||
// 调用注册器构建安全链,指定链 ID、HttpSecurity 对象和请求匹配器
|
||||
return registrar.buildChain(
|
||||
SecurityConstants.API_KEY_CHAIN_ID,
|
||||
http,
|
||||
combinedMatcher
|
||||
) { config ->
|
||||
if (securityAuthorizeProperties.apiKey.useAuthorizationManager) {
|
||||
// 启用授权管理器时,配置请求通过指定的 authorizeManager 进行访问控制
|
||||
config.authorizeHttpRequests {
|
||||
it.anyRequest().access(authorizeManager)
|
||||
}
|
||||
} else {
|
||||
// 禁用授权管理器时,要求所有请求必须经过身份验证
|
||||
config.authorizeHttpRequests {
|
||||
it.anyRequest().authenticated()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,19 +1,24 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.autoconfigure
|
||||
package com.gewuyou.forgeboot.security.authorize.autoconfigure.servlet
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.gewuyou.forgeboot.security.authorize.api.config.SecurityAuthorizeProperties
|
||||
import com.gewuyou.forgeboot.security.authorize.api.manager.AccessManager
|
||||
import com.gewuyou.forgeboot.security.authorize.api.resolver.PermissionResolver
|
||||
import com.gewuyou.forgeboot.security.authorize.impl.adapter.DynamicAuthorizationManagerAdapter
|
||||
import com.gewuyou.forgeboot.security.authorize.impl.builder.StatelessSecurityFilterChainRegistrar
|
||||
import com.gewuyou.forgeboot.security.authorize.impl.handler.AuthorizationExceptionHandler
|
||||
import com.gewuyou.forgeboot.security.core.common.builder.SecurityFilterChainRegistrar
|
||||
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.ConditionalOnProperty
|
||||
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
|
||||
@ -28,11 +33,26 @@ import org.springframework.security.web.util.matcher.AnyRequestMatcher
|
||||
* @author gewuyou
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnProperty(name = ["spring.main.web-application-type"], havingValue = "servlet", matchIfMissing = true)
|
||||
@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 编程模型
|
||||
*
|
||||
@ -42,13 +62,13 @@ class ServletAuthorizeSecurityConfiguration(
|
||||
* @throws Exception 构建过程中可能抛出的异常
|
||||
*/
|
||||
@Bean(name = ["defaultSecurityFilterChain"])
|
||||
@ConditionalOnBean(SecurityFilterChainRegistrar::class)
|
||||
@ConditionalOnBean
|
||||
@Throws(Exception::class)
|
||||
fun defaultSecurityFilterChain(
|
||||
registrar: SecurityFilterChainRegistrar,
|
||||
http: HttpSecurity,
|
||||
): SecurityFilterChain = registrar.buildChain(
|
||||
"default",
|
||||
SecurityConstants.DEFAULT_CHAIN_ID,
|
||||
http,
|
||||
AnyRequestMatcher.INSTANCE
|
||||
) { config ->
|
||||
@ -0,0 +1,133 @@
|
||||
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.ApiKeyServerHttpSecurityCustomizer
|
||||
import com.gewuyou.forgeboot.security.authorize.impl.webflux.filter.ApiKeyReactiveAuthenticationFilter
|
||||
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
|
||||
|
||||
/**
|
||||
* 反应式 API 密钥安全自动配置
|
||||
*
|
||||
* 该配置类负责在 WebFlux 环境下启用 API Key 认证机制。
|
||||
* 仅在满足以下条件时生效:
|
||||
* - 应用类型为 REACTIVE(反应式应用)
|
||||
* - 配置项 `forgeboot.security.authorize.api-key.enabled` 被设置为 true
|
||||
*
|
||||
* @property securityAuthorizeProperties 安全授权配置属性,用于获取 API Key 的路径匹配规则等信息
|
||||
* @since 2025-06-25 21:04:37
|
||||
* @author gewuyou
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
|
||||
@ConditionalOnProperty(
|
||||
prefix = "forgeboot.security.authorize.api-key",
|
||||
name = ["enabled"],
|
||||
havingValue = "true",
|
||||
matchIfMissing = false
|
||||
)
|
||||
class ReactiveApiKeySecurityAutoConfiguration(
|
||||
private val securityAuthorizeProperties: SecurityAuthorizeProperties
|
||||
) {
|
||||
|
||||
/**
|
||||
* 创建 API Key 反应式认证过滤器 Bean
|
||||
*
|
||||
* 该过滤器用于处理传入请求的 API Key 认证逻辑。
|
||||
* 如果容器中尚未定义名为 "apiKeyReactiveAuthenticationFilter" 的 Bean,则创建此 Bean。
|
||||
*
|
||||
* @param reactiveAuthenticationManager 反应式认证管理器,用于执行认证操作
|
||||
* @return 构建完成的 WebFilter 实例
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(name = ["apiKeyReactiveAuthenticationFilter"])
|
||||
fun apiKeyAuthenticationFilter(
|
||||
reactiveAuthenticationManager: ReactiveAuthenticationManager
|
||||
): WebFilter {
|
||||
return ApiKeyReactiveAuthenticationFilter(reactiveAuthenticationManager)
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建并注册 ServerHttpSecurityCustomizer 的 Bean,用于定制 API Key 安全配置。
|
||||
*
|
||||
* 此方法定义了一个用于构建 Spring Security 过滤器链时插入 API Key 认证逻辑的自定义器。
|
||||
* 仅当容器中尚未存在相同类型的 Bean 时,才会创建此 Bean。
|
||||
*
|
||||
* @param apiKeyReactiveAuthenticationFilter 使用指定名称从 Spring 容器中注入的 API Key 反应式认证过滤器 Bean。
|
||||
* 该过滤器负责处理实际的 API Key 认证逻辑。
|
||||
*
|
||||
* @return 构建完成的 ApiKeyServerHttpSecurityCustomizer 实例,用于在安全配置中添加 API Key 相关逻辑。
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
fun apiKeyServerHttpSecurityCustomizer(
|
||||
@Qualifier("apiKeyReactiveAuthenticationFilter")
|
||||
apiKeyReactiveAuthenticationFilter: WebFilter,
|
||||
): ServerHttpSecurityCustomizer {
|
||||
return ApiKeyServerHttpSecurityCustomizer(apiKeyReactiveAuthenticationFilter)
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建并注册基于 API Key 认证的 WebFlux 安全过滤器链。
|
||||
*
|
||||
* 该方法利用 SecurityWebFilterChainRegistrar 注册一个具有路径匹配规则的安全过滤器链,
|
||||
* 仅对符合配置中指定路径模式的请求生效,并要求通过 API Key 认证。
|
||||
*
|
||||
* @param registrar 用于注册和构建安全过滤器链的核心工具类,负责链的组装过程。
|
||||
* @param http Spring Security 提供的 ServerHttpSecurity 实例,用于构建 HTTP 安全配置。
|
||||
* @param reactiveAuthorizationManager 反应式授权管理器,用于在使用授权管理逻辑时提供访问控制。
|
||||
* @return 构建完成的 SecurityWebFilterChain 实例,表示定义好的安全过滤器链。
|
||||
*
|
||||
* 重要逻辑说明:
|
||||
* 1. patterns: 从配置中获取 API Key 的路径匹配规则;
|
||||
* 2. matchers: 将每个路径转换为 ServerWebExchangeMatcher 实例;
|
||||
* 3. combinedMatcher: 综合所有 matcher,生成复合的匹配规则;
|
||||
* 4. buildChain: 利用 registrar 构建过滤器链,并根据 useAuthorizationManager 配置决定采用何种认证方式:
|
||||
* - 若启用 authorizationManager,则通过 access 方法设置自定义的授权逻辑;
|
||||
* - 否则直接要求请求必须经过认证。
|
||||
*/
|
||||
@Bean(name = ["defaultApiKeySecurityWebFilterChain"])
|
||||
fun defaultApiKeySecurityWebFilterChain(
|
||||
registrar: SecurityWebFilterChainRegistrar,
|
||||
http: ServerHttpSecurity,
|
||||
reactiveAuthorizationManager: ReactiveAuthorizationManager<AuthorizationContext>
|
||||
): SecurityWebFilterChain {
|
||||
val patterns = securityAuthorizeProperties.apiKey.pathPatterns
|
||||
val matchers = patterns.map { PathPatternParserServerWebExchangeMatcher(it) }
|
||||
val combinedMatcher: ServerWebExchangeMatcher =
|
||||
ServerWebExchangeMatchers.matchers(*matchers.toTypedArray())
|
||||
return registrar.buildChain(
|
||||
SecurityConstants.API_KEY_CHAIN_ID,
|
||||
http,
|
||||
combinedMatcher
|
||||
) { config ->
|
||||
if (securityAuthorizeProperties.apiKey.useAuthorizationManager) {
|
||||
config.authorizeExchange {
|
||||
it.anyExchange().access(reactiveAuthorizationManager)
|
||||
}
|
||||
} else {
|
||||
config.authorizeExchange {
|
||||
it.anyExchange().authenticated()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,26 +1,32 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.autoconfigure
|
||||
package com.gewuyou.forgeboot.security.authorize.autoconfigure.webflux
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.gewuyou.forgeboot.security.authorize.api.config.SecurityAuthorizeProperties
|
||||
import com.gewuyou.forgeboot.security.authorize.api.manager.AccessManager
|
||||
import com.gewuyou.forgeboot.security.authorize.api.resolver.PermissionResolver
|
||||
import com.gewuyou.forgeboot.security.authorize.impl.adapter.DynamicReactiveAuthorizationManagerAdapter
|
||||
import com.gewuyou.forgeboot.security.authorize.impl.builder.StatelessSecurityWebFilterChainRegistrar
|
||||
import com.gewuyou.forgeboot.security.authorize.impl.handler.ReactiveAuthorizationExceptionHandler
|
||||
import com.gewuyou.forgeboot.security.core.common.builder.SecurityWebFilterChainRegistrar
|
||||
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.ConditionalOnProperty
|
||||
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.anyExchange
|
||||
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers
|
||||
|
||||
/**
|
||||
* 反应式授权配置
|
||||
@ -31,7 +37,7 @@ import org.springframework.security.web.server.util.matcher.ServerWebExchangeMat
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableWebFluxSecurity
|
||||
@ConditionalOnProperty(name = ["spring.main.web-application-type"], havingValue = "reactive")
|
||||
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
|
||||
class ReactiveAuthorizeSecurityConfiguration(
|
||||
private val accessManager: AccessManager,
|
||||
private val permissionResolver: PermissionResolver,
|
||||
@ -54,9 +60,9 @@ class ReactiveAuthorizeSecurityConfiguration(
|
||||
http: ServerHttpSecurity,
|
||||
): SecurityWebFilterChain = registrar
|
||||
.buildChain(
|
||||
"default",
|
||||
SecurityConstants.DEFAULT_CHAIN_ID,
|
||||
http,
|
||||
anyExchange()
|
||||
ServerWebExchangeMatchers.anyExchange()
|
||||
) { it: ServerHttpSecurity ->
|
||||
it.authorizeExchange {
|
||||
it.anyExchange().denyAll()
|
||||
@ -93,6 +99,31 @@ class ReactiveAuthorizeSecurityConfiguration(
|
||||
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)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 无状态安全过滤链注册器
|
||||
* 创建并返回一个无状态的安全过滤链注册器,用于注册需要无状态处理的安全过滤链。
|
||||
@ -1,4 +1,7 @@
|
||||
com.gewuyou.forgeboot.security.authorize.autoconfigure.ForgeSecurityAuthorizeCoreConfiguration
|
||||
com.gewuyou.forgeboot.security.authorize.autoconfigure.ReactiveAuthorizeSecurityConfiguration
|
||||
com.gewuyou.forgeboot.security.authorize.autoconfigure.ForgeSecurityAuthorizeAutoConfiguration
|
||||
com.gewuyou.forgeboot.security.authorize.autoconfigure.ServletAuthorizeSecurityConfiguration
|
||||
com.gewuyou.forgeboot.security.authorize.autoconfigure.core.ForgeSecurityAuthorizeCoreConfiguration
|
||||
com.gewuyou.forgeboot.security.authorize.autoconfigure.core.ApiKeySecurityCoreAutoConfiguration
|
||||
com.gewuyou.forgeboot.security.authorize.autoconfigure.webflux.ReactiveAuthorizeSecurityConfiguration
|
||||
com.gewuyou.forgeboot.security.authorize.autoconfigure.webflux.ReactiveApiKeySecurityAutoConfiguration
|
||||
com.gewuyou.forgeboot.security.authorize.autoconfigure.servlet.ServletAuthorizeSecurityConfiguration
|
||||
com.gewuyou.forgeboot.security.authorize.autoconfigure.servlet.ServletApiKeySecurityAutoConfiguration
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.aspect
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.core.aspect
|
||||
|
||||
import com.gewuyou.forgeboot.security.authorize.api.annotations.RequiresPermission
|
||||
import com.gewuyou.forgeboot.security.authorize.api.manager.AccessManager
|
||||
import com.gewuyou.forgeboot.security.authorize.api.strategy.AuthorizationStrategy
|
||||
import com.gewuyou.forgeboot.security.authorize.impl.resolver.SpELResolver
|
||||
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
|
||||
@ -1,8 +1,8 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.manager
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.core.manager
|
||||
|
||||
import com.gewuyou.forgeboot.security.authorize.api.manager.AccessManager
|
||||
import com.gewuyou.forgeboot.security.authorize.api.provider.PermissionProvider
|
||||
import com.gewuyou.forgeboot.security.authorize.api.strategy.AuthorizationStrategy
|
||||
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
|
||||
|
||||
/**
|
||||
@ -1,7 +1,7 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.provider
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.core.provider
|
||||
|
||||
import com.gewuyou.forgeboot.core.extension.log
|
||||
import com.gewuyou.forgeboot.security.authorize.api.provider.PermissionProvider
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.provider.PermissionProvider
|
||||
import org.springframework.security.core.Authentication
|
||||
|
||||
/**
|
||||
@ -0,0 +1,57 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.core.provider
|
||||
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.service.ApiKeyService
|
||||
import com.gewuyou.forgeboot.security.core.common.token.ApiKeyAuthenticationToken
|
||||
import org.springframework.security.authentication.AuthenticationProvider
|
||||
import org.springframework.security.core.Authentication
|
||||
|
||||
/**
|
||||
* API 密钥身份验证提供程序
|
||||
*
|
||||
* 该类实现 Spring Security 的 AuthenticationProvider 接口,用于处理基于 API Key 的身份验证流程。
|
||||
*
|
||||
* @property apiKeyService 用于校验 API Key 并获取用户信息和权限的服务组件
|
||||
* @constructor 创建一个 ApiKeyAuthenticationProvider 实例
|
||||
*
|
||||
* @since 2025-06-25 13:09:43
|
||||
* @author gewuyou
|
||||
*/
|
||||
class ApiKeyAuthenticationProvider(
|
||||
private val apiKeyService: ApiKeyService
|
||||
) : AuthenticationProvider {
|
||||
|
||||
/**
|
||||
* 执行身份验证操作
|
||||
*
|
||||
* 将传入的 Authentication 对象转换为 ApiKeyAuthenticationToken,
|
||||
* 然后使用 apiKeyService 校验 API Key 并获取相关用户信息和权限。
|
||||
*
|
||||
* @param authentication 包含 API Key 的身份验证请求对象
|
||||
* @return 返回已认证的 Authentication 对象
|
||||
*/
|
||||
override fun authenticate(authentication: Authentication): Authentication {
|
||||
val token = authentication as ApiKeyAuthenticationToken
|
||||
val keyInfo = apiKeyService.validate(token.apiKey)
|
||||
|
||||
return ApiKeyAuthenticationToken(
|
||||
token.apiKey,
|
||||
keyInfo.principal,
|
||||
keyInfo.authorities
|
||||
).apply {
|
||||
isAuthenticated = true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断此 Provider 是否支持给定的身份验证类型
|
||||
*
|
||||
* 用于确定当前 Provider 是否可以处理指定的 Authentication 类型。
|
||||
* 此方法被调用时会检查是否为 ApiKeyAuthenticationToken 或其子类。
|
||||
*
|
||||
* @param authentication 要检查的身份验证类
|
||||
* @return 如果支持则返回 true,否则返回 false
|
||||
*/
|
||||
override fun supports(authentication: Class<*>): Boolean {
|
||||
return ApiKeyAuthenticationToken::class.java.isAssignableFrom(authentication)
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.resolver
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.core.resolver
|
||||
|
||||
import com.gewuyou.forgeboot.security.authorize.api.resolver.PermissionResolver
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.resolver.PermissionResolver
|
||||
|
||||
/**
|
||||
* 默认权限解析程序
|
||||
@ -1,4 +1,4 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.resolver
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.core.resolver
|
||||
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory
|
||||
import org.springframework.context.expression.BeanFactoryResolver
|
||||
@ -1,7 +1,7 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.strategy
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.core.strategy
|
||||
|
||||
import com.gewuyou.forgeboot.security.authorize.api.provider.PermissionProvider
|
||||
import com.gewuyou.forgeboot.security.authorize.api.strategy.AuthorizationStrategy
|
||||
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
|
||||
|
||||
/**
|
||||
@ -1,10 +1,10 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.adapter
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.servlet.adapter
|
||||
|
||||
import com.gewuyou.forgeboot.core.extension.log
|
||||
import com.gewuyou.forgeboot.security.authorize.api.manager.AccessManager
|
||||
import com.gewuyou.forgeboot.security.authorize.api.resolver.PermissionResolver
|
||||
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.authorization.AuthorizationManager
|
||||
import org.springframework.security.core.Authentication
|
||||
import org.springframework.security.web.access.intercept.RequestAuthorizationContext
|
||||
import java.util.function.Supplier
|
||||
@ -20,7 +20,7 @@ import java.util.function.Supplier
|
||||
class DynamicAuthorizationManagerAdapter(
|
||||
private val accessManager: AccessManager,
|
||||
private val permissionResolver: PermissionResolver,
|
||||
) : AuthorizationManager<RequestAuthorizationContext> {
|
||||
) : DynamicAuthorizationManager<RequestAuthorizationContext> {
|
||||
|
||||
/**
|
||||
* 执行权限校验的核心方法。
|
||||
@ -0,0 +1,55 @@
|
||||
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
|
||||
|
||||
/**
|
||||
* API 密钥 HTTP 安全定制器
|
||||
*
|
||||
* 用于为基于 API 密钥的身份验证机制定制 Spring Security 的 HTTP 安全配置。
|
||||
* 该类实现了 HttpSecurityCustomizer 接口,能够根据指定的安全链 ID 决定是否启用当前的认证逻辑,
|
||||
* 并负责将 API 密钥身份验证过滤器和提供者注入到安全配置中。
|
||||
*
|
||||
* @property apiKeyAuthenticationProvider 提供 API 密钥身份验证逻辑的认证提供者
|
||||
* @property apiKeyAuthenticationFilter 处理 API 密钥身份验证请求的过滤器实例
|
||||
* @since 2025-06-25 16:09:38
|
||||
* @author gewuyou
|
||||
*/
|
||||
class ApiKeyHttpSecurityCustomizer(
|
||||
private val apiKeyAuthenticationFilter: Filter
|
||||
) : HttpSecurityCustomizer {
|
||||
|
||||
/**
|
||||
* 判断当前定制器是否支持处理指定的安全链配置
|
||||
*
|
||||
* 此方法用于标识该定制器是否适用于特定的安全链配置。
|
||||
* 实现类应根据 chainId 参数决定是否启用此定制器的逻辑。
|
||||
*
|
||||
* @param chainId 安全链的唯一标识符,用于区分不同的安全配置场景
|
||||
* @return Boolean 返回 true 表示支持该 chainId,否则不支持
|
||||
*/
|
||||
override fun supports(chainId: String): Boolean {
|
||||
return SecurityConstants.API_KEY_CHAIN_ID == chainId
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行安全配置的定制逻辑
|
||||
*
|
||||
* 将 API 密钥身份验证相关的组件注册到 Spring Security 流程中。
|
||||
* 包括:
|
||||
* - 注册认证提供者(apiKeyAuthenticationProvider)
|
||||
* - 在请求处理流程中插入 ApiKeyAuthenticationFilter 过滤器
|
||||
* 该过滤器会在 UsernamePasswordAuthenticationFilter 前执行
|
||||
*
|
||||
* @param http 用于构建 HTTP 安全策略的 HttpSecurity 实例
|
||||
* 通过此参数可添加或修改安全规则,如认证、授权等
|
||||
*/
|
||||
override fun customize(http: HttpSecurity) {
|
||||
// 配置安全逻辑:注册认证提供者并将 API 密钥过滤器插入到过滤器链中的合适位置
|
||||
http
|
||||
.addFilterBefore(apiKeyAuthenticationFilter, UsernamePasswordAuthenticationFilter::class.java)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.servlet.filter
|
||||
|
||||
import com.gewuyou.forgeboot.security.core.common.constants.SecurityConstants
|
||||
import com.gewuyou.forgeboot.security.core.common.token.ApiKeyAuthenticationToken
|
||||
import jakarta.servlet.FilterChain
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import jakarta.servlet.http.HttpServletResponse
|
||||
import org.springframework.security.authentication.AuthenticationManager
|
||||
import org.springframework.security.core.context.SecurityContextHolder
|
||||
import org.springframework.web.filter.OncePerRequestFilter
|
||||
|
||||
/**
|
||||
* API 密钥身份验证筛选器
|
||||
* 用于处理基于API密钥的身份验证流程,继承自OncePerRequestFilter以确保每个请求只被过滤一次。
|
||||
*
|
||||
* @param authenticationManager 身份验证管理器,用于执行实际的身份验证操作
|
||||
* @since 2025-06-25 13:34:47
|
||||
* @author gewuyou
|
||||
*/
|
||||
class ApiKeyAuthenticationFilter(
|
||||
private val authenticationManager: AuthenticationManager
|
||||
) : OncePerRequestFilter() {
|
||||
|
||||
/**
|
||||
* 执行内部过滤逻辑
|
||||
* 从请求头中提取API密钥并进行身份验证
|
||||
*
|
||||
* @param request 当前HTTP请求
|
||||
* @param response 当前HTTP响应
|
||||
* @param chain 过滤器链
|
||||
*/
|
||||
override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, chain: FilterChain) {
|
||||
// 从请求头中获取Authorization字段
|
||||
val header = request.getHeader(SecurityConstants.AUTHORIZATION_HEADER)
|
||||
|
||||
// 检查是否为Bearer类型认证信息
|
||||
if (header?.startsWith(SecurityConstants.BEARER_PREFIX) == true) {
|
||||
// 提取并清理API密钥
|
||||
val apiKey = header.removePrefix(SecurityConstants.BEARER_PREFIX).trim()
|
||||
|
||||
// 创建认证令牌
|
||||
val token = ApiKeyAuthenticationToken(apiKey, null)
|
||||
|
||||
// 执行认证并存储认证结果到安全上下文中
|
||||
val authResult = authenticationManager.authenticate(token)
|
||||
SecurityContextHolder.getContext().authentication = authResult
|
||||
}
|
||||
// 继续执行过滤器链
|
||||
chain.doFilter(request, response)
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,8 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.handler
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.servlet.handler
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.gewuyou.forgeboot.core.extension.log
|
||||
import com.gewuyou.forgeboot.security.authorize.api.config.SecurityAuthorizeProperties
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.config.SecurityAuthorizeProperties
|
||||
import com.gewuyou.forgeboot.webmvc.dto.R
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import jakarta.servlet.http.HttpServletResponse
|
||||
@ -1,8 +1,8 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.builder
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.servlet.registrar
|
||||
|
||||
import com.gewuyou.forgeboot.security.core.common.builder.SecurityFilterChainRegistrar
|
||||
import com.gewuyou.forgeboot.security.core.common.customizer.HttpSecurityCustomizer
|
||||
import com.gewuyou.forgeboot.security.core.common.extension.cleanUnNeedConfig
|
||||
import com.gewuyou.forgeboot.security.core.common.registrar.SecurityFilterChainRegistrar
|
||||
import com.gewuyou.forgeboot.security.core.common.wrapper.SecurityFilterChainWrapper
|
||||
import org.springframework.http.HttpMethod
|
||||
import org.springframework.security.authorization.AuthorizationManager
|
||||
@ -45,7 +45,7 @@ class StatelessSecurityFilterChainRegistrar(
|
||||
matcher: RequestMatcher,
|
||||
config: (HttpSecurity) -> Unit,
|
||||
): SecurityFilterChainWrapper {
|
||||
// 清除不必要的默认安全配置,优化无状态场景下的行为
|
||||
// 清除不必要默认安全配置,优化无状态场景下的行为
|
||||
// 设置请求匹配器以确定过滤器链适用范围
|
||||
// 配置 HTTP 请求的授权规则:
|
||||
// - 允许所有 OPTIONS 请求(通常用于跨域预检)
|
||||
@ -1,8 +1,8 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.adapter
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.webflux.adapter
|
||||
|
||||
import com.gewuyou.forgeboot.security.authorize.api.manager.AccessManager
|
||||
import com.gewuyou.forgeboot.security.authorize.api.manager.DynamicReactiveAuthorizationManager
|
||||
import com.gewuyou.forgeboot.security.authorize.api.resolver.PermissionResolver
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.manager.AccessManager
|
||||
import com.gewuyou.forgeboot.security.authorize.api.webflux.manager.DynamicReactiveAuthorizationManager
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.resolver.PermissionResolver
|
||||
import org.springframework.security.authorization.AuthorizationDecision
|
||||
import org.springframework.security.core.Authentication
|
||||
import org.springframework.security.web.server.authorization.AuthorizationContext
|
||||
@ -0,0 +1,46 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.webflux.customizer
|
||||
|
||||
import com.gewuyou.forgeboot.security.core.common.constants.SecurityConstants
|
||||
import com.gewuyou.forgeboot.security.core.common.customizer.ServerHttpSecurityCustomizer
|
||||
import org.springframework.security.config.web.server.SecurityWebFiltersOrder
|
||||
import org.springframework.security.config.web.server.ServerHttpSecurity
|
||||
import org.springframework.web.server.WebFilter
|
||||
|
||||
/**
|
||||
* API 密钥服务器 HTTP 安全定制器
|
||||
*
|
||||
* 该类用于在 Spring WebFlux 环境下基于 API 密钥进行认证的安全配置定制。
|
||||
* 它实现了 ServerHttpSecurityCustomizer 接口,能将自定义的认证逻辑集成到安全链中。
|
||||
*
|
||||
* @constructor
|
||||
* @param apiKeyReactiveAuthenticationFilter 自定义的 WebFilter 实现,用于执行 API 密钥认证逻辑
|
||||
*/
|
||||
class ApiKeyServerHttpSecurityCustomizer(
|
||||
private val apiKeyReactiveAuthenticationFilter: WebFilter,
|
||||
) : ServerHttpSecurityCustomizer {
|
||||
/**
|
||||
* 判断当前定制器是否支持处理指定的安全链配置
|
||||
*
|
||||
* 此方法用于标识该定制器是否适用于特定的安全链配置。
|
||||
* 实现类应根据 chainId 参数决定是否启用此定制器的逻辑。
|
||||
*
|
||||
* @param chainId 安全链的唯一标识符,用于区分不同的安全配置场景
|
||||
* @return Boolean 返回 true 表示支持该 chainId,否则不支持
|
||||
*/
|
||||
override fun supports(chainId: String): Boolean {
|
||||
return SecurityConstants.API_KEY_CHAIN_ID == chainId
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义 ServerHttpSecurity 配置的方法
|
||||
*
|
||||
* 此方法由框架调用,允许开发者插入自定义的安全配置逻辑。
|
||||
* 方法参数提供了 ServerHttpSecurity 实例,可用于链式配置。
|
||||
*
|
||||
* @param http ServerHttpSecurity 实例,用于构建 WebFlux 安全配置
|
||||
*/
|
||||
override fun customize(http: ServerHttpSecurity) {
|
||||
// 将过滤器添加到安全链中的认证位置
|
||||
http.addFilterAt(apiKeyReactiveAuthenticationFilter, SecurityWebFiltersOrder.AUTHENTICATION)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,66 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.webflux.filter
|
||||
|
||||
import com.gewuyou.forgeboot.security.core.common.constants.SecurityConstants
|
||||
import com.gewuyou.forgeboot.security.core.common.token.ApiKeyAuthenticationToken
|
||||
import org.springframework.http.HttpHeaders
|
||||
import org.springframework.security.authentication.ReactiveAuthenticationManager
|
||||
import org.springframework.security.core.Authentication
|
||||
import org.springframework.security.web.server.authentication.AuthenticationWebFilter
|
||||
import org.springframework.security.web.server.authentication.ServerAuthenticationConverter
|
||||
import org.springframework.web.server.ServerWebExchange
|
||||
import reactor.core.publisher.Mono
|
||||
|
||||
/**
|
||||
* API 密钥反应式身份验证过滤器
|
||||
*
|
||||
* 用于在 WebFlux 环境下通过 API 密钥进行身份验证的过滤器。
|
||||
* 它继承自 [AuthenticationWebFilter],并使用 [ApiKeyServerAuthenticationConverter]
|
||||
* 将请求中的 API 密钥转换为认证对象 [ApiKeyAuthenticationToken]。
|
||||
*
|
||||
* @property authenticationManager 身份验证管理器,用于处理身份验证请求
|
||||
* @since 2025-06-25 16:46:13
|
||||
* @author gewuyou
|
||||
*/
|
||||
class ApiKeyReactiveAuthenticationFilter(
|
||||
authenticationManager: ReactiveAuthenticationManager
|
||||
) : AuthenticationWebFilter(authenticationManager) {
|
||||
|
||||
/**
|
||||
* 初始化代码块,设置当前过滤器使用的身份验证转换器。
|
||||
*
|
||||
* 此处将默认的转换逻辑替换为基于 API 密钥的身份验证转换器,
|
||||
* 该转换器负责从请求头中提取并解析 API 密钥。
|
||||
*/
|
||||
init {
|
||||
setServerAuthenticationConverter(ApiKeyServerAuthenticationConverter())
|
||||
}
|
||||
|
||||
/**
|
||||
* 基于 API 密钥的身份验证转换器
|
||||
*
|
||||
* 实现了 [ServerAuthenticationConverter] 接口,负责从 [ServerWebExchange] 中提取 API 密钥,
|
||||
* 并将其转换为对应的认证对象 [ApiKeyAuthenticationToken]。
|
||||
*/
|
||||
private class ApiKeyServerAuthenticationConverter : ServerAuthenticationConverter {
|
||||
|
||||
/**
|
||||
* 将传入的请求上下文转换为认证对象。
|
||||
*
|
||||
* 此方法尝试从请求头中获取 `Authorization` 字段,并检查其是否以指定的前缀开头。
|
||||
* 如果匹配,则移除前缀并提取出 API 密钥,最终构造一个未认证的 [ApiKeyAuthenticationToken] 对象。
|
||||
*
|
||||
* @param exchange 当前的服务器 Web 交换对象,包含请求信息
|
||||
* @return 返回一个 [Mono<Authentication>?] 类型的对象,如果成功提取 API 密钥则返回包含认证对象的 Mono;
|
||||
* 否则返回空的 Mono。
|
||||
*/
|
||||
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(ApiKeyAuthenticationToken(apiKey, null))
|
||||
} else {
|
||||
Mono.empty()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,8 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.handler
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.webflux.handler
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.gewuyou.forgeboot.core.extension.log
|
||||
import com.gewuyou.forgeboot.security.authorize.api.config.SecurityAuthorizeProperties
|
||||
import com.gewuyou.forgeboot.security.authorize.api.core.config.SecurityAuthorizeProperties
|
||||
import com.gewuyou.forgeboot.webmvc.dto.R
|
||||
import org.springframework.http.HttpHeaders
|
||||
import org.springframework.http.HttpStatus
|
||||
@ -1,8 +1,8 @@
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.builder
|
||||
package com.gewuyou.forgeboot.security.authorize.impl.webflux.registrar
|
||||
|
||||
import com.gewuyou.forgeboot.security.core.common.builder.SecurityWebFilterChainRegistrar
|
||||
import com.gewuyou.forgeboot.security.core.common.customizer.ServerHttpSecurityCustomizer
|
||||
import com.gewuyou.forgeboot.security.core.common.extension.cleanUnNeedConfig
|
||||
import com.gewuyou.forgeboot.security.core.common.registrar.SecurityWebFilterChainRegistrar
|
||||
import com.gewuyou.forgeboot.security.core.common.wrapper.SecurityWebFilterChainWrapper
|
||||
import org.springframework.http.HttpMethod
|
||||
import org.springframework.security.authorization.ReactiveAuthorizationManager
|
||||
@ -0,0 +1,17 @@
|
||||
package com.gewuyou.forgeboot.security.core.authorize.entities
|
||||
|
||||
import org.springframework.security.core.GrantedAuthority
|
||||
|
||||
/**
|
||||
* API 密钥主体,用于存储认证后的API密钥相关信息。
|
||||
*
|
||||
* @property principal 认证主体标识,通常是API密钥字符串
|
||||
* @property authorities 与此API密钥关联的权限列表
|
||||
*
|
||||
* @since 2025-06-25 13:11:37
|
||||
* @author gewuyou
|
||||
*/
|
||||
data class ApiKeyPrincipal (
|
||||
val principal: String,
|
||||
val authorities: List<GrantedAuthority>
|
||||
)
|
||||
@ -0,0 +1,31 @@
|
||||
package com.gewuyou.forgeboot.security.core.common.constants
|
||||
|
||||
/**
|
||||
* 安全相关常量定义
|
||||
*
|
||||
* 该对象存储与安全认证相关的通用常量,便于统一管理和维护。
|
||||
*
|
||||
* @since 2025-06-25 16:02:05
|
||||
* @author gewuyou
|
||||
*/
|
||||
object SecurityConstants {
|
||||
/**
|
||||
* HTTP请求头中用于携带身份凭证的字段名称
|
||||
*/
|
||||
const val AUTHORIZATION_HEADER = "Authorization"
|
||||
|
||||
/**
|
||||
* Bearer Token前缀,用于在请求头中标识Token类型
|
||||
*/
|
||||
const val BEARER_PREFIX = "Bearer "
|
||||
|
||||
/**
|
||||
* API密钥请求头字段名称,用于在请求头中携带API认证标识
|
||||
*/
|
||||
const val API_KEY_CHAIN_ID = "apiKey"
|
||||
|
||||
/**
|
||||
* 默认的API密钥标识
|
||||
*/
|
||||
const val DEFAULT_CHAIN_ID = "default"
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package com.gewuyou.forgeboot.security.core.common.builder
|
||||
package com.gewuyou.forgeboot.security.core.common.registrar
|
||||
|
||||
import com.gewuyou.forgeboot.security.core.common.wrapper.SecurityFilterChainWrapper
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
@ -1,4 +1,4 @@
|
||||
package com.gewuyou.forgeboot.security.core.common.builder
|
||||
package com.gewuyou.forgeboot.security.core.common.registrar
|
||||
|
||||
import com.gewuyou.forgeboot.security.core.common.wrapper.SecurityWebFilterChainWrapper
|
||||
import org.springframework.security.config.web.server.ServerHttpSecurity
|
||||
@ -0,0 +1,23 @@
|
||||
package com.gewuyou.forgeboot.security.core.common.token
|
||||
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken
|
||||
import org.springframework.security.core.GrantedAuthority
|
||||
|
||||
/**
|
||||
*API 密钥认证令牌
|
||||
*
|
||||
* @since 2025-06-25 13:06:54
|
||||
* @author gewuyou
|
||||
*/
|
||||
class ApiKeyAuthenticationToken(
|
||||
val apiKey: String,
|
||||
private val principal: Any?,
|
||||
private val authorities: Collection<GrantedAuthority> = listOf()
|
||||
) : AbstractAuthenticationToken(authorities) {
|
||||
|
||||
override fun getCredentials(): Any = apiKey
|
||||
|
||||
override fun getPrincipal(): Any? = principal
|
||||
|
||||
override fun isAuthenticated(): Boolean = super.isAuthenticated
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user