parent
5bcf3c559b
commit
77aedcf502
|
@ -21,6 +21,9 @@ import org.springframework.lang.Nullable;
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
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.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.security.test.context.TestSecurityContextHolder;
|
||||||
|
@ -33,12 +36,9 @@ import org.springframework.web.server.WebFilterChain;
|
||||||
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
|
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
import java.security.Principal;
|
|
||||||
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.Function;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test utilities for working with Spring Security and
|
* Test utilities for working with Spring Security and
|
||||||
|
@ -58,22 +58,12 @@ 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(createMutator( () -> TestSecurityContextHolder.getContext().getAuthentication())));
|
filters.add(0, new SetupMutatorFilter(TestSecurityContextHolder.getContext()));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the ServerWebExchange to use the provided Principal
|
|
||||||
*
|
|
||||||
* @param principal the principal to use.
|
|
||||||
* @return the {@link WebTestClientConfigurer} to use
|
|
||||||
*/
|
|
||||||
public static <T extends WebTestClientConfigurer & MockServerConfigurer> T mockPrincipal(Principal principal) {
|
|
||||||
return (T) new MutatorWebTestClientConfigurer(createMutator(() -> principal));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the ServerWebExchange to use the provided Authentication as the Principal
|
* Updates the ServerWebExchange to use the provided Authentication as the Principal
|
||||||
*
|
*
|
||||||
|
@ -81,7 +71,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 mockPrincipal(authentication);
|
return (T) new MutatorWebTestClientConfigurer(authentication);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -118,10 +108,6 @@ public class SecurityMockServerConfigurers {
|
||||||
return new UserExchangeMutator(username);
|
return new UserExchangeMutator(username);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Function<ServerWebExchange, ServerWebExchange> createMutator(Supplier<Principal> principal) {
|
|
||||||
return m -> principal.get() == null ? m : m.mutate().principal(Mono.just(principal.get())).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the WebServerExchange using {@code {@link SecurityMockServerConfigurers#mockUser(UserDetails)}. Defaults to use a
|
* Updates the WebServerExchange using {@code {@link SecurityMockServerConfigurers#mockUser(UserDetails)}. Defaults to use a
|
||||||
* password of "password" and granted authorities of "ROLE_USER".
|
* password of "password" and granted authorities of "ROLE_USER".
|
||||||
|
@ -230,12 +216,21 @@ public class SecurityMockServerConfigurers {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class MutatorWebTestClientConfigurer implements WebTestClientConfigurer, MockServerConfigurer {
|
private static class MutatorWebTestClientConfigurer implements WebTestClientConfigurer, MockServerConfigurer {
|
||||||
private final Function<ServerWebExchange, ServerWebExchange> mutator;
|
private final Mono<SecurityContext> context;
|
||||||
|
|
||||||
private MutatorWebTestClientConfigurer(Function<ServerWebExchange, ServerWebExchange> mutator) {
|
private MutatorWebTestClientConfigurer(Mono<SecurityContext> context) {
|
||||||
this.mutator = mutator;
|
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,34 +242,42 @@ public class SecurityMockServerConfigurers {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Consumer<List<WebFilter>> addSetupMutatorFilter() {
|
private Consumer<List<WebFilter>> addSetupMutatorFilter() {
|
||||||
return filters -> filters.add(0, new SetupMutatorFilter(mutator));
|
return filters -> filters.add(0, new SetupMutatorFilter(this.context));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class SetupMutatorFilter implements WebFilter {
|
private static class SetupMutatorFilter implements WebFilter {
|
||||||
private final Function<ServerWebExchange, ServerWebExchange> mutator;
|
private final Mono<SecurityContext> context;
|
||||||
|
|
||||||
private SetupMutatorFilter(Function<ServerWebExchange, ServerWebExchange> mutator) {
|
private SetupMutatorFilter(Mono<SecurityContext> context) {
|
||||||
this.mutator = mutator;
|
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 -> mutator);
|
exchange.getAttributes().computeIfAbsent(MutatorFilter.ATTRIBUTE_NAME, key -> this.context);
|
||||||
return webFilterChain.filter(exchange);
|
return webFilterChain.filter(exchange);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class MutatorFilter implements WebFilter {
|
private static class MutatorFilter implements WebFilter {
|
||||||
|
public static final String ATTRIBUTE_NAME = "context";
|
||||||
public static final String ATTRIBUTE_NAME = "mutator";
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain webFilterChain) {
|
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain webFilterChain) {
|
||||||
Function<ServerWebExchange, ServerWebExchange> mutator = exchange.getAttribute(ATTRIBUTE_NAME);
|
Mono<SecurityContext> context = exchange.getAttribute(ATTRIBUTE_NAME);
|
||||||
if(mutator != null) {
|
if(context != null) {
|
||||||
exchange.getAttributes().remove(ATTRIBUTE_NAME);
|
exchange.getAttributes().remove(ATTRIBUTE_NAME);
|
||||||
exchange = mutator.apply(exchange);
|
return webFilterChain.filter(exchange)
|
||||||
|
.subscriberContext(ReactiveSecurityContextHolder.withSecurityContext(context));
|
||||||
}
|
}
|
||||||
return webFilterChain.filter(exchange);
|
return webFilterChain.filter(exchange);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue