From 07b6699fd9564b1307bba802414fbe86ce6361fa Mon Sep 17 00:00:00 2001 From: Rob Winch Date: Wed, 5 Sep 2018 16:11:36 -0500 Subject: [PATCH] ServerWebExchangeReactorContextWebFilter Fixes: gh-5779 --- .../config/web/server/ServerHttpSecurity.java | 13 +++++++++ .../web/server/ServerHttpSecurityTests.java | 28 +++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java b/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java index 15d05aa732..f344332186 100644 --- a/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java +++ b/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java @@ -133,6 +133,7 @@ import org.springframework.web.cors.reactive.DefaultCorsProcessor; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebFilter; import org.springframework.web.server.WebFilterChain; +import reactor.util.context.Context; import static org.springframework.security.web.server.DelegatingServerAuthenticationEntryPoint.DelegateEntry; import static org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher.MatchResult.match; @@ -1098,6 +1099,7 @@ public class ServerHttpSecurity { } sortedWebFilters.add(f); }); + sortedWebFilters.add(0, new ServerWebExchangeReactorContextWebFilter()); return new MatcherSecurityWebFilterChain(getSecurityMatcher(), sortedWebFilters); } @@ -2191,4 +2193,15 @@ public class ServerHttpSecurity { + '}'; } } + + /** + * Workaround https://jira.spring.io/projects/SPR/issues/SPR-17213 + */ + static class ServerWebExchangeReactorContextWebFilter implements WebFilter { + @Override + public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { + return chain.filter(exchange) + .subscriberContext(Context.of(ServerWebExchange.class, exchange)); + } + } } diff --git a/config/src/test/java/org/springframework/security/config/web/server/ServerHttpSecurityTests.java b/config/src/test/java/org/springframework/security/config/web/server/ServerHttpSecurityTests.java index 5e572c559f..e13633efc8 100644 --- a/config/src/test/java/org/springframework/security/config/web/server/ServerHttpSecurityTests.java +++ b/config/src/test/java/org/springframework/security/config/web/server/ServerHttpSecurityTests.java @@ -27,12 +27,16 @@ import org.springframework.security.authentication.TestingAuthenticationToken; import org.springframework.security.config.annotation.web.reactive.ServerHttpSecurityConfigurationBuilder; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.test.web.reactive.server.WebTestClientBuilder; +import org.springframework.security.web.server.SecurityWebFilterChain; import org.springframework.security.web.server.WebFilterChainProxy; import org.springframework.security.web.server.context.ServerSecurityContextRepository; import org.springframework.security.web.server.context.WebSessionServerSecurityContextRepository; import org.springframework.test.web.reactive.server.EntityExchangeResult; import org.springframework.test.web.reactive.server.FluxExchangeResult; import org.springframework.test.web.reactive.server.WebTestClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; import reactor.test.publisher.TestPublisher; @@ -117,9 +121,33 @@ public class ServerHttpSecurityTests { .expectBody().isEmpty(); } + @Test + public void buildWhenServerWebExchangeFromContextThenFound() { + SecurityWebFilterChain filter = this.http.build(); + + WebTestClient client = WebTestClient.bindToController(new SubscriberContextController()) + .webFilter(new WebFilterChainProxy(filter)) + .build(); + + client.get().uri("/foo/bar") + .exchange() + .expectBody(String.class).isEqualTo("/foo/bar"); + } + private WebTestClient buildClient() { WebFilterChainProxy springSecurityFilterChain = new WebFilterChainProxy( this.http.build()); return WebTestClientBuilder.bindToWebFilters(springSecurityFilterChain).build(); } + + @RestController + private static class SubscriberContextController { + @GetMapping("/**") + Mono pathWithinApplicationFromContext() { + return Mono.subscriberContext() + .filter(c -> c.hasKey(ServerWebExchange.class)) + .map(c -> c.get(ServerWebExchange.class)) + .map(e -> e.getRequest().getPath().pathWithinApplication().value()); + } + } }