@ -27,6 +27,7 @@ import org.springframework.security.MockPortResolver;
@@ -27,6 +27,7 @@ import org.springframework.security.MockPortResolver;
import org.springframework.security.context.SecurityContextHolder ;
import org.springframework.security.providers.anonymous.AnonymousAuthenticationToken ;
import org.springframework.security.util.AuthorityUtils ;
import org.springframework.mock.web.MockHttpServletRequest ;
import org.springframework.mock.web.MockHttpServletResponse ;
@ -46,296 +47,270 @@ import javax.servlet.ServletResponse;
@@ -46,296 +47,270 @@ import javax.servlet.ServletResponse;
* benalex $
* /
public class ExceptionTranslationFilterTests extends TestCase {
//~ Methods ========================================================================================================
protected void tearDown ( ) throws Exception {
super . tearDown ( ) ;
SecurityContextHolder . clearContext ( ) ;
}
public void testAccessDeniedWhenAnonymous ( ) throws Exception {
// Setup our HTTP request
MockHttpServletRequest request = new MockHttpServletRequest ( ) ;
request . setServletPath ( "/secure/page.html" ) ;
request . setServerPort ( 80 ) ;
request . setScheme ( "http" ) ;
request . setServerName ( "www.example.com" ) ;
request . setContextPath ( "/mycontext" ) ;
request . setRequestURI ( "/mycontext/secure/page.html" ) ;
// Setup the FilterChain to thrown an access denied exception
MockFilterChain chain = new MockFilterChain ( true , false , false , false ) ;
// Setup SecurityContextHolder, as filter needs to check if user is
// anonymous
SecurityContextHolder . getContext ( ) . setAuthentication (
new AnonymousAuthenticationToken ( "ignored" , "ignored" ,
new GrantedAuthority [ ] { new GrantedAuthorityImpl ( "IGNORED" ) } ) ) ;
// Test
ExceptionTranslationFilter filter = new ExceptionTranslationFilter ( ) ;
filter . setAuthenticationEntryPoint ( new MockAuthenticationEntryPoint ( "/login.jsp" ) ) ;
MockHttpServletResponse response = new MockHttpServletResponse ( ) ;
filter . doFilter ( request , response , chain ) ;
assertEquals ( "/mycontext/login.jsp" , response . getRedirectedUrl ( ) ) ;
assertEquals ( "http://www.example.com/mycontext/secure/page.html" , AbstractProcessingFilter
. obtainFullSavedRequestUrl ( request ) ) ;
}
public void testAccessDeniedWhenNonAnonymous ( ) throws Exception {
// Setup our HTTP request
MockHttpServletRequest request = new MockHttpServletRequest ( ) ;
request . setServletPath ( "/secure/page.html" ) ;
// Setup the FilterChain to thrown an access denied exception
MockFilterChain chain = new MockFilterChain ( true , false , false , false ) ;
// Setup SecurityContextHolder, as filter needs to check if user is
// anonymous
SecurityContextHolder . getContext ( ) . setAuthentication ( null ) ;
// Setup a new AccessDeniedHandlerImpl that will do a "forward"
AccessDeniedHandlerImpl adh = new AccessDeniedHandlerImpl ( ) ;
adh . setErrorPage ( "/error.jsp" ) ;
// Test
ExceptionTranslationFilter filter = new ExceptionTranslationFilter ( ) ;
filter . setAuthenticationEntryPoint ( new MockAuthenticationEntryPoint ( "/login.jsp" ) ) ;
filter . setAccessDeniedHandler ( adh ) ;
MockHttpServletResponse response = new MockHttpServletResponse ( ) ;
filter . doFilter ( request , response , chain ) ;
assertEquals ( 403 , response . getStatus ( ) ) ;
assertEquals ( AccessDeniedException . class , request . getAttribute (
AccessDeniedHandlerImpl . SPRING_SECURITY_ACCESS_DENIED_EXCEPTION_KEY ) . getClass ( ) ) ;
}
public void testDoFilterWithNonHttpServletRequestDetected ( ) throws Exception {
ExceptionTranslationFilter filter = new ExceptionTranslationFilter ( ) ;
try {
filter . doFilter ( null , new MockHttpServletResponse ( ) , new MockFilterChain ( false , false , false , false ) ) ;
fail ( "Should have thrown ServletException" ) ;
}
catch ( ServletException expected ) {
assertEquals ( "Can only process HttpServletRequest" , expected . getMessage ( ) ) ;
}
}
public void testDoFilterWithNonHttpServletResponseDetected ( ) throws Exception {
ExceptionTranslationFilter filter = new ExceptionTranslationFilter ( ) ;
try {
filter . doFilter ( new MockHttpServletRequest ( null , null ) , null , new MockFilterChain ( false , false , false ,
false ) ) ;
fail ( "Should have thrown ServletException" ) ;
}
catch ( ServletException expected ) {
assertEquals ( "Can only process HttpServletResponse" , expected . getMessage ( ) ) ;
}
}
public void testGettersSetters ( ) {
ExceptionTranslationFilter filter = new ExceptionTranslationFilter ( ) ;
filter . setAuthenticationEntryPoint ( new MockAuthenticationEntryPoint ( "/login.jsp" ) ) ;
assertTrue ( filter . getAuthenticationEntryPoint ( ) ! = null ) ;
filter . setPortResolver ( new MockPortResolver ( 80 , 443 ) ) ;
assertTrue ( filter . getPortResolver ( ) ! = null ) ;
}
public void testRedirectedToLoginFormAndSessionShowsOriginalTargetWhenAuthenticationException ( ) throws Exception {
// Setup our HTTP request
MockHttpServletRequest request = new MockHttpServletRequest ( ) ;
request . setServletPath ( "/secure/page.html" ) ;
request . setServerPort ( 80 ) ;
request . setScheme ( "http" ) ;
request . setServerName ( "www.example.com" ) ;
request . setContextPath ( "/mycontext" ) ;
request . setRequestURI ( "/mycontext/secure/page.html" ) ;
// Setup the FilterChain to thrown an authentication failure exception
MockFilterChain chain = new MockFilterChain ( false , true , false , false ) ;
// Test
ExceptionTranslationFilter filter = new ExceptionTranslationFilter ( ) ;
filter . setAuthenticationEntryPoint ( new MockAuthenticationEntryPoint ( "/login.jsp" ) ) ;
filter . setPortResolver ( new MockPortResolver ( 80 , 443 ) ) ;
/ *
* Disabled the call to afterPropertiesSet as it requires
* applicationContext to be injected before it is invoked . We do not
* have this filter configured in IOC for this test hence no
* ApplicationContext
* /
// filter.afterPropertiesSet();
MockHttpServletResponse response = new MockHttpServletResponse ( ) ;
filter . doFilter ( request , response , chain ) ;
assertEquals ( "/mycontext/login.jsp" , response . getRedirectedUrl ( ) ) ;
assertEquals ( "http://www.example.com/mycontext/secure/page.html" , AbstractProcessingFilter
. obtainFullSavedRequestUrl ( request ) ) ;
}
public void testRedirectedToLoginFormAndSessionShowsOriginalTargetWithExoticPortWhenAuthenticationException ( )
throws Exception {
// Setup our HTTP request
MockHttpServletRequest request = new MockHttpServletRequest ( ) ;
request . setServletPath ( "/secure/page.html" ) ;
request . setServerPort ( 8080 ) ;
request . setScheme ( "http" ) ;
request . setServerName ( "www.example.com" ) ;
request . setContextPath ( "/mycontext" ) ;
request . setRequestURI ( "/mycontext/secure/page.html" ) ;
// Setup the FilterChain to thrown an authentication failure exception
MockFilterChain chain = new MockFilterChain ( false , true , false , false ) ;
// Test
ExceptionTranslationFilter filter = new ExceptionTranslationFilter ( ) ;
filter . setAuthenticationEntryPoint ( new MockAuthenticationEntryPoint ( "/login.jsp" ) ) ;
filter . setPortResolver ( new MockPortResolver ( 8080 , 8443 ) ) ;
/ *
* Disabled the call to afterPropertiesSet as it requires
* applicationContext to be injected before it is invoked . We do not
* have this filter configured in IOC for this test hence no
* ApplicationContext
* /
// filter.afterPropertiesSet();
MockHttpServletResponse response = new MockHttpServletResponse ( ) ;
filter . doFilter ( request , response , chain ) ;
assertEquals ( "/mycontext/login.jsp" , response . getRedirectedUrl ( ) ) ;
assertEquals ( "http://www.example.com:8080/mycontext/secure/page.html" , AbstractProcessingFilter
. obtainFullSavedRequestUrl ( request ) ) ;
}
public void testStartupDetectsMissingAuthenticationEntryPoint ( ) throws Exception {
ExceptionTranslationFilter filter = new ExceptionTranslationFilter ( ) ;
try {
filter . afterPropertiesSet ( ) ;
fail ( "Should have thrown IllegalArgumentException" ) ;
}
catch ( IllegalArgumentException expected ) {
assertEquals ( "authenticationEntryPoint must be specified" , expected . getMessage ( ) ) ;
}
}
public void testStartupDetectsMissingPortResolver ( ) throws Exception {
ExceptionTranslationFilter filter = new ExceptionTranslationFilter ( ) ;
filter . setAuthenticationEntryPoint ( new MockAuthenticationEntryPoint ( "/login.jsp" ) ) ;
filter . setPortResolver ( null ) ;
try {
filter . afterPropertiesSet ( ) ;
fail ( "Should have thrown IllegalArgumentException" ) ;
}
catch ( IllegalArgumentException expected ) {
assertEquals ( "portResolver must be specified" , expected . getMessage ( ) ) ;
}
}
public void testSuccessfulAccessGrant ( ) throws Exception {
// Setup our HTTP request
MockHttpServletRequest request = new MockHttpServletRequest ( ) ;
request . setServletPath ( "/secure/page.html" ) ;
// Setup the FilterChain to thrown no exceptions
MockFilterChain chain = new MockFilterChain ( false , false , false , false ) ;
// Test
ExceptionTranslationFilter filter = new ExceptionTranslationFilter ( ) ;
filter . setAuthenticationEntryPoint ( new MockAuthenticationEntryPoint ( "/login.jsp" ) ) ;
MockHttpServletResponse response = new MockHttpServletResponse ( ) ;
filter . doFilter ( request , response , chain ) ;
}
public void testSuccessfulStartupAndShutdownDown ( ) throws Exception {
ExceptionTranslationFilter filter = new ExceptionTranslationFilter ( ) ;
filter . init ( null ) ;
filter . destroy ( ) ;
assertTrue ( true ) ;
}
public void testThrowIOException ( ) throws Exception {
ExceptionTranslationFilter filter = new ExceptionTranslationFilter ( ) ;
filter . setAuthenticationEntryPoint ( new MockAuthenticationEntryPoint ( "" ) ) ;
/ *
* Disabled the call to afterPropertiesSet as it requires
* applicationContext to be injected before it is invoked . We do not
* have this filter configured in IOC for this test hence no
* ApplicationContext
* /
// filter.afterPropertiesSet();
try {
filter . doFilter ( new MockHttpServletRequest ( ) , new MockHttpServletResponse ( ) , new MockFilterChain ( false ,
false , false , true ) ) ;
fail ( "Should have thrown IOException" ) ;
}
catch ( IOException e ) {
assertNull ( "The IOException thrown should not have been wrapped" , e . getCause ( ) ) ;
}
}
public void testThrowServletException ( ) throws Exception {
ExceptionTranslationFilter filter = new ExceptionTranslationFilter ( ) ;
filter . setAuthenticationEntryPoint ( new MockAuthenticationEntryPoint ( "" ) ) ;
/ *
* Disabled the call to afterPropertiesSet as it requires
* applicationContext to be injected before it is invoked . We do not
* have this filter configured in IOC for this test hence no
* ApplicationContext
* /
// filter.afterPropertiesSet();
try {
filter . doFilter ( new MockHttpServletRequest ( ) , new MockHttpServletResponse ( ) , new MockFilterChain ( false ,
false , true , false ) ) ;
fail ( "Should have thrown ServletException" ) ;
}
catch ( ServletException e ) {
assertNull ( "The ServletException thrown should not have been wrapped" , e . getCause ( ) ) ;
}
}
// ~ Inner Classes =================================================================================================
private class MockFilterChain implements FilterChain {
private boolean throwAccessDenied ;
private boolean throwAuthenticationFailure ;
private boolean throwIOException ;
private boolean throwServletException ;
public MockFilterChain ( boolean throwAccessDenied , boolean throwAuthenticationFailure ,
boolean throwServletException , boolean throwIOException ) {
this . throwAccessDenied = throwAccessDenied ;
this . throwAuthenticationFailure = throwAuthenticationFailure ;
this . throwServletException = throwServletException ;
this . throwIOException = throwIOException ;
}
public void doFilter ( ServletRequest request , ServletResponse response ) throws IOException , ServletException {
if ( throwAccessDenied ) {
throw new AccessDeniedException ( "As requested" ) ;
}
if ( throwAuthenticationFailure ) {
throw new BadCredentialsException ( "As requested" ) ;
}
if ( throwServletException ) {
throw new ServletException ( "As requested" ) ;
}
if ( throwIOException ) {
throw new IOException ( "As requested" ) ;
}
}
}
//~ Methods ========================================================================================================
protected void tearDown ( ) throws Exception {
super . tearDown ( ) ;
SecurityContextHolder . clearContext ( ) ;
}
public void testAccessDeniedWhenAnonymous ( ) throws Exception {
// Setup our HTTP request
MockHttpServletRequest request = new MockHttpServletRequest ( ) ;
request . setServletPath ( "/secure/page.html" ) ;
request . setServerPort ( 80 ) ;
request . setScheme ( "http" ) ;
request . setServerName ( "www.example.com" ) ;
request . setContextPath ( "/mycontext" ) ;
request . setRequestURI ( "/mycontext/secure/page.html" ) ;
// Setup the FilterChain to thrown an access denied exception
MockFilterChain chain = new MockFilterChain ( true , false , false , false ) ;
// Setup SecurityContextHolder, as filter needs to check if user is
// anonymous
SecurityContextHolder . getContext ( ) . setAuthentication (
new AnonymousAuthenticationToken ( "ignored" , "ignored" , AuthorityUtils . createAuthorityList ( "IGNORED" ) ) ) ;
// Test
ExceptionTranslationFilter filter = new ExceptionTranslationFilter ( ) ;
filter . setAuthenticationEntryPoint ( new MockAuthenticationEntryPoint ( "/login.jsp" ) ) ;
MockHttpServletResponse response = new MockHttpServletResponse ( ) ;
filter . doFilter ( request , response , chain ) ;
assertEquals ( "/mycontext/login.jsp" , response . getRedirectedUrl ( ) ) ;
assertEquals ( "http://www.example.com/mycontext/secure/page.html" , AbstractProcessingFilter
. obtainFullSavedRequestUrl ( request ) ) ;
}
public void testAccessDeniedWhenNonAnonymous ( ) throws Exception {
// Setup our HTTP request
MockHttpServletRequest request = new MockHttpServletRequest ( ) ;
request . setServletPath ( "/secure/page.html" ) ;
// Setup the FilterChain to thrown an access denied exception
MockFilterChain chain = new MockFilterChain ( true , false , false , false ) ;
// Setup SecurityContextHolder, as filter needs to check if user is
// anonymous
SecurityContextHolder . getContext ( ) . setAuthentication ( null ) ;
// Setup a new AccessDeniedHandlerImpl that will do a "forward"
AccessDeniedHandlerImpl adh = new AccessDeniedHandlerImpl ( ) ;
adh . setErrorPage ( "/error.jsp" ) ;
// Test
ExceptionTranslationFilter filter = new ExceptionTranslationFilter ( ) ;
filter . setAuthenticationEntryPoint ( new MockAuthenticationEntryPoint ( "/login.jsp" ) ) ;
filter . setAccessDeniedHandler ( adh ) ;
MockHttpServletResponse response = new MockHttpServletResponse ( ) ;
filter . doFilter ( request , response , chain ) ;
assertEquals ( 403 , response . getStatus ( ) ) ;
assertEquals ( AccessDeniedException . class , request . getAttribute (
AccessDeniedHandlerImpl . SPRING_SECURITY_ACCESS_DENIED_EXCEPTION_KEY ) . getClass ( ) ) ;
}
public void testGettersSetters ( ) {
ExceptionTranslationFilter filter = new ExceptionTranslationFilter ( ) ;
filter . setAuthenticationEntryPoint ( new MockAuthenticationEntryPoint ( "/login.jsp" ) ) ;
assertTrue ( filter . getAuthenticationEntryPoint ( ) ! = null ) ;
filter . setPortResolver ( new MockPortResolver ( 80 , 443 ) ) ;
assertTrue ( filter . getPortResolver ( ) ! = null ) ;
}
public void testRedirectedToLoginFormAndSessionShowsOriginalTargetWhenAuthenticationException ( ) throws Exception {
// Setup our HTTP request
MockHttpServletRequest request = new MockHttpServletRequest ( ) ;
request . setServletPath ( "/secure/page.html" ) ;
request . setServerPort ( 80 ) ;
request . setScheme ( "http" ) ;
request . setServerName ( "www.example.com" ) ;
request . setContextPath ( "/mycontext" ) ;
request . setRequestURI ( "/mycontext/secure/page.html" ) ;
// Setup the FilterChain to thrown an authentication failure exception
MockFilterChain chain = new MockFilterChain ( false , true , false , false ) ;
// Test
ExceptionTranslationFilter filter = new ExceptionTranslationFilter ( ) ;
filter . setAuthenticationEntryPoint ( new MockAuthenticationEntryPoint ( "/login.jsp" ) ) ;
filter . setPortResolver ( new MockPortResolver ( 80 , 443 ) ) ;
/ *
* Disabled the call to afterPropertiesSet as it requires
* applicationContext to be injected before it is invoked . We do not
* have this filter configured in IOC for this test hence no
* ApplicationContext
* /
// filter.afterPropertiesSet();
MockHttpServletResponse response = new MockHttpServletResponse ( ) ;
filter . doFilter ( request , response , chain ) ;
assertEquals ( "/mycontext/login.jsp" , response . getRedirectedUrl ( ) ) ;
assertEquals ( "http://www.example.com/mycontext/secure/page.html" , AbstractProcessingFilter
. obtainFullSavedRequestUrl ( request ) ) ;
}
public void testRedirectedToLoginFormAndSessionShowsOriginalTargetWithExoticPortWhenAuthenticationException ( )
throws Exception {
// Setup our HTTP request
MockHttpServletRequest request = new MockHttpServletRequest ( ) ;
request . setServletPath ( "/secure/page.html" ) ;
request . setServerPort ( 8080 ) ;
request . setScheme ( "http" ) ;
request . setServerName ( "www.example.com" ) ;
request . setContextPath ( "/mycontext" ) ;
request . setRequestURI ( "/mycontext/secure/page.html" ) ;
// Setup the FilterChain to thrown an authentication failure exception
MockFilterChain chain = new MockFilterChain ( false , true , false , false ) ;
// Test
ExceptionTranslationFilter filter = new ExceptionTranslationFilter ( ) ;
filter . setAuthenticationEntryPoint ( new MockAuthenticationEntryPoint ( "/login.jsp" ) ) ;
filter . setPortResolver ( new MockPortResolver ( 8080 , 8443 ) ) ;
/ *
* Disabled the call to afterPropertiesSet as it requires
* applicationContext to be injected before it is invoked . We do not
* have this filter configured in IOC for this test hence no
* ApplicationContext
* /
// filter.afterPropertiesSet();
MockHttpServletResponse response = new MockHttpServletResponse ( ) ;
filter . doFilter ( request , response , chain ) ;
assertEquals ( "/mycontext/login.jsp" , response . getRedirectedUrl ( ) ) ;
assertEquals ( "http://www.example.com:8080/mycontext/secure/page.html" , AbstractProcessingFilter
. obtainFullSavedRequestUrl ( request ) ) ;
}
public void testStartupDetectsMissingAuthenticationEntryPoint ( ) throws Exception {
ExceptionTranslationFilter filter = new ExceptionTranslationFilter ( ) ;
try {
filter . afterPropertiesSet ( ) ;
fail ( "Should have thrown IllegalArgumentException" ) ;
}
catch ( IllegalArgumentException expected ) {
assertEquals ( "authenticationEntryPoint must be specified" , expected . getMessage ( ) ) ;
}
}
public void testStartupDetectsMissingPortResolver ( ) throws Exception {
ExceptionTranslationFilter filter = new ExceptionTranslationFilter ( ) ;
filter . setAuthenticationEntryPoint ( new MockAuthenticationEntryPoint ( "/login.jsp" ) ) ;
filter . setPortResolver ( null ) ;
try {
filter . afterPropertiesSet ( ) ;
fail ( "Should have thrown IllegalArgumentException" ) ;
}
catch ( IllegalArgumentException expected ) {
assertEquals ( "portResolver must be specified" , expected . getMessage ( ) ) ;
}
}
public void testSuccessfulAccessGrant ( ) throws Exception {
// Setup our HTTP request
MockHttpServletRequest request = new MockHttpServletRequest ( ) ;
request . setServletPath ( "/secure/page.html" ) ;
// Setup the FilterChain to thrown no exceptions
MockFilterChain chain = new MockFilterChain ( false , false , false , false ) ;
// Test
ExceptionTranslationFilter filter = new ExceptionTranslationFilter ( ) ;
filter . setAuthenticationEntryPoint ( new MockAuthenticationEntryPoint ( "/login.jsp" ) ) ;
MockHttpServletResponse response = new MockHttpServletResponse ( ) ;
filter . doFilter ( request , response , chain ) ;
}
public void testSuccessfulStartupAndShutdownDown ( ) throws Exception {
ExceptionTranslationFilter filter = new ExceptionTranslationFilter ( ) ;
filter . init ( null ) ;
filter . destroy ( ) ;
assertTrue ( true ) ;
}
public void testThrowIOException ( ) throws Exception {
ExceptionTranslationFilter filter = new ExceptionTranslationFilter ( ) ;
filter . setAuthenticationEntryPoint ( new MockAuthenticationEntryPoint ( "" ) ) ;
/ *
* Disabled the call to afterPropertiesSet as it requires
* applicationContext to be injected before it is invoked . We do not
* have this filter configured in IOC for this test hence no
* ApplicationContext
* /
// filter.afterPropertiesSet();
try {
filter . doFilter ( new MockHttpServletRequest ( ) , new MockHttpServletResponse ( ) , new MockFilterChain ( false ,
false , false , true ) ) ;
fail ( "Should have thrown IOException" ) ;
}
catch ( IOException e ) {
assertNull ( "The IOException thrown should not have been wrapped" , e . getCause ( ) ) ;
}
}
public void testThrowServletException ( ) throws Exception {
ExceptionTranslationFilter filter = new ExceptionTranslationFilter ( ) ;
filter . setAuthenticationEntryPoint ( new MockAuthenticationEntryPoint ( "" ) ) ;
/ *
* Disabled the call to afterPropertiesSet as it requires
* applicationContext to be injected before it is invoked . We do not
* have this filter configured in IOC for this test hence no
* ApplicationContext
* /
// filter.afterPropertiesSet();
try {
filter . doFilter ( new MockHttpServletRequest ( ) , new MockHttpServletResponse ( ) , new MockFilterChain ( false ,
false , true , false ) ) ;
fail ( "Should have thrown ServletException" ) ;
}
catch ( ServletException e ) {
assertNull ( "The ServletException thrown should not have been wrapped" , e . getCause ( ) ) ;
}
}
// ~ Inner Classes =================================================================================================
private class MockFilterChain implements FilterChain {
private boolean throwAccessDenied ;
private boolean throwAuthenticationFailure ;
private boolean throwIOException ;
private boolean throwServletException ;
public MockFilterChain ( boolean throwAccessDenied , boolean throwAuthenticationFailure ,
boolean throwServletException , boolean throwIOException ) {
this . throwAccessDenied = throwAccessDenied ;
this . throwAuthenticationFailure = throwAuthenticationFailure ;
this . throwServletException = throwServletException ;
this . throwIOException = throwIOException ;
}
public void doFilter ( ServletRequest request , ServletResponse response ) throws IOException , ServletException {
if ( throwAccessDenied ) {
throw new AccessDeniedException ( "As requested" ) ;
}
if ( throwAuthenticationFailure ) {
throw new BadCredentialsException ( "As requested" ) ;
}
if ( throwServletException ) {
throw new ServletException ( "As requested" ) ;
}
if ( throwIOException ) {
throw new IOException ( "As requested" ) ;
}
}
}
}