Bladeren bron

ReactorContextWebFilter preserves main Context

Previously ReactorContextWebFilter overrode
the main Context.

Fixes: gh-4962
Rob Winch 7 jaren geleden
bovenliggende
commit
141e3f581f

+ 7 - 2
web/src/main/java/org/springframework/security/web/server/context/ReactorContextWebFilter.java

@@ -22,6 +22,7 @@ import org.springframework.web.server.ServerWebExchange;
 import org.springframework.web.server.WebFilter;
 import org.springframework.web.server.WebFilterChain;
 import reactor.core.publisher.Mono;
+import reactor.util.context.Context;
 
 /**
  * @author Rob Winch
@@ -39,8 +40,12 @@ public class ReactorContextWebFilter implements WebFilter {
 	public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
 		return chain.filter(exchange)
 			.subscriberContext(c -> c.hasKey(SecurityContext.class) ? c :
-				Mono.defer(() -> this.repository.load(exchange))
-					.as(ReactiveSecurityContextHolder::withSecurityContext)
+				withSecurityContext(c, exchange)
 			);
 	}
+
+	private Context withSecurityContext(Context mainContext, ServerWebExchange exchange) {
+		return mainContext.putAll(Mono.defer(() -> this.repository.load(exchange))
+			.as(ReactiveSecurityContextHolder::withSecurityContext));
+	}
 }

+ 24 - 0
web/src/test/java/org/springframework/security/web/server/context/ReactorContextWebFilterTests.java

@@ -22,12 +22,19 @@ import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnitRunner;
 import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
+import org.springframework.mock.web.server.MockServerWebExchange;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.context.ReactiveSecurityContextHolder;
 import org.springframework.security.core.context.SecurityContext;
 import org.springframework.security.core.context.SecurityContextImpl;
 import org.springframework.security.test.web.reactive.server.WebTestHandler;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.web.server.WebFilter;
+import org.springframework.web.server.WebFilterChain;
+import org.springframework.web.server.handler.DefaultWebFilterChain;
 import reactor.core.publisher.Mono;
+import reactor.test.StepVerifier;
+import reactor.util.context.Context;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.*;
@@ -98,4 +105,21 @@ public class ReactorContextWebFilterTests {
 
 		verify(this.repository).load(any());
 	}
+
+	@Test
+	// gh-4962
+	public void filterWhenMainContextThenDoesNotOverride() {
+		String contextKey = "main";
+		WebFilter mainContextWebFilter = (e, c) -> c
+			.filter(e)
+			.subscriberContext(Context.of(contextKey, true));
+
+		WebFilterChain chain = new DefaultWebFilterChain(e -> Mono.empty(), mainContextWebFilter, this.filter);
+		Mono<Void> filter = chain.filter(MockServerWebExchange.from(this.exchange.build()));
+		StepVerifier.create(filter)
+			.expectAccessibleContext()
+			.hasKey(contextKey)
+			.then()
+			.verifyComplete();
+	}
 }