mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-05-31 09:12:14 +00:00
Add Annotated Support for WebTestClient
Fixes gh-4457
This commit is contained in:
parent
f50812c385
commit
544f39f826
@ -25,6 +25,7 @@ import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
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.WebTestClient;
|
||||
import org.springframework.test.web.reactive.server.WebTestClientConfigurer;
|
||||
@ -39,6 +40,7 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Test utilities for working with Spring Security and
|
||||
@ -56,7 +58,10 @@ public class SecurityMockServerConfigurers {
|
||||
public static MockServerConfigurer springSecurity() {
|
||||
return new MockServerConfigurer() {
|
||||
public void beforeServerCreated(WebHttpHandlerBuilder builder) {
|
||||
builder.filters( filters -> filters.add(0, new MutatorFilter()));
|
||||
builder.filters( filters -> {
|
||||
filters.add(0, new MutatorFilter());
|
||||
filters.add(0, new SetupMutatorFilter(createMutator( () -> TestSecurityContextHolder.getContext().getAuthentication())));
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -68,7 +73,7 @@ public class SecurityMockServerConfigurers {
|
||||
* @return the {@link WebTestClientConfigurer} to use
|
||||
*/
|
||||
public static <T extends WebTestClientConfigurer & MockServerConfigurer> T mockPrincipal(Principal principal) {
|
||||
return (T) new MutatorWebTestClientConfigurer(m -> m.mutate().principal(Mono.just(principal)).build());
|
||||
return (T) new MutatorWebTestClientConfigurer(createMutator(() -> principal));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -115,6 +120,10 @@ public class SecurityMockServerConfigurers {
|
||||
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
|
||||
* password of "password" and granted authorities of "ROLE_USER".
|
||||
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright 2002-2017 the original author or authors.
|
||||
* *
|
||||
* * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* * you may not use this file except in compliance with the License.
|
||||
* * You may obtain a copy of the License at
|
||||
* *
|
||||
* * http://www.apache.org/licenses/LICENSE-2.0
|
||||
* *
|
||||
* * Unless required by applicable law or agreed to in writing, software
|
||||
* * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* * See the License for the specific language governing permissions and
|
||||
* * limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.springframework.security.test.web.reactive.server;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.security.Principal;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.springSecurity;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
abstract class AbstractMockServerConfigurersTests {
|
||||
protected PrincipalController controller = new PrincipalController();
|
||||
|
||||
protected User.UserBuilder userBuilder = User
|
||||
.withUsername("user")
|
||||
.password("password")
|
||||
.roles("USER");
|
||||
|
||||
protected void assertPrincipalCreatedFromUserDetails(Principal principal, UserDetails originalUserDetails) {
|
||||
assertThat(principal).isInstanceOf(UsernamePasswordAuthenticationToken.class);
|
||||
|
||||
UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) principal;
|
||||
assertThat(authentication.getCredentials()).isEqualTo(originalUserDetails.getPassword());
|
||||
assertThat(authentication.getAuthorities()).containsOnlyElementsOf(originalUserDetails.getAuthorities());
|
||||
|
||||
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
|
||||
assertThat(userDetails.getPassword()).isEqualTo(authentication.getCredentials());
|
||||
assertThat(authentication.getAuthorities()).containsOnlyElementsOf(userDetails.getAuthorities());
|
||||
}
|
||||
|
||||
@RestController
|
||||
protected static class PrincipalController {
|
||||
Principal principal;
|
||||
|
||||
@RequestMapping("/**")
|
||||
public Principal get(Principal principal) {
|
||||
this.principal = principal;
|
||||
return principal;
|
||||
}
|
||||
|
||||
public Principal removePrincipal() {
|
||||
Principal result = this.principal;
|
||||
this.principal = null;
|
||||
return result;
|
||||
}
|
||||
|
||||
public void assertPrincipalIsEqualTo(Principal expected) {
|
||||
assertThat(this.principal).isEqualTo(expected);
|
||||
this.principal = null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright 2002-2017 the original author or authors.
|
||||
* *
|
||||
* * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* * you may not use this file except in compliance with the License.
|
||||
* * You may obtain a copy of the License at
|
||||
* *
|
||||
* * http://www.apache.org/licenses/LICENSE-2.0
|
||||
* *
|
||||
* * Unless required by applicable law or agreed to in writing, software
|
||||
* * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* * See the License for the specific language governing permissions and
|
||||
* * limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.springframework.security.test.web.reactive.server;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.test.context.TestSecurityContextHolder;
|
||||
import org.springframework.security.test.context.annotation.SecurityTestExecutionListeners;
|
||||
import org.springframework.security.test.context.support.WithMockUser;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
|
||||
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.springSecurity;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SecurityTestExecutionListeners
|
||||
public class SecurityMockServerConfigurersAnnotatedTests extends AbstractMockServerConfigurersTests {
|
||||
|
||||
WebTestClient client = WebTestClient
|
||||
.bindToController(controller)
|
||||
.apply(springSecurity())
|
||||
.configureClient()
|
||||
.defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
|
||||
.build();
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void withMockUserWhenOnMethodThenSuccess() {
|
||||
client
|
||||
.get()
|
||||
.exchange()
|
||||
.expectStatus().isOk();
|
||||
|
||||
Authentication authentication = TestSecurityContextHolder.getContext().getAuthentication();
|
||||
controller.assertPrincipalIsEqualTo(authentication);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void withMockUserWhenGlobalMockPrincipalThenOverridesAnnotation() {
|
||||
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
|
||||
@WithMockUser
|
||||
public void withMockUserWhenMutateWithMockPrincipalThenOverridesAnnotation() {
|
||||
Principal principal = () -> "principal";
|
||||
client
|
||||
.mutateWith(mockPrincipal(principal))
|
||||
.get()
|
||||
.exchange()
|
||||
.expectStatus().isOk();
|
||||
|
||||
controller.assertPrincipalIsEqualTo(principal);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void withMockUserWhenMutateWithMockPrincipalAndNoMutateThenOverridesAnnotationAndUsesAnnotation() {
|
||||
Principal principal = () -> "principal";
|
||||
client
|
||||
.mutateWith(mockPrincipal(principal))
|
||||
.get()
|
||||
.exchange()
|
||||
.expectStatus().isOk();
|
||||
|
||||
controller.assertPrincipalIsEqualTo(principal);
|
||||
|
||||
|
||||
client
|
||||
.get()
|
||||
.exchange()
|
||||
.expectStatus().isOk();
|
||||
|
||||
principal = controller.removePrincipal();
|
||||
assertPrincipalCreatedFromUserDetails(principal, userBuilder.build());
|
||||
}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright 2002-2017 the original author or authors.
|
||||
* *
|
||||
* * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* * you may not use this file except in compliance with the License.
|
||||
* * You may obtain a copy of the License at
|
||||
* *
|
||||
* * http://www.apache.org/licenses/LICENSE-2.0
|
||||
* *
|
||||
* * Unless required by applicable law or agreed to in writing, software
|
||||
* * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* * See the License for the specific language governing permissions and
|
||||
* * limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.springframework.security.test.web.reactive.server;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.test.context.TestSecurityContextHolder;
|
||||
import org.springframework.security.test.context.annotation.SecurityTestExecutionListeners;
|
||||
import org.springframework.security.test.context.support.WithMockUser;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
|
||||
import java.security.Principal;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.mockUser;
|
||||
import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.springSecurity;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
@WithMockUser
|
||||
@RunWith(SpringRunner.class)
|
||||
@SecurityTestExecutionListeners
|
||||
public class SecurityMockServerConfigurersClassAnnotatedTests extends AbstractMockServerConfigurersTests {
|
||||
WebTestClient client = WebTestClient
|
||||
.bindToController(controller)
|
||||
.apply(springSecurity())
|
||||
.configureClient()
|
||||
.defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
|
||||
.build();
|
||||
|
||||
@Test
|
||||
public void wheMockUserWhenClassAnnotatedThenSuccess() {
|
||||
client
|
||||
.get()
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody(String.class).consumeWith( response -> assertThat(response.getResponseBody()).contains("\"username\":\"user\""));
|
||||
|
||||
Authentication authentication = TestSecurityContextHolder.getContext().getAuthentication();
|
||||
controller.assertPrincipalIsEqualTo(authentication);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser("method-user")
|
||||
public void withMockUserWhenClassAndMethodAnnotationThenMethodOverrides() {
|
||||
client
|
||||
.get()
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody(String.class).consumeWith( response -> assertThat(response.getResponseBody()).contains("\"username\":\"method-user\""));
|
||||
|
||||
Authentication authentication = TestSecurityContextHolder.getContext().getAuthentication();
|
||||
controller.assertPrincipalIsEqualTo(authentication);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withMockUserWhenMutateWithThenMustateWithOverrides() {
|
||||
client
|
||||
.mutateWith(mockUser("mutateWith-mockUser"))
|
||||
.get()
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody(String.class).consumeWith( response -> assertThat(response.getResponseBody()).contains("\"username\":\"mutateWith-mockUser\""));
|
||||
|
||||
Principal principal = controller.removePrincipal();
|
||||
assertPrincipalCreatedFromUserDetails(principal, userBuilder.username("mutateWith-mockUser").build());
|
||||
}
|
||||
}
|
@ -22,25 +22,19 @@ import org.junit.Test;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.security.Principal;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.*;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
public class SecurityMockServerConfigurersTests {
|
||||
PrincipalController controller = new PrincipalController();
|
||||
|
||||
public class SecurityMockServerConfigurersTests extends AbstractMockServerConfigurersTests {
|
||||
WebTestClient client = WebTestClient
|
||||
.bindToController(controller)
|
||||
.apply(springSecurity())
|
||||
@ -48,11 +42,6 @@ public class SecurityMockServerConfigurersTests {
|
||||
.defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
|
||||
.build();
|
||||
|
||||
User.UserBuilder userBuilder = User
|
||||
.withUsername("user")
|
||||
.password("password")
|
||||
.roles("USER");
|
||||
|
||||
@Test
|
||||
public void mockPrincipalWhenLocalThenSuccess() {
|
||||
Principal principal = () -> "principal";
|
||||
@ -197,38 +186,4 @@ public class SecurityMockServerConfigurersTests {
|
||||
|
||||
assertPrincipalCreatedFromUserDetails(actual, userBuilder.build());
|
||||
}
|
||||
|
||||
private void assertPrincipalCreatedFromUserDetails(Principal principal, UserDetails originalUserDetails) {
|
||||
assertThat(principal).isInstanceOf(UsernamePasswordAuthenticationToken.class);
|
||||
|
||||
UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) principal;
|
||||
assertThat(authentication.getCredentials()).isEqualTo(originalUserDetails.getPassword());
|
||||
assertThat(authentication.getAuthorities()).containsOnlyElementsOf(originalUserDetails.getAuthorities());
|
||||
|
||||
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
|
||||
assertThat(userDetails.getPassword()).isEqualTo(authentication.getCredentials());
|
||||
assertThat(authentication.getAuthorities()).containsOnlyElementsOf(userDetails.getAuthorities());
|
||||
}
|
||||
|
||||
@RestController
|
||||
static class PrincipalController {
|
||||
Principal principal;
|
||||
|
||||
@RequestMapping("/**")
|
||||
public Principal get(Principal principal) {
|
||||
this.principal = principal;
|
||||
return principal;
|
||||
}
|
||||
|
||||
public Principal removePrincipal() {
|
||||
Principal result = this.principal;
|
||||
this.principal = null;
|
||||
return result;
|
||||
}
|
||||
|
||||
public void assertPrincipalIsEqualTo(Principal expected) {
|
||||
assertThat(this.principal).isEqualTo(expected);
|
||||
this.principal = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user