如何绕过spring webflux security中的一些url?
Posted
技术标签:
【中文标题】如何绕过spring webflux security中的一些url?【英文标题】:How to bypass some urls in spring webflux security? 【发布时间】:2021-08-15 16:12:56 【问题描述】:我有一个 spring webflux 应用程序并使用以下代码启用了 spring webflux 安全性:-
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http)
log.debug("Configuring tenant web security");
return http
.csrf().disable()
.authorizeExchange()
.pathMatchers("/actuator/**").permitAll()
.anyExchange().authenticated()
.and()
.addFilterAt(authenticationWebFilter(), SecurityWebFiltersOrder.AUTHENTICATION)
.addFilterAt(authorizationWebFilter(), SecurityWebFiltersOrder.AUTHORIZATION)
.build();
private AuthenticationWebFilter authenticationWebFilter()
AuthenticationWebFilter authenticationWebFilter = new AuthenticationWebFilter(
customAuthenticationManager);
authenticationWebFilter.setServerAuthenticationConverter(customAuthenticationConverter);
return authenticationWebFilter;
private AuthorizationWebFilter authorizationWebFilter()
return new AuthorizationWebFilter(customAuthorizationManager);
我想绕过代码中提到的执行器 url,但不知何故,它们仍然进入 ServerAuthenticationConverter
类,我已覆盖该类以解析标题。
我正在请求localhost:8082/actuator/health
,它仍在通过所有安全链。
我在这里做错了什么?
以下链接与此问题有关,但找不到任何有用的答案:- How to exclude a path from authentication in a spring based reactive application?
异常调试日志:-
2021-05-27 21:11:50.496 DEBUG 87018 --- [ctor-http-nio-3] io.netty.buffer.AbstractByteBuf : -Dio.netty.buffer.checkBounds: true
2021-05-27 21:11:50.497 DEBUG 87018 --- [ctor-http-nio-3] i.n.util.ResourceLeakDetectorFactory : Loaded default ResourceLeakDetector: io.netty.util.ResourceLeakDetector@1afad0f4
2021-05-27 21:11:50.510 DEBUG 87018 --- [ctor-http-nio-3] r.n.http.server.HttpServerOperations : [id: 0xdbf63e0b, L:/[0:0:0:0:0:0:0:1]:8082 - R:/[0:0:0:0:0:0:0:1]:53830] New http connection, requesting read
2021-05-27 21:11:50.510 DEBUG 87018 --- [ctor-http-nio-2] r.n.http.server.HttpServerOperations : [id: 0x3302bee3, L:/[0:0:0:0:0:0:0:1]:8082 - R:/[0:0:0:0:0:0:0:1]:53829] New http connection, requesting read
2021-05-27 21:11:50.510 DEBUG 87018 --- [ctor-http-nio-2] reactor.netty.transport.TransportConfig : [id: 0x3302bee3, L:/[0:0:0:0:0:0:0:1]:8082 - R:/[0:0:0:0:0:0:0:1]:53829] Initialized pipeline DefaultChannelPipeline(reactor.left.httpCodec = io.netty.handler.codec.http.HttpServerCodec), (reactor.left.httpTrafficHandler = reactor.netty.http.server.HttpTrafficHandler), (reactor.right.reactiveBridge = reactor.netty.channel.ChannelOperationsHandler)
2021-05-27 21:11:50.510 DEBUG 87018 --- [ctor-http-nio-3] reactor.netty.transport.TransportConfig : [id: 0xdbf63e0b, L:/[0:0:0:0:0:0:0:1]:8082 - R:/[0:0:0:0:0:0:0:1]:53830] Initialized pipeline DefaultChannelPipeline(reactor.left.httpCodec = io.netty.handler.codec.http.HttpServerCodec), (reactor.left.httpTrafficHandler = reactor.netty.http.server.HttpTrafficHandler), (reactor.right.reactiveBridge = reactor.netty.channel.ChannelOperationsHandler)
2021-05-27 21:11:50.516 DEBUG 87018 --- [ctor-http-nio-3] io.netty.util.Recycler : -Dio.netty.recycler.maxCapacityPerThread: 4096
2021-05-27 21:11:50.516 DEBUG 87018 --- [ctor-http-nio-3] io.netty.util.Recycler : -Dio.netty.recycler.maxSharedCapacityFactor: 2
2021-05-27 21:11:50.516 DEBUG 87018 --- [ctor-http-nio-3] io.netty.util.Recycler : -Dio.netty.recycler.linkCapacity: 16
2021-05-27 21:11:50.516 DEBUG 87018 --- [ctor-http-nio-3] io.netty.util.Recycler : -Dio.netty.recycler.ratio: 8
2021-05-27 21:11:50.516 DEBUG 87018 --- [ctor-http-nio-3] io.netty.util.Recycler : -Dio.netty.recycler.delayedQueue.ratio: 8
2021-05-27 21:11:50.542 DEBUG 87018 --- [ctor-http-nio-3] r.n.http.server.HttpServerOperations : [id: 0xdbf63e0b, L:/[0:0:0:0:0:0:0:1]:8082 - R:/[0:0:0:0:0:0:0:1]:53830] Increasing pending responses, now 1
2021-05-27 21:11:50.547 DEBUG 87018 --- [ctor-http-nio-3] reactor.netty.http.server.HttpServer : [id: 0xdbf63e0b, L:/[0:0:0:0:0:0:0:1]:8082 - R:/[0:0:0:0:0:0:0:1]:53830] Handler is being applied: org.springframework.http.server.reactive.ReactorHttpHandlerAdapter@60ba6618
2021-05-27 21:11:50.553 DEBUG 87018 --- [ctor-http-nio-3] o.s.w.s.adapter.HttpWebHandlerAdapter : [dbf63e0b-1] HTTP GET "/actuator/health"
2021-05-27 21:11:50.589 WARN 87018 --- [ctor-http-nio-3] c.r.c.a.c.e.RestWebExceptionHandler : Web request for uri http://localhost:8082/actuator/health failed with exception java.lang.IllegalArgumentException: X-Auth header is not present.
at com.demo.ceresgateway.app.config.security.CustomServerAuthenticationConverter.resolveHeaders(CustomServerAuthenticationConverter.java:61)
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ org.springframework.security.web.server.authentication.AuthenticationWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.context.ReactorContextWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.header.HttpHeaderWriterWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.config.web.server.ServerHttpSecurity$ServerWebExchangeReactorContextWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.WebFilterChainProxy [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ HTTP GET "/actuator/health" [ExceptionHandlingWebHandler]
Stack trace:
at com.demo.ceresgateway.app.config.security.CustomServerAuthenticationConverter.resolveHeaders(CustomServerAuthenticationConverter.java:61)
at com.demo.ceresgateway.app.config.security.CustomServerAuthenticationConverter.convert(CustomServerAuthenticationConverter.java:31)
at org.springframework.security.web.server.authentication.AuthenticationWebFilter.lambda$filter$2(AuthenticationWebFilter.java:112)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:125)
at reactor.core.publisher.FluxFilterFuseable$FilterFuseableSubscriber.onNext(FluxFilterFuseable.java:118)
at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2346)
at reactor.core.publisher.FluxFilterFuseable$FilterFuseableSubscriber.request(FluxFilterFuseable.java:191)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onSubscribe(MonoFlatMap.java:110)
at reactor.core.publisher.FluxFilterFuseable$FilterFuseableSubscriber.onSubscribe(FluxFilterFuseable.java:87)
at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:54)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:157)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:127)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:127)
at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1784)
at reactor.core.publisher.MonoFlatMap$FlatMapInner.onNext(MonoFlatMap.java:249)
at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1784)
at reactor.core.publisher.MonoCollectList$MonoCollectListSubscriber.onComplete(MonoCollectList.java:128)
at reactor.core.publisher.FluxIterable$IterableSubscription.fastPath(FluxIterable.java:360)
at reactor.core.publisher.FluxIterable$IterableSubscription.request(FluxIterable.java:225)
at reactor.core.publisher.MonoCollectList$MonoCollectListSubscriber.onSubscribe(MonoCollectList.java:79)
at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:164)
at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:86)
at reactor.core.publisher.MonoFromFluxOperator.subscribe(MonoFromFluxOperator.java:81)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:157)
at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:73)
at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:82)
at reactor.core.publisher.FluxFilterWhen$FluxFilterWhenSubscriber.drain(FluxFilterWhen.java:301)
at reactor.core.publisher.FluxFilterWhen$FluxFilterWhenSubscriber.onNext(FluxFilterWhen.java:140)
at reactor.core.publisher.FluxIterable$IterableSubscription.slowPath(FluxIterable.java:270)
at reactor.core.publisher.FluxIterable$IterableSubscription.request(FluxIterable.java:228)
at reactor.core.publisher.FluxFilterWhen$FluxFilterWhenSubscriber.onSubscribe(FluxFilterWhen.java:200)
at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:164)
at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:86)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.Mono.subscribe(Mono.java:4046)
at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:173)
at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
at reactor.netty.http.server.HttpServer$HttpServerHandle.onStateChange(HttpServer.java:632)
at reactor.netty.ReactorNetty$CompositeConnectionObserver.onStateChange(ReactorNetty.java:612)
at reactor.netty.transport.ServerTransport$ChildObserver.onStateChange(ServerTransport.java:453)
at reactor.netty.http.server.HttpServerOperations.onInboundNext(HttpServerOperations.java:510)
at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:94)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at reactor.netty.http.server.HttpTrafficHandler.channelRead(HttpTrafficHandler.java:208)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436)
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296)
at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:832)
2021-05-27 21:11:50.595 DEBUG 87018 --- [ctor-http-nio-3] a.w.r.e.AbstractErrorWebExceptionHandler : [dbf63e0b-1] Resolved [IllegalArgumentException: Only one of (X-Auth-Token) or (X-Username, X-Api-Key/X-Password) headers should be present at a time and when giving X-Username only one of X-Api-Key or X-Password header should be present.] for HTTP GET /actuator/health
2021-05-27 21:11:50.611 DEBUG 87018 --- [ctor-http-nio-3] o.s.http.codec.json.Jackson2JsonEncoder : [dbf63e0b-1] Encoding [timestamp=Thu May 27 21:11:50 IST 2021, path=/actuator/health, status=400, message=Only one of (X-A (truncated)...]
2021-05-27 21:11:50.656 DEBUG 87018 --- [ctor-http-nio-3] r.n.http.server.HttpServerOperations : [id: 0xdbf63e0b, L:/[0:0:0:0:0:0:0:1]:8082 - R:/[0:0:0:0:0:0:0:1]:53830] Decreasing pending responses, now 0
2021-05-27 21:11:50.660 DEBUG 87018 --- [ctor-http-nio-3] r.n.http.server.HttpServerOperations : [id: 0xdbf63e0b, L:/[0:0:0:0:0:0:0:1]:8082 - R:/[0:0:0:0:0:0:0:1]:53830] Last HTTP packet was sent, terminating the channel
2021-05-27 21:11:50.660 DEBUG 87018 --- [ctor-http-nio-3] o.s.w.s.adapter.HttpWebHandlerAdapter : [dbf63e0b-1] Completed 400 BAD_REQUEST
2021-05-27 21:11:50.662 DEBUG 87018 --- [ctor-http-nio-3] r.n.http.server.HttpServerOperations : [id: 0xdbf63e0b, L:/[0:0:0:0:0:0:0:1]:8082 - R:/[0:0:0:0:0:0:0:1]:53830] Last HTTP response frame
【问题讨论】:
使用 Spring Security 服务器调试日志和您提出的请求更新您的问题。 我已经更新了我的问题 看不到任何调试日志。 更新了调试日志 像您所做的那样禁用安全性意味着一些弹簧内部过滤器将被禁用。这并不意味着过滤器链中的每个过滤器都被禁用。您已构建自定义过滤器,这意味着您已选择不使用框架中提供的功能。我的建议是,如果您希望能够利用排除等功能,您可以自定义内置过滤器的弹簧。您的另一个选择是在自定义过滤器中构建排除项。我个人认为自定义安全过滤器是不好的做法。所有自定义安全都是不好的做法。 【参考方案1】:您无需在配置中手动添加AuthenticationWebFilter
和AuthorizationWebFilter
。
实现您想要的更现代的方法通常是这样:
@Bean
SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http)
http
.authorizeExchange((exchanges) -> exchanges
.pathMatchers("/actuator/**").permitAll()
.anyExchange().authenticated()
)
.csrf().disable();
return http.build();
您可以在Spring Security docs中找到有关安全配置的更多信息
【讨论】:
我添加了 AuthenticationWebFilter 和 AuthorizationWebFilter 来提供一些自定义实现。以上是关于如何绕过spring webflux security中的一些url?的主要内容,如果未能解决你的问题,请参考以下文章
spring5 webflux,如何返回自定义json数据?
如何在 Spring boot 2 + Webflux + Thymeleaf 中配置 i18n?
如何使用 Spring Boot 对 WebFlux 进行异常处理?