mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-05-07 12:17:25 +00:00
SEC-1250: RequestHeaderPreAuthenticatedProcessingFilter cannot be use to fail back to another authentication type. Added exceptionIfHeaderMissing property.
This commit is contained in:
parent
e398922f85
commit
0da99171da
@ -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
|
* 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
|
* 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
|
* 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
|
* identity of a user merely by setting the correct header name. This also means it should not generally be used
|
||||||
* with other Spring Security authentication mechanisms such as form login, as this would imply there was a means of
|
* in combination with other Spring Security authentication mechanisms such as form login, as this would imply there
|
||||||
* bypassing the external system which would be risky.
|
* was a means of bypassing the external system which would be risky.
|
||||||
* <p>
|
* <p>
|
||||||
* The property <tt>principalRequestHeader</tt> is the name of the request header that contains the username. It
|
* 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.
|
* 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
|
* @author Luke Taylor
|
||||||
@ -26,16 +29,19 @@ import org.springframework.util.Assert;
|
|||||||
public class RequestHeaderAuthenticationFilter extends AbstractPreAuthenticatedProcessingFilter {
|
public class RequestHeaderAuthenticationFilter extends AbstractPreAuthenticatedProcessingFilter {
|
||||||
private String principalRequestHeader = "SM_USER";
|
private String principalRequestHeader = "SM_USER";
|
||||||
private String credentialsRequestHeader;
|
private String credentialsRequestHeader;
|
||||||
|
private boolean exceptionIfHeaderMissing = true;
|
||||||
|
private boolean exceptionIfMissingHeader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read and returns the header named by <tt>principalRequestHeader</tt> from the request.
|
* 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) {
|
protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
|
||||||
String principal = request.getHeader(principalRequestHeader);
|
String principal = request.getHeader(principalRequestHeader);
|
||||||
|
|
||||||
if (principal == null) {
|
if (principal == null && exceptionIfHeaderMissing) {
|
||||||
throw new PreAuthenticatedCredentialsNotFoundException(principalRequestHeader
|
throw new PreAuthenticatedCredentialsNotFoundException(principalRequestHeader
|
||||||
+ " header not found in request.");
|
+ " header not found in request.");
|
||||||
}
|
}
|
||||||
@ -66,4 +72,14 @@ public class RequestHeaderAuthenticationFilter extends AbstractPreAuthenticatedP
|
|||||||
Assert.hasText(credentialsRequestHeader, "credentialsRequestHeader must not be empty or null");
|
Assert.hasText(credentialsRequestHeader, "credentialsRequestHeader must not be empty or null");
|
||||||
this.credentialsRequestHeader = credentialsRequestHeader;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ import org.springframework.security.web.authentication.preauth.RequestHeaderAuth
|
|||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class RequestHeaderPreAuthenticatedProcessingFilterTests {
|
public class RequestHeaderAuthenticationFilterTests {
|
||||||
|
|
||||||
@After
|
@After
|
||||||
@Before
|
@Before
|
||||||
@ -108,6 +108,28 @@ public class RequestHeaderPreAuthenticatedProcessingFilterTests {
|
|||||||
assertSame(dog, SecurityContextHolder.getContext().getAuthentication());
|
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.
|
* Create an authentication manager which returns the passed in object.
|
||||||
*/
|
*/
|
Loading…
x
Reference in New Issue
Block a user