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);