SEC-180: BasicProcessingFilter should configurably ignore authentication failures.

This commit is contained in:
Ben Alex 2006-02-09 06:41:31 +00:00
parent e63b2ec9e6
commit b1dd784dee
2 changed files with 64 additions and 23 deletions

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,8 +18,11 @@ package org.acegisecurity.ui.basicauth;
import org.acegisecurity.Authentication;
import org.acegisecurity.AuthenticationException;
import org.acegisecurity.AuthenticationManager;
import org.acegisecurity.context.SecurityContextHolder;
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.acegisecurity.ui.AuthenticationEntryPoint;
import org.acegisecurity.ui.WebAuthenticationDetails;
@ -78,8 +81,9 @@ import javax.servlet.http.HttpServletResponse;
* </p>
*
* <p>
* If authentication fails, an {@link AuthenticationEntryPoint} implementation
* is called. Usually this should be {@link BasicProcessingFilterEntryPoint},
* If authentication fails and <code>ignoreFailure</code> is <code>false</code>
* (the default), an {@link AuthenticationEntryPoint} implementation is
* called. Usually this should be {@link BasicProcessingFilterEntryPoint},
* which will prompt the user to authenticate again via BASIC authentication.
* </p>
*
@ -110,27 +114,10 @@ public class BasicProcessingFilter implements Filter, InitializingBean {
private AuthenticationEntryPoint authenticationEntryPoint;
private AuthenticationManager authenticationManager;
private boolean ignoreFailure = false;
//~ Methods ================================================================
public void setAuthenticationEntryPoint(
AuthenticationEntryPoint authenticationEntryPoint) {
this.authenticationEntryPoint = authenticationEntryPoint;
}
public AuthenticationEntryPoint getAuthenticationEntryPoint() {
return authenticationEntryPoint;
}
public void setAuthenticationManager(
AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
public AuthenticationManager getAuthenticationManager() {
return authenticationManager;
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(this.authenticationManager,
"An AuthenticationManager is required");
@ -196,7 +183,13 @@ public class BasicProcessingFilter implements Filter, InitializingBean {
}
SecurityContextHolder.getContext().setAuthentication(null);
authenticationEntryPoint.commence(request, response, failed);
if (ignoreFailure) {
chain.doFilter(request, response);
} else {
authenticationEntryPoint.commence(request, response,
failed);
}
return;
}
@ -214,5 +207,31 @@ public class BasicProcessingFilter implements Filter, InitializingBean {
chain.doFilter(request, response);
}
public AuthenticationEntryPoint getAuthenticationEntryPoint() {
return authenticationEntryPoint;
}
public AuthenticationManager getAuthenticationManager() {
return authenticationManager;
}
public void init(FilterConfig arg0) throws ServletException {}
public boolean isIgnoreFailure() {
return ignoreFailure;
}
public void setAuthenticationEntryPoint(
AuthenticationEntryPoint authenticationEntryPoint) {
this.authenticationEntryPoint = authenticationEntryPoint;
}
public void setAuthenticationManager(
AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
public void setIgnoreFailure(boolean ignoreFailure) {
this.ignoreFailure = ignoreFailure;
}
}

View File

@ -285,7 +285,8 @@ public class BasicProcessingFilterTests extends MockObjectTestCase {
assertEquals(401, response.getStatus());
}
public void testWrongPasswordReturnsForbidden() throws Exception {
public void testWrongPasswordContinuesFilterChainIfIgnoreFailureIsTrue()
throws Exception {
// Setup our HTTP request
String token = "marissa:WRONG_PASSWORD";
MockHttpServletRequest request = new MockHttpServletRequest();
@ -294,6 +295,27 @@ public class BasicProcessingFilterTests extends MockObjectTestCase {
request.setServletPath("/some_file.html");
request.setSession(new MockHttpSession());
filter.setIgnoreFailure(true);
assertTrue(filter.isIgnoreFailure());
// Test - the filter chain will be invoked, as we've set ignoreFailure = true
MockHttpServletResponse response = executeFilterInContainerSimulator(filter,
request, true);
assertNull(SecurityContextHolder.getContext().getAuthentication());
}
public void testWrongPasswordReturnsForbiddenIfIgnoreFailureIsFalse()
throws Exception {
// Setup our HTTP request
String token = "marissa:WRONG_PASSWORD";
MockHttpServletRequest request = new MockHttpServletRequest();
request.addHeader("Authorization",
"Basic " + new String(Base64.encodeBase64(token.getBytes())));
request.setServletPath("/some_file.html");
request.setSession(new MockHttpSession());
assertFalse(filter.isIgnoreFailure());
// Test - the filter chain will not be invoked, as we get a 403 forbidden response
MockHttpServletResponse response = executeFilterInContainerSimulator(filter,
request, false);