SecurityMockServerConfiguers fixes

Issue: gh-4719
This commit is contained in:
Rob Winch 2017-10-26 07:24:38 -05:00
parent 77aedcf502
commit c467dcdbe1
4 changed files with 29 additions and 83 deletions

View File

@ -26,7 +26,6 @@ import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextImpl; import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.test.context.TestSecurityContextHolder;
import org.springframework.test.web.reactive.server.MockServerConfigurer; import org.springframework.test.web.reactive.server.MockServerConfigurer;
import org.springframework.test.web.reactive.server.WebTestClient; import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.test.web.reactive.server.WebTestClientConfigurer; import org.springframework.test.web.reactive.server.WebTestClientConfigurer;
@ -39,6 +38,7 @@ import reactor.core.publisher.Mono;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Supplier;
/** /**
* Test utilities for working with Spring Security and * Test utilities for working with Spring Security and
@ -58,7 +58,6 @@ public class SecurityMockServerConfigurers {
public void beforeServerCreated(WebHttpHandlerBuilder builder) { public void beforeServerCreated(WebHttpHandlerBuilder builder) {
builder.filters( filters -> { builder.filters( filters -> {
filters.add(0, new MutatorFilter()); filters.add(0, new MutatorFilter());
filters.add(0, new SetupMutatorFilter(TestSecurityContextHolder.getContext()));
}); });
} }
}; };
@ -71,7 +70,7 @@ public class SecurityMockServerConfigurers {
* @return the {@link WebTestClientConfigurer}} to use * @return the {@link WebTestClientConfigurer}} to use
*/ */
public static <T extends WebTestClientConfigurer & MockServerConfigurer> T mockAuthentication(Authentication authentication) { public static <T extends WebTestClientConfigurer & MockServerConfigurer> T mockAuthentication(Authentication authentication) {
return (T) new MutatorWebTestClientConfigurer(authentication); return (T) new MutatorWebTestClientConfigurer(() -> Mono.just(authentication).map(SecurityContextImpl::new));
} }
/** /**
@ -216,21 +215,11 @@ public class SecurityMockServerConfigurers {
} }
private static class MutatorWebTestClientConfigurer implements WebTestClientConfigurer, MockServerConfigurer { private static class MutatorWebTestClientConfigurer implements WebTestClientConfigurer, MockServerConfigurer {
private final Mono<SecurityContext> context; private final Supplier<Mono<SecurityContext>> context;
private MutatorWebTestClientConfigurer(Mono<SecurityContext> context) { private MutatorWebTestClientConfigurer(Supplier<Mono<SecurityContext>> context) {
this.context = context; this.context = context;
} }
private MutatorWebTestClientConfigurer(SecurityContext context) {
this(Mono.just(context));
}
private MutatorWebTestClientConfigurer(Authentication authentication) {
this(new SecurityContextImpl(authentication));
}
@Override @Override
public void beforeServerCreated(WebHttpHandlerBuilder builder) { public void beforeServerCreated(WebHttpHandlerBuilder builder) {
builder.filters(addSetupMutatorFilter()); builder.filters(addSetupMutatorFilter());
@ -247,20 +236,12 @@ public class SecurityMockServerConfigurers {
} }
private static class SetupMutatorFilter implements WebFilter { private static class SetupMutatorFilter implements WebFilter {
private final Mono<SecurityContext> context; private final Supplier<Mono<SecurityContext>> context;
private SetupMutatorFilter(Mono<SecurityContext> context) { private SetupMutatorFilter(Supplier<Mono<SecurityContext>> context) {
this.context = context; this.context = context;
} }
private SetupMutatorFilter(SecurityContext context) {
this(Mono.just(context));
}
private SetupMutatorFilter(Authentication authentication) {
this(new SecurityContextImpl(authentication));
}
@Override @Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain webFilterChain) { public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain webFilterChain) {
exchange.getAttributes().computeIfAbsent(MutatorFilter.ATTRIBUTE_NAME, key -> this.context); exchange.getAttributes().computeIfAbsent(MutatorFilter.ATTRIBUTE_NAME, key -> this.context);
@ -273,11 +254,11 @@ public class SecurityMockServerConfigurers {
@Override @Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain webFilterChain) { public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain webFilterChain) {
Mono<SecurityContext> context = exchange.getAttribute(ATTRIBUTE_NAME); Supplier<Mono<SecurityContext>> context = exchange.getAttribute(ATTRIBUTE_NAME);
if(context != null) { if(context != null) {
exchange.getAttributes().remove(ATTRIBUTE_NAME); exchange.getAttributes().remove(ATTRIBUTE_NAME);
return webFilterChain.filter(exchange) return webFilterChain.filter(exchange)
.subscriberContext(ReactiveSecurityContextHolder.withSecurityContext(context)); .subscriberContext(ReactiveSecurityContextHolder.withSecurityContext(context.get()));
} }
return webFilterChain.filter(exchange); return webFilterChain.filter(exchange);
} }

View File

@ -20,16 +20,18 @@ import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.test.context.TestSecurityContextHolder; import org.springframework.security.test.context.TestSecurityContextHolder;
import org.springframework.security.test.context.annotation.SecurityTestExecutionListeners; import org.springframework.security.test.context.annotation.SecurityTestExecutionListeners;
import org.springframework.security.test.context.support.WithMockUser; import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.security.web.server.context.SecurityContextServerWebExchangeWebFilter;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient; import org.springframework.test.web.reactive.server.WebTestClient;
import java.security.Principal; import java.security.Principal;
import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.mockPrincipal; import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.mockAuthentication;
import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.springSecurity; import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.springSecurity;
/** /**
@ -42,6 +44,7 @@ public class SecurityMockServerConfigurersAnnotatedTests extends AbstractMockSer
WebTestClient client = WebTestClient WebTestClient client = WebTestClient
.bindToController(controller) .bindToController(controller)
.webFilter(new SecurityContextServerWebExchangeWebFilter())
.apply(springSecurity()) .apply(springSecurity())
.configureClient() .configureClient()
.defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
@ -62,11 +65,12 @@ public class SecurityMockServerConfigurersAnnotatedTests extends AbstractMockSer
@Test @Test
@WithMockUser @WithMockUser
public void withMockUserWhenGlobalMockPrincipalThenOverridesAnnotation() { public void withMockUserWhenGlobalMockPrincipalThenOverridesAnnotation() {
Principal principal = () -> "principal"; TestingAuthenticationToken authentication = new TestingAuthenticationToken("authentication", "secret", "ROLE_USER");
client = WebTestClient client = WebTestClient
.bindToController(controller) .bindToController(controller)
.webFilter(new SecurityContextServerWebExchangeWebFilter())
.apply(springSecurity()) .apply(springSecurity())
.apply(mockPrincipal(principal)) .apply(mockAuthentication(authentication))
.configureClient() .configureClient()
.defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
.build(); .build();
@ -76,33 +80,33 @@ public class SecurityMockServerConfigurersAnnotatedTests extends AbstractMockSer
.exchange() .exchange()
.expectStatus().isOk(); .expectStatus().isOk();
controller.assertPrincipalIsEqualTo(principal); controller.assertPrincipalIsEqualTo(authentication);
} }
@Test @Test
@WithMockUser @WithMockUser
public void withMockUserWhenMutateWithMockPrincipalThenOverridesAnnotation() { public void withMockUserWhenMutateWithMockPrincipalThenOverridesAnnotation() {
Principal principal = () -> "principal"; TestingAuthenticationToken authentication = new TestingAuthenticationToken("authentication", "secret", "ROLE_USER");
client client
.mutateWith(mockPrincipal(principal)) .mutateWith(mockAuthentication(authentication))
.get() .get()
.exchange() .exchange()
.expectStatus().isOk(); .expectStatus().isOk();
controller.assertPrincipalIsEqualTo(principal); controller.assertPrincipalIsEqualTo(authentication);
} }
@Test @Test
@WithMockUser @WithMockUser
public void withMockUserWhenMutateWithMockPrincipalAndNoMutateThenOverridesAnnotationAndUsesAnnotation() { public void withMockUserWhenMutateWithMockPrincipalAndNoMutateThenOverridesAnnotationAndUsesAnnotation() {
Principal principal = () -> "principal"; TestingAuthenticationToken authentication = new TestingAuthenticationToken("authentication", "secret", "ROLE_USER");
client client
.mutateWith(mockPrincipal(principal)) .mutateWith(mockAuthentication(authentication))
.get() .get()
.exchange() .exchange()
.expectStatus().isOk(); .expectStatus().isOk();
controller.assertPrincipalIsEqualTo(principal); controller.assertPrincipalIsEqualTo(authentication);
client client
@ -110,7 +114,6 @@ public class SecurityMockServerConfigurersAnnotatedTests extends AbstractMockSer
.exchange() .exchange()
.expectStatus().isOk(); .expectStatus().isOk();
principal = controller.removePrincipal(); assertPrincipalCreatedFromUserDetails(controller.removePrincipal(), userBuilder.build());
assertPrincipalCreatedFromUserDetails(principal, userBuilder.build());
} }
} }

View File

@ -24,6 +24,7 @@ import org.springframework.security.core.Authentication;
import org.springframework.security.test.context.TestSecurityContextHolder; import org.springframework.security.test.context.TestSecurityContextHolder;
import org.springframework.security.test.context.annotation.SecurityTestExecutionListeners; import org.springframework.security.test.context.annotation.SecurityTestExecutionListeners;
import org.springframework.security.test.context.support.WithMockUser; import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.security.web.server.context.SecurityContextServerWebExchangeWebFilter;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient; import org.springframework.test.web.reactive.server.WebTestClient;
@ -43,6 +44,7 @@ import static org.springframework.security.test.web.reactive.server.SecurityMock
public class SecurityMockServerConfigurersClassAnnotatedTests extends AbstractMockServerConfigurersTests { public class SecurityMockServerConfigurersClassAnnotatedTests extends AbstractMockServerConfigurersTests {
WebTestClient client = WebTestClient WebTestClient client = WebTestClient
.bindToController(controller) .bindToController(controller)
.webFilter(new SecurityContextServerWebExchangeWebFilter())
.apply(springSecurity()) .apply(springSecurity())
.configureClient() .configureClient()
.defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)

View File

@ -22,6 +22,7 @@ import org.springframework.http.MediaType;
import org.springframework.security.authentication.TestingAuthenticationToken; import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.server.context.SecurityContextServerWebExchangeWebFilter;
import org.springframework.test.web.reactive.server.WebTestClient; import org.springframework.test.web.reactive.server.WebTestClient;
import java.security.Principal; import java.security.Principal;
@ -35,55 +36,12 @@ import static org.springframework.security.test.web.reactive.server.SecurityMock
public class SecurityMockServerConfigurersTests extends AbstractMockServerConfigurersTests { public class SecurityMockServerConfigurersTests extends AbstractMockServerConfigurersTests {
WebTestClient client = WebTestClient WebTestClient client = WebTestClient
.bindToController(controller) .bindToController(controller)
.webFilter(new SecurityContextServerWebExchangeWebFilter())
.apply(springSecurity()) .apply(springSecurity())
.configureClient() .configureClient()
.defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
.build(); .build();
@Test
public void mockPrincipalWhenLocalThenSuccess() {
Principal principal = () -> "principal";
client
.mutateWith(mockPrincipal(principal))
.get()
.exchange()
.expectStatus().isOk();
controller.assertPrincipalIsEqualTo(principal);
}
@Test
public void mockPrincipalWhenGlobalTheWorks() {
Principal principal = () -> "principal";
client = WebTestClient
.bindToController(controller)
.apply(springSecurity())
.apply(mockPrincipal(principal))
.configureClient()
.defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
.build();
client
.get()
.exchange()
.expectStatus().isOk();
controller.assertPrincipalIsEqualTo(principal);
}
@Test
public void mockPrincipalWhenMultipleInvocationsThenLastInvocationWins() {
Principal principal = () -> "principal";
client
.mutateWith(mockPrincipal(() -> "will be overridden"))
.mutateWith(mockPrincipal(principal))
.get()
.exchange()
.expectStatus().isOk();
controller.assertPrincipalIsEqualTo(principal);
}
@Test @Test
public void mockAuthenticationWhenLocalThenSuccess() { public void mockAuthenticationWhenLocalThenSuccess() {
TestingAuthenticationToken authentication = new TestingAuthenticationToken("authentication", "secret", "ROLE_USER"); TestingAuthenticationToken authentication = new TestingAuthenticationToken("authentication", "secret", "ROLE_USER");
@ -100,6 +58,7 @@ public class SecurityMockServerConfigurersTests extends AbstractMockServerConfig
TestingAuthenticationToken authentication = new TestingAuthenticationToken("authentication", "secret", "ROLE_USER"); TestingAuthenticationToken authentication = new TestingAuthenticationToken("authentication", "secret", "ROLE_USER");
client = WebTestClient client = WebTestClient
.bindToController(controller) .bindToController(controller)
.webFilter(new SecurityContextServerWebExchangeWebFilter())
.apply(springSecurity()) .apply(springSecurity())
.apply(mockAuthentication(authentication)) .apply(mockAuthentication(authentication))
.configureClient() .configureClient()
@ -129,6 +88,7 @@ public class SecurityMockServerConfigurersTests extends AbstractMockServerConfig
public void mockUserWhenGlobalThenSuccess() { public void mockUserWhenGlobalThenSuccess() {
client = WebTestClient client = WebTestClient
.bindToController(controller) .bindToController(controller)
.webFilter(new SecurityContextServerWebExchangeWebFilter())
.apply(springSecurity()) .apply(springSecurity())
.apply(mockUser()) .apply(mockUser())
.configureClient() .configureClient()