diff --git a/config/config.gradle b/config/config.gradle
index 7b3abcb65a..e375a1838e 100644
--- a/config/config.gradle
+++ b/config/config.gradle
@@ -16,7 +16,7 @@ dependencies {
provided "javax.servlet:servlet-api:2.5"
- groovy group: 'org.codehaus.groovy', name: 'groovy', version: '1.7.3'
+ groovy group: 'org.codehaus.groovy', name: 'groovy', version: '1.7.4'
testCompile project(':spring-security-ldap'),
project(':spring-security-openid'),
diff --git a/config/src/main/java/org/springframework/security/config/http/AuthenticationConfigBuilder.java b/config/src/main/java/org/springframework/security/config/http/AuthenticationConfigBuilder.java
index 2b5657aa2b..86e3b0f818 100644
--- a/config/src/main/java/org/springframework/security/config/http/AuthenticationConfigBuilder.java
+++ b/config/src/main/java/org/springframework/security/config/http/AuthenticationConfigBuilder.java
@@ -64,6 +64,8 @@ final class AuthenticationConfigBuilder {
private static final String OPEN_ID_ATTRIBUTE_FACTORY_CLASS = "org.springframework.security.openid.RegexBasedAxFetchListFactory";
static final String AUTHENTICATION_PROCESSING_FILTER_CLASS = "org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter";
+ static final String ATT_AUTH_DETAILS_SOURCE_REF = "authentication-details-source-ref";
+
private static final String ATT_AUTO_CONFIG = "auto-config";
private static final String ATT_ACCESS_DENIED_PAGE = "access-denied-page";
@@ -72,6 +74,7 @@ final class AuthenticationConfigBuilder {
private static final String ATT_USER_SERVICE_REF = "user-service-ref";
+
private final Element httpElt;
private final ParserContext pc;
@@ -148,7 +151,7 @@ final class AuthenticationConfigBuilder {
key = DEF_KEY;
}
- rememberMeFilter = (RootBeanDefinition) new RememberMeBeanDefinitionParser(key).parse(rememberMeElt, pc);
+ rememberMeFilter = new RememberMeBeanDefinitionParser(key).parse(rememberMeElt, pc);
rememberMeFilter.getPropertyValues().addPropertyValue("authenticationManager", authenticationManager);
rememberMeServicesId = ((RuntimeBeanReference) rememberMeFilter.getPropertyValues().getPropertyValue("rememberMeServices").getValue()).getBeanName();
createRememberMeProvider(key);
@@ -291,35 +294,41 @@ final class AuthenticationConfigBuilder {
void createBasicFilter(BeanReference authManager) {
Element basicAuthElt = DomUtils.getChildElementByTagName(httpElt, Elements.BASIC_AUTH);
+ if (basicAuthElt == null && !autoConfig) {
+ // No basic auth, do nothing
+ return;
+ }
+
String realm = httpElt.getAttribute(ATT_REALM);
if (!StringUtils.hasText(realm)) {
realm = DEF_REALM;
}
- RootBeanDefinition filter = null;
+ BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(BasicAuthenticationFilter.class);
- if (basicAuthElt != null || autoConfig) {
- BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(BasicAuthenticationFilter.class);
+ String entryPointId;
- String entryPointId;
-
- if (basicAuthElt != null && StringUtils.hasText(basicAuthElt.getAttribute(ATT_ENTRY_POINT_REF))) {
+ if (basicAuthElt != null) {
+ if (StringUtils.hasText(basicAuthElt.getAttribute(ATT_ENTRY_POINT_REF))) {
basicEntryPoint = new RuntimeBeanReference(basicAuthElt.getAttribute(ATT_ENTRY_POINT_REF));
- } else {
- RootBeanDefinition entryPoint = new RootBeanDefinition(BasicAuthenticationEntryPoint.class);
- entryPoint.setSource(pc.extractSource(httpElt));
- entryPoint.getPropertyValues().addPropertyValue("realmName", realm);
- entryPointId = pc.getReaderContext().generateBeanName(entryPoint);
- pc.registerBeanComponent(new BeanComponentDefinition(entryPoint, entryPointId));
- basicEntryPoint = new RuntimeBeanReference(entryPointId);
}
- filterBuilder.addPropertyValue("authenticationManager", authManager);
- filterBuilder.addPropertyValue("authenticationEntryPoint", basicEntryPoint);
- filter = (RootBeanDefinition) filterBuilder.getBeanDefinition();
+ injectAuthenticationDetailsSource(basicAuthElt, filterBuilder);
+
}
- basicFilter = filter;
+ if (basicEntryPoint == null) {
+ RootBeanDefinition entryPoint = new RootBeanDefinition(BasicAuthenticationEntryPoint.class);
+ entryPoint.setSource(pc.extractSource(httpElt));
+ entryPoint.getPropertyValues().addPropertyValue("realmName", realm);
+ entryPointId = pc.getReaderContext().generateBeanName(entryPoint);
+ pc.registerBeanComponent(new BeanComponentDefinition(entryPoint, entryPointId));
+ basicEntryPoint = new RuntimeBeanReference(entryPointId);
+ }
+
+ filterBuilder.addPropertyValue("authenticationManager", authManager);
+ filterBuilder.addPropertyValue("authenticationEntryPoint", basicEntryPoint);
+ basicFilter = filterBuilder.getBeanDefinition();
}
void createX509Filter(BeanReference authManager) {
@@ -339,6 +348,9 @@ final class AuthenticationConfigBuilder {
filterBuilder.addPropertyValue("principalExtractor", extractor.getBeanDefinition());
}
+
+ injectAuthenticationDetailsSource(x509Elt, filterBuilder);
+
filter = (RootBeanDefinition) filterBuilder.getBeanDefinition();
createPrauthEntryPoint(x509Elt);
@@ -348,6 +360,14 @@ final class AuthenticationConfigBuilder {
x509Filter = filter;
}
+ private void injectAuthenticationDetailsSource(Element elt, BeanDefinitionBuilder filterBuilder) {
+ String authDetailsSourceRef = elt.getAttribute(AuthenticationConfigBuilder.ATT_AUTH_DETAILS_SOURCE_REF);
+
+ if (StringUtils.hasText(authDetailsSourceRef)) {
+ filterBuilder.addPropertyReference("authenticationDetailsSource", authDetailsSourceRef);
+ }
+ }
+
private void createX509Provider() {
Element x509Elt = DomUtils.getChildElementByTagName(httpElt, Elements.X509);
BeanDefinition provider = new RootBeanDefinition(PreAuthenticatedAuthenticationProvider.class);
diff --git a/config/src/main/java/org/springframework/security/config/http/FormLoginBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/FormLoginBeanDefinitionParser.java
index e202253c48..ee95ef91af 100644
--- a/config/src/main/java/org/springframework/security/config/http/FormLoginBeanDefinitionParser.java
+++ b/config/src/main/java/org/springframework/security/config/http/FormLoginBeanDefinitionParser.java
@@ -68,6 +68,7 @@ public class FormLoginBeanDefinitionParser {
// Only available with form-login
String usernameParameter = null;
String passwordParameter = null;
+ String authDetailsSourceRef = null;
Object source = null;
@@ -83,6 +84,8 @@ public class FormLoginBeanDefinitionParser {
loginPage = elt.getAttribute(ATT_LOGIN_PAGE);
successHandlerRef = elt.getAttribute(ATT_SUCCESS_HANDLER_REF);
failureHandlerRef = elt.getAttribute(ATT_FAILURE_HANDLER_REF);
+ authDetailsSourceRef = elt.getAttribute(AuthenticationConfigBuilder.ATT_AUTH_DETAILS_SOURCE_REF);
+
if (!StringUtils.hasText(loginPage)) {
loginPage = null;
@@ -93,7 +96,7 @@ public class FormLoginBeanDefinitionParser {
}
filterBean = createFilterBean(loginUrl, defaultTargetUrl, alwaysUseDefault, loginPage, authenticationFailureUrl,
- successHandlerRef, failureHandlerRef);
+ successHandlerRef, failureHandlerRef, authDetailsSourceRef);
if (StringUtils.hasText(usernameParameter)) {
filterBean.getPropertyValues().addPropertyValue("usernameParameter", usernameParameter);
@@ -114,7 +117,8 @@ public class FormLoginBeanDefinitionParser {
}
private RootBeanDefinition createFilterBean(String loginUrl, String defaultTargetUrl, String alwaysUseDefault,
- String loginPage, String authenticationFailureUrl, String successHandlerRef, String failureHandlerRef) {
+ String loginPage, String authenticationFailureUrl, String successHandlerRef, String failureHandlerRef,
+ String authDetailsSourceRef) {
BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(filterClassName);
@@ -136,6 +140,10 @@ public class FormLoginBeanDefinitionParser {
filterBuilder.addPropertyValue("authenticationSuccessHandler", successHandler.getBeanDefinition());
}
+ if (StringUtils.hasText(authDetailsSourceRef)) {
+ filterBuilder.addPropertyReference("authenticationDetailsSource", authDetailsSourceRef);
+ }
+
if (sessionStrategy != null) {
filterBuilder.addPropertyValue("sessionAuthenticationStrategy", sessionStrategy);
}
diff --git a/config/src/main/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParser.java
index fad301d6b6..0c1af2800c 100644
--- a/config/src/main/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParser.java
+++ b/config/src/main/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParser.java
@@ -187,10 +187,10 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
logger.info("Checking sorted filter chain: " + filters);
for(int i=0; i < filters.size(); i++) {
- OrderDecorator filter = (OrderDecorator)filters.get(i);
+ OrderDecorator filter = filters.get(i);
if (i > 0) {
- OrderDecorator previous = (OrderDecorator)filters.get(i-1);
+ OrderDecorator previous = filters.get(i-1);
if (filter.getOrder() == previous.getOrder()) {
pc.getReaderContext().error("Filter beans '" + filter.bean + "' and '" +
previous.bean + "' have the same 'order' value. When using custom filters, " +
diff --git a/config/src/main/resources/org/springframework/security/config/spring-security-3.1.rnc b/config/src/main/resources/org/springframework/security/config/spring-security-3.1.rnc
index a37f10bc51..2ac422207e 100644
--- a/config/src/main/resources/org/springframework/security/config/spring-security-3.1.rnc
+++ b/config/src/main/resources/org/springframework/security/config/spring-security-3.1.rnc
@@ -381,6 +381,10 @@ form-login.attlist &=
form-login.attlist &=
## Reference to an AuthenticationFailureHandler bean which should be used to handle a failed authentication request. Should not be used in combination with authentication-failure-url as the implementation should always deal with navigation to the subsequent destination
attribute authentication-failure-handler-ref {xsd:token}?
+form-login.attlist &=
+ ## Reference to an AuthenticationDetailsSource which will be used by the authentication filter
+ attribute authentication-details-source-ref {xsd:token}?
+
openid-login =
## Sets up form login for authentication with an Open ID identity
@@ -451,6 +455,9 @@ http-basic =
http-basic.attlist &=
## Sets the AuthenticationEntryPoint which is used by the BasicAuthenticationFilter.
attribute entry-point-ref {xsd:token}?
+http-basic.attlist &=
+ ## Reference to an AuthenticationDetailsSource which will be used by the authentication filter
+ attribute authentication-details-source-ref {xsd:token}?
session-management =
element session-management {session-management.attlist, concurrency-control?}
@@ -565,6 +572,8 @@ x509.attlist &=
x509.attlist &=
## Explicitly specifies which user-service should be used to load user data for X.509 authenticated clients. If ommitted, the default user-service will be used.
user-service-ref?
+x509.attlist &=
+ attribute authentication-details-source-ref {xsd:token}?
jee =
## Adds a J2eePreAuthenticatedProcessingFilter to the filter chain to provide integration with container authentication.
diff --git a/config/src/main/resources/org/springframework/security/config/spring-security-3.1.xsd b/config/src/main/resources/org/springframework/security/config/spring-security-3.1.xsd
index 023e450aff..1286a74689 100644
--- a/config/src/main/resources/org/springframework/security/config/spring-security-3.1.xsd
+++ b/config/src/main/resources/org/springframework/security/config/spring-security-3.1.xsd
@@ -926,6 +926,11 @@
Reference to an AuthenticationFailureHandler bean which should be used to handle a failed authentication request. Should not be used in combination with authentication-failure-url as the implementation should always deal with navigation to the subsequent destination
+
+
+ Reference to an AuthenticationDetailsSource which will be used by the authentication filter
+
+
@@ -1059,6 +1064,11 @@
Sets the AuthenticationEntryPoint which is used by the BasicAuthenticationFilter.
+
+
+ Reference to an AuthenticationDetailsSource which will be used by the authentication filter
+
+
@@ -1167,7 +1177,7 @@
- Allows a custom implementation of RememberMeServices to be used. Note that this implementation should return RememberMeAuthenticationToken instances with the same "key" value as specified in the remember-me element. Alternatively it should register its own AuthenticationProvider.
+ Allows a custom implementation of RememberMeServices to be used. Note that this implementation should return RememberMeAuthenticationToken instances with the same "key" value as specified in the remember-me element. Alternatively it should register its own AuthenticationProvider. It should also implement the LogoutHandler interface, which will be invoked when a user logs out. Typically the remember-me cookie would be removed on logout.
@@ -1217,6 +1227,7 @@
A reference to a user-service (or UserDetailsService bean) Id
+
Adds a J2eePreAuthenticatedProcessingFilter to the filter chain to provide integration with container authentication.
diff --git a/config/src/test/groovy/org/springframework/security/config/http/AbstractHttpConfigTests.groovy b/config/src/test/groovy/org/springframework/security/config/http/AbstractHttpConfigTests.groovy
index df25edc7de..205b630fca 100644
--- a/config/src/test/groovy/org/springframework/security/config/http/AbstractHttpConfigTests.groovy
+++ b/config/src/test/groovy/org/springframework/security/config/http/AbstractHttpConfigTests.groovy
@@ -1,18 +1,11 @@
package org.springframework.security.config.http
-import groovy.lang.Closure;
-import groovy.xml.MarkupBuilder
-import java.util.List;
-
-import javax.servlet.Filter;
-
+import javax.servlet.Filter
import org.springframework.mock.web.MockFilterChain
import org.springframework.mock.web.MockHttpServletRequest
import org.springframework.mock.web.MockHttpServletResponse
import org.springframework.security.config.AbstractXmlConfigTests
import org.springframework.security.config.BeanIds
-import org.springframework.security.config.util.InMemoryXmlApplicationContext
-import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.web.FilterChainProxy
import org.springframework.security.web.FilterInvocation
diff --git a/config/src/test/groovy/org/springframework/security/config/http/MiscHttpConfigTests.groovy b/config/src/test/groovy/org/springframework/security/config/http/MiscHttpConfigTests.groovy
index 7fb9a2d215..09cc1b6da4 100644
--- a/config/src/test/groovy/org/springframework/security/config/http/MiscHttpConfigTests.groovy
+++ b/config/src/test/groovy/org/springframework/security/config/http/MiscHttpConfigTests.groovy
@@ -44,7 +44,8 @@ import org.springframework.security.web.savedrequest.RequestCacheAwareFilter;
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
import org.springframework.security.web.session.SessionManagementFilter;
-import groovy.lang.Closure;
+import groovy.lang.Closure
+import org.springframework.security.openid.OpenIDAuthenticationFilter;
class MiscHttpConfigTests extends AbstractHttpConfigTests {
def 'Minimal configuration parses'() {
@@ -502,6 +503,23 @@ class MiscHttpConfigTests extends AbstractHttpConfigTests {
roles.contains 'ROLE_user'
roles.contains 'ROLE_c'
}
+
+ def authenticationDetailsSourceInjectionSucceeds() {
+ xml.http() {
+ 'form-login'('authentication-details-source-ref' : 'adsr')
+ 'openid-login' ('authentication-details-source-ref' : 'adsr')
+ 'http-basic' ('authentication-details-source-ref' : 'adsr')
+ 'x509' ('authentication-details-source-ref' : 'adsr')
+ }
+ bean('adsr', 'org.springframework.security.web.authentication.WebAuthenticationDetailsSource')
+ createAppContext()
+ def adsr = appContext.getBean('adsr')
+ expect:
+ getFilter(UsernamePasswordAuthenticationFilter).authenticationDetailsSource == adsr
+ getFilter(OpenIDAuthenticationFilter).authenticationDetailsSource == adsr
+ getFilter(BasicAuthenticationFilter).authenticationDetailsSource == adsr
+ getFilter(X509AuthenticationFilter).authenticationDetailsSource == adsr
+ }
}
class MockEntryPoint extends LoginUrlAuthenticationEntryPoint {
diff --git a/web/src/main/java/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilter.java b/web/src/main/java/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilter.java
index 7b3e2c3ac1..637ff119c0 100755
--- a/web/src/main/java/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilter.java
+++ b/web/src/main/java/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilter.java
@@ -196,6 +196,10 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
this.authenticationDetailsSource = authenticationDetailsSource;
}
+ protected AuthenticationDetailsSource getAuthenticationDetailsSource() {
+ return authenticationDetailsSource;
+ }
+
/**
* @param authenticationManager
* The AuthenticationManager to use