Add DisableUrlRewritingFilter

Closes gh-11084
This commit is contained in:
Rob Winch 2022-04-06 14:42:47 -05:00
parent 32b83aae63
commit 39b0620a84
14 changed files with 375 additions and 36 deletions

View File

@ -42,6 +42,7 @@ import org.springframework.security.web.jaasapi.JaasApiIntegrationFilter;
import org.springframework.security.web.savedrequest.RequestCacheAwareFilter;
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
import org.springframework.security.web.session.ConcurrentSessionFilter;
import org.springframework.security.web.session.DisableEncodeUrlFilter;
import org.springframework.security.web.session.SessionManagementFilter;
/**
@ -124,6 +125,7 @@ public interface HttpSecurityBuilder<H extends HttpSecurityBuilder<H>>
* The ordering of the Filters is:
*
* <ul>
* <li>{@link DisableEncodeUrlFilter}</li>
* <li>{@link ChannelProcessingFilter}</li>
* <li>{@link SecurityContextPersistenceFilter}</li>
* <li>{@link LogoutFilter}</li>

View File

@ -46,6 +46,7 @@ import org.springframework.security.web.jaasapi.JaasApiIntegrationFilter;
import org.springframework.security.web.savedrequest.RequestCacheAwareFilter;
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
import org.springframework.security.web.session.ConcurrentSessionFilter;
import org.springframework.security.web.session.DisableEncodeUrlFilter;
import org.springframework.security.web.session.SessionManagementFilter;
import org.springframework.web.filter.CorsFilter;
@ -68,6 +69,7 @@ final class FilterOrderRegistration {
FilterOrderRegistration() {
Step order = new Step(INITIAL_ORDER, ORDER_STEP);
put(DisableEncodeUrlFilter.class, order.next());
put(ChannelProcessingFilter.class, order.next());
order.next(); // gh-8105
put(WebAsyncManagerIntegrationFilter.class, order.next());

View File

@ -52,6 +52,7 @@ import org.springframework.security.web.context.SecurityContextRepository;
import org.springframework.security.web.savedrequest.NullRequestCache;
import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.security.web.session.ConcurrentSessionFilter;
import org.springframework.security.web.session.DisableEncodeUrlFilter;
import org.springframework.security.web.session.InvalidSessionStrategy;
import org.springframework.security.web.session.SessionInformationExpiredStrategy;
import org.springframework.security.web.session.SessionManagementFilter;
@ -376,6 +377,9 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
concurrentSessionFilter = postProcess(concurrentSessionFilter);
http.addFilter(concurrentSessionFilter);
}
if (!this.enableSessionUrlRewriting) {
http.addFilter(new DisableEncodeUrlFilter());
}
}
private ConcurrentSessionFilter createConcurrencyFilter(H http) {

View File

@ -68,6 +68,7 @@ import org.springframework.security.web.savedrequest.NullRequestCache;
import org.springframework.security.web.savedrequest.RequestCacheAwareFilter;
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
import org.springframework.security.web.session.ConcurrentSessionFilter;
import org.springframework.security.web.session.DisableEncodeUrlFilter;
import org.springframework.security.web.session.SessionManagementFilter;
import org.springframework.security.web.session.SimpleRedirectInvalidSessionStrategy;
import org.springframework.security.web.session.SimpleRedirectSessionInformationExpiredStrategy;
@ -179,6 +180,8 @@ class HttpConfigurationBuilder {
private BeanDefinition csrfFilter;
private BeanDefinition disableUrlRewriteFilter;
private BeanDefinition wellKnownChangePasswordRedirectFilter;
private BeanMetadataElement csrfLogoutHandler;
@ -204,6 +207,7 @@ class HttpConfigurationBuilder {
String createSession = element.getAttribute(ATT_CREATE_SESSION);
this.sessionPolicy = !StringUtils.hasText(createSession) ? SessionCreationPolicy.IF_REQUIRED
: createPolicy(createSession);
createDisableEncodeUrlFilter();
createCsrfFilter();
createSecurityPersistence();
createSessionManagementFilters();
@ -319,10 +323,6 @@ class HttpConfigurationBuilder {
private void createSecurityContextRepository() {
String repoRef = this.httpElt.getAttribute(ATT_SECURITY_CONTEXT_REPOSITORY);
String disableUrlRewriting = this.httpElt.getAttribute(ATT_DISABLE_URL_REWRITING);
if (!StringUtils.hasText(disableUrlRewriting)) {
disableUrlRewriting = "true";
}
if (!StringUtils.hasText(repoRef)) {
BeanDefinitionBuilder contextRepo;
if (this.sessionPolicy == SessionCreationPolicy.STATELESS) {
@ -340,7 +340,7 @@ class HttpConfigurationBuilder {
default:
contextRepo.addPropertyValue("allowSessionCreation", Boolean.TRUE);
}
if ("true".equals(disableUrlRewriting)) {
if (isDisableUrlRewriting()) {
contextRepo.addPropertyValue("disableUrlRewriting", Boolean.TRUE);
}
}
@ -352,6 +352,11 @@ class HttpConfigurationBuilder {
this.contextRepoRef = new RuntimeBeanReference(repoRef);
}
private boolean isDisableUrlRewriting() {
String disableUrlRewriting = this.httpElt.getAttribute(ATT_DISABLE_URL_REWRITING);
return !"false".equals(disableUrlRewriting);
}
private void createSecurityContextHolderFilter() {
BeanDefinitionBuilder filter = BeanDefinitionBuilder.rootBeanDefinition(SecurityContextHolderFilter.class);
filter.addConstructorArgValue(this.contextRepoRef);
@ -718,6 +723,12 @@ class HttpConfigurationBuilder {
}
private void createDisableEncodeUrlFilter() {
if (isDisableUrlRewriting()) {
this.disableUrlRewriteFilter = new RootBeanDefinition(DisableEncodeUrlFilter.class);
}
}
private void createCsrfFilter() {
Element elmt = DomUtils.getChildElementByTagName(this.httpElt, Elements.CSRF);
this.csrfParser = new CsrfBeanDefinitionParser();
@ -757,6 +768,9 @@ class HttpConfigurationBuilder {
List<OrderDecorator> getFilters() {
List<OrderDecorator> filters = new ArrayList<>();
if (this.disableUrlRewriteFilter != null) {
filters.add(new OrderDecorator(this.disableUrlRewriteFilter, SecurityFilters.DISABLE_ENCODE_URL_FILTER));
}
if (this.cpf != null) {
filters.add(new OrderDecorator(this.cpf, SecurityFilters.CHANNEL_FILTER));
}

View File

@ -29,6 +29,8 @@ enum SecurityFilters {
FIRST(Integer.MIN_VALUE),
DISABLE_ENCODE_URL_FILTER,
CHANNEL_FILTER,
SECURITY_CONTEXT_FILTER,

View File

@ -1318,4 +1318,4 @@ position =
## The explicit position at which the custom-filter should be placed in the chain. Use if you are replacing a standard filter.
attribute position {named-security-filter}
named-security-filter = "FIRST" | "CHANNEL_FILTER" | "SECURITY_CONTEXT_FILTER" | "CONCURRENT_SESSION_FILTER" | "WEB_ASYNC_MANAGER_FILTER" | "HEADERS_FILTER" | "CORS_FILTER" | "SAML2_LOGOUT_REQUEST_FILTER" | "SAML2_LOGOUT_RESPONSE_FILTER" | "CSRF_FILTER" | "SAML2_LOGOUT_FILTER" | "LOGOUT_FILTER" | "OAUTH2_AUTHORIZATION_REQUEST_FILTER" | "SAML2_AUTHENTICATION_REQUEST_FILTER" | "X509_FILTER" | "PRE_AUTH_FILTER" | "CAS_FILTER" | "OAUTH2_LOGIN_FILTER" | "SAML2_AUTHENTICATION_FILTER" | "FORM_LOGIN_FILTER" | "OPENID_FILTER" | "LOGIN_PAGE_FILTER" |"LOGOUT_PAGE_FILTER" | "DIGEST_AUTH_FILTER" | "BEARER_TOKEN_AUTH_FILTER" | "BASIC_AUTH_FILTER" | "REQUEST_CACHE_FILTER" | "SERVLET_API_SUPPORT_FILTER" | "JAAS_API_SUPPORT_FILTER" | "REMEMBER_ME_FILTER" | "ANONYMOUS_FILTER" | "OAUTH2_AUTHORIZATION_CODE_GRANT_FILTER" | "WELL_KNOWN_CHANGE_PASSWORD_REDIRECT_FILTER" | "SESSION_MANAGEMENT_FILTER" | "EXCEPTION_TRANSLATION_FILTER" | "FILTER_SECURITY_INTERCEPTOR" | "SWITCH_USER_FILTER" | "LAST"
named-security-filter = "FIRST" | "DISABLE_ENCODE_URL_FILTER" | "CHANNEL_FILTER" | "SECURITY_CONTEXT_FILTER" | "CONCURRENT_SESSION_FILTER" | "WEB_ASYNC_MANAGER_FILTER" | "HEADERS_FILTER" | "CORS_FILTER" | "SAML2_LOGOUT_REQUEST_FILTER" | "SAML2_LOGOUT_RESPONSE_FILTER" | "CSRF_FILTER" | "SAML2_LOGOUT_FILTER" | "LOGOUT_FILTER" | "OAUTH2_AUTHORIZATION_REQUEST_FILTER" | "SAML2_AUTHENTICATION_REQUEST_FILTER" | "X509_FILTER" | "PRE_AUTH_FILTER" | "CAS_FILTER" | "OAUTH2_LOGIN_FILTER" | "SAML2_AUTHENTICATION_FILTER" | "FORM_LOGIN_FILTER" | "OPENID_FILTER" | "LOGIN_PAGE_FILTER" |"LOGOUT_PAGE_FILTER" | "DIGEST_AUTH_FILTER" | "BEARER_TOKEN_AUTH_FILTER" | "BASIC_AUTH_FILTER" | "REQUEST_CACHE_FILTER" | "SERVLET_API_SUPPORT_FILTER" | "JAAS_API_SUPPORT_FILTER" | "REMEMBER_ME_FILTER" | "ANONYMOUS_FILTER" | "OAUTH2_AUTHORIZATION_CODE_GRANT_FILTER" | "WELL_KNOWN_CHANGE_PASSWORD_REDIRECT_FILTER" | "SESSION_MANAGEMENT_FILTER" | "EXCEPTION_TRANSLATION_FILTER" | "FILTER_SECURITY_INTERCEPTOR" | "SWITCH_USER_FILTER" | "LAST"

View File

@ -3720,6 +3720,7 @@
<xs:simpleType name="named-security-filter">
<xs:restriction base="xs:token">
<xs:enumeration value="FIRST"/>
<xs:enumeration value="DISABLE_ENCODE_URL_FILTER"/>
<xs:enumeration value="CHANNEL_FILTER"/>
<xs:enumeration value="SECURITY_CONTEXT_FILTER"/>
<xs:enumeration value="CONCURRENT_SESSION_FILTER"/>

View File

@ -53,7 +53,7 @@ public class FilterOrderRegistrationTests {
@Test
public void putWhenPredefinedFilterThenDoesNotOverride() {
int position = 100;
int position = 200;
Integer predefinedFilterOrderBefore = this.filterOrderRegistration.getOrder(ChannelProcessingFilter.class);
this.filterOrderRegistration.put(MyFilter.class, position);
Integer myFilterOrder = this.filterOrderRegistration.getOrder(MyFilter.class);

View File

@ -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";
}
}
}

View File

@ -103,6 +103,7 @@ import org.springframework.security.web.header.HeaderWriterFilter;
import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.security.web.savedrequest.RequestCacheAwareFilter;
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
import org.springframework.security.web.session.DisableEncodeUrlFilter;
import org.springframework.security.web.session.SessionManagementFilter;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.test.web.servlet.MockMvc;
@ -121,6 +122,8 @@ import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.willAnswer;
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.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
@ -540,6 +543,28 @@ public class MiscHttpConfigTests {
assertThat(response.getRedirectedUrl()).isEqualTo("http://localhost/login");
}
@Test
public void configureWhenUsingDisableUrlRewritingAndCustomRepositoryThenRedirectIsNotEncodedByResponse()
throws IOException, ServletException {
this.spring.configLocations(xml("DisableUrlRewriting-NullSecurityContextRepository")).autowire();
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
MockHttpServletResponse responseToSpy = spy(new MockHttpServletResponse());
FilterChainProxy proxy = this.spring.getContext().getBean(FilterChainProxy.class);
proxy.doFilter(request, responseToSpy, (req, resp) -> {
HttpServletResponse httpResponse = (HttpServletResponse) resp;
httpResponse.encodeUrl("/");
httpResponse.encodeURL("/");
httpResponse.encodeRedirectUrl("/");
httpResponse.encodeRedirectURL("/");
httpResponse.getWriter().write("encodeRedirect");
});
verify(responseToSpy, never()).encodeRedirectURL(any());
verify(responseToSpy, never()).encodeRedirectUrl(any());
verify(responseToSpy, never()).encodeURL(any());
verify(responseToSpy, never()).encodeUrl(any());
assertThat(responseToSpy.getContentAsString()).isEqualTo("encodeRedirect");
}
@Test
public void configureWhenUserDetailsServiceInParentContextThenLocatesSuccessfully() {
assertThatExceptionOfType(BeansException.class).isThrownBy(
@ -755,6 +780,7 @@ public class MiscHttpConfigTests {
private void assertThatFiltersMatchExpectedAutoConfigList(String url) {
Iterator<Filter> filters = getFilters(url).iterator();
assertThat(filters.next()).isInstanceOf(DisableEncodeUrlFilter.class);
assertThat(filters.next()).isInstanceOf(SecurityContextPersistenceFilter.class);
assertThat(filters.next()).isInstanceOf(WebAsyncManagerIntegrationFilter.class);
assertThat(filters.next()).isInstanceOf(HeaderWriterFilter.class);

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2002-2018 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
~
~ https://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.
-->
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/security"
xsi:schemaLocation="
http://www.springframework.org/schema/security
https://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<http auto-config="true" disable-url-rewriting="true" security-context-repository-ref="securityContextRepository">
<intercept-url pattern="/**" access="permitAll"/>
</http>
<b:bean id="securityContextRepository" class="org.springframework.security.web.context.NullSecurityContextRepository"/>
<b:import resource="userservice.xml"/>
</b:beans>

View File

@ -253,6 +253,10 @@ The filters are listed in the order in which they occur in the filter chain.
|===
| Alias | Filter Class | Namespace Element or Attribute
| DISABLE_ENCODE_URL_FILTER
| `DisableEncodeUrlFilter`
| `http@disable-url-rewriting`
| CHANNEL_FILTER
| `ChannelProcessingFilter`
| `http/intercept-url@requires-channel`

View File

@ -0,0 +1,86 @@
/*
* Copyright 2002-2022 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
*
* https://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.web.session;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import org.springframework.web.filter.OncePerRequestFilter;
/**
* Disables encoding URLs using the {@link HttpServletResponse} to prevent including the
* session id in URLs which is not considered URL because the session id can be leaked in
* things like HTTP access logs.
*
* @author Rob Winch
* @since 5.7
*/
public class DisableEncodeUrlFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
filterChain.doFilter(request, new DisableEncodeUrlResponseWrapper(response));
}
/**
* Disables URL rewriting for the {@link HttpServletResponse} to prevent including the
* session id in URLs which is not considered URL because the session id can be leaked
* in things like HTTP access logs.
*
* @author Rob Winch
* @since 5.7
*/
private static final class DisableEncodeUrlResponseWrapper extends HttpServletResponseWrapper {
/**
* Constructs a response adaptor wrapping the given response.
* @param response the {@link HttpServletResponse} to be wrapped.
* @throws IllegalArgumentException if the response is null
*/
private DisableEncodeUrlResponseWrapper(HttpServletResponse response) {
super(response);
}
@Override
public String encodeRedirectUrl(String url) {
return url;
}
@Override
public String encodeRedirectURL(String url) {
return url;
}
@Override
public String encodeUrl(String url) {
return url;
}
@Override
public String encodeURL(String url) {
return url;
}
}
}

View File

@ -0,0 +1,73 @@
/*
* Copyright 2002-2022 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
*
* https://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.web.session;
import java.util.function.Consumer;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.mockito.Mockito.verifyNoInteractions;
/**
* @author Rob Winch
*/
@ExtendWith(MockitoExtension.class)
class DisableEncodeUrlFilterTests {
@Mock
private HttpServletRequest request;
@Mock
private HttpServletResponse response;
private DisableEncodeUrlFilter filter = new DisableEncodeUrlFilter();
@Test
void doFilterDisablesEncodeURL() throws Exception {
verifyDoFilterDoesNotInteractWithResponse((httpResponse) -> httpResponse.encodeURL("/"));
}
@Test
void doFilterDisablesEncodeUrl() throws Exception {
verifyDoFilterDoesNotInteractWithResponse((httpResponse) -> httpResponse.encodeUrl("/"));
}
@Test
void doFilterDisablesEncodeRedirectURL() throws Exception {
verifyDoFilterDoesNotInteractWithResponse((httpResponse) -> httpResponse.encodeRedirectURL("/"));
}
@Test
void doFilterDisablesEncodeRedirectUrl() throws Exception {
verifyDoFilterDoesNotInteractWithResponse((httpResponse) -> httpResponse.encodeRedirectUrl("/"));
}
private void verifyDoFilterDoesNotInteractWithResponse(Consumer<HttpServletResponse> toInvoke) throws Exception {
this.filter.doFilter(this.request, this.response, (request, response) -> {
HttpServletResponse httpResponse = (HttpServletResponse) response;
toInvoke.accept(httpResponse);
});
verifyNoInteractions(this.response);
}
}