禁用执行器健康端点的 webflux(反应式)安全性
Posted
技术标签:
【中文标题】禁用执行器健康端点的 webflux(反应式)安全性【英文标题】:Disable webflux (reactive) security for actuator health endpoint 【发布时间】:2019-12-28 01:37:02 【问题描述】:我有一个包含 WebFlux、Health actuator 和 Spring security 的项目。我正在尝试构建自定义身份验证,但该身份验证也适用于健康执行器端点。如何禁用它?
根据文档,我实现了一个自定义 ServerSecurityContextRepository
,这是它看起来有点像的基本版本:
@Component
class MySecurityContextRepository: ServerSecurityContextRepository
override fun save(exchange: ServerWebExchange?, context: SecurityContext?) = Mono.empty()
override fun load(exchange: ServerWebExchange) = Mono.error(ResponseStatusException(HttpStatus.UNAUTHORIZED, "Access denied"))
根据文档,我不应该被要求做任何额外的配置来禁用健康端点上的身份验证。这是来自application.yml
的配置:
management:
metrics:
web:
server:
auto-time-requests: true
requests-metric-name: xxx-xxx-xxx
export:
statsd:
enabled: xxxx
host: xxxxxxxxxxxx
flavor: xxx
endpoint:
health:
enabled: true
endpoints:
web:
base-path: /application
这不起作用,因为我从 /application/health
端点看到了 401。所以我也将它添加到我的安全配置中:
@EnableWebFluxSecurity
class SecurityConfig @Autowired constructor(
private val myRepository: MySecurityContextRepository
)
@Bean
fun securityWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain
http.securityContextRepository(myRepository)
http.authorizeExchange()
.pathMatchers("/application/health").permitAll()
.anyExchange().permitAll()
http.cors().disable()
http.csrf().disable()
http.formLogin().disable()
return http.build()
尽管添加此操作 curl http://localhost:8080/application/health/
会导致 "name":"xxxxxx","message":"Unknown Error","response":"401 UNAUTHORIZED \"Access denied\""
并且状态代码也是 401
。如何禁用对我的健康端点的授权?
【问题讨论】:
【参考方案1】:所以在没有帮助之后,我开始查看源代码,结果发现ServerSecurityContextRepository
总是为HealthEndpoint
和InfoEndpoint
调用,所以我自己添加了跳过存储库中的身份验证检查的逻辑。您可以轻松做到:
val HEALTH_ENDPOINTS = EndpointRequest.to(HealthEndpoint::class.java, InfoEndpoint::class.java)
现在您可以执行以下操作:
return HEALTH_ENDPOINTS.matches(exchange).flatMap matches ->
if (matches.isMatch)
Mono.just(SecurityContextImpl(GuestAuthToken))
else
Mono.empty()
这样我就不会在我的存储库中硬编码任何路径。这并不理想,但可以完成工作。
【讨论】:
【参考方案2】:最好使用EndpointRequest 来匹配执行器端点,因为它会匹配您的配置。使用反应式导入(不是 servlet)。
application.yml:
management:
endpoint:
health:
enabled: true
endpoints:
web:
base-path: /application
WebSecurityConfig.java:
@Configuration
@EnableWebFluxSecurity
public class WebSecurityConfig
@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http)
return http.csrf().disable()
.authorizeExchange()
.matchers(EndpointRequest.to("health")).permitAll()
.and().build();
【讨论】:
【参考方案3】:关于 spring docu 29.2 WebFlux Security 你只需要添加:
import org.springframework.boot.autoconfigure.security.reactive.PathRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
@Configuration
public class WebFluxSecurityConfigurer
@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http)
return http
.authorizeExchange()
.pathMatchers("/status/**")
.permitAll().and()
.build();
不要忘记添加所有可能的路径,例如 ../health 和 ../health/ 或者使用通配符更好
【讨论】:
以上是关于禁用执行器健康端点的 webflux(反应式)安全性的主要内容,如果未能解决你的问题,请参考以下文章
Webflux,使用Websocket如何防止订阅两次反应式redis消息操作
Spring Webflux 2.4.2 - 执行器 /auditevents /httptrace /integrationgraph /sessions 端点上的 404