---> .csrf((c) -> {c.disable();}) for the /api/** security filter chain caused the following to happen for an unknown reason:
The issue is not having the gateway route filters and resources servers not being called if there are multiple SecurityWebFilterChain beans.
Using Spring Boot 3.3.1, Spring Cloud 2023.0.2, and Webflux:
The application is split into a Webflux gateway and multiple resource servers that are configured with spring.cloud.gateway.routes that are registered with a Eureka instance. One SecurityWebFilterChain bean has a security matcher for "/api/" which should get forwarded to a resource server and a second SecurityWebFilterChain is for all other requests (default "/"). The "/api/**" bean has a higher order so it gets applied before the second bean.
Requests handled by the second SecurityWebFilterChain (/) bean applies the gateway route filters properly and forwards the request to the proper resource server. Requests handled by the API SecurityWebFilterChain (/api/) do not apply any gateway route filters or forward the request to the resource server although the response is a HTTP 200.
If I combined all requests into one SecurityWebFilterChain bean, everything works fine but I can't due to different configuration requirements for each path.
I'm trying to keep this concise with enough details to be helpful.
application.yml
gateway:
filter:
request-rate-limiter:
enabled: true
default-filters:
- JWTRelay
- name: RequestRateLimiter
routes:
- id: route1
uri: lb://resourceserver1
predicates:
- Path=/resourceserver1/**
filters:
- StripPrefix=1
- RemoveRequestHeader=Cookie
- id: route2
uri: lb://resourceserver2
predicates:
- Path=/resourceserver2/**
filters:
- StripPrefix=1
- RemoveRequestHeader=Cookie
- id: api_route
uri: lb://resourceserverapi
predicates:
- Path=/api/**
filters:
- StripPrefix=1
- RemoveRequestHeader=Cookie
SecurityConfig.java
@Order(Ordered.HIGHEST_PRECEDENCE)
@Bean
SecurityWebFilterChain apiHttpSecurity(ServerHttpSecurity http) {
http
.securityMatcher(new PathPatternParserServerWebExchangeMatcher("/api/**"))
.authorizeExchange((exchanges) -> exchanges
.anyExchange().authenticated()
)
.....
return http.build();
}
@Bean
SecurityWebFilterChain webHttpSecurity(ServerHttpSecurity http) {
http
.authorizeExchange((exchanges) -> exchanges
.anyExchange().authenticated()
)
.....
return http.build();
}
Logs when it works:
Weights attr: {} Pattern "[/services/resourceserver1/]" does not match against value "/resourceserver2/foo/" Pattern "[/services/resourceserver2/]" does not match against value "/resourceserver2/foo/" Pattern "[/services/api/]" does not match against value "/resourceserver2/foo/" Pattern "[/resourceserver1/]" does not match against value "/resourceserver2/foo/" Pattern "/resourceserver2/**" matches against value "/resourceserver2/foo/" Route matched: route2 ...
Logs when it doesn't work for /api/**:
Weights attr: {} ---no more logs---
I would expect to have the spring.cloud.gateway.routes configured to be applied to all SecurityWebFilterChain beans.
Request flow through the filter chains:
-> /api/foo -> SecurityWebFilterChain (/api/**) -> Gateway routes -> resourceserverapi
-> /resourceserver1/foo -> SecurityWebFilterChain (/**) -> Gateway routes -> resourceserver1