SEC-56: Add localisation support.

This commit is contained in:
Ben Alex 2005-11-26 05:11:53 +00:00
parent f4c3e2ff8c
commit fddcd6112e
44 changed files with 2403 additions and 1862 deletions

View File

@ -29,6 +29,8 @@ import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.jdbc.object.MappingSqlQuery;
import org.springframework.util.Assert;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
@ -51,9 +53,6 @@ import javax.sql.DataSource;
* the {@link MappingSqlQuery} instance used, via the {@link
* #initMappingSqlQueries()} extension point.
* </p>
*
* @author Ben Alex
* @version $Id$
*/
public class JdbcDaoImpl extends JdbcDaoSupport implements BasicAclDao {
//~ Static fields/initializers =============================================
@ -79,113 +78,6 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements BasicAclDao {
//~ Methods ================================================================
/**
* Returns the ACLs associated with the requested
* <code>AclObjectIdentity</code>.
*
* <P>
* The {@link BasicAclEntry}s returned by this method will have
* <code>String</code>-based recipients. This will not be a problem if you
* are using the <code>GrantedAuthorityEffectiveAclsResolver</code>, which
* is the default configured against <code>BasicAclProvider</code>.
* </p>
*
* <P>
* This method will only return ACLs for requests where the
* <code>AclObjectIdentity</code> is of type {@link
* NamedEntityObjectIdentity}. Of course, you can subclass or replace this
* class and support your own custom <code>AclObjectIdentity</code> types.
* </p>
*
* @param aclObjectIdentity for which ACL information is required (cannot
* be <code>null</code> and must be an instance of
* <code>NamedEntityObjectIdentity</code>)
*
* @return the ACLs that apply (without any <code>null</code>s inside the
* array), or <code>null</code> if not found or if an incompatible
* <code>AclObjectIdentity</code> was requested
*/
public BasicAclEntry[] getAcls(AclObjectIdentity aclObjectIdentity) {
String aclObjectIdentityString;
try {
aclObjectIdentityString = convertAclObjectIdentityToString(aclObjectIdentity);
} catch (IllegalArgumentException unsupported) {
return null; // pursuant to contract described in JavaDocs above
}
// Lookup the object's main properties from the RDBMS (guaranteed no nulls)
List objects = objectProperties.execute(aclObjectIdentityString);
if (objects.size() == 0) {
// this is an unknown object identity string
return null;
}
// Cast to an object properties holder (there should only be one record)
AclDetailsHolder propertiesInformation = (AclDetailsHolder) objects.get(0);
// Lookup the object's ACLs from RDBMS (guaranteed no nulls)
List acls = aclsByObjectIdentity.execute(propertiesInformation
.getForeignKeyId());
if (acls.size() == 0) {
// return merely an inheritence marker (as we know about the object but it has no related ACLs)
return new BasicAclEntry[] {createBasicAclEntry(propertiesInformation,
null)};
} else {
// return the individual ACL instances
AclDetailsHolder[] aclHolders = (AclDetailsHolder[]) acls.toArray(new AclDetailsHolder[] {});
List toReturnAcls = new Vector();
for (int i = 0; i < aclHolders.length; i++) {
toReturnAcls.add(createBasicAclEntry(propertiesInformation,
aclHolders[i]));
}
return (BasicAclEntry[]) toReturnAcls.toArray(new BasicAclEntry[] {});
}
}
public void setAclsByObjectIdentity(
MappingSqlQuery aclsByObjectIdentityQuery) {
this.aclsByObjectIdentity = aclsByObjectIdentityQuery;
}
public MappingSqlQuery getAclsByObjectIdentity() {
return aclsByObjectIdentity;
}
/**
* Allows the default query string used to retrieve ACLs based on object
* identity to be overriden, if default table or column names need to be
* changed. The default query is {@link
* #DEF_ACLS_BY_OBJECT_IDENTITY_QUERY}; when modifying this query, ensure
* that all returned columns are mapped back to the same column names as
* in the default query.
*
* @param queryString The query string to set
*/
public void setAclsByObjectIdentityQuery(String queryString) {
aclsByObjectIdentityQuery = queryString;
}
public String getAclsByObjectIdentityQuery() {
return aclsByObjectIdentityQuery;
}
public void setObjectProperties(MappingSqlQuery objectPropertiesQuery) {
this.objectProperties = objectPropertiesQuery;
}
public void setObjectPropertiesQuery(String queryString) {
objectPropertiesQuery = queryString;
}
public String getObjectPropertiesQuery() {
return objectPropertiesQuery;
}
/**
* Responsible for covering a <code>AclObjectIdentity</code> to a
* <code>String</code> that can be located in the RDBMS.
@ -193,17 +85,13 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements BasicAclDao {
* @param aclObjectIdentity to locate
*
* @return the object identity as a <code>String</code>
*
* @throws IllegalArgumentException DOCUMENT ME!
*/
protected String convertAclObjectIdentityToString(
AclObjectIdentity aclObjectIdentity) {
// Ensure we can process this type of AclObjectIdentity
if (!(aclObjectIdentity instanceof NamedEntityObjectIdentity)) {
throw new IllegalArgumentException(
"Only aclObjectIdentity of type NamedEntityObjectIdentity supported (was passed: "
+ aclObjectIdentity + ")");
}
Assert.isInstanceOf(NamedEntityObjectIdentity.class, aclObjectIdentity,
"Only aclObjectIdentity of type NamedEntityObjectIdentity supported (was passed: "
+ aclObjectIdentity + ")");
NamedEntityObjectIdentity neoi = (NamedEntityObjectIdentity) aclObjectIdentity;
@ -211,19 +99,6 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements BasicAclDao {
return neoi.getClassname() + ":" + neoi.getId();
}
protected void initDao() throws ApplicationContextException {
initMappingSqlQueries();
}
/**
* Extension point to allow other MappingSqlQuery objects to be substituted
* in a subclass
*/
protected void initMappingSqlQueries() {
setAclsByObjectIdentity(new AclsByObjectIdentityMapping(getDataSource()));
setObjectProperties(new ObjectPropertiesMapping(getDataSource()));
}
/**
* Constructs an individual <code>BasicAclEntry</code> from the passed
* <code>AclDetailsHolder</code>s.
@ -263,206 +138,336 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements BasicAclDao {
entry.setAclObjectIdentity(propertiesInformation.getAclObjectIdentity());
entry.setAclObjectParentIdentity(propertiesInformation
.getAclObjectParentIdentity());
.getAclObjectParentIdentity());
if (aclInformation == null) {
// this is an inheritence marker instance only
entry.setMask(0);
entry.setRecipient(RECIPIENT_USED_FOR_INHERITENCE_MARKER);
} else {
// this is an individual ACL entry
entry.setMask(aclInformation.getMask());
entry.setRecipient(aclInformation.getRecipient());
}
if (aclInformation == null) {
// this is an inheritence marker instance only
entry.setMask(0);
entry.setRecipient(RECIPIENT_USED_FOR_INHERITENCE_MARKER);
} else {
// this is an individual ACL entry
entry.setMask(aclInformation.getMask());
entry.setRecipient(aclInformation.getRecipient());
}
return entry;
}
//~ Inner Classes ==========================================================
/**
* Used to hold details of a domain object instance's properties, or an
* individual ACL entry.
*
* <P>
* Not all properties will be set. The actual properties set will depend on
* which <code>MappingSqlQuery</code> creates the object.
* </p>
*
* <P>
* Does not enforce <code>null</code>s or empty <code>String</code>s as
* this is performed by the <code>MappingSqlQuery</code> objects (or
* preferably the backend RDBMS via schema constraints).
* </p>
*/
protected final class AclDetailsHolder {
private AclObjectIdentity aclObjectIdentity;
private AclObjectIdentity aclObjectParentIdentity;
private Class aclClass;
private Object recipient;
private int mask;
private long foreignKeyId;
/**
* Record details of an individual ACL entry (usually from the
* ACL_PERMISSION table)
*
* @param recipient the recipient
* @param mask the integer to be masked
*/
public AclDetailsHolder(Object recipient, int mask) {
this.recipient = recipient;
this.mask = mask;
return entry;
}
/**
* Record details of a domain object instance's properties (usually
* from the ACL_OBJECT_IDENTITY table)
* Returns the ACLs associated with the requested
* <code>AclObjectIdentity</code>.
*
* <P>
* The {@link BasicAclEntry}s returned by this method will have
* <code>String</code>-based recipients. This will not be a problem if
* you are using the
* <code>GrantedAuthorityEffectiveAclsResolver</code>, which is the
* default configured against <code>BasicAclProvider</code>.
* </p>
*
* <P>
* This method will only return ACLs for requests where the
* <code>AclObjectIdentity</code> is of type {@link
* NamedEntityObjectIdentity}. Of course, you can subclass or replace
* this class and support your own custom
* <code>AclObjectIdentity</code> types.
* </p>
*
* @param foreignKeyId used by the
* <code>AclsByObjectIdentityMapping</code> to locate the
* individual ACL entries
* @param aclObjectIdentity the object identity of the domain object
* instance
* @param aclObjectParentIdentity the object identity of the domain
* object instance's parent
* @param aclClass the class of which a new instance which should be
* created for each individual ACL entry (or an inheritence
* "holder" class if there are no ACL entries)
* @param aclObjectIdentity for which ACL information is required
* (cannot be <code>null</code> and must be an instance of
* <code>NamedEntityObjectIdentity</code>)
*
* @return the ACLs that apply (without any <code>null</code>s inside
* the array), or <code>null</code> if not found or if an
* incompatible <code>AclObjectIdentity</code> was requested
*/
public AclDetailsHolder(long foreignKeyId,
AclObjectIdentity aclObjectIdentity,
AclObjectIdentity aclObjectParentIdentity, Class aclClass) {
this.foreignKeyId = foreignKeyId;
this.aclObjectIdentity = aclObjectIdentity;
this.aclObjectParentIdentity = aclObjectParentIdentity;
this.aclClass = aclClass;
}
public Class getAclClass() {
return aclClass;
}
public AclObjectIdentity getAclObjectIdentity() {
return aclObjectIdentity;
}
public AclObjectIdentity getAclObjectParentIdentity() {
return aclObjectParentIdentity;
}
public long getForeignKeyId() {
return foreignKeyId;
}
public int getMask() {
return mask;
}
public Object getRecipient() {
return recipient;
}
}
/**
* Query object to look up individual ACL entries.
*
* <P>
* Returns the generic <code>AclDetailsHolder</code> object.
* </p>
*
* <P>
* Guarantees to never return <code>null</code> (exceptions are thrown in
* the event of any issues).
* </p>
*
* <P>
* The executed SQL requires the following information be made available
* from the indicated placeholders: 1. RECIPIENT, 2. MASK.
* </p>
*/
protected class AclsByObjectIdentityMapping extends MappingSqlQuery {
protected AclsByObjectIdentityMapping(DataSource ds) {
super(ds, aclsByObjectIdentityQuery);
declareParameter(new SqlParameter(Types.BIGINT));
compile();
}
protected Object mapRow(ResultSet rs, int rownum)
throws SQLException {
String recipient = rs.getString(1);
int mask = rs.getInt(2);
if ((recipient == null) || "".equals(recipient)) {
throw new IllegalArgumentException("recipient required");
}
return new AclDetailsHolder(recipient, mask);
}
}
/**
* Query object to look up properties for an object identity.
*
* <P>
* Returns the generic <code>AclDetailsHolder</code> object.
* </p>
*
* <P>
* Guarantees to never return <code>null</code> (exceptions are thrown in
* the event of any issues).
* </p>
*
* <P>
* The executed SQL requires the following information be made available
* from the indicated placeholders: 1. ID, 2. OBJECT_IDENTITY, 3.
* ACL_CLASS and 4. PARENT_OBJECT_IDENTITY.
* </p>
*/
protected class ObjectPropertiesMapping extends MappingSqlQuery {
protected ObjectPropertiesMapping(DataSource ds) {
super(ds, objectPropertiesQuery);
declareParameter(new SqlParameter(Types.VARCHAR));
compile();
}
protected Object mapRow(ResultSet rs, int rownum)
throws SQLException {
long id = rs.getLong(1); // required
String objectIdentity = rs.getString(2); // required
String aclClass = rs.getString(3); // required
String parentObjectIdentity = rs.getString(4); // optional
if ((objectIdentity == null) || "".equals(objectIdentity)
|| (aclClass == null) || "".equals(aclClass)) {
// shouldn't happen if DB schema defined NOT NULL columns
throw new IllegalArgumentException(
"required DEF_OBJECT_PROPERTIES_QUERY value returned null or empty");
}
Class aclClazz;
public BasicAclEntry[] getAcls(AclObjectIdentity aclObjectIdentity) {
String aclObjectIdentityString;
try {
aclClazz = this.getClass().getClassLoader().loadClass(aclClass);
} catch (ClassNotFoundException cnf) {
throw new IllegalArgumentException(cnf.getMessage());
aclObjectIdentityString = convertAclObjectIdentityToString(aclObjectIdentity);
} catch (IllegalArgumentException unsupported) {
return null; // pursuant to contract described in JavaDocs above
}
return new AclDetailsHolder(id, buildIdentity(objectIdentity),
buildIdentity(parentObjectIdentity), aclClazz);
}
// Lookup the object's main properties from the RDBMS (guaranteed no nulls)
List objects = objectProperties.execute(aclObjectIdentityString);
private AclObjectIdentity buildIdentity(String identity) {
if (identity == null) {
// Must be an empty parent, so return null
if (objects.size() == 0) {
// this is an unknown object identity string
return null;
}
int delim = identity.lastIndexOf(":");
String classname = identity.substring(0, delim);
String id = identity.substring(delim + 1);
// Cast to an object properties holder (there should only be one record)
AclDetailsHolder propertiesInformation = (AclDetailsHolder) objects
.get(0);
return new NamedEntityObjectIdentity(classname, id);
}
}
}
// Lookup the object's ACLs from RDBMS (guaranteed no nulls)
List acls = aclsByObjectIdentity.execute(propertiesInformation
.getForeignKeyId());
if (acls.size() == 0) {
// return merely an inheritence marker (as we know about the object but it has no related ACLs)
return new BasicAclEntry[] {createBasicAclEntry(propertiesInformation,
null)};
} else {
// return the individual ACL instances
AclDetailsHolder[] aclHolders = (AclDetailsHolder[]) acls
.toArray(new AclDetailsHolder[] {});
List toReturnAcls = new Vector();
for (int i = 0; i < aclHolders.length; i++) {
toReturnAcls.add(createBasicAclEntry(
propertiesInformation, aclHolders[i]));
}
return (BasicAclEntry[]) toReturnAcls.toArray(new BasicAclEntry[] {});
}
}
public MappingSqlQuery getAclsByObjectIdentity() {
return aclsByObjectIdentity;
}
public String getAclsByObjectIdentityQuery() {
return aclsByObjectIdentityQuery;
}
public String getObjectPropertiesQuery() {
return objectPropertiesQuery;
}
protected void initDao() throws ApplicationContextException {
initMappingSqlQueries();
}
/**
* Extension point to allow other MappingSqlQuery objects to be
* substituted in a subclass
*/
protected void initMappingSqlQueries() {
setAclsByObjectIdentity(new AclsByObjectIdentityMapping(
getDataSource()));
setObjectProperties(new ObjectPropertiesMapping(
getDataSource()));
}
public void setAclsByObjectIdentity(
MappingSqlQuery aclsByObjectIdentityQuery) {
this.aclsByObjectIdentity = aclsByObjectIdentityQuery;
}
/**
* Allows the default query string used to retrieve ACLs based
* on object identity to be overriden, if default table or
* column names need to be changed. The default query is
* {@link #DEF_ACLS_BY_OBJECT_IDENTITY_QUERY}; when modifying
* this query, ensure that all returned columns are mapped
* back to the same column names as in the default query.
*
* @param queryString The query string to set
*/
public void setAclsByObjectIdentityQuery(String queryString) {
aclsByObjectIdentityQuery = queryString;
}
public void setObjectProperties(
MappingSqlQuery objectPropertiesQuery) {
this.objectProperties = objectPropertiesQuery;
}
public void setObjectPropertiesQuery(String queryString) {
objectPropertiesQuery = queryString;
}
//~ Inner Classes ==========================================================
/**
* Used to hold details of a domain object instance's
* properties, or an individual ACL entry.
*
* <P>
* Not all properties will be set. The actual properties set
* will depend on which <code>MappingSqlQuery</code> creates
* the object.
* </p>
*
* <P>
* Does not enforce <code>null</code>s or empty
* <code>String</code>s as this is performed by the
* <code>MappingSqlQuery</code> objects (or preferably the
* backend RDBMS via schema constraints).
* </p>
*/
protected final class AclDetailsHolder {
private AclObjectIdentity aclObjectIdentity;
private AclObjectIdentity aclObjectParentIdentity;
private Class aclClass;
private Object recipient;
private int mask;
private long foreignKeyId;
/**
* Record details of an individual ACL entry (usually from
* the ACL_PERMISSION table)
*
* @param recipient the recipient
* @param mask the integer to be masked
*/
public AclDetailsHolder(Object recipient, int mask) {
this.recipient = recipient;
this.mask = mask;
}
/**
* Record details of a domain object instance's properties
* (usually from the ACL_OBJECT_IDENTITY table)
*
* @param foreignKeyId used by the
* <code>AclsByObjectIdentityMapping</code> to
* locate the individual ACL entries
* @param aclObjectIdentity the object identity of the
* domain object instance
* @param aclObjectParentIdentity the object identity of
* the domain object instance's parent
* @param aclClass the class of which a new instance which
* should be created for each individual ACL entry
* (or an inheritence "holder" class if there are
* no ACL entries)
*/
public AclDetailsHolder(long foreignKeyId,
AclObjectIdentity aclObjectIdentity,
AclObjectIdentity aclObjectParentIdentity,
Class aclClass) {
this.foreignKeyId = foreignKeyId;
this.aclObjectIdentity = aclObjectIdentity;
this.aclObjectParentIdentity = aclObjectParentIdentity;
this.aclClass = aclClass;
}
public Class getAclClass() {
return aclClass;
}
public AclObjectIdentity getAclObjectIdentity() {
return aclObjectIdentity;
}
public AclObjectIdentity getAclObjectParentIdentity() {
return aclObjectParentIdentity;
}
public long getForeignKeyId() {
return foreignKeyId;
}
public int getMask() {
return mask;
}
public Object getRecipient() {
return recipient;
}
}
/**
* Query object to look up individual ACL entries.
*
* <P>
* Returns the generic <code>AclDetailsHolder</code> object.
* </p>
*
* <P>
* Guarantees to never return <code>null</code> (exceptions are
* thrown in the event of any issues).
* </p>
*
* <P>
* The executed SQL requires the following information be made
* available from the indicated placeholders: 1. RECIPIENT, 2.
* MASK.
* </p>
*/
protected class AclsByObjectIdentityMapping
extends MappingSqlQuery {
protected AclsByObjectIdentityMapping(DataSource ds) {
super(ds, aclsByObjectIdentityQuery);
declareParameter(new SqlParameter(Types.BIGINT));
compile();
}
protected Object mapRow(ResultSet rs, int rownum)
throws SQLException {
String recipient = rs.getString(1);
int mask = rs.getInt(2);
Assert.hasText(recipient, "recipient required");
return new AclDetailsHolder(recipient, mask);
}
}
/**
* Query object to look up properties for an object identity.
*
* <P>
* Returns the generic <code>AclDetailsHolder</code> object.
* </p>
*
* <P>
* Guarantees to never return <code>null</code> (exceptions are
* thrown in the event of any issues).
* </p>
*
* <P>
* The executed SQL requires the following information be made
* available from the indicated placeholders: 1. ID, 2.
* OBJECT_IDENTITY, 3. ACL_CLASS and 4.
* PARENT_OBJECT_IDENTITY.
* </p>
*/
protected class ObjectPropertiesMapping extends MappingSqlQuery {
protected ObjectPropertiesMapping(DataSource ds) {
super(ds, objectPropertiesQuery);
declareParameter(new SqlParameter(Types.VARCHAR));
compile();
}
private AclObjectIdentity buildIdentity(String identity) {
if (identity == null) {
// Must be an empty parent, so return null
return null;
}
int delim = identity.lastIndexOf(":");
String classname = identity.substring(0, delim);
String id = identity.substring(delim + 1);
return new NamedEntityObjectIdentity(classname, id);
}
protected Object mapRow(ResultSet rs, int rownum)
throws SQLException {
long id = rs.getLong(1); // required
String objectIdentity = rs.getString(2); // required
String aclClass = rs.getString(3); // required
String parentObjectIdentity = rs.getString(4); // optional
Assert.hasText(objectIdentity,
"required DEF_OBJECT_PROPERTIES_QUERY value (objectIdentity) returned null or empty");
Assert.hasText(aclClass,
"required DEF_OBJECT_PROPERTIES_QUERY value (aclClass) returned null or empty");
Class aclClazz;
try {
aclClazz = this.getClass().getClassLoader()
.loadClass(aclClass);
} catch (ClassNotFoundException cnf) {
throw new IllegalArgumentException(cnf.getMessage());
}
return new AclDetailsHolder(id,
buildIdentity(objectIdentity),
buildIdentity(parentObjectIdentity), aclClazz);
}
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,9 +18,15 @@ package org.acegisecurity.adapters;
import org.acegisecurity.Authentication;
import org.acegisecurity.AuthenticationException;
import org.acegisecurity.BadCredentialsException;
import org.acegisecurity.providers.AuthenticationProvider;
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.util.Assert;
@ -38,28 +44,20 @@ import org.springframework.util.Assert;
* <P>
* If the key does not match, a <code>BadCredentialsException</code> is thrown.
* </p>
*
* @author Ben Alex
* @version $Id$
*/
public class AuthByAdapterProvider implements InitializingBean,
AuthenticationProvider {
AuthenticationProvider, MessageSourceAware {
//~ Instance fields ========================================================
protected MessageSourceAccessor messages;
private String key;
//~ Methods ================================================================
public void setKey(String key) {
this.key = key;
}
public String getKey() {
return key;
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(key, "A Key is required and should match that configured for the adapters");
Assert.notNull(key,
"A Key is required and should match that configured for the adapters");
Assert.notNull(messages, "A message source must be set");
}
public Authentication authenticate(Authentication authentication)
@ -69,11 +67,24 @@ public class AuthByAdapterProvider implements InitializingBean,
if (token.getKeyHash() == key.hashCode()) {
return authentication;
} else {
throw new BadCredentialsException(
"The presented AuthByAdapter implementation does not contain the expected key");
throw new BadCredentialsException(messages.getMessage(
"AuthByAdapterProvider.incorrectKey",
"The presented AuthByAdapter implementation does not contain the expected key"));
}
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public void setMessageSource(MessageSource messageSource) {
this.messages = new MessageSourceAccessor(messageSource);
}
public boolean supports(Class authentication) {
if (AuthByAdapter.class.isAssignableFrom(authentication)) {
return true;

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -19,6 +19,7 @@ import org.acegisecurity.AccessDeniedException;
import org.acegisecurity.Authentication;
import org.acegisecurity.ConfigAttribute;
import org.acegisecurity.ConfigAttributeDefinition;
import org.acegisecurity.acl.AclEntry;
import org.acegisecurity.acl.AclManager;
import org.acegisecurity.acl.basic.BasicAclEntry;
@ -28,6 +29,11 @@ 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.util.Assert;
import java.util.Iterator;
@ -45,9 +51,8 @@ import java.util.Iterator;
* (ACL) permissions associated with a domain object instance for the current
* <code>Authentication</code> object. This class is designed to process
* {@link AclEntry}s that are subclasses of {@link
* org.acegisecurity.acl.basic.BasicAclEntry} only. Generally these
* are obtained by using the {@link
* org.acegisecurity.acl.basic.BasicAclProvider}.
* org.acegisecurity.acl.basic.BasicAclEntry} only. Generally these are
* obtained by using the {@link org.acegisecurity.acl.basic.BasicAclProvider}.
* </p>
*
* <p>
@ -55,8 +60,8 @@ import java.util.Iterator;
* ConfigAttribute#getAttribute()} matches the {@link
* #processConfigAttribute}. The provider will then lookup the ACLs from the
* <code>AclManager</code> and ensure the principal is {@link
* org.acegisecurity.acl.basic.BasicAclEntry#isPermitted(int)} for
* at least one of the {@link #requirePermission}s.
* org.acegisecurity.acl.basic.BasicAclEntry#isPermitted(int)} for at least
* one of the {@link #requirePermission}s.
* </p>
*
* <p>
@ -74,9 +79,8 @@ import java.util.Iterator;
* <p>
* The <code>AclManager</code> is allowed to return any implementations of
* <code>AclEntry</code> it wishes. However, this provider will only be able
* to validate against <code>BasicAclEntry</code>s, and thus access
* will be denied if no <code>AclEntry</code> is of type
* <code>BasicAclEntry</code>.
* to validate against <code>BasicAclEntry</code>s, and thus access will be
* denied if no <code>AclEntry</code> is of type <code>BasicAclEntry</code>.
* </p>
*
* <p>
@ -87,12 +91,9 @@ import java.util.Iterator;
* <p>
* All comparisons and prefixes are case sensitive.
* </p>
*
* @author Ben Alex
* @version $Id$
*/
public class BasicAclEntryAfterInvocationProvider
implements AfterInvocationProvider, InitializingBean {
implements AfterInvocationProvider, InitializingBean, MessageSourceAware {
//~ Static fields/initializers =============================================
protected static final Log logger = LogFactory.getLog(BasicAclEntryAfterInvocationProvider.class);
@ -100,41 +101,21 @@ public class BasicAclEntryAfterInvocationProvider
//~ Instance fields ========================================================
private AclManager aclManager;
protected MessageSourceAccessor messages;
private String processConfigAttribute = "AFTER_ACL_READ";
private int[] requirePermission = {SimpleAclEntry.READ};
//~ Methods ================================================================
public void setAclManager(AclManager aclManager) {
this.aclManager = aclManager;
}
public AclManager getAclManager() {
return aclManager;
}
public void setProcessConfigAttribute(String processConfigAttribute) {
this.processConfigAttribute = processConfigAttribute;
}
public String getProcessConfigAttribute() {
return processConfigAttribute;
}
public void setRequirePermission(int[] requirePermission) {
this.requirePermission = requirePermission;
}
public int[] getRequirePermission() {
return requirePermission;
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(processConfigAttribute, "A processConfigAttribute is mandatory");
Assert.notNull(processConfigAttribute,
"A processConfigAttribute is mandatory");
Assert.notNull(aclManager, "An aclManager is mandatory");
Assert.notNull(messages, "A message source must be set");
if ((requirePermission == null) || (requirePermission.length == 0)) {
throw new IllegalArgumentException("One or more requirePermission entries is mandatory");
throw new IllegalArgumentException(
"One or more requirePermission entries is mandatory");
}
}
@ -162,16 +143,16 @@ public class BasicAclEntryAfterInvocationProvider
authentication);
if ((acls == null) || (acls.length == 0)) {
throw new AccessDeniedException("Authentication: "
+ authentication.toString()
+ " has NO permissions at all to the domain object: "
+ returnedObject);
throw new AccessDeniedException(messages.getMessage(
"BasicAclEntryAfterInvocationProvider.noPermission",
new Object[] {authentication.getName(), returnedObject},
"Authentication {0} has NO permissions at all to the domain object {1}"));
}
for (int i = 0; i < acls.length; i++) {
// Locate processable AclEntrys
if (acls[i] instanceof BasicAclEntry) {
BasicAclEntry processableAcl = (BasicAclEntry) acls[i];
BasicAclEntry processableAcl = (BasicAclEntry) acls[i];
// See if principal has any of the required permissions
for (int y = 0; y < requirePermission.length; y++) {
@ -190,16 +171,44 @@ public class BasicAclEntryAfterInvocationProvider
}
// No permissions match
throw new AccessDeniedException("Authentication: "
+ authentication.toString()
+ " has ACL permissions to the domain object, but not the required ACL permission to the domain object: "
+ returnedObject);
throw new AccessDeniedException(messages.getMessage(
"BasicAclEntryAfterInvocationProvider.insufficientPermission",
new Object[] {authentication.getName(), returnedObject},
"Authentication {0} has ACL permissions to the domain object, but not the required ACL permission to the domain object {1}"));
}
}
return returnedObject;
}
public AclManager getAclManager() {
return aclManager;
}
public String getProcessConfigAttribute() {
return processConfigAttribute;
}
public int[] getRequirePermission() {
return requirePermission;
}
public void setAclManager(AclManager aclManager) {
this.aclManager = aclManager;
}
public void setMessageSource(MessageSource messageSource) {
this.messages = new MessageSourceAccessor(messageSource);
}
public void setProcessConfigAttribute(String processConfigAttribute) {
this.processConfigAttribute = processConfigAttribute;
}
public void setRequirePermission(int[] requirePermission) {
this.requirePermission = requirePermission;
}
public boolean supports(ConfigAttribute attribute) {
if ((attribute.getAttribute() != null)
&& attribute.getAttribute().equals(getProcessConfigAttribute())) {

View File

@ -19,6 +19,11 @@ import org.acegisecurity.Authentication;
import org.acegisecurity.AuthenticationException;
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.util.Assert;
@ -30,36 +35,61 @@ import org.springframework.util.Assert;
* By default uses {@link org.acegisecurity.concurrent.SessionRegistryImpl},
* although any <code>SessionRegistry</code> may be used.
* </p>
*
* @author Ben Alex
* @version $Id$
*/
public class ConcurrentSessionControllerImpl
implements ConcurrentSessionController, InitializingBean {
implements ConcurrentSessionController, InitializingBean,
MessageSourceAware {
//~ Instance fields ========================================================
protected MessageSourceAccessor messages;
private SessionRegistry sessionRegistry = new SessionRegistryImpl();
private int maximumSessions = 1;
private boolean exceptionIfMaximumExceeded = false;
private int maximumSessions = 1;
//~ Methods ================================================================
public void setMaximumSessions(int maximumSessions) {
this.maximumSessions = maximumSessions;
}
public void setSessionRegistry(SessionRegistry sessionRegistry) {
this.sessionRegistry = sessionRegistry;
}
public void setExceptionIfMaximumExceeded(boolean exceptionIfMaximumExceeded) {
this.exceptionIfMaximumExceeded = exceptionIfMaximumExceeded;
}
public void afterPropertiesSet() throws Exception {
public void afterPropertiesSet() throws Exception {
Assert.notNull(sessionRegistry, "SessionRegistry required");
Assert.isTrue(maximumSessions != 0,
"MaximumLogins must be either -1 to allow unlimited logins, or a positive integer to specify a maximum");
Assert.notNull(this.messages, "A message source must be set");
}
/**
* Allows subclasses to customise behaviour when too many sessions are
* detected.
*
* @param sessionId the session ID of the present request
* @param sessions either <code>null</code> or all unexpired sessions
* associated with the principal
* @param allowableSessions DOCUMENT ME!
* @param registry an instance of the <code>SessionRegistry</code> for
* subclass use
*
* @throws ConcurrentLoginException DOCUMENT ME!
*/
protected void allowableSessionsExceeded(String sessionId,
SessionInformation[] sessions, int allowableSessions,
SessionRegistry registry) {
if (exceptionIfMaximumExceeded || (sessions == null)) {
throw new ConcurrentLoginException(messages.getMessage(
"ConcurrentSessionControllerImpl.exceededAllowed",
new Object[] {new Integer(allowableSessions)},
"Maximum sessions of {0} for this principal exceeded"));
}
// Determine least recently used session, and mark it for invalidation
SessionInformation leastRecentlyUsed = null;
for (int i = 0; i < sessions.length; i++) {
if ((leastRecentlyUsed == null)
|| sessions[i].getLastRequest()
.before(leastRecentlyUsed.getLastRequest())) {
leastRecentlyUsed = sessions[i];
}
}
leastRecentlyUsed.expireNow();
}
public void checkAuthenticationAllowed(Authentication request)
@ -68,86 +98,82 @@ public class ConcurrentSessionControllerImpl
"Authentication request cannot be null (violation of interface contract)");
Object principal = SessionRegistryUtils
.obtainPrincipalFromAuthentication(request);
String sessionId = SessionRegistryUtils
.obtainSessionIdFromAuthentication(request);
.obtainPrincipalFromAuthentication(request);
String sessionId = SessionRegistryUtils
.obtainSessionIdFromAuthentication(request);
SessionInformation[] sessions = sessionRegistry.getAllSessions(principal);
SessionInformation[] sessions = sessionRegistry.getAllSessions(principal);
int sessionCount = 0;
int sessionCount = 0;
if (sessions != null) {
sessionCount = sessions.length;
}
int allowableSessions = getMaximumSessionsForThisUser(request);
Assert.isTrue(allowableSessions != 0,
"getMaximumSessionsForThisUser() must return either -1 to allow unlimited logins, or a positive integer to specify a maximum");
if (sessionCount < allowableSessions) {
return;
} else if (sessionCount == allowableSessions) {
// Only permit it though if this request is associated with one of the sessions
for (int i = 0; i < sessionCount; i++) {
if (sessions[i].getSessionId().equals(sessionId)) {
return;
if (sessions != null) {
sessionCount = sessions.length;
}
int allowableSessions = getMaximumSessionsForThisUser(request);
Assert.isTrue(allowableSessions != 0,
"getMaximumSessionsForThisUser() must return either -1 to allow unlimited logins, or a positive integer to specify a maximum");
if (sessionCount < allowableSessions) {
return;
} else if (sessionCount == allowableSessions) {
// Only permit it though if this request is associated with one of the sessions
for (int i = 0; i < sessionCount; i++) {
if (sessions[i].getSessionId().equals(sessionId)) {
return;
}
}
}
allowableSessionsExceeded(sessionId, sessions,
allowableSessions, sessionRegistry);
}
}
allowableSessionsExceeded(sessionId, sessions, allowableSessions, sessionRegistry);
}
/**
* Allows subclasses to customise behaviour when too many sessions are
* detected.
*
* @param sessionId the session ID of the present request
* @param sessions either <code>null</code> or all unexpired sessions associated with the principal
* @param registry an instance of the <code>SessionRegistry</code> for subclass use
*/
protected void allowableSessionsExceeded(String sessionId, SessionInformation[] sessions, int allowableSessions, SessionRegistry registry) {
if (exceptionIfMaximumExceeded || sessions == null) {
throw new ConcurrentLoginException("Maximum sessions of "
+ allowableSessions + " for this principal exceeded");
}
// Determine least recently used session, and mark it for invalidation
SessionInformation leastRecentlyUsed = null;
for (int i = 0; i < sessions.length; i++) {
if (leastRecentlyUsed == null || sessions[i].getLastRequest().before(leastRecentlyUsed.getLastRequest())) {
leastRecentlyUsed = sessions[i];
}
}
leastRecentlyUsed.expireNow();
}
/**
* Method intended for use by subclasses to override the maximum
* number of sessions that are permitted for a particular
* authentication. The default implementation simply returns the
* <code>maximumSessions</code> value for the bean.
*
* @param authentication to determine the maximum sessions for
*
* @return either -1 meaning unlimited, or a positive integer to
* limit (never zero)
*/
protected int getMaximumSessionsForThisUser(
Authentication authentication) {
return maximumSessions;
}
public void registerSuccessfulAuthentication(Authentication authentication) {
Assert.notNull(authentication,
"Authentication cannot be null (violation of interface contract)");
public void registerSuccessfulAuthentication(
Authentication authentication) {
Assert.notNull(authentication,
"Authentication cannot be null (violation of interface contract)");
Object principal = SessionRegistryUtils
.obtainPrincipalFromAuthentication(authentication);
String sessionId = SessionRegistryUtils
.obtainSessionIdFromAuthentication(authentication);
Object principal = SessionRegistryUtils
.obtainPrincipalFromAuthentication(authentication);
String sessionId = SessionRegistryUtils
.obtainSessionIdFromAuthentication(authentication);
sessionRegistry.removeSessionInformation(sessionId);
sessionRegistry.registerNewSession(sessionId, principal);
}
sessionRegistry.removeSessionInformation(sessionId);
sessionRegistry.registerNewSession(sessionId, principal);
}
/**
* Method intended for use by subclasses to override the maximum number of
* sessions that are permitted for a particular authentication. The
* default implementation simply returns the <code>maximumSessions</code>
* value for the bean.
*
* @param authentication to determine the maximum sessions for
*
* @return either -1 meaning unlimited, or a positive integer to limit
* (never zero)
*/
protected int getMaximumSessionsForThisUser(Authentication authentication) {
return maximumSessions;
}
}
public void setExceptionIfMaximumExceeded(
boolean exceptionIfMaximumExceeded) {
this.exceptionIfMaximumExceeded = exceptionIfMaximumExceeded;
}
public void setMaximumSessions(int maximumSessions) {
this.maximumSessions = maximumSessions;
}
public void setMessageSource(MessageSource messageSource) {
this.messages = new MessageSourceAccessor(messageSource);
}
public void setSessionRegistry(
SessionRegistry sessionRegistry) {
this.sessionRegistry = sessionRegistry;
}
}

View File

@ -42,6 +42,9 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.util.Assert;
@ -135,12 +138,9 @@ import java.util.Set;
* </li>
* </ol>
* </p>
*
* @author Ben Alex
* @version $Id$
*/
public abstract class AbstractSecurityInterceptor implements InitializingBean,
ApplicationEventPublisherAware {
ApplicationEventPublisherAware, MessageSourceAware {
//~ Static fields/initializers =============================================
protected static final Log logger = LogFactory.getLog(AbstractSecurityInterceptor.class);
@ -151,6 +151,7 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean,
private AfterInvocationManager afterInvocationManager;
private ApplicationEventPublisher eventPublisher;
private AuthenticationManager authenticationManager;
protected MessageSourceAccessor messages;
private RunAsManager runAsManager = new NullRunAsManager();
private boolean alwaysReauthenticate = false;
private boolean rejectPublicInvocations = false;
@ -158,194 +159,6 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean,
//~ Methods ================================================================
public void setAfterInvocationManager(
AfterInvocationManager afterInvocationManager) {
this.afterInvocationManager = afterInvocationManager;
}
public AfterInvocationManager getAfterInvocationManager() {
return afterInvocationManager;
}
/**
* Indicates whether the <code>AbstractSecurityInterceptor</code> should
* ignore the {@link Authentication#isAuthenticated()} property. Defaults
* to <code>false</code>, meaning by default the
* <code>Authentication.isAuthenticated()</code> property is trusted and
* re-authentication will not occur if the principal has already been
* authenticated.
*
* @param alwaysReauthenticate <code>true</code> to force
* <code>AbstractSecurityInterceptor</code> to disregard the value
* of <code>Authentication.isAuthenticated()</code> and always
* re-authenticate the request (defaults to <code>false</code>).
*/
public void setAlwaysReauthenticate(boolean alwaysReauthenticate) {
this.alwaysReauthenticate = alwaysReauthenticate;
}
public boolean isAlwaysReauthenticate() {
return alwaysReauthenticate;
}
public void setApplicationEventPublisher(
ApplicationEventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
/**
* Indicates the type of secure objects the subclass will be presenting to
* the abstract parent for processing. This is used to ensure
* collaborators wired to the <code>AbstractSecurityInterceptor</code> all
* support the indicated secure object class.
*
* @return the type of secure object the subclass provides services for
*/
public abstract Class getSecureObjectClass();
public abstract ObjectDefinitionSource obtainObjectDefinitionSource();
public void setAccessDecisionManager(
AccessDecisionManager accessDecisionManager) {
this.accessDecisionManager = accessDecisionManager;
}
public AccessDecisionManager getAccessDecisionManager() {
return accessDecisionManager;
}
public void setAuthenticationManager(AuthenticationManager newManager) {
this.authenticationManager = newManager;
}
public AuthenticationManager getAuthenticationManager() {
return this.authenticationManager;
}
/**
* By rejecting public invocations (and setting this property to
* <code>true</code>), essentially you are ensuring that every secure
* object invocation advised by <code>AbstractSecurityInterceptor</code>
* has a configuration attribute defined. This is useful to ensure a "fail
* safe" mode where undeclared secure objects will be rejected and
* configuration omissions detected early. An
* <code>IllegalArgumentException</code> will be thrown by the
* <code>AbstractSecurityInterceptor</code> if you set this property to
* <code>true</code> and an attempt is made to invoke a secure object that
* has no configuration attributes.
*
* @param rejectPublicInvocations set to <code>true</code> to reject
* invocations of secure objects that have no configuration
* attributes (by default it is <code>true</code> which treats
* undeclared secure objects as "public" or unauthorized)
*/
public void setRejectPublicInvocations(boolean rejectPublicInvocations) {
this.rejectPublicInvocations = rejectPublicInvocations;
}
public boolean isRejectPublicInvocations() {
return rejectPublicInvocations;
}
public void setRunAsManager(RunAsManager runAsManager) {
this.runAsManager = runAsManager;
}
public RunAsManager getRunAsManager() {
return runAsManager;
}
public void setValidateConfigAttributes(boolean validateConfigAttributes) {
this.validateConfigAttributes = validateConfigAttributes;
}
public boolean isValidateConfigAttributes() {
return validateConfigAttributes;
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(getSecureObjectClass(),
"Subclass must provide a non-null response to getSecureObjectClass()");
Assert.notNull(this.authenticationManager,
"An AuthenticationManager is required");
Assert.notNull(this.accessDecisionManager,
"An AccessDecisionManager is required");
Assert.notNull(this.runAsManager, "A RunAsManager is required");
Assert.notNull(this.obtainObjectDefinitionSource(),
"An ObjectDefinitionSource is required");
if (!this.obtainObjectDefinitionSource().supports(getSecureObjectClass())) {
throw new IllegalArgumentException(
"ObjectDefinitionSource does not support secure object class: "
+ getSecureObjectClass());
}
if (!this.runAsManager.supports(getSecureObjectClass())) {
throw new IllegalArgumentException(
"RunAsManager does not support secure object class: "
+ getSecureObjectClass());
}
if (!this.accessDecisionManager.supports(getSecureObjectClass())) {
throw new IllegalArgumentException(
"AccessDecisionManager does not support secure object class: "
+ getSecureObjectClass());
}
if ((this.afterInvocationManager != null)
&& !this.afterInvocationManager.supports(getSecureObjectClass())) {
throw new IllegalArgumentException(
"AfterInvocationManager does not support secure object class: "
+ getSecureObjectClass());
}
if (this.validateConfigAttributes) {
Iterator iter = this.obtainObjectDefinitionSource()
.getConfigAttributeDefinitions();
if (iter == null) {
if (logger.isWarnEnabled()) {
logger.warn(
"Could not validate configuration attributes as the MethodDefinitionSource did not return a ConfigAttributeDefinition Iterator");
}
} else {
Set set = new HashSet();
while (iter.hasNext()) {
ConfigAttributeDefinition def = (ConfigAttributeDefinition) iter
.next();
Iterator attributes = def.getConfigAttributes();
while (attributes.hasNext()) {
ConfigAttribute attr = (ConfigAttribute) attributes
.next();
if (!this.runAsManager.supports(attr)
&& !this.accessDecisionManager.supports(attr)
&& ((this.afterInvocationManager == null)
|| !this.afterInvocationManager.supports(attr))) {
set.add(attr);
}
}
}
if (set.size() == 0) {
if (logger.isInfoEnabled()) {
logger.info("Validated configuration attributes");
}
} else {
throw new IllegalArgumentException(
"Unsupported configuration attributes: "
+ set.toString());
}
}
}
}
/**
* Completes the work of the <code>AbstractSecurityInterceptor</code> after
* the secure object invocation has been complete
@ -371,151 +184,353 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean,
+ token.getAuthentication().toString());
}
SecurityContextHolder.getContext().setAuthentication(token
.getAuthentication());
SecurityContextHolder.getContext()
.setAuthentication(token.getAuthentication());
}
if (afterInvocationManager != null) {
returnedObject = afterInvocationManager.decide(token
.getAuthentication(), token.getSecureObject(),
token.getAttr(), returnedObject);
}
return returnedObject;
}
protected InterceptorStatusToken beforeInvocation(Object object) {
Assert.notNull(object, "Object was null");
Assert.isTrue(getSecureObjectClass().isAssignableFrom(object.getClass()),
"Security invocation attempted for object "
+ object.getClass().getName()
+ " but AbstractSecurityInterceptor only configured to support secure objects of type: "
+ getSecureObjectClass());
ConfigAttributeDefinition attr = this.obtainObjectDefinitionSource()
.getAttributes(object);
if ((attr == null) && rejectPublicInvocations) {
throw new IllegalArgumentException(
"No public invocations are allowed via this AbstractSecurityInterceptor. This indicates a configuration error because the AbstractSecurityInterceptor.rejectPublicInvocations property is set to 'true'");
}
if (attr != null) {
if (logger.isDebugEnabled()) {
logger.debug("Secure object: " + object.toString()
+ "; ConfigAttributes: " + attr.toString());
.getAuthentication(), token.getSecureObject(),
token.getAttr(), returnedObject);
}
// We check for just the property we're interested in (we do
// not call Context.validate() like the ContextInterceptor)
if (SecurityContextHolder.getContext().getAuthentication() == null) {
credentialsNotFound("Authentication credentials were not found in the SecurityContext",
object, attr);
return returnedObject;
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(getSecureObjectClass(),
"Subclass must provide a non-null response to getSecureObjectClass()");
Assert.notNull(this.messages, "A message source must be set");
Assert.notNull(this.authenticationManager,
"An AuthenticationManager is required");
Assert.notNull(this.accessDecisionManager,
"An AccessDecisionManager is required");
Assert.notNull(this.runAsManager, "A RunAsManager is required");
Assert.notNull(this.obtainObjectDefinitionSource(),
"An ObjectDefinitionSource is required");
if (!this.obtainObjectDefinitionSource()
.supports(getSecureObjectClass())) {
throw new IllegalArgumentException(
"ObjectDefinitionSource does not support secure object class: "
+ getSecureObjectClass());
}
// Attempt authentication if not already authenticated, or user always wants reauthentication
Authentication authenticated;
if (!this.runAsManager.supports(getSecureObjectClass())) {
throw new IllegalArgumentException(
"RunAsManager does not support secure object class: "
+ getSecureObjectClass());
}
if (!SecurityContextHolder.getContext().getAuthentication()
.isAuthenticated()
|| alwaysReauthenticate) {
if (!this.accessDecisionManager.supports(getSecureObjectClass())) {
throw new IllegalArgumentException(
"AccessDecisionManager does not support secure object class: "
+ getSecureObjectClass());
}
if ((this.afterInvocationManager != null)
&& !this.afterInvocationManager.supports(getSecureObjectClass())) {
throw new IllegalArgumentException(
"AfterInvocationManager does not support secure object class: "
+ getSecureObjectClass());
}
if (this.validateConfigAttributes) {
Iterator iter = this.obtainObjectDefinitionSource()
.getConfigAttributeDefinitions();
if (iter == null) {
if (logger.isWarnEnabled()) {
logger.warn(
"Could not validate configuration attributes as the MethodDefinitionSource did not return a ConfigAttributeDefinition Iterator");
}
} else {
Set set = new HashSet();
while (iter.hasNext()) {
ConfigAttributeDefinition def = (ConfigAttributeDefinition) iter
.next();
Iterator attributes = def.getConfigAttributes();
while (attributes.hasNext()) {
ConfigAttribute attr = (ConfigAttribute) attributes
.next();
if (!this.runAsManager.supports(attr)
&& !this.accessDecisionManager.supports(attr)
&& ((this.afterInvocationManager == null)
|| !this.afterInvocationManager.supports(attr))) {
set.add(attr);
}
}
}
if (set.size() == 0) {
if (logger.isInfoEnabled()) {
logger.info("Validated configuration attributes");
}
} else {
throw new IllegalArgumentException(
"Unsupported configuration attributes: "
+ set.toString());
}
}
}
}
protected InterceptorStatusToken beforeInvocation(Object object) {
Assert.notNull(object, "Object was null");
Assert.isTrue(getSecureObjectClass()
.isAssignableFrom(object.getClass()),
"Security invocation attempted for object "
+ object.getClass().getName()
+ " but AbstractSecurityInterceptor only configured to support secure objects of type: "
+ getSecureObjectClass());
ConfigAttributeDefinition attr = this.obtainObjectDefinitionSource()
.getAttributes(object);
if ((attr == null) && rejectPublicInvocations) {
throw new IllegalArgumentException(
"No public invocations are allowed via this AbstractSecurityInterceptor. This indicates a configuration error because the AbstractSecurityInterceptor.rejectPublicInvocations property is set to 'true'");
}
if (attr != null) {
if (logger.isDebugEnabled()) {
logger.debug("Secure object: " + object.toString()
+ "; ConfigAttributes: " + attr.toString());
}
// We check for just the property we're interested in (we do
// not call Context.validate() like the ContextInterceptor)
if (SecurityContextHolder.getContext().getAuthentication() == null) {
credentialsNotFound(messages.getMessage(
"AbstractSecurityInterceptor.authenticationNotFound",
"An Authentication object was not found in the SecurityContext"),
object, attr);
}
// Attempt authentication if not already authenticated, or user always wants reauthentication
Authentication authenticated;
if (!SecurityContextHolder.getContext().getAuthentication()
.isAuthenticated()
|| alwaysReauthenticate) {
try {
authenticated = this.authenticationManager.authenticate(SecurityContextHolder.getContext()
.getAuthentication());
} catch (AuthenticationException authenticationException) {
throw authenticationException;
}
// We don't authenticated.setAuthentication(true), because each provider should do that
if (logger.isDebugEnabled()) {
logger.debug("Successfully Authenticated: "
+ authenticated.toString());
}
SecurityContextHolder.getContext()
.setAuthentication(authenticated);
} else {
authenticated = SecurityContextHolder.getContext()
.getAuthentication();
if (logger.isDebugEnabled()) {
logger.debug("Previously Authenticated: "
+ authenticated.toString());
}
}
// Attempt authorization
try {
authenticated = this.authenticationManager.authenticate(SecurityContextHolder.getContext()
.getAuthentication());
} catch (AuthenticationException authenticationException) {
throw authenticationException;
}
this.accessDecisionManager.decide(authenticated, object,
attr);
} catch (AccessDeniedException accessDeniedException) {
AuthorizationFailureEvent event = new AuthorizationFailureEvent(object,
attr, authenticated, accessDeniedException);
this.eventPublisher.publishEvent(event);
// We don't authenticated.setAuthentication(true), because each provider should do that
if (logger.isDebugEnabled()) {
logger.debug("Successfully Authenticated: "
+ authenticated.toString());
throw accessDeniedException;
}
SecurityContextHolder.getContext().setAuthentication(authenticated);
} else {
authenticated = SecurityContextHolder.getContext()
.getAuthentication();
if (logger.isDebugEnabled()) {
logger.debug("Previously Authenticated: "
+ authenticated.toString());
logger.debug("Authorization successful");
}
}
// Attempt authorization
try {
this.accessDecisionManager.decide(authenticated, object, attr);
} catch (AccessDeniedException accessDeniedException) {
AuthorizationFailureEvent event = new AuthorizationFailureEvent(object,
attr, authenticated, accessDeniedException);
AuthorizedEvent event = new AuthorizedEvent(object, attr,
authenticated);
this.eventPublisher.publishEvent(event);
throw accessDeniedException;
}
// Attempt to run as a different user
Authentication runAs = this.runAsManager.buildRunAs(authenticated,
object, attr);
if (logger.isDebugEnabled()) {
logger.debug("Authorization successful");
}
if (runAs == null) {
if (logger.isDebugEnabled()) {
logger.debug(
"RunAsManager did not change Authentication object");
}
AuthorizedEvent event = new AuthorizedEvent(object, attr,
authenticated);
this.eventPublisher.publishEvent(event);
return new InterceptorStatusToken(authenticated, false,
attr, object); // no further work post-invocation
} else {
if (logger.isDebugEnabled()) {
logger.debug("Switching to RunAs Authentication: "
+ runAs.toString());
}
// Attempt to run as a different user
Authentication runAs = this.runAsManager.buildRunAs(authenticated,
object, attr);
SecurityContextHolder.getContext().setAuthentication(runAs);
if (runAs == null) {
if (logger.isDebugEnabled()) {
logger.debug(
"RunAsManager did not change Authentication object");
return new InterceptorStatusToken(authenticated, true,
attr, object); // revert to token.Authenticated post-invocation
}
return new InterceptorStatusToken(authenticated, false, attr,
object); // no further work post-invocation
} else {
if (logger.isDebugEnabled()) {
logger.debug("Switching to RunAs Authentication: "
+ runAs.toString());
logger.debug("Public object - authentication not attempted");
}
SecurityContextHolder.getContext().setAuthentication(runAs);
this.eventPublisher.publishEvent(new PublicInvocationEvent(
object));
return new InterceptorStatusToken(authenticated, true, attr,
object); // revert to token.Authenticated post-invocation
}
} else {
if (logger.isDebugEnabled()) {
logger.debug("Public object - authentication not attempted");
return null; // no further work post-invocation
}
}
this.eventPublisher.publishEvent(new PublicInvocationEvent(object));
/**
* Helper method which generates an exception containing the passed
* reason, and publishes an event to the application context.
*
* <p>
* Always throws an exception.
* </p>
*
* @param reason to be provided in the exception detail
* @param secureObject that was being called
* @param configAttribs that were defined for the secureObject
*/
private void credentialsNotFound(String reason, Object secureObject,
ConfigAttributeDefinition configAttribs) {
AuthenticationCredentialsNotFoundException exception = new AuthenticationCredentialsNotFoundException(reason);
return null; // no further work post-invocation
AuthenticationCredentialsNotFoundEvent event = new AuthenticationCredentialsNotFoundEvent(secureObject,
configAttribs, exception);
this.eventPublisher.publishEvent(event);
throw exception;
}
public AccessDecisionManager getAccessDecisionManager() {
return accessDecisionManager;
}
public AfterInvocationManager getAfterInvocationManager() {
return afterInvocationManager;
}
public AuthenticationManager getAuthenticationManager() {
return this.authenticationManager;
}
public RunAsManager getRunAsManager() {
return runAsManager;
}
/**
* Indicates the type of secure objects the subclass will be presenting
* to the abstract parent for processing. This is used to ensure
* collaborators wired to the <code>AbstractSecurityInterceptor</code>
* all support the indicated secure object class.
*
* @return the type of secure object the subclass provides services for
*/
public abstract Class getSecureObjectClass();
public boolean isAlwaysReauthenticate() {
return alwaysReauthenticate;
}
public boolean isRejectPublicInvocations() {
return rejectPublicInvocations;
}
public boolean isValidateConfigAttributes() {
return validateConfigAttributes;
}
public abstract ObjectDefinitionSource obtainObjectDefinitionSource();
public void setAccessDecisionManager(
AccessDecisionManager accessDecisionManager) {
this.accessDecisionManager = accessDecisionManager;
}
public void setAfterInvocationManager(
AfterInvocationManager afterInvocationManager) {
this.afterInvocationManager = afterInvocationManager;
}
/**
* Indicates whether the <code>AbstractSecurityInterceptor</code>
* should ignore the {@link Authentication#isAuthenticated()}
* property. Defaults to <code>false</code>, meaning by default the
* <code>Authentication.isAuthenticated()</code> property is trusted
* and re-authentication will not occur if the principal has already
* been authenticated.
*
* @param alwaysReauthenticate <code>true</code> to force
* <code>AbstractSecurityInterceptor</code> to disregard the
* value of <code>Authentication.isAuthenticated()</code> and
* always re-authenticate the request (defaults to
* <code>false</code>).
*/
public void setAlwaysReauthenticate(boolean alwaysReauthenticate) {
this.alwaysReauthenticate = alwaysReauthenticate;
}
public void setApplicationEventPublisher(
ApplicationEventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
public void setAuthenticationManager(AuthenticationManager newManager) {
this.authenticationManager = newManager;
}
public void setMessageSource(MessageSource messageSource) {
this.messages = new MessageSourceAccessor(messageSource);
}
/**
* By rejecting public invocations (and setting this property to
* <code>true</code>), essentially you are ensuring that every secure
* object invocation advised by
* <code>AbstractSecurityInterceptor</code> has a configuration
* attribute defined. This is useful to ensure a "fail safe" mode
* where undeclared secure objects will be rejected and configuration
* omissions detected early. An <code>IllegalArgumentException</code>
* will be thrown by the <code>AbstractSecurityInterceptor</code> if
* you set this property to <code>true</code> and an attempt is made
* to invoke a secure object that has no configuration attributes.
*
* @param rejectPublicInvocations set to <code>true</code> to reject
* invocations of secure objects that have no configuration
* attributes (by default it is <code>true</code> which treats
* undeclared secure objects as "public" or unauthorized)
*/
public void setRejectPublicInvocations(boolean rejectPublicInvocations) {
this.rejectPublicInvocations = rejectPublicInvocations;
}
public void setRunAsManager(RunAsManager runAsManager) {
this.runAsManager = runAsManager;
}
public void setValidateConfigAttributes(
boolean validateConfigAttributes) {
this.validateConfigAttributes = validateConfigAttributes;
}
}
/**
* Helper method which generates an exception containing the passed reason,
* and publishes an event to the application context.
*
* <p>
* Always throws an exception.
* </p>
*
* @param reason to be provided in the exception detail
* @param secureObject that was being called
* @param configAttribs that were defined for the secureObject
*/
private void credentialsNotFound(String reason, Object secureObject,
ConfigAttributeDefinition configAttribs) {
AuthenticationCredentialsNotFoundException exception = new AuthenticationCredentialsNotFoundException(reason);
AuthenticationCredentialsNotFoundEvent event = new AuthenticationCredentialsNotFoundEvent(secureObject,
configAttribs, exception);
this.eventPublisher.publishEvent(event);
throw exception;
}
}

View File

@ -0,0 +1,39 @@
AuthByAdapterProvider.incorrectKey=The presented AuthByAdapter implementation does not contain the expected key
BasicAclEntryAfterInvocationProvider.noPermission=Authentication {0} has NO permissions at all to the domain object {1}
BasicAclEntryAfterInvocationProvider.insufficientPermission=Authentication {0} has ACL permissions to the domain object, but not the required ACL permission to the domain object {1}
ConcurrentSessionControllerImpl.exceededAllowed=Maximum sessions of {0} for this principal exceeded
ProviderManager.providerNotFound=No AuthenticationProvider found for {0}
AnonymousAuthenticationProvider.incorrectKey=The presented AnonymousAuthenticationToken does not contain the expected key
CasAuthenticationProvider.incorrectKey=The presented CasAuthenticationToken does not contain the expected key
CasAuthenticationProvider.noServiceTicket=Failed to provide a CAS service ticket to validate
NamedCasProxyDecider.untrusted=Nearest proxy {0} is untrusted
RejectProxyTickets.reject=Proxy tickets are rejected
AbstractSecurityInterceptor.authenticationNotFound=An Authentication object was not found in the SecurityContext
AbstractUserDetailsAuthenticationProvider.onlySupports=Only UsernamePasswordAuthenticationToken is supported
AbstractUserDetailsAuthenticationProvider.locked=User account is locked
AbstractUserDetailsAuthenticationProvider.disabled=User is disabled
AbstractUserDetailsAuthenticationProvider.expired=User account has expired
AbstractUserDetailsAuthenticationProvider.credentialsExpired=User credentials have expired
AbstractUserDetailsAuthenticationProvider.badCredentials=Bad credentials
X509AuthenticationProvider.certificateNull=Certificate is null
DaoX509AuthoritiesPopulator.noMatching=No matching pattern was found in subjectDN: {0}
RememberMeAuthenticationProvider.incorrectKey=The presented RememberMeAuthenticationToken does not contain the expected key
RunAsImplAuthenticationProvider.incorrectKey=The presented RunAsUserToken does not contain the expected key
DigestProcessingFilter.missingMandatory=Missing mandatory digest value; received header {0}
DigestProcessingFilter.missingAuth=Missing mandatory digest value for 'auth' QOP; received header {0}
DigestProcessingFilter.incorrectRealm=Response realm name {0} does not match system realm name of {1}
DigestProcessingFilter.nonceExpired=Nonce has expired/timed out
DigestProcessingFilter.nonceEncoding=Nonce is not encoded in Base64; received nonce {0}
DigestProcessingFilter.nonceNotTwoTokens=Nonce should have yielded two tokens but was {0}
DigestProcessingFilter.nonceNotNumeric=Nonce token should have yielded a numeric first token, but was {0}
DigestProcessingFilter.nonceCompromised=Nonce token compromised {0}
DigestProcessingFilter.usernameNotFound=Username {0} not found
DigestProcessingFilter.incorrectResponse=Incorrect response
SwitchUserProcessingFilter.noCurrentUser=No current user associated with this request
SwitchUserProcessingFilter.noOriginalAuthentication=Could not find original Authentication object
SwitchUserProcessingFilter.usernameNotFound=Username {0} not found
SwitchUserProcessingFilter.locked=User account is locked
SwitchUserProcessingFilter.disabled=User is disabled
SwitchUserProcessingFilter.expired=User account has expired
SwitchUserProcessingFilter.credentialsExpired=User credentials have expired
AbstractAccessDecisionManager.accessDenied=Access is denied

View File

@ -24,9 +24,11 @@ import org.acegisecurity.BadCredentialsException;
import org.acegisecurity.CredentialsExpiredException;
import org.acegisecurity.DisabledException;
import org.acegisecurity.LockedException;
import org.acegisecurity.concurrent.ConcurrentLoginException;
import org.acegisecurity.concurrent.ConcurrentSessionController;
import org.acegisecurity.concurrent.NullConcurrentSessionController;
import org.acegisecurity.event.authentication.AbstractAuthenticationEvent;
import org.acegisecurity.event.authentication.AuthenticationFailureBadCredentialsEvent;
import org.acegisecurity.event.authentication.AuthenticationFailureConcurrentLoginEvent;
@ -38,6 +40,7 @@ import org.acegisecurity.event.authentication.AuthenticationFailureProviderNotFo
import org.acegisecurity.event.authentication.AuthenticationFailureProxyUntrustedEvent;
import org.acegisecurity.event.authentication.AuthenticationFailureServiceExceptionEvent;
import org.acegisecurity.event.authentication.AuthenticationSuccessEvent;
import org.acegisecurity.providers.cas.ProxyUntrustedException;
import org.acegisecurity.providers.dao.UsernameNotFoundException;
@ -48,6 +51,9 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.util.Assert;
@ -85,8 +91,8 @@ import java.util.Properties;
* If a valid <code>Authentication</code> is returned by an
* <code>AuthenticationProvider</code>, the <code>ProviderManager</code> will
* publish an {@link
* org.acegisecurity.event.authentication.AuthenticationSuccessEvent}. If
* an <code>AuthenticationException</code> is detected, the final
* org.acegisecurity.event.authentication.AuthenticationSuccessEvent}. If an
* <code>AuthenticationException</code> is detected, the final
* <code>AuthenticationException</code> thrown will be used to publish an
* appropriate failure event. By default <code>ProviderManager</code> maps
* common exceptions to events, but this can be fine-tuned by providing a new
@ -98,15 +104,11 @@ import java.util.Properties;
* and provides its constructor.
* </p>
*
* @author Ben Alex
* @author Wesley Hall
* @author Ray Krueger
* @version $Id$
*
* @see ConcurrentSessionController
*/
public class ProviderManager extends AbstractAuthenticationManager
implements InitializingBean, ApplicationEventPublisherAware {
implements InitializingBean, ApplicationEventPublisherAware,
MessageSourceAware {
//~ Static fields/initializers =============================================
private static final Log logger = LogFactory.getLog(ProviderManager.class);
@ -116,74 +118,14 @@ public class ProviderManager extends AbstractAuthenticationManager
private ApplicationEventPublisher applicationEventPublisher;
private ConcurrentSessionController sessionController = new NullConcurrentSessionController();
private List providers;
protected MessageSourceAccessor messages;
private Properties exceptionMappings;
//~ Methods ================================================================
public void setApplicationEventPublisher(
ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
/**
* Sets the {@link AuthenticationProvider} objects to be used for
* authentication.
*
* @param newList
*
* @throws IllegalArgumentException DOCUMENT ME!
*/
public void setProviders(List newList) {
checkIfValidList(newList);
Iterator iter = newList.iterator();
while (iter.hasNext()) {
Object currentObject = null;
try {
currentObject = iter.next();
AuthenticationProvider attemptToCast = (AuthenticationProvider) currentObject;
} catch (ClassCastException cce) {
throw new IllegalArgumentException("AuthenticationProvider "
+ currentObject.getClass().getName()
+ " must implement AuthenticationProvider");
}
}
this.providers = newList;
}
public List getProviders() {
return this.providers;
}
/**
* Set the {@link ConcurrentSessionController} to be used for limiting
* user's sessions. The {@link NullConcurrentSessionController} is used
* by default
*
* @param sessionController {@link ConcurrentSessionController}
*/
public void setSessionController(
ConcurrentSessionController sessionController) {
this.sessionController = sessionController;
}
/**
* The configured {@link ConcurrentSessionController} is returned or the
* {@link NullConcurrentSessionController} if a specific one has not been
* set.
*
* @return {@link ConcurrentSessionController} instance
*/
public ConcurrentSessionController getSessionController() {
return sessionController;
}
public void afterPropertiesSet() throws Exception {
checkIfValidList(this.providers);
Assert.notNull(this.messages, "A message source must be set");
if (exceptionMappings == null) {
exceptionMappings = new Properties();
@ -211,6 +153,23 @@ public class ProviderManager extends AbstractAuthenticationManager
}
}
private void checkIfValidList(List listToCheck) {
if ((listToCheck == null) || (listToCheck.size() == 0)) {
throw new IllegalArgumentException(
"A list of AuthenticationManagers is required");
}
}
/**
* Provided so subclasses can add extra exception mappings during startup
* if no exception mappings are injected by the IoC container.
*
* @param exceptionMappings the properties object, which already has
* entries in it
*/
protected void doAddExtraDefaultExceptionMappings(
Properties exceptionMappings) {}
/**
* Attempts to authenticate the passed {@link Authentication} object.
*
@ -244,8 +203,7 @@ public class ProviderManager extends AbstractAuthenticationManager
AuthenticationException lastException = null;
while (iter.hasNext()) {
AuthenticationProvider provider = (AuthenticationProvider) iter
.next();
AuthenticationProvider provider = (AuthenticationProvider) iter.next();
if (provider.supports(toTest)) {
logger.debug("Authentication attempt using "
@ -272,8 +230,10 @@ public class ProviderManager extends AbstractAuthenticationManager
}
if (lastException == null) {
lastException = new ProviderNotFoundException(
"No authentication provider for " + toTest.getName());
lastException = new ProviderNotFoundException(messages.getMessage(
"ProviderManager.providerNotFound",
new Object[] {toTest.getName()},
"No AuthenticationProvider found for {0}"));
}
// Publish the event
@ -309,20 +269,69 @@ public class ProviderManager extends AbstractAuthenticationManager
throw lastException;
}
/**
* Provided so subclasses can add extra exception mappings during startup
* if no exception mappings are injected by the IoC container.
*
* @param exceptionMappings the properties object, which already has
* entries in it
*/
protected void doAddExtraDefaultExceptionMappings(
Properties exceptionMappings) {}
public List getProviders() {
return this.providers;
}
private void checkIfValidList(List listToCheck) {
if ((listToCheck == null) || (listToCheck.size() == 0)) {
throw new IllegalArgumentException(
"A list of AuthenticationManagers is required");
/**
* The configured {@link ConcurrentSessionController} is returned or the
* {@link NullConcurrentSessionController} if a specific one has not been
* set.
*
* @return {@link ConcurrentSessionController} instance
*/
public ConcurrentSessionController getSessionController() {
return sessionController;
}
public void setApplicationEventPublisher(
ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
public void setMessageSource(MessageSource messageSource) {
this.messages = new MessageSourceAccessor(messageSource);
}
/**
* Sets the {@link AuthenticationProvider} objects to be used for
* authentication.
*
* @param newList
*
* @throws IllegalArgumentException DOCUMENT ME!
*/
public void setProviders(List newList) {
checkIfValidList(newList);
Iterator iter = newList.iterator();
while (iter.hasNext()) {
Object currentObject = null;
try {
currentObject = iter.next();
AuthenticationProvider attemptToCast = (AuthenticationProvider) currentObject;
} catch (ClassCastException cce) {
throw new IllegalArgumentException("AuthenticationProvider "
+ currentObject.getClass().getName()
+ " must implement AuthenticationProvider");
}
}
this.providers = newList;
}
/**
* Set the {@link ConcurrentSessionController} to be used for limiting
* user's sessions. The {@link NullConcurrentSessionController} is used
* by default
*
* @param sessionController {@link ConcurrentSessionController}
*/
public void setSessionController(
ConcurrentSessionController sessionController) {
this.sessionController = sessionController;
}
}

View File

@ -18,6 +18,7 @@ package org.acegisecurity.providers.anonymous;
import org.acegisecurity.Authentication;
import org.acegisecurity.AuthenticationException;
import org.acegisecurity.BadCredentialsException;
import org.acegisecurity.providers.AuthenticationProvider;
import org.apache.commons.logging.Log;
@ -25,6 +26,10 @@ 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.util.Assert;
@ -37,32 +42,23 @@ import org.springframework.util.Assert;
* org.acegisecurity.providers.anonymous.AnonymousAuthenticationToken#getKeyHash()}
* must match this class' {@link #getKey()}.
* </p>
*
* @author Ben Alex
* @version $Id$
*/
public class AnonymousAuthenticationProvider implements AuthenticationProvider,
InitializingBean {
InitializingBean, MessageSourceAware {
//~ Static fields/initializers =============================================
private static final Log logger = LogFactory.getLog(AnonymousAuthenticationProvider.class);
//~ Instance fields ========================================================
protected MessageSourceAccessor messages;
private String key;
//~ Methods ================================================================
public void setKey(String key) {
this.key = key;
}
public String getKey() {
return key;
}
public void afterPropertiesSet() throws Exception {
Assert.hasLength(key);
Assert.hasLength(key, "A Key is required");
Assert.notNull(this.messages, "A message source must be set");
}
public Authentication authenticate(Authentication authentication)
@ -73,13 +69,26 @@ public class AnonymousAuthenticationProvider implements AuthenticationProvider,
if (this.key.hashCode() != ((AnonymousAuthenticationToken) authentication)
.getKeyHash()) {
throw new BadCredentialsException(
"The presented AnonymousAuthenticationToken does not contain the expected key");
throw new BadCredentialsException(messages.getMessage(
"AnonymousAuthenticationProvider.incorrectKey",
"The presented AnonymousAuthenticationToken does not contain the expected key"));
}
return authentication;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public void setMessageSource(MessageSource messageSource) {
this.messages = new MessageSourceAccessor(messageSource);
}
public boolean supports(Class authentication) {
return (AnonymousAuthenticationToken.class.isAssignableFrom(authentication));
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -19,14 +19,21 @@ import org.acegisecurity.Authentication;
import org.acegisecurity.AuthenticationException;
import org.acegisecurity.BadCredentialsException;
import org.acegisecurity.UserDetails;
import org.acegisecurity.providers.AuthenticationProvider;
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.acegisecurity.ui.cas.CasProcessingFilter;
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.util.Assert;
@ -42,12 +49,9 @@ import org.springframework.util.Assert;
* CasProcessingFilter#CAS_STATELESS_IDENTIFIER}. It can also validate a
* previously created {@link CasAuthenticationToken}.
* </p>
*
* @author Ben Alex
* @version $Id$
*/
public class CasAuthenticationProvider implements AuthenticationProvider,
InitializingBean {
InitializingBean, MessageSourceAware {
//~ Static fields/initializers =============================================
private static final Log logger = LogFactory.getLog(CasAuthenticationProvider.class);
@ -56,60 +60,23 @@ public class CasAuthenticationProvider implements AuthenticationProvider,
private CasAuthoritiesPopulator casAuthoritiesPopulator;
private CasProxyDecider casProxyDecider;
protected MessageSourceAccessor messages;
private StatelessTicketCache statelessTicketCache;
private String key;
private TicketValidator ticketValidator;
//~ Methods ================================================================
public void setCasAuthoritiesPopulator(
CasAuthoritiesPopulator casAuthoritiesPopulator) {
this.casAuthoritiesPopulator = casAuthoritiesPopulator;
}
public CasAuthoritiesPopulator getCasAuthoritiesPopulator() {
return casAuthoritiesPopulator;
}
public void setCasProxyDecider(CasProxyDecider casProxyDecider) {
this.casProxyDecider = casProxyDecider;
}
public CasProxyDecider getCasProxyDecider() {
return casProxyDecider;
}
public void setKey(String key) {
this.key = key;
}
public String getKey() {
return key;
}
public void setStatelessTicketCache(
StatelessTicketCache statelessTicketCache) {
this.statelessTicketCache = statelessTicketCache;
}
public StatelessTicketCache getStatelessTicketCache() {
return statelessTicketCache;
}
public void setTicketValidator(TicketValidator ticketValidator) {
this.ticketValidator = ticketValidator;
}
public TicketValidator getTicketValidator() {
return ticketValidator;
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(this.casAuthoritiesPopulator, "A casAuthoritiesPopulator must be set");
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");
Assert.notNull(this.statelessTicketCache, "A statelessTicketCache must be set");
Assert.notNull(key, "A Key is required so CasAuthenticationProvider can identify tokens it previously authenticated");
Assert.notNull(this.statelessTicketCache,
"A statelessTicketCache must be set");
Assert.notNull(key,
"A Key is required so CasAuthenticationProvider can identify tokens it previously authenticated");
Assert.notNull(this.messages, "A message source must be set");
}
public Authentication authenticate(Authentication authentication)
@ -133,16 +100,18 @@ public class CasAuthenticationProvider implements AuthenticationProvider,
.getKeyHash()) {
return authentication;
} else {
throw new BadCredentialsException(
"The presented CasAuthenticationToken does not contain the expected key");
throw new BadCredentialsException(messages.getMessage(
"CasAuthenticationProvider.incorrectKey",
"The presented CasAuthenticationToken does not contain the expected key"));
}
}
// Ensure credentials are presented
if ((authentication.getCredentials() == null)
|| "".equals(authentication.getCredentials())) {
throw new BadCredentialsException(
"Failed to provide a CAS service ticket to validate");
throw new BadCredentialsException(messages.getMessage(
"CasAuthenticationProvider.noServiceTicket",
"Failed to provide a CAS service ticket to validate"));
}
boolean stateless = false;
@ -173,17 +142,6 @@ public class CasAuthenticationProvider implements AuthenticationProvider,
return result;
}
public boolean supports(Class authentication) {
if (UsernamePasswordAuthenticationToken.class.isAssignableFrom(
authentication)) {
return true;
} else if (CasAuthenticationToken.class.isAssignableFrom(authentication)) {
return true;
} else {
return false;
}
}
private CasAuthenticationToken authenticateNow(
Authentication authentication) throws AuthenticationException {
// Validate
@ -203,4 +161,61 @@ public class CasAuthenticationProvider implements AuthenticationProvider,
userDetails, response.getProxyList(),
response.getProxyGrantingTicketIou());
}
public CasAuthoritiesPopulator getCasAuthoritiesPopulator() {
return casAuthoritiesPopulator;
}
public CasProxyDecider getCasProxyDecider() {
return casProxyDecider;
}
public String getKey() {
return key;
}
public StatelessTicketCache getStatelessTicketCache() {
return statelessTicketCache;
}
public TicketValidator getTicketValidator() {
return ticketValidator;
}
public void setCasAuthoritiesPopulator(
CasAuthoritiesPopulator casAuthoritiesPopulator) {
this.casAuthoritiesPopulator = casAuthoritiesPopulator;
}
public void setCasProxyDecider(CasProxyDecider casProxyDecider) {
this.casProxyDecider = casProxyDecider;
}
public void setKey(String key) {
this.key = key;
}
public void setMessageSource(MessageSource messageSource) {
this.messages = new MessageSourceAccessor(messageSource);
}
public void setStatelessTicketCache(
StatelessTicketCache statelessTicketCache) {
this.statelessTicketCache = statelessTicketCache;
}
public void setTicketValidator(TicketValidator ticketValidator) {
this.ticketValidator = ticketValidator;
}
public boolean supports(Class authentication) {
if (UsernamePasswordAuthenticationToken.class.isAssignableFrom(
authentication)) {
return true;
} else if (CasAuthenticationToken.class.isAssignableFrom(authentication)) {
return true;
} else {
return false;
}
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -22,6 +22,11 @@ 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.util.Assert;
import java.util.List;
@ -35,11 +40,9 @@ import java.util.List;
* Also accepts the request if there was no proxy (ie the user directly
* authenticated against this service).
* </p>
*
* @author Ben Alex
* @version $Id$
*/
public class NamedCasProxyDecider implements CasProxyDecider, InitializingBean {
public class NamedCasProxyDecider implements CasProxyDecider, InitializingBean,
MessageSourceAware {
//~ Static fields/initializers =============================================
private static final Log logger = LogFactory.getLog(NamedCasProxyDecider.class);
@ -47,19 +50,13 @@ public class NamedCasProxyDecider implements CasProxyDecider, InitializingBean {
//~ Instance fields ========================================================
private List validProxies;
protected MessageSourceAccessor messages;
//~ Methods ================================================================
public void setValidProxies(List validProxies) {
this.validProxies = validProxies;
}
public List getValidProxies() {
return validProxies;
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(this.validProxies, "A validProxies list must be set");
Assert.notNull(this.messages, "A message source must be set");
}
public void confirmProxyListTrusted(List proxyList)
@ -76,8 +73,22 @@ public class NamedCasProxyDecider implements CasProxyDecider, InitializingBean {
}
if (!validProxies.contains(proxyList.get(0))) {
throw new ProxyUntrustedException("Nearest proxy '"
+ proxyList.get(0) + "' is untrusted");
throw new ProxyUntrustedException(messages.getMessage(
"NamedCasProxyDecider.untrusted",
new Object[] {proxyList.get(0)},
"Nearest proxy {0} is untrusted"));
}
}
public List getValidProxies() {
return validProxies;
}
public void setMessageSource(MessageSource messageSource) {
this.messages = new MessageSourceAccessor(messageSource);
}
public void setValidProxies(List validProxies) {
this.validProxies = validProxies;
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -20,6 +20,13 @@ import org.acegisecurity.providers.cas.ProxyUntrustedException;
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.util.Assert;
import java.util.List;
@ -32,17 +39,23 @@ import java.util.List;
* This class should be used if only service tickets wish to be accepted (ie no
* proxy tickets at all).
* </p>
*
* @author Ben Alex
* @version $Id$
*/
public class RejectProxyTickets implements CasProxyDecider {
public class RejectProxyTickets implements CasProxyDecider, MessageSourceAware,
InitializingBean {
//~ Static fields/initializers =============================================
private static final Log logger = LogFactory.getLog(RejectProxyTickets.class);
//~ Instance fields ========================================================
protected MessageSourceAccessor messages;
//~ Methods ================================================================
public void afterPropertiesSet() throws Exception {
Assert.notNull(this.messages, "A message source must be set");
}
public void confirmProxyListTrusted(List proxyList)
throws ProxyUntrustedException {
Assert.notNull(proxyList, "proxyList cannot be null");
@ -54,9 +67,14 @@ public class RejectProxyTickets implements CasProxyDecider {
if (logger.isDebugEnabled()) {
logger.debug("Proxies are unacceptable; proxy list provided: "
+ proxyList.toString());
+ proxyList.toString());
}
throw new ProxyUntrustedException("Proxy tickets are rejected");
throw new ProxyUntrustedException(messages.getMessage(
"RejectProxyTickets.reject", "Proxy tickets are rejected"));
}
public void setMessageSource(MessageSource messageSource) {
this.messages = new MessageSourceAccessor(messageSource);
}
}

View File

@ -22,12 +22,17 @@ import org.acegisecurity.CredentialsExpiredException;
import org.acegisecurity.DisabledException;
import org.acegisecurity.LockedException;
import org.acegisecurity.UserDetails;
import org.acegisecurity.providers.AuthenticationProvider;
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.acegisecurity.providers.dao.cache.NullUserCache;
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.util.Assert;
@ -62,110 +67,17 @@ import org.springframework.util.Assert;
* incorrect password, the {@link AuthenticationDao} will be queried to
* confirm the most up-to-date password was used for comparison.
* </p>
*
* @author Ben Alex
* @version $Id$
*/
public abstract class AbstractUserDetailsAuthenticationProvider
implements AuthenticationProvider, InitializingBean {
implements AuthenticationProvider, InitializingBean, MessageSourceAware {
//~ Instance fields ========================================================
protected MessageSourceAccessor messages;
private UserCache userCache = new NullUserCache();
private boolean forcePrincipalAsString = false;
//~ Methods ================================================================
public void setForcePrincipalAsString(boolean forcePrincipalAsString) {
this.forcePrincipalAsString = forcePrincipalAsString;
}
public boolean isForcePrincipalAsString() {
return forcePrincipalAsString;
}
public void setUserCache(UserCache userCache) {
this.userCache = userCache;
}
public UserCache getUserCache() {
return userCache;
}
public final void afterPropertiesSet() throws Exception {
Assert.notNull(this.userCache, "A user cache must be set");
doAfterPropertiesSet();
}
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class,
authentication,
"Only UsernamePasswordAuthenticationToken is supported");
// Determine username
String username = (authentication.getPrincipal() == null)
? "NONE_PROVIDED" : authentication.getName();
boolean cacheWasUsed = true;
UserDetails user = this.userCache.getUserFromCache(username);
if (user == null) {
cacheWasUsed = false;
user = retrieveUser(username,
(UsernamePasswordAuthenticationToken) authentication);
Assert.notNull(user,
"retrieveUser returned null - a violation of the interface contract");
}
if (!user.isAccountNonLocked()) {
throw new LockedException("User account is locked");
}
if (!user.isEnabled()) {
throw new DisabledException("User is disabled");
}
if (!user.isAccountNonExpired()) {
throw new AccountExpiredException("User account has expired");
}
// This check must come here, as we don't want to tell users
// about account status unless they presented the correct credentials
try {
additionalAuthenticationChecks(user,
(UsernamePasswordAuthenticationToken) authentication);
} catch (AuthenticationException exception) {
// There was a problem, so try again after checking we're using latest data
cacheWasUsed = false;
user = retrieveUser(username,
(UsernamePasswordAuthenticationToken) authentication);
additionalAuthenticationChecks(user,
(UsernamePasswordAuthenticationToken) authentication);
}
if (!user.isCredentialsNonExpired()) {
throw new CredentialsExpiredException(
"User credentials have expired");
}
if (!cacheWasUsed) {
this.userCache.putUserInCache(user);
}
Object principalToReturn = user;
if (forcePrincipalAsString) {
principalToReturn = user.getUsername();
}
return createSuccessAuthentication(principalToReturn, authentication,
user);
}
public boolean supports(Class authentication) {
return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
}
/**
* Allows subclasses to perform any additional checks of a returned (or
* cached) <code>UserDetails</code> for a given authentication request.
@ -190,8 +102,132 @@ public abstract class AbstractUserDetailsAuthenticationProvider
UsernamePasswordAuthenticationToken authentication)
throws AuthenticationException;
public final void afterPropertiesSet() throws Exception {
Assert.notNull(this.userCache, "A user cache must be set");
Assert.notNull(this.messages, "A message source must be set");
doAfterPropertiesSet();
}
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class,
authentication,
messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.onlySupports",
"Only UsernamePasswordAuthenticationToken is supported"));
// Determine username
String username = (authentication.getPrincipal() == null)
? "NONE_PROVIDED" : authentication.getName();
boolean cacheWasUsed = true;
UserDetails user = this.userCache.getUserFromCache(username);
if (user == null) {
cacheWasUsed = false;
user = retrieveUser(username,
(UsernamePasswordAuthenticationToken) authentication);
Assert.notNull(user,
"retrieveUser returned null - a violation of the interface contract");
}
if (!user.isAccountNonLocked()) {
throw new LockedException(messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.locked",
"User account is locked"));
}
if (!user.isEnabled()) {
throw new DisabledException(messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.disabled",
"User is disabled"));
}
if (!user.isAccountNonExpired()) {
throw new AccountExpiredException(messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.expired",
"User account has expired"));
}
// This check must come here, as we don't want to tell users
// about account status unless they presented the correct credentials
try {
additionalAuthenticationChecks(user,
(UsernamePasswordAuthenticationToken) authentication);
} catch (AuthenticationException exception) {
// There was a problem, so try again after checking we're using latest data
cacheWasUsed = false;
user = retrieveUser(username,
(UsernamePasswordAuthenticationToken) authentication);
additionalAuthenticationChecks(user,
(UsernamePasswordAuthenticationToken) authentication);
}
if (!user.isCredentialsNonExpired()) {
throw new CredentialsExpiredException(messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.credentialsExpired",
"User credentials have expired"));
}
if (!cacheWasUsed) {
this.userCache.putUserInCache(user);
}
Object principalToReturn = user;
if (forcePrincipalAsString) {
principalToReturn = user.getUsername();
}
return createSuccessAuthentication(principalToReturn, authentication,
user);
}
/**
* Creates a successful {@link Authentication} object.
*
* <P>
* Protected so subclasses can override.
* </p>
*
* <P>
* Subclasses will usually store the original credentials the user supplied
* (not salted or encoded passwords) in the returned
* <code>Authentication</code> object.
* </p>
*
* @param principal that should be the principal in the returned object
* (defined by the {@link #isForcePrincipalAsString()} method)
* @param authentication that was presented to the
* <code>DaoAuthenticationProvider</code> for validation
* @param user that was loaded by the <code>AuthenticationDao</code>
*
* @return the successful authentication token
*/
protected Authentication createSuccessAuthentication(Object principal,
Authentication authentication, UserDetails user) {
// Ensure we return the original credentials the user supplied,
// so subsequent attempts are successful even with encoded passwords.
// Also ensure we return the original getDetails(), so that future
// authentication events after cache expiry contain the details
UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(principal,
authentication.getCredentials(), user.getAuthorities());
result.setDetails((authentication.getDetails() != null)
? authentication.getDetails() : null);
return result;
}
protected void doAfterPropertiesSet() throws Exception {}
public UserCache getUserCache() {
return userCache;
}
public boolean isForcePrincipalAsString() {
return forcePrincipalAsString;
}
/**
* Allows subclasses to actually retrieve the <code>UserDetails</code> from
* an implementation-specific location, with the option of throwing an
@ -243,38 +279,19 @@ public abstract class AbstractUserDetailsAuthenticationProvider
UsernamePasswordAuthenticationToken authentication)
throws AuthenticationException;
/**
* Creates a successful {@link Authentication} object.
*
* <P>
* Protected so subclasses can override.
* </p>
*
* <P>
* Subclasses will usually store the original credentials the user supplied
* (not salted or encoded passwords) in the returned
* <code>Authentication</code> object.
* </p>
*
* @param principal that should be the principal in the returned object
* (defined by the {@link #isForcePrincipalAsString()} method)
* @param authentication that was presented to the
* <code>DaoAuthenticationProvider</code> for validation
* @param user that was loaded by the <code>AuthenticationDao</code>
*
* @return the successful authentication token
*/
protected Authentication createSuccessAuthentication(Object principal,
Authentication authentication, UserDetails user) {
// Ensure we return the original credentials the user supplied,
// so subsequent attempts are successful even with encoded passwords.
// Also ensure we return the original getDetails(), so that future
// authentication events after cache expiry contain the details
UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(principal,
authentication.getCredentials(), user.getAuthorities());
result.setDetails((authentication.getDetails() != null)
? authentication.getDetails() : null);
public void setForcePrincipalAsString(boolean forcePrincipalAsString) {
this.forcePrincipalAsString = forcePrincipalAsString;
}
return result;
public void setMessageSource(MessageSource messageSource) {
this.messages = new MessageSourceAccessor(messageSource);
}
public void setUserCache(UserCache userCache) {
this.userCache = userCache;
}
public boolean supports(Class authentication) {
return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
}
}

View File

@ -19,6 +19,7 @@ import org.acegisecurity.AuthenticationException;
import org.acegisecurity.AuthenticationServiceException;
import org.acegisecurity.BadCredentialsException;
import org.acegisecurity.UserDetails;
import org.acegisecurity.providers.AuthenticationProvider;
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.acegisecurity.providers.encoding.PasswordEncoder;
@ -32,9 +33,6 @@ import org.springframework.util.Assert;
/**
* An {@link AuthenticationProvider} implementation that retrieves user details
* from an {@link AuthenticationDao}.
*
* @author Ben Alex
* @version $Id$
*/
public class DaoAuthenticationProvider
extends AbstractUserDetailsAuthenticationProvider {
@ -47,68 +45,6 @@ public class DaoAuthenticationProvider
//~ Methods ================================================================
public void setAuthenticationDao(AuthenticationDao authenticationDao) {
this.authenticationDao = authenticationDao;
}
public AuthenticationDao getAuthenticationDao() {
return authenticationDao;
}
/**
* By default the <code>DaoAuthenticationProvider</code> throws a
* <code>BadCredentialsException</code> if a username is not found or the
* password is incorrect. Setting this property to <code>false</code> will
* cause <code>UsernameNotFoundException</code>s to be thrown instead for
* the former. Note this is considered less secure than throwing
* <code>BadCredentialsException</code> for both exceptions.
*
* @param hideUserNotFoundExceptions set to <code>false</code> if you wish
* <code>UsernameNotFoundException</code>s to be thrown instead of
* the non-specific <code>BadCredentialsException</code> (defaults
* to <code>true</code>)
*/
public void setHideUserNotFoundExceptions(
boolean hideUserNotFoundExceptions) {
this.hideUserNotFoundExceptions = hideUserNotFoundExceptions;
}
public boolean isHideUserNotFoundExceptions() {
return hideUserNotFoundExceptions;
}
/**
* Sets the PasswordEncoder instance to be used to encode and validate
* passwords. If not set, {@link PlaintextPasswordEncoder} will be used by
* default.
*
* @param passwordEncoder The passwordEncoder to use
*/
public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
this.passwordEncoder = passwordEncoder;
}
public PasswordEncoder getPasswordEncoder() {
return passwordEncoder;
}
/**
* The source of salts to use when decoding passwords. <code>null</code>
* is a valid value, meaning the <code>DaoAuthenticationProvider</code>
* will present <code>null</code> to the relevant
* <code>PasswordEncoder</code>.
*
* @param saltSource to use when attempting to decode passwords via the
* <code>PasswordEncoder</code>
*/
public void setSaltSource(SaltSource saltSource) {
this.saltSource = saltSource;
}
public SaltSource getSaltSource() {
return saltSource;
}
protected void additionalAuthenticationChecks(UserDetails userDetails,
UsernamePasswordAuthenticationToken authentication)
throws AuthenticationException {
@ -120,7 +56,9 @@ public class DaoAuthenticationProvider
if (!passwordEncoder.isPasswordValid(userDetails.getPassword(),
authentication.getCredentials().toString(), salt)) {
throw new BadCredentialsException("Bad credentials", userDetails);
throw new BadCredentialsException(messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.badCredentials",
"Bad credentials"), userDetails);
}
}
@ -129,6 +67,22 @@ public class DaoAuthenticationProvider
"An Authentication DAO must be set");
}
public AuthenticationDao getAuthenticationDao() {
return authenticationDao;
}
public PasswordEncoder getPasswordEncoder() {
return passwordEncoder;
}
public SaltSource getSaltSource() {
return saltSource;
}
public boolean isHideUserNotFoundExceptions() {
return hideUserNotFoundExceptions;
}
protected final UserDetails retrieveUser(String username,
UsernamePasswordAuthenticationToken authentication)
throws AuthenticationException {
@ -138,20 +92,70 @@ public class DaoAuthenticationProvider
loadedUser = this.authenticationDao.loadUserByUsername(username);
} catch (UsernameNotFoundException notFound) {
if (hideUserNotFoundExceptions) {
throw new BadCredentialsException("Bad credentials presented");
throw new BadCredentialsException(messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.badCredentials",
"Bad credentials"));
} else {
throw notFound;
}
} catch (DataAccessException repositoryProblem) {
throw new AuthenticationServiceException(repositoryProblem
.getMessage(), repositoryProblem);
.getMessage(), repositoryProblem);
}
if (loadedUser == null) {
throw new AuthenticationServiceException(
"AuthenticationDao returned null, which is an interface contract violation");
}
return loadedUser;
}
if (loadedUser == null) {
throw new AuthenticationServiceException(
"AuthenticationDao returned null, which is an interface contract violation");
public void setAuthenticationDao(AuthenticationDao authenticationDao) {
this.authenticationDao = authenticationDao;
}
return loadedUser;
/**
* By default the <code>DaoAuthenticationProvider</code> throws a
* <code>BadCredentialsException</code> if a username is not found or
* the password is incorrect. Setting this property to
* <code>false</code> will cause
* <code>UsernameNotFoundException</code>s to be thrown instead for
* the former. Note this is considered less secure than throwing
* <code>BadCredentialsException</code> for both exceptions.
*
* @param hideUserNotFoundExceptions set to <code>false</code> if you
* wish <code>UsernameNotFoundException</code>s to be thrown
* instead of the non-specific
* <code>BadCredentialsException</code> (defaults to
* <code>true</code>)
*/
public void setHideUserNotFoundExceptions(
boolean hideUserNotFoundExceptions) {
this.hideUserNotFoundExceptions = hideUserNotFoundExceptions;
}
/**
* Sets the PasswordEncoder instance to be used to encode and validate
* passwords. If not set, {@link PlaintextPasswordEncoder} will be
* used by default.
*
* @param passwordEncoder The passwordEncoder to use
*/
public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
this.passwordEncoder = passwordEncoder;
}
/**
* The source of salts to use when decoding passwords.
* <code>null</code> is a valid value, meaning the
* <code>DaoAuthenticationProvider</code> will present
* <code>null</code> to the relevant <code>PasswordEncoder</code>.
*
* @param saltSource to use when attempting to decode passwords via the
* <code>PasswordEncoder</code>
*/
public void setSaltSource(SaltSource saltSource) {
this.saltSource = saltSource;
}
}
}

View File

@ -18,6 +18,7 @@ package org.acegisecurity.providers.rememberme;
import org.acegisecurity.Authentication;
import org.acegisecurity.AuthenticationException;
import org.acegisecurity.BadCredentialsException;
import org.acegisecurity.providers.AuthenticationProvider;
import org.apache.commons.logging.Log;
@ -25,6 +26,10 @@ 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.util.Assert;
@ -37,32 +42,23 @@ import org.springframework.util.Assert;
* org.acegisecurity.providers.rememberme.RememberMeAuthenticationToken#getKeyHash()}
* must match this class' {@link #getKey()}.
* </p>
*
* @author Ben Alex
* @version $Id$
*/
public class RememberMeAuthenticationProvider implements AuthenticationProvider,
InitializingBean {
InitializingBean, MessageSourceAware {
//~ Static fields/initializers =============================================
private static final Log logger = LogFactory.getLog(RememberMeAuthenticationProvider.class);
//~ Instance fields ========================================================
protected MessageSourceAccessor messages;
private String key;
//~ Methods ================================================================
public void setKey(String key) {
this.key = key;
}
public String getKey() {
return key;
}
public void afterPropertiesSet() throws Exception {
Assert.hasLength(key);
Assert.notNull(this.messages, "A message source must be set");
}
public Authentication authenticate(Authentication authentication)
@ -73,13 +69,26 @@ public class RememberMeAuthenticationProvider implements AuthenticationProvider,
if (this.key.hashCode() != ((RememberMeAuthenticationToken) authentication)
.getKeyHash()) {
throw new BadCredentialsException(
"The presented RememberMeAuthenticationToken does not contain the expected key");
throw new BadCredentialsException(messages.getMessage(
"RememberMeAuthenticationProvider.incorrectKey",
"The presented RememberMeAuthenticationToken does not contain the expected key"));
}
return authentication;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public void setMessageSource(MessageSource messageSource) {
this.messages = new MessageSourceAccessor(messageSource);
}
public boolean supports(Class authentication) {
return (RememberMeAuthenticationToken.class.isAssignableFrom(authentication));
}

View File

@ -15,71 +15,81 @@
package org.acegisecurity.providers.x509;
import org.acegisecurity.providers.AuthenticationProvider;
import org.acegisecurity.providers.x509.cache.NullX509UserCache;
import org.acegisecurity.Authentication;
import org.acegisecurity.AuthenticationException;
import org.acegisecurity.UserDetails;
import org.acegisecurity.BadCredentialsException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import org.acegisecurity.UserDetails;
import org.acegisecurity.providers.AuthenticationProvider;
import org.acegisecurity.providers.x509.cache.NullX509UserCache;
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.util.Assert;
import java.security.cert.X509Certificate;
/**
* Processes an X.509 authentication request.
*
* <p>
* The request will typically originate from
* {@link org.acegisecurity.ui.x509.X509ProcessingFilter}).
* The request will typically originate from {@link
* org.acegisecurity.ui.x509.X509ProcessingFilter}).
* </p>
*
* @author Luke Taylor
* @version $Id$
*/
public class X509AuthenticationProvider implements AuthenticationProvider,
InitializingBean {
InitializingBean, MessageSourceAware {
//~ Static fields/initializers =============================================
private static final Log logger = LogFactory.getLog(X509AuthenticationProvider.class);
//~ Instance fields ========================================================
protected MessageSourceAccessor messages;
private X509AuthoritiesPopulator x509AuthoritiesPopulator;
private X509UserCache userCache = new NullX509UserCache();
//~ Methods ================================================================
public void setX509AuthoritiesPopulator(X509AuthoritiesPopulator x509AuthoritiesPopulator) {
this.x509AuthoritiesPopulator = x509AuthoritiesPopulator;
}
public void setX509UserCache(X509UserCache cache) {
this.userCache = cache;
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(userCache, "An x509UserCache must be set");
Assert.notNull(x509AuthoritiesPopulator, "An X509AuthoritiesPopulator must be set");
Assert.notNull(x509AuthoritiesPopulator,
"An X509AuthoritiesPopulator must be set");
Assert.notNull(this.messages, "A message source must be set");
}
/**
* If the supplied authentication token contains a certificate then this will be passed
* to the configured {@link X509AuthoritiesPopulator}
* to obtain the user details and authorities for the user identified by the certificate.
* If the supplied authentication token contains a certificate then this
* will be passed to the configured {@link X509AuthoritiesPopulator} to
* obtain the user details and authorities for the user identified by the
* certificate.
*
* <p>
* If no certificate is present (for example, if the filter is applied to an HttpRequest for which
* client authentication hasn't been configured in the container) then a BadCredentialsException will be raised.
* If no certificate is present (for example, if the filter is applied to
* an HttpRequest for which client authentication hasn't been configured
* in the container) then a BadCredentialsException will be raised.
* </p>
*
* @param authentication the authentication request.
* @return an X509AuthenticationToken containing the authorities of the principal represented by the
* certificate.
* @throws AuthenticationException if the {@link X509AuthoritiesPopulator} rejects the certficate.
* @throws BadCredentialsException if no certificate was presented in the authentication request.
*
* @return an X509AuthenticationToken containing the authorities of the
* principal represented by the certificate.
*
* @throws AuthenticationException if the {@link X509AuthoritiesPopulator}
* rejects the certficate.
* @throws BadCredentialsException if no certificate was presented in the
* authentication request.
*/
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
if (!supports(authentication.getClass())) {
return null;
}
@ -88,25 +98,42 @@ public class X509AuthenticationProvider implements AuthenticationProvider,
logger.debug("X509 authentication request: " + authentication);
}
X509Certificate clientCertificate = (X509Certificate)authentication.getCredentials();
X509Certificate clientCertificate = (X509Certificate) authentication
.getCredentials();
if(clientCertificate == null) {
throw new BadCredentialsException("Certificate is null.");
if (clientCertificate == null) {
throw new BadCredentialsException(messages.getMessage(
"X509AuthenticationProvider.certificateNull",
"Certificate is null"));
}
UserDetails user = userCache.getUserFromCache(clientCertificate);
if (user == null) {
logger.debug("Authenticating with certificate "
+ clientCertificate);
user = x509AuthoritiesPopulator.getUserDetails(clientCertificate);
userCache.putUserInCache(clientCertificate, user);
}
return new X509AuthenticationToken(user, clientCertificate,
user.getAuthorities());
}
UserDetails user = userCache.getUserFromCache(clientCertificate);
if(user == null) {
logger.debug("Authenticating with certificate " + clientCertificate);
user = x509AuthoritiesPopulator.getUserDetails(clientCertificate);
userCache.putUserInCache(clientCertificate, user);
public void setMessageSource(MessageSource messageSource) {
this.messages = new MessageSourceAccessor(messageSource);
}
return new X509AuthenticationToken(user, clientCertificate, user.getAuthorities());
}
public void setX509AuthoritiesPopulator(
X509AuthoritiesPopulator x509AuthoritiesPopulator) {
this.x509AuthoritiesPopulator = x509AuthoritiesPopulator;
}
public boolean supports(Class authentication) {
return X509AuthenticationToken.class.isAssignableFrom(authentication);
}
public void setX509UserCache(X509UserCache cache) {
this.userCache = cache;
}
}
public boolean supports(Class authentication) {
return X509AuthenticationToken.class.isAssignableFrom(authentication);
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,29 +16,34 @@
package org.acegisecurity.providers.x509.populator;
import org.acegisecurity.AuthenticationException;
import org.acegisecurity.UserDetails;
import org.acegisecurity.BadCredentialsException;
import org.acegisecurity.UserDetails;
import org.acegisecurity.providers.dao.AuthenticationDao;
import org.acegisecurity.providers.x509.X509AuthoritiesPopulator;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.oro.text.regex.*;
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.util.Assert;
import java.security.cert.X509Certificate;
/**
* Populates the X509 authorities via an {@link org.acegisecurity.providers.dao.AuthenticationDao}.
*
* @author Luke Taylor
* @version $Id$
* Populates the X509 authorities via an {@link
* org.acegisecurity.providers.dao.AuthenticationDao}.
*/
public class DaoX509AuthoritiesPopulator implements X509AuthoritiesPopulator,
InitializingBean {
InitializingBean, MessageSourceAware {
//~ Static fields/initializers =============================================
private static final Log logger = LogFactory.getLog(DaoX509AuthoritiesPopulator.class);
@ -46,18 +51,64 @@ public class DaoX509AuthoritiesPopulator implements X509AuthoritiesPopulator,
//~ Instance fields ========================================================
private AuthenticationDao authenticationDao;
private String subjectDNRegex = "CN=(.*?),";
protected MessageSourceAccessor messages;
private Pattern subjectDNPattern;
private String subjectDNRegex = "CN=(.*?),";
//~ Methods ================================================================
public void afterPropertiesSet() throws Exception {
Assert.notNull(authenticationDao, "An authenticationDao must be set");
Assert.notNull(this.messages, "A message source must be set");
Perl5Compiler compiler = new Perl5Compiler();
try {
subjectDNPattern = compiler.compile(subjectDNRegex,
Perl5Compiler.READ_ONLY_MASK
| Perl5Compiler.CASE_INSENSITIVE_MASK);
} catch (MalformedPatternException mpe) {
throw new IllegalArgumentException("Malformed regular expression: "
+ subjectDNRegex);
}
}
public UserDetails getUserDetails(X509Certificate clientCert)
throws AuthenticationException {
String subjectDN = clientCert.getSubjectDN().getName();
PatternMatcher matcher = new Perl5Matcher();
if (!matcher.contains(subjectDN, subjectDNPattern)) {
throw new BadCredentialsException(messages.getMessage(
"DaoX509AuthoritiesPopulator.noMatching",
new Object[] {subjectDN},
"No matching pattern was found in subjectDN: {0}"));
}
MatchResult match = matcher.getMatch();
if (match.groups() != 2) { // 2 = 1 + the entire match
throw new IllegalArgumentException(
"Regular expression must contain a single group ");
}
String userName = match.group(1);
return this.authenticationDao.loadUserByUsername(userName);
}
public void setAuthenticationDao(AuthenticationDao authenticationDao) {
this.authenticationDao = authenticationDao;
}
public void setMessageSource(MessageSource messageSource) {
this.messages = new MessageSourceAccessor(messageSource);
}
/**
* Sets the regular expression which will by used to extract the user name
* from the certificate's Subject DN.
*
* <p>
* It should contain a single group; for example the default expression
* "CN=(.*?)," matches the common name field. So "CN=Jimi Hendrix, OU=..."
@ -73,36 +124,4 @@ public class DaoX509AuthoritiesPopulator implements X509AuthoritiesPopulator,
public void setSubjectDNRegex(String subjectDNRegex) {
this.subjectDNRegex = subjectDNRegex;
}
public UserDetails getUserDetails(X509Certificate clientCert)
throws AuthenticationException {
String subjectDN = clientCert.getSubjectDN().getName();
PatternMatcher matcher = new Perl5Matcher();
if(!matcher.contains(subjectDN , subjectDNPattern)) {
throw new BadCredentialsException("No matching pattern was found in subjectDN: " + subjectDN);
}
MatchResult match = matcher.getMatch();
if(match.groups() != 2) { // 2 = 1 + the entire match
throw new IllegalArgumentException("Regular expression must contain a single group ");
}
String userName = match.group(1);
return this.authenticationDao.loadUserByUsername(userName);
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(authenticationDao, "An authenticationDao must be set");
Perl5Compiler compiler = new Perl5Compiler();
try {
subjectDNPattern = compiler.compile(subjectDNRegex,
Perl5Compiler.READ_ONLY_MASK | Perl5Compiler.CASE_INSENSITIVE_MASK);
} catch (MalformedPatternException mpe) {
throw new IllegalArgumentException("Malformed regular expression: " + subjectDNRegex);
}
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,9 +18,15 @@ package org.acegisecurity.runas;
import org.acegisecurity.Authentication;
import org.acegisecurity.AuthenticationException;
import org.acegisecurity.BadCredentialsException;
import org.acegisecurity.providers.AuthenticationProvider;
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.util.Assert;
@ -38,28 +44,19 @@ import org.springframework.util.Assert;
* <P>
* If the key does not match, a <code>BadCredentialsException</code> is thrown.
* </p>
*
* @author Ben Alex
* @version $Id$
*/
public class RunAsImplAuthenticationProvider implements InitializingBean,
AuthenticationProvider {
AuthenticationProvider, MessageSourceAware {
//~ Instance fields ========================================================
protected MessageSourceAccessor messages;
private String key;
//~ Methods ================================================================
public void setKey(String key) {
this.key = key;
}
public String getKey() {
return key;
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(key, "A Key is required and should match that configured for the RunAsManagerImpl");
Assert.notNull(key,
"A Key is required and should match that configured for the RunAsManagerImpl");
}
public Authentication authenticate(Authentication authentication)
@ -69,11 +66,24 @@ public class RunAsImplAuthenticationProvider implements InitializingBean,
if (token.getKeyHash() == key.hashCode()) {
return authentication;
} else {
throw new BadCredentialsException(
"The presented RunAsUserToken does not contain the expected key");
throw new BadCredentialsException(messages.getMessage(
"RunAsImplAuthenticationProvider.incorrectKey",
"The presented RunAsUserToken does not contain the expected key"));
}
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public void setMessageSource(MessageSource messageSource) {
this.messages = new MessageSourceAccessor(messageSource);
}
public boolean supports(Class authentication) {
if (RunAsUserToken.class.isAssignableFrom(authentication)) {
return true;

View File

@ -15,7 +15,32 @@
package org.acegisecurity.ui;
import org.acegisecurity.Authentication;
import org.acegisecurity.AuthenticationException;
import org.acegisecurity.AuthenticationManager;
import org.acegisecurity.context.SecurityContextHolder;
import org.acegisecurity.event.authentication.InteractiveAuthenticationSuccessEvent;
import org.acegisecurity.ui.rememberme.NullRememberMeServices;
import org.acegisecurity.ui.rememberme.RememberMeServices;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.util.Assert;
import java.io.IOException;
import java.util.Properties;
import javax.servlet.Filter;
@ -27,21 +52,6 @@ import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.acegisecurity.Authentication;
import org.acegisecurity.AuthenticationException;
import org.acegisecurity.AuthenticationManager;
import org.acegisecurity.context.SecurityContextHolder;
import org.acegisecurity.event.authentication.InteractiveAuthenticationSuccessEvent;
import org.acegisecurity.ui.rememberme.NullRememberMeServices;
import org.acegisecurity.ui.rememberme.RememberMeServices;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.util.Assert;
/**
* Abstract processor of browser-based HTTP-based authentication requests.
@ -115,20 +125,16 @@ import org.springframework.util.Assert;
*
* <p>
* If authentication is successful, an {@link
* org.acegisecurity.event.authentication.InteractiveAuthenticationSuccessEvent} will be
* published to the application context. No events will be published if
* authentication was unsuccessful, because this would generally be recorded
* via an <code>AuthenticationManager</code>-specific application event.
* org.acegisecurity.event.authentication.InteractiveAuthenticationSuccessEvent}
* will be published to the application context. No events will be published
* if authentication was unsuccessful, because this would generally be
* recorded via an <code>AuthenticationManager</code>-specific application
* event.
* </p>
*
* @author Ben Alex
* @author colin sampaleanu
* @author Ray Krueger
* @version $Id$
*/
public abstract class AbstractProcessingFilter implements Filter,
InitializingBean, ApplicationEventPublisherAware {
//~ Static fields/initializersApplicationContextAware =============================================
InitializingBean, ApplicationEventPublisherAware, MessageSourceAware {
//~ Static fields/initializers =============================================
public static final String ACEGI_SECURITY_TARGET_URL_KEY = "ACEGI_SECURITY_TARGET_URL";
public static final String ACEGI_SECURITY_LAST_EXCEPTION_KEY = "ACEGI_SECURITY_LAST_EXCEPTION";
@ -138,6 +144,7 @@ public abstract class AbstractProcessingFilter implements Filter,
private ApplicationEventPublisher eventPublisher;
private AuthenticationManager authenticationManager;
protected MessageSourceAccessor messages;
private Properties exceptionMappings = new Properties();
private RememberMeServices rememberMeServices = new NullRememberMeServices();
@ -173,65 +180,15 @@ public abstract class AbstractProcessingFilter implements Filter,
//~ Methods ================================================================
public void setAlwaysUseDefaultTargetUrl(boolean alwaysUseDefaultTargetUrl) {
this.alwaysUseDefaultTargetUrl = alwaysUseDefaultTargetUrl;
}
public boolean isAlwaysUseDefaultTargetUrl() {
return alwaysUseDefaultTargetUrl;
}
public void setApplicationEventPublisher(ApplicationEventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
public void setContinueChainBeforeSuccessfulAuthentication(
boolean continueChainBeforeSuccessfulAuthentication) {
this.continueChainBeforeSuccessfulAuthentication = continueChainBeforeSuccessfulAuthentication;
}
public boolean isContinueChainBeforeSuccessfulAuthentication() {
return continueChainBeforeSuccessfulAuthentication;
}
/**
* Specifies the default <code>filterProcessesUrl</code> for the
* implementation.
*
* @return the default <code>filterProcessesUrl</code>
*/
public abstract String getDefaultFilterProcessesUrl();
public void setDefaultTargetUrl(String defaultTargetUrl) {
this.defaultTargetUrl = defaultTargetUrl;
}
public String getDefaultTargetUrl() {
return defaultTargetUrl;
}
public void setExceptionMappings(Properties exceptionMappings) {
this.exceptionMappings = exceptionMappings;
}
public Properties getExceptionMappings() {
return new Properties(exceptionMappings);
}
public void setFilterProcessesUrl(String filterProcessesUrl) {
this.filterProcessesUrl = filterProcessesUrl;
}
public String getFilterProcessesUrl() {
return filterProcessesUrl;
}
public void setRememberMeServices(RememberMeServices rememberMeServices) {
this.rememberMeServices = rememberMeServices;
}
public RememberMeServices getRememberMeServices() {
return rememberMeServices;
public void afterPropertiesSet() throws Exception {
Assert.hasLength(filterProcessesUrl,
"filterProcessesUrl must be specified");
Assert.hasLength(defaultTargetUrl, "defaultTargetUrl must be specified");
Assert.hasLength(authenticationFailureUrl,
"authenticationFailureUrl must be specified");
Assert.notNull(authenticationManager,
"authenticationManager must be specified");
Assert.notNull(this.rememberMeServices);
}
/**
@ -247,34 +204,6 @@ public abstract class AbstractProcessingFilter implements Filter,
public abstract Authentication attemptAuthentication(
HttpServletRequest request) throws AuthenticationException;
public void setAuthenticationFailureUrl(String authenticationFailureUrl) {
this.authenticationFailureUrl = authenticationFailureUrl;
}
public String getAuthenticationFailureUrl() {
return authenticationFailureUrl;
}
public void setAuthenticationManager(
AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
public AuthenticationManager getAuthenticationManager() {
return authenticationManager;
}
public void afterPropertiesSet() throws Exception {
Assert.hasLength(filterProcessesUrl,
"filterProcessesUrl must be specified");
Assert.hasLength(defaultTargetUrl, "defaultTargetUrl must be specified");
Assert.hasLength(authenticationFailureUrl,
"authenticationFailureUrl must be specified");
Assert.notNull(authenticationManager,
"authenticationManager must be specified");
Assert.notNull(this.rememberMeServices);
}
/**
* Does nothing. We use IoC container lifecycle services instead.
*/
@ -324,6 +253,38 @@ public abstract class AbstractProcessingFilter implements Filter,
chain.doFilter(request, response);
}
public String getAuthenticationFailureUrl() {
return authenticationFailureUrl;
}
public AuthenticationManager getAuthenticationManager() {
return authenticationManager;
}
/**
* Specifies the default <code>filterProcessesUrl</code> for the
* implementation.
*
* @return the default <code>filterProcessesUrl</code>
*/
public abstract String getDefaultFilterProcessesUrl();
public String getDefaultTargetUrl() {
return defaultTargetUrl;
}
public Properties getExceptionMappings() {
return new Properties(exceptionMappings);
}
public String getFilterProcessesUrl() {
return filterProcessesUrl;
}
public RememberMeServices getRememberMeServices() {
return rememberMeServices;
}
/**
* Does nothing. We use IoC container lifecycle services instead.
*
@ -333,6 +294,14 @@ public abstract class AbstractProcessingFilter implements Filter,
*/
public void init(FilterConfig arg0) throws ServletException {}
public boolean isAlwaysUseDefaultTargetUrl() {
return alwaysUseDefaultTargetUrl;
}
public boolean isContinueChainBeforeSuccessfulAuthentication() {
return continueChainBeforeSuccessfulAuthentication;
}
protected void onPreAuthentication(HttpServletRequest request,
HttpServletResponse response) throws IOException {}
@ -380,6 +349,49 @@ public abstract class AbstractProcessingFilter implements Filter,
return uri.endsWith(request.getContextPath() + filterProcessesUrl);
}
public void setAlwaysUseDefaultTargetUrl(boolean alwaysUseDefaultTargetUrl) {
this.alwaysUseDefaultTargetUrl = alwaysUseDefaultTargetUrl;
}
public void setApplicationEventPublisher(
ApplicationEventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
public void setAuthenticationFailureUrl(String authenticationFailureUrl) {
this.authenticationFailureUrl = authenticationFailureUrl;
}
public void setAuthenticationManager(
AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
public void setContinueChainBeforeSuccessfulAuthentication(
boolean continueChainBeforeSuccessfulAuthentication) {
this.continueChainBeforeSuccessfulAuthentication = continueChainBeforeSuccessfulAuthentication;
}
public void setDefaultTargetUrl(String defaultTargetUrl) {
this.defaultTargetUrl = defaultTargetUrl;
}
public void setExceptionMappings(Properties exceptionMappings) {
this.exceptionMappings = exceptionMappings;
}
public void setFilterProcessesUrl(String filterProcessesUrl) {
this.filterProcessesUrl = filterProcessesUrl;
}
public void setMessageSource(MessageSource messageSource) {
this.messages = new MessageSourceAccessor(messageSource);
}
public void setRememberMeServices(RememberMeServices rememberMeServices) {
this.rememberMeServices = rememberMeServices;
}
protected void successfulAuthentication(HttpServletRequest request,
HttpServletResponse response, Authentication authResult)
throws IOException {
@ -395,7 +407,8 @@ public abstract class AbstractProcessingFilter implements Filter,
+ authResult + "'");
}
String targetUrl = (String) request.getSession().getAttribute(ACEGI_SECURITY_TARGET_URL_KEY);
String targetUrl = (String) request.getSession()
.getAttribute(ACEGI_SECURITY_TARGET_URL_KEY);
request.getSession().removeAttribute(ACEGI_SECURITY_TARGET_URL_KEY);
if (alwaysUseDefaultTargetUrl == true) {
@ -444,8 +457,8 @@ public abstract class AbstractProcessingFilter implements Filter,
}
try {
request.getSession().setAttribute(ACEGI_SECURITY_LAST_EXCEPTION_KEY,
failed);
request.getSession()
.setAttribute(ACEGI_SECURITY_LAST_EXCEPTION_KEY, failed);
} catch (Exception ignored) {}
onUnsuccessfulAuthentication(request, response);

View File

@ -19,13 +19,17 @@ import org.acegisecurity.AuthenticationException;
import org.acegisecurity.AuthenticationServiceException;
import org.acegisecurity.BadCredentialsException;
import org.acegisecurity.UserDetails;
import org.acegisecurity.context.SecurityContextHolder;
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.acegisecurity.providers.dao.AuthenticationDao;
import org.acegisecurity.providers.dao.UserCache;
import org.acegisecurity.providers.dao.UsernameNotFoundException;
import org.acegisecurity.providers.dao.cache.NullUserCache;
import org.acegisecurity.ui.WebAuthenticationDetails;
import org.acegisecurity.util.StringSplitUtils;
import org.apache.commons.codec.binary.Base64;
@ -35,6 +39,10 @@ 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.util.Assert;
import org.springframework.util.StringUtils;
@ -72,19 +80,22 @@ import javax.servlet.http.HttpServletResponse;
* <p>
* This Digest implementation has been designed to avoid needing to store
* session state between invocations. All session management information is
* stored in the "nonce" that is sent to the client by the {@link DigestProcessingFilterEntryPoint}.
* stored in the "nonce" that is sent to the client by the {@link
* DigestProcessingFilterEntryPoint}.
* </p>
*
* <P>
* If authentication is successful, the resulting {@link org.acegisecurity.Authentication Authentication}
* object will be placed into the <code>SecurityContextHolder</code>.
* If authentication is successful, the resulting {@link
* org.acegisecurity.Authentication Authentication} object will be placed into
* the <code>SecurityContextHolder</code>.
* </p>
*
* <p>
* If authentication fails, an
* {@link org.acegisecurity.intercept.web.AuthenticationEntryPoint AuthenticationEntryPoint}
* implementation is called. This must always be {@link DigestProcessingFilterEntryPoint},
* which will prompt the user to authenticate again via Digest authentication.
* If authentication fails, an {@link
* org.acegisecurity.intercept.web.AuthenticationEntryPoint
* AuthenticationEntryPoint} implementation is called. This must always be
* {@link DigestProcessingFilterEntryPoint}, which will prompt the user to
* authenticate again via Digest authentication.
* </p>
*
* <P>
@ -100,11 +111,9 @@ import javax.servlet.http.HttpServletResponse;
* <code>web.xml</code> to use the {@link
* org.acegisecurity.util.FilterToBeanProxy}.
* </p>
*
* @author Ben Alex
* @version $Id$
*/
public class DigestProcessingFilter implements Filter, InitializingBean {
public class DigestProcessingFilter implements Filter, InitializingBean,
MessageSourceAware {
//~ Static fields/initializers =============================================
private static final Log logger = LogFactory.getLog(DigestProcessingFilter.class);
@ -113,32 +122,12 @@ public class DigestProcessingFilter implements Filter, InitializingBean {
private AuthenticationDao authenticationDao;
private DigestProcessingFilterEntryPoint authenticationEntryPoint;
protected MessageSourceAccessor messages;
private UserCache userCache = new NullUserCache();
private boolean passwordAlreadyEncoded = false;
//~ Methods ================================================================
public void setPasswordAlreadyEncoded(boolean passwordAlreadyEncoded) {
this.passwordAlreadyEncoded = passwordAlreadyEncoded;
}
public void setAuthenticationDao(AuthenticationDao authenticationDao) {
this.authenticationDao = authenticationDao;
}
public AuthenticationDao getAuthenticationDao() {
return authenticationDao;
}
public void setAuthenticationEntryPoint(
DigestProcessingFilterEntryPoint authenticationEntryPoint) {
this.authenticationEntryPoint = authenticationEntryPoint;
}
public DigestProcessingFilterEntryPoint getAuthenticationEntryPoint() {
return authenticationEntryPoint;
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(authenticationDao, "An AuthenticationDao is required");
Assert.notNull(authenticationEntryPoint,
@ -169,8 +158,7 @@ public class DigestProcessingFilter implements Filter, InitializingBean {
if ((header != null) && header.startsWith("Digest ")) {
String section212response = header.substring(7);
String[] headerEntries = StringUtils
.commaDelimitedListToStringArray(section212response);
String[] headerEntries = StringUtils.commaDelimitedListToStringArray(section212response);
Map headerMap = StringSplitUtils.splitEachArrayElementAndCreateMap(headerEntries,
"=", "\"");
@ -194,9 +182,10 @@ public class DigestProcessingFilter implements Filter, InitializingBean {
}
fail(request, response,
new BadCredentialsException(
"Missing mandatory digest value; received header '"
+ section212response + "'"));
new BadCredentialsException(messages.getMessage(
"DigestProcessingFilter.missingMandatory",
new Object[] {section212response},
"Missing mandatory digest value; received header {0}")));
return;
}
@ -210,9 +199,10 @@ public class DigestProcessingFilter implements Filter, InitializingBean {
}
fail(request, response,
new BadCredentialsException(
"Missing mandatory digest value for 'auth' QOP; received header '"
+ section212response + "'"));
new BadCredentialsException(messages.getMessage(
"DigestProcessingFilter.missingAuth",
new Object[] {section212response},
"Missing mandatory digest value; received header {0}")));
return;
}
@ -221,10 +211,11 @@ public class DigestProcessingFilter implements Filter, InitializingBean {
// Check realm name equals what we expected
if (!this.getAuthenticationEntryPoint().getRealmName().equals(realm)) {
fail(request, response,
new BadCredentialsException("Response realm name '" + realm
+ "' does not match system realm name of '"
+ this.getAuthenticationEntryPoint().getRealmName()
+ "'"));
new BadCredentialsException(messages.getMessage(
"DigestProcessingFilter.incorrectRealm",
new Object[] {realm, this.getAuthenticationEntryPoint()
.getRealmName()},
"Response realm name '{0}' does not match system realm name of '{1}'")));
return;
}
@ -232,9 +223,10 @@ public class DigestProcessingFilter implements Filter, InitializingBean {
// Check nonce was a Base64 encoded (as sent by DigestProcessingFilterEntryPoint)
if (!Base64.isArrayByteBase64(nonce.getBytes())) {
fail(request, response,
new BadCredentialsException(
"Nonce is not encoded in Base64; received nonce: '"
+ nonce + "'"));
new BadCredentialsException(messages.getMessage(
"DigestProcessingFilter.nonceEncoding",
new Object[] {nonce},
"Nonce is not encoded in Base64; received nonce {0}")));
return;
}
@ -249,9 +241,10 @@ public class DigestProcessingFilter implements Filter, InitializingBean {
if (nonceTokens.length != 2) {
fail(request, response,
new BadCredentialsException(
"Nonce should have yielded two tokens but was: '"
+ nonceAsPlainText + "'"));
new BadCredentialsException(messages.getMessage(
"DigestProcessingFilter.nonceNotTwoTokens",
new Object[] {nonceAsPlainText},
"Nonce should have yielded two tokens but was {0}")));
return;
}
@ -263,9 +256,10 @@ public class DigestProcessingFilter implements Filter, InitializingBean {
nonceExpiryTime = new Long(nonceTokens[0]).longValue();
} catch (NumberFormatException nfe) {
fail(request, response,
new BadCredentialsException(
"Nonce token should have yielded a numeric first token, but was: '"
+ nonceAsPlainText + "'"));
new BadCredentialsException(messages.getMessage(
"DigestProcessingFilter.nonceNotNumeric",
new Object[] {nonceAsPlainText},
"Nonce token should have yielded a numeric first token, but was {0}")));
return;
}
@ -276,14 +270,17 @@ public class DigestProcessingFilter implements Filter, InitializingBean {
if (!expectedNonceSignature.equals(nonceTokens[1])) {
fail(request, response,
new BadCredentialsException("Nonce token compromised: '"
+ nonceAsPlainText + "'"));
new BadCredentialsException(messages.getMessage(
"DigestProcessingFilter.nonceCompromised",
new Object[] {nonceAsPlainText},
"Nonce token compromised {0}")));
return;
}
// Lookup password for presented username
// NB: DAO-provided password MUST be clear text - not encoded/salted
// (unless this instance's passwordAlreadyEncoded property is 'false')
boolean loadedFromDao = false;
UserDetails user = userCache.getUserFromCache(username);
@ -294,8 +291,10 @@ public class DigestProcessingFilter implements Filter, InitializingBean {
user = authenticationDao.loadUserByUsername(username);
} catch (UsernameNotFoundException notFound) {
fail(request, response,
new BadCredentialsException("Username '" + username
+ "' not known"));
new BadCredentialsException(messages.getMessage(
"DigestProcessingFilter.usernameNotFound",
new Object[] {username},
"Username {0} not found")));
return;
}
@ -312,8 +311,8 @@ public class DigestProcessingFilter implements Filter, InitializingBean {
String serverDigestMd5;
// Don't catch IllegalArgumentException (already checked validity)
serverDigestMd5 = generateDigest(passwordAlreadyEncoded, username, realm,
user.getPassword(),
serverDigestMd5 = generateDigest(passwordAlreadyEncoded, username,
realm, user.getPassword(),
((HttpServletRequest) request).getMethod(), uri, qop,
nonce, nc, cnonce);
@ -329,15 +328,17 @@ public class DigestProcessingFilter implements Filter, InitializingBean {
} catch (UsernameNotFoundException notFound) {
// Would very rarely happen, as user existed earlier
fail(request, response,
new BadCredentialsException("Username '" + username
+ "' not known"));
new BadCredentialsException(messages.getMessage(
"DigestProcessingFilter.usernameNotFound",
new Object[] {username},
"Username {0} not found")));
}
userCache.putUserInCache(user);
// Don't catch IllegalArgumentException (already checked validity)
serverDigestMd5 = generateDigest(passwordAlreadyEncoded, username, realm,
user.getPassword(),
serverDigestMd5 = generateDigest(passwordAlreadyEncoded,
username, realm, user.getPassword(),
((HttpServletRequest) request).getMethod(), uri, qop,
nonce, nc, cnonce);
}
@ -351,7 +352,9 @@ public class DigestProcessingFilter implements Filter, InitializingBean {
}
fail(request, response,
new BadCredentialsException("Incorrect response"));
new BadCredentialsException(messages.getMessage(
"DigestProcessingFilter.incorrectResponse",
"Incorrect response")));
return;
}
@ -362,7 +365,9 @@ public class DigestProcessingFilter implements Filter, InitializingBean {
// but the request was otherwise appearing to be valid
if (nonceExpiryTime < System.currentTimeMillis()) {
fail(request, response,
new NonceExpiredException("Nonce has expired/timed out"));
new NonceExpiredException(messages.getMessage(
"DigestProcessingFilter.nonceExpired",
"Nonce has expired/timed out")));
return;
}
@ -382,18 +387,32 @@ public class DigestProcessingFilter implements Filter, InitializingBean {
chain.doFilter(request, response);
}
public static String encodePasswordInA1Format(String username, String realm, String password) {
public static String encodePasswordInA1Format(String username,
String realm, String password) {
String a1 = username + ":" + realm + ":" + password;
String a1Md5 = new String(DigestUtils.md5Hex(a1));
return a1Md5;
return a1Md5;
}
private void fail(ServletRequest request, ServletResponse response,
AuthenticationException failed) throws IOException, ServletException {
SecurityContextHolder.getContext().setAuthentication(null);
if (logger.isDebugEnabled()) {
logger.debug(failed);
}
authenticationEntryPoint.commence(request, response, failed);
}
/**
* Computes the <code>response</code> portion of a Digest authentication
* header. Both the server and user agent should compute the
* <code>response</code> independently. Provided as a static method to
* simplify the coding of user agents.
*
* @param passwordAlreadyEncoded DOCUMENT ME!
* @param username DOCUMENT ME!
* @param realm DOCUMENT ME!
* @param password DOCUMENT ME!
@ -408,19 +427,20 @@ public class DigestProcessingFilter implements Filter, InitializingBean {
*
* @throws IllegalArgumentException DOCUMENT ME!
*/
public static String generateDigest(boolean passwordAlreadyEncoded, String username, String realm,
String password, String httpMethod, String uri, String qop,
String nonce, String nc, String cnonce) throws IllegalArgumentException {
public static String generateDigest(boolean passwordAlreadyEncoded,
String username, String realm, String password, String httpMethod,
String uri, String qop, String nonce, String nc, String cnonce)
throws IllegalArgumentException {
String a1Md5 = null;
String a2 = httpMethod + ":" + uri;
String a2Md5 = new String(DigestUtils.md5Hex(a2));
if (passwordAlreadyEncoded) {
a1Md5 = password;
a1Md5 = password;
} else {
a1Md5 = encodePasswordInA1Format(username, realm, password);
a1Md5 = encodePasswordInA1Format(username, realm, password);
}
String digest;
if (qop == null) {
@ -440,8 +460,12 @@ public class DigestProcessingFilter implements Filter, InitializingBean {
return digestMd5;
}
public void setUserCache(UserCache userCache) {
this.userCache = userCache;
public AuthenticationDao getAuthenticationDao() {
return authenticationDao;
}
public DigestProcessingFilterEntryPoint getAuthenticationEntryPoint() {
return authenticationEntryPoint;
}
public UserCache getUserCache() {
@ -450,14 +474,24 @@ public class DigestProcessingFilter implements Filter, InitializingBean {
public void init(FilterConfig ignored) throws ServletException {}
private void fail(ServletRequest request, ServletResponse response,
AuthenticationException failed) throws IOException, ServletException {
SecurityContextHolder.getContext().setAuthentication(null);
public void setAuthenticationDao(AuthenticationDao authenticationDao) {
this.authenticationDao = authenticationDao;
}
if (logger.isDebugEnabled()) {
logger.debug(failed);
}
public void setAuthenticationEntryPoint(
DigestProcessingFilterEntryPoint authenticationEntryPoint) {
this.authenticationEntryPoint = authenticationEntryPoint;
}
authenticationEntryPoint.commence(request, response, failed);
public void setMessageSource(MessageSource messageSource) {
this.messages = new MessageSourceAccessor(messageSource);
}
public void setPasswordAlreadyEncoded(boolean passwordAlreadyEncoded) {
this.passwordAlreadyEncoded = passwordAlreadyEncoded;
}
public void setUserCache(UserCache userCache) {
this.userCache = userCache;
}
}

View File

@ -22,12 +22,17 @@ import org.acegisecurity.AuthenticationException;
import org.acegisecurity.CredentialsExpiredException;
import org.acegisecurity.DisabledException;
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.LockedException;
import org.acegisecurity.UserDetails;
import org.acegisecurity.context.SecurityContextHolder;
import org.acegisecurity.event.authentication.AuthenticationSwitchUserEvent;
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.acegisecurity.providers.dao.AuthenticationDao;
import org.acegisecurity.providers.dao.UsernameNotFoundException;
import org.acegisecurity.ui.WebAuthenticationDetails;
import org.apache.commons.logging.Log;
@ -36,8 +41,11 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.util.Assert;
@ -80,8 +88,8 @@ import javax.servlet.http.HttpServletResponse;
* <p>
* On successful switch, the user's <code>SecurityContextHolder</code> will be
* updated to reflect the specified user and will also contain an additinal
* {@link org.acegisecurity.ui.switchuser.SwitchUserGrantedAuthority }
* which contains the original user.
* {@link org.acegisecurity.ui.switchuser.SwitchUserGrantedAuthority } which
* contains the original user.
* </p>
*
* <p>
@ -104,13 +112,10 @@ import javax.servlet.http.HttpServletResponse;
* </pre>
* </p>
*
* @author Mark St.Godard
* @version $Id$
*
* @see org.acegisecurity.ui.switchuser.SwitchUserGrantedAuthority
*/
public class SwitchUserProcessingFilter implements Filter, InitializingBean,
ApplicationEventPublisherAware {
ApplicationEventPublisherAware, MessageSourceAware {
//~ Static fields/initializers =============================================
private static final Log logger = LogFactory.getLog(SwitchUserProcessingFilter.class);
@ -127,105 +132,21 @@ public class SwitchUserProcessingFilter implements Filter, InitializingBean,
// ~ Instance fields
// ========================================================
private AuthenticationDao authenticationDao;
protected MessageSourceAccessor messages;
private String exitUserUrl = "/j_acegi_exit_user";
private String switchUserUrl = "/j_acegi_switch_user";
private String targetUrl;
//~ Methods ================================================================
public void setApplicationEventPublisher(ApplicationEventPublisher eventPublisher)
throws BeansException {
this.eventPublisher = eventPublisher;
}
/**
* Sets the authentication data access object.
*
* @param authenticationDao The authentication dao
*/
public void setAuthenticationDao(AuthenticationDao authenticationDao) {
this.authenticationDao = authenticationDao;
}
/**
* Set the URL to respond to exit user processing.
*
* @param exitUserUrl The exit user URL.
*/
public void setExitUserUrl(String exitUserUrl) {
this.exitUserUrl = exitUserUrl;
}
/**
* Set the URL to respond to switch user processing.
*
* @param switchUserUrl The switch user URL.
*/
public void setSwitchUserUrl(String switchUserUrl) {
this.switchUserUrl = switchUserUrl;
}
/**
* Sets the URL to go to after a successful switch / exit user request.
*
* @param targetUrl The target url.
*/
public void setTargetUrl(String targetUrl) {
this.targetUrl = targetUrl;
}
public void afterPropertiesSet() throws Exception {
Assert.hasLength(switchUserUrl, "switchUserUrl must be specified");
Assert.hasLength(exitUserUrl, "exitUserUrl must be specified");
Assert.hasLength(targetUrl, "targetUrl must be specified");
Assert.notNull(authenticationDao, "authenticationDao must be specified");
Assert.notNull(messages, "A message source must be set");
}
public void destroy() {}
/**
* @see javax.servlet.Filter#doFilter
*/
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
Assert.isInstanceOf(HttpServletRequest.class, request);
Assert.isInstanceOf(HttpServletResponse.class, response);
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
// check for switch or exit request
if (requiresSwitchUser(httpRequest)) {
// if set, attempt switch and store original
Authentication targetUser = attemptSwitchUser(httpRequest);
// update the current context to the new target user
SecurityContextHolder.getContext().setAuthentication(targetUser);
// redirect to target url
httpResponse.sendRedirect(httpResponse.encodeRedirectURL(httpRequest
.getContextPath() + targetUrl));
return;
} else if (requiresExitUser(httpRequest)) {
// get the original authentication object (if exists)
Authentication originalUser = attemptExitUser(httpRequest);
// update the current context back to the original user
SecurityContextHolder.getContext().setAuthentication(originalUser);
// redirect to target url
httpResponse.sendRedirect(httpResponse.encodeRedirectURL(httpRequest
.getContextPath() + targetUrl));
return;
}
chain.doFilter(request, response);
}
public void init(FilterConfig ignored) throws ServletException {}
/**
* Attempt to exit from an already switched user.
*
@ -244,229 +165,397 @@ public class SwitchUserProcessingFilter implements Filter, InitializingBean,
.getAuthentication();
if (null == current) {
throw new AuthenticationCredentialsNotFoundException(
"No current user associated with this request!");
}
// check to see if the current user did actual switch to another user
// if so, get the original source user so we can switch back
Authentication original = getSourceAuthentication(current);
if (original == null) {
logger.error("Could not find original user Authentication object!");
throw new AuthenticationCredentialsNotFoundException(
"Could not find original Authentication object!");
}
// get the source user details
UserDetails originalUser = null;
Object obj = original.getPrincipal();
if ((obj != null) && obj instanceof UserDetails) {
originalUser = (UserDetails) obj;
}
// publish event
if (this.eventPublisher != null) {
eventPublisher.publishEvent(new AuthenticationSwitchUserEvent(current,
originalUser));
}
return original;
}
/**
* Attempt to switch to another user. If the user does not exist or is not
* active, return null.
*
* @param request The http request
*
* @return The new <code>Authentication</code> request if successfully
* switched to another user, <code>null</code> otherwise.
*
* @throws AuthenticationException
* @throws UsernameNotFoundException If the target user is not found.
* @throws DisabledException If the target user is disabled.
* @throws AccountExpiredException If the target user account is expired.
* @throws CredentialsExpiredException If the target user credentials are
* expired.
*/
protected Authentication attemptSwitchUser(HttpServletRequest request)
throws AuthenticationException {
UsernamePasswordAuthenticationToken targetUserRequest = null;
String username = request.getParameter(ACEGI_SECURITY_SWITCH_USERNAME_KEY);
if (username == null) {
username = "";
}
if (logger.isDebugEnabled()) {
logger.debug("Attempt to switch to user [" + username + "]");
}
// load the user by name
UserDetails targetUser = this.authenticationDao.loadUserByUsername(username);
// user not found
if (targetUser == null) {
throw new UsernameNotFoundException("User [" + username
+ "] cannot be found!");
}
// user is disabled
if (!targetUser.isEnabled()) {
throw new DisabledException("User is disabled");
}
// account is expired
if (!targetUser.isAccountNonExpired()) {
throw new AccountExpiredException("User account has expired");
}
// credentials expired
if (!targetUser.isCredentialsNonExpired()) {
throw new CredentialsExpiredException("User credentials expired");
}
// ok, create the switch user token
targetUserRequest = createSwitchUserToken(request, username, targetUser);
if (logger.isDebugEnabled()) {
logger.debug("Switch User Token [" + targetUserRequest + "]");
}
// publish event
if (this.eventPublisher != null) {
eventPublisher.publishEvent(new AuthenticationSwitchUserEvent(
SecurityContextHolder.getContext().getAuthentication(),
targetUser));
}
return targetUserRequest;
}
/**
* Checks the request URI for the presence of <tt>exitUserUrl</tt>.
*
* @param request The http servlet request
*
* @return <code>true</code> if the request requires a exit user,
* <code>false</code> otherwise.
*
* @see SwitchUserProcessingFilter#exitUserUrl
*/
protected boolean requiresExitUser(HttpServletRequest request) {
String uri = stripUri(request);
return uri.endsWith(request.getContextPath() + exitUserUrl);
}
/**
* Checks the request URI for the presence of <tt>switchUserUrl</tt>.
*
* @param request The http servlet request
*
* @return <code>true</code> if the request requires a switch,
* <code>false</code> otherwise.
*
* @see SwitchUserProcessingFilter#switchUserUrl
*/
protected boolean requiresSwitchUser(HttpServletRequest request) {
String uri = stripUri(request);
return uri.endsWith(request.getContextPath() + switchUserUrl);
}
/**
* Strips any content after the ';' in the request URI
*
* @param request The http request
*
* @return The stripped uri
*/
private static String stripUri(HttpServletRequest request) {
String uri = request.getRequestURI();
int idx = uri.indexOf(';');
if (idx > 0) {
uri = uri.substring(0, idx);
}
return uri;
}
/**
* Find the original <code>Authentication</code> object from the current
* user's granted authorities. A successfully switched user should have a
* <code>SwitchUserGrantedAuthority</code> that contains the original
* source user <code>Authentication</code> object.
*
* @param current The current <code>Authentication</code> object
*
* @return The source user <code>Authentication</code> object or
* <code>null</code> otherwise.
*/
private Authentication getSourceAuthentication(Authentication current) {
Authentication original = null;
// iterate over granted authorities and find the 'switch user' authority
GrantedAuthority[] authorities = current.getAuthorities();
for (int i = 0; i < authorities.length; i++) {
// check for switch user type of authority
if (authorities[i] instanceof SwitchUserGrantedAuthority) {
original = ((SwitchUserGrantedAuthority) authorities[i])
.getSource();
logger.debug("Found original switch user granted authority ["
+ original + "]");
throw new AuthenticationCredentialsNotFoundException(messages
.getMessage("SwitchUserProcessingFilter.noCurrentUser",
"No current user associated with this request"));
}
}
return original;
}
// check to see if the current user did actual switch to another user
// if so, get the original source user so we can switch back
Authentication original = getSourceAuthentication(current);
/**
* Create a switch user token that contains an additional
* <tt>GrantedAuthority</tt> that contains the original
* <code>Authentication</code> object.
*
* @param request The http servlet request.
* @param username The username of target user
* @param targetUser The target user
*
* @return The authentication token
*
* @see SwitchUserGrantedAuthority
*/
private UsernamePasswordAuthenticationToken createSwitchUserToken(
HttpServletRequest request, String username, UserDetails targetUser) {
UsernamePasswordAuthenticationToken targetUserRequest;
if (original == null) {
logger.error(
"Could not find original user Authentication object!");
throw new AuthenticationCredentialsNotFoundException(messages
.getMessage(
"SwitchUserProcessingFilter.noOriginalAuthentication",
"Could not find original Authentication object"));
}
// grant an additional authority that contains the original Authentication object
// which will be used to 'exit' from the current switched user.
Authentication currentAuth = SecurityContextHolder.getContext()
.getAuthentication();
GrantedAuthority switchAuthority = new SwitchUserGrantedAuthority(ROLE_PREVIOUS_ADMINISTRATOR,
currentAuth);
// get the source user details
UserDetails originalUser = null;
Object obj = original.getPrincipal();
// get the original authorities
List orig = Arrays.asList(targetUser.getAuthorities());
if ((obj != null) && obj instanceof UserDetails) {
originalUser = (UserDetails) obj;
}
// add the new switch user authority
List newAuths = new ArrayList(orig);
newAuths.add(switchAuthority);
// publish event
if (this.eventPublisher != null) {
eventPublisher.publishEvent(new AuthenticationSwitchUserEvent(
current, originalUser));
}
GrantedAuthority[] authorities = {};
authorities = (GrantedAuthority[]) newAuths.toArray(authorities);
return original;
}
// create the new authentication token
targetUserRequest = new UsernamePasswordAuthenticationToken(targetUser,
targetUser.getPassword(), authorities);
/**
* Attempt to switch to another user. If the user does not exist or
* is not active, return null.
*
* @param request The http request
*
* @return The new <code>Authentication</code> request if
* successfully switched to another user,
* <code>null</code> otherwise.
*
* @throws AuthenticationException
* @throws UsernameNotFoundException If the target user is not
* found.
* @throws LockedException DOCUMENT ME!
* @throws DisabledException If the target user is disabled.
* @throws AccountExpiredException If the target user account is
* expired.
* @throws CredentialsExpiredException If the target user
* credentials are expired.
*/
protected Authentication attemptSwitchUser(
HttpServletRequest request) throws AuthenticationException {
UsernamePasswordAuthenticationToken targetUserRequest = null;
// set details
targetUserRequest.setDetails(new WebAuthenticationDetails(request));
String username = request.getParameter(ACEGI_SECURITY_SWITCH_USERNAME_KEY);
return targetUserRequest;
}
}
if (username == null) {
username = "";
}
if (logger.isDebugEnabled()) {
logger.debug("Attempt to switch to user [" + username + "]");
}
// load the user by name
UserDetails targetUser = this.authenticationDao
.loadUserByUsername(username);
// user not found
if (targetUser == null) {
throw new UsernameNotFoundException(messages.getMessage(
"SwitchUserProcessingFilter.usernameNotFound",
new Object[] {username},
"Username {0} not found"));
}
// account is expired
if (!targetUser.isAccountNonLocked()) {
throw new LockedException(messages.getMessage(
"SwitchUserProcessingFilter.locked",
"User account is locked"));
}
// user is disabled
if (!targetUser.isEnabled()) {
throw new DisabledException(messages.getMessage(
"SwitchUserProcessingFilter.disabled",
"User is disabled"));
}
// account is expired
if (!targetUser.isAccountNonExpired()) {
throw new AccountExpiredException(messages.getMessage(
"SwitchUserProcessingFilter.expired",
"User account has expired"));
}
// credentials expired
if (!targetUser.isCredentialsNonExpired()) {
throw new CredentialsExpiredException(messages
.getMessage(
"SwitchUserProcessingFilter.credentialsExpired",
"User credentials have expired"));
}
// ok, create the switch user token
targetUserRequest = createSwitchUserToken(request,
username, targetUser);
if (logger.isDebugEnabled()) {
logger.debug("Switch User Token ["
+ targetUserRequest + "]");
}
// publish event
if (this.eventPublisher != null) {
eventPublisher.publishEvent(new AuthenticationSwitchUserEvent(
SecurityContextHolder.getContext()
.getAuthentication(),
targetUser));
}
return targetUserRequest;
}
/**
* Create a switch user token that contains an additional
* <tt>GrantedAuthority</tt> that contains the original
* <code>Authentication</code> object.
*
* @param request The http servlet request.
* @param username The username of target user
* @param targetUser The target user
*
* @return The authentication token
*
* @see SwitchUserGrantedAuthority
*/
private UsernamePasswordAuthenticationToken createSwitchUserToken(
HttpServletRequest request, String username,
UserDetails targetUser) {
UsernamePasswordAuthenticationToken targetUserRequest;
// grant an additional authority that contains the original Authentication object
// which will be used to 'exit' from the current switched user.
Authentication currentAuth = SecurityContextHolder.getContext()
.getAuthentication();
GrantedAuthority switchAuthority = new SwitchUserGrantedAuthority(ROLE_PREVIOUS_ADMINISTRATOR,
currentAuth);
// get the original authorities
List orig = Arrays.asList(targetUser.getAuthorities());
// add the new switch user authority
List newAuths = new ArrayList(orig);
newAuths.add(switchAuthority);
GrantedAuthority[] authorities = {};
authorities = (GrantedAuthority[]) newAuths.toArray(authorities);
// create the new authentication token
targetUserRequest = new UsernamePasswordAuthenticationToken(targetUser,
targetUser.getPassword(), authorities);
// set details
targetUserRequest.setDetails(new WebAuthenticationDetails(
request));
return targetUserRequest;
}
public void destroy() {}
/**
* @see javax.servlet.Filter#doFilter
*/
public void doFilter(ServletRequest request,
ServletResponse response, FilterChain chain)
throws IOException, ServletException {
Assert.isInstanceOf(HttpServletRequest.class, request);
Assert.isInstanceOf(HttpServletResponse.class, response);
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
// check for switch or exit request
if (requiresSwitchUser(httpRequest)) {
// if set, attempt switch and store original
Authentication targetUser = attemptSwitchUser(httpRequest);
// update the current context to the new target user
SecurityContextHolder.getContext()
.setAuthentication(targetUser);
// redirect to target url
httpResponse.sendRedirect(httpResponse
.encodeRedirectURL(httpRequest
.getContextPath() + targetUrl));
return;
} else if (requiresExitUser(httpRequest)) {
// get the original authentication object (if exists)
Authentication originalUser = attemptExitUser(httpRequest);
// update the current context back to the original user
SecurityContextHolder.getContext()
.setAuthentication(originalUser);
// redirect to target url
httpResponse.sendRedirect(httpResponse
.encodeRedirectURL(httpRequest
.getContextPath()
+ targetUrl));
return;
}
chain.doFilter(request, response);
}
/**
* Find the original
* <code>Authentication</code> object from
* the current user's granted authorities.
* A successfully switched user should
* have a
* <code>SwitchUserGrantedAuthority</code>
* that contains the original source user
* <code>Authentication</code> object.
*
* @param current The current
* <code>Authentication</code>
* object
*
* @return The source user
* <code>Authentication</code>
* object or <code>null</code>
* otherwise.
*/
private Authentication getSourceAuthentication(
Authentication current) {
Authentication original = null;
// iterate over granted authorities and find the 'switch user' authority
GrantedAuthority[] authorities = current
.getAuthorities();
for (int i = 0; i < authorities.length;
i++) {
// check for switch user type of authority
if (authorities[i] instanceof SwitchUserGrantedAuthority) {
original = ((SwitchUserGrantedAuthority) authorities[i])
.getSource();
logger.debug(
"Found original switch user granted authority ["
+ original + "]");
}
}
return original;
}
public void init(FilterConfig ignored)
throws ServletException {}
/**
* Checks the request URI for the presence
* of <tt>exitUserUrl</tt>.
*
* @param request The http servlet request
*
* @return <code>true</code> if the request
* requires a exit user,
* <code>false</code> otherwise.
*
* @see SwitchUserProcessingFilter#exitUserUrl
*/
protected boolean requiresExitUser(
HttpServletRequest request) {
String uri = stripUri(request);
return uri.endsWith(request
.getContextPath() + exitUserUrl);
}
/**
* Checks the request URI for the
* presence of <tt>switchUserUrl</tt>.
*
* @param request The http servlet
* request
*
* @return <code>true</code> if the
* request requires a switch,
* <code>false</code>
* otherwise.
*
* @see SwitchUserProcessingFilter#switchUserUrl
*/
protected boolean requiresSwitchUser(
HttpServletRequest request) {
String uri = stripUri(request);
return uri.endsWith(request
.getContextPath()
+ switchUserUrl);
}
public void setApplicationEventPublisher(
ApplicationEventPublisher eventPublisher)
throws BeansException {
this.eventPublisher = eventPublisher;
}
/**
* Sets the authentication data
* access object.
*
* @param authenticationDao The
* authentication dao
*/
public void setAuthenticationDao(
AuthenticationDao authenticationDao) {
this.authenticationDao = authenticationDao;
}
/**
* Set the URL to respond to exit
* user processing.
*
* @param exitUserUrl The exit user
* URL.
*/
public void setExitUserUrl(
String exitUserUrl) {
this.exitUserUrl = exitUserUrl;
}
public void setMessageSource(
MessageSource messageSource) {
this.messages = new MessageSourceAccessor(messageSource);
}
/**
* Set the URL to respond to switch
* user processing.
*
* @param switchUserUrl The switch
* user URL.
*/
public void setSwitchUserUrl(
String switchUserUrl) {
this.switchUserUrl = switchUserUrl;
}
/**
* Sets the URL to go to after a
* successful switch / exit user
* request.
*
* @param targetUrl The target url.
*/
public void setTargetUrl(
String targetUrl) {
this.targetUrl = targetUrl;
}
/**
* Strips any content after the ';'
* in the request URI
*
* @param request The http request
*
* @return The stripped uri
*/
private static String stripUri(
HttpServletRequest request) {
String uri = request
.getRequestURI();
int idx = uri.indexOf(';');
if (idx > 0) {
uri = uri.substring(0,
idx);
}
return uri;
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -20,6 +20,12 @@ import org.acegisecurity.ConfigAttribute;
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.util.Assert;
import java.util.Iterator;
import java.util.List;
@ -32,28 +38,42 @@ import java.util.List;
* AccessDecisionVoter}s and the access control behaviour if all voters
* abstain from voting (defaults to deny access).
* </p>
*
* @author Ben Alex
* @version $Id$
*/
public abstract class AbstractAccessDecisionManager
implements AccessDecisionManager, InitializingBean {
implements AccessDecisionManager, InitializingBean, MessageSourceAware {
//~ Instance fields ========================================================
private List decisionVoters;
protected MessageSourceAccessor messages;
private boolean allowIfAllAbstainDecisions = false;
//~ Methods ================================================================
public void setAllowIfAllAbstainDecisions(
boolean allowIfAllAbstainDecisions) {
this.allowIfAllAbstainDecisions = allowIfAllAbstainDecisions;
public void afterPropertiesSet() throws Exception {
checkIfValidList(this.decisionVoters);
Assert.notNull(this.messages, "A message source must be set");
}
private void checkIfValidList(List listToCheck) {
if ((listToCheck == null) || (listToCheck.size() == 0)) {
throw new IllegalArgumentException(
"A list of AccessDecisionVoters is required");
}
}
public List getDecisionVoters() {
return this.decisionVoters;
}
public boolean isAllowIfAllAbstainDecisions() {
return allowIfAllAbstainDecisions;
}
public void setAllowIfAllAbstainDecisions(
boolean allowIfAllAbstainDecisions) {
this.allowIfAllAbstainDecisions = allowIfAllAbstainDecisions;
}
public void setDecisionVoters(List newList) {
checkIfValidList(newList);
@ -76,12 +96,8 @@ public abstract class AbstractAccessDecisionManager
this.decisionVoters = newList;
}
public List getDecisionVoters() {
return this.decisionVoters;
}
public void afterPropertiesSet() throws Exception {
checkIfValidList(this.decisionVoters);
public void setMessageSource(MessageSource messageSource) {
this.messages = new MessageSourceAccessor(messageSource);
}
public boolean supports(ConfigAttribute attribute) {
@ -124,11 +140,4 @@ public abstract class AbstractAccessDecisionManager
return true;
}
private void checkIfValidList(List listToCheck) {
if ((listToCheck == null) || (listToCheck.size() == 0)) {
throw new IllegalArgumentException(
"A list of AccessDecisionVoters is required");
}
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -29,9 +29,6 @@ import java.util.Iterator;
* Simple concrete implementation of {@link
* org.acegisecurity.AccessDecisionManager} that grants access if any
* <code>AccessDecisionVoter</code> returns an affirmative response.
*
* @author Ben Alex
* @version $Id$
*/
public class AffirmativeBased extends AbstractAccessDecisionManager {
//~ Static fields/initializers =============================================
@ -83,14 +80,18 @@ public class AffirmativeBased extends AbstractAccessDecisionManager {
}
if (deny > 0) {
throw new AccessDeniedException("Access is denied.");
throw new AccessDeniedException(messages.getMessage(
"AbstractAccessDecisionManager.accessDenied",
"Access is denied"));
}
// To get this far, every AccessDecisionVoter abstained
if (this.isAllowIfAllAbstainDecisions()) {
return;
} else {
throw new AccessDeniedException("Access is denied.");
throw new AccessDeniedException(messages.getMessage(
"AbstractAccessDecisionManager.accessDenied",
"Access is denied"));
}
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -29,9 +29,6 @@ import java.util.Iterator;
* Simple concrete implementation of {@link
* org.acegisecurity.AccessDecisionManager} that uses a consensus-based
* approach.
*
* @author Ben Alex
* @version $Id$
*/
public class ConsensusBased extends AbstractAccessDecisionManager {
//~ Static fields/initializers =============================================
@ -44,15 +41,6 @@ public class ConsensusBased extends AbstractAccessDecisionManager {
//~ Methods ================================================================
public void setAllowIfEqualGrantedDeniedDecisions(
boolean allowIfEqualGrantedDeniedDecisions) {
this.allowIfEqualGrantedDeniedDecisions = allowIfEqualGrantedDeniedDecisions;
}
public boolean isAllowIfEqualGrantedDeniedDecisions() {
return allowIfEqualGrantedDeniedDecisions;
}
/**
* This concrete implementation simply polls all configured {@link
* AccessDecisionVoter}s and upon completion determines the consensus of
@ -111,14 +99,18 @@ public class ConsensusBased extends AbstractAccessDecisionManager {
}
if (deny > grant) {
throw new AccessDeniedException("Access is denied.");
throw new AccessDeniedException(messages.getMessage(
"AbstractAccessDecisionManager.accessDenied",
"Access is denied"));
}
if ((grant == deny) && (grant != 0)) {
if (this.allowIfEqualGrantedDeniedDecisions) {
return;
} else {
throw new AccessDeniedException("Access is denied.");
throw new AccessDeniedException(messages.getMessage(
"AbstractAccessDecisionManager.accessDenied",
"Access is denied"));
}
}
@ -126,7 +118,18 @@ public class ConsensusBased extends AbstractAccessDecisionManager {
if (this.isAllowIfAllAbstainDecisions()) {
return;
} else {
throw new AccessDeniedException("Access is denied.");
throw new AccessDeniedException(messages.getMessage(
"AbstractAccessDecisionManager.accessDenied",
"Access is denied"));
}
}
public boolean isAllowIfEqualGrantedDeniedDecisions() {
return allowIfEqualGrantedDeniedDecisions;
}
public void setAllowIfEqualGrantedDeniedDecisions(
boolean allowIfEqualGrantedDeniedDecisions) {
this.allowIfEqualGrantedDeniedDecisions = allowIfEqualGrantedDeniedDecisions;
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -30,9 +30,6 @@ import java.util.Iterator;
* Simple concrete implementation of {@link
* org.acegisecurity.AccessDecisionManager} that requires all voters to
* abstain or grant access.
*
* @author Ben Alex
* @version $Id$
*/
public class UnanimousBased extends AbstractAccessDecisionManager {
//~ Static fields/initializers =============================================
@ -105,7 +102,9 @@ public class UnanimousBased extends AbstractAccessDecisionManager {
}
if (deny > 0) {
throw new AccessDeniedException("Access is denied.");
throw new AccessDeniedException(messages.getMessage(
"AbstractAccessDecisionManager.accessDenied",
"Access is denied"));
}
// To get this far, there were no deny votes
@ -117,7 +116,9 @@ public class UnanimousBased extends AbstractAccessDecisionManager {
if (this.isAllowIfAllAbstainDecisions()) {
return;
} else {
throw new AccessDeniedException("Access is denied.");
throw new AccessDeniedException(messages.getMessage(
"AbstractAccessDecisionManager.accessDenied",
"Access is denied"));
}
}
}

View File

@ -23,6 +23,7 @@ import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.GrantedAuthorityImpl;
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.springframework.context.support.StaticMessageSource;
/**
@ -81,6 +82,7 @@ public class AuthByAdapterTests extends TestCase {
public void testAuthByAdapterProviderNonAuthenticationMethods()
throws Exception {
AuthByAdapterProvider provider = new AuthByAdapterProvider();
provider.setMessageSource(new StaticMessageSource());
try {
provider.afterPropertiesSet();
@ -99,6 +101,7 @@ public class AuthByAdapterTests extends TestCase {
public void testAuthByAdapterProviderOnlyAcceptsAuthByAdapterImplementations()
throws Exception {
AuthByAdapterProvider provider = new AuthByAdapterProvider();
provider.setMessageSource(new StaticMessageSource());
provider.setKey("my_password");
// Should fail as UsernamePassword is not interface of AuthByAdapter
@ -119,6 +122,7 @@ public class AuthByAdapterTests extends TestCase {
public void testAuthByAdapterProviderRequiresCorrectKey()
throws Exception {
AuthByAdapterProvider provider = new AuthByAdapterProvider();
provider.setMessageSource(new StaticMessageSource());
provider.setKey("my_password");
// Should fail as PrincipalAcegiUserToken has different key

View File

@ -27,6 +27,7 @@ import org.acegisecurity.acl.basic.MockAclObjectIdentity;
import org.acegisecurity.acl.basic.SimpleAclEntry;
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.acegisecurity.util.SimpleMethodInvocation;
import org.springframework.context.support.StaticMessageSource;
/**
@ -65,6 +66,7 @@ public class BasicAclEntryAfterInvocationProviderTests extends TestCase {
SimpleAclEntry.ADMINISTRATION)});
BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider();
provider.setMessageSource(new StaticMessageSource());
provider.setAclManager(aclManager);
provider.afterPropertiesSet();
@ -94,6 +96,7 @@ public class BasicAclEntryAfterInvocationProviderTests extends TestCase {
new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE)});
BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider();
provider.setMessageSource(new StaticMessageSource());
provider.setAclManager(aclManager);
provider.afterPropertiesSet();
@ -123,6 +126,7 @@ public class BasicAclEntryAfterInvocationProviderTests extends TestCase {
new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE)});
BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider();
provider.setMessageSource(new StaticMessageSource());
provider.setAclManager(aclManager);
assertEquals(aclManager, provider.getAclManager());
provider.afterPropertiesSet();
@ -150,6 +154,7 @@ public class BasicAclEntryAfterInvocationProviderTests extends TestCase {
new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE), new MockAclEntry()});
BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider();
provider.setMessageSource(new StaticMessageSource());
provider.setAclManager(aclManager);
provider.afterPropertiesSet();
@ -171,6 +176,7 @@ public class BasicAclEntryAfterInvocationProviderTests extends TestCase {
new MockAclObjectIdentity(), null, SimpleAclEntry.READ), new MockAclEntry()});
BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider();
provider.setMessageSource(new StaticMessageSource());
provider.setAclManager(aclManager);
assertEquals("AFTER_ACL_READ", provider.getProcessConfigAttribute());
provider.setProcessConfigAttribute("AFTER_ACL_ADMIN");
@ -202,6 +208,7 @@ public class BasicAclEntryAfterInvocationProviderTests extends TestCase {
SimpleAclEntry.ADMINISTRATION), new MockAclEntry()});
BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider();
provider.setMessageSource(new StaticMessageSource());
provider.setAclManager(aclManager);
assertEquals(SimpleAclEntry.READ, provider.getRequirePermission()[0]);
provider.setRequirePermission(new int[] {SimpleAclEntry.ADMINISTRATION});
@ -222,6 +229,7 @@ public class BasicAclEntryAfterInvocationProviderTests extends TestCase {
public void testStartupDetectsMissingAclManager() throws Exception {
BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider();
provider.setMessageSource(new StaticMessageSource());
try {
provider.afterPropertiesSet();
@ -234,6 +242,7 @@ public class BasicAclEntryAfterInvocationProviderTests extends TestCase {
public void testStartupDetectsMissingProcessConfigAttribute()
throws Exception {
BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider();
provider.setMessageSource(new StaticMessageSource());
AclManager aclManager = new MockAclManager("sydney", "marissa",
new AclEntry[] {new SimpleAclEntry("marissa",
new MockAclObjectIdentity(), null,
@ -254,6 +263,7 @@ public class BasicAclEntryAfterInvocationProviderTests extends TestCase {
public void testStartupDetectsMissingRequirePermission()
throws Exception {
BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider();
provider.setMessageSource(new StaticMessageSource());
AclManager aclManager = new MockAclManager("sydney", "marissa",
new AclEntry[] {new SimpleAclEntry("marissa",
new MockAclObjectIdentity(), null,

View File

@ -21,6 +21,7 @@ import org.acegisecurity.Authentication;
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.acegisecurity.ui.WebAuthenticationDetails;
import org.springframework.context.support.StaticMessageSource;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpSession;
@ -39,6 +40,7 @@ public class ConcurrentSessionControllerImplTests extends TestCase {
ConcurrentSessionControllerImpl sc = new ConcurrentSessionControllerImpl();
SessionRegistry registry = new SessionRegistryImpl();
sc.setSessionRegistry(registry);
sc.setMessageSource(new StaticMessageSource());
// Attempt to authenticate - it should be successful
Authentication auth = createAuthentication("bob", "1212");

View File

@ -41,6 +41,7 @@ import org.acegisecurity.runas.RunAsManagerImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.StaticMessageSource;
import java.lang.reflect.Method;
@ -177,6 +178,7 @@ public class MethodSecurityInterceptorTests extends TestCase {
public void testRejectsAccessDecisionManagersThatDoNotSupportMethodInvocation()
throws Exception {
MethodSecurityInterceptor si = new MethodSecurityInterceptor();
si.setMessageSource(new StaticMessageSource());
si.setAccessDecisionManager(new MockAccessDecisionManagerWhichOnlySupportsStrings());
si.setAuthenticationManager(new MockAuthenticationManager());
si.setObjectDefinitionSource(new MockMethodDefinitionSource(false, true));
@ -212,6 +214,7 @@ public class MethodSecurityInterceptorTests extends TestCase {
public void testRejectsCallsWhenObjectDefinitionSourceDoesNotSupportObject()
throws Throwable {
MethodSecurityInterceptor interceptor = new MethodSecurityInterceptor();
interceptor.setMessageSource(new StaticMessageSource());
interceptor.setObjectDefinitionSource(new MockObjectDefinitionSourceWhichOnlySupportsStrings());
interceptor.setAccessDecisionManager(new MockAccessDecisionManager());
interceptor.setAuthenticationManager(new MockAuthenticationManager());
@ -228,6 +231,7 @@ public class MethodSecurityInterceptorTests extends TestCase {
public void testRejectsCallsWhenObjectIsNull() throws Throwable {
MethodSecurityInterceptor interceptor = new MethodSecurityInterceptor();
interceptor.setMessageSource(new StaticMessageSource());
try {
interceptor.invoke(null);
@ -240,6 +244,7 @@ public class MethodSecurityInterceptorTests extends TestCase {
public void testRejectsRunAsManagersThatDoNotSupportMethodInvocation()
throws Exception {
MethodSecurityInterceptor si = new MethodSecurityInterceptor();
si.setMessageSource(new StaticMessageSource());
si.setAccessDecisionManager(new MockAccessDecisionManager());
si.setAuthenticationManager(new MockAuthenticationManager());
si.setObjectDefinitionSource(new MockMethodDefinitionSource(false, true));
@ -258,6 +263,7 @@ public class MethodSecurityInterceptorTests extends TestCase {
public void testStartupCheckForAccessDecisionManager()
throws Exception {
MethodSecurityInterceptor si = new MethodSecurityInterceptor();
si.setMessageSource(new StaticMessageSource());
si.setRunAsManager(new MockRunAsManager());
si.setAuthenticationManager(new MockAuthenticationManager());
si.setAfterInvocationManager(new MockAfterInvocationManager());
@ -276,6 +282,7 @@ public class MethodSecurityInterceptorTests extends TestCase {
public void testStartupCheckForAuthenticationManager()
throws Exception {
MethodSecurityInterceptor si = new MethodSecurityInterceptor();
si.setMessageSource(new StaticMessageSource());
si.setAccessDecisionManager(new MockAccessDecisionManager());
si.setRunAsManager(new MockRunAsManager());
si.setAfterInvocationManager(new MockAfterInvocationManager());
@ -294,6 +301,7 @@ public class MethodSecurityInterceptorTests extends TestCase {
public void testStartupCheckForMethodDefinitionSource()
throws Exception {
MethodSecurityInterceptor si = new MethodSecurityInterceptor();
si.setMessageSource(new StaticMessageSource());
si.setAccessDecisionManager(new MockAccessDecisionManager());
si.setAuthenticationManager(new MockAuthenticationManager());
@ -308,6 +316,7 @@ public class MethodSecurityInterceptorTests extends TestCase {
public void testStartupCheckForRunAsManager() throws Exception {
MethodSecurityInterceptor si = new MethodSecurityInterceptor();
si.setMessageSource(new StaticMessageSource());
si.setAccessDecisionManager(new MockAccessDecisionManager());
si.setAuthenticationManager(new MockAuthenticationManager());
si.setRunAsManager(null); // Overriding the default
@ -325,6 +334,7 @@ public class MethodSecurityInterceptorTests extends TestCase {
public void testStartupCheckForValidAfterInvocationManager()
throws Exception {
MethodSecurityInterceptor si = new MethodSecurityInterceptor();
si.setMessageSource(new StaticMessageSource());
si.setRunAsManager(new MockRunAsManager());
si.setAuthenticationManager(new MockAuthenticationManager());
si.setAfterInvocationManager(new MockAfterInvocationManagerWhichOnlySupportsStrings());
@ -342,6 +352,7 @@ public class MethodSecurityInterceptorTests extends TestCase {
public void testValidationFailsIfInvalidAttributePresented()
throws Exception {
MethodSecurityInterceptor si = new MethodSecurityInterceptor();
si.setMessageSource(new StaticMessageSource());
si.setAccessDecisionManager(new MockAccessDecisionManager());
si.setAuthenticationManager(new MockAuthenticationManager());
si.setRunAsManager(new RunAsManagerImpl());
@ -361,6 +372,7 @@ public class MethodSecurityInterceptorTests extends TestCase {
public void testValidationNotAttemptedIfIsValidateConfigAttributesSetToFalse()
throws Exception {
MethodSecurityInterceptor si = new MethodSecurityInterceptor();
si.setMessageSource(new StaticMessageSource());
si.setAccessDecisionManager(new MockAccessDecisionManager());
si.setAuthenticationManager(new MockAuthenticationManager());
@ -376,6 +388,7 @@ public class MethodSecurityInterceptorTests extends TestCase {
public void testValidationNotAttemptedIfMethodDefinitionSourceCannotReturnIterator()
throws Exception {
MethodSecurityInterceptor si = new MethodSecurityInterceptor();
si.setMessageSource(new StaticMessageSource());
si.setAccessDecisionManager(new MockAccessDecisionManager());
si.setRunAsManager(new MockRunAsManager());
si.setAuthenticationManager(new MockAuthenticationManager());

View File

@ -30,6 +30,7 @@ import org.acegisecurity.context.SecurityContextHolder;
import org.acegisecurity.intercept.method.MethodDefinitionMap;
import org.acegisecurity.intercept.method.MethodDefinitionSourceEditor;
import org.acegisecurity.providers.TestingAuthenticationToken;
import org.springframework.context.support.StaticMessageSource;
import java.lang.reflect.Method;
@ -64,6 +65,7 @@ public class AspectJSecurityInterceptorTests extends TestCase {
public void testCallbackIsInvokedWhenPermissionGranted()
throws Exception {
AspectJSecurityInterceptor si = new AspectJSecurityInterceptor();
si.setMessageSource(new StaticMessageSource());
si.setApplicationEventPublisher(MockApplicationContext.getContext());
si.setAccessDecisionManager(new MockAccessDecisionManager());
si.setAuthenticationManager(new MockAuthenticationManager());
@ -100,6 +102,7 @@ public class AspectJSecurityInterceptorTests extends TestCase {
public void testCallbackIsNotInvokedWhenPermissionDenied()
throws Exception {
AspectJSecurityInterceptor si = new AspectJSecurityInterceptor();
si.setMessageSource(new StaticMessageSource());
si.setApplicationEventPublisher(MockApplicationContext.getContext());
si.setAccessDecisionManager(new MockAccessDecisionManager());
si.setAuthenticationManager(new MockAuthenticationManager());

View File

@ -34,6 +34,7 @@ import org.acegisecurity.context.SecurityContextHolder;
import org.acegisecurity.context.SecurityContextImpl;
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.springframework.context.support.StaticMessageSource;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
@ -77,6 +78,7 @@ public class FilterSecurityInterceptorTests extends TestCase {
public void testEnsuresAccessDecisionManagerSupportsFilterInvocationClass()
throws Exception {
FilterSecurityInterceptor interceptor = new FilterSecurityInterceptor();
interceptor.setMessageSource(new StaticMessageSource());
interceptor.setAuthenticationManager(new MockAuthenticationManager());
interceptor.setObjectDefinitionSource(new RegExpBasedFilterInvocationDefinitionMap());
interceptor.setRunAsManager(new MockRunAsManager());
@ -110,6 +112,7 @@ public class FilterSecurityInterceptorTests extends TestCase {
public void testEnsuresRunAsManagerSupportsFilterInvocationClass()
throws Exception {
FilterSecurityInterceptor interceptor = new FilterSecurityInterceptor();
interceptor.setMessageSource(new StaticMessageSource());
interceptor.setAccessDecisionManager(new MockAccessDecisionManager());
interceptor.setAuthenticationManager(new MockAuthenticationManager());
interceptor.setObjectDefinitionSource(new RegExpBasedFilterInvocationDefinitionMap());
@ -144,6 +147,7 @@ public class FilterSecurityInterceptorTests extends TestCase {
throws Throwable {
// Setup the FilterSecurityInterceptor
FilterSecurityInterceptor interceptor = new FilterSecurityInterceptor();
interceptor.setMessageSource(new StaticMessageSource());
interceptor.setAccessDecisionManager(new MockAccessDecisionManager());
interceptor.setAuthenticationManager(new MockAuthenticationManager());
interceptor.setRunAsManager(new MockRunAsManager());
@ -183,6 +187,7 @@ public class FilterSecurityInterceptorTests extends TestCase {
public void testNormalStartupAndGetter() throws Exception {
FilterSecurityInterceptor interceptor = new FilterSecurityInterceptor();
interceptor.setMessageSource(new StaticMessageSource());
interceptor.setAccessDecisionManager(new MockAccessDecisionManager());
interceptor.setAuthenticationManager(new MockAuthenticationManager());
@ -203,6 +208,7 @@ public class FilterSecurityInterceptorTests extends TestCase {
public void testSuccessfulInvocation() throws Throwable {
// Setup the FilterSecurityInterceptor
FilterSecurityInterceptor interceptor = new FilterSecurityInterceptor();
interceptor.setMessageSource(new StaticMessageSource());
interceptor.setAccessDecisionManager(new MockAccessDecisionManager());
interceptor.setAuthenticationManager(new MockAuthenticationManager());
interceptor.setRunAsManager(new MockRunAsManager());

View File

@ -29,6 +29,7 @@ import org.acegisecurity.concurrent.NullConcurrentSessionController;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.support.StaticMessageSource;
/**
@ -182,8 +183,8 @@ public class ProviderManagerTests extends TestCase {
ProviderManager mgr = new ProviderManager();
mgr.setProviders(providers);
mgr.setMessageSource(new StaticMessageSource());
mgr.afterPropertiesSet();
return mgr;
}

View File

@ -22,6 +22,7 @@ import org.acegisecurity.BadCredentialsException;
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.GrantedAuthorityImpl;
import org.acegisecurity.providers.TestingAuthenticationToken;
import org.springframework.context.support.StaticMessageSource;
/**
@ -53,6 +54,7 @@ public class AnonymousAuthenticationProviderTests extends TestCase {
public void testDetectsAnInvalidKey() throws Exception {
AnonymousAuthenticationProvider aap = new AnonymousAuthenticationProvider();
aap.setMessageSource(new StaticMessageSource());
aap.setKey("qwerty");
AnonymousAuthenticationToken token = new AnonymousAuthenticationToken("WRONG_KEY",
@ -71,6 +73,7 @@ public class AnonymousAuthenticationProviderTests extends TestCase {
public void testDetectsMissingKey() throws Exception {
AnonymousAuthenticationProvider aap = new AnonymousAuthenticationProvider();
aap.setMessageSource(new StaticMessageSource());
try {
aap.afterPropertiesSet();
@ -82,6 +85,7 @@ public class AnonymousAuthenticationProviderTests extends TestCase {
public void testGettersSetters() throws Exception {
AnonymousAuthenticationProvider aap = new AnonymousAuthenticationProvider();
aap.setMessageSource(new StaticMessageSource());
aap.setKey("qwerty");
aap.afterPropertiesSet();
assertEquals("qwerty", aap.getKey());
@ -89,6 +93,7 @@ public class AnonymousAuthenticationProviderTests extends TestCase {
public void testIgnoresClassesItDoesNotSupport() throws Exception {
AnonymousAuthenticationProvider aap = new AnonymousAuthenticationProvider();
aap.setMessageSource(new StaticMessageSource());
aap.setKey("qwerty");
TestingAuthenticationToken token = new TestingAuthenticationToken("user",
@ -102,6 +107,7 @@ public class AnonymousAuthenticationProviderTests extends TestCase {
public void testNormalOperation() throws Exception {
AnonymousAuthenticationProvider aap = new AnonymousAuthenticationProvider();
aap.setMessageSource(new StaticMessageSource());
aap.setKey("qwerty");
AnonymousAuthenticationToken token = new AnonymousAuthenticationToken("qwerty",
@ -116,6 +122,7 @@ public class AnonymousAuthenticationProviderTests extends TestCase {
public void testSupports() {
AnonymousAuthenticationProvider aap = new AnonymousAuthenticationProvider();
aap.setMessageSource(new StaticMessageSource());
assertTrue(aap.supports(AnonymousAuthenticationToken.class));
assertFalse(aap.supports(TestingAuthenticationToken.class));
}

View File

@ -28,6 +28,7 @@ import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.acegisecurity.providers.cas.ticketvalidator.AbstractTicketValidator;
import org.acegisecurity.providers.dao.User;
import org.acegisecurity.ui.cas.CasProcessingFilter;
import org.springframework.context.support.StaticMessageSource;
import java.util.HashMap;
import java.util.List;
@ -64,6 +65,7 @@ public class CasAuthenticationProviderTests extends TestCase {
public void testAuthenticateStateful() throws Exception {
CasAuthenticationProvider cap = new CasAuthenticationProvider();
cap.setMessageSource(new StaticMessageSource());
cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator());
cap.setCasProxyDecider(new MockProxyDecider(true));
cap.setKey("qwerty");
@ -108,6 +110,7 @@ public class CasAuthenticationProviderTests extends TestCase {
public void testAuthenticateStateless() throws Exception {
CasAuthenticationProvider cap = new CasAuthenticationProvider();
cap.setMessageSource(new StaticMessageSource());
cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator());
cap.setCasProxyDecider(new MockProxyDecider(true));
cap.setKey("qwerty");
@ -144,6 +147,7 @@ public class CasAuthenticationProviderTests extends TestCase {
public void testDetectsAMissingTicketId() throws Exception {
CasAuthenticationProvider cap = new CasAuthenticationProvider();
cap.setMessageSource(new StaticMessageSource());
cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator());
cap.setCasProxyDecider(new MockProxyDecider(true));
cap.setKey("qwerty");
@ -167,6 +171,7 @@ public class CasAuthenticationProviderTests extends TestCase {
public void testDetectsAnInvalidKey() throws Exception {
CasAuthenticationProvider cap = new CasAuthenticationProvider();
cap.setMessageSource(new StaticMessageSource());
cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator());
cap.setCasProxyDecider(new MockProxyDecider(true));
cap.setKey("qwerty");
@ -193,6 +198,7 @@ public class CasAuthenticationProviderTests extends TestCase {
public void testDetectsMissingAuthoritiesPopulator()
throws Exception {
CasAuthenticationProvider cap = new CasAuthenticationProvider();
cap.setMessageSource(new StaticMessageSource());
cap.setCasProxyDecider(new MockProxyDecider());
cap.setKey("qwerty");
cap.setStatelessTicketCache(new MockStatelessTicketCache());
@ -209,6 +215,7 @@ public class CasAuthenticationProviderTests extends TestCase {
public void testDetectsMissingKey() throws Exception {
CasAuthenticationProvider cap = new CasAuthenticationProvider();
cap.setMessageSource(new StaticMessageSource());
cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator());
cap.setCasProxyDecider(new MockProxyDecider());
cap.setStatelessTicketCache(new MockStatelessTicketCache());
@ -225,6 +232,7 @@ public class CasAuthenticationProviderTests extends TestCase {
public void testDetectsMissingProxyDecider() throws Exception {
CasAuthenticationProvider cap = new CasAuthenticationProvider();
cap.setMessageSource(new StaticMessageSource());
cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator());
cap.setKey("qwerty");
cap.setStatelessTicketCache(new MockStatelessTicketCache());
@ -241,6 +249,7 @@ public class CasAuthenticationProviderTests extends TestCase {
public void testDetectsMissingStatelessTicketCache()
throws Exception {
CasAuthenticationProvider cap = new CasAuthenticationProvider();
cap.setMessageSource(new StaticMessageSource());
cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator());
cap.setCasProxyDecider(new MockProxyDecider());
cap.setKey("qwerty");
@ -257,6 +266,7 @@ public class CasAuthenticationProviderTests extends TestCase {
public void testDetectsMissingTicketValidator() throws Exception {
CasAuthenticationProvider cap = new CasAuthenticationProvider();
cap.setMessageSource(new StaticMessageSource());
cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator());
cap.setCasProxyDecider(new MockProxyDecider(true));
cap.setKey("qwerty");
@ -272,6 +282,7 @@ public class CasAuthenticationProviderTests extends TestCase {
public void testGettersSetters() throws Exception {
CasAuthenticationProvider cap = new CasAuthenticationProvider();
cap.setMessageSource(new StaticMessageSource());
cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator());
cap.setCasProxyDecider(new MockProxyDecider());
cap.setKey("qwerty");
@ -288,6 +299,7 @@ public class CasAuthenticationProviderTests extends TestCase {
public void testIgnoresClassesItDoesNotSupport() throws Exception {
CasAuthenticationProvider cap = new CasAuthenticationProvider();
cap.setMessageSource(new StaticMessageSource());
cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator());
cap.setCasProxyDecider(new MockProxyDecider());
cap.setKey("qwerty");
@ -307,6 +319,7 @@ public class CasAuthenticationProviderTests extends TestCase {
public void testIgnoresUsernamePasswordAuthenticationTokensWithoutCasIdentifiersAsPrincipal()
throws Exception {
CasAuthenticationProvider cap = new CasAuthenticationProvider();
cap.setMessageSource(new StaticMessageSource());
cap.setCasAuthoritiesPopulator(new MockAuthoritiesPopulator());
cap.setCasProxyDecider(new MockProxyDecider());
cap.setKey("qwerty");
@ -322,6 +335,7 @@ public class CasAuthenticationProviderTests extends TestCase {
public void testSupports() {
CasAuthenticationProvider cap = new CasAuthenticationProvider();
cap.setMessageSource(new StaticMessageSource());
assertTrue(cap.supports(UsernamePasswordAuthenticationToken.class));
assertTrue(cap.supports(CasAuthenticationToken.class));
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -19,15 +19,14 @@ import junit.framework.TestCase;
import org.acegisecurity.providers.cas.ProxyUntrustedException;
import org.springframework.context.support.StaticMessageSource;
import java.util.List;
import java.util.Vector;
/**
* Tests {@link NamedCasProxyDecider}.
*
* @author Ben Alex
* @version $Id$
*/
public class NamedCasProxyDeciderTests extends TestCase {
//~ Constructors ===========================================================
@ -42,17 +41,18 @@ public class NamedCasProxyDeciderTests extends TestCase {
//~ Methods ================================================================
public final void setUp() throws Exception {
super.setUp();
}
public static void main(String[] args) {
junit.textui.TestRunner.run(NamedCasProxyDeciderTests.class);
}
public final void setUp() throws Exception {
super.setUp();
}
public void testAcceptsIfNearestProxyIsAuthorized()
throws Exception {
NamedCasProxyDecider proxyDecider = new NamedCasProxyDecider();
proxyDecider.setMessageSource(new StaticMessageSource());
// Build the ticket returned from CAS
List proxyList = new Vector();
@ -72,6 +72,8 @@ public class NamedCasProxyDeciderTests extends TestCase {
public void testAcceptsIfNoProxiesInTicket() {
NamedCasProxyDecider proxyDecider = new NamedCasProxyDecider();
proxyDecider.setMessageSource(new StaticMessageSource());
List proxyList = new Vector(); // no proxies in list
proxyDecider.confirmProxyListTrusted(proxyList);
@ -80,6 +82,7 @@ public class NamedCasProxyDeciderTests extends TestCase {
public void testDetectsMissingValidProxiesList() throws Exception {
NamedCasProxyDecider proxyDecider = new NamedCasProxyDecider();
proxyDecider.setMessageSource(new StaticMessageSource());
try {
proxyDecider.afterPropertiesSet();
@ -92,6 +95,7 @@ public class NamedCasProxyDeciderTests extends TestCase {
public void testDoesNotAcceptNull() {
NamedCasProxyDecider proxyDecider = new NamedCasProxyDecider();
proxyDecider.setMessageSource(new StaticMessageSource());
try {
proxyDecider.confirmProxyListTrusted(null);
@ -103,6 +107,7 @@ public class NamedCasProxyDeciderTests extends TestCase {
public void testGettersSetters() {
NamedCasProxyDecider proxyDecider = new NamedCasProxyDecider();
proxyDecider.setMessageSource(new StaticMessageSource());
// Build the list of valid nearest proxies
List validProxies = new Vector();
@ -117,6 +122,7 @@ public class NamedCasProxyDeciderTests extends TestCase {
public void testRejectsIfNearestProxyIsNotAuthorized()
throws Exception {
NamedCasProxyDecider proxyDecider = new NamedCasProxyDecider();
proxyDecider.setMessageSource(new StaticMessageSource());
// Build the ticket returned from CAS
List proxyList = new Vector();

View File

@ -18,6 +18,7 @@ package org.acegisecurity.providers.cas.proxy;
import junit.framework.TestCase;
import org.acegisecurity.providers.cas.ProxyUntrustedException;
import org.springframework.context.support.StaticMessageSource;
import java.util.List;
import java.util.Vector;
@ -71,6 +72,7 @@ public class RejectProxyTicketsTests extends TestCase {
public void testRejectsIfAnyProxyInList() {
RejectProxyTickets proxyDecider = new RejectProxyTickets();
proxyDecider.setMessageSource(new StaticMessageSource());
List proxyList = new Vector();
proxyList.add("https://localhost/webApp/j_acegi_cas_security_check");

View File

@ -34,6 +34,7 @@ import org.acegisecurity.providers.dao.cache.NullUserCache;
import org.acegisecurity.providers.dao.salt.SystemWideSaltSource;
import org.acegisecurity.providers.encoding.ShaPasswordEncoder;
import org.springframework.context.support.StaticMessageSource;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataRetrievalFailureException;
@ -63,6 +64,7 @@ public class DaoAuthenticationProviderTests extends TestCase {
"KOala");
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setMessageSource(new StaticMessageSource());
provider.setAuthenticationDao(new MockAuthenticationDaoUserMarissa());
provider.setUserCache(new MockUserCache());
@ -79,6 +81,7 @@ public class DaoAuthenticationProviderTests extends TestCase {
"opal");
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setMessageSource(new StaticMessageSource());
provider.setAuthenticationDao(new MockAuthenticationDaoUserPeterAccountExpired());
provider.setUserCache(new MockUserCache());
@ -95,6 +98,7 @@ public class DaoAuthenticationProviderTests extends TestCase {
"opal");
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setMessageSource(new StaticMessageSource());
provider.setAuthenticationDao(new MockAuthenticationDaoUserPeterAccountLocked());
provider.setUserCache(new MockUserCache());
@ -111,6 +115,7 @@ public class DaoAuthenticationProviderTests extends TestCase {
"opal");
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setMessageSource(new StaticMessageSource());
provider.setAuthenticationDao(new MockAuthenticationDaoUserPeterCredentialsExpired());
provider.setUserCache(new MockUserCache());
@ -138,6 +143,7 @@ public class DaoAuthenticationProviderTests extends TestCase {
"opal");
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setMessageSource(new StaticMessageSource());
provider.setAuthenticationDao(new MockAuthenticationDaoUserPeter());
provider.setUserCache(new MockUserCache());
@ -154,6 +160,7 @@ public class DaoAuthenticationProviderTests extends TestCase {
"koala");
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setMessageSource(new StaticMessageSource());
provider.setAuthenticationDao(new MockAuthenticationDaoSimulateBackendError());
provider.setUserCache(new MockUserCache());
@ -170,6 +177,7 @@ public class DaoAuthenticationProviderTests extends TestCase {
"koala");
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setMessageSource(new StaticMessageSource());
provider.setAuthenticationDao(new MockAuthenticationDaoUserMarissa());
provider.setUserCache(new MockUserCache());
@ -186,6 +194,7 @@ public class DaoAuthenticationProviderTests extends TestCase {
"INVALID_PASSWORD");
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setMessageSource(new StaticMessageSource());
provider.setAuthenticationDao(new MockAuthenticationDaoUserMarissa());
provider.setUserCache(new MockUserCache());
@ -202,6 +211,7 @@ public class DaoAuthenticationProviderTests extends TestCase {
"koala");
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setMessageSource(new StaticMessageSource());
provider.setHideUserNotFoundExceptions(false); // we want UsernameNotFoundExceptions
provider.setAuthenticationDao(new MockAuthenticationDaoUserMarissa());
provider.setUserCache(new MockUserCache());
@ -219,6 +229,7 @@ public class DaoAuthenticationProviderTests extends TestCase {
"koala");
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setMessageSource(new StaticMessageSource());
assertTrue(provider.isHideUserNotFoundExceptions());
provider.setAuthenticationDao(new MockAuthenticationDaoUserMarissa());
provider.setUserCache(new MockUserCache());
@ -236,6 +247,7 @@ public class DaoAuthenticationProviderTests extends TestCase {
"koala");
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setMessageSource(new StaticMessageSource());
provider.setAuthenticationDao(new MockAuthenticationDaoUserMarissa());
provider.setUserCache(new MockUserCache());
@ -253,6 +265,7 @@ public class DaoAuthenticationProviderTests extends TestCase {
token.setDetails("192.168.0.1");
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setMessageSource(new StaticMessageSource());
provider.setAuthenticationDao(new MockAuthenticationDaoUserMarissa());
provider.setUserCache(new MockUserCache());
@ -276,6 +289,7 @@ public class DaoAuthenticationProviderTests extends TestCase {
"koala");
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setMessageSource(new StaticMessageSource());
provider.setAuthenticationDao(new MockAuthenticationDaoUserMarissa());
provider.setUserCache(new MockUserCache());
@ -305,6 +319,7 @@ public class DaoAuthenticationProviderTests extends TestCase {
salt.setSystemWideSalt("SYSTEM_SALT_VALUE");
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setMessageSource(new StaticMessageSource());
provider.setAuthenticationDao(new MockAuthenticationDaoUserMarissaWithSalt());
provider.setSaltSource(salt);
provider.setUserCache(new MockUserCache());
@ -330,6 +345,7 @@ public class DaoAuthenticationProviderTests extends TestCase {
"koala");
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setMessageSource(new StaticMessageSource());
provider.setAuthenticationDao(new MockAuthenticationDaoUserMarissa());
provider.setUserCache(new MockUserCache());
provider.setForcePrincipalAsString(true);
@ -351,6 +367,7 @@ public class DaoAuthenticationProviderTests extends TestCase {
"koala");
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setMessageSource(new StaticMessageSource());
provider.setAuthenticationDao(new MockAuthenticationDaoReturnsNull());
try {
@ -364,6 +381,7 @@ public class DaoAuthenticationProviderTests extends TestCase {
public void testGettersSetters() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setMessageSource(new StaticMessageSource());
provider.setPasswordEncoder(new ShaPasswordEncoder());
assertEquals(ShaPasswordEncoder.class,
provider.getPasswordEncoder().getClass());
@ -388,6 +406,7 @@ public class DaoAuthenticationProviderTests extends TestCase {
MockAuthenticationDaoUserMarissa authenticationDao = new MockAuthenticationDaoUserMarissa();
MockUserCache cache = new MockUserCache();
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setMessageSource(new StaticMessageSource());
provider.setAuthenticationDao(authenticationDao);
provider.setUserCache(cache);
@ -414,6 +433,7 @@ public class DaoAuthenticationProviderTests extends TestCase {
public void testStartupFailsIfNoAuthenticationDao()
throws Exception {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setMessageSource(new StaticMessageSource());
try {
provider.afterPropertiesSet();
@ -425,6 +445,7 @@ public class DaoAuthenticationProviderTests extends TestCase {
public void testStartupFailsIfNoUserCacheSet() throws Exception {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setMessageSource(new StaticMessageSource());
provider.setAuthenticationDao(new MockAuthenticationDaoUserMarissa());
assertEquals(NullUserCache.class, provider.getUserCache().getClass());
provider.setUserCache(null);
@ -439,6 +460,7 @@ public class DaoAuthenticationProviderTests extends TestCase {
public void testStartupSuccess() throws Exception {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setMessageSource(new StaticMessageSource());
AuthenticationDao dao = new MockAuthenticationDaoUserMarissa();
provider.setAuthenticationDao(dao);
provider.setUserCache(new MockUserCache());
@ -449,6 +471,7 @@ public class DaoAuthenticationProviderTests extends TestCase {
public void testSupports() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setMessageSource(new StaticMessageSource());
assertTrue(provider.supports(UsernamePasswordAuthenticationToken.class));
assertTrue(!provider.supports(TestingAuthenticationToken.class));
}

View File

@ -22,6 +22,7 @@ import org.acegisecurity.BadCredentialsException;
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.GrantedAuthorityImpl;
import org.acegisecurity.providers.TestingAuthenticationToken;
import org.springframework.context.support.StaticMessageSource;
/**
@ -53,6 +54,7 @@ public class RememberMeAuthenticationProviderTests extends TestCase {
public void testDetectsAnInvalidKey() throws Exception {
RememberMeAuthenticationProvider aap = new RememberMeAuthenticationProvider();
aap.setMessageSource(new StaticMessageSource());
aap.setKey("qwerty");
RememberMeAuthenticationToken token = new RememberMeAuthenticationToken("WRONG_KEY",
@ -71,6 +73,7 @@ public class RememberMeAuthenticationProviderTests extends TestCase {
public void testDetectsMissingKey() throws Exception {
RememberMeAuthenticationProvider aap = new RememberMeAuthenticationProvider();
aap.setMessageSource(new StaticMessageSource());
try {
aap.afterPropertiesSet();
@ -82,6 +85,7 @@ public class RememberMeAuthenticationProviderTests extends TestCase {
public void testGettersSetters() throws Exception {
RememberMeAuthenticationProvider aap = new RememberMeAuthenticationProvider();
aap.setMessageSource(new StaticMessageSource());
aap.setKey("qwerty");
aap.afterPropertiesSet();
assertEquals("qwerty", aap.getKey());
@ -102,6 +106,7 @@ public class RememberMeAuthenticationProviderTests extends TestCase {
public void testNormalOperation() throws Exception {
RememberMeAuthenticationProvider aap = new RememberMeAuthenticationProvider();
aap.setMessageSource(new StaticMessageSource());
aap.setKey("qwerty");
RememberMeAuthenticationToken token = new RememberMeAuthenticationToken("qwerty",
@ -116,6 +121,7 @@ public class RememberMeAuthenticationProviderTests extends TestCase {
public void testSupports() {
RememberMeAuthenticationProvider aap = new RememberMeAuthenticationProvider();
aap.setMessageSource(new StaticMessageSource());
assertTrue(aap.supports(RememberMeAuthenticationToken.class));
assertFalse(aap.supports(TestingAuthenticationToken.class));
}

View File

@ -20,6 +20,7 @@ import junit.framework.TestCase;
import org.acegisecurity.*;
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.acegisecurity.providers.dao.User;
import org.springframework.context.support.StaticMessageSource;
import java.security.cert.X509Certificate;
@ -49,6 +50,7 @@ public class X509AuthenticationProviderTests extends TestCase {
public void testAuthenticationIsNullWithUnsupportedToken() {
X509AuthenticationProvider provider = new X509AuthenticationProvider();
provider.setMessageSource(new StaticMessageSource());
Authentication request = new UsernamePasswordAuthenticationToken("dummy",
"dummy");
Authentication result = provider.authenticate(request);
@ -57,6 +59,7 @@ public class X509AuthenticationProviderTests extends TestCase {
public void testFailsWithNullCertificate() {
X509AuthenticationProvider provider = new X509AuthenticationProvider();
provider.setMessageSource(new StaticMessageSource());
provider.setX509AuthoritiesPopulator(new MockAuthoritiesPopulator(false));
@ -70,6 +73,7 @@ public class X509AuthenticationProviderTests extends TestCase {
public void testNormalOperation() throws Exception {
X509AuthenticationProvider provider = new X509AuthenticationProvider();
provider.setMessageSource(new StaticMessageSource());
provider.setX509AuthoritiesPopulator(new MockAuthoritiesPopulator(false));
provider.afterPropertiesSet();
@ -82,6 +86,7 @@ public class X509AuthenticationProviderTests extends TestCase {
public void testPopulatorRejectionCausesFailure() throws Exception {
X509AuthenticationProvider provider = new X509AuthenticationProvider();
provider.setMessageSource(new StaticMessageSource());
provider.setX509AuthoritiesPopulator(new MockAuthoritiesPopulator(true));
try {
@ -94,6 +99,7 @@ public class X509AuthenticationProviderTests extends TestCase {
public void testRequiresPopulator() throws Exception {
X509AuthenticationProvider provider = new X509AuthenticationProvider();
provider.setMessageSource(new StaticMessageSource());
try {
provider.afterPropertiesSet();

View File

@ -26,6 +26,7 @@ import org.acegisecurity.providers.dao.User;
import org.acegisecurity.providers.dao.UsernameNotFoundException;
import org.acegisecurity.providers.x509.X509TestUtils;
import org.springframework.context.support.StaticMessageSource;
import org.springframework.dao.DataAccessException;
import java.security.cert.X509Certificate;
@ -56,6 +57,7 @@ public class DaoX509AuthoritiesPopulatorTests extends TestCase {
public void testDefaultCNPatternMatch() throws Exception {
X509Certificate cert = X509TestUtils.buildTestCertificate();
DaoX509AuthoritiesPopulator populator = new DaoX509AuthoritiesPopulator();
populator.setMessageSource(new StaticMessageSource());
populator.setAuthenticationDao(new MockAuthenticationDaoMatchesNameOrEmail());
populator.afterPropertiesSet();
@ -65,6 +67,7 @@ public class DaoX509AuthoritiesPopulatorTests extends TestCase {
public void testEmailPatternMatch() throws Exception {
X509Certificate cert = X509TestUtils.buildTestCertificate();
DaoX509AuthoritiesPopulator populator = new DaoX509AuthoritiesPopulator();
populator.setMessageSource(new StaticMessageSource());
populator.setAuthenticationDao(new MockAuthenticationDaoMatchesNameOrEmail());
populator.setSubjectDNRegex("emailAddress=(.*?),");
@ -74,6 +77,7 @@ public class DaoX509AuthoritiesPopulatorTests extends TestCase {
public void testInvalidRegexFails() throws Exception {
DaoX509AuthoritiesPopulator populator = new DaoX509AuthoritiesPopulator();
populator.setMessageSource(new StaticMessageSource());
populator.setAuthenticationDao(new MockAuthenticationDaoMatchesNameOrEmail());
populator.setSubjectDNRegex("CN=(.*?,"); // missing closing bracket on group
@ -88,6 +92,7 @@ public class DaoX509AuthoritiesPopulatorTests extends TestCase {
public void testMatchOnShoeSizeFieldInDNFails() throws Exception {
X509Certificate cert = X509TestUtils.buildTestCertificate();
DaoX509AuthoritiesPopulator populator = new DaoX509AuthoritiesPopulator();
populator.setMessageSource(new StaticMessageSource());
populator.setAuthenticationDao(new MockAuthenticationDaoMatchesNameOrEmail());
populator.setSubjectDNRegex("shoeSize=(.*?),");
@ -104,6 +109,7 @@ public class DaoX509AuthoritiesPopulatorTests extends TestCase {
public void testPatternWithNoGroupFails() throws Exception {
X509Certificate cert = X509TestUtils.buildTestCertificate();
DaoX509AuthoritiesPopulator populator = new DaoX509AuthoritiesPopulator();
populator.setMessageSource(new StaticMessageSource());
populator.setAuthenticationDao(new MockAuthenticationDaoMatchesNameOrEmail());
populator.setSubjectDNRegex("CN=.*?,");
@ -120,6 +126,7 @@ public class DaoX509AuthoritiesPopulatorTests extends TestCase {
public void testRequiresDao() throws Exception {
DaoX509AuthoritiesPopulator populator = new DaoX509AuthoritiesPopulator();
populator.setMessageSource(new StaticMessageSource());
try {
populator.afterPropertiesSet();

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -21,15 +21,15 @@ import org.acegisecurity.Authentication;
import org.acegisecurity.BadCredentialsException;
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.GrantedAuthorityImpl;
import org.acegisecurity.providers.TestingAuthenticationToken;
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.springframework.context.support.StaticMessageSource;
/**
* Tests {@link RunAsImplAuthenticationProvider}.
*
* @author Ben Alex
* @version $Id$
*/
public class RunAsImplAuthenticationProviderTests extends TestCase {
//~ Constructors ===========================================================
@ -44,14 +44,14 @@ public class RunAsImplAuthenticationProviderTests extends TestCase {
//~ Methods ================================================================
public final void setUp() throws Exception {
super.setUp();
}
public static void main(String[] args) {
junit.textui.TestRunner.run(RunAsImplAuthenticationProviderTests.class);
}
public final void setUp() throws Exception {
super.setUp();
}
public void testAuthenticationFailDueToWrongKey() {
RunAsUserToken token = new RunAsUserToken("WRONG_PASSWORD", "Test",
"Password",
@ -59,6 +59,7 @@ public class RunAsImplAuthenticationProviderTests extends TestCase {
"ROLE_TWO")}, UsernamePasswordAuthenticationToken.class);
RunAsImplAuthenticationProvider provider = new RunAsImplAuthenticationProvider();
provider.setKey("hello_world");
provider.setMessageSource(new StaticMessageSource());
try {
provider.authenticate(token);

View File

@ -31,6 +31,7 @@ import org.acegisecurity.providers.dao.User;
import org.acegisecurity.providers.dao.UsernameNotFoundException;
import org.acegisecurity.util.MockFilterChain;
import org.springframework.context.support.StaticMessageSource;
import org.springframework.dao.DataAccessException;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
@ -74,6 +75,7 @@ public class SwitchUserProcessingFilterTests extends TestCase {
"user-that-doesnt-exist");
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setMessageSource(new StaticMessageSource());
filter.setAuthenticationDao(new MockAuthenticationDaoUserJackLord());
try {
@ -97,6 +99,7 @@ public class SwitchUserProcessingFilterTests extends TestCase {
"mcgarrett");
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setMessageSource(new StaticMessageSource());
filter.setAuthenticationDao(new MockAuthenticationDaoUserJackLord());
try {
@ -122,6 +125,7 @@ public class SwitchUserProcessingFilterTests extends TestCase {
"wofat");
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setMessageSource(new StaticMessageSource());
filter.setAuthenticationDao(new MockAuthenticationDaoUserJackLord());
try {
@ -147,6 +151,7 @@ public class SwitchUserProcessingFilterTests extends TestCase {
"steve");
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setMessageSource(new StaticMessageSource());
filter.setAuthenticationDao(new MockAuthenticationDaoUserJackLord());
try {
@ -169,6 +174,7 @@ public class SwitchUserProcessingFilterTests extends TestCase {
"jacklord");
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setMessageSource(new StaticMessageSource());
filter.setAuthenticationDao(new MockAuthenticationDaoUserJackLord());
Authentication result = filter.attemptSwitchUser(request);
@ -177,6 +183,7 @@ public class SwitchUserProcessingFilterTests extends TestCase {
public void testBadConfigMissingAuthenticationDao() {
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setMessageSource(new StaticMessageSource());
filter.setSwitchUserUrl("/j_acegi_switch_user");
filter.setExitUserUrl("/j_acegi_exit_user");
filter.setTargetUrl("/main.jsp");
@ -191,6 +198,7 @@ public class SwitchUserProcessingFilterTests extends TestCase {
public void testBadConfigMissingTargetUrl() {
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setMessageSource(new StaticMessageSource());
filter.setAuthenticationDao(new MockAuthenticationDaoUserJackLord());
filter.setSwitchUserUrl("/j_acegi_switch_user");
filter.setExitUserUrl("/j_acegi_exit_user");
@ -206,6 +214,7 @@ public class SwitchUserProcessingFilterTests extends TestCase {
public void testDefaultProcessesFilterUrlWithPathParameter() {
MockHttpServletRequest request = createMockSwitchRequest();
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setMessageSource(new StaticMessageSource());
filter.setSwitchUserUrl("/j_acegi_switch_user");
request.setRequestURI(
@ -238,6 +247,7 @@ public class SwitchUserProcessingFilterTests extends TestCase {
// setup filter
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setMessageSource(new StaticMessageSource());
filter.setAuthenticationDao(new MockAuthenticationDaoUserJackLord());
filter.setExitUserUrl("/j_acegi_exit_user");
@ -266,6 +276,7 @@ public class SwitchUserProcessingFilterTests extends TestCase {
// setup filter
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setMessageSource(new StaticMessageSource());
filter.setAuthenticationDao(new MockAuthenticationDaoUserJackLord());
filter.setExitUserUrl("/j_acegi_exit_user");
@ -294,6 +305,7 @@ public class SwitchUserProcessingFilterTests extends TestCase {
MockFilterChain chain = new MockFilterChain(true);
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setMessageSource(new StaticMessageSource());
filter.setSwitchUserUrl("/j_acegi_switch_user");
filter.setTargetUrl("/webapp/someOtherUrl");
filter.setAuthenticationDao(new MockAuthenticationDaoUserJackLord());
@ -343,6 +355,7 @@ public class SwitchUserProcessingFilterTests extends TestCase {
// setup filter
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setMessageSource(new StaticMessageSource());
filter.setAuthenticationDao(new MockAuthenticationDaoUserJackLord());
filter.setSwitchUserUrl("/j_acegi_switch_user");

View File

@ -23,6 +23,7 @@ import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.GrantedAuthorityImpl;
import org.acegisecurity.SecurityConfig;
import org.acegisecurity.providers.TestingAuthenticationToken;
import org.springframework.context.support.StaticMessageSource;
import java.util.List;
import java.util.Vector;
@ -143,6 +144,7 @@ public class AffirmativeBasedTests extends TestCase {
private AffirmativeBased makeDecisionManager() {
AffirmativeBased decisionManager = new AffirmativeBased();
decisionManager.setMessageSource(new StaticMessageSource());
RoleVoter roleVoter = new RoleVoter();
DenyVoter denyForSureVoter = new DenyVoter();
DenyAgainVoter denyAgainForSureVoter = new DenyAgainVoter();

View File

@ -23,6 +23,7 @@ import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.GrantedAuthorityImpl;
import org.acegisecurity.SecurityConfig;
import org.acegisecurity.providers.TestingAuthenticationToken;
import org.springframework.context.support.StaticMessageSource;
import java.util.List;
import java.util.Vector;
@ -164,6 +165,7 @@ public class ConsensusBasedTests extends TestCase {
private ConsensusBased makeDecisionManager() {
ConsensusBased decisionManager = new ConsensusBased();
decisionManager.setMessageSource(new StaticMessageSource());
RoleVoter roleVoter = new RoleVoter();
DenyVoter denyForSureVoter = new DenyVoter();
DenyAgainVoter denyAgainForSureVoter = new DenyAgainVoter();

View File

@ -23,6 +23,7 @@ import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.GrantedAuthorityImpl;
import org.acegisecurity.SecurityConfig;
import org.acegisecurity.providers.TestingAuthenticationToken;
import org.springframework.context.support.StaticMessageSource;
import java.util.List;
import java.util.Vector;
@ -59,6 +60,7 @@ public class UnanimousBasedTests extends TestCase {
throws Exception {
TestingAuthenticationToken auth = makeTestToken();
UnanimousBased mgr = makeDecisionManager();
mgr.setMessageSource(new StaticMessageSource());
ConfigAttributeDefinition config = new ConfigAttributeDefinition();
config.addConfigAttribute(new SecurityConfig("ROLE_1")); // grant
@ -76,6 +78,7 @@ public class UnanimousBasedTests extends TestCase {
throws Exception {
TestingAuthenticationToken auth = makeTestToken();
UnanimousBased mgr = makeDecisionManager();
mgr.setMessageSource(new StaticMessageSource());
ConfigAttributeDefinition config = new ConfigAttributeDefinition();
config.addConfigAttribute(new SecurityConfig("ROLE_2")); // grant
@ -88,6 +91,7 @@ public class UnanimousBasedTests extends TestCase {
throws Exception {
TestingAuthenticationToken auth = makeTestToken();
UnanimousBased mgr = makeDecisionManager();
mgr.setMessageSource(new StaticMessageSource());
ConfigAttributeDefinition config = new ConfigAttributeDefinition();
config.addConfigAttribute(new SecurityConfig("ROLE_WE_DO_NOT_HAVE")); // deny
@ -103,6 +107,7 @@ public class UnanimousBasedTests extends TestCase {
public void testRoleVoterPrefixObserved() throws Exception {
TestingAuthenticationToken auth = makeTestTokenWithFooBarPrefix();
UnanimousBased mgr = makeDecisionManagerWithFooBarPrefix();
mgr.setMessageSource(new StaticMessageSource());
ConfigAttributeDefinition config = new ConfigAttributeDefinition();
config.addConfigAttribute(new SecurityConfig("FOOBAR_1")); // grant
@ -116,6 +121,7 @@ public class UnanimousBasedTests extends TestCase {
throws Exception {
TestingAuthenticationToken auth = makeTestToken();
UnanimousBased mgr = makeDecisionManager();
mgr.setMessageSource(new StaticMessageSource());
assertTrue(!mgr.isAllowIfAllAbstainDecisions()); // check default
@ -135,6 +141,7 @@ public class UnanimousBasedTests extends TestCase {
TestingAuthenticationToken auth = makeTestToken();
UnanimousBased mgr = makeDecisionManager();
mgr.setAllowIfAllAbstainDecisions(true);
mgr.setMessageSource(new StaticMessageSource());
assertTrue(mgr.isAllowIfAllAbstainDecisions()); // check changed
ConfigAttributeDefinition config = new ConfigAttributeDefinition();
@ -148,6 +155,7 @@ public class UnanimousBasedTests extends TestCase {
throws Exception {
TestingAuthenticationToken auth = makeTestToken();
UnanimousBased mgr = makeDecisionManager();
mgr.setMessageSource(new StaticMessageSource());
ConfigAttributeDefinition config = new ConfigAttributeDefinition();
config.addConfigAttribute(new SecurityConfig("ROLE_1")); // grant
@ -159,6 +167,7 @@ public class UnanimousBasedTests extends TestCase {
private UnanimousBased makeDecisionManager() {
UnanimousBased decisionManager = new UnanimousBased();
decisionManager.setMessageSource(new StaticMessageSource());
RoleVoter roleVoter = new RoleVoter();
DenyVoter denyForSureVoter = new DenyVoter();
DenyAgainVoter denyAgainForSureVoter = new DenyAgainVoter();
@ -173,6 +182,7 @@ public class UnanimousBasedTests extends TestCase {
private UnanimousBased makeDecisionManagerWithFooBarPrefix() {
UnanimousBased decisionManager = new UnanimousBased();
decisionManager.setMessageSource(new StaticMessageSource());
RoleVoter roleVoter = new RoleVoter();
roleVoter.setRolePrefix("FOOBAR_");