SEC-56: Add localisation support.
This commit is contained in:
parent
f4c3e2ff8c
commit
fddcd6112e
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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())) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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_");
|
||||
|
||||
|
|
Loading…
Reference in New Issue