SEC-271: Spring 2-based configuration simplification of Acegi Security

This commit is contained in:
Vishal Puri 2007-05-11 00:09:56 +00:00
parent 566314dae5
commit 9794c518d6
19 changed files with 195 additions and 46 deletions

View File

@ -27,6 +27,7 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.core.Ordered;
import org.springframework.util.Assert;
@ -38,15 +39,24 @@ import org.springframework.util.Assert;
* <code>AuthByAdapterProvider</code>-configured key.</p>
* <P>If the key does not match, a <code>BadCredentialsException</code> is thrown.</p>
*/
public class AuthByAdapterProvider implements InitializingBean, AuthenticationProvider, MessageSourceAware {
public class AuthByAdapterProvider implements InitializingBean, AuthenticationProvider, MessageSourceAware, Ordered {
//~ Instance fields ================================================================================================
protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor();
private String key;
private int order = -1; // default: same as non-Ordered
//~ Methods ========================================================================================================
public void afterPropertiesSet() throws Exception {
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(key, "A Key is required and should match that configured for the adapters");
Assert.notNull(messages, "A message source must be set");
}

View File

@ -25,7 +25,7 @@ import org.w3c.dom.NodeList;
*/
public class AuthenticationRepositoryBeanDefinitionParser extends AbstractBeanDefinitionParser {
// ~~ Instance Variables
// ~ Instance fields ================================================================================================
private static final String REPOSITORY_BEAN_REF = "repositoryBeanRef";
@ -49,7 +49,7 @@ public class AuthenticationRepositoryBeanDefinitionParser extends AbstractBeanDe
// ~~ Methods
// ~ Method ================================================================================================
/**
* TODO: Document Me !!!
*/

View File

@ -34,13 +34,13 @@ public class ContextIntegrationBeanDefinitionParser extends AbstractSingleBeanDe
private static final String NEVER = "never";
@Override
protected Class getBeanClass(Element element) {
return HttpSessionContextIntegrationFilter.class;
}
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
NamedNodeMap attributes = element.getAttributes();

View File

@ -8,7 +8,6 @@ import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@ -19,16 +18,13 @@ import org.w3c.dom.Element;
*
*@since
*/
public class RememberMeFilterBeanDefinitionParser extends AbstractBeanDefinitionParser implements
BeanDefinitionParser {
public class RememberMeFilterBeanDefinitionParser extends AbstractBeanDefinitionParser {
private static final String REMEMBER_ME_SERVICES_REF = "rememberMeServicesBeanRef";
private static final String REMEMBER_ME_SERVICES = "rememberMeServices";
/**
*
*/
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
Assert.notNull(parserContext, "ParserContext must not be null");
@ -45,5 +41,9 @@ public class RememberMeFilterBeanDefinitionParser extends AbstractBeanDefinition
}
return rememberMeFilterBeanDef;
}
}

View File

@ -21,6 +21,7 @@ public class SecurityNamespaceHandler extends NamespaceHandlerSupport {
public void init() {
registerBeanDefinitionParser("session-context-integration", new ContextIntegrationBeanDefinitionParser());
registerBeanDefinitionParser("authentication-repository", new AuthenticationRepositoryBeanDefinitionParser());
registerBeanDefinitionParser("authentication-mechanism", new AuthenticationMechanismBeanDefinitionParser());
registerBeanDefinitionParser("authentication-remember-me-services", new RememberMeServicesBeanDefinitionParser());
registerBeanDefinitionParser("authentication-remember-me-filter", new RememberMeFilterBeanDefinitionParser());
}

View File

@ -19,18 +19,14 @@ import org.acegisecurity.AcegiMessageSource;
import org.acegisecurity.Authentication;
import org.acegisecurity.AuthenticationException;
import org.acegisecurity.BadCredentialsException;
import org.acegisecurity.providers.AuthenticationProvider;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.core.Ordered;
import org.springframework.util.Assert;
@ -40,7 +36,7 @@ import org.springframework.util.Assert;
* {@link org.acegisecurity.providers.anonymous.AnonymousAuthenticationToken#getKeyHash()} must match this class'
* {@link #getKey()}.</p>
*/
public class AnonymousAuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware {
public class AnonymousAuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware, Ordered {
//~ Static fields/initializers =====================================================================================
private static final Log logger = LogFactory.getLog(AnonymousAuthenticationProvider.class);
@ -49,10 +45,19 @@ public class AnonymousAuthenticationProvider implements AuthenticationProvider,
protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor();
private String key;
private int order = -1; // default: same as non-Ordered
//~ Methods ========================================================================================================
public void afterPropertiesSet() throws Exception {
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
public void afterPropertiesSet() throws Exception {
Assert.hasLength(key, "A Key is required");
Assert.notNull(this.messages, "A message source must be set");
}

View File

@ -35,6 +35,7 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.core.Ordered;
import org.springframework.util.Assert;
@ -49,7 +50,7 @@ import org.springframework.util.Assert;
* @author Ben Alex
* @version $Id$
*/
public class CasAuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware {
public class CasAuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware, Ordered {
//~ Static fields/initializers =====================================================================================
private static final Log logger = LogFactory.getLog(CasAuthenticationProvider.class);
@ -62,10 +63,19 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
private StatelessTicketCache statelessTicketCache;
private String key;
private TicketValidator ticketValidator;
private int order = -1; // default: same as non-Ordered
//~ Methods ========================================================================================================
public void afterPropertiesSet() throws Exception {
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(this.casAuthoritiesPopulator, "A casAuthoritiesPopulator must be set");
Assert.notNull(this.ticketValidator, "A ticketValidator must be set");
Assert.notNull(this.casProxyDecider, "A casProxyDecider must be set");

View File

@ -27,6 +27,7 @@ import org.acegisecurity.providers.encoding.PlaintextPasswordEncoder;
import org.acegisecurity.userdetails.UserDetails;
import org.acegisecurity.userdetails.UserDetailsService;
import org.springframework.core.Ordered;
import org.springframework.dao.DataAccessException;
import org.springframework.util.Assert;
@ -38,13 +39,15 @@ import org.springframework.util.Assert;
* @author Ben Alex
* @version $Id$
*/
public class DaoAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
public class DaoAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider implements Ordered {
//~ Instance fields ================================================================================================
private PasswordEncoder passwordEncoder = new PlaintextPasswordEncoder();
private SaltSource saltSource;
private UserDetailsService userDetailsService;
private boolean includeDetailsObject = true;
private int order = -1; // default: same as non-Ordered
//~ Methods ========================================================================================================
@ -95,7 +98,6 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
throw new AuthenticationServiceException(
"UserDetailsService returned null, which is an interface contract violation");
}
return loadedUser;
}
@ -131,4 +133,14 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
public void setIncludeDetailsObject(boolean includeDetailsObject) {
this.includeDetailsObject = includeDetailsObject;
}
public void setOrder(int order) {
this.order = order;
}
public int getOrder() {
return order ;
}
}

View File

@ -41,6 +41,7 @@ import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.Ordered;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
@ -141,7 +142,7 @@ import javax.security.auth.login.LoginException;
* @version $Id$
*/
public class JaasAuthenticationProvider implements AuthenticationProvider, InitializingBean, ApplicationContextAware,
ApplicationListener {
ApplicationListener, Ordered {
//~ Static fields/initializers =====================================================================================
protected static final Log log = LogFactory.getLog(JaasAuthenticationProvider.class);
@ -154,10 +155,19 @@ public class JaasAuthenticationProvider implements AuthenticationProvider, Initi
private String loginContextName = "ACEGI";
private AuthorityGranter[] authorityGranters;
private JaasAuthenticationCallbackHandler[] callbackHandlers;
private int order = -1; // default: same as non-Ordered
//~ Methods ========================================================================================================
public void afterPropertiesSet() throws Exception {
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(loginConfig, "loginConfig must be set on " + getClass());
Assert.hasLength(loginContextName, "loginContextName must be set on " + getClass());

View File

@ -32,6 +32,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.core.Ordered;
import org.springframework.dao.DataAccessException;
@ -113,7 +114,7 @@ import org.springframework.dao.DataAccessException;
* @see org.acegisecurity.providers.ldap.authenticator.BindAuthenticator
* @see org.acegisecurity.providers.ldap.populator.DefaultLdapAuthoritiesPopulator
*/
public class LdapAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
public class LdapAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider implements Ordered {
//~ Static fields/initializers =====================================================================================
private static final Log logger = LogFactory.getLog(LdapAuthenticationProvider.class);
@ -123,10 +124,19 @@ public class LdapAuthenticationProvider extends AbstractUserDetailsAuthenticatio
private LdapAuthenticator authenticator;
private LdapAuthoritiesPopulator authoritiesPopulator;
private boolean includeDetailsObject = true;
private int order = -1; // default: same as non-Ordered
//~ Constructors ===================================================================================================
/**
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
/**
* Create an initialized instance to the values passed as arguments
*
* @param authenticator the authentication strategy (bind, password comparison, etc)

View File

@ -23,6 +23,7 @@ import org.acegisecurity.providers.AuthenticationProvider;
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.Ordered;
import org.springframework.util.Assert;
@ -43,14 +44,23 @@ import org.springframework.util.Assert;
* @author Ben Alex
* @version $Id$
*/
public class RemoteAuthenticationProvider implements AuthenticationProvider, InitializingBean {
public class RemoteAuthenticationProvider implements AuthenticationProvider, InitializingBean, Ordered {
//~ Instance fields ================================================================================================
private RemoteAuthenticationManager remoteAuthenticationManager;
private int order = -1; // default: same as non-Ordered
//~ Methods ========================================================================================================
public void afterPropertiesSet() throws Exception {
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(this.remoteAuthenticationManager, "remoteAuthenticationManager is mandatory");
}

View File

@ -30,6 +30,7 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.core.Ordered;
import org.springframework.util.Assert;
@ -40,7 +41,7 @@ import org.springframework.util.Assert;
* {@link org.acegisecurity.providers.rememberme.RememberMeAuthenticationToken#getKeyHash()} must match this class'
* {@link #getKey()}.</p>
*/
public class RememberMeAuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware {
public class RememberMeAuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware, Ordered {
//~ Static fields/initializers =====================================================================================
private static final Log logger = LogFactory.getLog(RememberMeAuthenticationProvider.class);
@ -49,10 +50,19 @@ public class RememberMeAuthenticationProvider implements AuthenticationProvider,
protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor();
private String key;
private int order = -1; // default: same as non-Ordered
//~ Methods ========================================================================================================
public void afterPropertiesSet() throws Exception {
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
public void afterPropertiesSet() throws Exception {
Assert.hasLength(key);
Assert.notNull(this.messages, "A message source must be set");
}

View File

@ -28,6 +28,7 @@ import org.acegisecurity.userdetails.UserDetails;
import org.acegisecurity.userdetails.UserDetailsService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.Ordered;
import org.springframework.dao.DataAccessException;
import org.springframework.util.Assert;
@ -37,7 +38,8 @@ import org.springframework.util.Assert;
* @author Scott McCrory
* @version $Id: SiteminderAuthenticationProvider.java 1582 2006-07-15 15:18:51Z smccrory $
*/
public class SiteminderAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
public class SiteminderAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider implements Ordered {
/**
* Our logging object
@ -50,6 +52,8 @@ public class SiteminderAuthenticationProvider extends AbstractUserDetailsAuthent
* Our user details service (which does the real work of checking the user against a back-end user store).
*/
private UserDetailsService userDetailsService;
private int order = -1; // default: same as non-Ordered
//~ Methods ========================================================================================================
@ -129,4 +133,12 @@ public class SiteminderAuthenticationProvider extends AbstractUserDetailsAuthent
this.userDetailsService = userDetailsService;
}
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
}

View File

@ -33,6 +33,7 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.core.Ordered;
import org.springframework.util.Assert;
@ -46,7 +47,7 @@ import java.security.cert.X509Certificate;
* @author Luke Taylor
* @version $Id$
*/
public class X509AuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware {
public class X509AuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware, Ordered {
//~ Static fields/initializers =====================================================================================
private static final Log logger = LogFactory.getLog(X509AuthenticationProvider.class);
@ -56,10 +57,19 @@ public class X509AuthenticationProvider implements AuthenticationProvider, Initi
protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor();
private X509AuthoritiesPopulator x509AuthoritiesPopulator;
private X509UserCache userCache = new NullX509UserCache();
private int order = -1; // default: same as non-Ordered
//~ Methods ========================================================================================================
public void afterPropertiesSet() throws Exception {
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(userCache, "An x509UserCache must be set");
Assert.notNull(x509AuthoritiesPopulator, "An X509AuthoritiesPopulator must be set");
Assert.notNull(this.messages, "A message source must be set");

View File

@ -27,6 +27,7 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.core.Ordered;
import org.springframework.util.Assert;
@ -38,15 +39,24 @@ import org.springframework.util.Assert;
* <code>RunAsImplAuthenticationProvider</code>-configured key.</p>
* <P>If the key does not match, a <code>BadCredentialsException</code> is thrown.</p>
*/
public class RunAsImplAuthenticationProvider implements InitializingBean, AuthenticationProvider, MessageSourceAware {
public class RunAsImplAuthenticationProvider implements InitializingBean, AuthenticationProvider, MessageSourceAware, Ordered {
//~ Instance fields ================================================================================================
protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor();
private String key;
private int order = -1; // default: same as non-Ordered
//~ Methods ========================================================================================================
public void afterPropertiesSet() throws Exception {
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(key, "A Key is required and should match that configured for the RunAsManagerImpl");
}

View File

@ -123,6 +123,38 @@
<xsd:attribute name="principalRepositoryBeanRef" type="xsd:string"
use="optional" />
</xsd:complexType>
<xsd:element name="authentication-mechanism"
type="AuthenticationManager" />
<xsd:complexType name="AuthenticationManager">
<xsd:sequence>
<xsd:element ref="authentication-jdbc" minOccurs="0" maxOccurs="1"/>
<xsd:element ref="authentication-ldap" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:ID">
<xsd:annotation>
<xsd:documentation>
<![CDATA[
The unique identifier for a bean.
]]>
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:element name="authentication-jdbc">
<xsd:complexType>
<xsd:attribute name="ref" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="authentication-ldap">
<xsd:complexType>
<xsd:attribute name="ref" type="xsd:string"/>
</xsd:complexType>
</xsd:element>

View File

@ -10,6 +10,7 @@ public class RememberMeBeanDefinitionParserTest extends TestCase {
public void testRememberMeDefaults() {
ApplicationContext context = new ClassPathXmlApplicationContext("org/acegisecurity/config/remember-me-defaults.xml");
}
}

View File

@ -14,8 +14,7 @@ http://www.springframework.org/schema/security http://www.springframework.org/sc
<!-- ======================== AUTHENTICATION ======================= -->
<!-- makes the filter, but does little else, as it auto-detects everything -->
<security:authentication-remember-me-filter id="rememberMeFilter"
rememberMeServicesBeanRef="rememberMeServices" />
<security:authentication-remember-me-filter id="rememberMeFilter" rememberMeServicesBeanRef="rememberMeServices" />
<!-- services should auto-detect UserDetails from app ctx if principalRepository was not specified; -->
<!-- key is optional; if unspecified, in the NamespaceHandler pick a rnd int and use for all unspecified key properties for acegi beans -->
@ -29,17 +28,24 @@ http://www.springframework.org/schema/security http://www.springframework.org/sc
If ProviderManager.setProvider(List) is never called, auto-detect all AuthenticationProviders from app ctx, using Ordered to resolve their order
Every authentication mechanism OR provider must start with security:authentication-something
Use appropriate attrs and elements depending on provider or mechanism
-->
<bean id="authenticationManager"
-->
<security:authentication-mechanism id="authenticationManager">
<security:authentication-jdbc ref="authenticationRepository"/>
</security:authentication-mechanism>
<!--<bean id="authenticationManager"
class="org.acegisecurity.providers.ProviderManager">
<property name="providers">
make it optional, if not supplied autodetect all auth-providers from app ctx, using Ordered to resolve their order
<property name="providers">
<list>
<ref local="authenticationRepository" />
</list>
</property>
</bean>
</bean>
--><!-- dao authentication provider -->
<security:authentication-repository id="authenticationRepository" />
<bean id="userDetailsService"

View File

@ -66,8 +66,8 @@
we will call setOrder(2) such that this app effectively will use somehing with a higher order as the app-wide default -->
<security:authentication-basic id="id" realmName="Spring Security Application" entryPointOrder="2"/>
<!-- This is used if they want an out-of-the-bx UserDetails; if they write their own, this goes away and they wire a legacy bean definition and then the various
beans depending on a UserDetails will auto-detect it at runtime OR provide a way of setUserDetails(UserDetails) if to specified explicitly.
<!-- This is used if they want an out-of-the-bx UserDetailsService; if they write their own, this goes away and they wire a legacy bean definition and then the various
beans depending on a UserDetailsService will auto-detect it at runtime OR provide a way of setUserDetailsService(UserDetailsService) if to specified explicitly.
If they fail to provide a repository, the security-autodetect will set one up for them with a few basic in-memory users and pwds -->
<security:principal-repository id="id">
<security:ldap x="you can do the attributes and suitable nested elements"/>