Spring Webflux如何配置特定路径用HTTP Basic其余路径用JWT认证
实现思路
和Spring MVC的多配置逻辑一致,WebFlux安全体系也支持注册多个SecurityWebFilterChain Bean,通过@Order指定执行优先级即可:高优先级配置仅匹配/actuator/**路径,单独走HTTP Basic认证;低优先级配置处理剩余所有业务接口,复用原有JWT认证逻辑。
完整实现代码
import org.springframework.beans.factory.annotation.Value import org.springframework.boot.autoconfigure.security.SecurityProperties import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.core.Ordered import org.springframework.core.annotation.Order import org.springframework.http.HttpMethod import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity import org.springframework.security.config.web.server.ServerHttpSecurity import org.springframework.security.core.userdetails.MapReactiveUserDetailsService import org.springframework.security.core.userdetails.User import org.springframework.security.crypto.argon2.Argon2PasswordEncoder import org.springframework.security.crypto.password.PasswordEncoder import org.springframework.security.oauth2.server.resource.authentication.ReactiveJwtAuthenticationConverter import org.springframework.security.web.server.SecurityWebFilterChain import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers @EnableWebFluxSecurity @EnableReactiveMethodSecurity class SecurityConfig( val userService: UserService, // 注入配置项,可根据实际情况调整 @Value("\${management.endpoints.web.base-path:/actuator}") val managementPath: String, @Value("\${config.actuator.user.name}") val actuatorUser: String, @Value("\${config.actuator.user.password}") val actuatorPassword: String ) { /** * 高优先级配置:仅处理Actuator端点,走HTTP Basic认证 * Order数值越小优先级越高,此处设为最高优先级 */ @Bean @Order(Ordered.HIGHEST_PRECEDENCE) fun actuatorSecurityFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain { return http { // 限定仅匹配actuator所有路径,不拦截其他业务接口 securityMatcher(ServerWebExchangeMatchers.pathMatchers("$managementPath/**")) csrf { disable() } formLogin { disable() } // 开启HTTP Basic认证 httpBasic { } authorizeExchange { // 所有actuator端点需要有ACTUATOR角色才能访问 authorize(anyExchange, hasRole("ACTUATOR")) } // 禁用当前链的JWT认证,避免和Basic认证冲突 oauth2ResourceServer { disable() } } } /** * 低优先级配置:处理所有业务接口,走原有JWT认证逻辑 */ @Bean @Order(SecurityProperties.BASIC_AUTH_ORDER) fun apiSecurityFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain { return http { csrf { disable() } formLogin { disable() } httpBasic { disable() } authorizeExchange { authorize(ServerWebExchangeMatchers.pathMatchers(HttpMethod.OPTIONS, "/**"), permitAll) authorize(anyExchange, authenticated) } oauth2ResourceServer { jwt { jwtAuthenticationConverter = customConverter() } } } } /** * 响应式内存用户存储,存储Actuator专用认证账号 */ @Bean fun actuatorUserDetailsService(passwordEncoder: PasswordEncoder): MapReactiveUserDetailsService { val actuatorAccount = User.withUsername(actuatorUser) .password(passwordEncoder.encode(actuatorPassword)) .roles("ACTUATOR") .build() return MapReactiveUserDetailsService(actuatorAccount) } /** * 密码编码器,和原有MVC逻辑保持一致使用Argon2 */ @Bean fun passwordEncoder(): PasswordEncoder = Argon2PasswordEncoder() // 原有JWT转换逻辑保持不变即可 private fun customConverter(): ReactiveJwtAuthenticationConverter { // 原有实现逻辑 } }
关键注意事项
- 高优先级的Actuator配置必须加
securityMatcher限定匹配路径,否则会拦截所有请求 - WebFlux下的内存用户实现为
MapReactiveUserDetailsService,不可使用MVC体系下的非响应式用户存储组件 - 若需要开放部分actuator端点(如健康检查),可在Actuator配置的
authorizeExchange中单独配置permitAll规则
内容的提问来源于stack exchange,提问作者Stuck
相关产品推荐
相关产品推荐

