SEC-1250: RequestHeaderPreAuthenticatedProcessingFilter cannot be use to fail back to another authentication type. Added exceptionIfHeaderMissing property.

This commit is contained in:
Luke Taylor 2009-10-08 16:37:53 +00:00
parent e398922f85
commit 0da99171da
2 changed files with 44 additions and 6 deletions

View File

@ -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.
* <p>
* The property <tt>principalRequestHeader</tt> is the name of the request header that contains the username. It
* defaults to "SM_USER" for compatibility with Siteminder.
* <p>
* If the header is missing from the request, <tt>getPreAuthenticatedPrincipal</tt> will throw an exception. You
* can override this behaviour by setting the <tt>exceptionIfMissingHeader</tt> 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 <tt>principalRequestHeader</tt> from the request.
*
* @throws PreAuthenticatedCredentialsNotFoundException if the header is missing
* @throws PreAuthenticatedCredentialsNotFoundException if the header is missing and <tt>exceptionIfHeaderMissing</tt>
* is set to <tt>true</tt>.
*/
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 <tt>true</tt>.
*
* @param exceptionIfHeaderMissing set to <tt>false</tt> to override the default behaviour and allow
* the request to proceed if no header is found.
*/
public void setExceptionIfHeaderMissing(boolean exceptionIfHeaderMissing) {
this.exceptionIfHeaderMissing = exceptionIfMissingHeader;
}
}

View File

@ -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.
*/