ExceptionTranslationFilter does not handle committed responses

Fixes: gh-5273
This commit is contained in:
Rob Winch 2018-04-30 15:34:20 -05:00
parent eb067bc3a1
commit 9bb841ac67
3 changed files with 44 additions and 15 deletions

View File

@ -131,6 +131,7 @@ class InterceptUrlConfigTests extends AbstractHttpConfigTests {
when: 'user cannot access otheruser'
request = new MockHttpServletRequest(method:'GET', servletPath : '/user/otheruser/abc')
login(request, 'user', 'password')
response = new MockHttpServletResponse()
chain.reset()
springSecurityFilterChain.doFilter(request,response,chain)
then: 'The response is OK'
@ -138,6 +139,7 @@ class InterceptUrlConfigTests extends AbstractHttpConfigTests {
when: 'user can access case insensitive URL'
request = new MockHttpServletRequest(method:'GET', servletPath : '/USER/user/abc')
login(request, 'user', 'password')
response = new MockHttpServletResponse()
chain.reset()
springSecurityFilterChain.doFilter(request,response,chain)
then: 'The response is OK'
@ -164,6 +166,7 @@ class InterceptUrlConfigTests extends AbstractHttpConfigTests {
when: 'user cannot access otheruser'
request = new MockHttpServletRequest(method:'GET', servletPath : '/user/otheruser/abc')
login(request, 'user', 'password')
response = new MockHttpServletResponse()
chain.reset()
springSecurityFilterChain.doFilter(request,response,chain)
then: 'The response is OK'
@ -171,6 +174,7 @@ class InterceptUrlConfigTests extends AbstractHttpConfigTests {
when: 'user can access case insensitive URL'
request = new MockHttpServletRequest(method:'GET', servletPath : '/USER/user/abc')
login(request, 'user', 'password')
response = new MockHttpServletResponse()
chain.reset()
springSecurityFilterChain.doFilter(request,response,chain)
then: 'The response is OK'

View File

@ -135,6 +135,9 @@ public class ExceptionTranslationFilter extends GenericFilterBean {
}
if (ase != null) {
if (response.isCommitted()) {
throw new ServletException("Unable to handle the Spring Security Exception because the response is already committed.", ex);
}
handleSpringSecurityException(request, response, chain, ase);
}
else {

View File

@ -15,6 +15,23 @@
*/
package org.springframework.security.web.access;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verifyZeroInteractions;
import java.io.IOException;
import java.util.Locale;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@ -36,20 +53,6 @@ import org.springframework.security.web.WebAttributes;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.savedrequest.SavedRequest;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Locale;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
/**
* Tests {@link ExceptionTranslationFilter}.
*
@ -302,7 +305,26 @@ public class ExceptionTranslationFilterTests {
}
}
private final AuthenticationEntryPoint mockEntryPoint = new AuthenticationEntryPoint() {
@Test
public void doFilterWhenResponseCommittedThenRethrowsException() throws Exception {
this.mockEntryPoint = mock(AuthenticationEntryPoint.class);
FilterChain chain = (request, response) -> {
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST);
throw new AccessDeniedException("Denied");
};
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
ExceptionTranslationFilter filter = new ExceptionTranslationFilter(mockEntryPoint);
assertThatThrownBy(() -> filter.doFilter(request, response, chain))
.isInstanceOf(ServletException.class)
.hasCauseInstanceOf(AccessDeniedException.class);
verifyZeroInteractions(mockEntryPoint);
}
private AuthenticationEntryPoint mockEntryPoint = new AuthenticationEntryPoint() {
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException,
ServletException {