|
@@ -38,6 +38,7 @@ import org.springframework.security.config.test.SpringTestContextExtension;
|
|
|
import org.springframework.security.core.context.SecurityContext;
|
|
|
import org.springframework.security.core.session.SessionRegistry;
|
|
|
import org.springframework.security.core.userdetails.PasswordEncodedUser;
|
|
|
+import org.springframework.security.web.DefaultSecurityFilterChain;
|
|
|
import org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy;
|
|
|
import org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy;
|
|
|
import org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy;
|
|
@@ -51,19 +52,26 @@ import org.springframework.security.web.session.SessionManagementFilter;
|
|
|
import org.springframework.test.web.servlet.MockMvc;
|
|
|
import org.springframework.test.web.servlet.MvcResult;
|
|
|
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
|
|
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
|
|
+import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
+import org.springframework.web.bind.annotation.RestController;
|
|
|
|
|
|
import static org.assertj.core.api.Assertions.assertThat;
|
|
|
import static org.mockito.ArgumentMatchers.any;
|
|
|
import static org.mockito.BDDMockito.given;
|
|
|
+import static org.mockito.Mockito.atLeastOnce;
|
|
|
import static org.mockito.Mockito.mock;
|
|
|
+import static org.mockito.Mockito.never;
|
|
|
import static org.mockito.Mockito.spy;
|
|
|
import static org.mockito.Mockito.verify;
|
|
|
import static org.mockito.Mockito.verifyNoInteractions;
|
|
|
import static org.springframework.security.config.Customizer.withDefaults;
|
|
|
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
|
|
|
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
|
|
|
+import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
|
|
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
|
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
|
|
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
|
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
|
|
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
|
|
|
|
@@ -295,6 +303,46 @@ public class SessionManagementConfigurerTests {
|
|
|
verifyNoInteractions(SessionRegistryTwoBeansConfig.SESSION_REGISTRY_TWO);
|
|
|
}
|
|
|
|
|
|
+ @Test
|
|
|
+ public void whenEnableSessionUrlRewritingTrueThenEncodeNotInvoked() throws Exception {
|
|
|
+ this.spring.register(EnableUrlRewriteConfig.class).autowire();
|
|
|
+ // @formatter:off
|
|
|
+ this.mvc = MockMvcBuilders.webAppContextSetup(this.spring.getContext())
|
|
|
+ .addFilters((request, response, chain) -> {
|
|
|
+ HttpServletResponse responseToSpy = spy((HttpServletResponse) response);
|
|
|
+ chain.doFilter(request, responseToSpy);
|
|
|
+ verify(responseToSpy, atLeastOnce()).encodeRedirectURL(any());
|
|
|
+ verify(responseToSpy, atLeastOnce()).encodeRedirectUrl(any());
|
|
|
+ verify(responseToSpy, atLeastOnce()).encodeURL(any());
|
|
|
+ verify(responseToSpy, atLeastOnce()).encodeUrl(any());
|
|
|
+ })
|
|
|
+ .apply(springSecurity())
|
|
|
+ .build();
|
|
|
+ // @formatter:on
|
|
|
+
|
|
|
+ this.mvc.perform(get("/")).andExpect(content().string("encoded"));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void whenDefaultThenEncodeNotInvoked() throws Exception {
|
|
|
+ this.spring.register(DefaultUrlRewriteConfig.class).autowire();
|
|
|
+ // @formatter:off
|
|
|
+ this.mvc = MockMvcBuilders.webAppContextSetup(this.spring.getContext())
|
|
|
+ .addFilters((request, response, chain) -> {
|
|
|
+ HttpServletResponse responseToSpy = spy((HttpServletResponse) response);
|
|
|
+ chain.doFilter(request, responseToSpy);
|
|
|
+ verify(responseToSpy, never()).encodeRedirectURL(any());
|
|
|
+ verify(responseToSpy, never()).encodeRedirectUrl(any());
|
|
|
+ verify(responseToSpy, never()).encodeURL(any());
|
|
|
+ verify(responseToSpy, never()).encodeUrl(any());
|
|
|
+ })
|
|
|
+ .apply(springSecurity())
|
|
|
+ .build();
|
|
|
+ // @formatter:on
|
|
|
+
|
|
|
+ this.mvc.perform(get("/")).andExpect(content().string("encoded"));
|
|
|
+ }
|
|
|
+
|
|
|
@EnableWebSecurity
|
|
|
static class SessionManagementRequestCacheConfig extends WebSecurityConfigurerAdapter {
|
|
|
|
|
@@ -569,4 +617,49 @@ public class SessionManagementConfigurerTests {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ @EnableWebSecurity
|
|
|
+ static class DefaultUrlRewriteConfig {
|
|
|
+
|
|
|
+ @Bean
|
|
|
+ DefaultSecurityFilterChain configure(HttpSecurity http) throws Exception {
|
|
|
+ return http.build();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Bean
|
|
|
+ EncodesUrls encodesUrls() {
|
|
|
+ return new EncodesUrls();
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @EnableWebSecurity
|
|
|
+ static class EnableUrlRewriteConfig {
|
|
|
+
|
|
|
+ @Bean
|
|
|
+ DefaultSecurityFilterChain configure(HttpSecurity http) throws Exception {
|
|
|
+ http.sessionManagement((sessions) -> sessions.enableSessionUrlRewriting(true));
|
|
|
+ return http.build();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Bean
|
|
|
+ EncodesUrls encodesUrls() {
|
|
|
+ return new EncodesUrls();
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @RestController
|
|
|
+ static class EncodesUrls {
|
|
|
+
|
|
|
+ @RequestMapping("/")
|
|
|
+ String encoded(HttpServletResponse response) {
|
|
|
+ response.encodeURL("/foo");
|
|
|
+ response.encodeUrl("/foo");
|
|
|
+ response.encodeRedirectURL("/foo");
|
|
|
+ response.encodeRedirectUrl("/foo");
|
|
|
+ return "encoded";
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
}
|