소스 검색

fix Mock Authentication resolution

Oleh Dokuka 7 년 전
부모
커밋
76e36bd06e

+ 7 - 3
test/src/main/java/org/springframework/security/test/context/support/ReactorContextTestExecutionListener.java

@@ -19,6 +19,7 @@ package org.springframework.security.test.context.support;
 import org.reactivestreams.Subscription;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.context.ReactiveSecurityContextHolder;
+import org.springframework.security.core.context.SecurityContext;
 import org.springframework.security.test.context.TestSecurityContextHolder;
 import org.springframework.test.context.TestContext;
 import org.springframework.test.context.TestExecutionListener;
@@ -54,7 +55,8 @@ public class ReactorContextTestExecutionListener
 	private static class DelegateTestExecutionListener extends AbstractTestExecutionListener {
 		@Override
 		public void beforeTestMethod(TestContext testContext) throws Exception {
-			Hooks.onLastOperator(Operators.lift((s, sub) -> new SecuritySubContext<>(sub)));
+			SecurityContext securityContext = TestSecurityContextHolder.getContext();
+			Hooks.onLastOperator(Operators.lift((s, sub) -> new SecuritySubContext<>(sub, securityContext)));
 		}
 
 		@Override
@@ -66,9 +68,11 @@ public class ReactorContextTestExecutionListener
 			private static String CONTEXT_DEFAULTED_ATTR_NAME = SecuritySubContext.class.getName().concat(".CONTEXT_DEFAULTED_ATTR_NAME");
 
 			private final CoreSubscriber<T> delegate;
+			private final SecurityContext securityContext;
 
-			SecuritySubContext(CoreSubscriber<T> delegate) {
+			SecuritySubContext(CoreSubscriber<T> delegate, SecurityContext securityContext) {
 				this.delegate = delegate;
+				this.securityContext = securityContext;
 			}
 
 			@Override
@@ -78,7 +82,7 @@ public class ReactorContextTestExecutionListener
 					return context;
 				}
 				context = context.put(CONTEXT_DEFAULTED_ATTR_NAME, Boolean.TRUE);
-				Authentication authentication = TestSecurityContextHolder.getContext().getAuthentication();
+				Authentication authentication = securityContext.getAuthentication();
 				if (authentication == null) {
 					return context;
 				}

+ 14 - 0
test/src/test/java/org/springframework/security/test/context/support/ReactorContextTestExecutionListenerTests.java

@@ -21,6 +21,8 @@ package org.springframework.security.test.context.support;
  * @since 5.0
  */
 
+import java.util.concurrent.ForkJoinPool;
+
 import org.junit.After;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -153,6 +155,18 @@ public class ReactorContextTestExecutionListenerTests {
 		assertThat(comparator.compare(withSecurity, reactorContext)).isLessThan(0);
 	}
 
+	@Test
+	public void checkSecurityContextResolutionWhenSubscribedContextCalledOnTheDifferentThreadThanWithSecurityContextTestExecutionListener() throws Exception {
+		TestingAuthenticationToken contextHolder = new TestingAuthenticationToken("contextHolder", "password", "ROLE_USER");
+		TestSecurityContextHolder.setContext(new SecurityContextImpl(contextHolder));
+
+		this.listener.beforeTestMethod(this.testContext);
+
+		ForkJoinPool.commonPool()
+			.submit(() -> assertAuthentication(contextHolder))
+			.join();
+	}
+
 	public void assertAuthentication(Authentication expected) {
 		Mono<Authentication> authentication = ReactiveSecurityContextHolder.getContext()
 			.map(SecurityContext::getAuthentication);

+ 1 - 1
test/src/test/java/org/springframework/security/test/web/reactive/server/AbstractMockServerConfigurersTests.java

@@ -52,7 +52,7 @@ abstract class AbstractMockServerConfigurersTests {
 
 	@RestController
 	protected static class PrincipalController {
-		Principal principal;
+		volatile Principal principal;
 
 		@RequestMapping("/**")
 		public Principal get(Principal principal) {

+ 52 - 0
test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurersAnnotatedTests.java

@@ -16,6 +16,8 @@
 
 package org.springframework.security.test.web.reactive.server;
 
+import java.util.concurrent.ForkJoinPool;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.springframework.http.HttpHeaders;
@@ -114,4 +116,54 @@ public class SecurityMockServerConfigurersAnnotatedTests extends AbstractMockSer
 
 		assertPrincipalCreatedFromUserDetails(controller.removePrincipal(), userBuilder.build());
 	}
+
+	@Test
+	@WithMockUser
+	public void withMockUserWhenOnMethodAndRequestIsExecutedOnDifferentThreadThenSuccess() {
+		Authentication authentication = TestSecurityContextHolder.getContext().getAuthentication();
+		ForkJoinPool
+			.commonPool()
+			.submit(() ->
+				client
+					.get()
+					.exchange()
+					.expectStatus()
+					.isOk()
+			)
+			.join();
+
+		controller.assertPrincipalIsEqualTo(authentication);
+	}
+
+	@Test
+	@WithMockUser
+	public void withMockUserAndWithCallOnSeparateThreadWhenMutateWithMockPrincipalAndNoMutateThenOverridesAnnotationAndUsesAnnotation() {
+		TestingAuthenticationToken authentication = new TestingAuthenticationToken("authentication", "secret", "ROLE_USER");
+
+		ForkJoinPool
+			.commonPool()
+			.submit(() ->
+				client
+					.mutateWith(mockAuthentication(authentication))
+					.get()
+					.exchange()
+					.expectStatus().isOk()
+			)
+			.join();
+
+		controller.assertPrincipalIsEqualTo(authentication);
+
+
+		ForkJoinPool
+			.commonPool()
+			.submit(() ->
+				client
+					.get()
+					.exchange()
+					.expectStatus().isOk()
+			)
+			.join();
+
+		assertPrincipalCreatedFromUserDetails(controller.removePrincipal(), userBuilder.build());
+	}
 }