diff --git a/web/src/main/java/org/springframework/security/web/authentication/preauth/RequestHeaderAuthenticationFilter.java b/web/src/main/java/org/springframework/security/web/authentication/preauth/RequestHeaderAuthenticationFilter.java index 3e7c4f173d..47bde8692b 100644 --- a/web/src/main/java/org/springframework/security/web/authentication/preauth/RequestHeaderAuthenticationFilter.java +++ b/web/src/main/java/org/springframework/security/web/authentication/preauth/RequestHeaderAuthenticationFilter.java @@ -11,12 +11,15 @@ import org.springframework.util.Assert; * As with most pre-authenticated scenarios, it is essential that the external authentication system is set up * correctly as this filter does no authentication whatsoever. All the protection is assumed to be provided externally * and if this filter is included inappropriately in a configuration, it would be possible to assume the - * identity of a user merely by setting the correct header name. This also means it should not be used in combination - * with other Spring Security authentication mechanisms such as form login, as this would imply there was a means of - * bypassing the external system which would be risky. + * identity of a user merely by setting the correct header name. This also means it should not generally be used + * in combination with other Spring Security authentication mechanisms such as form login, as this would imply there + * was a means of bypassing the external system which would be risky. *
* The property principalRequestHeader is the name of the request header that contains the username. It * defaults to "SM_USER" for compatibility with Siteminder. + *
+ * If the header is missing from the request, getPreAuthenticatedPrincipal will throw an exception. You + * can override this behaviour by setting the exceptionIfMissingHeader property. * * * @author Luke Taylor @@ -26,16 +29,19 @@ import org.springframework.util.Assert; public class RequestHeaderAuthenticationFilter extends AbstractPreAuthenticatedProcessingFilter { private String principalRequestHeader = "SM_USER"; private String credentialsRequestHeader; + private boolean exceptionIfHeaderMissing = true; + private boolean exceptionIfMissingHeader; /** * Read and returns the header named by principalRequestHeader from the request. * - * @throws PreAuthenticatedCredentialsNotFoundException if the header is missing + * @throws PreAuthenticatedCredentialsNotFoundException if the header is missing and exceptionIfHeaderMissing + * is set to true. */ protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) { String principal = request.getHeader(principalRequestHeader); - if (principal == null) { + if (principal == null && exceptionIfHeaderMissing) { throw new PreAuthenticatedCredentialsNotFoundException(principalRequestHeader + " header not found in request."); } @@ -66,4 +72,14 @@ public class RequestHeaderAuthenticationFilter extends AbstractPreAuthenticatedP Assert.hasText(credentialsRequestHeader, "credentialsRequestHeader must not be empty or null"); this.credentialsRequestHeader = credentialsRequestHeader; } + + /** + * Defines whether an exception should be raised if the principal header is missing. Defaults to true. + * + * @param exceptionIfHeaderMissing set to false to override the default behaviour and allow + * the request to proceed if no header is found. + */ + public void setExceptionIfHeaderMissing(boolean exceptionIfHeaderMissing) { + this.exceptionIfHeaderMissing = exceptionIfMissingHeader; + } } diff --git a/web/src/test/java/org/springframework/security/web/authentication/preauth/header/RequestHeaderPreAuthenticatedProcessingFilterTests.java b/web/src/test/java/org/springframework/security/web/authentication/preauth/header/RequestHeaderAuthenticationFilterTests.java similarity index 83% rename from web/src/test/java/org/springframework/security/web/authentication/preauth/header/RequestHeaderPreAuthenticatedProcessingFilterTests.java rename to web/src/test/java/org/springframework/security/web/authentication/preauth/header/RequestHeaderAuthenticationFilterTests.java index 3bae2a03b9..cdb470d352 100644 --- a/web/src/test/java/org/springframework/security/web/authentication/preauth/header/RequestHeaderPreAuthenticatedProcessingFilterTests.java +++ b/web/src/test/java/org/springframework/security/web/authentication/preauth/header/RequestHeaderAuthenticationFilterTests.java @@ -23,7 +23,7 @@ import org.springframework.security.web.authentication.preauth.RequestHeaderAuth * @author Luke Taylor * @version $Id$ */ -public class RequestHeaderPreAuthenticatedProcessingFilterTests { +public class RequestHeaderAuthenticationFilterTests { @After @Before @@ -108,6 +108,28 @@ public class RequestHeaderPreAuthenticatedProcessingFilterTests { assertSame(dog, SecurityContextHolder.getContext().getAuthentication()); } + @Test(expected=PreAuthenticatedCredentialsNotFoundException.class) + public void missingHeaderCausesException() throws Exception { + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + MockFilterChain chain = new MockFilterChain(); + RequestHeaderAuthenticationFilter filter = new RequestHeaderAuthenticationFilter(); + filter.setAuthenticationManager(createAuthenticationManager()); + + filter.doFilter(request, response, chain); + } + + @Test + public void missingHeaderIsIgnoredIfExceptionIfHeaderMissingIsFalse() throws Exception { + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + MockFilterChain chain = new MockFilterChain(); + RequestHeaderAuthenticationFilter filter = new RequestHeaderAuthenticationFilter(); + filter.setExceptionIfHeaderMissing(false); + filter.setAuthenticationManager(createAuthenticationManager()); + filter.doFilter(request, response, chain); + } + /** * Create an authentication manager which returns the passed in object. */