|
@@ -76,12 +76,10 @@ import org.springframework.web.context.request.ServletRequestAttributes;
|
|
|
import org.springframework.web.reactive.function.BodyInserter;
|
|
|
import org.springframework.web.reactive.function.client.ClientRequest;
|
|
|
import org.springframework.web.reactive.function.client.WebClient;
|
|
|
-import reactor.core.CoreSubscriber;
|
|
|
-import reactor.core.publisher.BaseSubscriber;
|
|
|
-import reactor.core.publisher.Mono;
|
|
|
import reactor.util.context.Context;
|
|
|
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
|
+import javax.servlet.http.HttpServletResponse;
|
|
|
import java.net.URI;
|
|
|
import java.time.Duration;
|
|
|
import java.time.Instant;
|
|
@@ -93,7 +91,6 @@ import java.util.Optional;
|
|
|
import java.util.function.Consumer;
|
|
|
|
|
|
import static org.assertj.core.api.Assertions.assertThat;
|
|
|
-import static org.assertj.core.api.Assertions.assertThatCode;
|
|
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
|
|
|
import static org.mockito.Mockito.*;
|
|
|
import static org.springframework.http.HttpMethod.GET;
|
|
@@ -163,7 +160,6 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionTests {
|
|
|
public void cleanup() throws Exception {
|
|
|
SecurityContextHolder.clearContext();
|
|
|
RequestContextHolder.resetRequestAttributes();
|
|
|
- this.function.destroy();
|
|
|
}
|
|
|
|
|
|
@Test
|
|
@@ -591,18 +587,15 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionTests {
|
|
|
// gh-6483
|
|
|
@Test
|
|
|
public void filterWhenChainedThenDefaultsStillAvailable() throws Exception {
|
|
|
- this.function.afterPropertiesSet(); // Hooks.onLastOperator() initialized
|
|
|
this.function.setDefaultOAuth2AuthorizedClient(true);
|
|
|
|
|
|
MockHttpServletRequest servletRequest = new MockHttpServletRequest();
|
|
|
MockHttpServletResponse servletResponse = new MockHttpServletResponse();
|
|
|
- RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(servletRequest, servletResponse));
|
|
|
|
|
|
OAuth2User user = mock(OAuth2User.class);
|
|
|
List<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList("ROLE_USER");
|
|
|
OAuth2AuthenticationToken authentication = new OAuth2AuthenticationToken(
|
|
|
user, authorities, this.registration.getRegistrationId());
|
|
|
- SecurityContextHolder.getContext().setAuthentication(authentication);
|
|
|
|
|
|
OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(
|
|
|
this.registration, "principalName", this.accessToken);
|
|
@@ -619,12 +612,13 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionTests {
|
|
|
// Default request attributes NOT set
|
|
|
final ClientRequest request2 = ClientRequest.create(GET, URI.create("https://example2.com")).build();
|
|
|
|
|
|
+ Context context = context(servletRequest, servletResponse, authentication);
|
|
|
+
|
|
|
this.function.filter(request1, this.exchange)
|
|
|
.flatMap(response -> this.function.filter(request2, this.exchange))
|
|
|
+ .subscriberContext(context)
|
|
|
.block();
|
|
|
|
|
|
- this.function.destroy(); // Hooks.onLastOperator() released
|
|
|
-
|
|
|
List<ClientRequest> requests = this.exchange.getRequests();
|
|
|
assertThat(requests).hasSize(2);
|
|
|
|
|
@@ -641,147 +635,12 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionTests {
|
|
|
assertThat(getBody(request)).isEmpty();
|
|
|
}
|
|
|
|
|
|
- @Test
|
|
|
- public void filterWhenRequestAttributesNotSetAndHooksNotInitThenDefaultsNotAvailable() {
|
|
|
-// this.function.afterPropertiesSet(); // Hooks.onLastOperator() NOT initialized
|
|
|
- this.function.setDefaultOAuth2AuthorizedClient(true);
|
|
|
-
|
|
|
- MockHttpServletRequest servletRequest = new MockHttpServletRequest();
|
|
|
- MockHttpServletResponse servletResponse = new MockHttpServletResponse();
|
|
|
- RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(servletRequest, servletResponse));
|
|
|
-
|
|
|
- OAuth2User user = mock(OAuth2User.class);
|
|
|
- List<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList("ROLE_USER");
|
|
|
- OAuth2AuthenticationToken authentication = new OAuth2AuthenticationToken(
|
|
|
- user, authorities, this.registration.getRegistrationId());
|
|
|
- SecurityContextHolder.getContext().setAuthentication(authentication);
|
|
|
-
|
|
|
- ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")).build();
|
|
|
-
|
|
|
- this.function.filter(request, this.exchange).block();
|
|
|
-
|
|
|
- List<ClientRequest> requests = this.exchange.getRequests();
|
|
|
- assertThat(requests).hasSize(1);
|
|
|
-
|
|
|
- request = requests.get(0);
|
|
|
- assertThat(request.headers().getFirst(HttpHeaders.AUTHORIZATION)).isNull();
|
|
|
- assertThat(request.url().toASCIIString()).isEqualTo("https://example.com");
|
|
|
- assertThat(request.method()).isEqualTo(HttpMethod.GET);
|
|
|
- assertThat(getBody(request)).isEmpty();
|
|
|
- }
|
|
|
-
|
|
|
- @Test
|
|
|
- public void filterWhenRequestAttributesNotSetAndHooksInitHooksResetThenDefaultsNotAvailable() throws Exception {
|
|
|
- this.function.afterPropertiesSet(); // Hooks.onLastOperator() initialized
|
|
|
- this.function.destroy(); // Hooks.onLastOperator() released
|
|
|
- this.function.setDefaultOAuth2AuthorizedClient(true);
|
|
|
-
|
|
|
- MockHttpServletRequest servletRequest = new MockHttpServletRequest();
|
|
|
- MockHttpServletResponse servletResponse = new MockHttpServletResponse();
|
|
|
- RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(servletRequest, servletResponse));
|
|
|
-
|
|
|
- OAuth2User user = mock(OAuth2User.class);
|
|
|
- List<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList("ROLE_USER");
|
|
|
- OAuth2AuthenticationToken authentication = new OAuth2AuthenticationToken(
|
|
|
- user, authorities, this.registration.getRegistrationId());
|
|
|
- SecurityContextHolder.getContext().setAuthentication(authentication);
|
|
|
-
|
|
|
- ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")).build();
|
|
|
-
|
|
|
- this.function.filter(request, this.exchange).block();
|
|
|
-
|
|
|
- List<ClientRequest> requests = this.exchange.getRequests();
|
|
|
- assertThat(requests).hasSize(1);
|
|
|
-
|
|
|
- request = requests.get(0);
|
|
|
- assertThat(request.headers().getFirst(HttpHeaders.AUTHORIZATION)).isNull();
|
|
|
- assertThat(request.url().toASCIIString()).isEqualTo("https://example.com");
|
|
|
- assertThat(request.method()).isEqualTo(HttpMethod.GET);
|
|
|
- assertThat(getBody(request)).isEmpty();
|
|
|
- }
|
|
|
-
|
|
|
- // gh-7228
|
|
|
- @Test
|
|
|
- public void afterPropertiesSetWhenHooksInitAndOutsideWebSecurityContextThenShouldNotThrowException() throws Exception {
|
|
|
- this.function.afterPropertiesSet(); // Hooks.onLastOperator() initialized
|
|
|
- assertThatCode(() -> Mono.subscriberContext().block())
|
|
|
- .as("RequestContext Hook brakes application outside of web/security context")
|
|
|
- .doesNotThrowAnyException();
|
|
|
- }
|
|
|
-
|
|
|
- @Test
|
|
|
- public void createRequestContextSubscriberIfNecessaryWhenOutsideWebSecurityContextThenReturnOriginalSubscriber() throws Exception {
|
|
|
- BaseSubscriber<Object> originalSubscriber = new BaseSubscriber<Object>() {};
|
|
|
- CoreSubscriber<Object> resultSubscriber = this.function.createRequestContextSubscriberIfNecessary(originalSubscriber);
|
|
|
- assertThat(resultSubscriber).isSameAs(originalSubscriber);
|
|
|
- }
|
|
|
-
|
|
|
- // gh-7228
|
|
|
- @Test
|
|
|
- public void createRequestContextSubscriberWhenRequestResponseProvidedThenCreateWithParentContext() throws Exception {
|
|
|
- testRequestContextSubscriber(new MockHttpServletRequest(), new MockHttpServletResponse(), null);
|
|
|
- }
|
|
|
-
|
|
|
- // gh-7228
|
|
|
- @Test
|
|
|
- public void createRequestContextSubscriberWhenAuthenticationProvidedThenCreateWithParentContext() throws Exception {
|
|
|
- testRequestContextSubscriber(null, null, this.authentication);
|
|
|
- }
|
|
|
-
|
|
|
- @Test
|
|
|
- public void createRequestContextSubscriberWhenParentContextHasDataHolderThenShouldReuseParentContext() throws Exception {
|
|
|
- RequestContextDataHolder testValue = new RequestContextDataHolder(null, null, null);
|
|
|
- final Context parentContext = Context.of(RequestContextSubscriber.REQUEST_CONTEXT_DATA_HOLDER, testValue);
|
|
|
- BaseSubscriber<Object> parent = new BaseSubscriber<Object>() {
|
|
|
- @Override
|
|
|
- public Context currentContext() {
|
|
|
- return parentContext;
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- RequestContextSubscriber<Object> requestContextSubscriber =
|
|
|
- new RequestContextSubscriber<>(parent, null, null, authentication);
|
|
|
-
|
|
|
- Context resultContext = requestContextSubscriber.currentContext();
|
|
|
-
|
|
|
- assertThat(resultContext)
|
|
|
- .describedAs("parent context was replaced")
|
|
|
- .isSameAs(parentContext);
|
|
|
- }
|
|
|
-
|
|
|
- private void testRequestContextSubscriber(MockHttpServletRequest servletRequest,
|
|
|
- MockHttpServletResponse servletResponse,
|
|
|
- Authentication authentication) {
|
|
|
- String testKey = "test_key";
|
|
|
- String testValue = "test_value";
|
|
|
-
|
|
|
- BaseSubscriber<Object> parent = new BaseSubscriber<Object>() {
|
|
|
- @Override
|
|
|
- public Context currentContext() {
|
|
|
- return Context.of(testKey, testValue);
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- RequestContextSubscriber<Object> requestContextSubscriber =
|
|
|
- new RequestContextSubscriber<>(parent, servletRequest, servletResponse, authentication);
|
|
|
-
|
|
|
- Context resultContext = requestContextSubscriber.currentContext();
|
|
|
-
|
|
|
- assertThat(resultContext)
|
|
|
- .describedAs("result context is null")
|
|
|
- .isNotNull();
|
|
|
-
|
|
|
- assertThat(resultContext.getOrEmpty(testKey))
|
|
|
- .describedAs("context is replaced")
|
|
|
- .hasValue(testValue);
|
|
|
-
|
|
|
- Object dataHolder = resultContext.getOrDefault(RequestContextSubscriber.REQUEST_CONTEXT_DATA_HOLDER, null);
|
|
|
- assertThat(dataHolder)
|
|
|
- .describedAs("context is not populated with REQUEST_CONTEXT_DATA_HOLDER")
|
|
|
- .isNotNull()
|
|
|
- .hasFieldOrPropertyWithValue("request", servletRequest)
|
|
|
- .hasFieldOrPropertyWithValue("response", servletResponse)
|
|
|
- .hasFieldOrPropertyWithValue("authentication", authentication);
|
|
|
+ private Context context(HttpServletRequest servletRequest, HttpServletResponse servletResponse, Authentication authentication) {
|
|
|
+ Map<Object, Object> contextAttributes = new HashMap<>();
|
|
|
+ contextAttributes.put(HttpServletRequest.class, servletRequest);
|
|
|
+ contextAttributes.put(HttpServletResponse.class, servletResponse);
|
|
|
+ contextAttributes.put(Authentication.class, authentication);
|
|
|
+ return Context.of(SECURITY_REACTOR_CONTEXT_ATTRIBUTES_KEY, contextAttributes);
|
|
|
}
|
|
|
|
|
|
private static String getBody(ClientRequest request) {
|