From b1dd784deef9289900a8165afeba84b1753db6af Mon Sep 17 00:00:00 2001
From: Ben Alex
Date: Thu, 9 Feb 2006 06:41:31 +0000
Subject: [PATCH] SEC-180: BasicProcessingFilter should configurably ignore
authentication failures.
---
.../ui/basicauth/BasicProcessingFilter.java | 63 ++++++++++++-------
.../basicauth/BasicProcessingFilterTests.java | 24 ++++++-
2 files changed, 64 insertions(+), 23 deletions(-)
diff --git a/core/src/main/java/org/acegisecurity/ui/basicauth/BasicProcessingFilter.java b/core/src/main/java/org/acegisecurity/ui/basicauth/BasicProcessingFilter.java
index 784baa31d0..f652577c68 100644
--- a/core/src/main/java/org/acegisecurity/ui/basicauth/BasicProcessingFilter.java
+++ b/core/src/main/java/org/acegisecurity/ui/basicauth/BasicProcessingFilter.java
@@ -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;
*
*
*
- * If authentication fails, an {@link AuthenticationEntryPoint} implementation
- * is called. Usually this should be {@link BasicProcessingFilterEntryPoint},
+ * If authentication fails and ignoreFailure is false
+ * (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.
*
*
@@ -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;
+ }
}
diff --git a/core/src/test/java/org/acegisecurity/ui/basicauth/BasicProcessingFilterTests.java b/core/src/test/java/org/acegisecurity/ui/basicauth/BasicProcessingFilterTests.java
index b09d3c0477..7884cecf7e 100644
--- a/core/src/test/java/org/acegisecurity/ui/basicauth/BasicProcessingFilterTests.java
+++ b/core/src/test/java/org/acegisecurity/ui/basicauth/BasicProcessingFilterTests.java
@@ -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);