[SCM] Spring Security: Java libraries that provide security services for the Spring Framework branch, master, updated. upstream/3.0.4.RELEASE-2-g53b4880
Miguel Landaeta
miguel at miguel.cc
Wed May 23 19:07:19 UTC 2012
The following commit has been merged in the master branch:
commit 53b488044520e463fa8a699702c7a1dc86d3fc03
Author: Miguel Landaeta <miguel at miguel.cc>
Date: Wed May 23 19:42:28 2012 -0430
upstream import 3.1.0.RELEASE
diff --git a/dist/spring-security-acl/META-INF/MANIFEST.MF b/dist/spring-security-acl/META-INF/MANIFEST.MF
index 351fd34..58630c0 100644
--- a/dist/spring-security-acl/META-INF/MANIFEST.MF
+++ b/dist/spring-security-acl/META-INF/MANIFEST.MF
@@ -1,4 +1,2 @@
Manifest-Version: 1.0
-Archiver-Version: Plexus Archiver
-Created-By: 17.1-b03-307 (Apple Inc.)
diff --git a/dist/spring-security-acl/createAclSchema.sql b/dist/spring-security-acl/createAclSchema.sql
deleted file mode 100644
index e999a9f..0000000
--- a/dist/spring-security-acl/createAclSchema.sql
+++ /dev/null
@@ -1,46 +0,0 @@
--- ACL schema sql used in HSQLDB
-
--- drop table acl_entry;
--- drop table acl_object_identity;
--- drop table acl_class;
--- drop table acl_sid;
-
-
-create table acl_sid(
- id bigint generated by default as identity(start with 100) not null primary key,
- principal boolean not null,
- sid varchar_ignorecase(100) not null,
- constraint unique_uk_1 unique(sid,principal));
-
-create table acl_class(
- id bigint generated by default as identity(start with 100) not null primary key,
- class varchar_ignorecase(100) not null,
- constraint unique_uk_2 unique(class)
-);
-
-create table acl_object_identity(
- id bigint generated by default as identity(start with 100) not null primary key,
- object_id_class bigint not null,
- object_id_identity bigint not null,
- parent_object bigint,
- owner_sid bigint,
- entries_inheriting boolean not null,
- constraint unique_uk_3 unique(object_id_class,object_id_identity),
- constraint foreign_fk_1 foreign key(parent_object)references acl_object_identity(id),
- constraint foreign_fk_2 foreign key(object_id_class)references acl_class(id),
- constraint foreign_fk_3 foreign key(owner_sid)references acl_sid(id)
-);
-
-create table acl_entry(
- id bigint generated by default as identity(start with 100) not null primary key,
- acl_object_identity bigint not null,
- ace_order int not null,
- sid bigint not null,
- mask integer not null,
- granting boolean not null,
- audit_success boolean not null,
- audit_failure boolean not null,
- constraint unique_uk_4 unique(acl_object_identity,ace_order),
- constraint foreign_fk_4 foreign key(acl_object_identity) references acl_object_identity(id),
- constraint foreign_fk_5 foreign key(sid) references acl_sid(id)
-);
diff --git a/dist/spring-security-acl/createAclSchemaPostgres.sql b/dist/spring-security-acl/createAclSchemaPostgres.sql
deleted file mode 100644
index 364ebf9..0000000
--- a/dist/spring-security-acl/createAclSchemaPostgres.sql
+++ /dev/null
@@ -1,46 +0,0 @@
--- ACL Schema SQL for PostgreSQL
-
--- drop table acl_entry;
--- drop table acl_object_identity;
--- drop table acl_class;
--- drop table acl_sid;
-
-create table acl_sid(
- id bigserial not null primary key,
- principal boolean not null,
- sid varchar(100) not null,
- constraint unique_uk_1 unique(sid,principal)
-);
-
-create table acl_class(
- id bigserial not null primary key,
- class varchar(100) not null,
- constraint unique_uk_2 unique(class)
-);
-
-create table acl_object_identity(
- id bigserial primary key,
- object_id_class bigint not null,
- object_id_identity bigint not null,
- parent_object bigint,
- owner_sid bigint,
- entries_inheriting boolean not null,
- constraint unique_uk_3 unique(object_id_class,object_id_identity),
- constraint foreign_fk_1 foreign key(parent_object)references acl_object_identity(id),
- constraint foreign_fk_2 foreign key(object_id_class)references acl_class(id),
- constraint foreign_fk_3 foreign key(owner_sid)references acl_sid(id)
-);
-
-create table acl_entry(
- id bigserial primary key,
- acl_object_identity bigint not null,
- ace_order int not null,
- sid bigint not null,
- mask integer not null,
- granting boolean not null,
- audit_success boolean not null,
- audit_failure boolean not null,
- constraint unique_uk_4 unique(acl_object_identity,ace_order),
- constraint foreign_fk_4 foreign key(acl_object_identity) references acl_object_identity(id),
- constraint foreign_fk_5 foreign key(sid) references acl_sid(id)
-);
diff --git a/dist/spring-security-acl/org/springframework/security/acls/AclEntryVoter.java b/dist/spring-security-acl/org/springframework/security/acls/AclEntryVoter.java
index 8b5a4a7..240f8e4 100644
--- a/dist/spring-security-acl/org/springframework/security/acls/AclEntryVoter.java
+++ b/dist/spring-security-acl/org/springframework/security/acls/AclEntryVoter.java
@@ -20,6 +20,7 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.List;
+import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.access.AuthorizationServiceException;
@@ -145,14 +146,10 @@ public class AclEntryVoter extends AbstractAclVoter {
}
public boolean supports(ConfigAttribute attribute) {
- if ((attribute.getAttribute() != null) && attribute.getAttribute().equals(getProcessConfigAttribute())) {
- return true;
- } else {
- return false;
- }
+ return (attribute.getAttribute() != null) && attribute.getAttribute().equals(getProcessConfigAttribute());
}
- public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) {
+ public int vote(Authentication authentication, MethodInvocation object, Collection<ConfigAttribute> attributes) {
for(ConfigAttribute attr : attributes) {
@@ -177,7 +174,7 @@ public class AclEntryVoter extends AbstractAclVoter {
try {
Class<?> clazz = domainObject.getClass();
Method method = clazz.getMethod(internalMethod, new Class[0]);
- domainObject = method.invoke(domainObject, new Object[0]);
+ domainObject = method.invoke(domainObject);
} catch (NoSuchMethodException nsme) {
throw new AuthorizationServiceException("Object of class '" + domainObject.getClass()
+ "' does not provide the requested internalMethod: " + internalMethod);
diff --git a/dist/spring-security-acl/org/springframework/security/acls/AclPermissionEvaluator.java b/dist/spring-security-acl/org/springframework/security/acls/AclPermissionEvaluator.java
index f9f4014..adfddd1 100644
--- a/dist/spring-security-acl/org/springframework/security/acls/AclPermissionEvaluator.java
+++ b/dist/spring-security-acl/org/springframework/security/acls/AclPermissionEvaluator.java
@@ -34,7 +34,7 @@ public class AclPermissionEvaluator implements PermissionEvaluator {
private final Log logger = LogFactory.getLog(getClass());
- private AclService aclService;
+ private final AclService aclService;
private ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl();
private ObjectIdentityGenerator objectIdentityGenerator = new ObjectIdentityRetrievalStrategyImpl();
private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();
@@ -70,24 +70,30 @@ public class AclPermissionEvaluator implements PermissionEvaluator {
List<Sid> sids = sidRetrievalStrategy.getSids(authentication);
List<Permission> requiredPermission = resolvePermission(permission);
+ final boolean debug = logger.isDebugEnabled();
+
+ if (debug) {
+ logger.debug("Checking permission '" + permission + "' for object '" + oid + "'");
+ }
+
try {
// Lookup only ACLs for SIDs we're interested in
Acl acl = aclService.readAclById(oid, sids);
if (acl.isGranted(requiredPermission, sids, false)) {
- if (logger.isDebugEnabled()) {
+ if (debug) {
logger.debug("Access is granted");
}
return true;
}
- if (logger.isDebugEnabled()) {
+ if (debug) {
logger.debug("Returning false - ACLs returned, but insufficient permissions for this principal");
}
} catch (NotFoundException nfe) {
- if (logger.isDebugEnabled()) {
+ if (debug) {
logger.debug("Returning false - no ACLs apply for this principal");
}
}
@@ -111,7 +117,7 @@ public class AclPermissionEvaluator implements PermissionEvaluator {
if (permission instanceof String) {
String permString = (String)permission;
- Permission p = null;
+ Permission p;
try {
p = permissionFactory.buildFromName(permString);
diff --git a/dist/spring-security-acl/org/springframework/security/acls/afterinvocation/AbstractAclProvider.java b/dist/spring-security-acl/org/springframework/security/acls/afterinvocation/AbstractAclProvider.java
index 6e0f0ca..0e54862 100644
--- a/dist/spring-security-acl/org/springframework/security/acls/afterinvocation/AbstractAclProvider.java
+++ b/dist/spring-security-acl/org/springframework/security/acls/afterinvocation/AbstractAclProvider.java
@@ -43,12 +43,12 @@ import org.springframework.util.Assert;
public abstract class AbstractAclProvider implements AfterInvocationProvider {
//~ Instance fields ================================================================================================
- protected AclService aclService;
+ protected final AclService aclService;
protected Class<?> processDomainObjectClass = Object.class;
protected ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl();
protected SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();
protected String processConfigAttribute;
- protected List<Permission> requirePermission = Arrays.asList(BasePermission.READ);
+ protected final List<Permission> requirePermission;
//~ Constructors ===================================================================================================
@@ -78,11 +78,9 @@ public abstract class AbstractAclProvider implements AfterInvocationProvider {
// Obtain the SIDs applicable to the principal
List<Sid> sids = sidRetrievalStrategy.getSids(authentication);
- Acl acl = null;
-
try {
// Lookup only ACLs for SIDs we're interested in
- acl = aclService.readAclById(objectIdentity, sids);
+ Acl acl = aclService.readAclById(objectIdentity, sids);
return acl.isGranted(requirePermission, sids, false);
} catch (NotFoundException ignore) {
diff --git a/dist/spring-security-acl/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationCollectionFilteringProvider.java b/dist/spring-security-acl/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationCollectionFilteringProvider.java
index 19cf8d0..2ddcf12 100644
--- a/dist/spring-security-acl/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationCollectionFilteringProvider.java
+++ b/dist/spring-security-acl/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationCollectionFilteringProvider.java
@@ -75,9 +75,7 @@ public class AclEntryAfterInvocationCollectionFilteringProvider extends Abstract
Object returnedObject) throws AccessDeniedException {
if (returnedObject == null) {
- if (logger.isDebugEnabled()) {
- logger.debug("Return object is null, skipping");
- }
+ logger.debug("Return object is null, skipping");
return null;
}
diff --git a/dist/spring-security-acl/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationProvider.java b/dist/spring-security-acl/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationProvider.java
index 4d120dc..e12cf3f 100644
--- a/dist/spring-security-acl/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationProvider.java
+++ b/dist/spring-security-acl/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationProvider.java
@@ -65,7 +65,7 @@ public class AclEntryAfterInvocationProvider extends AbstractAclProvider impleme
//~ Constructors ===================================================================================================
public AclEntryAfterInvocationProvider(AclService aclService, List<Permission> requirePermission) {
- super(aclService, "AFTER_ACL_READ", requirePermission);
+ this(aclService, "AFTER_ACL_READ", requirePermission);
}
public AclEntryAfterInvocationProvider(AclService aclService, String processConfigAttribute,
@@ -81,17 +81,13 @@ public class AclEntryAfterInvocationProvider extends AbstractAclProvider impleme
if (returnedObject == null) {
// AclManager interface contract prohibits nulls
// As they have permission to null/nothing, grant access
- if (logger.isDebugEnabled()) {
- logger.debug("Return object is null, skipping");
- }
+ logger.debug("Return object is null, skipping");
return null;
}
if (!getProcessDomainObjectClass().isAssignableFrom(returnedObject.getClass())) {
- if (logger.isDebugEnabled()) {
- logger.debug("Return object is not applicable for this provider, skipping");
- }
+ logger.debug("Return object is not applicable for this provider, skipping");
return returnedObject;
}
@@ -108,7 +104,7 @@ public class AclEntryAfterInvocationProvider extends AbstractAclProvider impleme
logger.debug("Denying access");
- throw new AccessDeniedException(messages.getMessage("BasicAclEntryAfterInvocationProvider.noPermission",
+ throw new AccessDeniedException(messages.getMessage("AclEntryAfterInvocationProvider.noPermission",
new Object[] {authentication.getName(), returnedObject},
"Authentication {0} has NO permissions to the domain object {1}"));
}
diff --git a/dist/spring-security-acl/org/springframework/security/acls/afterinvocation/ArrayFilterer.java b/dist/spring-security-acl/org/springframework/security/acls/afterinvocation/ArrayFilterer.java
index afcd950..3cdd3c1 100644
--- a/dist/spring-security-acl/org/springframework/security/acls/afterinvocation/ArrayFilterer.java
+++ b/dist/spring-security-acl/org/springframework/security/acls/afterinvocation/ArrayFilterer.java
@@ -95,7 +95,7 @@ class ArrayFilterer<T> implements Filterer<T> {
}
public T next() {
- if (hasNext() == false) {
+ if (!hasNext()) {
throw new NoSuchElementException();
}
return list[index++];
diff --git a/dist/spring-security-acl/org/springframework/security/acls/afterinvocation/CollectionFilterer.java b/dist/spring-security-acl/org/springframework/security/acls/afterinvocation/CollectionFilterer.java
index 475b74d..7a01322 100644
--- a/dist/spring-security-acl/org/springframework/security/acls/afterinvocation/CollectionFilterer.java
+++ b/dist/spring-security-acl/org/springframework/security/acls/afterinvocation/CollectionFilterer.java
@@ -37,12 +37,9 @@ class CollectionFilterer<T> implements Filterer<T> {
//~ Instance fields ================================================================================================
- private Collection<T> collection;
+ private final Collection<T> collection;
- // collectionIter offers significant performance optimisations (as
- // per security-developer mailing list conversation 19/5/05)
- private Iterator<T> collectionIter;
- private Set<T> removeList;
+ private final Set<T> removeList;
//~ Constructors ===================================================================================================
@@ -88,9 +85,7 @@ class CollectionFilterer<T> implements Filterer<T> {
* @see org.springframework.security.acls.afterinvocation.Filterer#iterator()
*/
public Iterator<T> iterator() {
- collectionIter = collection.iterator();
-
- return collectionIter;
+ return collection.iterator();
}
/**
diff --git a/dist/spring-security-acl/org/springframework/security/acls/domain/AbstractPermission.java b/dist/spring-security-acl/org/springframework/security/acls/domain/AbstractPermission.java
index a0d1e26..8d55f75 100644
--- a/dist/spring-security-acl/org/springframework/security/acls/domain/AbstractPermission.java
+++ b/dist/spring-security-acl/org/springframework/security/acls/domain/AbstractPermission.java
@@ -12,7 +12,7 @@ public abstract class AbstractPermission implements Permission {
//~ Instance fields ================================================================================================
- protected char code;
+ protected final char code;
protected int mask;
//~ Constructors ===================================================================================================
diff --git a/dist/spring-security-acl/org/springframework/security/acls/domain/AccessControlEntryImpl.java b/dist/spring-security-acl/org/springframework/security/acls/domain/AccessControlEntryImpl.java
index 0fb3287..b19a9f6 100644
--- a/dist/spring-security-acl/org/springframework/security/acls/domain/AccessControlEntryImpl.java
+++ b/dist/spring-security-acl/org/springframework/security/acls/domain/AccessControlEntryImpl.java
@@ -33,13 +33,13 @@ import java.io.Serializable;
public class AccessControlEntryImpl implements AccessControlEntry, AuditableAccessControlEntry {
//~ Instance fields ================================================================================================
- private Acl acl;
+ private final Acl acl;
private Permission permission;
- private Serializable id;
- private Sid sid;
+ private final Serializable id;
+ private final Sid sid;
private boolean auditFailure = false;
private boolean auditSuccess = false;
- private boolean granting;
+ private final boolean granting;
//~ Constructors ===================================================================================================
diff --git a/dist/spring-security-acl/org/springframework/security/acls/domain/AclAuthorizationStrategyImpl.java b/dist/spring-security-acl/org/springframework/security/acls/domain/AclAuthorizationStrategyImpl.java
index eb06f31..35ceed5 100644
--- a/dist/spring-security-acl/org/springframework/security/acls/domain/AclAuthorizationStrategyImpl.java
+++ b/dist/spring-security-acl/org/springframework/security/acls/domain/AclAuthorizationStrategyImpl.java
@@ -41,9 +41,9 @@ import org.springframework.util.Assert;
public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
//~ Instance fields ================================================================================================
- private GrantedAuthority gaGeneralChanges;
- private GrantedAuthority gaModifyAuditing;
- private GrantedAuthority gaTakeOwnership;
+ private final GrantedAuthority gaGeneralChanges;
+ private final GrantedAuthority gaModifyAuditing;
+ private final GrantedAuthority gaTakeOwnership;
private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();
//~ Constructors ===================================================================================================
@@ -52,16 +52,23 @@ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
* Constructor. The only mandatory parameter relates to the system-wide {@link GrantedAuthority} instances that
* can be held to always permit ACL changes.
*
- * @param auths an array of <code>GrantedAuthority</code>s that have
+ * @param auths the <code>GrantedAuthority</code>s that have
* special permissions (index 0 is the authority needed to change
* ownership, index 1 is the authority needed to modify auditing details,
* index 2 is the authority needed to change other ACL and ACE details) (required)
+ * <p>
+ * Alternatively, a single value can be supplied for all three permissions.
*/
- public AclAuthorizationStrategyImpl(GrantedAuthority[] auths) {
- Assert.isTrue(auths != null && auths.length == 3, "GrantedAuthority[] with three elements required");
- this.gaTakeOwnership = auths[0];
- this.gaModifyAuditing = auths[1];
- this.gaGeneralChanges = auths[2];
+ public AclAuthorizationStrategyImpl(GrantedAuthority... auths) {
+ Assert.isTrue(auths != null && (auths.length == 3 || auths.length == 1),
+ "One or three GrantedAuthority instances required");
+ if (auths.length == 3) {
+ gaTakeOwnership = auths[0];
+ gaModifyAuditing = auths[1];
+ gaGeneralChanges = auths[2];
+ } else {
+ gaTakeOwnership = gaModifyAuditing = gaGeneralChanges = auths[0];
+ }
}
//~ Methods ========================================================================================================
@@ -84,7 +91,7 @@ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
}
// Not authorized by ACL ownership; try via adminstrative permissions
- GrantedAuthority requiredAuthority = null;
+ GrantedAuthority requiredAuthority;
if (changeType == CHANGE_AUDITING) {
requiredAuthority = this.gaModifyAuditing;
diff --git a/dist/spring-security-acl/org/springframework/security/acls/domain/AclImpl.java b/dist/spring-security-acl/org/springframework/security/acls/domain/AclImpl.java
index 38687b1..cb597b5 100644
--- a/dist/spring-security-acl/org/springframework/security/acls/domain/AclImpl.java
+++ b/dist/spring-security-acl/org/springframework/security/acls/domain/AclImpl.java
@@ -26,6 +26,7 @@ import org.springframework.security.acls.model.NotFoundException;
import org.springframework.security.acls.model.ObjectIdentity;
import org.springframework.security.acls.model.OwnershipAcl;
import org.springframework.security.acls.model.Permission;
+import org.springframework.security.acls.model.PermissionGrantingStrategy;
import org.springframework.security.acls.model.Sid;
import org.springframework.security.acls.model.UnloadedSidException;
import org.springframework.util.Assert;
@@ -41,8 +42,8 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
private Acl parentAcl;
private transient AclAuthorizationStrategy aclAuthorizationStrategy;
- private transient AuditLogger auditLogger;
- private List<AccessControlEntry> aces = new ArrayList<AccessControlEntry>();
+ private transient PermissionGrantingStrategy permissionGrantingStrategy;
+ private final List<AccessControlEntry> aces = new ArrayList<AccessControlEntry>();
private ObjectIdentity objectIdentity;
private Serializable id;
private Sid owner; // OwnershipAcl
@@ -69,39 +70,48 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
this.objectIdentity = objectIdentity;
this.id = id;
this.aclAuthorizationStrategy = aclAuthorizationStrategy;
- this.auditLogger = auditLogger;
+ this.permissionGrantingStrategy = new DefaultPermissionGrantingStrategy(auditLogger);
+ }
+
+ /**
+ * @deprecated Use the version which takes a {@code PermissionGrantingStrategy} argument instead.
+ */
+ @Deprecated
+ public AclImpl(ObjectIdentity objectIdentity, Serializable id, AclAuthorizationStrategy aclAuthorizationStrategy,
+ AuditLogger auditLogger, Acl parentAcl, List<Sid> loadedSids, boolean entriesInheriting, Sid owner) {
+ this(objectIdentity, id, aclAuthorizationStrategy, new DefaultPermissionGrantingStrategy(auditLogger),
+ parentAcl, loadedSids, entriesInheriting, owner);
}
/**
* Full constructor, which should be used by persistence tools that do not
* provide field-level access features.
*
- * @param objectIdentity the object identity this ACL relates to (required)
- * @param id the primary key assigned to this ACL (required)
- * @param aclAuthorizationStrategy authorization strategy (required)
- * @param auditLogger audit logger (required)
- * @param parentAcl the parent (may be <code>null</code>)
- * @param loadedSids the loaded SIDs if only a subset were loaded (may be
- * <code>null</code>)
+ * @param objectIdentity the object identity this ACL relates to
+ * @param id the primary key assigned to this ACL
+ * @param aclAuthorizationStrategy authorization strategy
+ * @param grantingStrategy the {@code PermissionGrantingStrategy} which will be used by the {@code isGranted()} method
+ * @param parentAcl the parent (may be may be {@code null})
+ * @param loadedSids the loaded SIDs if only a subset were loaded (may be {@code null})
* @param entriesInheriting if ACEs from the parent should inherit into
* this ACL
* @param owner the owner (required)
*/
public AclImpl(ObjectIdentity objectIdentity, Serializable id, AclAuthorizationStrategy aclAuthorizationStrategy,
- AuditLogger auditLogger, Acl parentAcl, List<Sid> loadedSids, boolean entriesInheriting, Sid owner) {
+ PermissionGrantingStrategy grantingStrategy, Acl parentAcl, List<Sid> loadedSids, boolean entriesInheriting, Sid owner) {
Assert.notNull(objectIdentity, "Object Identity required");
Assert.notNull(id, "Id required");
Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required");
Assert.notNull(owner, "Owner required");
- Assert.notNull(auditLogger, "AuditLogger required");
+
this.objectIdentity = objectIdentity;
this.id = id;
this.aclAuthorizationStrategy = aclAuthorizationStrategy;
- this.auditLogger = auditLogger;
this.parentAcl = parentAcl; // may be null
this.loadedSids = loadedSids; // may be null
this.entriesInheriting = entriesInheriting;
this.owner = owner;
+ this.permissionGrantingStrategy = grantingStrategy;
}
/**
@@ -168,35 +178,11 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
}
/**
- * Determines authorization. The order of the <code>permission</code> and <code>sid</code> arguments is
- * <em>extremely important</em>! The method will iterate through each of the <code>permission</code>s in the order
- * specified. For each iteration, all of the <code>sid</code>s will be considered, again in the order they are
- * presented. A search will then be performed for the first {@link AccessControlEntry} object that directly
- * matches that <code>permission:sid</code> combination. When the <em>first full match</em> is found (ie an ACE
- * that has the SID currently being searched for and the exact permission bit mask being search for), the grant or
- * deny flag for that ACE will prevail. If the ACE specifies to grant access, the method will return
- * <code>true</code>. If the ACE specifies to deny access, the loop will stop and the next <code>permission</code>
- * iteration will be performed. If each permission indicates to deny access, the first deny ACE found will be
- * considered the reason for the failure (as it was the first match found, and is therefore the one most logically
- * requiring changes - although not always). If absolutely no matching ACE was found at all for any permission,
- * the parent ACL will be tried (provided that there is a parent and {@link #isEntriesInheriting()} is
- * <code>true</code>. The parent ACL will also scan its parent and so on. If ultimately no matching ACE is found,
- * a <code>NotFoundException</code> will be thrown and the caller will need to decide how to handle the permission
- * check. Similarly, if any of the SID arguments presented to the method were not loaded by the ACL,
- * <code>UnloadedSidException</code> will be thrown.
+ * Delegates to the {@link PermissionGrantingStrategy}.
*
- * @param permission the exact permissions to scan for (order is important)
- * @param sids the exact SIDs to scan for (order is important)
- * @param administrativeMode if <code>true</code> denotes the query is for administrative purposes and no auditing
- * will be undertaken
- *
- * @return <code>true</code> if one of the permissions has been granted, <code>false</code> if one of the
- * permissions has been specifically revoked
- *
- * @throws NotFoundException if an exact ACE for one of the permission bit masks and SID combination could not be
- * found
* @throws UnloadedSidException if the passed SIDs are unknown to this ACL because the ACL was only loaded for a
* subset of SIDs
+ * @see DefaultPermissionGrantingStrategy
*/
public boolean isGranted(List<Permission> permission, List<Sid> sids, boolean administrativeMode)
throws NotFoundException, UnloadedSidException {
@@ -207,64 +193,7 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
throw new UnloadedSidException("ACL was not loaded for one or more SID");
}
- AccessControlEntry firstRejection = null;
-
- for (Permission p : permission) {
- for (Sid sid: sids) {
- // Attempt to find exact match for this permission mask and SID
- boolean scanNextSid = true;
-
- for (AccessControlEntry ace : aces ) {
-
- if ((ace.getPermission().getMask() == p.getMask()) && ace.getSid().equals(sid)) {
- // Found a matching ACE, so its authorization decision will prevail
- if (ace.isGranting()) {
- // Success
- if (!administrativeMode) {
- auditLogger.logIfNeeded(true, ace);
- }
-
- return true;
- }
-
- // Failure for this permission, so stop search
- // We will see if they have a different permission
- // (this permission is 100% rejected for this SID)
- if (firstRejection == null) {
- // Store first rejection for auditing reasons
- firstRejection = ace;
- }
-
- scanNextSid = false; // helps break the loop
-
- break; // exit aces loop
- }
- }
-
- if (!scanNextSid) {
- break; // exit SID for loop (now try next permission)
- }
- }
- }
-
- if (firstRejection != null) {
- // We found an ACE to reject the request at this point, as no
- // other ACEs were found that granted a different permission
- if (!administrativeMode) {
- auditLogger.logIfNeeded(false, firstRejection);
- }
-
- return false;
- }
-
- // No matches have been found so far
- if (isEntriesInheriting() && (parentAcl != null)) {
- // We have a parent, so let them try to find a matching ACE
- return parentAcl.isGranted(permission, sids, false);
- } else {
- // We either have no parent, or we're the uppermost parent
- throw new NotFoundException("Unable to locate a matching ACE for passed permissions and SIDs");
- }
+ return permissionGrantingStrategy.isGranted(this, permission, sids, administrativeMode);
}
public boolean isSidLoaded(List<Sid> sids) {
@@ -320,39 +249,6 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
return parentAcl;
}
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("AclImpl[");
- sb.append("id: ").append(this.id).append("; ");
- sb.append("objectIdentity: ").append(this.objectIdentity).append("; ");
- sb.append("owner: ").append(this.owner).append("; ");
-
- int count = 0;
-
- for (AccessControlEntry ace : aces) {
- count++;
-
- if (count == 1) {
- sb.append("\r\n");
- }
-
- sb.append(ace).append("\r\n");
- }
-
- if (count == 0) {
- sb.append("no ACEs; ");
- }
-
- sb.append("inheriting: ").append(this.entriesInheriting).append("; ");
- sb.append("parent: ").append((this.parentAcl == null) ? "Null" : this.parentAcl.getObjectIdentity().toString());
- sb.append("; ");
- sb.append("aclAuthorizationStrategy: ").append(this.aclAuthorizationStrategy).append("; ");
- sb.append("auditLogger: ").append(this.auditLogger);
- sb.append("]");
-
- return sb.toString();
- }
-
public void updateAce(int aceIndex, Permission permission)
throws NotFoundException {
aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL);
@@ -379,15 +275,15 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
if (obj instanceof AclImpl) {
AclImpl rhs = (AclImpl) obj;
if (this.aces.equals(rhs.aces)) {
- if ((this.parentAcl == null && rhs.parentAcl == null) || (this.parentAcl.equals(rhs.parentAcl))) {
- if ((this.objectIdentity == null && rhs.objectIdentity == null) || (this.objectIdentity.equals(rhs.objectIdentity))) {
- if ((this.id == null && rhs.id == null) || (this.id.equals(rhs.id))) {
- if ((this.owner == null && rhs.owner == null) || this.owner.equals(rhs.owner)) {
+ if ((this.parentAcl == null && rhs.parentAcl == null) || (this.parentAcl !=null && this.parentAcl.equals(rhs.parentAcl))) {
+ if ((this.objectIdentity == null && rhs.objectIdentity == null) || (this.objectIdentity != null && this.objectIdentity.equals(rhs.objectIdentity))) {
+ if ((this.id == null && rhs.id == null) || (this.id != null && this.id.equals(rhs.id))) {
+ if ((this.owner == null && rhs.owner == null) || (this.owner != null && this.owner.equals(rhs.owner))) {
if (this.entriesInheriting == rhs.entriesInheriting) {
if ((this.loadedSids == null && rhs.loadedSids == null)) {
return true;
}
- if (this.loadedSids.size() == rhs.loadedSids.size()) {
+ if (this.loadedSids != null && (this.loadedSids.size() == rhs.loadedSids.size())) {
for (int i = 0; i < this.loadedSids.size(); i++) {
if (!this.loadedSids.get(i).equals(rhs.loadedSids.get(i))) {
return false;
@@ -405,4 +301,37 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
return false;
}
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("AclImpl[");
+ sb.append("id: ").append(this.id).append("; ");
+ sb.append("objectIdentity: ").append(this.objectIdentity).append("; ");
+ sb.append("owner: ").append(this.owner).append("; ");
+
+ int count = 0;
+
+ for (AccessControlEntry ace : aces) {
+ count++;
+
+ if (count == 1) {
+ sb.append("\n");
+ }
+
+ sb.append(ace).append("\n");
+ }
+
+ if (count == 0) {
+ sb.append("no ACEs; ");
+ }
+
+ sb.append("inheriting: ").append(this.entriesInheriting).append("; ");
+ sb.append("parent: ").append((this.parentAcl == null) ? "Null" : this.parentAcl.getObjectIdentity().toString());
+ sb.append("; ");
+ sb.append("aclAuthorizationStrategy: ").append(this.aclAuthorizationStrategy).append("; ");
+ sb.append("permissionGrantingStrategy: ").append(this.permissionGrantingStrategy);
+ sb.append("]");
+
+ return sb.toString();
+ }
+
}
diff --git a/dist/spring-security-acl/org/springframework/security/acls/domain/DefaultPermissionFactory.java b/dist/spring-security-acl/org/springframework/security/acls/domain/DefaultPermissionFactory.java
index a6379e3..c64e7c0 100644
--- a/dist/spring-security-acl/org/springframework/security/acls/domain/DefaultPermissionFactory.java
+++ b/dist/spring-security-acl/org/springframework/security/acls/domain/DefaultPermissionFactory.java
@@ -64,18 +64,19 @@ public class DefaultPermissionFactory implements PermissionFactory {
Field[] fields = clazz.getFields();
- for (int i = 0; i < fields.length; i++) {
+ for (Field field : fields) {
try {
- Object fieldValue = fields[i].get(null);
+ Object fieldValue = field.get(null);
if (Permission.class.isAssignableFrom(fieldValue.getClass())) {
// Found a Permission static field
Permission perm = (Permission) fieldValue;
- String permissionName = fields[i].getName();
+ String permissionName = field.getName();
registerPermission(perm, permissionName);
}
- } catch (Exception ignore) {}
+ } catch (Exception ignore) {
+ }
}
}
@@ -83,7 +84,7 @@ public class DefaultPermissionFactory implements PermissionFactory {
Assert.notNull(perm, "Permission required");
Assert.hasText(permissionName, "Permission name required");
- Integer mask = new Integer(perm.getMask());
+ Integer mask = Integer.valueOf(perm.getMask());
// Ensure no existing Permission uses this integer or code
Assert.isTrue(!registeredPermissionsByInteger.containsKey(mask), "An existing Permission already provides mask " + mask);
@@ -97,7 +98,7 @@ public class DefaultPermissionFactory implements PermissionFactory {
public Permission buildFromMask(int mask) {
if (registeredPermissionsByInteger.containsKey(Integer.valueOf(mask))) {
// The requested mask has an exact match against a statically-defined Permission, so return it
- return registeredPermissionsByInteger.get(new Integer(mask));
+ return registeredPermissionsByInteger.get(Integer.valueOf(mask));
}
// To get this far, we have to use a CumulativePermission
diff --git a/dist/spring-security-acl/org/springframework/security/acls/domain/EhCacheBasedAclCache.java b/dist/spring-security-acl/org/springframework/security/acls/domain/EhCacheBasedAclCache.java
index 4b16770..d4362bd 100644
--- a/dist/spring-security-acl/org/springframework/security/acls/domain/EhCacheBasedAclCache.java
+++ b/dist/spring-security-acl/org/springframework/security/acls/domain/EhCacheBasedAclCache.java
@@ -23,34 +23,48 @@ import net.sf.ehcache.Element;
import org.springframework.security.acls.model.AclCache;
import org.springframework.security.acls.model.MutableAcl;
import org.springframework.security.acls.model.ObjectIdentity;
+import org.springframework.security.acls.model.PermissionGrantingStrategy;
import org.springframework.security.util.FieldUtils;
import org.springframework.util.Assert;
/**
* Simple implementation of {@link AclCache} that delegates to EH-CACHE.
- *
* <p>
* Designed to handle the transient fields in {@link AclImpl}. Note that this implementation assumes all
- * {@link AclImpl} instances share the same {@link AuditLogger} and {@link AclAuthorizationStrategy} instance.
- * </p>
+ * {@link AclImpl} instances share the same {@link PermissionGrantingStrategy} and {@link AclAuthorizationStrategy}
+ * instances.
*
* @author Ben Alex
*/
public class EhCacheBasedAclCache implements AclCache {
//~ Instance fields ================================================================================================
- private Ehcache cache;
- private AuditLogger auditLogger;
+ private final Ehcache cache;
+ private PermissionGrantingStrategy permissionGrantingStrategy;
private AclAuthorizationStrategy aclAuthorizationStrategy;
//~ Constructors ===================================================================================================
+ /**
+ * @deprecated use the second constructor which injects the strategy objects. See SEC-1498.
+ */
+ @Deprecated
public EhCacheBasedAclCache(Ehcache cache) {
Assert.notNull(cache, "Cache required");
this.cache = cache;
}
+ public EhCacheBasedAclCache(Ehcache cache, PermissionGrantingStrategy permissionGrantingStrategy,
+ AclAuthorizationStrategy aclAuthorizationStrategy) {
+ Assert.notNull(cache, "Cache required");
+ Assert.notNull(permissionGrantingStrategy, "PermissionGrantingStrategy required");
+ Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required");
+ this.cache = cache;
+ this.permissionGrantingStrategy = permissionGrantingStrategy;
+ this.aclAuthorizationStrategy = aclAuthorizationStrategy;
+ }
+
//~ Methods ========================================================================================================
public void evictFromCache(Serializable pk) {
@@ -115,7 +129,7 @@ public class EhCacheBasedAclCache implements AclCache {
if (this.aclAuthorizationStrategy == null) {
if (acl instanceof AclImpl) {
this.aclAuthorizationStrategy = (AclAuthorizationStrategy) FieldUtils.getProtectedFieldValue("aclAuthorizationStrategy", acl);
- this.auditLogger = (AuditLogger) FieldUtils.getProtectedFieldValue("auditLogger", acl);
+ this.permissionGrantingStrategy = (PermissionGrantingStrategy) FieldUtils.getProtectedFieldValue("permissionGrantingStrategy", acl);
}
}
@@ -130,7 +144,7 @@ public class EhCacheBasedAclCache implements AclCache {
private MutableAcl initializeTransientFields(MutableAcl value) {
if (value instanceof AclImpl) {
FieldUtils.setProtectedFieldValue("aclAuthorizationStrategy", value, this.aclAuthorizationStrategy);
- FieldUtils.setProtectedFieldValue("auditLogger", value, this.auditLogger);
+ FieldUtils.setProtectedFieldValue("permissionGrantingStrategy", value, this.permissionGrantingStrategy);
}
if (value.getParentAcl() != null) {
diff --git a/dist/spring-security-acl/org/springframework/security/acls/domain/GrantedAuthoritySid.java b/dist/spring-security-acl/org/springframework/security/acls/domain/GrantedAuthoritySid.java
index 0bb056d..e31f265 100644
--- a/dist/spring-security-acl/org/springframework/security/acls/domain/GrantedAuthoritySid.java
+++ b/dist/spring-security-acl/org/springframework/security/acls/domain/GrantedAuthoritySid.java
@@ -30,7 +30,7 @@ import org.springframework.util.Assert;
public class GrantedAuthoritySid implements Sid {
//~ Instance fields ================================================================================================
- private String grantedAuthority;
+ private final String grantedAuthority;
//~ Constructors ===================================================================================================
diff --git a/dist/spring-security-acl/org/springframework/security/acls/domain/ObjectIdentityImpl.java b/dist/spring-security-acl/org/springframework/security/acls/domain/ObjectIdentityImpl.java
index f805679..9026696 100644
--- a/dist/spring-security-acl/org/springframework/security/acls/domain/ObjectIdentityImpl.java
+++ b/dist/spring-security-acl/org/springframework/security/acls/domain/ObjectIdentityImpl.java
@@ -78,7 +78,7 @@ public class ObjectIdentityImpl implements ObjectIdentity {
try {
Method method = typeClass.getMethod("getId", new Class[] {});
- result = method.invoke(object, new Object[] {});
+ result = method.invoke(object);
} catch (Exception e) {
throw new IdentityUnavailableException("Could not extract identity from object " + object, e);
}
diff --git a/dist/spring-security-acl/org/springframework/security/acls/domain/PrincipalSid.java b/dist/spring-security-acl/org/springframework/security/acls/domain/PrincipalSid.java
index db59ac6..d9253c7 100644
--- a/dist/spring-security-acl/org/springframework/security/acls/domain/PrincipalSid.java
+++ b/dist/spring-security-acl/org/springframework/security/acls/domain/PrincipalSid.java
@@ -32,7 +32,7 @@ import org.springframework.util.Assert;
public class PrincipalSid implements Sid {
//~ Instance fields ================================================================================================
- private String principal;
+ private final String principal;
//~ Constructors ===================================================================================================
diff --git a/dist/spring-security-acl/org/springframework/security/acls/domain/SidRetrievalStrategyImpl.java b/dist/spring-security-acl/org/springframework/security/acls/domain/SidRetrievalStrategyImpl.java
index afed23c..4c0c0d6 100644
--- a/dist/spring-security-acl/org/springframework/security/acls/domain/SidRetrievalStrategyImpl.java
+++ b/dist/spring-security-acl/org/springframework/security/acls/domain/SidRetrievalStrategyImpl.java
@@ -51,7 +51,7 @@ public class SidRetrievalStrategyImpl implements SidRetrievalStrategy {
//~ Methods ========================================================================================================
public List<Sid> getSids(Authentication authentication) {
- Collection<GrantedAuthority> authorities = roleHierarchy.getReachableGrantedAuthorities(authentication.getAuthorities());
+ Collection<? extends GrantedAuthority> authorities = roleHierarchy.getReachableGrantedAuthorities(authentication.getAuthorities());
List<Sid> sids = new ArrayList<Sid>(authorities.size() + 1);
sids.add(new PrincipalSid(authentication));
diff --git a/dist/spring-security-acl/org/springframework/security/acls/jdbc/BasicLookupStrategy.java b/dist/spring-security-acl/org/springframework/security/acls/jdbc/BasicLookupStrategy.java
index 62ab519..ab469d1 100644
--- a/dist/spring-security-acl/org/springframework/security/acls/jdbc/BasicLookupStrategy.java
+++ b/dist/spring-security-acl/org/springframework/security/acls/jdbc/BasicLookupStrategy.java
@@ -29,7 +29,6 @@ import java.util.Set;
import javax.sql.DataSource;
-import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.jdbc.core.ResultSetExtractor;
@@ -38,6 +37,7 @@ import org.springframework.security.acls.domain.AclAuthorizationStrategy;
import org.springframework.security.acls.domain.AclImpl;
import org.springframework.security.acls.domain.AuditLogger;
import org.springframework.security.acls.domain.DefaultPermissionFactory;
+import org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy;
import org.springframework.security.acls.domain.GrantedAuthoritySid;
import org.springframework.security.acls.domain.ObjectIdentityImpl;
import org.springframework.security.acls.domain.PermissionFactory;
@@ -49,6 +49,7 @@ import org.springframework.security.acls.model.MutableAcl;
import org.springframework.security.acls.model.NotFoundException;
import org.springframework.security.acls.model.ObjectIdentity;
import org.springframework.security.acls.model.Permission;
+import org.springframework.security.acls.model.PermissionGrantingStrategy;
import org.springframework.security.acls.model.Sid;
import org.springframework.security.acls.model.UnloadedSidException;
import org.springframework.security.util.FieldUtils;
@@ -106,11 +107,11 @@ public final class BasicLookupStrategy implements LookupStrategy {
//~ Instance fields ================================================================================================
- private AclAuthorizationStrategy aclAuthorizationStrategy;
+ private final AclAuthorizationStrategy aclAuthorizationStrategy;
private PermissionFactory permissionFactory = new DefaultPermissionFactory();
- private AclCache aclCache;
- private AuditLogger auditLogger;
- private JdbcTemplate jdbcTemplate;
+ private final AclCache aclCache;
+ private final PermissionGrantingStrategy grantingStrategy;
+ private final JdbcTemplate jdbcTemplate;
private int batchSize = 50;
private final Field fieldAces = FieldUtils.getField(AclImpl.class, "aces");
@@ -130,19 +131,28 @@ public final class BasicLookupStrategy implements LookupStrategy {
* @param dataSource to access the database
* @param aclCache the cache where fully-loaded elements can be stored
* @param aclAuthorizationStrategy authorization strategy (required)
+ *
+ * @deprecated Use the version which takes a {@code PermissionGrantingStrategy} argument instead.
*/
+ @Deprecated
public BasicLookupStrategy(DataSource dataSource, AclCache aclCache,
- AclAuthorizationStrategy aclAuthorizationStrategy, AuditLogger auditLogger) {
+ AclAuthorizationStrategy aclAuthorizationStrategy, AuditLogger auditLogger) {
+ this(dataSource, aclCache, aclAuthorizationStrategy, new DefaultPermissionGrantingStrategy(auditLogger));
+ }
+
+ public BasicLookupStrategy(DataSource dataSource, AclCache aclCache,
+ AclAuthorizationStrategy aclAuthorizationStrategy, PermissionGrantingStrategy grantingStrategy) {
Assert.notNull(dataSource, "DataSource required");
Assert.notNull(aclCache, "AclCache required");
Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required");
- Assert.notNull(auditLogger, "AuditLogger required");
+ Assert.notNull(grantingStrategy, "grantingStrategy required");
jdbcTemplate = new JdbcTemplate(dataSource);
this.aclCache = aclCache;
this.aclAuthorizationStrategy = aclAuthorizationStrategy;
- this.auditLogger = auditLogger;
+ this.grantingStrategy = grantingStrategy;
fieldAces.setAccessible(true);
fieldAcl.setAccessible(true);
+
}
//~ Methods ========================================================================================================
@@ -395,7 +405,7 @@ public final class BasicLookupStrategy implements LookupStrategy {
// Now we have the parent (if there is one), create the true AclImpl
AclImpl result = new AclImpl(inputAcl.getObjectIdentity(), (Long) inputAcl.getId(), aclAuthorizationStrategy,
- auditLogger, parent, null, inputAcl.isEntriesInheriting(), inputAcl.getOwner());
+ grantingStrategy, parent, null, inputAcl.isEntriesInheriting(), inputAcl.getOwner());
// Copy the "aces" from the input to the destination
@@ -466,8 +476,8 @@ public final class BasicLookupStrategy implements LookupStrategy {
//~ Inner Classes ==================================================================================================
private class ProcessResultSet implements ResultSetExtractor<Set<Long>> {
- private Map<Serializable, Acl> acls;
- private List<Sid> sids;
+ private final Map<Serializable, Acl> acls;
+ private final List<Sid> sids;
public ProcessResultSet(Map<Serializable, Acl> acls, List<Sid> sids) {
Assert.notNull(acls, "ACLs cannot be null");
@@ -484,9 +494,8 @@ public final class BasicLookupStrategy implements LookupStrategy {
* @param rs The {@link ResultSet} to be processed
* @return a list of parent IDs remaining to be looked up (may be empty, but never <tt>null</tt>)
* @throws SQLException
- * @throws DataAccessException
*/
- public Set<Long> extractData(ResultSet rs) throws SQLException, DataAccessException {
+ public Set<Long> extractData(ResultSet rs) throws SQLException {
Set<Long> parentIdsToLookup = new HashSet<Long>(); // Set of parent_id Longs
while (rs.next()) {
@@ -555,7 +564,7 @@ public final class BasicLookupStrategy implements LookupStrategy {
owner = new GrantedAuthoritySid(rs.getString("acl_sid"));
}
- acl = new AclImpl(objectIdentity, id, aclAuthorizationStrategy, auditLogger, parentAcl, null,
+ acl = new AclImpl(objectIdentity, id, aclAuthorizationStrategy, grantingStrategy, parentAcl, null,
entriesInheriting, owner);
acls.put(id, acl);
@@ -594,7 +603,7 @@ public final class BasicLookupStrategy implements LookupStrategy {
}
private class StubAclParent implements Acl {
- private Long id;
+ private final Long id;
public StubAclParent(Long id) {
this.id = id;
diff --git a/dist/spring-security-acl/org/springframework/security/acls/jdbc/JdbcAclService.java b/dist/spring-security-acl/org/springframework/security/acls/jdbc/JdbcAclService.java
index 30ba34f..b94ca9e 100644
--- a/dist/spring-security-acl/org/springframework/security/acls/jdbc/JdbcAclService.java
+++ b/dist/spring-security-acl/org/springframework/security/acls/jdbc/JdbcAclService.java
@@ -56,8 +56,8 @@ public class JdbcAclService implements AclService {
//~ Instance fields ================================================================================================
- protected JdbcTemplate jdbcTemplate;
- private LookupStrategy lookupStrategy;
+ protected final JdbcTemplate jdbcTemplate;
+ private final LookupStrategy lookupStrategy;
private String findChildrenSql = DEFAULT_SELECT_ACL_WITH_PARENT_SQL;
//~ Constructors ===================================================================================================
@@ -109,10 +109,9 @@ public class JdbcAclService implements AclService {
Map<ObjectIdentity, Acl> result = lookupStrategy.readAclsById(objects, sids);
// Check every requested object identity was found (throw NotFoundException if needed)
- for (int i = 0; i < objects.size(); i++) {
- if (!result.containsKey(objects.get(i))) {
- throw new NotFoundException("Unable to find ACL information for object identity '"
- + objects.get(i) + "'");
+ for (ObjectIdentity oid : objects) {
+ if (!result.containsKey(oid)) {
+ throw new NotFoundException("Unable to find ACL information for object identity '" + oid + "'");
}
}
diff --git a/dist/spring-security-acl/org/springframework/security/acls/jdbc/JdbcMutableAclService.java b/dist/spring-security-acl/org/springframework/security/acls/jdbc/JdbcMutableAclService.java
index d7b35aa..22d86d4 100644
--- a/dist/spring-security-acl/org/springframework/security/acls/jdbc/JdbcMutableAclService.java
+++ b/dist/spring-security-acl/org/springframework/security/acls/jdbc/JdbcMutableAclService.java
@@ -61,7 +61,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
//~ Instance fields ================================================================================================
private boolean foreignKeysInDatabase = true;
- private AclCache aclCache;
+ private final AclCache aclCache;
private String deleteEntryByObjectIdentityForeignKey = "delete from acl_entry where acl_object_identity=?";
private String deleteObjectIdentityByPrimaryKey = "delete from acl_object_identity where id=?";
private String classIdentityQuery = "call identity()";
@@ -194,7 +194,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
protected Long createOrRetrieveSidPrimaryKey(Sid sid, boolean allowCreate) {
Assert.notNull(sid, "Sid required");
- String sidName = null;
+ String sidName;
boolean sidIsPrincipal = true;
if (sid instanceof PrincipalSid) {
@@ -214,7 +214,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
}
if (allowCreate) {
- jdbcTemplate.update(insertSid, new Object[] {Boolean.valueOf(sidIsPrincipal), sidName});
+ jdbcTemplate.update(insertSid, Boolean.valueOf(sidIsPrincipal), sidName);
Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), "Transaction must be running");
return new Long(jdbcTemplate.queryForLong(sidIdentityQuery));
}
@@ -229,8 +229,8 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
if (deleteChildren) {
List<ObjectIdentity> children = findChildren(objectIdentity);
if (children != null) {
- for (int i = 0; i < children.size(); i++) {
- deleteAcl(children.get(i), true);
+ for (ObjectIdentity child : children) {
+ deleteAcl(child, true);
}
}
} else {
@@ -263,8 +263,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
* @param oidPrimaryKey the rows in acl_entry to delete
*/
protected void deleteEntries(Long oidPrimaryKey) {
- jdbcTemplate.update(deleteEntryByObjectIdentityForeignKey,
- new Object[] {oidPrimaryKey});
+ jdbcTemplate.update(deleteEntryByObjectIdentityForeignKey, oidPrimaryKey);
}
/**
@@ -277,7 +276,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
*/
protected void deleteObjectIdentity(Long oidPrimaryKey) {
// Delete the acl_object_identity row
- jdbcTemplate.update(deleteObjectIdentityByPrimaryKey, new Object[] {oidPrimaryKey});
+ jdbcTemplate.update(deleteObjectIdentityByPrimaryKey, oidPrimaryKey);
}
/**
@@ -291,8 +290,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
*/
protected Long retrieveObjectIdentityPrimaryKey(ObjectIdentity oid) {
try {
- return new Long(jdbcTemplate.queryForLong(selectObjectIdentityPrimaryKey,
- new Object[] {oid.getType(), oid.getIdentifier()}));
+ return new Long(jdbcTemplate.queryForLong(selectObjectIdentityPrimaryKey, oid.getType(), oid.getIdentifier()));
} catch (DataAccessException notFound) {
return null;
}
@@ -326,8 +324,8 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
Assert.notNull(objectIdentity, "ObjectIdentity required");
List<ObjectIdentity> children = findChildren(objectIdentity);
if (children != null) {
- for (int i = 0; i < children.size(); i++) {
- clearCacheIncludingChildren(children.get(i));
+ for (ObjectIdentity child : children) {
+ clearCacheIncludingChildren(child);
}
}
aclCache.evictFromCache(objectIdentity);
@@ -356,7 +354,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
Long ownerSid = createOrRetrieveSidPrimaryKey(acl.getOwner(), true);
int count = jdbcTemplate.update(updateObjectIdentity,
- new Object[] {parentId, ownerSid, new Boolean(acl.isEntriesInheriting()), acl.getId()});
+ parentId, ownerSid, Boolean.valueOf(acl.isEntriesInheriting()), acl.getId());
if (count != 1) {
throw new NotFoundException("Unable to locate ACL to update");
diff --git a/dist/spring-security-acl/select.sql b/dist/spring-security-acl/select.sql
deleted file mode 100644
index ad759c7..0000000
--- a/dist/spring-security-acl/select.sql
+++ /dev/null
@@ -1,39 +0,0 @@
--- Not required. Just shows the sort of queries being sent to DB.
-
-
-select acl_object_identity.object_id_identity,
- acl_entry.ace_order,
- acl_object_identity.id as acl_id,
- acl_object_identity.parent_object,
- acl_object_identity,
- entries_inheriting,
- acl_entry.id as ace_id,
- acl_entry.mask,
- acl_entry.granting,
- acl_entry.audit_success,
- acl_entry.audit_failure,
- acl_sid.principal as ace_principal,
- acl_sid.sid as ace_sid,
- acli_sid.principal as acl_principal,
- acli_sid.sid as acl_sid,
- acl_class.class
-
-from acl_object_identity,
- acl_sid acli_sid,
- acl_class
-
-left join acl_entry on acl_object_identity.id = acl_entry.acl_object_identity
-left join acl_sid on acl_entry.sid = acl_sid.id
-
-where
- acli_sid.id = acl_object_identity.owner_sid
-
-and acl_class.id = acl_object_identity.object_id_class
-
-and (
-
- (acl_object_identity.object_id_identity = 1 and acl_class.class = 'sample.contact.contact')
-or
- (acl_object_identity.object_id_identity = 2000 and acl_class.class = 'sample.contact.contact')
-
-) order by acl_object_identity.object_id_identity asc, acl_entry.ace_order asc
diff --git a/dist/spring-security-aspects/META-INF/MANIFEST.MF b/dist/spring-security-aspects/META-INF/MANIFEST.MF
index 351fd34..58630c0 100644
--- a/dist/spring-security-aspects/META-INF/MANIFEST.MF
+++ b/dist/spring-security-aspects/META-INF/MANIFEST.MF
@@ -1,4 +1,2 @@
Manifest-Version: 1.0
-Archiver-Version: Plexus Archiver
-Created-By: 17.1-b03-307 (Apple Inc.)
diff --git a/dist/spring-security-aspects/META-INF/aop.xml b/dist/spring-security-aspects/META-INF/aop.xml
deleted file mode 100644
index a9d76e8..0000000
--- a/dist/spring-security-aspects/META-INF/aop.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0"?>
-
- <!--
- AspectJ load-time weaving config file to install common Spring
- aspects.
- -->
-<aspectj>
-
- <!--
- <weaver options="-showWeaveInfo"/>
- -->
-
- <aspects>
- <aspect
- name="org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect" />
- </aspects>
-
-</aspectj>
diff --git a/dist/spring-security-aspects/org/springframework/security/access/intercept/aspectj/aspect/AnnotationSecurityAspect.aj b/dist/spring-security-aspects/org/springframework/security/access/intercept/aspectj/aspect/AnnotationSecurityAspect.aj
deleted file mode 100644
index f219406..0000000
--- a/dist/spring-security-aspects/org/springframework/security/access/intercept/aspectj/aspect/AnnotationSecurityAspect.aj
+++ /dev/null
@@ -1,76 +0,0 @@
-package org.springframework.security.access.intercept.aspectj.aspect;
-
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.security.access.annotation.Secured;
-import org.springframework.security.access.prepost.*;
-import org.springframework.security.access.intercept.aspectj.AspectJCallback;
-import org.springframework.security.access.intercept.aspectj.AspectJMethodSecurityInterceptor;
-
-/**
- * Concrete AspectJ aspect using Spring Security @Secured annotation
- * for JDK 1.5+.
- *
- * <p>
- * When using this aspect, you <i>must</i> annotate the implementation class
- * (and/or methods within that class), <i>not</i> the interface (if any) that
- * the class implements. AspectJ follows Java's rule that annotations on
- * interfaces are <i>not</i> inherited. This will vary from Spring AOP.
- *
- * @author Mike Wiesner
- * @author Luke Taylor
- * @since 3.1
- */
-public aspect AnnotationSecurityAspect implements InitializingBean {
-
- /**
- * Matches the execution of any public method in a type with the Secured
- * annotation, or any subtype of a type with the Secured annotation.
- */
- private pointcut executionOfAnyPublicMethodInAtSecuredType() :
- execution(public * ((@Secured *)+).*(..)) && @this(Secured);
-
- /**
- * Matches the execution of any method with the Secured annotation.
- */
- private pointcut executionOfSecuredMethod() :
- execution(* *(..)) && @annotation(Secured);
-
- /**
- * Matches the execution of any method with Pre/Post annotations.
- */
- private pointcut executionOfPrePostAnnotatedMethod() :
- execution(* *(..)) && (@annotation(PreAuthorize) || @annotation(PreFilter)
- || @annotation(PostAuthorize) || @annotation(PostFilter));
-
- private pointcut securedMethodExecution() :
- executionOfAnyPublicMethodInAtSecuredType() ||
- executionOfSecuredMethod() ||
- executionOfPrePostAnnotatedMethod();
-
- private AspectJMethodSecurityInterceptor securityInterceptor;
-
- Object around(): securedMethodExecution() {
- if (this.securityInterceptor == null) {
- return proceed();
- }
-
- AspectJCallback callback = new AspectJCallback() {
- public Object proceedWithObject() {
- return proceed();
- }
- };
-
- return this.securityInterceptor.invoke(thisJoinPoint, callback);
- }
-
- public void setSecurityInterceptor(AspectJMethodSecurityInterceptor securityInterceptor) {
- this.securityInterceptor = securityInterceptor;
- }
-
- public void afterPropertiesSet() throws Exception {
- if (this.securityInterceptor == null) {
- throw new IllegalArgumentException("securityInterceptor required");
- }
- }
-
-}
diff --git a/dist/spring-security-cas-client/META-INF/MANIFEST.MF b/dist/spring-security-cas-client/META-INF/MANIFEST.MF
deleted file mode 100644
index 351fd34..0000000
--- a/dist/spring-security-cas-client/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,4 +0,0 @@
-Manifest-Version: 1.0
-Archiver-Version: Plexus Archiver
-Created-By: 17.1-b03-307 (Apple Inc.)
-
diff --git a/dist/spring-security-cas-client/org/springframework/security/cas/SamlServiceProperties.java b/dist/spring-security-cas-client/org/springframework/security/cas/SamlServiceProperties.java
deleted file mode 100644
index 15ead68..0000000
--- a/dist/spring-security-cas-client/org/springframework/security/cas/SamlServiceProperties.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/* Copyright 2004, 2005, 2006 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.security.cas;
-
-/**
- * Sets the appropriate parameters for CAS's implementation of SAML (which is not guaranteed to be actually SAML compliant).
- *
- * @author Scott Battaglia
- * @since 3.0
- */
-public final class SamlServiceProperties extends ServiceProperties {
-
- public static final String DEFAULT_SAML_ARTIFACT_PARAMETER = "SAMLart";
-
- public static final String DEFAULT_SAML_SERVICE_PARAMETER = "TARGET";
-
- public SamlServiceProperties() {
- super.setArtifactParameter(DEFAULT_SAML_ARTIFACT_PARAMETER);
- super.setServiceParameter(DEFAULT_SAML_SERVICE_PARAMETER);
- }
-}
diff --git a/dist/spring-security-cas-client/org/springframework/security/cas/ServiceProperties.java b/dist/spring-security-cas-client/org/springframework/security/cas/ServiceProperties.java
deleted file mode 100644
index f6488df..0000000
--- a/dist/spring-security-cas-client/org/springframework/security/cas/ServiceProperties.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/* Copyright 2004, 2005, 2006 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.cas;
-
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.util.Assert;
-
-
-/**
- * Stores properties related to this CAS service.
- * <p>
- * Each web application capable of processing CAS tickets is known as a service.
- * This class stores the properties that are relevant to the local CAS service, being the application
- * that is being secured by Spring Security.
- *
- * @author Ben Alex
- */
-public class ServiceProperties implements InitializingBean {
-
- public static final String DEFAULT_CAS_ARTIFACT_PARAMETER = "ticket";
-
- public static final String DEFAULT_CAS_SERVICE_PARAMETER = "service";
-
- //~ Instance fields ================================================================================================
-
- private String service;
-
- private boolean sendRenew = false;
-
- private String artifactParameter = DEFAULT_CAS_ARTIFACT_PARAMETER;
-
- private String serviceParameter = DEFAULT_CAS_SERVICE_PARAMETER;
-
- //~ Methods ========================================================================================================
-
- public void afterPropertiesSet() throws Exception {
- Assert.hasLength(this.service, "service must be specified.");
- Assert.hasLength(this.artifactParameter, "artifactParameter cannot be empty.");
- Assert.hasLength(this.serviceParameter, "serviceParameter cannot be empty.");
- }
-
- /**
- * Represents the service the user is authenticating to.
- * <p>
- * This service is the callback URL belonging to the local Spring Security System for Spring secured application.
- * For example,
- * <pre>
- * https://www.mycompany.com/application/j_spring_cas_security_check
- * </pre>
- *
- * @return the URL of the service the user is authenticating to
- */
- public final String getService() {
- return this.service;
- }
-
- /**
- * Indicates whether the <code>renew</code> parameter should be sent to the CAS login URL and CAS
- * validation URL.
- * <p>
- * If <code>true</code>, it will force CAS to authenticate the user again (even if the
- * user has previously authenticated). During ticket validation it will require the ticket was generated as a
- * consequence of an explicit login. High security applications would probably set this to <code>true</code>.
- * Defaults to <code>false</code>, providing automated single sign on.
- *
- * @return whether to send the <code>renew</code> parameter to CAS
- */
- public final boolean isSendRenew() {
- return this.sendRenew;
- }
-
- public final void setSendRenew(final boolean sendRenew) {
- this.sendRenew = sendRenew;
- }
-
- public final void setService(final String service) {
- this.service = service;
- }
-
- public final String getArtifactParameter() {
- return this.artifactParameter;
- }
-
- /**
- * Configures the Request Parameter to look for when attempting to see if a CAS ticket was sent from the server.
- *
- * @param artifactParameter the id to use. Default is "ticket".
- */
- public final void setArtifactParameter(final String artifactParameter) {
- this.artifactParameter = artifactParameter;
- }
-
- /**
- * Configures the Request parameter to look for when attempting to send a request to CAS.
- *
- * @return the service parameter to use. Default is "service".
- */
- public final String getServiceParameter() {
- return serviceParameter;
- }
-
- public final void setServiceParameter(final String serviceParameter) {
- this.serviceParameter = serviceParameter;
- }
-}
diff --git a/dist/spring-security-cas-client/org/springframework/security/cas/authentication/CasAssertionAuthenticationToken.java b/dist/spring-security-cas-client/org/springframework/security/cas/authentication/CasAssertionAuthenticationToken.java
deleted file mode 100644
index 8db8b8f..0000000
--- a/dist/spring-security-cas-client/org/springframework/security/cas/authentication/CasAssertionAuthenticationToken.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/* Copyright 2004, 2005, 2006 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.security.cas.authentication;
-
-import java.util.ArrayList;
-
-import org.jasig.cas.client.validation.Assertion;
-import org.springframework.security.authentication.AbstractAuthenticationToken;
-import org.springframework.security.core.GrantedAuthority;
-
-/**
- * Temporary authentication object needed to load the user details service.
- *
- * @author Scott Battaglia
- * @since 3.0
- */
-public final class CasAssertionAuthenticationToken extends AbstractAuthenticationToken {
-
- private final Assertion assertion;
-
- private final String ticket;
-
- public CasAssertionAuthenticationToken(final Assertion assertion, final String ticket) {
- super(new ArrayList<GrantedAuthority>());
-
- this.assertion = assertion;
- this.ticket = ticket;
- }
-
- public Object getPrincipal() {
- return this.assertion.getPrincipal().getName();
- }
-
- public Object getCredentials() {
- return this.ticket;
- }
-
- public Assertion getAssertion() {
- return this.assertion;
- }
-}
diff --git a/dist/spring-security-cas-client/org/springframework/security/cas/authentication/CasAuthenticationProvider.java b/dist/spring-security-cas-client/org/springframework/security/cas/authentication/CasAuthenticationProvider.java
deleted file mode 100644
index 68b8265..0000000
--- a/dist/spring-security-cas-client/org/springframework/security/cas/authentication/CasAuthenticationProvider.java
+++ /dev/null
@@ -1,201 +0,0 @@
-/* Copyright 2004, 2005, 2006 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.cas.authentication;
-
-import org.jasig.cas.client.validation.Assertion;
-import org.jasig.cas.client.validation.TicketValidationException;
-import org.jasig.cas.client.validation.TicketValidator;
-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.security.authentication.AccountStatusUserDetailsChecker;
-import org.springframework.security.authentication.AuthenticationProvider;
-import org.springframework.security.authentication.BadCredentialsException;
-import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
-import org.springframework.security.cas.ServiceProperties;
-import org.springframework.security.cas.web.CasAuthenticationFilter;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.AuthenticationException;
-import org.springframework.security.core.SpringSecurityMessageSource;
-import org.springframework.security.core.userdetails.*;
-import org.springframework.util.Assert;
-
-
-/**
- * An {@link AuthenticationProvider} implementation that integrates with JA-SIG Central Authentication Service
- * (CAS).
- * <p>
- * This <code>AuthenticationProvider</code> is capable of validating {@link UsernamePasswordAuthenticationToken}
- * requests which contain a <code>principal</code> name equal to either
- * {@link CasAuthenticationFilter#CAS_STATEFUL_IDENTIFIER} or {@link CasAuthenticationFilter#CAS_STATELESS_IDENTIFIER}.
- * It can also validate a previously created {@link CasAuthenticationToken}.
- *
- * @author Ben Alex
- * @author Scott Battaglia
- */
-public class CasAuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware {
-
- //~ Instance fields ================================================================================================
-
- private AuthenticationUserDetailsService authenticationUserDetailsService;
-
- private UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker();
- protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
- private StatelessTicketCache statelessTicketCache = new NullStatelessTicketCache();
- private String key;
- private TicketValidator ticketValidator;
- private ServiceProperties serviceProperties;
-
- //~ Methods ========================================================================================================
-
- public void afterPropertiesSet() throws Exception {
- Assert.notNull(this.authenticationUserDetailsService, "An authenticationUserDetailsService must be set");
- Assert.notNull(this.ticketValidator, "A ticketValidator must be set");
- Assert.notNull(this.statelessTicketCache, "A statelessTicketCache must be set");
- Assert.hasText(this.key, "A Key is required so CasAuthenticationProvider can identify tokens it previously authenticated");
- Assert.notNull(this.messages, "A message source must be set");
- Assert.notNull(this.serviceProperties, "serviceProperties is a required field.");
- }
-
- public Authentication authenticate(Authentication authentication) throws AuthenticationException {
- if (!supports(authentication.getClass())) {
- return null;
- }
-
- if (authentication instanceof UsernamePasswordAuthenticationToken
- && (!CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER.equals(authentication.getPrincipal().toString())
- && !CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER.equals(authentication.getPrincipal().toString()))) {
- // UsernamePasswordAuthenticationToken not CAS related
- return null;
- }
-
- // If an existing CasAuthenticationToken, just check we created it
- if (authentication instanceof CasAuthenticationToken) {
- if (this.key.hashCode() == ((CasAuthenticationToken) authentication).getKeyHash()) {
- return authentication;
- } else {
- 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(messages.getMessage("CasAuthenticationProvider.noServiceTicket",
- "Failed to provide a CAS service ticket to validate"));
- }
-
- boolean stateless = false;
-
- if (authentication instanceof UsernamePasswordAuthenticationToken
- && CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER.equals(authentication.getPrincipal())) {
- stateless = true;
- }
-
- CasAuthenticationToken result = null;
-
- if (stateless) {
- // Try to obtain from cache
- result = statelessTicketCache.getByTicketId(authentication.getCredentials().toString());
- }
-
- if (result == null) {
- result = this.authenticateNow(authentication);
- result.setDetails(authentication.getDetails());
- }
-
- if (stateless) {
- // Add to cache
- statelessTicketCache.putTicketInCache(result);
- }
-
- return result;
- }
-
- private CasAuthenticationToken authenticateNow(final Authentication authentication) throws AuthenticationException {
- try {
- final Assertion assertion = this.ticketValidator.validate(authentication.getCredentials().toString(), serviceProperties.getService());
- final UserDetails userDetails = loadUserByAssertion(assertion);
- userDetailsChecker.check(userDetails);
- return new CasAuthenticationToken(this.key, userDetails, authentication.getCredentials(), userDetails.getAuthorities(), userDetails, assertion);
- } catch (final TicketValidationException e) {
- throw new BadCredentialsException(e.getMessage(), e);
- }
- }
-
- /**
- * Template method for retrieving the UserDetails based on the assertion. Default is to call configured userDetailsService and pass the username. Deployers
- * can override this method and retrieve the user based on any criteria they desire.
- *
- * @param assertion The CAS Assertion.
- * @return the UserDetails.
- */
- protected UserDetails loadUserByAssertion(final Assertion assertion) {
- final CasAssertionAuthenticationToken token = new CasAssertionAuthenticationToken(assertion, "");
- return this.authenticationUserDetailsService.loadUserDetails(token);
- }
-
- @Deprecated
- /**
- * @deprecated as of 3.0. Use the {@link org.springframework.security.cas.authentication.CasAuthenticationProvider#setAuthenticationUserDetailsService(org.springframework.security.core.userdetails.AuthenticationUserDetailsService)} instead.
- */
- public void setUserDetailsService(final UserDetailsService userDetailsService) {
- this.authenticationUserDetailsService = new UserDetailsByNameServiceWrapper(userDetailsService);
- }
-
- public void setAuthenticationUserDetailsService(final AuthenticationUserDetailsService authenticationUserDetailsService) {
- this.authenticationUserDetailsService = authenticationUserDetailsService;
- }
-
- public void setServiceProperties(final ServiceProperties serviceProperties) {
- this.serviceProperties = serviceProperties;
- }
-
- protected String getKey() {
- return key;
- }
-
- public void setKey(String key) {
- this.key = key;
- }
-
- public StatelessTicketCache getStatelessTicketCache() {
- return statelessTicketCache;
- }
-
- protected TicketValidator getTicketValidator() {
- return ticketValidator;
- }
-
- public void setMessageSource(final MessageSource messageSource) {
- this.messages = new MessageSourceAccessor(messageSource);
- }
-
- public void setStatelessTicketCache(final StatelessTicketCache statelessTicketCache) {
- this.statelessTicketCache = statelessTicketCache;
- }
-
- public void setTicketValidator(final TicketValidator ticketValidator) {
- this.ticketValidator = ticketValidator;
- }
-
- public boolean supports(final Class<? extends Object> authentication) {
- return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication)) ||
- (CasAuthenticationToken.class.isAssignableFrom(authentication)) ||
- (CasAssertionAuthenticationToken.class.isAssignableFrom(authentication));
- }
-}
diff --git a/dist/spring-security-cas-client/org/springframework/security/cas/authentication/CasAuthenticationToken.java b/dist/spring-security-cas-client/org/springframework/security/cas/authentication/CasAuthenticationToken.java
deleted file mode 100644
index c5ab824..0000000
--- a/dist/spring-security-cas-client/org/springframework/security/cas/authentication/CasAuthenticationToken.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/* Copyright 2004, 2005, 2006 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.cas.authentication;
-
-import java.io.Serializable;
-import java.util.Collection;
-
-import org.jasig.cas.client.validation.Assertion;
-import org.springframework.security.authentication.AbstractAuthenticationToken;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.userdetails.UserDetails;
-
-/**
- * Represents a successful CAS <code>Authentication</code>.
- *
- * @author Ben Alex
- * @author Scott Battaglia
- */
-public class CasAuthenticationToken extends AbstractAuthenticationToken implements Serializable {
- //~ Instance fields ================================================================================================
-
- private static final long serialVersionUID = 1L;
- private final Object credentials;
- private final Object principal;
- private final UserDetails userDetails;
- private final int keyHash;
- private final Assertion assertion;
-
- //~ Constructors ===================================================================================================
-
- /**
- * Constructor.
- *
- * @param key to identify if this object made by a given {@link
- * CasAuthenticationProvider}
- * @param principal typically the UserDetails object (cannot be <code>null</code>)
- * @param credentials the service/proxy ticket ID from CAS (cannot be
- * <code>null</code>)
- * @param authorities the authorities granted to the user (from the {@link
- * org.springframework.security.core.userdetails.UserDetailsService}) (cannot be <code>null</code>)
- * @param userDetails the user details (from the {@link
- * org.springframework.security.core.userdetails.UserDetailsService}) (cannot be <code>null</code>)
- * @param assertion the assertion returned from the CAS servers. It contains the principal and how to obtain a
- * proxy ticket for the user.
- *
- * @throws IllegalArgumentException if a <code>null</code> was passed
- */
- public CasAuthenticationToken(final String key, final Object principal, final Object credentials,
- final Collection<? extends GrantedAuthority> authorities, final UserDetails userDetails, final Assertion assertion) {
- super(authorities);
-
- if ((key == null) || ("".equals(key)) || (principal == null) || "".equals(principal) || (credentials == null)
- || "".equals(credentials) || (authorities == null) || (userDetails == null) || (assertion == null)) {
- throw new IllegalArgumentException("Cannot pass null or empty values to constructor");
- }
-
- this.keyHash = key.hashCode();
- this.principal = principal;
- this.credentials = credentials;
- this.userDetails = userDetails;
- this.assertion = assertion;
- setAuthenticated(true);
- }
-
- //~ Methods ========================================================================================================
-
- public boolean equals(final Object obj) {
- if (!super.equals(obj)) {
- return false;
- }
-
- if (obj instanceof CasAuthenticationToken) {
- CasAuthenticationToken test = (CasAuthenticationToken) obj;
-
- if (!this.assertion.equals(test.getAssertion())) {
- return false;
- }
-
- if (this.getKeyHash() != test.getKeyHash()) {
- return false;
- }
-
- return true;
- }
-
- return false;
- }
-
- public Object getCredentials() {
- return this.credentials;
- }
-
- public int getKeyHash() {
- return this.keyHash;
- }
-
- public Object getPrincipal() {
- return this.principal;
- }
-
- public Assertion getAssertion() {
- return this.assertion;
- }
-
- public UserDetails getUserDetails() {
- return userDetails;
- }
-
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append(super.toString());
- sb.append(" Assertion: ").append(this.assertion);
- sb.append(" Credentials (Service/Proxy Ticket): ").append(this.credentials);
-
- return (sb.toString());
- }
-}
diff --git a/dist/spring-security-cas-client/org/springframework/security/cas/authentication/EhCacheBasedTicketCache.java b/dist/spring-security-cas-client/org/springframework/security/cas/authentication/EhCacheBasedTicketCache.java
deleted file mode 100644
index abbc5c7..0000000
--- a/dist/spring-security-cas-client/org/springframework/security/cas/authentication/EhCacheBasedTicketCache.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/* Copyright 2004, 2005, 2006 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.cas.authentication;
-
-import net.sf.ehcache.CacheException;
-import net.sf.ehcache.Element;
-import net.sf.ehcache.Ehcache;
-
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.springframework.beans.factory.InitializingBean;
-
-import org.springframework.dao.DataRetrievalFailureException;
-
-import org.springframework.util.Assert;
-
-
-/**
- * Caches tickets using a Spring IoC defined <A HREF="http://ehcache.sourceforge.net">EHCACHE</a>.
- *
- * @author Ben Alex
- */
-public class EhCacheBasedTicketCache implements StatelessTicketCache, InitializingBean {
- //~ Static fields/initializers =====================================================================================
-
- private static final Log logger = LogFactory.getLog(EhCacheBasedTicketCache.class);
-
- //~ Instance fields ================================================================================================
-
- private Ehcache cache;
-
- //~ Methods ========================================================================================================
-
- public void afterPropertiesSet() throws Exception {
- Assert.notNull(cache, "cache mandatory");
- }
-
- public CasAuthenticationToken getByTicketId(final String serviceTicket) {
- try {
- final Element element = cache.get(serviceTicket);
-
- if (logger.isDebugEnabled()) {
- logger.debug("Cache hit: " + (element != null) + "; service ticket: " + serviceTicket);
- }
-
- return element == null ? null : (CasAuthenticationToken) element.getValue();
-
- } catch (CacheException cacheException) {
- throw new DataRetrievalFailureException("Cache failure: " + cacheException.getMessage());
- }
- }
-
- public Ehcache getCache() {
- return cache;
- }
-
- public void putTicketInCache(final CasAuthenticationToken token) {
- final Element element = new Element(token.getCredentials().toString(), token);
-
- if (logger.isDebugEnabled()) {
- logger.debug("Cache put: " + element.getKey());
- }
-
- cache.put(element);
- }
-
- public void removeTicketFromCache(final CasAuthenticationToken token) {
- if (logger.isDebugEnabled()) {
- logger.debug("Cache remove: " + token.getCredentials().toString());
- }
-
- this.removeTicketFromCache(token.getCredentials().toString());
- }
-
- public void removeTicketFromCache(final String serviceTicket) {
- cache.remove(serviceTicket);
- }
-
- public void setCache(final Ehcache cache) {
- this.cache = cache;
- }
-}
diff --git a/dist/spring-security-cas-client/org/springframework/security/cas/authentication/NullStatelessTicketCache.java b/dist/spring-security-cas-client/org/springframework/security/cas/authentication/NullStatelessTicketCache.java
deleted file mode 100644
index 9f63863..0000000
--- a/dist/spring-security-cas-client/org/springframework/security/cas/authentication/NullStatelessTicketCache.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/* Copyright 2004, 2005, 2006 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.security.cas.authentication;
-
-
-/**
- * Implementation of @link {@link StatelessTicketCache} that has no backing cache. Useful
- * in instances where storing of tickets for stateless session management is not required.
- * <p>
- * This is the default StatelessTicketCache of the @link {@link CasAuthenticationProvider} to
- * eliminate the unnecessary dependency on EhCache that applications have even if they are not using
- * the stateless session management.
- *
- * @author Scott Battaglia
- *
- *@see CasAuthenticationProvider
- */
-public final class NullStatelessTicketCache implements StatelessTicketCache {
-
- /**
- * @return null since we are not storing any tickets.
- */
- public CasAuthenticationToken getByTicketId(final String serviceTicket) {
- return null;
- }
-
- /**
- * This is a no-op since we are not storing tickets.
- */
- public void putTicketInCache(final CasAuthenticationToken token) {
- // nothing to do
- }
-
- /**
- * This is a no-op since we are not storing tickets.
- */
- public void removeTicketFromCache(final CasAuthenticationToken token) {
- // nothing to do
- }
-
- /**
- * This is a no-op since we are not storing tickets.
- */
- public void removeTicketFromCache(final String serviceTicket) {
- // nothing to do
- }
-}
diff --git a/dist/spring-security-cas-client/org/springframework/security/cas/authentication/StatelessTicketCache.java b/dist/spring-security-cas-client/org/springframework/security/cas/authentication/StatelessTicketCache.java
deleted file mode 100644
index 6d9b22e..0000000
--- a/dist/spring-security-cas-client/org/springframework/security/cas/authentication/StatelessTicketCache.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/* Copyright 2004 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.cas.authentication;
-
-/**
- * Caches CAS service tickets and CAS proxy tickets for stateless connections.
- *
- * <p>
- * When a service ticket or proxy ticket is validated against the CAS server,
- * it is unable to be used again. Most types of callers are stateful and are
- * associated with a given <code>HttpSession</code>. This allows the
- * affirmative CAS validation outcome to be stored in the
- * <code>HttpSession</code>, meaning the removal of the ticket from the CAS
- * server is not an issue.
- * </p>
- *
- * <P>
- * Stateless callers, such as remoting protocols, cannot take advantage of
- * <code>HttpSession</code>. If the stateless caller is located a significant
- * network distance from the CAS server, acquiring a fresh service ticket or
- * proxy ticket for each invocation would be expensive.
- * </p>
- *
- * <P>
- * To avoid this issue with stateless callers, it is expected stateless callers
- * will obtain a single service ticket or proxy ticket, and then present this
- * same ticket to the Spring Security secured application on each
- * occasion. As no <code>HttpSession</code> is available for such callers, the
- * affirmative CAS validation outcome cannot be stored in this location.
- * </p>
- *
- * <P>
- * The <code>StatelessTicketCache</code> enables the service tickets and proxy
- * tickets belonging to stateless callers to be placed in a cache. This
- * in-memory cache stores the <code>CasAuthenticationToken</code>, effectively
- * providing the same capability as a <code>HttpSession</code> with the ticket
- * identifier being the key rather than a session identifier.
- * </p>
- *
- * <P>
- * Implementations should provide a reasonable timeout on stored entries, such
- * that the stateless caller are not required to unnecessarily acquire fresh
- * CAS service tickets or proxy tickets.
- * </p>
- *
- * @author Ben Alex
- */
-public interface StatelessTicketCache {
- //~ Methods ================================================================
-
- /**
- * Retrieves the <code>CasAuthenticationToken</code> associated with the
- * specified ticket.
- *
- * <P>
- * If not found, returns a
- * <code>null</code><code>CasAuthenticationToken</code>.
- * </p>
- *
- * @return the fully populated authentication token
- */
- CasAuthenticationToken getByTicketId(String serviceTicket);
-
- /**
- * Adds the specified <code>CasAuthenticationToken</code> to the cache.
- *
- * <P>
- * The {@link CasAuthenticationToken#getCredentials()} method is used to
- * retrieve the service ticket number.
- * </p>
- *
- * @param token to be added to the cache
- */
- void putTicketInCache(CasAuthenticationToken token);
-
- /**
- * Removes the specified ticket from the cache, as per {@link
- * #removeTicketFromCache(String)}.
- *
- * <P>
- * Implementations should use {@link
- * CasAuthenticationToken#getCredentials()} to obtain the ticket and then
- * delegate to to the {@link #removeTicketFromCache(String)} method.
- * </p>
- *
- * @param token to be removed
- */
- void removeTicketFromCache(CasAuthenticationToken token);
-
- /**
- * Removes the specified ticket from the cache, meaning that future calls
- * will require a new service ticket.
- *
- * <P>
- * This is in case applications wish to provide a session termination
- * capability for their stateless clients.
- * </p>
- *
- * @param serviceTicket to be removed
- */
- void removeTicketFromCache(String serviceTicket);
-}
diff --git a/dist/spring-security-cas-client/org/springframework/security/cas/authentication/package-info.java b/dist/spring-security-cas-client/org/springframework/security/cas/authentication/package-info.java
deleted file mode 100644
index 6671180..0000000
--- a/dist/spring-security-cas-client/org/springframework/security/cas/authentication/package-info.java
+++ /dev/null
@@ -1,5 +0,0 @@
-/**
- * An {@code AuthenticationProvider} that can process CAS service tickets and proxy tickets.
- */
-package org.springframework.security.cas.authentication;
-
diff --git a/dist/spring-security-cas-client/org/springframework/security/cas/package-info.java b/dist/spring-security-cas-client/org/springframework/security/cas/package-info.java
deleted file mode 100644
index 6f1ef76..0000000
--- a/dist/spring-security-cas-client/org/springframework/security/cas/package-info.java
+++ /dev/null
@@ -1,5 +0,0 @@
-/**
- * Spring Security support for Jasig's Central Authentication Service (<a href="http://www.jasig.org/cas">CAS</a>).
- */
-package org.springframework.security.cas;
-
diff --git a/dist/spring-security-cas-client/org/springframework/security/cas/userdetails/AbstractCasAssertionUserDetailsService.java b/dist/spring-security-cas-client/org/springframework/security/cas/userdetails/AbstractCasAssertionUserDetailsService.java
deleted file mode 100644
index c62885b..0000000
--- a/dist/spring-security-cas-client/org/springframework/security/cas/userdetails/AbstractCasAssertionUserDetailsService.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/* Copyright 2004, 2005, 2006 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.security.cas.userdetails;
-
-import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.security.core.userdetails.UsernameNotFoundException;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.cas.authentication.CasAssertionAuthenticationToken;
-import org.springframework.util.Assert;
-import org.jasig.cas.client.validation.Assertion;
-
-/**
- * Abstract class for using the provided CAS assertion to construct a new User object. This generally is most
- * useful when combined with a SAML-based response from the CAS Server/client.
- *
- * @author Scott Battaglia
- * @since 3.0
- */
-public abstract class AbstractCasAssertionUserDetailsService implements AuthenticationUserDetailsService {
-
- public final UserDetails loadUserDetails(final Authentication token) throws UsernameNotFoundException {
- Assert.isInstanceOf(CasAssertionAuthenticationToken.class, token, "The provided token MUST be an instance of CasAssertionAuthenticationToken.class");
- return loadUserDetails(((CasAssertionAuthenticationToken) token).getAssertion());
- }
-
- /**
- * Protected template method for construct a {@link org.springframework.security.core.userdetails.UserDetails} via the supplied CAS
- * assertion.
- *
- * @param assertion the assertion to use to construct the new UserDetails. CANNOT be NULL.
- * @return the newly constructed UserDetails.
- */
- protected abstract UserDetails loadUserDetails(Assertion assertion);
-}
diff --git a/dist/spring-security-cas-client/org/springframework/security/cas/userdetails/GrantedAuthorityFromAssertionAttributesUserDetailsService.java b/dist/spring-security-cas-client/org/springframework/security/cas/userdetails/GrantedAuthorityFromAssertionAttributesUserDetailsService.java
deleted file mode 100644
index b6adc85..0000000
--- a/dist/spring-security-cas-client/org/springframework/security/cas/userdetails/GrantedAuthorityFromAssertionAttributesUserDetailsService.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/* Copyright 2004, 2005, 2006 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.security.cas.userdetails;
-
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.security.core.userdetails.User;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.authority.GrantedAuthorityImpl;
-import org.springframework.util.Assert;
-import org.jasig.cas.client.validation.Assertion;
-
-import java.util.List;
-import java.util.ArrayList;
-
-/**
- * Populates the {@link org.springframework.security.core.GrantedAuthority}s for a user by reading a list of attributes that were returned as
- * part of the CAS response. Each attribute is read and each value of the attribute is turned into a GrantedAuthority. If the attribute has no
- * value then its not added.
- *
- * @author Scott Battaglia
- * @since 3.0
- */
-public final class GrantedAuthorityFromAssertionAttributesUserDetailsService extends AbstractCasAssertionUserDetailsService {
-
- private static final String NON_EXISTENT_PASSWORD_VALUE = "NO_PASSWORD";
-
- private String[] attributes;
-
- private boolean convertToUpperCase = true;
-
- public GrantedAuthorityFromAssertionAttributesUserDetailsService(final String[] attributes) {
- Assert.notNull(attributes, "attributes cannot be null.");
- Assert.isTrue(attributes.length > 0, "At least one attribute is required to retrieve roles from.");
- this.attributes = attributes;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- protected UserDetails loadUserDetails(final Assertion assertion) {
- final List<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();
-
- for (final String attribute : this.attributes) {
- final Object value = assertion.getPrincipal().getAttributes().get(attribute);
-
- if (value == null) {
- continue;
- }
-
- if (value instanceof List) {
- final List list = (List) value;
-
- for (final Object o : list) {
- grantedAuthorities.add(new GrantedAuthorityImpl(this.convertToUpperCase ? o.toString().toUpperCase() : o.toString()));
- }
-
- } else {
- grantedAuthorities.add(new GrantedAuthorityImpl(this.convertToUpperCase ? value.toString().toUpperCase() : value.toString()));
- }
-
- }
-
- return new User(assertion.getPrincipal().getName(), NON_EXISTENT_PASSWORD_VALUE, true, true, true, true, grantedAuthorities);
- }
-
- /**
- * Converts the returned attribute values to uppercase values.
- *
- * @param convertToUpperCase true if it should convert, false otherwise.
- */
- public void setConvertToUpperCase(final boolean convertToUpperCase) {
- this.convertToUpperCase = convertToUpperCase;
- }
-}
diff --git a/dist/spring-security-cas-client/org/springframework/security/cas/web/CasAuthenticationEntryPoint.java b/dist/spring-security-cas-client/org/springframework/security/cas/web/CasAuthenticationEntryPoint.java
deleted file mode 100644
index cb4a8a2..0000000
--- a/dist/spring-security-cas-client/org/springframework/security/cas/web/CasAuthenticationEntryPoint.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/* Copyright 2004, 2005, 2006 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.cas.web;
-
-import java.io.IOException;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.jasig.cas.client.util.CommonUtils;
-import org.springframework.security.cas.ServiceProperties;
-import org.springframework.security.core.AuthenticationException;
-import org.springframework.security.web.AuthenticationEntryPoint;
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.util.Assert;
-
-
-/**
- * Used by the <code>ExceptionTranslationFilter</code> to commence authentication via the JA-SIG Central
- * Authentication Service (CAS).
- * <p>
- * The user's browser will be redirected to the JA-SIG CAS enterprise-wide login page.
- * This page is specified by the <code>loginUrl</code> property. Once login is complete, the CAS login page will
- * redirect to the page indicated by the <code>service</code> property. The <code>service</code> is a HTTP URL
- * belonging to the current application. The <code>service</code> URL is monitored by the {@link CasAuthenticationFilter},
- * which will validate the CAS login was successful.
- *
- * @author Ben Alex
- * @author Scott Battaglia
- */
-public class CasAuthenticationEntryPoint implements AuthenticationEntryPoint, InitializingBean {
- //~ Instance fields ================================================================================================
- private ServiceProperties serviceProperties;
-
- private String loginUrl;
-
- /**
- * Determines whether the Service URL should include the session id for the specific user. As of CAS 3.0.5, the
- * session id will automatically be stripped. However, older versions of CAS (i.e. CAS 2), do not automatically
- * strip the session identifier (this is a bug on the part of the older server implementations), so an option to
- * disable the session encoding is provided for backwards compatibility.
- *
- * By default, encoding is enabled.
- * @deprecated since 3.0.0 because CAS is currently on 3.3.5.
- */
- @Deprecated
- private boolean encodeServiceUrlWithSessionId = true;
-
- //~ Methods ========================================================================================================
-
- public void afterPropertiesSet() throws Exception {
- Assert.hasLength(this.loginUrl, "loginUrl must be specified");
- Assert.notNull(this.serviceProperties, "serviceProperties must be specified");
- }
-
- public final void commence(final HttpServletRequest servletRequest, final HttpServletResponse response,
- final AuthenticationException authenticationException) throws IOException, ServletException {
-
- final String urlEncodedService = createServiceUrl(servletRequest, response);
- final String redirectUrl = createRedirectUrl(urlEncodedService);
-
- preCommence(servletRequest, response);
-
- response.sendRedirect(redirectUrl);
- }
-
- /**
- * Constructs a new Service Url. The default implementation relies on the CAS client to do the bulk of the work.
- * @param request the HttpServletRequest
- * @param response the HttpServlet Response
- * @return the constructed service url. CANNOT be NULL.
- */
- protected String createServiceUrl(final HttpServletRequest request, final HttpServletResponse response) {
- return CommonUtils.constructServiceUrl(null, response, this.serviceProperties.getService(), null, this.serviceProperties.getArtifactParameter(), this.encodeServiceUrlWithSessionId);
- }
-
- /**
- * Constructs the Url for Redirection to the CAS server. Default implementation relies on the CAS client to do the bulk of the work.
- *
- * @param serviceUrl the service url that should be included.
- * @return the redirect url. CANNOT be NULL.
- */
- protected String createRedirectUrl(final String serviceUrl) {
- return CommonUtils.constructRedirectUrl(this.loginUrl, this.serviceProperties.getServiceParameter(), serviceUrl, this.serviceProperties.isSendRenew(), false);
- }
-
- /**
- * Template method for you to do your own pre-processing before the redirect occurs.
- *
- * @param request the HttpServletRequest
- * @param response the HttpServletResponse
- */
- protected void preCommence(final HttpServletRequest request, final HttpServletResponse response) {
-
- }
-
- /**
- * The enterprise-wide CAS login URL. Usually something like
- * <code>https://www.mycompany.com/cas/login</code>.
- *
- * @return the enterprise-wide CAS login URL
- */
- public final String getLoginUrl() {
- return this.loginUrl;
- }
-
- public final ServiceProperties getServiceProperties() {
- return this.serviceProperties;
- }
-
- public final void setLoginUrl(final String loginUrl) {
- this.loginUrl = loginUrl;
- }
-
- public final void setServiceProperties(final ServiceProperties serviceProperties) {
- this.serviceProperties = serviceProperties;
- }
-
- /**
- * Sets whether to encode the service url with the session id or not.
- *
- * @param encodeServiceUrlWithSessionId whether to encode the service url with the session id or not.
- * @deprecated since 3.0.0 because CAS is currently on 3.3.5.
- */
- @Deprecated
- public final void setEncodeServiceUrlWithSessionId(final boolean encodeServiceUrlWithSessionId) {
- this.encodeServiceUrlWithSessionId = encodeServiceUrlWithSessionId;
- }
-
- /**
- * Sets whether to encode the service url with the session id or not.
- * @return whether to encode the service url with the session id or not.
- *
- * @deprecated since 3.0.0 because CAS is currently on 3.3.5.
- */
- @Deprecated
- protected boolean getEncodeServiceUrlWithSessionId() {
- return this.encodeServiceUrlWithSessionId;
- }
-}
diff --git a/dist/spring-security-cas-client/org/springframework/security/cas/web/CasAuthenticationFilter.java b/dist/spring-security-cas-client/org/springframework/security/cas/web/CasAuthenticationFilter.java
deleted file mode 100644
index 314a1fd..0000000
--- a/dist/spring-security-cas-client/org/springframework/security/cas/web/CasAuthenticationFilter.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/* Copyright 2004, 2005, 2006 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.cas.web;
-
-import java.io.IOException;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage;
-import org.jasig.cas.client.util.CommonUtils;
-import org.jasig.cas.client.validation.TicketValidator;
-import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
-import org.springframework.security.cas.ServiceProperties;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.AuthenticationException;
-import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
-
-
-/**
- * Processes a CAS service ticket.
- * <p>
- * A service ticket consists of an opaque ticket string. It arrives at this filter by the user's browser successfully
- * authenticating using CAS, and then receiving a HTTP redirect to a <code>service</code>. The opaque ticket string is
- * presented in the <code>ticket</code> request parameter. This filter monitors the <code>service</code> URL so it can
- * receive the service ticket and process it. The CAS server knows which <code>service</code> URL to use via the
- * {@link ServiceProperties#getService()} method.
- * <p>
- * Processing the service ticket involves creating a <code>UsernamePasswordAuthenticationToken</code> which
- * uses {@link #CAS_STATEFUL_IDENTIFIER} for the <code>principal</code> and the opaque ticket string as the
- * <code>credentials</code>.
- * <p>
- * The configured <code>AuthenticationManager</code> is expected to provide a provider that can recognise
- * <code>UsernamePasswordAuthenticationToken</code>s containing this special <code>principal</code> name, and process
- * them accordingly by validation with the CAS server.
- * <p>
- * By configuring a shared {@link ProxyGrantingTicketStorage} between the {@link TicketValidator} and the
- * CasAuthenticationFilter one can have the CasAuthenticationFilter handle the proxying requirements for CAS. In addition, the
- * URI endpoint for the proxying would also need to be configured (i.e. the part after protocol, hostname, and port).
- * <p>
- * By default this filter processes the URL <tt>/j_spring_cas_security_check</tt>.
- *
- * @author Ben Alex
- */
-public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
- //~ Static fields/initializers =====================================================================================
-
- /** Used to identify a CAS request for a stateful user agent, such as a web browser. */
- public static final String CAS_STATEFUL_IDENTIFIER = "_cas_stateful_";
-
- /**
- * Used to identify a CAS request for a stateless user agent, such as a remoting protocol client (e.g.
- * Hessian, Burlap, SOAP etc). Results in a more aggressive caching strategy being used, as the absence of a
- * <code>HttpSession</code> will result in a new authentication attempt on every request.
- */
- public static final String CAS_STATELESS_IDENTIFIER = "_cas_stateless_";
-
- /**
- * The last portion of the receptor url, i.e. /proxy/receptor
- */
- private String proxyReceptorUrl;
-
- /**
- * The backing storage to store ProxyGrantingTicket requests.
- */
- private ProxyGrantingTicketStorage proxyGrantingTicketStorage;
-
- private String artifactParameter = ServiceProperties.DEFAULT_CAS_ARTIFACT_PARAMETER;
-
- //~ Constructors ===================================================================================================
-
- public CasAuthenticationFilter() {
- super("/j_spring_cas_security_check");
- }
-
- //~ Methods ========================================================================================================
-
- public Authentication attemptAuthentication(final HttpServletRequest request, final HttpServletResponse response)
- throws AuthenticationException {
- final String username = CAS_STATEFUL_IDENTIFIER;
- String password = request.getParameter(this.artifactParameter);
-
- if (password == null) {
- password = "";
- }
-
- final UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
-
- authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
-
- return this.getAuthenticationManager().authenticate(authRequest);
- }
-
- /**
- * Overridden to provide proxying capabilities.
- */
- protected boolean requiresAuthentication(final HttpServletRequest request, final HttpServletResponse response) {
- final String requestUri = request.getRequestURI();
-
- if (CommonUtils.isEmpty(this.proxyReceptorUrl) || !requestUri.endsWith(this.proxyReceptorUrl) || this.proxyGrantingTicketStorage == null) {
- return super.requiresAuthentication(request, response);
- }
-
- try {
- CommonUtils.readAndRespondToProxyReceptorRequest(request, response, this.proxyGrantingTicketStorage);
- return false;
- } catch (final IOException e) {
- return super.requiresAuthentication(request, response);
- }
- }
-
- public final void setProxyReceptorUrl(final String proxyReceptorUrl) {
- this.proxyReceptorUrl = proxyReceptorUrl;
- }
-
- public final void setProxyGrantingTicketStorage(
- final ProxyGrantingTicketStorage proxyGrantingTicketStorage) {
- this.proxyGrantingTicketStorage = proxyGrantingTicketStorage;
- }
-
- public final void setServiceProperties(final ServiceProperties serviceProperties) {
- this.artifactParameter = serviceProperties.getArtifactParameter();
- }
-}
diff --git a/dist/spring-security-cas-client/org/springframework/security/cas/web/package-info.java b/dist/spring-security-cas-client/org/springframework/security/cas/web/package-info.java
deleted file mode 100644
index b370ab5..0000000
--- a/dist/spring-security-cas-client/org/springframework/security/cas/web/package-info.java
+++ /dev/null
@@ -1,5 +0,0 @@
-/**
- * Authenticates standard web browser users via CAS.
- */
-package org.springframework.security.cas.web;
-
diff --git a/dist/spring-security-config/META-INF/MANIFEST.MF b/dist/spring-security-config/META-INF/MANIFEST.MF
index 351fd34..58630c0 100644
--- a/dist/spring-security-config/META-INF/MANIFEST.MF
+++ b/dist/spring-security-config/META-INF/MANIFEST.MF
@@ -1,4 +1,2 @@
Manifest-Version: 1.0
-Archiver-Version: Plexus Archiver
-Created-By: 17.1-b03-307 (Apple Inc.)
diff --git a/dist/spring-security-config/META-INF/spring.handlers b/dist/spring-security-config/META-INF/spring.handlers
deleted file mode 100644
index 8b8a959..0000000
--- a/dist/spring-security-config/META-INF/spring.handlers
+++ /dev/null
@@ -1 +0,0 @@
-http\://www.springframework.org/schema/security=org.springframework.security.config.SecurityNamespaceHandler
diff --git a/dist/spring-security-config/META-INF/spring.schemas b/dist/spring-security-config/META-INF/spring.schemas
deleted file mode 100644
index fb8035b..0000000
--- a/dist/spring-security-config/META-INF/spring.schemas
+++ /dev/null
@@ -1,8 +0,0 @@
-http\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-3.0.4.xsd
-http\://www.springframework.org/schema/security/spring-security-3.0.xsd=org/springframework/security/config/spring-security-3.0.xsd
-http\://www.springframework.org/schema/security/spring-security-3.0.4.xsd=org/springframework/security/config/spring-security-3.0.4.xsd
-http\://www.springframework.org/schema/security/spring-security-3.0.3.xsd=org/springframework/security/config/spring-security-3.0.3.xsd
-http\://www.springframework.org/schema/security/spring-security-2.0.xsd=org/springframework/security/config/spring-security-2.0.xsd
-http\://www.springframework.org/schema/security/spring-security-2.0.1.xsd=org/springframework/security/config/spring-security-2.0.1.xsd
-http\://www.springframework.org/schema/security/spring-security-2.0.2.xsd=org/springframework/security/config/spring-security-2.0.2.xsd
-http\://www.springframework.org/schema/security/spring-security-2.0.4.xsd=org/springframework/security/config/spring-security-2.0.4.xsd
diff --git a/dist/spring-security-config/org/springframework/security/config/BeanIds.java b/dist/spring-security-config/org/springframework/security/config/BeanIds.java
index b81b52f..077904a 100644
--- a/dist/spring-security-config/org/springframework/security/config/BeanIds.java
+++ b/dist/spring-security-config/org/springframework/security/config/BeanIds.java
@@ -6,6 +6,7 @@ package org.springframework.security.config;
* These are intended for internal use.
*
* @author Ben Alex
+ * @author Luke Taylor
*/
public abstract class BeanIds {
private static final String PREFIX = "org.springframework.security.";
@@ -19,12 +20,16 @@ public abstract class BeanIds {
public static final String CONTEXT_SOURCE_SETTING_POST_PROCESSOR = PREFIX + "contextSettingPostProcessor";
public static final String USER_DETAILS_SERVICE = PREFIX + "userDetailsService";
+ public static final String USER_DETAILS_SERVICE_FACTORY = PREFIX + "userDetailsServiceFactory";
public static final String METHOD_ACCESS_MANAGER = PREFIX + "defaultMethodAccessManager";
public static final String FILTER_CHAIN_PROXY = PREFIX + "filterChainProxy";
+ public static final String FILTER_CHAINS = PREFIX + "filterChains";
public static final String METHOD_SECURITY_METADATA_SOURCE_ADVISOR = PREFIX + "methodSecurityMetadataSourceAdvisor";
public static final String EMBEDDED_APACHE_DS = PREFIX + "apacheDirectoryServerContainer";
public static final String CONTEXT_SOURCE = PREFIX + "securityContextSource";
+
+ public static final String DEBUG_FILTER = PREFIX + "debugFilter";
}
diff --git a/dist/spring-security-config/org/springframework/security/config/Elements.java b/dist/spring-security-config/org/springframework/security/config/Elements.java
index 685b552..3efc60f 100644
--- a/dist/spring-security-config/org/springframework/security/config/Elements.java
+++ b/dist/spring-security-config/org/springframework/security/config/Elements.java
@@ -1,7 +1,7 @@
package org.springframework.security.config;
/**
- * Contains all the element names used by Spring Security 2 namespace support.
+ * Contains all the element names used by Spring Security 3 namespace support.
*
* @author Ben Alex
*/
@@ -46,9 +46,12 @@ public abstract class Elements {
public static final String CUSTOM_FILTER = "custom-filter";
public static final String REQUEST_CACHE = "request-cache";
public static final String X509 = "x509";
+ public static final String JEE = "jee";
public static final String FILTER_SECURITY_METADATA_SOURCE = "filter-security-metadata-source";
+ public static final String METHOD_SECURITY_METADATA_SOURCE = "method-security-metadata-source";
@Deprecated
public static final String FILTER_INVOCATION_DEFINITION_SOURCE = "filter-invocation-definition-source";
public static final String LDAP_PASSWORD_COMPARE = "password-compare";
+ public static final String DEBUG = "debug";
public static final String HTTP_FIREWALL = "http-firewall";
}
diff --git a/dist/spring-security-config/org/springframework/security/config/SecurityNamespaceHandler.java b/dist/spring-security-config/org/springframework/security/config/SecurityNamespaceHandler.java
index 0e3d31e..e2f295d 100644
--- a/dist/spring-security-config/org/springframework/security/config/SecurityNamespaceHandler.java
+++ b/dist/spring-security-config/org/springframework/security/config/SecurityNamespaceHandler.java
@@ -1,8 +1,5 @@
package org.springframework.security.config;
-import java.util.HashMap;
-import java.util.Map;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.config.BeanDefinition;
@@ -15,6 +12,7 @@ import org.springframework.security.config.authentication.AuthenticationManagerB
import org.springframework.security.config.authentication.AuthenticationProviderBeanDefinitionParser;
import org.springframework.security.config.authentication.JdbcUserServiceBeanDefinitionParser;
import org.springframework.security.config.authentication.UserServiceBeanDefinitionParser;
+import org.springframework.security.config.http.FilterChainBeanDefinitionParser;
import org.springframework.security.config.http.FilterChainMapBeanDefinitionDecorator;
import org.springframework.security.config.http.FilterInvocationSecurityMetadataSourceParser;
import org.springframework.security.config.http.HttpFirewallBeanDefinitionParser;
@@ -24,11 +22,14 @@ import org.springframework.security.config.ldap.LdapServerBeanDefinitionParser;
import org.springframework.security.config.ldap.LdapUserServiceBeanDefinitionParser;
import org.springframework.security.config.method.GlobalMethodSecurityBeanDefinitionParser;
import org.springframework.security.config.method.InterceptMethodsBeanDefinitionDecorator;
+import org.springframework.security.config.method.MethodSecurityMetadataSourceBeanDefinitionParser;
import org.springframework.security.core.SpringSecurityCoreVersion;
import org.springframework.util.ClassUtils;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
+import java.util.*;
+
/**
* Parses elements from the "security" namespace (http://www.springframework.org/schema/security).
*
@@ -38,7 +39,6 @@ import org.w3c.dom.Node;
*/
public final class SecurityNamespaceHandler implements NamespaceHandler {
private final Log logger = LogFactory.getLog(getClass());
-
private final Map<String, BeanDefinitionParser> parsers = new HashMap<String, BeanDefinitionParser>();
private final BeanDefinitionDecorator interceptMethodsBDD = new InterceptMethodsBeanDefinitionDecorator();
private BeanDefinitionDecorator filterChainMapBDD;
@@ -63,9 +63,8 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
public BeanDefinition parse(Element element, ParserContext pc) {
if (!namespaceMatchesVersion(element)) {
- pc.getReaderContext().fatal("You must use a 3.0 schema with Spring Security 3.0." +
- "(2.0 or 3.1 versions are not valid)" +
- " Please update your schema declarations to the 3.0.3 schema (spring-security-3.0.3.xsd).", element);
+ pc.getReaderContext().fatal("You cannot use a spring-security-2.0.xsd or spring-security-3.0.xsd schema " +
+ "with Spring Security 3.1. Please update your schema declarations to the 3.1 schema.", element);
}
String name = pc.getDelegate().getLocalName(element);
BeanDefinitionParser parser = parsers.get(name);
@@ -76,18 +75,20 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
}
if (parser == null) {
- if (Elements.HTTP.equals(name) || Elements.FILTER_SECURITY_METADATA_SOURCE.equals(name)) {
+ if (Elements.HTTP.equals(name) || Elements.FILTER_SECURITY_METADATA_SOURCE.equals(name) ||
+ Elements.FILTER_CHAIN_MAP.equals(name) || Elements.FILTER_CHAIN.equals(name)) {
reportMissingWebClasses(name, pc, element);
} else {
reportUnsupportedNodeType(name, pc, element);
}
+
+ return null;
}
return parser.parse(element, pc);
}
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext pc) {
- BeanDefinitionDecorator decorator = null;
String name = pc.getDelegate().getLocalName(node);
// We only handle elements
@@ -107,9 +108,7 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
}
}
- if (decorator == null) {
- reportUnsupportedNodeType(name, pc, node);
- }
+ reportUnsupportedNodeType(name, pc, node);
return null;
}
@@ -120,8 +119,8 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
}
private void reportMissingWebClasses(String nodeName, ParserContext pc, Node node) {
- pc.getReaderContext().fatal("spring-security-web classes are not available. " +
- "You need these to use <" + Elements.FILTER_CHAIN_MAP + ">", node);
+ pc.getReaderContext().fatal("The classes from the spring-security-web jar " +
+ "(or one of its dependencies) are not available. You need these to use <" + nodeName + ">", node);
}
public void init() {
@@ -139,21 +138,30 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
parsers.put(Elements.AUTHENTICATION_PROVIDER, new AuthenticationProviderBeanDefinitionParser());
parsers.put(Elements.GLOBAL_METHOD_SECURITY, new GlobalMethodSecurityBeanDefinitionParser());
parsers.put(Elements.AUTHENTICATION_MANAGER, new AuthenticationManagerBeanDefinitionParser());
+ parsers.put(Elements.METHOD_SECURITY_METADATA_SOURCE, new MethodSecurityMetadataSourceBeanDefinitionParser());
// Only load the web-namespace parsers if the web classes are available
- if (ClassUtils.isPresent("org.springframework.security.web.FilterChainProxy", getClass().getClassLoader())) {
+ try {
+ ClassUtils.forName("org.springframework.security.web.FilterChainProxy", getClass().getClassLoader());
+ parsers.put(Elements.DEBUG, new DebugBeanDefinitionParser());
parsers.put(Elements.HTTP, new HttpSecurityBeanDefinitionParser());
parsers.put(Elements.HTTP_FIREWALL, new HttpFirewallBeanDefinitionParser());
parsers.put(Elements.FILTER_INVOCATION_DEFINITION_SOURCE, new FilterInvocationSecurityMetadataSourceParser());
parsers.put(Elements.FILTER_SECURITY_METADATA_SOURCE, new FilterInvocationSecurityMetadataSourceParser());
+ parsers.put(Elements.FILTER_CHAIN, new FilterChainBeanDefinitionParser());
filterChainMapBDD = new FilterChainMapBeanDefinitionDecorator();
+ } catch(Throwable t) {
+ logger.error("Failed to load required web classes", t);
}
}
/**
* Check that the schema location declared in the source file being parsed matches the Spring Security version.
- * The old 2.0 schema is not compatible with the new 3.0 parser, so it is an error to explicitly use
- * 3.0. It might be an error to declare spring-security.xsd as an alias, but you are only going to find that out
+ * The old 2.0 schema is not compatible with the 3.1 parser, so it is an error to explicitly use
+ * 2.0.
+ * <p>
+ * There are also differences between 3.0 and 3.1 which are sufficient that we report using 3.0 as an error too.
+ * It might be an error to declare spring-security.xsd as an alias, but you are only going to find that out
* when one of the sub parsers breaks.
*
* @param element the element that is to be parsed next
@@ -165,8 +173,8 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
private boolean matchesVersionInternal(Element element) {
String schemaLocation = element.getAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "schemaLocation");
- return schemaLocation.matches("(?m).*spring-security-3\\.0.*xsd.*")
- || schemaLocation.matches("(?m).*spring-security\\.xsd.*")
+ return schemaLocation.matches("(?m).*spring-security-3\\.1.*.xsd.*")
+ || schemaLocation.matches("(?m).*spring-security.xsd.*")
|| !schemaLocation.matches("(?m).*spring-security.*");
}
diff --git a/dist/spring-security-config/org/springframework/security/config/authentication/AuthenticationManagerBeanDefinitionParser.java b/dist/spring-security-config/org/springframework/security/config/authentication/AuthenticationManagerBeanDefinitionParser.java
index 5e4a30c..e576cf4 100644
--- a/dist/spring-security-config/org/springframework/security/config/authentication/AuthenticationManagerBeanDefinitionParser.java
+++ b/dist/spring-security-config/org/springframework/security/config/authentication/AuthenticationManagerBeanDefinitionParser.java
@@ -38,8 +38,14 @@ public class AuthenticationManagerBeanDefinitionParser implements BeanDefinition
private static final String ATT_ERASE_CREDENTIALS = "erase-credentials";
public BeanDefinition parse(Element element, ParserContext pc) {
- Assert.state(!pc.getRegistry().containsBeanDefinition(BeanIds.AUTHENTICATION_MANAGER),
- "AuthenticationManager has already been registered!");
+ String id = element.getAttribute("id");
+
+ if (!StringUtils.hasText(id)) {
+ if (pc.getRegistry().containsBeanDefinition(BeanIds.AUTHENTICATION_MANAGER)) {
+ pc.getReaderContext().warning("Overriding globally registered AuthenticationManager", pc.extractSource(element));
+ }
+ id = BeanIds.AUTHENTICATION_MANAGER;
+ }
pc.pushContainingComponent(new CompositeComponentDefinition(element.getTagName(), pc.extractSource(element)));
BeanDefinitionBuilder providerManagerBldr = BeanDefinitionBuilder.rootBeanDefinition(ProviderManager.class);
@@ -57,13 +63,24 @@ public class AuthenticationManagerBeanDefinitionParser implements BeanDefinition
if (node instanceof Element) {
Element providerElt = (Element)node;
if (StringUtils.hasText(providerElt.getAttribute(ATT_REF))) {
+ if (providerElt.getAttributes().getLength() > 1) {
+ pc.getReaderContext().error("authentication-provider element cannot be used with other attributes " +
+ "when using 'ref' attribute", pc.extractSource(element));
+ }
+ NodeList providerChildren = providerElt.getChildNodes();
+ for (int j = 0; j < providerChildren.getLength(); j++) {
+ if (providerChildren.item(j) instanceof Element) {
+ pc.getReaderContext().error("authentication-provider element cannot have child elements when used " +
+ "with 'ref' attribute", pc.extractSource(element));
+ }
+ }
providers.add(new RuntimeBeanReference(providerElt.getAttribute(ATT_REF)));
} else {
BeanDefinition provider = resolver.resolve(providerElt.getNamespaceURI()).parse(providerElt, pc);
Assert.notNull(provider, "Parser for " + providerElt.getNodeName() + " returned a null bean definition");
- String id = pc.getReaderContext().generateBeanName(provider);
- pc.registerBeanComponent(new BeanComponentDefinition(provider, id));
- providers.add(new RuntimeBeanReference(id));
+ String providerId = pc.getReaderContext().generateBeanName(provider);
+ pc.registerBeanComponent(new BeanComponentDefinition(provider, providerId));
+ providers.add(new RuntimeBeanReference(providerId));
}
}
}
@@ -72,24 +89,23 @@ public class AuthenticationManagerBeanDefinitionParser implements BeanDefinition
providers.add(new RootBeanDefinition(NullAuthenticationProvider.class));
}
- providerManagerBldr.addPropertyValue("providers", providers);
+ providerManagerBldr.addConstructorArgValue(providers);
- if ("true".equals(element.getAttribute(ATT_ERASE_CREDENTIALS))) {
- providerManagerBldr.addPropertyValue("eraseCredentialsAfterAuthentication", true);
+ if ("false".equals(element.getAttribute(ATT_ERASE_CREDENTIALS))) {
+ providerManagerBldr.addPropertyValue("eraseCredentialsAfterAuthentication", false);
}
// Add the default event publisher
BeanDefinition publisher = new RootBeanDefinition(DefaultAuthenticationEventPublisher.class);
- String id = pc.getReaderContext().generateBeanName(publisher);
- pc.registerBeanComponent(new BeanComponentDefinition(publisher, id));
- providerManagerBldr.addPropertyReference("authenticationEventPublisher", id);
+ String pubId = pc.getReaderContext().generateBeanName(publisher);
+ pc.registerBeanComponent(new BeanComponentDefinition(publisher, pubId));
+ providerManagerBldr.addPropertyReference("authenticationEventPublisher", pubId);
- pc.registerBeanComponent(
- new BeanComponentDefinition(providerManagerBldr.getBeanDefinition(), BeanIds.AUTHENTICATION_MANAGER));
+ pc.registerBeanComponent(new BeanComponentDefinition(providerManagerBldr.getBeanDefinition(), id));
if (StringUtils.hasText(alias)) {
- pc.getRegistry().registerAlias(BeanIds.AUTHENTICATION_MANAGER, alias);
- pc.getReaderContext().fireAliasRegistered(BeanIds.AUTHENTICATION_MANAGER, alias, pc.extractSource(element));
+ pc.getRegistry().registerAlias(id, alias);
+ pc.getReaderContext().fireAliasRegistered(id, alias, pc.extractSource(element));
}
pc.popAndRegisterContainingComponent();
@@ -117,7 +133,7 @@ public class AuthenticationManagerBeanDefinitionParser implements BeanDefinition
return null;
}
- public boolean supports(Class<? extends Object> authentication) {
+ public boolean supports(Class<?> authentication) {
return false;
}
}
diff --git a/dist/spring-security-config/org/springframework/security/config/authentication/AuthenticationManagerFactoryBean.java b/dist/spring-security-config/org/springframework/security/config/authentication/AuthenticationManagerFactoryBean.java
index 4ddf156..b2c2655 100644
--- a/dist/spring-security-config/org/springframework/security/config/authentication/AuthenticationManagerFactoryBean.java
+++ b/dist/spring-security-config/org/springframework/security/config/authentication/AuthenticationManagerFactoryBean.java
@@ -19,8 +19,9 @@ import org.springframework.security.config.BeanIds;
*/
public class AuthenticationManagerFactoryBean implements FactoryBean<AuthenticationManager>, BeanFactoryAware {
private BeanFactory bf;
- public static final String MISSING_BEAN_ERROR_MESSAGE = "Did you forget to add an <authentication-manager> element " +
- "to your configuration (with child <authentication-provider> elements) ?";
+ public static final String MISSING_BEAN_ERROR_MESSAGE = "Did you forget to add a gobal <authentication-manager> element " +
+ "to your configuration (with child <authentication-provider> elements)? Alternatively you can use the " +
+ "authentication-manager-ref attribute on your <http> and <global-method-security> elements.";
public AuthenticationManager getObject() throws Exception {
try {
diff --git a/dist/spring-security-config/org/springframework/security/config/authentication/AuthenticationProviderBeanDefinitionParser.java b/dist/spring-security-config/org/springframework/security/config/authentication/AuthenticationProviderBeanDefinitionParser.java
index f354f6e..71704bb 100644
--- a/dist/spring-security-config/org/springframework/security/config/authentication/AuthenticationProviderBeanDefinitionParser.java
+++ b/dist/spring-security-config/org/springframework/security/config/authentication/AuthenticationProviderBeanDefinitionParser.java
@@ -18,7 +18,7 @@ import org.w3c.dom.Element;
* @author Luke Taylor
*/
public class AuthenticationProviderBeanDefinitionParser implements BeanDefinitionParser {
- private static String ATT_USER_DETAILS_REF = "user-service-ref";
+ private static final String ATT_USER_DETAILS_REF = "user-service-ref";
public BeanDefinition parse(Element element, ParserContext pc) {
RootBeanDefinition authProvider = new RootBeanDefinition(DaoAuthenticationProvider.class);
diff --git a/dist/spring-security-config/org/springframework/security/config/authentication/CachingUserDetailsService.java b/dist/spring-security-config/org/springframework/security/config/authentication/CachingUserDetailsService.java
index e72d677..364f18e 100644
--- a/dist/spring-security-config/org/springframework/security/config/authentication/CachingUserDetailsService.java
+++ b/dist/spring-security-config/org/springframework/security/config/authentication/CachingUserDetailsService.java
@@ -13,7 +13,7 @@ import org.springframework.util.Assert;
*/
public class CachingUserDetailsService implements UserDetailsService {
private UserCache userCache = new NullUserCache();
- private UserDetailsService delegate;
+ private final UserDetailsService delegate;
CachingUserDetailsService(UserDetailsService delegate) {
this.delegate = delegate;
diff --git a/dist/spring-security-config/org/springframework/security/config/authentication/PasswordEncoderParser.java b/dist/spring-security-config/org/springframework/security/config/authentication/PasswordEncoderParser.java
index 8af2300..5f8eb06 100644
--- a/dist/spring-security-config/org/springframework/security/config/authentication/PasswordEncoderParser.java
+++ b/dist/spring-security-config/org/springframework/security/config/authentication/PasswordEncoderParser.java
@@ -55,7 +55,7 @@ public class PasswordEncoderParser {
ENCODER_CLASSES.put(OPT_HASH_LDAP_SSHA, LdapShaPasswordEncoder.class);
}
- private static Log logger = LogFactory.getLog(PasswordEncoderParser.class);
+ private static final Log logger = LogFactory.getLog(PasswordEncoderParser.class);
private BeanMetadataElement passwordEncoder;
private BeanMetadataElement saltSource;
@@ -69,7 +69,7 @@ public class PasswordEncoderParser {
boolean useBase64 = false;
if (StringUtils.hasText(element.getAttribute(ATT_BASE_64))) {
- useBase64 = new Boolean(element.getAttribute(ATT_BASE_64)).booleanValue();
+ useBase64 = Boolean.valueOf(element.getAttribute(ATT_BASE_64)).booleanValue();
}
String ref = element.getAttribute(ATT_REF);
@@ -93,7 +93,7 @@ public class PasswordEncoderParser {
BeanDefinitionBuilder beanBldr = BeanDefinitionBuilder.rootBeanDefinition(beanClass);
if (OPT_HASH_SHA256.equals(hash)) {
- beanBldr.addConstructorArgValue(new Integer(256));
+ beanBldr.addConstructorArgValue(Integer.valueOf(256));
}
if (useBase64) {
diff --git a/dist/spring-security-config/org/springframework/security/config/authentication/UserServiceBeanDefinitionParser.java b/dist/spring-security-config/org/springframework/security/config/authentication/UserServiceBeanDefinitionParser.java
index 120c23c..e83b1d8 100644
--- a/dist/spring-security-config/org/springframework/security/config/authentication/UserServiceBeanDefinitionParser.java
+++ b/dist/spring-security-config/org/springframework/security/config/authentication/UserServiceBeanDefinitionParser.java
@@ -9,12 +9,12 @@ import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.support.ManagedMap;
+import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
-import org.springframework.security.core.userdetails.memory.UserMap;
+import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
@@ -24,7 +24,6 @@ import org.w3c.dom.Element;
* @author Luke Taylor
* @author Ben Alex
*/
- at SuppressWarnings("deprecation")
public class UserServiceBeanDefinitionParser extends AbstractUserDetailsServiceBeanDefinitionParser {
static final String ATT_PASSWORD = "password";
@@ -38,7 +37,7 @@ public class UserServiceBeanDefinitionParser extends AbstractUserDetailsServiceB
private SecureRandom random;
protected String getBeanClassName(Element element) {
- return "org.springframework.security.core.userdetails.memory.InMemoryDaoImpl";
+ return InMemoryUserDetailsManager.class.getName();
}
@SuppressWarnings("unchecked")
@@ -54,21 +53,20 @@ public class UserServiceBeanDefinitionParser extends AbstractUserDetailsServiceB
BeanDefinition bd = new RootBeanDefinition(PropertiesFactoryBean.class);
bd.getPropertyValues().addPropertyValue("location", userProperties);
- builder.addPropertyValue("userProperties", bd);
+ builder.addConstructorArgValue(bd);
return;
}
- if(CollectionUtils.isEmpty(userElts)) {
+ if (CollectionUtils.isEmpty(userElts)) {
throw new BeanDefinitionStoreException("You must supply user definitions, either with <" + ELT_USER + "> child elements or a " +
"properties file (using the '" + ATT_PROPERTIES + "' attribute)" );
}
- BeanDefinition userMap = new RootBeanDefinition(UserMap.class);
- ManagedMap<String, BeanDefinition> users = new ManagedMap<String, BeanDefinition>();
+ ManagedList<BeanDefinition> users = new ManagedList<BeanDefinition>();
- for (Iterator i = userElts.iterator(); i.hasNext();) {
- Element userElt = (Element) i.next();
+ for (Object elt : userElts) {
+ Element userElt = (Element) elt;
String userName = userElt.getAttribute(ATT_NAME);
String password = userElt.getAttribute(ATT_PASSWORD);
@@ -91,12 +89,10 @@ public class UserServiceBeanDefinitionParser extends AbstractUserDetailsServiceB
user.addConstructorArgValue(!locked);
user.addConstructorArgValue(authorities.getBeanDefinition());
- users.put(userName.toLowerCase(), user.getBeanDefinition());
+ users.add(user.getBeanDefinition());
}
- userMap.getPropertyValues().addPropertyValue("users", users);
-
- builder.addPropertyValue("userMap", userMap);
+ builder.addConstructorArgValue(users);
}
private String generateRandomPassword() {
diff --git a/dist/spring-security-config/org/springframework/security/config/catalog.xml b/dist/spring-security-config/org/springframework/security/config/catalog.xml
deleted file mode 100644
index f989707..0000000
--- a/dist/spring-security-config/org/springframework/security/config/catalog.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE catalog PUBLIC "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN" "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd">
-<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
- <system systemId="http://www.springframework.org/schema/security/spring-security-2.0.xsd" uri="spring-security-2.0.xsd"/>
-</catalog>
\ No newline at end of file
diff --git a/dist/spring-security-config/org/springframework/security/config/http/AuthenticationConfigBuilder.java b/dist/spring-security-config/org/springframework/security/config/http/AuthenticationConfigBuilder.java
index 2030366..5d0f6f3 100644
--- a/dist/spring-security-config/org/springframework/security/config/http/AuthenticationConfigBuilder.java
+++ b/dist/spring-security-config/org/springframework/security/config/http/AuthenticationConfigBuilder.java
@@ -2,11 +2,6 @@ package org.springframework.security.config.http;
import static org.springframework.security.config.http.SecurityFilters.*;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-import java.util.ArrayList;
-import java.util.List;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanMetadataElement;
@@ -18,28 +13,36 @@ import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
+import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.security.authentication.AnonymousAuthenticationProvider;
import org.springframework.security.authentication.RememberMeAuthenticationProvider;
+import org.springframework.security.config.BeanIds;
import org.springframework.security.config.Elements;
-import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper;
-import org.springframework.security.web.PortResolverImpl;
+import org.springframework.security.core.authority.mapping.SimpleAttributes2GrantedAuthoritiesMapper;
+import org.springframework.security.core.authority.mapping.SimpleMappableAttributesRetriever;
import org.springframework.security.web.access.AccessDeniedHandlerImpl;
import org.springframework.security.web.access.ExceptionTranslationFilter;
import org.springframework.security.web.authentication.AnonymousAuthenticationFilter;
import org.springframework.security.web.authentication.Http403ForbiddenEntryPoint;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider;
+import org.springframework.security.web.authentication.preauth.PreAuthenticatedGrantedAuthoritiesUserDetailsService;
+import org.springframework.security.web.authentication.preauth.j2ee.J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource;
+import org.springframework.security.web.authentication.preauth.j2ee.J2eePreAuthenticatedProcessingFilter;
import org.springframework.security.web.authentication.preauth.x509.SubjectDnX509PrincipalExtractor;
import org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter;
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
-import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
-import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
+import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
+import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
+import java.security.SecureRandom;
+import java.util.*;
+
/**
* Handles creation of authentication mechanism filters and related beans for <http> parsing.
*
@@ -54,10 +57,13 @@ final class AuthenticationConfigBuilder {
static final String OPEN_ID_AUTHENTICATION_PROCESSING_FILTER_CLASS = "org.springframework.security.openid.OpenIDAuthenticationFilter";
static final String OPEN_ID_AUTHENTICATION_PROVIDER_CLASS = "org.springframework.security.openid.OpenIDAuthenticationProvider";
- static final String OPEN_ID_CONSUMER_CLASS = "org.springframework.security.openid.OpenID4JavaConsumer";
+ private static final String OPEN_ID_CONSUMER_CLASS = "org.springframework.security.openid.OpenID4JavaConsumer";
static final String OPEN_ID_ATTRIBUTE_CLASS = "org.springframework.security.openid.OpenIDAttribute";
+ private static final String OPEN_ID_ATTRIBUTE_FACTORY_CLASS = "org.springframework.security.openid.RegexBasedAxFetchListFactory";
static final String AUTHENTICATION_PROCESSING_FILTER_CLASS = "org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter";
+ static final String ATT_AUTH_DETAILS_SOURCE_REF = "authentication-details-source-ref";
+
private static final String ATT_AUTO_CONFIG = "auto-config";
private static final String ATT_ACCESS_DENIED_PAGE = "access-denied-page";
@@ -66,14 +72,13 @@ final class AuthenticationConfigBuilder {
private static final String ATT_USER_SERVICE_REF = "user-service-ref";
- private static final String ATT_REF = "ref";
+ private static final String ATT_KEY = "key";
- private Element httpElt;
- private ParserContext pc;
+ private final Element httpElt;
+ private final ParserContext pc;
private final boolean autoConfig;
private final boolean allowSessionCreation;
- private final String portMapperName;
private RootBeanDefinition anonymousFilter;
private BeanReference anonymousProviderRef;
@@ -81,44 +86,47 @@ final class AuthenticationConfigBuilder {
private String rememberMeServicesId;
private BeanReference rememberMeProviderRef;
private BeanDefinition basicFilter;
- private BeanReference basicEntryPoint;
- private RootBeanDefinition formFilter;
+ private RuntimeBeanReference basicEntryPoint;
private BeanDefinition formEntryPoint;
- private RootBeanDefinition openIDFilter;
private BeanDefinition openIDEntryPoint;
private BeanReference openIDProviderRef;
- private String openIDProviderId;
private String formFilterId = null;
private String openIDFilterId = null;
private BeanDefinition x509Filter;
- private BeanDefinition x509EntryPoint;
private BeanReference x509ProviderRef;
- private String x509ProviderId;
+ private BeanDefinition jeeFilter;
+ private BeanReference jeeProviderRef;
+ private RootBeanDefinition preAuthEntryPoint;
+
private BeanDefinition logoutFilter;
private BeanDefinition loginPageGenerationFilter;
private BeanDefinition etf;
- private BeanReference requestCache;
-
- final SecureRandom random;
+ private final BeanReference requestCache;
- public AuthenticationConfigBuilder(Element element, ParserContext pc, boolean allowSessionCreation,
- String portMapperName) {
+ public AuthenticationConfigBuilder(Element element, ParserContext pc, SessionCreationPolicy sessionPolicy,
+ BeanReference requestCache, BeanReference authenticationManager, BeanReference sessionStrategy) {
this.httpElt = element;
this.pc = pc;
- this.portMapperName = portMapperName;
+ this.requestCache = requestCache;
autoConfig = "true".equals(element.getAttribute(ATT_AUTO_CONFIG));
- this.allowSessionCreation = allowSessionCreation;
- try {
- random = SecureRandom.getInstance("SHA1PRNG");
- } catch (NoSuchAlgorithmException e) {
- // Shouldn't happen...
- throw new RuntimeException("Failed find SHA1PRNG algorithm!");
- }
+ this.allowSessionCreation = sessionPolicy != SessionCreationPolicy.never
+ && sessionPolicy != SessionCreationPolicy.stateless;
+
+ createAnonymousFilter();
+ createRememberMeFilter(authenticationManager);
+ createBasicFilter(authenticationManager);
+ createFormLoginFilter(sessionStrategy, authenticationManager);
+ createOpenIDLoginFilter(sessionStrategy, authenticationManager);
+ createX509Filter(authenticationManager);
+ createJeeFilter(authenticationManager);
+ createLogoutFilter();
+ createLoginPageFilterIfNeeded();
+ createUserDetailsServiceFactory();
+ createExceptionTranslationFilter();
+
}
void createRememberMeFilter(BeanReference authenticationManager) {
- final String ATT_KEY = "key";
- final String DEF_KEY = "SpringSecured";
// Parse remember me before logout as RememberMeServices is also a LogoutHandler implementation.
Element rememberMeElt = DomUtils.getChildElementByTagName(httpElt, Elements.REMEMBER_ME);
@@ -127,10 +135,10 @@ final class AuthenticationConfigBuilder {
String key = rememberMeElt.getAttribute(ATT_KEY);
if (!StringUtils.hasText(key)) {
- key = DEF_KEY;
+ key = createKey();
}
- rememberMeFilter = (RootBeanDefinition) new RememberMeBeanDefinitionParser(key).parse(rememberMeElt, pc);
+ rememberMeFilter = new RememberMeBeanDefinitionParser(key).parse(rememberMeElt, pc);
rememberMeFilter.getPropertyValues().addPropertyValue("authenticationManager", authenticationManager);
rememberMeServicesId = ((RuntimeBeanReference) rememberMeFilter.getPropertyValues().getPropertyValue("rememberMeServices").getValue()).getBeanName();
createRememberMeProvider(key);
@@ -152,6 +160,7 @@ final class AuthenticationConfigBuilder {
void createFormLoginFilter(BeanReference sessionStrategy, BeanReference authManager) {
Element formLoginElt = DomUtils.getChildElementByTagName(httpElt, Elements.FORM_LOGIN);
+ RootBeanDefinition formFilter = null;
if (formLoginElt != null || autoConfig) {
FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_security_check",
@@ -166,7 +175,6 @@ final class AuthenticationConfigBuilder {
formFilter.getPropertyValues().addPropertyValue("allowSessionCreation", allowSessionCreation);
formFilter.getPropertyValues().addPropertyValue("authenticationManager", authManager);
-
// Id is required by login page filter
formFilterId = pc.getReaderContext().generateBeanName(formFilter);
pc.registerBeanComponent(new BeanComponentDefinition(formFilter, formFilterId));
@@ -176,6 +184,7 @@ final class AuthenticationConfigBuilder {
void createOpenIDLoginFilter(BeanReference sessionStrategy, BeanReference authManager) {
Element openIDLoginElt = DomUtils.getChildElementByTagName(httpElt, Elements.OPENID_LOGIN);
+ RootBeanDefinition openIDFilter = null;
if (openIDLoginElt != null) {
FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_openid_security_check",
@@ -185,30 +194,31 @@ final class AuthenticationConfigBuilder {
openIDFilter = parser.getFilterBean();
openIDEntryPoint = parser.getEntryPointBean();
- Element attrExElt = DomUtils.getChildElementByTagName(openIDLoginElt, Elements.OPENID_ATTRIBUTE_EXCHANGE);
+ List<Element> attrExElts = DomUtils.getChildElementsByTagName(openIDLoginElt, Elements.OPENID_ATTRIBUTE_EXCHANGE);
- if (attrExElt != null) {
+ if (!attrExElts.isEmpty()) {
// Set up the consumer with the required attribute list
BeanDefinitionBuilder consumerBldr = BeanDefinitionBuilder.rootBeanDefinition(OPEN_ID_CONSUMER_CLASS);
- ManagedList<BeanDefinition> attributes = new ManagedList<BeanDefinition> ();
- for (Element attElt : DomUtils.getChildElementsByTagName(attrExElt, Elements.OPENID_ATTRIBUTE)) {
- String name = attElt.getAttribute("name");
- String type = attElt.getAttribute("type");
- String required = attElt.getAttribute("required");
- String count = attElt.getAttribute("count");
- BeanDefinitionBuilder attrBldr = BeanDefinitionBuilder.rootBeanDefinition(OPEN_ID_ATTRIBUTE_CLASS);
- attrBldr.addConstructorArgValue(name);
- attrBldr.addConstructorArgValue(type);
- if (StringUtils.hasLength(required)) {
- attrBldr.addPropertyValue("required", Boolean.valueOf(required));
+ BeanDefinitionBuilder axFactory = BeanDefinitionBuilder.rootBeanDefinition(OPEN_ID_ATTRIBUTE_FACTORY_CLASS);
+ ManagedMap<String, ManagedList<BeanDefinition>> axMap = new ManagedMap<String, ManagedList<BeanDefinition>>();
+
+ for (Element attrExElt : attrExElts) {
+ String identifierMatch = attrExElt.getAttribute("identifier-match");
+
+ if (!StringUtils.hasText(identifierMatch)) {
+ if (attrExElts.size() > 1) {
+ pc.getReaderContext().error("You must supply an identifier-match attribute if using more" +
+ " than one " + Elements.OPENID_ATTRIBUTE_EXCHANGE + " element", attrExElt);
+ }
+ // Match anything
+ identifierMatch = ".*";
}
- if (StringUtils.hasLength(count)) {
- attrBldr.addPropertyValue("count", Integer.parseInt(count));
- }
- attributes.add(attrBldr.getBeanDefinition());
+ axMap.put(identifierMatch, parseOpenIDAttributes(attrExElt));
}
- consumerBldr.addConstructorArgValue(attributes);
+ axFactory.addConstructorArgValue(axMap);
+
+ consumerBldr.addConstructorArgValue(axFactory.getBeanDefinition());
openIDFilter.getPropertyValues().addPropertyValue("consumer", consumerBldr.getBeanDefinition());
}
}
@@ -225,20 +235,43 @@ final class AuthenticationConfigBuilder {
}
}
+ private ManagedList<BeanDefinition> parseOpenIDAttributes(Element attrExElt) {
+ ManagedList<BeanDefinition> attributes = new ManagedList<BeanDefinition> ();
+ for (Element attElt : DomUtils.getChildElementsByTagName(attrExElt, Elements.OPENID_ATTRIBUTE)) {
+ String name = attElt.getAttribute("name");
+ String type = attElt.getAttribute("type");
+ String required = attElt.getAttribute("required");
+ String count = attElt.getAttribute("count");
+ BeanDefinitionBuilder attrBldr = BeanDefinitionBuilder.rootBeanDefinition(OPEN_ID_ATTRIBUTE_CLASS);
+ attrBldr.addConstructorArgValue(name);
+ attrBldr.addConstructorArgValue(type);
+ if (StringUtils.hasLength(required)) {
+ attrBldr.addPropertyValue("required", Boolean.valueOf(required));
+ }
+
+ if (StringUtils.hasLength(count)) {
+ attrBldr.addPropertyValue("count", Integer.parseInt(count));
+ }
+ attributes.add(attrBldr.getBeanDefinition());
+ }
+
+ return attributes;
+ }
+
private void createOpenIDProvider() {
Element openIDLoginElt = DomUtils.getChildElementByTagName(httpElt, Elements.OPENID_LOGIN);
BeanDefinitionBuilder openIDProviderBuilder =
BeanDefinitionBuilder.rootBeanDefinition(OPEN_ID_AUTHENTICATION_PROVIDER_CLASS);
- String userService = openIDLoginElt.getAttribute(ATT_USER_SERVICE_REF);
+ RootBeanDefinition uds = new RootBeanDefinition();
+ uds.setFactoryBeanName(BeanIds.USER_DETAILS_SERVICE_FACTORY);
+ uds.setFactoryMethodName("authenticationUserDetailsService");
+ uds.getConstructorArgumentValues().addGenericArgumentValue(openIDLoginElt.getAttribute(ATT_USER_SERVICE_REF));
- if (StringUtils.hasText(userService)) {
- openIDProviderBuilder.addPropertyReference("userDetailsService", userService);
- }
+ openIDProviderBuilder.addPropertyValue("authenticationUserDetailsService", uds);
BeanDefinition openIDProvider = openIDProviderBuilder.getBeanDefinition();
- openIDProviderId = pc.getReaderContext().registerWithGeneratedName(openIDProvider);
- openIDProviderRef = new RuntimeBeanReference(openIDProviderId);
+ openIDProviderRef = new RuntimeBeanReference(pc.getReaderContext().registerWithGeneratedName(openIDProvider));
}
private void injectRememberMeServicesRef(RootBeanDefinition bean, String rememberMeServicesId) {
@@ -250,41 +283,46 @@ final class AuthenticationConfigBuilder {
void createBasicFilter(BeanReference authManager) {
Element basicAuthElt = DomUtils.getChildElementByTagName(httpElt, Elements.BASIC_AUTH);
+ if (basicAuthElt == null && !autoConfig) {
+ // No basic auth, do nothing
+ return;
+ }
+
String realm = httpElt.getAttribute(ATT_REALM);
if (!StringUtils.hasText(realm)) {
realm = DEF_REALM;
}
- RootBeanDefinition filter = null;
-
- if (basicAuthElt != null || autoConfig) {
- BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(BasicAuthenticationFilter.class);
+ BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(BasicAuthenticationFilter.class);
- String entryPointId;
+ String entryPointId;
- if (basicAuthElt != null && StringUtils.hasText(basicAuthElt.getAttribute(ATT_ENTRY_POINT_REF))) {
+ if (basicAuthElt != null) {
+ if (StringUtils.hasText(basicAuthElt.getAttribute(ATT_ENTRY_POINT_REF))) {
basicEntryPoint = new RuntimeBeanReference(basicAuthElt.getAttribute(ATT_ENTRY_POINT_REF));
- } else {
- RootBeanDefinition entryPoint = new RootBeanDefinition(BasicAuthenticationEntryPoint.class);
- entryPoint.setSource(pc.extractSource(httpElt));
- entryPoint.getPropertyValues().addPropertyValue("realmName", realm);
- entryPointId = pc.getReaderContext().generateBeanName(entryPoint);
- pc.registerBeanComponent(new BeanComponentDefinition(entryPoint, entryPointId));
- basicEntryPoint = new RuntimeBeanReference(entryPointId);
}
- filterBuilder.addPropertyValue("authenticationManager", authManager);
- filterBuilder.addPropertyValue("authenticationEntryPoint", basicEntryPoint);
- filter = (RootBeanDefinition) filterBuilder.getBeanDefinition();
+ injectAuthenticationDetailsSource(basicAuthElt, filterBuilder);
+
+ }
+
+ if (basicEntryPoint == null) {
+ RootBeanDefinition entryPoint = new RootBeanDefinition(BasicAuthenticationEntryPoint.class);
+ entryPoint.setSource(pc.extractSource(httpElt));
+ entryPoint.getPropertyValues().addPropertyValue("realmName", realm);
+ entryPointId = pc.getReaderContext().generateBeanName(entryPoint);
+ pc.registerBeanComponent(new BeanComponentDefinition(entryPoint, entryPointId));
+ basicEntryPoint = new RuntimeBeanReference(entryPointId);
}
- basicFilter = filter;
+ filterBuilder.addPropertyValue("authenticationManager", authManager);
+ filterBuilder.addPropertyValue("authenticationEntryPoint", basicEntryPoint);
+ basicFilter = filterBuilder.getBeanDefinition();
}
void createX509Filter(BeanReference authManager) {
Element x509Elt = DomUtils.getChildElementByTagName(httpElt, Elements.X509);
RootBeanDefinition filter = null;
- RootBeanDefinition entryPoint = null;
if (x509Elt != null) {
BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(X509AuthenticationFilter.class);
@@ -299,37 +337,102 @@ final class AuthenticationConfigBuilder {
filterBuilder.addPropertyValue("principalExtractor", extractor.getBeanDefinition());
}
+
+ injectAuthenticationDetailsSource(x509Elt, filterBuilder);
+
filter = (RootBeanDefinition) filterBuilder.getBeanDefinition();
- entryPoint = new RootBeanDefinition(Http403ForbiddenEntryPoint.class);
- entryPoint.setSource(pc.extractSource(x509Elt));
+ createPrauthEntryPoint(x509Elt);
createX509Provider();
}
x509Filter = filter;
- x509EntryPoint = entryPoint;
+ }
+
+ private void injectAuthenticationDetailsSource(Element elt, BeanDefinitionBuilder filterBuilder) {
+ String authDetailsSourceRef = elt.getAttribute(AuthenticationConfigBuilder.ATT_AUTH_DETAILS_SOURCE_REF);
+
+ if (StringUtils.hasText(authDetailsSourceRef)) {
+ filterBuilder.addPropertyReference("authenticationDetailsSource", authDetailsSourceRef);
+ }
}
private void createX509Provider() {
Element x509Elt = DomUtils.getChildElementByTagName(httpElt, Elements.X509);
BeanDefinition provider = new RootBeanDefinition(PreAuthenticatedAuthenticationProvider.class);
- String userServiceRef = x509Elt.getAttribute(ATT_USER_SERVICE_REF);
+ RootBeanDefinition uds = new RootBeanDefinition();
+ uds.setFactoryBeanName(BeanIds.USER_DETAILS_SERVICE_FACTORY);
+ uds.setFactoryMethodName("authenticationUserDetailsService");
+ uds.getConstructorArgumentValues().addGenericArgumentValue(x509Elt.getAttribute(ATT_USER_SERVICE_REF));
+
+ provider.getPropertyValues().addPropertyValue("preAuthenticatedUserDetailsService", uds);
+
+ x509ProviderRef = new RuntimeBeanReference(pc.getReaderContext().registerWithGeneratedName(provider));
+ }
+
+ private void createPrauthEntryPoint(Element source) {
+ if (preAuthEntryPoint == null) {
+ preAuthEntryPoint = new RootBeanDefinition(Http403ForbiddenEntryPoint.class);
+ preAuthEntryPoint.setSource(pc.extractSource(source));
+ }
+ }
+
+ void createJeeFilter(BeanReference authManager) {
+ final String ATT_MAPPABLE_ROLES = "mappable-roles";
+
+ Element jeeElt = DomUtils.getChildElementByTagName(httpElt, Elements.JEE);
+ RootBeanDefinition filter = null;
+
+ if (jeeElt != null) {
+ BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(J2eePreAuthenticatedProcessingFilter.class);
+ filterBuilder.getRawBeanDefinition().setSource(pc.extractSource(jeeElt));
+ filterBuilder.addPropertyValue("authenticationManager", authManager);
+
+ BeanDefinitionBuilder adsBldr = BeanDefinitionBuilder.rootBeanDefinition(J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource.class);
+ adsBldr.addPropertyValue("userRoles2GrantedAuthoritiesMapper", new RootBeanDefinition(SimpleAttributes2GrantedAuthoritiesMapper.class));
+
+ String roles = jeeElt.getAttribute(ATT_MAPPABLE_ROLES);
+ Assert.state(StringUtils.hasText(roles));
+ BeanDefinitionBuilder rolesBuilder = BeanDefinitionBuilder.rootBeanDefinition(StringUtils.class);
+ rolesBuilder.addConstructorArgValue(roles);
+ rolesBuilder.setFactoryMethod("commaDelimitedListToSet");
+
+ RootBeanDefinition mappableRolesRetriever = new RootBeanDefinition(SimpleMappableAttributesRetriever.class);
+ mappableRolesRetriever.getPropertyValues().addPropertyValue("mappableAttributes", rolesBuilder.getBeanDefinition());
+ adsBldr.addPropertyValue("mappableRolesRetriever", mappableRolesRetriever);
+ filterBuilder.addPropertyValue("authenticationDetailsSource", adsBldr.getBeanDefinition());
- if (StringUtils.hasText(userServiceRef)) {
- RootBeanDefinition preAuthUserService = new RootBeanDefinition(UserDetailsByNameServiceWrapper.class);
- preAuthUserService.setSource(pc.extractSource(x509Elt));
- preAuthUserService.getPropertyValues().addPropertyValue("userDetailsService", new RuntimeBeanReference(userServiceRef));
- provider.getPropertyValues().addPropertyValue("preAuthenticatedUserDetailsService", preAuthUserService);
+ filter = (RootBeanDefinition) filterBuilder.getBeanDefinition();
+
+ createPrauthEntryPoint(jeeElt);
+ createJeeProvider();
}
- x509ProviderId = pc.getReaderContext().registerWithGeneratedName(provider);
- x509ProviderRef = new RuntimeBeanReference(x509ProviderId);
+ jeeFilter = filter;
}
+ private void createJeeProvider() {
+ Element jeeElt = DomUtils.getChildElementByTagName(httpElt, Elements.JEE);
+ BeanDefinition provider = new RootBeanDefinition(PreAuthenticatedAuthenticationProvider.class);
+
+ RootBeanDefinition uds;
+ if (StringUtils.hasText(jeeElt.getAttribute(ATT_USER_SERVICE_REF))) {
+ uds = new RootBeanDefinition();
+ uds.setFactoryBeanName(BeanIds.USER_DETAILS_SERVICE_FACTORY);
+ uds.setFactoryMethodName("authenticationUserDetailsService");
+ uds.getConstructorArgumentValues().addGenericArgumentValue(jeeElt.getAttribute(ATT_USER_SERVICE_REF));
+ } else {
+ uds = new RootBeanDefinition(PreAuthenticatedGrantedAuthoritiesUserDetailsService.class);
+ }
+
+ provider.getPropertyValues().addPropertyValue("preAuthenticatedUserDetailsService", uds);
+
+ jeeProviderRef = new RuntimeBeanReference(pc.getReaderContext().registerWithGeneratedName(provider));
+ }
void createLoginPageFilterIfNeeded() {
- boolean needLoginPage = formFilter != null || openIDFilter != null;
+ boolean needLoginPage = formFilterId != null || openIDFilterId != null;
String formLoginPage = getLoginFormUrl(formEntryPoint);
String openIDLoginPage = getLoginFormUrl(openIDEntryPoint);
@@ -340,11 +443,11 @@ final class AuthenticationConfigBuilder {
BeanDefinitionBuilder loginPageFilter =
BeanDefinitionBuilder.rootBeanDefinition(DefaultLoginPageGeneratingFilter.class);
- if (formFilter != null) {
+ if (formFilterId != null) {
loginPageFilter.addConstructorArgReference(formFilterId);
}
- if (openIDFilter != null) {
+ if (openIDFilterId != null) {
loginPageFilter.addConstructorArgReference(openIDFilterId);
}
@@ -374,7 +477,7 @@ final class AuthenticationConfigBuilder {
if (anonymousElt != null) {
grantedAuthority = anonymousElt.getAttribute("granted-authority");
username = anonymousElt.getAttribute("username");
- key = anonymousElt.getAttribute("key");
+ key = anonymousElt.getAttribute(ATT_KEY);
source = pc.extractSource(anonymousElt);
}
@@ -388,7 +491,7 @@ final class AuthenticationConfigBuilder {
if (!StringUtils.hasText(key)) {
// Generate a random key for the Anonymous provider
- key = Long.toString(random.nextLong());
+ key = createKey();
}
anonymousFilter = new RootBeanDefinition(AnonymousAuthenticationFilter.class);
@@ -408,6 +511,11 @@ final class AuthenticationConfigBuilder {
}
+ private String createKey() {
+ SecureRandom random = new SecureRandom();
+ return Long.toString(random.nextLong());
+ }
+
void createExceptionTranslationFilter() {
BeanDefinitionBuilder etfBuilder = BeanDefinitionBuilder.rootBeanDefinition(ExceptionTranslationFilter.class);
etfBuilder.addPropertyValue("accessDeniedHandler", createAccessDeniedHandler(httpElt, pc));
@@ -418,28 +526,6 @@ final class AuthenticationConfigBuilder {
etf = etfBuilder.getBeanDefinition();
}
- void createRequestCache() {
- Element requestCacheElt = DomUtils.getChildElementByTagName(httpElt, Elements.REQUEST_CACHE);
-
- if (requestCacheElt != null) {
- requestCache = new RuntimeBeanReference(requestCacheElt.getAttribute(ATT_REF));
- return;
- }
-
- BeanDefinitionBuilder requestCacheBldr = BeanDefinitionBuilder.rootBeanDefinition(HttpSessionRequestCache.class);
- BeanDefinitionBuilder portResolver = BeanDefinitionBuilder.rootBeanDefinition(PortResolverImpl.class);
- portResolver.addPropertyReference("portMapper", portMapperName);
- requestCacheBldr.addPropertyValue("createSessionAllowed", allowSessionCreation);
- requestCacheBldr.addPropertyValue("portResolver", portResolver.getBeanDefinition());
-
- BeanDefinition bean = requestCacheBldr.getBeanDefinition();
- String id = pc.getReaderContext().generateBeanName(bean);
- pc.registerBeanComponent(new BeanComponentDefinition(bean, id));
-
- this.requestCache = new RuntimeBeanReference(id);
- }
-
-
private BeanMetadataElement createAccessDeniedHandler(Element element, ParserContext pc) {
String accessDeniedPage = element.getAttribute(ATT_ACCESS_DENIED_PAGE);
WebConfigUtils.validateHttpRedirect(accessDeniedPage, pc, pc.extractSource(element));
@@ -503,18 +589,18 @@ final class AuthenticationConfigBuilder {
"but not both.", pc.extractSource(openIDLoginElt));
}
- if (formFilter != null && openIDLoginPage == null) {
+ if (formFilterId != null && openIDLoginPage == null) {
return formEntryPoint;
}
// Otherwise use OpenID if enabled
- if (openIDFilter != null) {
+ if (openIDFilterId != null) {
return openIDEntryPoint;
}
- // If X.509 has been enabled, use the preauth entry point.
- if (DomUtils.getChildElementByTagName(httpElt, Elements.X509) != null) {
- return x509EntryPoint;
+ // If X.509 or JEE have been enabled, use the preauth entry point.
+ if (preAuthEntryPoint != null) {
+ return preAuthEntryPoint;
}
pc.getReaderContext().error("No AuthenticationEntryPoint could be established. Please " +
@@ -543,14 +629,14 @@ final class AuthenticationConfigBuilder {
return (String) pv.getValue();
}
- void createUserServiceInjector() {
- BeanDefinitionBuilder userServiceInjector =
- BeanDefinitionBuilder.rootBeanDefinition(UserDetailsServiceInjectionBeanPostProcessor.class);
- userServiceInjector.addConstructorArgValue(x509ProviderId);
- userServiceInjector.addConstructorArgValue(rememberMeServicesId);
- userServiceInjector.addConstructorArgValue(openIDProviderId);
- userServiceInjector.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
- pc.getReaderContext().registerWithGeneratedName(userServiceInjector.getBeanDefinition());
+ private void createUserDetailsServiceFactory() {
+ if (pc.getRegistry().containsBeanDefinition(BeanIds.USER_DETAILS_SERVICE_FACTORY)) {
+ // Multiple <http> case
+ return;
+ }
+ RootBeanDefinition bean = new RootBeanDefinition(UserDetailsServiceFactoryBean.class);
+ bean.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
+ pc.registerBeanComponent(new BeanComponentDefinition(bean, BeanIds.USER_DETAILS_SERVICE_FACTORY));
}
List<OrderDecorator> getFilters() {
@@ -572,12 +658,16 @@ final class AuthenticationConfigBuilder {
filters.add(new OrderDecorator(x509Filter, X509_FILTER));
}
- if (formFilter != null) {
- filters.add(new OrderDecorator(formFilter, FORM_LOGIN_FILTER));
+ if (jeeFilter != null) {
+ filters.add(new OrderDecorator(jeeFilter, PRE_AUTH_FILTER));
}
- if (openIDFilter != null) {
- filters.add(new OrderDecorator(openIDFilter, OPENID_FILTER));
+ if (formFilterId != null) {
+ filters.add(new OrderDecorator(new RuntimeBeanReference(formFilterId), FORM_LOGIN_FILTER));
+ }
+
+ if (openIDFilterId != null) {
+ filters.add(new OrderDecorator(new RuntimeBeanReference(openIDFilterId), OPENID_FILTER));
}
if (loginPageGenerationFilter != null) {
@@ -612,11 +702,11 @@ final class AuthenticationConfigBuilder {
providers.add(x509ProviderRef);
}
- return providers;
- }
+ if (jeeProviderRef != null) {
+ providers.add(jeeProviderRef);
+ }
- public BeanReference getRequestCache() {
- return requestCache;
+ return providers;
}
}
diff --git a/dist/spring-security-config/org/springframework/security/config/http/ChannelAttributeFactory.java b/dist/spring-security-config/org/springframework/security/config/http/ChannelAttributeFactory.java
index 41af43a..66e811f 100644
--- a/dist/spring-security-config/org/springframework/security/config/http/ChannelAttributeFactory.java
+++ b/dist/spring-security-config/org/springframework/security/config/http/ChannelAttributeFactory.java
@@ -18,8 +18,8 @@ public class ChannelAttributeFactory {
private static final String OPT_REQUIRES_HTTPS = "https";
private static final String OPT_ANY_CHANNEL = "any";
- public static final List<ConfigAttribute> createChannelAttributes(String requiredChannel) {
- String channelConfigAttribute = null;
+ public static List<ConfigAttribute> createChannelAttributes(String requiredChannel) {
+ String channelConfigAttribute;
if (requiredChannel.equals(OPT_REQUIRES_HTTPS)) {
channelConfigAttribute = "REQUIRES_SECURE_CHANNEL";
diff --git a/dist/spring-security-config/org/springframework/security/config/http/DefaultFilterChainValidator.java b/dist/spring-security-config/org/springframework/security/config/http/DefaultFilterChainValidator.java
index b92f704..8dbe102 100644
--- a/dist/spring-security-config/org/springframework/security/config/http/DefaultFilterChainValidator.java
+++ b/dist/spring-security-config/org/springframework/security/config/http/DefaultFilterChainValidator.java
@@ -1,16 +1,18 @@
package org.springframework.security.config.http;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
import javax.servlet.Filter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
+import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.FilterChainProxy;
+import org.springframework.security.web.FilterInvocation;
+import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.ExceptionTranslationFilter;
import org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
@@ -20,27 +22,57 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.security.web.context.SecurityContextPersistenceFilter;
+import org.springframework.security.web.jaasapi.JaasApiIntegrationFilter;
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
import org.springframework.security.web.session.SessionManagementFilter;
+import org.springframework.security.web.util.AnyRequestMatcher;
public class DefaultFilterChainValidator implements FilterChainProxy.FilterChainValidator {
- private Log logger = LogFactory.getLog(getClass());
+ private final Log logger = LogFactory.getLog(getClass());
public void validate(FilterChainProxy fcp) {
- Map<String, List<Filter>> filterChainMap = fcp.getFilterChainMap();
- for(String pattern : fcp.getFilterChainMap().keySet()) {
- List<Filter> filters = filterChainMap.get(pattern);
- checkFilterStack(filters);
+ for(SecurityFilterChain filterChain : fcp.getFilterChains()) {
+ checkLoginPageIsntProtected(fcp, filterChain.getFilters());
+ checkFilterStack(filterChain.getFilters());
}
- checkLoginPageIsntProtected(fcp, filterChainMap.get(fcp.getMatcher().getUniversalMatchPattern()));
+ checkPathOrder(new ArrayList<SecurityFilterChain>(fcp.getFilterChains()));
+ checkForDuplicateMatchers(new ArrayList<SecurityFilterChain>(fcp.getFilterChains()));
}
- private Object getFilter(Class<?> type, List<Filter> filters) {
+ private void checkPathOrder(List<SecurityFilterChain> filterChains) {
+ // Check that the universal pattern is listed at the end, if at all
+ Iterator<SecurityFilterChain> chains = filterChains.iterator();
+ while (chains.hasNext()) {
+ if (((DefaultSecurityFilterChain)chains.next()).getRequestMatcher() instanceof AnyRequestMatcher && chains.hasNext()) {
+ throw new IllegalArgumentException("A universal match pattern ('/**') is defined " +
+ " before other patterns in the filter chain, causing them to be ignored. Please check the " +
+ "ordering in your <security:http> namespace or FilterChainProxy bean configuration");
+ }
+ }
+ }
+
+ private void checkForDuplicateMatchers(List<SecurityFilterChain> chains) {
+
+ while (chains.size() > 1) {
+ DefaultSecurityFilterChain chain = (DefaultSecurityFilterChain)chains.remove(0);
+
+ for (SecurityFilterChain test : chains) {
+ if (chain.getRequestMatcher().equals(((DefaultSecurityFilterChain)test).getRequestMatcher())) {
+ throw new IllegalArgumentException("The FilterChainProxy contains two filter chains using the" +
+ " matcher " + chain.getRequestMatcher() + ". If you are using multiple <http> namespace " +
+ "elements, you must use a 'pattern' attribute to define the request patterns to which they apply.");
+ }
+ }
+ }
+ }
+
+ @SuppressWarnings({"unchecked"})
+ private <F extends Filter> F getFilter(Class<F> type, List<Filter> filters) {
for (Filter f : filters) {
if (type.isAssignableFrom(f.getClass())) {
- return f;
+ return (F) f;
}
}
@@ -56,6 +88,7 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain
checkForDuplicates(SessionManagementFilter.class, filters);
checkForDuplicates(BasicAuthenticationFilter.class, filters);
checkForDuplicates(SecurityContextHolderAwareRequestFilter.class, filters);
+ checkForDuplicates(JaasApiIntegrationFilter.class, filters);
checkForDuplicates(ExceptionTranslationFilter.class, filters);
checkForDuplicates(FilterSecurityInterceptor.class, filters);
}
@@ -78,56 +111,68 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain
}
/* Checks for the common error of having a login page URL protected by the security interceptor */
- private void checkLoginPageIsntProtected(FilterChainProxy fcp, List<Filter> defaultFilters) {
- ExceptionTranslationFilter etf = (ExceptionTranslationFilter)getFilter(ExceptionTranslationFilter.class, defaultFilters);
-
- if (etf.getAuthenticationEntryPoint() instanceof LoginUrlAuthenticationEntryPoint) {
- String loginPage =
- ((LoginUrlAuthenticationEntryPoint)etf.getAuthenticationEntryPoint()).getLoginFormUrl();
- List<Filter> filters = fcp.getFilters(loginPage);
- logger.info("Checking whether login URL '" + loginPage + "' is accessible with your configuration");
-
- if (filters == null || filters.isEmpty()) {
- logger.debug("Filter chain is empty for the login page");
- return;
- }
+ private void checkLoginPageIsntProtected(FilterChainProxy fcp, List<Filter> filterStack) {
+ ExceptionTranslationFilter etf = getFilter(ExceptionTranslationFilter.class, filterStack);
- if (getFilter(DefaultLoginPageGeneratingFilter.class, filters) != null) {
- logger.debug("Default generated login page is in use");
- return;
- }
+ if(etf == null || !(etf.getAuthenticationEntryPoint() instanceof LoginUrlAuthenticationEntryPoint)) {
+ return;
+ }
- FilterSecurityInterceptor fsi = (FilterSecurityInterceptor) getFilter(FilterSecurityInterceptor.class, filters);
- DefaultFilterInvocationSecurityMetadataSource fids =
- (DefaultFilterInvocationSecurityMetadataSource) fsi.getSecurityMetadataSource();
- Collection<ConfigAttribute> attributes = fids.lookupAttributes(loginPage, "POST");
+ String loginPage = ((LoginUrlAuthenticationEntryPoint)etf.getAuthenticationEntryPoint()).getLoginFormUrl();
+ logger.info("Checking whether login URL '" + loginPage + "' is accessible with your configuration");
+ FilterInvocation loginRequest = new FilterInvocation(loginPage, "POST");
+ List<Filter> filters = null;
+
+ try {
+ filters = fcp.getFilters(loginPage);
+ } catch (Exception e) {
+ // May happen legitimately if a filter-chain request matcher requires more request data than that provided
+ // by the dummy request used when creating the filter invocation.
+ logger.info("Failed to obtain filter chain information for the login page. Unable to complete check.");
+ }
- if (attributes == null) {
- logger.debug("No access attributes defined for login page URL");
- if (fsi.isRejectPublicInvocations()) {
- logger.warn("FilterSecurityInterceptor is configured to reject public invocations." +
- " Your login page may not be accessible.");
- }
- return;
- }
+ if (filters == null || filters.isEmpty()) {
+ logger.debug("Filter chain is empty for the login page");
+ return;
+ }
- AnonymousAuthenticationFilter anonPF = (AnonymousAuthenticationFilter) getFilter(AnonymousAuthenticationFilter.class, filters);
- if (anonPF == null) {
- logger.warn("The login page is being protected by the filter chain, but you don't appear to have" +
- " anonymous authentication enabled. This is almost certainly an error.");
- return;
- }
+ if (getFilter(DefaultLoginPageGeneratingFilter.class, filters) != null) {
+ logger.debug("Default generated login page is in use");
+ return;
+ }
+
+ FilterSecurityInterceptor fsi = getFilter(FilterSecurityInterceptor.class, filters);
+ DefaultFilterInvocationSecurityMetadataSource fids =
+ (DefaultFilterInvocationSecurityMetadataSource) fsi.getSecurityMetadataSource();
- // Simulate an anonymous access with the supplied attributes.
- AnonymousAuthenticationToken token = new AnonymousAuthenticationToken("key", anonPF.getUserAttribute().getPassword(),
- anonPF.getUserAttribute().getAuthorities());
- try {
- fsi.getAccessDecisionManager().decide(token, new Object(), fids.lookupAttributes(loginPage, "POST"));
- } catch (Exception e) {
- logger.warn("Anonymous access to the login page doesn't appear to be enabled. This is almost certainly " +
- "an error. Please check your configuration allows unauthenticated access to the configured " +
- "login page. (Simulated access was rejected: " + e + ")");
+ Collection<ConfigAttribute> attributes = fids.getAttributes(loginRequest);
+
+ if (attributes == null) {
+ logger.debug("No access attributes defined for login page URL");
+ if (fsi.isRejectPublicInvocations()) {
+ logger.warn("FilterSecurityInterceptor is configured to reject public invocations." +
+ " Your login page may not be accessible.");
}
+ return;
+ }
+
+ AnonymousAuthenticationFilter anonPF = getFilter(AnonymousAuthenticationFilter.class, filters);
+ if (anonPF == null) {
+ logger.warn("The login page is being protected by the filter chain, but you don't appear to have" +
+ " anonymous authentication enabled. This is almost certainly an error.");
+ return;
+ }
+
+ // Simulate an anonymous access with the supplied attributes.
+ AnonymousAuthenticationToken token = new AnonymousAuthenticationToken("key", anonPF.getPrincipal(),
+ anonPF.getAuthorities());
+ try {
+ fsi.getAccessDecisionManager().decide(token, loginRequest, attributes);
+ } catch (AccessDeniedException e) {
+ logger.warn("Anonymous access to the login page doesn't appear to be enabled. This is almost certainly " +
+ "an error. Please check your configuration allows unauthenticated access to the configured " +
+ "login page. (Simulated access was rejected: " + e + ")");
}
}
+
}
diff --git a/dist/spring-security-config/org/springframework/security/config/http/FilterChainMapBeanDefinitionDecorator.java b/dist/spring-security-config/org/springframework/security/config/http/FilterChainMapBeanDefinitionDecorator.java
index 2490ea5..7d86965 100644
--- a/dist/spring-security-config/org/springframework/security/config/http/FilterChainMapBeanDefinitionDecorator.java
+++ b/dist/spring-security-config/org/springframework/security/config/http/FilterChainMapBeanDefinitionDecorator.java
@@ -1,5 +1,10 @@
package org.springframework.security.config.http;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.RuntimeBeanReference;
@@ -8,14 +13,11 @@ import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.xml.BeanDefinitionDecorator;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.security.config.Elements;
-import org.springframework.security.web.util.RegexUrlPathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
-import java.util.*;
-
/**
* Sets the filter chain Map for a FilterChainProxy bean declaration.
*
@@ -30,11 +32,7 @@ public class FilterChainMapBeanDefinitionDecorator implements BeanDefinitionDeco
Map filterChainMap = new LinkedHashMap();
Element elt = (Element)node;
- String pathType = elt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_PATH_TYPE);
-
- if (HttpSecurityBeanDefinitionParser.OPT_PATH_TYPE_REGEX.equals(pathType)) {
- filterChainProxy.getPropertyValues().addPropertyValue("matcher", new RegexUrlPathMatcher());
- }
+ MatcherType matcherType = MatcherType.fromElement(elt);
List<Element> filterChainElts = DomUtils.getChildElementsByTagName(elt, Elements.FILTER_CHAIN);
@@ -52,17 +50,19 @@ public class FilterChainMapBeanDefinitionDecorator implements BeanDefinitionDeco
"'must not be empty", elt);
}
+ BeanDefinition matcher = matcherType.createMatcher(path, null);
+
if (filters.equals(HttpSecurityBeanDefinitionParser.OPT_FILTERS_NONE)) {
- filterChainMap.put(path, Collections.EMPTY_LIST);
+ filterChainMap.put(matcher, Collections.EMPTY_LIST);
} else {
String[] filterBeanNames = StringUtils.tokenizeToStringArray(filters, ",");
ManagedList filterChain = new ManagedList(filterBeanNames.length);
- for (int i=0; i < filterBeanNames.length; i++) {
- filterChain.add(new RuntimeBeanReference(filterBeanNames[i]));
+ for (String name : filterBeanNames) {
+ filterChain.add(new RuntimeBeanReference(name));
}
- filterChainMap.put(path, filterChain);
+ filterChainMap.put(matcher, filterChain);
}
}
diff --git a/dist/spring-security-config/org/springframework/security/config/http/FilterInvocationSecurityMetadataSourceParser.java b/dist/spring-security-config/org/springframework/security/config/http/FilterInvocationSecurityMetadataSourceParser.java
index 6505a77..3dc5c27 100644
--- a/dist/spring-security-config/org/springframework/security/config/http/FilterInvocationSecurityMetadataSourceParser.java
+++ b/dist/spring-security-config/org/springframework/security/config/http/FilterInvocationSecurityMetadataSourceParser.java
@@ -8,6 +8,7 @@ import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedMap;
+import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
@@ -17,9 +18,6 @@ import org.springframework.security.web.access.expression.DefaultWebSecurityExpr
import org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource;
import org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
-import org.springframework.security.web.access.intercept.RequestKey;
-import org.springframework.security.web.util.AntUrlPathMatcher;
-import org.springframework.security.web.util.UrlMatcher;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
@@ -62,12 +60,12 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit
return mds;
}
- static BeanDefinition createSecurityMetadataSource(List<Element> interceptUrls, Element elt, ParserContext pc) {
- UrlMatcher matcher = HttpSecurityBeanDefinitionParser.createUrlMatcher(elt);
+ static RootBeanDefinition createSecurityMetadataSource(List<Element> interceptUrls, Element elt, ParserContext pc) {
+ MatcherType matcherType = MatcherType.fromElement(elt);
boolean useExpressions = isUseExpressions(elt);
ManagedMap<BeanDefinition, BeanDefinition> requestToAttributesMap = parseInterceptUrlsForFilterInvocationRequestMap(
- interceptUrls, useExpressions, pc);
+ matcherType, interceptUrls, useExpressions, pc);
BeanDefinitionBuilder fidsBuilder;
if (useExpressions) {
@@ -77,33 +75,37 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit
if (StringUtils.hasText(expressionHandlerRef)) {
logger.info("Using bean '" + expressionHandlerRef + "' as web SecurityExpressionHandler implementation");
} else {
- BeanDefinition expressionHandler = BeanDefinitionBuilder.rootBeanDefinition(DefaultWebSecurityExpressionHandler.class).getBeanDefinition();
- expressionHandlerRef = pc.getReaderContext().generateBeanName(expressionHandler);
- pc.registerBeanComponent(new BeanComponentDefinition(expressionHandler, expressionHandlerRef));
+ expressionHandlerRef = registerDefaultExpressionHandler(pc);
}
fidsBuilder = BeanDefinitionBuilder.rootBeanDefinition(ExpressionBasedFilterInvocationSecurityMetadataSource.class);
- fidsBuilder.addConstructorArgValue(matcher);
fidsBuilder.addConstructorArgValue(requestToAttributesMap);
fidsBuilder.addConstructorArgReference(expressionHandlerRef);
} else {
fidsBuilder = BeanDefinitionBuilder.rootBeanDefinition(DefaultFilterInvocationSecurityMetadataSource.class);
- fidsBuilder.addConstructorArgValue(matcher);
fidsBuilder.addConstructorArgValue(requestToAttributesMap);
}
- fidsBuilder.addPropertyValue("stripQueryStringFromUrls", matcher instanceof AntUrlPathMatcher);
fidsBuilder.getRawBeanDefinition().setSource(pc.extractSource(elt));
- return fidsBuilder.getBeanDefinition();
+ return (RootBeanDefinition) fidsBuilder.getBeanDefinition();
+ }
+
+ static String registerDefaultExpressionHandler(ParserContext pc) {
+ BeanDefinition expressionHandler = BeanDefinitionBuilder.rootBeanDefinition(DefaultWebSecurityExpressionHandler.class).getBeanDefinition();
+ String expressionHandlerRef = pc.getReaderContext().generateBeanName(expressionHandler);
+ pc.registerBeanComponent(new BeanComponentDefinition(expressionHandler, expressionHandlerRef));
+
+ return expressionHandlerRef;
}
static boolean isUseExpressions(Element elt) {
return "true".equals(elt.getAttribute(ATT_USE_EXPRESSIONS));
}
- private static ManagedMap<BeanDefinition, BeanDefinition> parseInterceptUrlsForFilterInvocationRequestMap(List<Element> urlElts,
- boolean useExpressions, ParserContext parserContext) {
+ private static ManagedMap<BeanDefinition, BeanDefinition>
+ parseInterceptUrlsForFilterInvocationRequestMap(MatcherType matcherType,
+ List<Element> urlElts, boolean useExpressions, ParserContext parserContext) {
ManagedMap<BeanDefinition, BeanDefinition> filterInvocationDefinitionMap = new ManagedMap<BeanDefinition, BeanDefinition>();
@@ -124,10 +126,7 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit
method = null;
}
- BeanDefinitionBuilder keyBldr = BeanDefinitionBuilder.rootBeanDefinition(RequestKey.class);
- keyBldr.addConstructorArgValue(path);
- keyBldr.addConstructorArgValue(method);
-
+ BeanDefinition matcher = matcherType.createMatcher(path, method);
BeanDefinitionBuilder attributeBuilder = BeanDefinitionBuilder.rootBeanDefinition(SecurityConfig.class);
attributeBuilder.addConstructorArgValue(access);
@@ -140,13 +139,11 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit
attributeBuilder.setFactoryMethod("createListFromCommaDelimitedString");
}
- BeanDefinition key = keyBldr.getBeanDefinition();
-
- if (filterInvocationDefinitionMap.containsKey(key)) {
+ if (filterInvocationDefinitionMap.containsKey(matcher)) {
logger.warn("Duplicate URL defined: " + path + ". The original attribute values will be overwritten");
}
- filterInvocationDefinitionMap.put(key, attributeBuilder.getBeanDefinition());
+ filterInvocationDefinitionMap.put(matcher, attributeBuilder.getBeanDefinition());
}
return filterInvocationDefinitionMap;
diff --git a/dist/spring-security-config/org/springframework/security/config/http/FormLoginBeanDefinitionParser.java b/dist/spring-security-config/org/springframework/security/config/http/FormLoginBeanDefinitionParser.java
index 380e5c7..ee95ef9 100644
--- a/dist/spring-security-config/org/springframework/security/config/http/FormLoginBeanDefinitionParser.java
+++ b/dist/spring-security-config/org/springframework/security/config/http/FormLoginBeanDefinitionParser.java
@@ -29,6 +29,8 @@ public class FormLoginBeanDefinitionParser {
private static final String ATT_FORM_LOGIN_TARGET_URL = "default-target-url";
private static final String ATT_ALWAYS_USE_DEFAULT_TARGET_URL = "always-use-default-target";
private static final String DEF_FORM_LOGIN_TARGET_URL = "/";
+ private static final String ATT_USERNAME_PARAMETER = "username-parameter";
+ private static final String ATT_PASSWORD_PARAMETER = "password-parameter";
private static final String ATT_FORM_LOGIN_AUTHENTICATION_FAILURE_URL = "authentication-failure-url";
private static final String DEF_FORM_LOGIN_AUTHENTICATION_FAILURE_URL =
@@ -63,6 +65,10 @@ public class FormLoginBeanDefinitionParser {
String alwaysUseDefault = null;
String successHandlerRef = null;
String failureHandlerRef = null;
+ // Only available with form-login
+ String usernameParameter = null;
+ String passwordParameter = null;
+ String authDetailsSourceRef = null;
Object source = null;
@@ -78,15 +84,27 @@ public class FormLoginBeanDefinitionParser {
loginPage = elt.getAttribute(ATT_LOGIN_PAGE);
successHandlerRef = elt.getAttribute(ATT_SUCCESS_HANDLER_REF);
failureHandlerRef = elt.getAttribute(ATT_FAILURE_HANDLER_REF);
+ authDetailsSourceRef = elt.getAttribute(AuthenticationConfigBuilder.ATT_AUTH_DETAILS_SOURCE_REF);
+
if (!StringUtils.hasText(loginPage)) {
loginPage = null;
}
WebConfigUtils.validateHttpRedirect(loginPage, pc, source);
+ usernameParameter = elt.getAttribute(ATT_USERNAME_PARAMETER);
+ passwordParameter = elt.getAttribute(ATT_PASSWORD_PARAMETER);
}
filterBean = createFilterBean(loginUrl, defaultTargetUrl, alwaysUseDefault, loginPage, authenticationFailureUrl,
- successHandlerRef, failureHandlerRef);
+ successHandlerRef, failureHandlerRef, authDetailsSourceRef);
+
+ if (StringUtils.hasText(usernameParameter)) {
+ filterBean.getPropertyValues().addPropertyValue("usernameParameter", usernameParameter);
+ }
+ if (StringUtils.hasText(passwordParameter)) {
+ filterBean.getPropertyValues().addPropertyValue("passwordParameter", passwordParameter);
+ }
+
filterBean.setSource(source);
BeanDefinitionBuilder entryPointBuilder =
@@ -99,7 +117,8 @@ public class FormLoginBeanDefinitionParser {
}
private RootBeanDefinition createFilterBean(String loginUrl, String defaultTargetUrl, String alwaysUseDefault,
- String loginPage, String authenticationFailureUrl, String successHandlerRef, String failureHandlerRef) {
+ String loginPage, String authenticationFailureUrl, String successHandlerRef, String failureHandlerRef,
+ String authDetailsSourceRef) {
BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(filterClassName);
@@ -121,6 +140,10 @@ public class FormLoginBeanDefinitionParser {
filterBuilder.addPropertyValue("authenticationSuccessHandler", successHandler.getBeanDefinition());
}
+ if (StringUtils.hasText(authDetailsSourceRef)) {
+ filterBuilder.addPropertyReference("authenticationDetailsSource", authDetailsSourceRef);
+ }
+
if (sessionStrategy != null) {
filterBuilder.addPropertyValue("sessionAuthenticationStrategy", sessionStrategy);
}
diff --git a/dist/spring-security-config/org/springframework/security/config/http/HttpConfigurationBuilder.java b/dist/spring-security-config/org/springframework/security/config/http/HttpConfigurationBuilder.java
index 6dafcd3..690c3c1 100644
--- a/dist/spring-security-config/org/springframework/security/config/http/HttpConfigurationBuilder.java
+++ b/dist/spring-security-config/org/springframework/security/config/http/HttpConfigurationBuilder.java
@@ -1,13 +1,11 @@
package org.springframework.security.config.http;
-import static org.springframework.security.config.http.SecurityFilters.*;
import static org.springframework.security.config.http.HttpSecurityBeanDefinitionParser.*;
+import static org.springframework.security.config.http.SecurityFilters.*;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
-import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanReference;
import org.springframework.beans.factory.config.RuntimeBeanReference;
@@ -24,6 +22,7 @@ import org.springframework.security.access.vote.AuthenticatedVoter;
import org.springframework.security.access.vote.RoleVoter;
import org.springframework.security.config.Elements;
import org.springframework.security.core.session.SessionRegistryImpl;
+import org.springframework.security.web.PortResolverImpl;
import org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator;
import org.springframework.security.web.access.channel.ChannelDecisionManagerImpl;
import org.springframework.security.web.access.channel.ChannelProcessingFilter;
@@ -34,17 +33,20 @@ import org.springframework.security.web.access.channel.SecureChannelProcessor;
import org.springframework.security.web.access.expression.WebExpressionVoter;
import org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
-import org.springframework.security.web.access.intercept.RequestKey;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy;
import org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
+import org.springframework.security.web.context.NullSecurityContextRepository;
import org.springframework.security.web.context.SecurityContextPersistenceFilter;
+import org.springframework.security.web.jaasapi.JaasApiIntegrationFilter;
+import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
+import org.springframework.security.web.savedrequest.NullRequestCache;
+import org.springframework.security.web.savedrequest.RequestCacheAwareFilter;
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
import org.springframework.security.web.session.ConcurrentSessionFilter;
import org.springframework.security.web.session.SessionManagementFilter;
-import org.springframework.security.web.util.AntUrlPathMatcher;
-import org.springframework.security.web.util.UrlMatcher;
+import org.springframework.security.web.session.SimpleRedirectInvalidSessionStrategy;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
@@ -57,9 +59,6 @@ import org.w3c.dom.Element;
*/
class HttpConfigurationBuilder {
private static final String ATT_CREATE_SESSION = "create-session";
- private static final String OPT_CREATE_SESSION_NEVER = "never";
- private static final String DEF_CREATE_SESSION_IF_REQUIRED = "ifRequired";
- private static final String OPT_CREATE_SESSION_ALWAYS = "always";
private static final String ATT_SESSION_FIXATION_PROTECTION = "session-fixation-protection";
private static final String OPT_SESSION_FIXATION_NO_PROTECTION = "none";
@@ -75,66 +74,60 @@ class HttpConfigurationBuilder {
private static final String ATT_ACCESS_MGR = "access-decision-manager-ref";
private static final String ATT_ONCE_PER_REQUEST = "once-per-request";
+ private static final String ATT_REF = "ref";
+
private final Element httpElt;
private final ParserContext pc;
- private final UrlMatcher matcher;
- private final Boolean convertPathsToLowerCase;
- private final boolean allowSessionCreation;
+ private final SessionCreationPolicy sessionPolicy;
private final List<Element> interceptUrls;
-
- // Use ManagedMap to allow placeholder resolution
- private ManagedMap<Object, List<BeanMetadataElement>> filterChainMap;
+ private final MatcherType matcherType;
private BeanDefinition cpf;
private BeanDefinition securityContextPersistenceFilter;
private BeanReference contextRepoRef;
private BeanReference sessionRegistryRef;
private BeanDefinition concurrentSessionFilter;
+ private BeanDefinition requestCacheAwareFilter;
private BeanReference sessionStrategyRef;
private RootBeanDefinition sfpf;
private BeanDefinition servApiFilter;
- private String portMapperName;
+ private BeanDefinition jaasApiFilter;
+ private final String portMapperName;
private BeanReference fsi;
+ private BeanReference requestCache;
+
+ public HttpConfigurationBuilder(Element element, ParserContext pc,
+ String portMapperName, BeanReference authenticationManager) {
- public HttpConfigurationBuilder(Element element, ParserContext pc, UrlMatcher matcher, String portMapperName) {
this.httpElt = element;
this.pc = pc;
this.portMapperName = portMapperName;
- this.matcher = matcher;
- // SEC-501 - should paths stored in request maps be converted to lower case
- // true if Ant path and using lower case
- convertPathsToLowerCase = (matcher instanceof AntUrlPathMatcher) && matcher.requiresLowerCaseUrl();
+ this.matcherType = MatcherType.fromElement(element);
interceptUrls = DomUtils.getChildElementsByTagName(element, Elements.INTERCEPT_URL);
- allowSessionCreation = !OPT_CREATE_SESSION_NEVER.equals(element.getAttribute(ATT_CREATE_SESSION));
- }
-
- void parseInterceptUrlsForEmptyFilterChains() {
- filterChainMap = new ManagedMap<Object, List<BeanMetadataElement>>();
for (Element urlElt : interceptUrls) {
- String path = urlElt.getAttribute(ATT_PATH_PATTERN);
-
- if(!StringUtils.hasText(path)) {
- pc.getReaderContext().error("path attribute cannot be empty or null", urlElt);
+ if (StringUtils.hasText(urlElt.getAttribute(ATT_FILTERS))) {
+ pc.getReaderContext().error("The use of \"filters='none'\" is no longer supported. Please define a" +
+ " separate <http> element for the pattern you want to exclude and use the attribute" +
+ " \"security='none'\".", pc.extractSource(urlElt));
}
+ }
- BeanDefinitionBuilder pathBean = BeanDefinitionBuilder.rootBeanDefinition(HttpConfigurationBuilder.class);
- pathBean.setFactoryMethod("createPath");
- pathBean.addConstructorArgValue(path);
- pathBean.addConstructorArgValue(convertPathsToLowerCase);
-
- String filters = urlElt.getAttribute(ATT_FILTERS);
-
- if (StringUtils.hasText(filters)) {
- if (!filters.equals(OPT_FILTERS_NONE)) {
- pc.getReaderContext().error("Currently only 'none' is supported as the custom " +
- "filters attribute", urlElt);
- }
+ String createSession = element.getAttribute(ATT_CREATE_SESSION);
- List<BeanMetadataElement> noFilters = Collections.emptyList();
- filterChainMap.put(pathBean.getBeanDefinition(), noFilters);
- }
+ if (StringUtils.hasText(createSession)) {
+ sessionPolicy = SessionCreationPolicy.valueOf(createSession);
+ } else {
+ sessionPolicy = SessionCreationPolicy.ifRequired;
}
+
+ createSecurityContextPersistenceFilter();
+ createSessionManagementFilters();
+ createRequestCacheFilter();
+ createServletApiFilter();
+ createJaasApiFilter();
+ createChannelProcessingFilter();
+ createFilterSecurityInterceptor(authenticationManager);
}
// Needed to account for placeholders
@@ -142,43 +135,44 @@ class HttpConfigurationBuilder {
return lowerCase ? path.toLowerCase() : path;
}
- void createSecurityContextPersistenceFilter() {
+ private void createSecurityContextPersistenceFilter() {
BeanDefinitionBuilder scpf = BeanDefinitionBuilder.rootBeanDefinition(SecurityContextPersistenceFilter.class);
String repoRef = httpElt.getAttribute(ATT_SECURITY_CONTEXT_REPOSITORY);
- String createSession = httpElt.getAttribute(ATT_CREATE_SESSION);
String disableUrlRewriting = httpElt.getAttribute(ATT_DISABLE_URL_REWRITING);
if (StringUtils.hasText(repoRef)) {
- if (OPT_CREATE_SESSION_ALWAYS.equals(createSession)) {
+ if (sessionPolicy == SessionCreationPolicy.always) {
scpf.addPropertyValue("forceEagerSessionCreation", Boolean.TRUE);
- } else if (StringUtils.hasText(createSession)) {
- pc.getReaderContext().error("If using security-context-repository-ref, the only value you can set for " +
- "'create-session' is 'always'. Other session creation logic should be handled by the " +
- "SecurityContextRepository", httpElt);
}
} else {
- BeanDefinitionBuilder contextRepo = BeanDefinitionBuilder.rootBeanDefinition(HttpSessionSecurityContextRepository.class);
- if (OPT_CREATE_SESSION_ALWAYS.equals(createSession)) {
- contextRepo.addPropertyValue("allowSessionCreation", Boolean.TRUE);
- scpf.addPropertyValue("forceEagerSessionCreation", Boolean.TRUE);
- } else if (OPT_CREATE_SESSION_NEVER.equals(createSession)) {
- contextRepo.addPropertyValue("allowSessionCreation", Boolean.FALSE);
- scpf.addPropertyValue("forceEagerSessionCreation", Boolean.FALSE);
+ BeanDefinitionBuilder contextRepo;
+ if (sessionPolicy == SessionCreationPolicy.stateless) {
+ contextRepo = BeanDefinitionBuilder.rootBeanDefinition(NullSecurityContextRepository.class);
} else {
- createSession = DEF_CREATE_SESSION_IF_REQUIRED;
- contextRepo.addPropertyValue("allowSessionCreation", Boolean.TRUE);
- scpf.addPropertyValue("forceEagerSessionCreation", Boolean.FALSE);
- }
+ contextRepo = BeanDefinitionBuilder.rootBeanDefinition(HttpSessionSecurityContextRepository.class);
+ switch (sessionPolicy) {
+ case always:
+ contextRepo.addPropertyValue("allowSessionCreation", Boolean.TRUE);
+ scpf.addPropertyValue("forceEagerSessionCreation", Boolean.TRUE);
+ break;
+ case never:
+ contextRepo.addPropertyValue("allowSessionCreation", Boolean.FALSE);
+ scpf.addPropertyValue("forceEagerSessionCreation", Boolean.FALSE);
+ break;
+ default:
+ contextRepo.addPropertyValue("allowSessionCreation", Boolean.TRUE);
+ scpf.addPropertyValue("forceEagerSessionCreation", Boolean.FALSE);
+ }
- if ("true".equals(disableUrlRewriting)) {
- contextRepo.addPropertyValue("disableUrlRewriting", Boolean.TRUE);
+ if ("true".equals(disableUrlRewriting)) {
+ contextRepo.addPropertyValue("disableUrlRewriting", Boolean.TRUE);
+ }
}
BeanDefinition repoBean = contextRepo.getBeanDefinition();
repoRef = pc.getReaderContext().generateBeanName(repoBean);
pc.registerBeanComponent(new BeanComponentDefinition(repoBean, repoRef));
-
}
contextRepoRef = new RuntimeBeanReference(repoRef);
@@ -187,7 +181,7 @@ class HttpConfigurationBuilder {
securityContextPersistenceFilter = scpf.getBeanDefinition();
}
- void createSessionManagementFilters() {
+ private void createSessionManagementFilters() {
Element sessionMgmtElt = DomUtils.getChildElementByTagName(httpElt, Elements.SESSION_MANAGEMENT);
Element sessionCtrlElt = null;
@@ -197,6 +191,11 @@ class HttpConfigurationBuilder {
String errorUrl = null;
if (sessionMgmtElt != null) {
+ if (sessionPolicy == SessionCreationPolicy.stateless) {
+ pc.getReaderContext().error(Elements.SESSION_MANAGEMENT + " cannot be used" +
+ " in combination with " + ATT_CREATE_SESSION + "='"+ SessionCreationPolicy.stateless +"'",
+ pc.extractSource(sessionMgmtElt));
+ }
sessionFixationAttribute = sessionMgmtElt.getAttribute(ATT_SESSION_FIXATION_PROTECTION);
invalidSessionUrl = sessionMgmtElt.getAttribute(ATT_INVALID_SESSION_URL);
sessionAuthStratRef = sessionMgmtElt.getAttribute(ATT_SESSION_AUTH_STRATEGY_REF);
@@ -216,7 +215,12 @@ class HttpConfigurationBuilder {
sessionFixationAttribute = OPT_SESSION_FIXATION_MIGRATE_SESSION;
} else if (StringUtils.hasText(sessionAuthStratRef)) {
pc.getReaderContext().error(ATT_SESSION_FIXATION_PROTECTION + " attribute cannot be used" +
- " in combination with " + ATT_SESSION_AUTH_STRATEGY_REF, pc.extractSource(sessionCtrlElt));
+ " in combination with " + ATT_SESSION_AUTH_STRATEGY_REF, pc.extractSource(sessionMgmtElt));
+ }
+
+ if (sessionPolicy == SessionCreationPolicy.stateless) {
+ // SEC-1424: do nothing
+ return;
}
boolean sessionFixationProtectionRequired = !sessionFixationAttribute.equals(OPT_SESSION_FIXATION_NO_PROTECTION);
@@ -267,7 +271,7 @@ class HttpConfigurationBuilder {
}
if (StringUtils.hasText(invalidSessionUrl)) {
- sessionMgmtFilter.addPropertyValue("invalidSessionUrl", invalidSessionUrl);
+ sessionMgmtFilter.addPropertyValue("invalidSessionStrategy", new SimpleRedirectInvalidSessionStrategy(invalidSessionUrl));
}
sessionMgmtFilter.addPropertyReference("sessionAuthenticationStrategy", sessionAuthStratRef);
@@ -323,7 +327,7 @@ class HttpConfigurationBuilder {
}
// Adds the servlet-api integration filter if required
- void createServletApiFilter() {
+ private void createServletApiFilter() {
final String ATT_SERVLET_API_PROVISION = "servlet-api-provision";
final String DEF_SERVLET_API_PROVISION = "true";
@@ -337,7 +341,22 @@ class HttpConfigurationBuilder {
}
}
- void createChannelProcessingFilter() {
+ // Adds the jaas-api integration filter if required
+ private void createJaasApiFilter() {
+ final String ATT_JAAS_API_PROVISION = "jaas-api-provision";
+ final String DEF_JAAS_API_PROVISION = "false";
+
+ String provideJaasApi = httpElt.getAttribute(ATT_JAAS_API_PROVISION);
+ if (!StringUtils.hasText(provideJaasApi)) {
+ provideJaasApi = DEF_JAAS_API_PROVISION;
+ }
+
+ if ("true".equals(provideJaasApi)) {
+ jaasApiFilter = new RootBeanDefinition(JaasApiIntegrationFilter.class);
+ }
+ }
+
+ private void createChannelProcessingFilter() {
ManagedMap<BeanDefinition,BeanDefinition> channelRequestMap = parseInterceptUrlsForChannelSecurity();
if (channelRequestMap.isEmpty()) {
@@ -346,9 +365,8 @@ class HttpConfigurationBuilder {
RootBeanDefinition channelFilter = new RootBeanDefinition(ChannelProcessingFilter.class);
BeanDefinitionBuilder metadataSourceBldr = BeanDefinitionBuilder.rootBeanDefinition(DefaultFilterInvocationSecurityMetadataSource.class);
- metadataSourceBldr.addConstructorArgValue(matcher);
metadataSourceBldr.addConstructorArgValue(channelRequestMap);
- metadataSourceBldr.addPropertyValue("stripQueryStringFromUrls", matcher instanceof AntUrlPathMatcher);
+// metadataSourceBldr.addPropertyValue("stripQueryStringFromUrls", matcher instanceof AntUrlPathMatcher);
channelFilter.getPropertyValues().addPropertyValue("securityMetadataSource", metadataSourceBldr.getBeanDefinition());
RootBeanDefinition channelDecisionManager = new RootBeanDefinition(ChannelDecisionManagerImpl.class);
@@ -381,52 +399,79 @@ class HttpConfigurationBuilder {
for (Element urlElt : interceptUrls) {
String path = urlElt.getAttribute(ATT_PATH_PATTERN);
+ String method = urlElt.getAttribute(ATT_HTTP_METHOD);
if(!StringUtils.hasText(path)) {
- pc.getReaderContext().error("path attribute cannot be empty or null", urlElt);
- }
-
- if (convertPathsToLowerCase) {
- path = path.toLowerCase();
+ pc.getReaderContext().error("pattern attribute cannot be empty or null", urlElt);
}
String requiredChannel = urlElt.getAttribute(ATT_REQUIRES_CHANNEL);
if (StringUtils.hasText(requiredChannel)) {
- BeanDefinition requestKey = new RootBeanDefinition(RequestKey.class);
- requestKey.getConstructorArgumentValues().addGenericArgumentValue(path);
-
- String method = urlElt.getAttribute(ATT_HTTP_METHOD);
- if(StringUtils.hasText(method)) {
- requestKey.getConstructorArgumentValues().addGenericArgumentValue(method);
- }
+ BeanDefinition matcher = matcherType.createMatcher(path, method);
RootBeanDefinition channelAttributes = new RootBeanDefinition(ChannelAttributeFactory.class);
channelAttributes.getConstructorArgumentValues().addGenericArgumentValue(requiredChannel);
channelAttributes.setFactoryMethodName("createChannelAttributes");
- channelRequestMap.put(requestKey, channelAttributes);
+ channelRequestMap.put(matcher, channelAttributes);
}
}
return channelRequestMap;
}
- void createFilterSecurityInterceptor(BeanReference authManager) {
+ private void createRequestCacheFilter() {
+ Element requestCacheElt = DomUtils.getChildElementByTagName(httpElt, Elements.REQUEST_CACHE);
+
+ if (requestCacheElt != null) {
+ requestCache = new RuntimeBeanReference(requestCacheElt.getAttribute(ATT_REF));
+ } else {
+ BeanDefinitionBuilder requestCacheBldr;
+
+ if (sessionPolicy == SessionCreationPolicy.stateless) {
+ requestCacheBldr = BeanDefinitionBuilder.rootBeanDefinition(NullRequestCache.class);
+ } else {
+ requestCacheBldr = BeanDefinitionBuilder.rootBeanDefinition(HttpSessionRequestCache.class);
+ BeanDefinitionBuilder portResolver = BeanDefinitionBuilder.rootBeanDefinition(PortResolverImpl.class);
+ portResolver.addPropertyReference("portMapper", portMapperName);
+ requestCacheBldr.addPropertyValue("createSessionAllowed", sessionPolicy == SessionCreationPolicy.ifRequired);
+ requestCacheBldr.addPropertyValue("portResolver", portResolver.getBeanDefinition());
+ }
+
+ BeanDefinition bean = requestCacheBldr.getBeanDefinition();
+ String id = pc.getReaderContext().generateBeanName(bean);
+ pc.registerBeanComponent(new BeanComponentDefinition(bean, id));
+
+ this.requestCache = new RuntimeBeanReference(id);
+ }
+
+ requestCacheAwareFilter = new RootBeanDefinition(RequestCacheAwareFilter.class);
+ requestCacheAwareFilter.getPropertyValues().addPropertyValue("requestCache", requestCache);
+ }
+
+ private void createFilterSecurityInterceptor(BeanReference authManager) {
boolean useExpressions = FilterInvocationSecurityMetadataSourceParser.isUseExpressions(httpElt);
- BeanDefinition securityMds = FilterInvocationSecurityMetadataSourceParser.createSecurityMetadataSource(interceptUrls, httpElt, pc);
+ RootBeanDefinition securityMds = FilterInvocationSecurityMetadataSourceParser.createSecurityMetadataSource(interceptUrls, httpElt, pc);
RootBeanDefinition accessDecisionMgr;
ManagedList<BeanDefinition> voters = new ManagedList<BeanDefinition>(2);
if (useExpressions) {
- voters.add(new RootBeanDefinition(WebExpressionVoter.class));
+ BeanDefinitionBuilder expressionVoter = BeanDefinitionBuilder.rootBeanDefinition(WebExpressionVoter.class);
+ // Read the expression handler from the FISMS
+ RuntimeBeanReference expressionHandler = (RuntimeBeanReference)
+ securityMds.getConstructorArgumentValues().getArgumentValue(1, RuntimeBeanReference.class).getValue();
+
+ expressionVoter.addPropertyValue("expressionHandler", expressionHandler);
+
+ voters.add(expressionVoter.getBeanDefinition());
} else {
voters.add(new RootBeanDefinition(RoleVoter.class));
voters.add(new RootBeanDefinition(AuthenticatedVoter.class));
}
accessDecisionMgr = new RootBeanDefinition(AffirmativeBased.class);
- accessDecisionMgr.getPropertyValues().addPropertyValue("decisionVoters", voters);
+ accessDecisionMgr.getConstructorArgumentValues().addGenericArgumentValue(voters);
accessDecisionMgr.setSource(pc.extractSource(httpElt));
// Set up the access manager reference for http
@@ -464,13 +509,12 @@ class HttpConfigurationBuilder {
return sessionStrategyRef;
}
-
- boolean isAllowSessionCreation() {
- return allowSessionCreation;
+ SessionCreationPolicy getSessionCreationPolicy() {
+ return sessionPolicy;
}
- public ManagedMap<Object, List<BeanMetadataElement>> getFilterChainMap() {
- return filterChainMap;
+ BeanReference getRequestCache() {
+ return requestCache;
}
List<OrderDecorator> getFilters() {
@@ -490,12 +534,20 @@ class HttpConfigurationBuilder {
filters.add(new OrderDecorator(servApiFilter, SERVLET_API_SUPPORT_FILTER));
}
+ if (jaasApiFilter != null) {
+ filters.add(new OrderDecorator(jaasApiFilter, JAAS_API_SUPPORT_FILTER));
+ }
+
if (sfpf != null) {
filters.add(new OrderDecorator(sfpf, SESSION_MANAGEMENT_FILTER));
}
filters.add(new OrderDecorator(fsi, FILTER_SECURITY_INTERCEPTOR));
+ if (sessionPolicy != SessionCreationPolicy.stateless) {
+ filters.add(new OrderDecorator(requestCacheAwareFilter, REQUEST_CACHE_FILTER));
+ }
+
return filters;
}
}
diff --git a/dist/spring-security-config/org/springframework/security/config/http/HttpFirewallBeanDefinitionParser.java b/dist/spring-security-config/org/springframework/security/config/http/HttpFirewallBeanDefinitionParser.java
index 5565ff2..3b232ef 100644
--- a/dist/spring-security-config/org/springframework/security/config/http/HttpFirewallBeanDefinitionParser.java
+++ b/dist/spring-security-config/org/springframework/security/config/http/HttpFirewallBeanDefinitionParser.java
@@ -1,19 +1,13 @@
package org.springframework.security.config.http;
-import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanReference;
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.support.ManagedMap;
-import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.security.config.BeanIds;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
-import java.util.*;
-
/**
* Injects the supplied {@code HttpFirewall} bean reference into the {@code FilterChainProxy}.
*
@@ -28,10 +22,10 @@ public class HttpFirewallBeanDefinitionParser implements BeanDefinitionParser {
pc.getReaderContext().error("ref attribute is required", pc.extractSource(element));
}
- BeanDefinitionBuilder injector = BeanDefinitionBuilder.rootBeanDefinition(HttpFirewallInjectionBeanPostProcessor.class);
- injector.addConstructorArgValue(ref);
-
- pc.getReaderContext().registerWithGeneratedName(injector.getBeanDefinition());
+ // Ensure the FCP is registered.
+ HttpSecurityBeanDefinitionParser.registerFilterChainProxyIfNecessary(pc, pc.extractSource(element));
+ BeanDefinition filterChainProxy = pc.getRegistry().getBeanDefinition(BeanIds.FILTER_CHAIN_PROXY);
+ filterChainProxy.getPropertyValues().addPropertyValue("firewall", new RuntimeBeanReference(ref));
return null;
}
diff --git a/dist/spring-security-config/org/springframework/security/config/http/HttpFirewallInjectionBeanPostProcessor.java b/dist/spring-security-config/org/springframework/security/config/http/HttpFirewallInjectionBeanPostProcessor.java
deleted file mode 100644
index a88cb90..0000000
--- a/dist/spring-security-config/org/springframework/security/config/http/HttpFirewallInjectionBeanPostProcessor.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package org.springframework.security.config.http;
-
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.BeanFactory;
-import org.springframework.beans.factory.BeanFactoryAware;
-import org.springframework.beans.factory.config.BeanPostProcessor;
-import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
-import org.springframework.security.config.BeanIds;
-import org.springframework.security.web.FilterChainProxy;
-import org.springframework.security.web.firewall.HttpFirewall;
-
-/**
- * @author Luke Taylor
- */
-public class HttpFirewallInjectionBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {
- private ConfigurableListableBeanFactory beanFactory;
- private String ref;
-
- public HttpFirewallInjectionBeanPostProcessor(String ref) {
- this.ref = ref;
- }
-
- public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
- if (BeanIds.FILTER_CHAIN_PROXY.equals(beanName)) {
- HttpFirewall fw = (HttpFirewall) beanFactory.getBean(ref);
- ((FilterChainProxy)bean).setFirewall(fw);
- }
-
- return bean;
- }
-
- public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
- return bean;
- }
-
-
- public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
- this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
- }
-}
diff --git a/dist/spring-security-config/org/springframework/security/config/http/HttpSecurityBeanDefinitionParser.java b/dist/spring-security-config/org/springframework/security/config/http/HttpSecurityBeanDefinitionParser.java
index 2d29511..ce4a364 100644
--- a/dist/spring-security-config/org/springframework/security/config/http/HttpSecurityBeanDefinitionParser.java
+++ b/dist/spring-security-config/org/springframework/security/config/http/HttpSecurityBeanDefinitionParser.java
@@ -1,24 +1,17 @@
package org.springframework.security.config.http;
-import static org.springframework.security.config.http.SecurityFilters.REQUEST_CACHE_FILTER;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanReference;
+import org.springframework.beans.factory.config.ListFactoryBean;
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
-import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
@@ -28,15 +21,15 @@ import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.Elements;
import org.springframework.security.config.authentication.AuthenticationManagerFactoryBean;
+import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.FilterChainProxy;
-import org.springframework.security.web.savedrequest.RequestCacheAwareFilter;
-import org.springframework.security.web.util.AntUrlPathMatcher;
-import org.springframework.security.web.util.RegexUrlPathMatcher;
-import org.springframework.security.web.util.UrlMatcher;
+import org.springframework.security.web.util.AnyRequestMatcher;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
+import java.util.*;
+
/**
* Sets up HTTP security: filter stack and protected URLs.
*
@@ -47,25 +40,19 @@ import org.w3c.dom.Element;
public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
private static final Log logger = LogFactory.getLog(HttpSecurityBeanDefinitionParser.class);
+ private static final String ATT_AUTHENTICATION_MANAGER_REF = "authentication-manager-ref";
+ private static final String ATT_REQUEST_MATCHER_REF = "request-matcher-ref";
static final String ATT_PATH_PATTERN = "pattern";
- static final String ATT_PATH_TYPE = "path-type";
- static final String OPT_PATH_TYPE_REGEX = "regex";
- private static final String DEF_PATH_TYPE_ANT = "ant";
+ static final String ATT_HTTP_METHOD = "method";
static final String ATT_FILTERS = "filters";
static final String OPT_FILTERS_NONE = "none";
static final String ATT_REQUIRES_CHANNEL = "requires-channel";
- static final String ATT_HTTP_METHOD = "method";
-
- private static final String ATT_LOWERCASE_COMPARISONS = "lowercase-comparisons";
private static final String ATT_REF = "ref";
-
- static final String EXPRESSION_FIMDS_CLASS = "org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource";
- static final String EXPRESSION_HANDLER_CLASS = "org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler";
-
- static final List<BeanMetadataElement> NO_FILTERS = Collections.emptyList();
+ private static final String ATT_SECURED = "security";
+ private static final String OPT_SECURITY_NONE = "none";
public HttpSecurityBeanDefinitionParser() {
}
@@ -78,72 +65,118 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
* By the end of this method, the default <tt>FilterChainProxy</tt> bean should have been registered and will have
* the map of filter chains defined, with the "universal" match pattern mapped to the list of beans which have been parsed here.
*/
+ @SuppressWarnings({"unchecked"})
public BeanDefinition parse(Element element, ParserContext pc) {
CompositeComponentDefinition compositeDef =
new CompositeComponentDefinition(element.getTagName(), pc.extractSource(element));
pc.pushContainingComponent(compositeDef);
- final Object source = pc.extractSource(element);
- final String portMapperName = createPortMapper(element, pc);
- final UrlMatcher matcher = createUrlMatcher(element);
+ registerFilterChainProxyIfNecessary(pc, pc.extractSource(element));
+
+ // Obtain the filter chains and add the new chain to it
+ BeanDefinition listFactoryBean = pc.getRegistry().getBeanDefinition(BeanIds.FILTER_CHAINS);
+ List<BeanReference> filterChains = (List<BeanReference>)
+ listFactoryBean.getPropertyValues().getPropertyValue("sourceList").getValue();
+
+ filterChains.add(createFilterChain(element, pc));
+
+ pc.popAndRegisterContainingComponent();
+ return null;
+ }
- HttpConfigurationBuilder httpBldr = new HttpConfigurationBuilder(element, pc, matcher, portMapperName);
+ /**
+ * Creates the {@code SecurityFilterChain} bean from an <http> element.
+ */
+ private BeanReference createFilterChain(Element element, ParserContext pc) {
+ boolean secured = !OPT_SECURITY_NONE.equals(element.getAttribute(ATT_SECURED));
+
+ if (!secured) {
+ if (!StringUtils.hasText(element.getAttribute(ATT_PATH_PATTERN)) &&
+ !StringUtils.hasText(ATT_REQUEST_MATCHER_REF)) {
+ pc.getReaderContext().error("The '" + ATT_SECURED + "' attribute must be used in combination with" +
+ " the '" + ATT_PATH_PATTERN +"' or '" + ATT_REQUEST_MATCHER_REF + "' attributes.",
+ pc.extractSource(element));
+ }
+
+ for (int n=0; n < element.getChildNodes().getLength(); n ++) {
+ if (element.getChildNodes().item(n) instanceof Element) {
+ pc.getReaderContext().error("If you are using <http> to define an unsecured pattern, " +
+ "it cannot contain child elements.", pc.extractSource(element));
+ }
+ }
- httpBldr.parseInterceptUrlsForEmptyFilterChains();
- httpBldr.createSecurityContextPersistenceFilter();
- httpBldr.createSessionManagementFilters();
+ return createSecurityFilterChainBean(element, pc, Collections.emptyList());
+ }
+
+ final String portMapperName = createPortMapper(element, pc);
ManagedList<BeanReference> authenticationProviders = new ManagedList<BeanReference>();
- BeanReference authenticationManager = createAuthenticationManager(element, pc, authenticationProviders, null);
+ BeanReference authenticationManager = createAuthenticationManager(element, pc, authenticationProviders);
- httpBldr.createServletApiFilter();
- httpBldr.createChannelProcessingFilter();
- httpBldr.createFilterSecurityInterceptor(authenticationManager);
+ HttpConfigurationBuilder httpBldr = new HttpConfigurationBuilder(element, pc,
+ portMapperName, authenticationManager);
AuthenticationConfigBuilder authBldr = new AuthenticationConfigBuilder(element, pc,
- httpBldr.isAllowSessionCreation(), portMapperName);
-
- authBldr.createAnonymousFilter();
- authBldr.createRememberMeFilter(authenticationManager);
- authBldr.createRequestCache();
- authBldr.createBasicFilter(authenticationManager);
- authBldr.createFormLoginFilter(httpBldr.getSessionStrategy(), authenticationManager);
- authBldr.createOpenIDLoginFilter(httpBldr.getSessionStrategy(), authenticationManager);
- authBldr.createX509Filter(authenticationManager);
- authBldr.createLogoutFilter();
- authBldr.createLoginPageFilterIfNeeded();
- authBldr.createUserServiceInjector();
- authBldr.createExceptionTranslationFilter();
+ httpBldr.getSessionCreationPolicy(), httpBldr.getRequestCache(), authenticationManager,
+ httpBldr.getSessionStrategy());
+
+ authenticationProviders.addAll(authBldr.getProviders());
List<OrderDecorator> unorderedFilterChain = new ArrayList<OrderDecorator>();
unorderedFilterChain.addAll(httpBldr.getFilters());
unorderedFilterChain.addAll(authBldr.getFilters());
-
- authenticationProviders.addAll(authBldr.getProviders());
-
- BeanDefinition requestCacheAwareFilter = new RootBeanDefinition(RequestCacheAwareFilter.class);
- requestCacheAwareFilter.getPropertyValues().addPropertyValue("requestCache", authBldr.getRequestCache());
- unorderedFilterChain.add(new OrderDecorator(requestCacheAwareFilter, REQUEST_CACHE_FILTER));
-
unorderedFilterChain.addAll(buildCustomFilterList(element, pc));
Collections.sort(unorderedFilterChain, new OrderComparator());
- checkFilterChainOrder(unorderedFilterChain, pc, source);
+ checkFilterChainOrder(unorderedFilterChain, pc, pc.extractSource(element));
+ // The list of filter beans
List<BeanMetadataElement> filterChain = new ManagedList<BeanMetadataElement>();
for (OrderDecorator od : unorderedFilterChain) {
filterChain.add(od.bean);
}
- ManagedMap<Object, List<BeanMetadataElement>> filterChainMap = httpBldr.getFilterChainMap();
- filterChainMap.put(matcher.getUniversalMatchPattern(), filterChain);
+ return createSecurityFilterChainBean(element, pc, filterChain);
+ }
- registerFilterChainProxy(pc, filterChainMap, matcher, source);
+ private BeanReference createSecurityFilterChainBean(Element element, ParserContext pc, List<?> filterChain) {
+ BeanMetadataElement filterChainMatcher;
- pc.popAndRegisterContainingComponent();
- return null;
+ String requestMatcherRef = element.getAttribute(ATT_REQUEST_MATCHER_REF);
+ String filterChainPattern = element.getAttribute(ATT_PATH_PATTERN);
+
+ if (StringUtils.hasText(requestMatcherRef)) {
+ if (StringUtils.hasText(filterChainPattern)) {
+ pc.getReaderContext().error("You can't define a pattern and a request-matcher-ref for the " +
+ "same filter chain", pc.extractSource(element));
+ }
+ filterChainMatcher = new RuntimeBeanReference(requestMatcherRef);
+
+ } else if (StringUtils.hasText(filterChainPattern)) {
+ filterChainMatcher = MatcherType.fromElement(element).createMatcher(filterChainPattern, null);
+ } else {
+ filterChainMatcher = new RootBeanDefinition(AnyRequestMatcher.class);
+ }
+
+ BeanDefinitionBuilder filterChainBldr = BeanDefinitionBuilder.rootBeanDefinition(DefaultSecurityFilterChain.class);
+ filterChainBldr.addConstructorArgValue(filterChainMatcher);
+ filterChainBldr.addConstructorArgValue(filterChain);
+
+ BeanDefinition filterChainBean = filterChainBldr.getBeanDefinition();
+
+ String id = element.getAttribute("name");
+ if (!StringUtils.hasText(id)) {
+ id = element.getAttribute("id");
+ if (!StringUtils.hasText(id)) {
+ id = pc.getReaderContext().generateBeanName(filterChainBean);
+ }
+ }
+
+ pc.registerBeanComponent(new BeanComponentDefinition(filterChainBean, id));
+
+ return new RuntimeBeanReference(id);
}
private String createPortMapper(Element elt, ParserContext pc) {
@@ -157,25 +190,33 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
}
/**
- * Creates the internal AuthenticationManager bean which uses the externally registered (global) one as
- * a parent.
+ * Creates the internal AuthenticationManager bean which uses either the externally registered (global) one as
+ * a parent or the bean specified by "authentication-manager-ref".
*
- * All the providers registered by this <http> block will be registered with the internal
- * authentication manager.
+ * All the providers registered by this <http> block will be registered with the internal authentication
+ * manager.
*/
private BeanReference createAuthenticationManager(Element element, ParserContext pc,
- ManagedList<BeanReference> authenticationProviders, BeanReference concurrencyController) {
+ ManagedList<BeanReference> authenticationProviders) {
+ String parentMgrRef = element.getAttribute(ATT_AUTHENTICATION_MANAGER_REF);
BeanDefinitionBuilder authManager = BeanDefinitionBuilder.rootBeanDefinition(ProviderManager.class);
- authManager.addPropertyValue("parent", new RootBeanDefinition(AuthenticationManagerFactoryBean.class));
- authManager.addPropertyValue("providers", authenticationProviders);
- RootBeanDefinition clearCredentials = new RootBeanDefinition(MethodInvokingFactoryBean.class);
- clearCredentials.getPropertyValues().addPropertyValue("targetObject", new RootBeanDefinition(AuthenticationManagerFactoryBean.class));
- clearCredentials.getPropertyValues().addPropertyValue("targetMethod", "isEraseCredentialsAfterAuthentication");
- authManager.addPropertyValue("eraseCredentialsAfterAuthentication", clearCredentials);
-
- if (concurrencyController != null) {
- authManager.addPropertyValue("sessionController", concurrencyController);
+ authManager.addConstructorArgValue(authenticationProviders);
+
+ if (StringUtils.hasText(parentMgrRef)) {
+ authManager.addConstructorArgValue(new RuntimeBeanReference(parentMgrRef));
+ } else {
+ RootBeanDefinition amfb = new RootBeanDefinition(AuthenticationManagerFactoryBean.class);
+ amfb.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
+ String amfbId = pc.getReaderContext().generateBeanName(amfb);
+ pc.registerBeanComponent(new BeanComponentDefinition(amfb, amfbId));
+ RootBeanDefinition clearCredentials = new RootBeanDefinition(MethodInvokingFactoryBean.class);
+ clearCredentials.getPropertyValues().addPropertyValue("targetObject", new RuntimeBeanReference(amfbId));
+ clearCredentials.getPropertyValues().addPropertyValue("targetMethod", "isEraseCredentialsAfterAuthentication");
+
+ authManager.addConstructorArgValue(new RuntimeBeanReference(amfbId));
+ authManager.addPropertyValue("eraseCredentialsAfterAuthentication", clearCredentials);
}
+
authManager.getRawBeanDefinition().setSource(pc.extractSource(element));
BeanDefinition authMgrBean = authManager.getBeanDefinition();
String id = pc.getReaderContext().generateBeanName(authMgrBean);
@@ -188,10 +229,10 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
logger.info("Checking sorted filter chain: " + filters);
for(int i=0; i < filters.size(); i++) {
- OrderDecorator filter = (OrderDecorator)filters.get(i);
+ OrderDecorator filter = filters.get(i);
if (i > 0) {
- OrderDecorator previous = (OrderDecorator)filters.get(i-1);
+ OrderDecorator previous = filters.get(i-1);
if (filter.getOrder() == previous.getOrder()) {
pc.getReaderContext().error("Filter beans '" + filter.bean + "' and '" +
previous.bean + "' have the same 'order' value. When using custom filters, " +
@@ -251,62 +292,29 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
return customFilters;
}
- private void registerFilterChainProxy(ParserContext pc, Map<Object, List<BeanMetadataElement>> filterChainMap, UrlMatcher matcher, Object source) {
+ static void registerFilterChainProxyIfNecessary(ParserContext pc, Object source) {
if (pc.getRegistry().containsBeanDefinition(BeanIds.FILTER_CHAIN_PROXY)) {
- pc.getReaderContext().error("Duplicate <http> element detected", source);
+ return;
}
+ // Not already registered, so register the list of filter chains and the FilterChainProxy
+ BeanDefinition listFactoryBean = new RootBeanDefinition(ListFactoryBean.class);
+ listFactoryBean.getPropertyValues().add("sourceList", new ManagedList());
+ pc.registerBeanComponent(new BeanComponentDefinition(listFactoryBean, BeanIds.FILTER_CHAINS));
BeanDefinitionBuilder fcpBldr = BeanDefinitionBuilder.rootBeanDefinition(FilterChainProxy.class);
fcpBldr.getRawBeanDefinition().setSource(source);
- fcpBldr.addPropertyValue("matcher", matcher);
- fcpBldr.addPropertyValue("stripQueryStringFromUrls", Boolean.valueOf(matcher instanceof AntUrlPathMatcher));
- fcpBldr.addPropertyValue("filterChainMap", filterChainMap);
+ fcpBldr.addConstructorArgReference(BeanIds.FILTER_CHAINS);
+ fcpBldr.addPropertyValue("filterChainValidator", new RootBeanDefinition(DefaultFilterChainValidator.class));
BeanDefinition fcpBean = fcpBldr.getBeanDefinition();
pc.registerBeanComponent(new BeanComponentDefinition(fcpBean, BeanIds.FILTER_CHAIN_PROXY));
pc.getRegistry().registerAlias(BeanIds.FILTER_CHAIN_PROXY, BeanIds.SPRING_SECURITY_FILTER_CHAIN);
}
- static UrlMatcher createUrlMatcher(Element element) {
- String patternType = element.getAttribute(ATT_PATH_TYPE);
- if (!StringUtils.hasText(patternType)) {
- patternType = DEF_PATH_TYPE_ANT;
- }
-
- boolean useRegex = patternType.equals(OPT_PATH_TYPE_REGEX);
-
- UrlMatcher matcher = new AntUrlPathMatcher();
-
- if (useRegex) {
- matcher = new RegexUrlPathMatcher();
- }
-
- // Deal with lowercase conversion requests
- String lowercaseComparisons = element.getAttribute(ATT_LOWERCASE_COMPARISONS);
- if (!StringUtils.hasText(lowercaseComparisons)) {
- lowercaseComparisons = null;
- }
-
- // Only change from the defaults if the attribute has been set
- if ("true".equals(lowercaseComparisons)) {
- if (useRegex) {
- ((RegexUrlPathMatcher)matcher).setRequiresLowerCaseUrl(true);
- }
- // Default for ant is already to force lower case
- } else if ("false".equals(lowercaseComparisons)) {
- if (!useRegex) {
- ((AntUrlPathMatcher)matcher).setRequiresLowerCaseUrl(false);
- }
- // Default for regex is no change
- }
-
- return matcher;
- }
-
}
class OrderDecorator implements Ordered {
- BeanMetadataElement bean;
- int order;
+ final BeanMetadataElement bean;
+ final int order;
public OrderDecorator(BeanMetadataElement bean, SecurityFilters filterOrder) {
this.bean = bean;
diff --git a/dist/spring-security-config/org/springframework/security/config/http/LogoutBeanDefinitionParser.java b/dist/spring-security-config/org/springframework/security/config/http/LogoutBeanDefinitionParser.java
index 4697c56..e4d5de5 100644
--- a/dist/spring-security-config/org/springframework/security/config/http/LogoutBeanDefinitionParser.java
+++ b/dist/spring-security-config/org/springframework/security/config/http/LogoutBeanDefinitionParser.java
@@ -4,8 +4,10 @@ import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
+import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.security.web.authentication.logout.CookieClearingLogoutHandler;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.util.StringUtils;
@@ -20,13 +22,13 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser {
static final String DEF_LOGOUT_SUCCESS_URL = "/";
static final String ATT_INVALIDATE_SESSION = "invalidate-session";
- static final String DEF_INVALIDATE_SESSION = "true";
static final String ATT_LOGOUT_URL = "logout-url";
static final String DEF_LOGOUT_URL = "/j_spring_security_logout";
static final String ATT_LOGOUT_HANDLER = "success-handler-ref";
+ static final String ATT_DELETE_COOKIES = "delete-cookies";
- String rememberMeServices;
+ final String rememberMeServices;
public LogoutBeanDefinitionParser(String rememberMeServices) {
this.rememberMeServices = rememberMeServices;
@@ -38,6 +40,7 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser {
String successHandlerRef = null;
String logoutSuccessUrl = null;
String invalidateSession = null;
+ String deleteCookies = null;
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(LogoutFilter.class);
@@ -50,6 +53,7 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser {
logoutSuccessUrl = element.getAttribute(ATT_LOGOUT_SUCCESS_URL);
WebConfigUtils.validateHttpRedirect(logoutSuccessUrl, pc, source);
invalidateSession = element.getAttribute(ATT_INVALIDATE_SESSION);
+ deleteCookies = element.getAttribute(ATT_DELETE_COOKIES);
}
if (!StringUtils.hasText(logoutUrl)) {
@@ -71,23 +75,22 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser {
builder.addConstructorArgValue(logoutSuccessUrl);
}
- if (!StringUtils.hasText(invalidateSession)) {
- invalidateSession = DEF_INVALIDATE_SESSION;
- }
-
ManagedList handlers = new ManagedList();
- SecurityContextLogoutHandler sclh = new SecurityContextLogoutHandler();
- if ("true".equals(invalidateSession)) {
- sclh.setInvalidateHttpSession(true);
- } else {
- sclh.setInvalidateHttpSession(false);
- }
+ BeanDefinition sclh = new RootBeanDefinition(SecurityContextLogoutHandler.class);
+ sclh.getPropertyValues().addPropertyValue("invalidateHttpSession", !"false".equals(invalidateSession));
handlers.add(sclh);
if (rememberMeServices != null) {
handlers.add(new RuntimeBeanReference(rememberMeServices));
}
+ if (StringUtils.hasText(deleteCookies)) {
+ BeanDefinition cookieDeleter = new RootBeanDefinition(CookieClearingLogoutHandler.class);
+ String[] names = StringUtils.tokenizeToStringArray(deleteCookies, ",");
+ cookieDeleter.getConstructorArgumentValues().addGenericArgumentValue(names);
+ handlers.add(cookieDeleter);
+ }
+
builder.addConstructorArgValue(handlers);
return builder.getBeanDefinition();
diff --git a/dist/spring-security-config/org/springframework/security/config/http/RememberMeBeanDefinitionParser.java b/dist/spring-security-config/org/springframework/security/config/http/RememberMeBeanDefinitionParser.java
index c4c2598..17f5f6a 100644
--- a/dist/spring-security-config/org/springframework/security/config/http/RememberMeBeanDefinitionParser.java
+++ b/dist/spring-security-config/org/springframework/security/config/http/RememberMeBeanDefinitionParser.java
@@ -10,6 +10,7 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.security.config.BeanIds;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices;
import org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter;
@@ -27,11 +28,11 @@ class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
static final String ATT_SERVICES_ALIAS = "services-alias";
static final String ATT_TOKEN_REPOSITORY = "token-repository-ref";
static final String ATT_USER_SERVICE_REF = "user-service-ref";
+ static final String ATT_SUCCESS_HANDLER_REF = "authentication-success-handler-ref";
static final String ATT_TOKEN_VALIDITY = "token-validity-seconds";
static final String ATT_SECURE_COOKIE = "use-secure-cookie";
protected final Log logger = LogFactory.getLog(getClass());
- private String servicesName;
private final String key;
RememberMeBeanDefinitionParser(String key) {
@@ -46,6 +47,7 @@ class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
String tokenRepository = element.getAttribute(ATT_TOKEN_REPOSITORY);
String dataSource = element.getAttribute(ATT_DATA_SOURCE);
String userServiceRef = element.getAttribute(ATT_USER_SERVICE_REF);
+ String successHandlerRef = element.getAttribute(ATT_SUCCESS_HANDLER_REF);
String rememberMeServicesRef = element.getAttribute(ATT_SERVICES_REF);
String tokenValiditySeconds = element.getAttribute(ATT_TOKEN_VALIDITY);
Object source = pc.extractSource(element);
@@ -86,18 +88,24 @@ class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
services = new RootBeanDefinition(TokenBasedRememberMeServices.class);
}
+ String servicesName;
+
if (services != null) {
- if (userServiceSet) {
- services.getPropertyValues().addPropertyValue("userDetailsService", new RuntimeBeanReference(userServiceRef));
- }
+ RootBeanDefinition uds = new RootBeanDefinition();
+ uds.setFactoryBeanName(BeanIds.USER_DETAILS_SERVICE_FACTORY);
+ uds.setFactoryMethodName("cachingUserDetailsService");
+ uds.getConstructorArgumentValues().addGenericArgumentValue(userServiceRef);
- if ("true".equals(element.getAttribute(ATT_SECURE_COOKIE))) {
- services.getPropertyValues().addPropertyValue("useSecureCookie", true);
+ services.getPropertyValues().addPropertyValue("userDetailsService", uds);
+
+ String useSecureCookie = element.getAttribute(ATT_SECURE_COOKIE);
+ if (StringUtils.hasText(useSecureCookie)) {
+ services.getPropertyValues().addPropertyValue("useSecureCookie", Boolean.valueOf(useSecureCookie));
}
if (tokenValiditySet) {
- Integer tokenValidity = new Integer(tokenValiditySeconds);
- if (tokenValidity.intValue() < 0 && isPersistent) {
+ int tokenValidity = Integer.parseInt(tokenValiditySeconds);
+ if (tokenValidity < 0 && isPersistent) {
pc.getReaderContext().error(ATT_TOKEN_VALIDITY + " cannot be negative if using" +
" a persistent remember-me token repository", source);
}
@@ -115,17 +123,18 @@ class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
pc.getRegistry().registerAlias(servicesName, element.getAttribute(ATT_SERVICES_ALIAS));
}
- BeanDefinition filter = createFilter(pc, source);
- pc.popAndRegisterContainingComponent();
-
- return filter;
- }
-
- private BeanDefinition createFilter(ParserContext pc, Object source) {
BeanDefinitionBuilder filter = BeanDefinitionBuilder.rootBeanDefinition(RememberMeAuthenticationFilter.class);
filter.getRawBeanDefinition().setSource(source);
+
+ if (StringUtils.hasText(successHandlerRef)) {
+ filter.addPropertyReference("authenticationSuccessHandler", successHandlerRef);
+ }
+
filter.addPropertyReference("rememberMeServices", servicesName);
+ pc.popAndRegisterContainingComponent();
+
return filter.getBeanDefinition();
}
+
}
diff --git a/dist/spring-security-config/org/springframework/security/config/http/SecurityFilters.java b/dist/spring-security-config/org/springframework/security/config/http/SecurityFilters.java
index af9ea19..0e7568b 100644
--- a/dist/spring-security-config/org/springframework/security/config/http/SecurityFilters.java
+++ b/dist/spring-security-config/org/springframework/security/config/http/SecurityFilters.java
@@ -23,6 +23,7 @@ enum SecurityFilters {
BASIC_AUTH_FILTER,
REQUEST_CACHE_FILTER,
SERVLET_API_SUPPORT_FILTER,
+ JAAS_API_SUPPORT_FILTER,
REMEMBER_ME_FILTER,
ANONYMOUS_FILTER,
SESSION_MANAGEMENT_FILTER,
diff --git a/dist/spring-security-config/org/springframework/security/config/http/UserDetailsServiceInjectionBeanPostProcessor.java b/dist/spring-security-config/org/springframework/security/config/http/UserDetailsServiceInjectionBeanPostProcessor.java
deleted file mode 100644
index 2502c6a..0000000
--- a/dist/spring-security-config/org/springframework/security/config/http/UserDetailsServiceInjectionBeanPostProcessor.java
+++ /dev/null
@@ -1,187 +0,0 @@
-package org.springframework.security.config.http;
-
-import java.util.Map;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.beans.BeanWrapperImpl;
-import org.springframework.beans.BeansException;
-import org.springframework.beans.PropertyValue;
-import org.springframework.beans.factory.BeanFactory;
-import org.springframework.beans.factory.BeanFactoryAware;
-import org.springframework.beans.factory.HierarchicalBeanFactory;
-import org.springframework.beans.factory.ListableBeanFactory;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.config.BeanPostProcessor;
-import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
-import org.springframework.beans.factory.config.RuntimeBeanReference;
-import org.springframework.beans.factory.support.RootBeanDefinition;
-import org.springframework.context.ApplicationContextException;
-import org.springframework.security.config.authentication.AbstractUserDetailsServiceBeanDefinitionParser;
-import org.springframework.security.config.authentication.CachingUserDetailsService;
-import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper;
-import org.springframework.security.core.userdetails.UserDetailsService;
-import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider;
-import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices;
-import org.springframework.util.Assert;
-
-/**
- * Registered by {@link HttpSecurityBeanDefinitionParser} to inject a UserDetailsService into
- * the X509Provider, RememberMeServices and OpenIDAuthenticationProvider instances created by
- * the namespace.
- *
- * @author Luke Taylor
- * @since 2.0.2
- */
-public class UserDetailsServiceInjectionBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {
- private final Log logger = LogFactory.getLog(getClass());
-
- private ConfigurableListableBeanFactory beanFactory;
- private final String x509ProviderId;
- private final String rememberMeServicesId;
- private final String openIDProviderId;
-
- public UserDetailsServiceInjectionBeanPostProcessor(String x509ProviderId, String rememberMeServicesId,
- String openIDProviderId) {
- this.x509ProviderId = x509ProviderId;
- this.rememberMeServicesId = rememberMeServicesId;
- this.openIDProviderId = openIDProviderId;
- }
-
- public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
- if(beanName == null) {
- return bean;
- }
- if (beanName.equals(x509ProviderId)) {
- injectUserDetailsServiceIntoX509Provider((PreAuthenticatedAuthenticationProvider) bean);
- } else if (beanName.equals(rememberMeServicesId)) {
- injectUserDetailsServiceIntoRememberMeServices(bean);
- } else if (beanName.equals(openIDProviderId)) {
- injectUserDetailsServiceIntoOpenIDProvider(bean);
- }
-
- return bean;
- }
-
- public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
- return bean;
- }
-
- private void injectUserDetailsServiceIntoRememberMeServices(Object rms) {
- if (!(rms instanceof AbstractRememberMeServices)) {
- logger.info("RememberMeServices is not an instance of AbstractRememberMeServices. UserDetailsService will" +
- " not be automatically injected.");
- return;
- }
-
- AbstractRememberMeServices services = (AbstractRememberMeServices) rms;
-
- BeanDefinition beanDefinition = beanFactory.getBeanDefinition(rememberMeServicesId);
- PropertyValue pv = beanDefinition.getPropertyValues().getPropertyValue("userDetailsService");
-
- if (pv == null) {
- // If it doesn't already have a UserDetailsService set, then set it.
- services.setUserDetailsService(getUserDetailsService());
- } else {
- // If already set, then attempt to locate a caching version of the injected UserDetailsService
- UserDetailsService cachingUserService = getCachingUserService(pv.getValue());
-
- if (cachingUserService != null) {
- services.setUserDetailsService(cachingUserService);
- }
- }
- }
-
- private void injectUserDetailsServiceIntoX509Provider(PreAuthenticatedAuthenticationProvider provider) {
- BeanDefinition beanDefinition = beanFactory.getBeanDefinition(x509ProviderId);
- PropertyValue pv = beanDefinition.getPropertyValues().getPropertyValue("preAuthenticatedUserDetailsService");
- UserDetailsByNameServiceWrapper wrapper = new UserDetailsByNameServiceWrapper();
-
- if (pv == null) {
- wrapper.setUserDetailsService(getUserDetailsService());
- provider.setPreAuthenticatedUserDetailsService(wrapper);
- } else {
- RootBeanDefinition preAuthUserService = (RootBeanDefinition) pv.getValue();
- Object userService =
- preAuthUserService.getPropertyValues().getPropertyValue("userDetailsService").getValue();
-
- UserDetailsService cachingUserService = getCachingUserService(userService);
-
- if (cachingUserService != null) {
- wrapper.setUserDetailsService(cachingUserService);
- provider.setPreAuthenticatedUserDetailsService(wrapper);
- }
- }
- }
-
- private void injectUserDetailsServiceIntoOpenIDProvider(Object bean) {
- BeanDefinition beanDefinition = beanFactory.getBeanDefinition(openIDProviderId);
- PropertyValue pv = beanDefinition.getPropertyValues().getPropertyValue("userDetailsService");
-
- if (pv == null) {
- BeanWrapperImpl beanWrapper = new BeanWrapperImpl(bean);
- beanWrapper.setPropertyValue("userDetailsService", getUserDetailsService());
- }
- }
-
- /**
- * Obtains a user details service for use in RememberMeServices etc. Will return a caching version
- * if available so should not be used for beans which need to separate the two.
- */
- UserDetailsService getUserDetailsService() {
- Map<String,?> beans = getBeansOfType(CachingUserDetailsService.class);
-
- if (beans.size() == 0) {
- beans = getBeansOfType(UserDetailsService.class);
- }
-
- if (beans.size() == 0) {
- throw new ApplicationContextException("No UserDetailsService registered.");
-
- } else if (beans.size() > 1) {
- throw new ApplicationContextException("More than one UserDetailsService registered. Please " +
- "use a specific Id reference in <remember-me/> <openid-login/> or <x509 /> elements.");
- }
-
- return (UserDetailsService) beans.values().toArray()[0];
- }
-
- private UserDetailsService getCachingUserService(Object userServiceRef) {
- Assert.isInstanceOf(RuntimeBeanReference.class, userServiceRef,
- "userDetailsService property value must be a RuntimeBeanReference");
-
- String id = ((RuntimeBeanReference)userServiceRef).getBeanName();
- // Overwrite with the caching version if available
- String cachingId = id + AbstractUserDetailsServiceBeanDefinitionParser.CACHING_SUFFIX;
-
- if (beanFactory.containsBeanDefinition(cachingId)) {
- return (UserDetailsService) beanFactory.getBean(cachingId);
- }
-
- return null;
- }
-
- private Map<String,?> getBeansOfType(Class<?> type) {
- Map<String,?> beans = beanFactory.getBeansOfType(type);
-
- // Check ancestor bean factories if they exist and the current one has none of the required type
- BeanFactory parent = beanFactory.getParentBeanFactory();
- while (parent != null && beans.size() == 0) {
- if (parent instanceof ListableBeanFactory) {
- beans = ((ListableBeanFactory)parent).getBeansOfType(type);
- }
- if (parent instanceof HierarchicalBeanFactory) {
- parent = ((HierarchicalBeanFactory)parent).getParentBeanFactory();
- } else {
- break;
- }
- }
-
- return beans;
- }
-
-
- public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
- this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
- }
-}
diff --git a/dist/spring-security-config/org/springframework/security/config/http/WebConfigUtils.java b/dist/spring-security-config/org/springframework/security/config/http/WebConfigUtils.java
index 95d8c95..746c5e4 100644
--- a/dist/spring-security-config/org/springframework/security/config/http/WebConfigUtils.java
+++ b/dist/spring-security-config/org/springframework/security/config/http/WebConfigUtils.java
@@ -15,8 +15,8 @@ abstract class WebConfigUtils {
public static int countNonEmpty(String[] objects) {
int nonNulls = 0;
- for (int i = 0; i < objects.length; i++) {
- if (StringUtils.hasText(objects[i])) {
+ for (String object : objects) {
+ if (StringUtils.hasText(object)) {
nonNulls++;
}
}
diff --git a/dist/spring-security-config/org/springframework/security/config/ldap/ContextSourceSettingPostProcessor.java b/dist/spring-security-config/org/springframework/security/config/ldap/ContextSourceSettingPostProcessor.java
index 3fa3c5b..f867d7b 100644
--- a/dist/spring-security-config/org/springframework/security/config/ldap/ContextSourceSettingPostProcessor.java
+++ b/dist/spring-security-config/org/springframework/security/config/ldap/ContextSourceSettingPostProcessor.java
@@ -36,12 +36,12 @@ class ContextSourceSettingPostProcessor implements BeanFactoryPostProcessor, Ord
"jar file in your application", e);
}
- String[] sources = bf.getBeanNamesForType(contextSourceClass);
-
+ String[] sources = bf.getBeanNamesForType(contextSourceClass, false, false);
if (sources.length == 0) {
throw new ApplicationContextException("No BaseLdapPathContextSource instances found. Have you " +
- "added an <" + Elements.LDAP_SERVER + " /> element to your application context?");
+ "added an <" + Elements.LDAP_SERVER + " /> element to your application context? If you have " +
+ "declared an explicit bean, do not use lazy-init");
}
if (!bf.containsBean(BeanIds.CONTEXT_SOURCE) && defaultNameRequired) {
diff --git a/dist/spring-security-config/org/springframework/security/config/ldap/LdapProviderBeanDefinitionParser.java b/dist/spring-security-config/org/springframework/security/config/ldap/LdapProviderBeanDefinitionParser.java
index 3a6b93d..f1b5b9e 100644
--- a/dist/spring-security-config/org/springframework/security/config/ldap/LdapProviderBeanDefinitionParser.java
+++ b/dist/spring-security-config/org/springframework/security/config/ldap/LdapProviderBeanDefinitionParser.java
@@ -20,7 +20,7 @@ import org.w3c.dom.Element;
* @since 2.0
*/
public class LdapProviderBeanDefinitionParser implements BeanDefinitionParser {
- private Log logger = LogFactory.getLog(getClass());
+ private final Log logger = LogFactory.getLog(getClass());
private static final String ATT_USER_DN_PATTERN = "user-dn-pattern";
private static final String ATT_USER_PASSWORD = "password-attribute";
@@ -81,7 +81,7 @@ public class LdapProviderBeanDefinitionParser implements BeanDefinitionParser {
parserContext.getReaderContext().warning("Salt source information isn't valid when used with LDAP",
passwordEncoderElement);
}
- } else if (StringUtils.hasText(hash)) {;
+ } else if (StringUtils.hasText(hash)) {
authenticatorBuilder.addPropertyValue("passwordEncoder",
PasswordEncoderParser.createPasswordEncoderBeanDefinition(hash, false));
}
diff --git a/dist/spring-security-config/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java b/dist/spring-security-config/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java
index 11c4127..2ee269d 100644
--- a/dist/spring-security-config/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java
+++ b/dist/spring-security-config/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java
@@ -123,7 +123,7 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser {
apacheContainer.getConstructorArgumentValues().addGenericArgumentValue(ldifs);
apacheContainer.getPropertyValues().addPropertyValue("port", port);
- logger.info("Embedded LDAP server bean created for URL: " + url);
+ logger.info("Embedded LDAP server bean definition created for URL: " + url);
if (parserContext.getRegistry().containsBeanDefinition(BeanIds.EMBEDDED_APACHE_DS)) {
parserContext.getReaderContext().error("Only one embedded server bean is allowed per application context",
diff --git a/dist/spring-security-config/org/springframework/security/config/method/GlobalMethodSecurityBeanDefinitionParser.java b/dist/spring-security-config/org/springframework/security/config/method/GlobalMethodSecurityBeanDefinitionParser.java
index b2f614c..88e5547 100644
--- a/dist/spring-security-config/org/springframework/security/config/method/GlobalMethodSecurityBeanDefinitionParser.java
+++ b/dist/spring-security-config/org/springframework/security/config/method/GlobalMethodSecurityBeanDefinitionParser.java
@@ -69,6 +69,7 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
private final Log logger = LogFactory.getLog(getClass());
+ private static final String ATT_AUTHENTICATION_MANAGER_REF = "authentication-manager-ref";
private static final String ATT_ACCESS = "access";
private static final String ATT_EXPRESSION = "expression";
private static final String ATT_ACCESS_MGR = "access-decision-manager-ref";
@@ -79,6 +80,7 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
private static final String ATT_REF = "ref";
private static final String ATT_MODE = "mode";
private static final String ATT_ADVICE_ORDER = "order";
+ private static final String ATT_META_DATA_SOURCE_REF = "metadata-source-ref";
public BeanDefinition parse(Element element, ParserContext pc) {
CompositeComponentDefinition compositeDef =
@@ -97,6 +99,13 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
BeanDefinition preInvocationVoter = null;
ManagedList<BeanMetadataElement> afterInvocationProviders = new ManagedList<BeanMetadataElement>();
+ // Check for an external SecurityMetadataSource, which takes priority over other sources
+ String metaDataSourceId = element.getAttribute(ATT_META_DATA_SOURCE_REF);
+
+ if (StringUtils.hasText(metaDataSourceId)) {
+ delegates.add(new RuntimeBeanReference(metaDataSourceId));
+ }
+
if (prePostAnnotationsEnabled) {
Element prePostElt = DomUtils.getChildElementByTagName(element, INVOCATION_HANDLING);
Element expressionHandlerElt = DomUtils.getChildElementByTagName(element, EXPRESSION_HANDLER);
@@ -196,8 +205,10 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
accessManagerId = registerAccessManager(pc, jsr250Enabled, preInvocationVoter);
}
+ String authMgrRef = element.getAttribute(ATT_AUTHENTICATION_MANAGER_REF);
+
String runAsManagerId = element.getAttribute(ATT_RUN_AS_MGR);
- BeanReference interceptor = registerMethodSecurityInterceptor(pc, accessManagerId, runAsManagerId,
+ BeanReference interceptor = registerMethodSecurityInterceptor(pc, authMgrRef, accessManagerId, runAsManagerId,
metadataSource, afterInvocationProviders, source, useAspectJ);
if (useAspectJ) {
@@ -239,7 +250,7 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
voters.add(new RootBeanDefinition(Jsr250Voter.class));
}
- accessMgrBuilder.addPropertyValue("decisionVoters", voters);
+ accessMgrBuilder.addConstructorArgValue(voters);
BeanDefinition accessManager = accessMgrBuilder.getBeanDefinition();
String id = pc.getReaderContext().generateBeanName(accessManager);
@@ -252,7 +263,7 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
private BeanReference registerDelegatingMethodSecurityMetadataSource(ParserContext pc, ManagedList delegates, Object source) {
RootBeanDefinition delegatingMethodSecurityMetadataSource = new RootBeanDefinition(DelegatingMethodSecurityMetadataSource.class);
delegatingMethodSecurityMetadataSource.setSource(source);
- delegatingMethodSecurityMetadataSource.getPropertyValues().addPropertyValue("methodSecurityMetadataSources", delegates);
+ delegatingMethodSecurityMetadataSource.getConstructorArgumentValues().addGenericArgumentValue(delegates);
String id = pc.getReaderContext().generateBeanName(delegatingMethodSecurityMetadataSource);
pc.registerBeanComponent(new BeanComponentDefinition(delegatingMethodSecurityMetadataSource, id));
@@ -299,7 +310,7 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
return pointcutMap;
}
- private BeanReference registerMethodSecurityInterceptor(ParserContext pc, String accessManagerId,
+ private BeanReference registerMethodSecurityInterceptor(ParserContext pc, String authMgrRef, String accessManagerId,
String runAsManagerId, BeanReference metadataSource,
List<BeanMetadataElement> afterInvocationProviders, Object source, boolean useAspectJ) {
BeanDefinitionBuilder bldr =
@@ -307,7 +318,9 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
AspectJMethodSecurityInterceptor.class : MethodSecurityInterceptor.class);
bldr.getRawBeanDefinition().setSource(source);
bldr.addPropertyReference("accessDecisionManager", accessManagerId);
- bldr.addPropertyValue("authenticationManager", new RootBeanDefinition(AuthenticationManagerDelegator.class));
+ RootBeanDefinition authMgr = new RootBeanDefinition(AuthenticationManagerDelegator.class);
+ authMgr.getConstructorArgumentValues().addGenericArgumentValue(authMgrRef);
+ bldr.addPropertyValue("authenticationManager", authMgr);
bldr.addPropertyValue("securityMetadataSource", metadataSource);
if (StringUtils.hasText(runAsManagerId)) {
@@ -315,7 +328,7 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
}
if (!afterInvocationProviders.isEmpty()) {
- BeanDefinition afterInvocationManager = null;
+ BeanDefinition afterInvocationManager;
afterInvocationManager = new RootBeanDefinition(AfterInvocationProviderManager.class);
afterInvocationManager.getPropertyValues().addPropertyValue("providers", afterInvocationProviders);
bldr.addPropertyValue("afterInvocationManager", afterInvocationManager);
@@ -359,13 +372,18 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
private AuthenticationManager delegate;
private final Object delegateMonitor = new Object();
private BeanFactory beanFactory;
+ private final String authMgrBean;
+
+ AuthenticationManagerDelegator(String authMgrBean) {
+ this.authMgrBean = StringUtils.hasText(authMgrBean) ? authMgrBean : BeanIds.AUTHENTICATION_MANAGER;
+ }
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
synchronized(delegateMonitor) {
if (delegate == null) {
- Assert.state(beanFactory != null, "BeanFactory must be set to resolve " + BeanIds.AUTHENTICATION_MANAGER);
+ Assert.state(beanFactory != null, "BeanFactory must be set to resolve " + authMgrBean);
try {
- delegate = beanFactory.getBean(BeanIds.AUTHENTICATION_MANAGER, ProviderManager.class);
+ delegate = beanFactory.getBean(authMgrBean, ProviderManager.class);
} catch (NoSuchBeanDefinitionException e) {
if (BeanIds.AUTHENTICATION_MANAGER.equals(e.getBeanName())) {
throw new NoSuchBeanDefinitionException(BeanIds.AUTHENTICATION_MANAGER,
diff --git a/dist/spring-security-config/org/springframework/security/config/method/InterceptMethodsBeanDefinitionDecorator.java b/dist/spring-security-config/org/springframework/security/config/method/InterceptMethodsBeanDefinitionDecorator.java
index 2d95646..15f0325 100644
--- a/dist/spring-security-config/org/springframework/security/config/method/InterceptMethodsBeanDefinitionDecorator.java
+++ b/dist/spring-security-config/org/springframework/security/config/method/InterceptMethodsBeanDefinitionDecorator.java
@@ -1,9 +1,5 @@
package org.springframework.security.config.method;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
import org.springframework.aop.config.AbstractInterceptorDrivenBeanDefinitionDecorator;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
@@ -13,7 +9,6 @@ import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionDecorator;
import org.springframework.beans.factory.xml.ParserContext;
-import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor;
import org.springframework.security.access.method.MapBasedMethodSecurityMetadataSource;
@@ -24,13 +19,15 @@ import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
+import java.util.*;
+
/**
* @author Luke Taylor
* @author Ben Alex
*
*/
public class InterceptMethodsBeanDefinitionDecorator implements BeanDefinitionDecorator {
- private BeanDefinitionDecorator delegate = new InternalInterceptMethodsBeanDefinitionDecorator();
+ private final BeanDefinitionDecorator delegate = new InternalInterceptMethodsBeanDefinitionDecorator();
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) {
MethodConfigUtils.registerDefaultMethodAccessManagerIfNecessary(parserContext);
@@ -65,6 +62,7 @@ class InternalInterceptMethodsBeanDefinitionDecorator extends AbstractIntercepto
interceptor.addPropertyValue("authenticationManager", new RuntimeBeanReference(BeanIds.AUTHENTICATION_MANAGER));
// Lookup parent bean information
+
String parentBeanClass = ((Element) node.getParentNode()).getAttribute("class");
// Parse the included methods
diff --git a/dist/spring-security-config/org/springframework/security/config/method/ProtectPointcutPostProcessor.java b/dist/spring-security-config/org/springframework/security/config/method/ProtectPointcutPostProcessor.java
index 018454e..8fa3f1b 100644
--- a/dist/spring-security-config/org/springframework/security/config/method/ProtectPointcutPostProcessor.java
+++ b/dist/spring-security-config/org/springframework/security/config/method/ProtectPointcutPostProcessor.java
@@ -89,10 +89,10 @@ final class ProtectPointcutPostProcessor implements BeanPostProcessor {
}
// Check to see if any of those methods are compatible with our pointcut expressions
- for (int i = 0; i < methods.length; i++) {
+ for (Method method : methods) {
for (PointcutExpression expression : pointCutExpressions) {
// Try for the bean class directly
- if (attemptMatch(bean.getClass(), methods[i], expression, beanName)) {
+ if (attemptMatch(bean.getClass(), method, expression, beanName)) {
// We've found the first expression that matches this method, so move onto the next method now
break; // the "while" loop, not the "for" loop
}
diff --git a/dist/spring-security-config/org/springframework/security/config/spring-security-2.0.1.xsd b/dist/spring-security-config/org/springframework/security/config/spring-security-2.0.1.xsd
deleted file mode 100644
index 1d8830a..0000000
--- a/dist/spring-security-config/org/springframework/security/config/spring-security-2.0.1.xsd
+++ /dev/null
@@ -1,1335 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
- xmlns:security="http://www.springframework.org/schema/security" elementFormDefault="qualified"
- targetNamespace="http://www.springframework.org/schema/security">
- <xs:attributeGroup name="hash">
- <xs:attribute name="hash" use="required">
- <xs:annotation>
- <xs:documentation>Defines the hashing algorithm used on user passwords. We recommend
- strongly against using MD4, as it is a very weak hashing algorithm.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="plaintext"/>
- <xs:enumeration value="sha"/>
- <xs:enumeration value="md5"/>
- <xs:enumeration value="md4"/>
- <xs:enumeration value="{sha}"/>
- <xs:enumeration value="{ssha}"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="base64">
- <xs:attribute name="base64" use="required">
- <xs:annotation>
- <xs:documentation>Whether a string should be base64 encoded</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="true"/>
- <xs:enumeration value="false"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="path-type">
- <xs:attribute name="path-type" use="required">
- <xs:annotation>
- <xs:documentation>Defines the type of pattern used to specify URL paths (either JDK
- 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if
- unspecified.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="ant"/>
- <xs:enumeration value="regex"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="port">
- <xs:attribute name="port" use="required" type="xs:integer">
- <xs:annotation>
- <xs:documentation>Specifies an IP port number. Used to configure an embedded LDAP server,
- for example.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="url">
- <xs:attribute name="url" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Specifies a URL.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="id">
- <xs:attribute name="id" use="required" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
- context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="ref">
- <xs:attribute name="ref" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="cache-ref">
- <xs:attribute name="cache-ref" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Defines a reference to a cache for use with a
- UserDetailsService.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-service-ref">
- <xs:attribute name="user-service-ref" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean)
- Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="password-encoder.attlist">
- <xs:attribute name="ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="hash">
- <xs:annotation>
- <xs:documentation>Defines the hashing algorithm used on user passwords. We recommend
- strongly against using MD4, as it is a very weak hashing algorithm.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="plaintext"/>
- <xs:enumeration value="sha"/>
- <xs:enumeration value="md5"/>
- <xs:enumeration value="md4"/>
- <xs:enumeration value="{sha}"/>
- <xs:enumeration value="{ssha}"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="base64">
- <xs:annotation>
- <xs:documentation>Whether a string should be base64 encoded</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="true"/>
- <xs:enumeration value="false"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-property">
- <xs:attribute name="user-property" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>A property of the UserDetails object which will be used as salt by a
- password encoder. Typically something like "username" might be used. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="system-wide">
- <xs:attribute name="system-wide" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>A single value that will be used as the salt for a password encoder.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:simpleType name="boolean">
- <xs:restriction base="xs:token">
- <xs:enumeration value="true"/>
- <xs:enumeration value="false"/>
- </xs:restriction>
- </xs:simpleType>
- <xs:attributeGroup name="role-prefix">
- <xs:attribute name="role-prefix" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>A non-empty string prefix that will be added to role strings loaded from
- persistent storage (e.g. "ROLE_").</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="ldap-server">
- <xs:annotation>
- <xs:documentation>Defines an LDAP server location or starts an embedded server. The url
- indicates the location of a remote server. If no url is given, an embedded server will be
- started, listening on the supplied port number. The port is optional and defaults to 33389.
- A Spring LDAP ContextSource bean will be registered for the server with the id supplied.
- </xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:ldap-server.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="ldap-server.attlist">
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
- context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="url" type="xs:string">
- <xs:annotation>
- <xs:documentation>Specifies a URL.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="port" type="xs:integer">
- <xs:annotation>
- <xs:documentation>Specifies an IP port number. Used to configure an embedded LDAP server,
- for example.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="manager-dn" type="xs:string">
- <xs:annotation>
- <xs:documentation>Username (DN) of the "manager" user identity which will be used to
- authenticate to a (non-embedded) LDAP server. If omitted, anonymous access will be used.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="manager-password" type="xs:string"/>
- <xs:attribute name="ldif" type="xs:string">
- <xs:annotation>
- <xs:documentation>Explicitly specifies an ldif file resource to load into an embedded LDAP
- server</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="root" type="xs:string">
- <xs:annotation>
- <xs:documentation>Optional root suffix for the embedded LDAP server. Default is
- "dc=springframework,dc=org"</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="ldap-server-ref-attribute">
- <xs:attribute name="server-ref" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>The optional server to use. If omitted, and a default LDAP server is
- registered (using <ldap-server> with no Id), that server will be used.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="group-search-filter-attribute">
- <xs:attribute name="group-search-filter" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Group search filter. Defaults to (uniqueMember={0}). The substituted
- parameter is the DN of the user.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="group-search-base-attribute">
- <xs:attribute name="group-search-base" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Search base for group membership searches. Defaults to
- "ou=groups".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-search-filter-attribute">
- <xs:attribute name="user-search-filter" use="required" type="xs:string"/>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-search-base-attribute">
- <xs:attribute name="user-search-base" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Search base for user searches. Defaults to "".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="group-role-attribute-attribute">
- <xs:attribute name="group-role-attribute" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>The LDAP attribute name which contains the role name which will be used
- within Spring Security. Defaults to "cn".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-details-class-attribute">
- <xs:attribute name="user-details-class" use="required">
- <xs:annotation>
- <xs:documentation>Allows the objectClass of the user entry to be specified. If set, the
- framework will attempt to load standard attributes for the defined class into the returned
- UserDetails object</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="person"/>
- <xs:enumeration value="inetOrgPerson"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="ldap-user-service" substitutionGroup="security:any-user-service">
- <xs:complexType>
- <xs:attributeGroup ref="security:ldap-us.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="ldap-us.attlist">
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
- context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="server-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>The optional server to use. If omitted, and a default LDAP server is
- registered (using <ldap-server> with no Id), that server will be used.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-search-filter" type="xs:string"/>
- <xs:attribute name="user-search-base" type="xs:string">
- <xs:annotation>
- <xs:documentation>Search base for user searches. Defaults to "".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-search-filter" type="xs:string">
- <xs:annotation>
- <xs:documentation>Group search filter. Defaults to (uniqueMember={0}). The substituted
- parameter is the DN of the user.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-search-base" type="xs:string">
- <xs:annotation>
- <xs:documentation>Search base for group membership searches. Defaults to
- "ou=groups".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-role-attribute" type="xs:string">
- <xs:annotation>
- <xs:documentation>The LDAP attribute name which contains the role name which will be used
- within Spring Security. Defaults to "cn".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="cache-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Defines a reference to a cache for use with a
- UserDetailsService.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="role-prefix" type="xs:string">
- <xs:annotation>
- <xs:documentation>A non-empty string prefix that will be added to role strings loaded from
- persistent storage (e.g. "ROLE_").</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-details-class">
- <xs:annotation>
- <xs:documentation>Allows the objectClass of the user entry to be specified. If set, the
- framework will attempt to load standard attributes for the defined class into the returned
- UserDetails object</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="person"/>
- <xs:enumeration value="inetOrgPerson"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="ldap-authentication-provider">
- <xs:annotation>
- <xs:documentation>Sets up an ldap authentication provider</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="password-compare">
- <xs:annotation>
- <xs:documentation>Specifies that an LDAP provider should use an LDAP compare operation
- of the user's password to authenticate the user</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="password-encoder">
- <xs:annotation>
- <xs:documentation>element which defines a password encoding strategy. Used by an
- authentication provider to convert submitted passwords to hashed versions, for
- example.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="salt-source">
- <xs:complexType>
- <xs:attribute name="user-property" type="xs:string">
- <xs:annotation>
- <xs:documentation>A property of the UserDetails object which will be
- used as salt by a password encoder. Typically something like
- "username" might be used. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="system-wide" type="xs:string">
- <xs:annotation>
- <xs:documentation>A single value that will be used as the salt for a
- password encoder. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:password-encoder.attlist"/>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:password-compare.attlist"/>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:ldap-ap.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="ldap-ap.attlist">
- <xs:attribute name="server-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>The optional server to use. If omitted, and a default LDAP server is
- registered (using <ldap-server> with no Id), that server will be used.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-search-base" type="xs:string">
- <xs:annotation>
- <xs:documentation>Search base for user searches. Defaults to "".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-search-filter" type="xs:string"/>
- <xs:attribute name="group-search-base" type="xs:string">
- <xs:annotation>
- <xs:documentation>Search base for group membership searches. Defaults to
- "ou=groups".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-search-filter" type="xs:string">
- <xs:annotation>
- <xs:documentation>Group search filter. Defaults to (uniqueMember={0}). The substituted
- parameter is the DN of the user.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-role-attribute" type="xs:string">
- <xs:annotation>
- <xs:documentation>The LDAP attribute name which contains the role name which will be used
- within Spring Security. Defaults to "cn".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-dn-pattern" type="xs:string">
- <xs:annotation>
- <xs:documentation>A specific pattern used to build the user's DN, for example
- "uid={0},ou=people". The key "{0}" must be present and will be substituted with the
- username.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="role-prefix" type="xs:string">
- <xs:annotation>
- <xs:documentation>A non-empty string prefix that will be added to role strings loaded from
- persistent storage (e.g. "ROLE_").</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-details-class">
- <xs:annotation>
- <xs:documentation>Allows the objectClass of the user entry to be specified. If set, the
- framework will attempt to load standard attributes for the defined class into the returned
- UserDetails object</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="person"/>
- <xs:enumeration value="inetOrgPerson"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="password-compare.attlist">
- <xs:attribute name="password-attribute" type="xs:string">
- <xs:annotation>
- <xs:documentation>The attribute in the directory which contains the user password. Defaults
- to "userPassword".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="hash">
- <xs:annotation>
- <xs:documentation>Defines the hashing algorithm used on user passwords. We recommend
- strongly against using MD4, as it is a very weak hashing algorithm.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="plaintext"/>
- <xs:enumeration value="sha"/>
- <xs:enumeration value="md5"/>
- <xs:enumeration value="md4"/>
- <xs:enumeration value="{sha}"/>
- <xs:enumeration value="{ssha}"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="intercept-methods">
- <xs:annotation>
- <xs:documentation>Can be used inside a bean definition to add a security interceptor to the
- bean and set up access configuration attributes for the bean's methods</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="security:protect"/>
- </xs:sequence>
- <xs:attributeGroup ref="security:intercept-methods.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="intercept-methods.attlist">
- <xs:attribute name="access-decision-manager-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Optional AccessDecisionManager bean ID to be used by the created method
- security interceptor.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="protect">
- <xs:annotation>
- <xs:documentation>Defines a protected method and the access control configuration attributes
- that apply to it. We strongly advise you NOT to mix "protect" declarations with any services
- provided "global-method-security".</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:protect.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="protect.attlist">
- <xs:attribute name="method" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>A method name</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Access configuration attributes list that applies to the method, e.g.
- "ROLE_A,ROLE_B".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="global-method-security">
- <xs:annotation>
- <xs:documentation>Provides method security for all beans registered in the Spring application
- context. Specifically, beans will be scanned for Spring Security annotations and/or matches
- with the ordered list of "protect-pointcut" sub-elements. Where there is a match, the beans
- will automatically be proxied and security authorization applied to the methods accordingly.
- If you use and enable all three sources of method security metadata (ie "protect-pointcut"
- declarations, @Secured and also JSR 250 security annotations), the metadata sources will be
- queried in that order. In practical terms, this enables you to use XML to override method
- security metadata expressed by way of @Secured annotations, with @Secured annotations
- overriding method security metadata expressed by JSR 250 annotations. It is perfectly
- acceptable to mix and match, with a given Java type using a combination of XML, @Secured and
- JSR 250 to express method security metadata (albeit on different
- methods).</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" name="protect-pointcut">
- <xs:annotation>
- <xs:documentation>Defines a protected pointcut and the access control configuration
- attributes that apply to it. Every bean registered in the Spring application context
- that provides a method that matches the pointcut will receive security
- authorization.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:protect-pointcut.attlist"/>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:global-method-security.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="global-method-security.attlist">
- <xs:attribute name="secured-annotations">
- <xs:annotation>
- <xs:documentation>Specifies whether the use of Spring Security's @Secured annotations should
- be enabled for this application context. Please ensure you have the
- spring-security-tiger-xxx.jar on the classpath. Defaults to "disabled".</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="disabled"/>
- <xs:enumeration value="enabled"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="jsr250-annotations">
- <xs:annotation>
- <xs:documentation>Specifies whether JSR-250 style attributes are to be used (for example
- "RolesAllowed"). This will require the javax.annotation.security classes on the classpath.
- Defaults to "disabled".</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="disabled"/>
- <xs:enumeration value="enabled"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="access-decision-manager-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Optional AccessDecisionManager bean ID to override the default used for
- method security.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="custom-after-invocation-provider">
- <xs:complexType/>
- </xs:element>
- <xs:attributeGroup name="protect-pointcut.attlist">
- <xs:attribute name="expression" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>An AspectJ expression, including the 'execution' keyword. For example,
- 'execution(int com.foo.TargetObject.countLength(String))' (without the
- quotes).</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Access configuration attributes list that applies to all methods matching
- the pointcut, e.g. "ROLE_A,ROLE_B"</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="http">
- <xs:annotation>
- <xs:documentation>Container element for HTTP security configuration</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element name="intercept-url">
- <xs:annotation>
- <xs:documentation>Specifies the access attributes and/or filter list for a particular
- set of URLs.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:intercept-url.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="form-login">
- <xs:annotation>
- <xs:documentation>Sets up a form login configuration for authentication with a username
- and password</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:form-login.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:element ref="security:openid-login"/>
- <xs:element name="x509">
- <xs:annotation>
- <xs:documentation>Adds support for X.509 client authentication.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:x509.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="http-basic">
- <xs:annotation>
- <xs:documentation>Adds support for basic authentication (this is an element to permit
- future expansion, such as supporting an "ignoreFailure" attribute)</xs:documentation>
- </xs:annotation>
- <xs:complexType/>
- </xs:element>
- <xs:element name="logout">
- <xs:annotation>
- <xs:documentation>Incorporates a logout processing filter. Most web applications require
- a logout filter, although you may not require one if you write a controller to
- provider similar logic.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:logout.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="concurrent-session-control">
- <xs:annotation>
- <xs:documentation>Adds support for concurrent session control, allowing limits to be
- placed on the number of sessions a user can have.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:concurrent-sessions.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="remember-me">
- <xs:complexType>
- <xs:attributeGroup ref="security:remember-me.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="anonymous">
- <xs:annotation>
- <xs:documentation>Adds support for automatically granting all anonymous web requests a
- particular principal identity and a corresponding granted
- authority.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:anonymous.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="port-mappings">
- <xs:annotation>
- <xs:documentation>Defines the list of mappings between http and https ports for use in
- redirects</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="security:port-mapping"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- </xs:choice>
- <xs:attributeGroup ref="security:http.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="http.attlist">
- <xs:attribute name="auto-config" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Automatically registers a login form, BASIC authentication, anonymous
- authentication, logout services, remember-me and servlet-api-integration. If set to
- "true", all of these capabilities are added (although you can still customize the
- configuration of each by providing the respective element). If unspecified, defaults to
- "false".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="create-session">
- <xs:annotation>
- <xs:documentation>Controls the eagerness with which an HTTP session is created. If not set,
- defaults to "ifRequired".</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="ifRequired"/>
- <xs:enumeration value="always"/>
- <xs:enumeration value="never"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="path-type">
- <xs:annotation>
- <xs:documentation>Defines the type of pattern used to specify URL paths (either JDK
- 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if
- unspecified.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="ant"/>
- <xs:enumeration value="regex"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="lowercase-comparisons" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Whether test URLs should be converted to lower case prior to comparing
- with defined path patterns. If unspecified, defaults to "true".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="servlet-api-provision" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Provides versions of HttpServletRequest security methods such as
- isUserInRole() and getPrincipal() which are implemented by accessing the Spring
- SecurityContext. Defaults to "true".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access-decision-manager-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Optional attribute specifying the ID of the AccessDecisionManager
- implementation which should be used for authorizing HTTP requests.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="realm" type="xs:string">
- <xs:annotation>
- <xs:documentation>Optional attribute specifying the realm name that will be used for all
- authentication features that require a realm name (eg BASIC and Digest authentication). If
- unspecified, defaults to "Spring Security Application".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="session-fixation-protection">
- <xs:annotation>
- <xs:documentation>Indicates whether an existing session should be invalidated when a user
- authenticates and a new session started. If set to "none" no change will be made.
- "newSession" will create a new empty session. "migrateSession" will create a new session
- and copy the session attributes to the new session. Defaults to
- "migrateSession".</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="none"/>
- <xs:enumeration value="newSession"/>
- <xs:enumeration value="migrateSession"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="entry-point-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Allows a customized AuthenticationEntryPoint to be
- used.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="once-per-request" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Corresponds to the observeOncePerRequest property of
- FilterSecurityInterceptor. Defaults to "true"</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access-denied-page" type="xs:string">
- <xs:annotation>
- <xs:documentation>Allows the access denied page to be set (the user will be redirected here
- if an AccessDeniedException is raised).</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="intercept-url.attlist">
- <xs:attribute name="pattern" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>The pattern which defines the URL path. The content will depend on the
- type set in the containing http element, so will default to ant path
- syntax.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access" type="xs:string">
- <xs:annotation>
- <xs:documentation>The access configuration attributes that apply for the configured
- path.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="method">
- <xs:annotation>
- <xs:documentation>The HTTP Method for which the access configuration attributes should
- apply. If not specified, the attributes will apply to any method.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="GET"/>
- <xs:enumeration value="DELETE"/>
- <xs:enumeration value="HEAD"/>
- <xs:enumeration value="OPTIONS"/>
- <xs:enumeration value="POST"/>
- <xs:enumeration value="PUT"/>
- <xs:enumeration value="TRACE"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="filters">
- <xs:annotation>
- <xs:documentation>The filter list for the path. Currently can be set to "none" to remove a
- path from having any filters applied. The full filter stack (consisting of all defined
- filters, will be applied to any other paths).</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="none"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="requires-channel">
- <xs:annotation>
- <xs:documentation>Used to specify that a URL must be accessed over http or
- https</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="http"/>
- <xs:enumeration value="https"/>
- <xs:enumeration value="any"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="logout.attlist">
- <xs:attribute name="logout-url" type="xs:string">
- <xs:annotation>
- <xs:documentation>Specifies the URL that will cause a logout. Spring Security will
- initialize a filter that responds to this particular URL. Defaults to
- /j_spring_security_logout if unspecified.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="logout-success-url" type="xs:string">
- <xs:annotation>
- <xs:documentation>Specifies the URL to display once the user has logged out. If not
- specified, defaults to /.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="invalidate-session" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Specifies whether a logout also causes HttpSession invalidation, which is
- generally desirable. If unspecified, defaults to true.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="form-login.attlist">
- <xs:attribute name="login-processing-url" type="xs:string">
- <xs:annotation>
- <xs:documentation>The URL that the login form is posted to. If unspecified, it defaults to
- /j_spring_security_check.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="default-target-url" type="xs:string">
- <xs:annotation>
- <xs:documentation>The URL that will be redirected to after successful authentication, if the
- user's previous action could not be resumed. This generally happens if the user visits a
- login page without having first requested a secured operation that triggers
- authentication. If unspecified, defaults to the root of the
- application.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="always-use-default-target" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Whether the user should always be redirected to the default-target-url
- after login. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="login-page" type="xs:string">
- <xs:annotation>
- <xs:documentation>The URL for the login page. If no login URL is specified, Spring Security
- will automatically create a login URL at /spring_security_login and a corresponding filter
- to render that login URL when requested.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="authentication-failure-url" type="xs:string">
- <xs:annotation>
- <xs:documentation>The URL for the login failure page. If no login failure URL is specified,
- Spring Security will automatically create a failure login URL at
- /spring_security_login?login_error and a corresponding filter to render that login failure
- URL when requested.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="openid-login">
- <xs:annotation>
- <xs:documentation>Sets up form login for authentication with an Open ID
- identity</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:form-login.attlist"/>
- <xs:attribute name="user-service-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean)
- Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="filter-chain-map">
- <xs:annotation>
- <xs:documentation>Used to explicitly configure a FilterChainProxy instance with a
- FilterChainMap</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" name="filter-chain">
- <xs:annotation>
- <xs:documentation>Used within filter-chain-map to define a specific URL pattern and the
- list of filters which apply to the URLs matching that pattern. When multiple
- filter-chain elements are used within a filter-chain-map element, the most specific
- patterns must be placed at the top of the list, with most general ones at the
- bottom.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:filter-chain.attlist"/>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:filter-chain-map.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="filter-chain-map.attlist">
- <xs:attributeGroup ref="security:path-type"/>
- </xs:attributeGroup>
- <xs:attributeGroup name="filter-chain.attlist">
- <xs:attribute name="pattern" use="required" type="xs:string"/>
- <xs:attribute name="filters" use="required" type="xs:string"/>
- </xs:attributeGroup>
- <xs:element name="filter-invocation-definition-source">
- <xs:annotation>
- <xs:documentation>Used to explicitly configure a FilterInvocationDefinitionSource bean for use
- with a FilterSecurityInterceptor. Usually only needed if you are configuring a
- FilterChainProxy explicitly, rather than using the <http> element. The
- intercept-url elements used should only contain pattern, method and access attributes. Any
- others will result in a configuration error. </xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" name="intercept-url">
- <xs:annotation>
- <xs:documentation>Specifies the access attributes and/or filter list for a particular
- set of URLs.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:intercept-url.attlist"/>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:fids.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="fids.attlist">
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
- context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="lowercase-comparisons" type="security:boolean">
- <xs:annotation>
- <xs:documentation>as for http element</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="path-type">
- <xs:annotation>
- <xs:documentation>Defines the type of pattern used to specify URL paths (either JDK
- 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if
- unspecified.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="ant"/>
- <xs:enumeration value="regex"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="concurrent-sessions.attlist">
- <xs:attribute name="max-sessions" type="xs:positiveInteger"/>
- <xs:attribute name="expired-url" type="xs:string"/>
- <xs:attribute name="exception-if-maximum-exceeded" type="security:boolean"/>
- <xs:attribute name="session-registry-alias" type="xs:string">
- <xs:annotation>
- <xs:documentation>Allows you to define an alias for the SessionRegistry bean in order to
- access it in your own configuration</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="remember-me.attlist">
- <xs:attribute name="key" type="xs:string"/>
- <xs:attribute name="token-repository-ref" type="xs:string"/>
- <xs:attribute name="data-source-ref" type="xs:string"/>
- <xs:attribute name="user-service-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean)
- Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="anonymous.attlist">
- <xs:attribute name="key" type="xs:string">
- <xs:annotation>
- <xs:documentation>The key shared between the provider and filter. This generally does not
- need to be set. If unset, it will default to "doesNotMatter".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="username" type="xs:string">
- <xs:annotation>
- <xs:documentation>The username that should be assigned to the anonymous request. This allows
- the principal to be identified, which may be important for logging and auditing. if unset,
- defaults to "anonymousUser".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="granted-authority" type="xs:string">
- <xs:annotation>
- <xs:documentation>The granted authority that should be assigned to the anonymous request.
- Commonly this is used to assign the anonymous request particular roles, which can
- subsequently be used in authorization decisions. If unset, defaults to
- "ROLE_ANONYMOUS".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="port-mapping">
- <xs:complexType>
- <xs:attributeGroup ref="security:http-port"/>
- <xs:attributeGroup ref="security:https-port"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="http-port">
- <xs:attribute name="http" use="required" type="xs:integer"/>
- </xs:attributeGroup>
- <xs:attributeGroup name="https-port">
- <xs:attribute name="https" use="required" type="xs:integer"/>
- </xs:attributeGroup>
- <xs:attributeGroup name="x509.attlist">
- <xs:attribute name="subject-principal-regex" type="xs:string">
- <xs:annotation>
- <xs:documentation>The regular expression used to obtain the username from the certificate's
- subject. Defaults to matching on the common name using the pattern
- "CN=(.*?),".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-service-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean)
- Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="authentication-manager">
- <xs:annotation>
- <xs:documentation>If you are using namespace configuration with Spring Security, an
- AuthenticationManager will automatically be registered. This element simple allows you to
- define an alias to allow you to reference the authentication-manager in your own beans.
- </xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:authman.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="authman.attlist">
- <xs:annotation>
- <xs:documentation>The alias you wish to use for the AuthenticationManager
- bean</xs:documentation>
- </xs:annotation>
- <xs:attribute name="alias" use="required" type="xs:ID"/>
- </xs:attributeGroup>
- <xs:element name="authentication-provider">
- <xs:annotation>
- <xs:documentation>Indicates that the contained user-service should be used as an
- authentication source. </xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="security:any-user-service"/>
- <xs:element name="password-encoder">
- <xs:annotation>
- <xs:documentation>element which defines a password encoding strategy. Used by an
- authentication provider to convert submitted passwords to hashed versions, for
- example.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="salt-source">
- <xs:complexType>
- <xs:attribute name="user-property" type="xs:string">
- <xs:annotation>
- <xs:documentation>A property of the UserDetails object which will be used as
- salt by a password encoder. Typically something like "username" might be
- used. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="system-wide" type="xs:string">
- <xs:annotation>
- <xs:documentation>A single value that will be used as the salt for a password
- encoder. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:password-encoder.attlist"/>
- </xs:complexType>
- </xs:element>
- </xs:choice>
- <xs:attributeGroup ref="security:ap.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="ap.attlist">
- <xs:attribute name="user-service-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean)
- Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="custom-authentication-provider">
- <xs:complexType/>
- </xs:element>
- <xs:element name="user-service" substitutionGroup="security:any-user-service">
- <xs:annotation>
- <xs:documentation>Creates an in-memory UserDetailsService from a properties file or a list of
- "user" child elements.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="security:user"/>
- </xs:sequence>
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
- context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attributeGroup ref="security:properties-file"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="properties-file">
- <xs:attribute name="properties" type="xs:string"/>
- </xs:attributeGroup>
- <xs:element name="user">
- <xs:annotation>
- <xs:documentation>Represents a user in the application.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:user.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="user.attlist">
- <xs:attribute name="name" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>The username assigned to the user.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="password" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>The password assigned to the user. This may be hashed if the corresponding
- authentication provider supports hashing (remember to set the "hash" attribute of the
- "user-service" element).</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="authorities" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>One of more authorities granted to the user. Separate authorities with a
- comma (but no space). For example, "ROLE_USER,ROLE_ADMINISTRATOR"</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="locked" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Can be set to "true" to mark an account as locked and
- unusable.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="disabled" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Can be set to "true" to mark an account as disabled and
- unusable.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="jdbc-user-service" substitutionGroup="security:any-user-service">
- <xs:annotation>
- <xs:documentation>Causes creation of a JDBC-based UserDetailsService.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
- context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attributeGroup ref="security:jdbc-user-service.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="jdbc-user-service.attlist">
- <xs:attribute name="data-source-ref" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>The bean ID of the DataSource which provides the required
- tables.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="cache-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Defines a reference to a cache for use with a
- UserDetailsService.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="users-by-username-query" type="xs:string">
- <xs:annotation>
- <xs:documentation>An SQL statement to query a username, password, and enabled status given a
- username</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="authorities-by-username-query" type="xs:string">
- <xs:annotation>
- <xs:documentation>An SQL statement to query for a user's granted authorities given a
- username.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-authorities-by-username-query" type="xs:string">
- <xs:annotation>
- <xs:documentation>An SQL statement to query user's group authorities given a
- username.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="role-prefix" type="xs:string">
- <xs:annotation>
- <xs:documentation>A non-empty string prefix that will be added to role strings loaded from
- persistent storage (e.g. "ROLE_").</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="any-user-service" abstract="true"/>
- <xs:group name="custom-filter">
- <xs:sequence>
- <xs:element minOccurs="0" ref="security:custom-filter"/>
- </xs:sequence>
- </xs:group>
- <xs:element name="custom-filter">
- <xs:annotation>
- <xs:documentation>Used to indicate that a filter bean declaration should be incorporated into
- the security filter chain. If neither the 'after' or 'before' options are supplied, then the
- filter must implement the Ordered interface directly. </xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attribute name="after" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The filter immediately after which the custom-filter should be placed in
- the chain. This feature will only be needed by advanced users who wish to mix their own
- filters into the security filter chain and have some knowledge of the standard Spring
- Security filters. The filter names map to specific Spring Security implementation
- filters. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="before" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The filter immediately before which the custom-filter should be placed
- in the chain</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="position" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The explicit position at which the custom-filter should be placed in the
- chain. Use if you are replacing a standard filter.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="after">
- <xs:attribute name="after" use="required" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The filter immediately after which the custom-filter should be placed in
- the chain. This feature will only be needed by advanced users who wish to mix their own
- filters into the security filter chain and have some knowledge of the standard Spring
- Security filters. The filter names map to specific Spring Security implementation filters.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="before">
- <xs:attribute name="before" use="required" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The filter immediately before which the custom-filter should be placed in
- the chain</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="position">
- <xs:attribute name="position" use="required" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The explicit position at which the custom-filter should be placed in the
- chain. Use if you are replacing a standard filter.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:simpleType name="named-security-filter">
- <xs:restriction base="xs:token">
- <xs:enumeration value="FIRST"/>
- <xs:enumeration value="CHANNEL_FILTER"/>
- <xs:enumeration value="CONCURRENT_SESSION_FILTER"/>
- <xs:enumeration value="SESSION_CONTEXT_INTEGRATION_FILTER"/>
- <xs:enumeration value="LOGOUT_FILTER"/>
- <xs:enumeration value="X509_FILTER"/>
- <xs:enumeration value="PRE_AUTH_FILTER"/>
- <xs:enumeration value="CAS_PROCESSING_FILTER"/>
- <xs:enumeration value="AUTHENTICATION_PROCESSING_FILTER"/>
- <xs:enumeration value="BASIC_PROCESSING_FILTER"/>
- <xs:enumeration value="SERVLET_API_SUPPORT_FILTER"/>
- <xs:enumeration value="REMEMBER_ME_FILTER"/>
- <xs:enumeration value="ANONYMOUS_FILTER"/>
- <xs:enumeration value="EXCEPTION_TRANSLATION_FILTER"/>
- <xs:enumeration value="NTLM_FILTER"/>
- <xs:enumeration value="FILTER_SECURITY_INTERCEPTOR"/>
- <xs:enumeration value="SWITCH_USER_FILTER"/>
- <xs:enumeration value="LAST"/>
- </xs:restriction>
- </xs:simpleType>
-</xs:schema>
diff --git a/dist/spring-security-config/org/springframework/security/config/spring-security-2.0.2.xsd b/dist/spring-security-config/org/springframework/security/config/spring-security-2.0.2.xsd
deleted file mode 100644
index c80145e..0000000
--- a/dist/spring-security-config/org/springframework/security/config/spring-security-2.0.2.xsd
+++ /dev/null
@@ -1,1422 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
- xmlns:security="http://www.springframework.org/schema/security" elementFormDefault="qualified"
- targetNamespace="http://www.springframework.org/schema/security">
- <xs:attributeGroup name="hash">
- <xs:attribute name="hash" use="required">
- <xs:annotation>
- <xs:documentation>Defines the hashing algorithm used on user passwords. We recommend
- strongly against using MD4, as it is a very weak hashing algorithm.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="plaintext"/>
- <xs:enumeration value="sha"/>
- <xs:enumeration value="sha-256"/>
- <xs:enumeration value="md5"/>
- <xs:enumeration value="md4"/>
- <xs:enumeration value="{sha}"/>
- <xs:enumeration value="{ssha}"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="base64">
- <xs:attribute name="base64" use="required">
- <xs:annotation>
- <xs:documentation>Whether a string should be base64 encoded</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="true"/>
- <xs:enumeration value="false"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="path-type">
- <xs:attribute name="path-type" use="required">
- <xs:annotation>
- <xs:documentation>Defines the type of pattern used to specify URL paths (either JDK
- 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if
- unspecified.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="ant"/>
- <xs:enumeration value="regex"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="port">
- <xs:attribute name="port" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Specifies an IP port number. Used to configure an embedded LDAP server,
- for example.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="url">
- <xs:attribute name="url" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Specifies a URL.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="id">
- <xs:attribute name="id" use="required" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
- context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="ref">
- <xs:attribute name="ref" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="cache-ref">
- <xs:attribute name="cache-ref" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Defines a reference to a cache for use with a
- UserDetailsService.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-service-ref">
- <xs:attribute name="user-service-ref" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean)
- Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="data-source-ref">
- <xs:attribute name="data-source-ref" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>A reference to a DataSource bean</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="password-encoder.attlist">
- <xs:attribute name="ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="hash">
- <xs:annotation>
- <xs:documentation>Defines the hashing algorithm used on user passwords. We recommend
- strongly against using MD4, as it is a very weak hashing algorithm.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="plaintext"/>
- <xs:enumeration value="sha"/>
- <xs:enumeration value="sha-256"/>
- <xs:enumeration value="md5"/>
- <xs:enumeration value="md4"/>
- <xs:enumeration value="{sha}"/>
- <xs:enumeration value="{ssha}"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="base64">
- <xs:annotation>
- <xs:documentation>Whether a string should be base64 encoded</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="true"/>
- <xs:enumeration value="false"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-property">
- <xs:attribute name="user-property" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>A property of the UserDetails object which will be used as salt by a
- password encoder. Typically something like "username" might be used. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="system-wide">
- <xs:attribute name="system-wide" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>A single value that will be used as the salt for a password encoder.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:simpleType name="boolean">
- <xs:restriction base="xs:token">
- <xs:enumeration value="true"/>
- <xs:enumeration value="false"/>
- </xs:restriction>
- </xs:simpleType>
- <xs:attributeGroup name="role-prefix">
- <xs:attribute name="role-prefix" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>A non-empty string prefix that will be added to role strings loaded from
- persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the
- default is non-empty.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="ldap-server">
- <xs:annotation>
- <xs:documentation>Defines an LDAP server location or starts an embedded server. The url
- indicates the location of a remote server. If no url is given, an embedded server will be
- started, listening on the supplied port number. The port is optional and defaults to 33389.
- A Spring LDAP ContextSource bean will be registered for the server with the id supplied.
- </xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:ldap-server.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="ldap-server.attlist">
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
- context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="url" type="xs:string">
- <xs:annotation>
- <xs:documentation>Specifies a URL.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="port" type="xs:string">
- <xs:annotation>
- <xs:documentation>Specifies an IP port number. Used to configure an embedded LDAP server,
- for example.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="manager-dn" type="xs:string">
- <xs:annotation>
- <xs:documentation>Username (DN) of the "manager" user identity which will be used to
- authenticate to a (non-embedded) LDAP server. If omitted, anonymous access will be used.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="manager-password" type="xs:string"/>
- <xs:attribute name="ldif" type="xs:string">
- <xs:annotation>
- <xs:documentation>Explicitly specifies an ldif file resource to load into an embedded LDAP
- server</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="root" type="xs:string">
- <xs:annotation>
- <xs:documentation>Optional root suffix for the embedded LDAP server. Default is
- "dc=springframework,dc=org"</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="ldap-server-ref-attribute">
- <xs:attribute name="server-ref" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>The optional server to use. If omitted, and a default LDAP server is
- registered (using <ldap-server> with no Id), that server will be used.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="group-search-filter-attribute">
- <xs:attribute name="group-search-filter" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Group search filter. Defaults to (uniqueMember={0}). The substituted
- parameter is the DN of the user.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="group-search-base-attribute">
- <xs:attribute name="group-search-base" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Search base for group membership searches. Defaults to
- "ou=groups".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-search-filter-attribute">
- <xs:attribute name="user-search-filter" use="required" type="xs:string"/>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-search-base-attribute">
- <xs:attribute name="user-search-base" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Search base for user searches. Defaults to "".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="group-role-attribute-attribute">
- <xs:attribute name="group-role-attribute" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>The LDAP attribute name which contains the role name which will be used
- within Spring Security. Defaults to "cn".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-details-class-attribute">
- <xs:attribute name="user-details-class" use="required">
- <xs:annotation>
- <xs:documentation>Allows the objectClass of the user entry to be specified. If set, the
- framework will attempt to load standard attributes for the defined class into the returned
- UserDetails object</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="person"/>
- <xs:enumeration value="inetOrgPerson"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="ldap-user-service" substitutionGroup="security:any-user-service">
- <xs:complexType>
- <xs:attributeGroup ref="security:ldap-us.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="ldap-us.attlist">
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
- context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="server-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>The optional server to use. If omitted, and a default LDAP server is
- registered (using <ldap-server> with no Id), that server will be used.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-search-filter" type="xs:string"/>
- <xs:attribute name="user-search-base" type="xs:string">
- <xs:annotation>
- <xs:documentation>Search base for user searches. Defaults to "".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-search-filter" type="xs:string">
- <xs:annotation>
- <xs:documentation>Group search filter. Defaults to (uniqueMember={0}). The substituted
- parameter is the DN of the user.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-search-base" type="xs:string">
- <xs:annotation>
- <xs:documentation>Search base for group membership searches. Defaults to
- "ou=groups".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-role-attribute" type="xs:string">
- <xs:annotation>
- <xs:documentation>The LDAP attribute name which contains the role name which will be used
- within Spring Security. Defaults to "cn".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="cache-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Defines a reference to a cache for use with a
- UserDetailsService.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="role-prefix" type="xs:string">
- <xs:annotation>
- <xs:documentation>A non-empty string prefix that will be added to role strings loaded from
- persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the
- default is non-empty.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-details-class">
- <xs:annotation>
- <xs:documentation>Allows the objectClass of the user entry to be specified. If set, the
- framework will attempt to load standard attributes for the defined class into the returned
- UserDetails object</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="person"/>
- <xs:enumeration value="inetOrgPerson"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="ldap-authentication-provider">
- <xs:annotation>
- <xs:documentation>Sets up an ldap authentication provider</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="password-compare">
- <xs:annotation>
- <xs:documentation>Specifies that an LDAP provider should use an LDAP compare operation
- of the user's password to authenticate the user</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="password-encoder">
- <xs:annotation>
- <xs:documentation>element which defines a password encoding strategy. Used by an
- authentication provider to convert submitted passwords to hashed versions, for
- example.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="salt-source">
- <xs:complexType>
- <xs:attribute name="user-property" type="xs:string">
- <xs:annotation>
- <xs:documentation>A property of the UserDetails object which will be
- used as salt by a password encoder. Typically something like
- "username" might be used. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="system-wide" type="xs:string">
- <xs:annotation>
- <xs:documentation>A single value that will be used as the salt for a
- password encoder. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:password-encoder.attlist"/>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:password-compare.attlist"/>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:ldap-ap.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="ldap-ap.attlist">
- <xs:attribute name="server-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>The optional server to use. If omitted, and a default LDAP server is
- registered (using <ldap-server> with no Id), that server will be used.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-search-base" type="xs:string">
- <xs:annotation>
- <xs:documentation>Search base for user searches. Defaults to "".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-search-filter" type="xs:string"/>
- <xs:attribute name="group-search-base" type="xs:string">
- <xs:annotation>
- <xs:documentation>Search base for group membership searches. Defaults to
- "ou=groups".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-search-filter" type="xs:string">
- <xs:annotation>
- <xs:documentation>Group search filter. Defaults to (uniqueMember={0}). The substituted
- parameter is the DN of the user.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-role-attribute" type="xs:string">
- <xs:annotation>
- <xs:documentation>The LDAP attribute name which contains the role name which will be used
- within Spring Security. Defaults to "cn".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-dn-pattern" type="xs:string">
- <xs:annotation>
- <xs:documentation>A specific pattern used to build the user's DN, for example
- "uid={0},ou=people". The key "{0}" must be present and will be substituted with the
- username.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="role-prefix" type="xs:string">
- <xs:annotation>
- <xs:documentation>A non-empty string prefix that will be added to role strings loaded from
- persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the
- default is non-empty.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-details-class">
- <xs:annotation>
- <xs:documentation>Allows the objectClass of the user entry to be specified. If set, the
- framework will attempt to load standard attributes for the defined class into the returned
- UserDetails object</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="person"/>
- <xs:enumeration value="inetOrgPerson"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="password-compare.attlist">
- <xs:attribute name="password-attribute" type="xs:string">
- <xs:annotation>
- <xs:documentation>The attribute in the directory which contains the user password. Defaults
- to "userPassword".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="hash">
- <xs:annotation>
- <xs:documentation>Defines the hashing algorithm used on user passwords. We recommend
- strongly against using MD4, as it is a very weak hashing algorithm.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="plaintext"/>
- <xs:enumeration value="sha"/>
- <xs:enumeration value="sha-256"/>
- <xs:enumeration value="md5"/>
- <xs:enumeration value="md4"/>
- <xs:enumeration value="{sha}"/>
- <xs:enumeration value="{ssha}"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="intercept-methods">
- <xs:annotation>
- <xs:documentation>Can be used inside a bean definition to add a security interceptor to the
- bean and set up access configuration attributes for the bean's methods</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" name="protect">
- <xs:annotation>
- <xs:documentation>Defines a protected method and the access control configuration
- attributes that apply to it. We strongly advise you NOT to mix "protect" declarations
- with any services provided "global-method-security".</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:protect.attlist"/>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:intercept-methods.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="intercept-methods.attlist">
- <xs:attribute name="access-decision-manager-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Optional AccessDecisionManager bean ID to be used by the created method
- security interceptor.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="protect.attlist">
- <xs:attribute name="method" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>A method name</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Access configuration attributes list that applies to the method, e.g.
- "ROLE_A,ROLE_B".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="global-method-security">
- <xs:annotation>
- <xs:documentation>Provides method security for all beans registered in the Spring application
- context. Specifically, beans will be scanned for Spring Security annotations and/or matches
- with the ordered list of "protect-pointcut" sub-elements. Where there is a match, the beans
- will automatically be proxied and security authorization applied to the methods accordingly.
- If you use and enable all three sources of method security metadata (ie "protect-pointcut"
- declarations, @Secured and also JSR 250 security annotations), the metadata sources will be
- queried in that order. In practical terms, this enables you to use XML to override method
- security metadata expressed by way of @Secured annotations, with @Secured annotations
- overriding method security metadata expressed by JSR 250 annotations. It is perfectly
- acceptable to mix and match, with a given Java type using a combination of XML, @Secured and
- JSR 250 to express method security metadata (albeit on different
- methods).</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" name="protect-pointcut">
- <xs:annotation>
- <xs:documentation>Defines a protected pointcut and the access control configuration
- attributes that apply to it. Every bean registered in the Spring application context
- that provides a method that matches the pointcut will receive security
- authorization.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:protect-pointcut.attlist"/>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:global-method-security.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="global-method-security.attlist">
- <xs:attribute name="secured-annotations">
- <xs:annotation>
- <xs:documentation>Specifies whether the use of Spring Security's @Secured annotations should
- be enabled for this application context. Please ensure you have the
- spring-security-tiger-xxx.jar on the classpath. Defaults to "disabled".</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="disabled"/>
- <xs:enumeration value="enabled"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="jsr250-annotations">
- <xs:annotation>
- <xs:documentation>Specifies whether JSR-250 style attributes are to be used (for example
- "RolesAllowed"). This will require the javax.annotation.security classes on the classpath.
- Defaults to "disabled".</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="disabled"/>
- <xs:enumeration value="enabled"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="access-decision-manager-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Optional AccessDecisionManager bean ID to override the default used for
- method security.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="custom-after-invocation-provider">
- <xs:complexType/>
- </xs:element>
- <xs:attributeGroup name="protect-pointcut.attlist">
- <xs:attribute name="expression" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>An AspectJ expression, including the 'execution' keyword. For example,
- 'execution(int com.foo.TargetObject.countLength(String))' (without the
- quotes).</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Access configuration attributes list that applies to all methods matching
- the pointcut, e.g. "ROLE_A,ROLE_B"</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="http">
- <xs:annotation>
- <xs:documentation>Container element for HTTP security configuration</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element name="intercept-url">
- <xs:annotation>
- <xs:documentation>Specifies the access attributes and/or filter list for a particular
- set of URLs.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:intercept-url.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="form-login">
- <xs:annotation>
- <xs:documentation>Sets up a form login configuration for authentication with a username
- and password</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:form-login.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:element ref="security:openid-login"/>
- <xs:element name="x509">
- <xs:annotation>
- <xs:documentation>Adds support for X.509 client authentication.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:x509.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="http-basic">
- <xs:annotation>
- <xs:documentation>Adds support for basic authentication (this is an element to permit
- future expansion, such as supporting an "ignoreFailure" attribute)</xs:documentation>
- </xs:annotation>
- <xs:complexType/>
- </xs:element>
- <xs:element name="logout">
- <xs:annotation>
- <xs:documentation>Incorporates a logout processing filter. Most web applications require
- a logout filter, although you may not require one if you write a controller to
- provider similar logic.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:logout.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="concurrent-session-control">
- <xs:annotation>
- <xs:documentation>Adds support for concurrent session control, allowing limits to be
- placed on the number of sessions a user can have.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:concurrent-sessions.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="remember-me">
- <xs:annotation>
- <xs:documentation>Sets up remember-me authentication. If used with the "key" attribute
- (or no attributes) the cookie-only implementation will be used. Specifying
- "token-repository-ref" or "remember-me-data-source-ref" will use the more secure,
- persisten token approach. </xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:remember-me.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="anonymous">
- <xs:annotation>
- <xs:documentation>Adds support for automatically granting all anonymous web requests a
- particular principal identity and a corresponding granted
- authority.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:anonymous.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="port-mappings">
- <xs:annotation>
- <xs:documentation>Defines the list of mappings between http and https ports for use in
- redirects</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="security:port-mapping"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- </xs:choice>
- <xs:attributeGroup ref="security:http.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="http.attlist">
- <xs:attribute name="auto-config" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Automatically registers a login form, BASIC authentication, anonymous
- authentication, logout services, remember-me and servlet-api-integration. If set to
- "true", all of these capabilities are added (although you can still customize the
- configuration of each by providing the respective element). If unspecified, defaults to
- "false".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="create-session">
- <xs:annotation>
- <xs:documentation>Controls the eagerness with which an HTTP session is created. If not set,
- defaults to "ifRequired".</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="ifRequired"/>
- <xs:enumeration value="always"/>
- <xs:enumeration value="never"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="path-type">
- <xs:annotation>
- <xs:documentation>Defines the type of pattern used to specify URL paths (either JDK
- 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if
- unspecified.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="ant"/>
- <xs:enumeration value="regex"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="lowercase-comparisons" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Whether test URLs should be converted to lower case prior to comparing
- with defined path patterns. If unspecified, defaults to "true".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="servlet-api-provision" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Provides versions of HttpServletRequest security methods such as
- isUserInRole() and getPrincipal() which are implemented by accessing the Spring
- SecurityContext. Defaults to "true".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access-decision-manager-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Optional attribute specifying the ID of the AccessDecisionManager
- implementation which should be used for authorizing HTTP requests.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="realm" type="xs:string">
- <xs:annotation>
- <xs:documentation>Optional attribute specifying the realm name that will be used for all
- authentication features that require a realm name (eg BASIC and Digest authentication). If
- unspecified, defaults to "Spring Security Application".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="session-fixation-protection">
- <xs:annotation>
- <xs:documentation>Indicates whether an existing session should be invalidated when a user
- authenticates and a new session started. If set to "none" no change will be made.
- "newSession" will create a new empty session. "migrateSession" will create a new session
- and copy the session attributes to the new session. Defaults to
- "migrateSession".</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="none"/>
- <xs:enumeration value="newSession"/>
- <xs:enumeration value="migrateSession"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="entry-point-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Allows a customized AuthenticationEntryPoint to be
- used.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="once-per-request" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Corresponds to the observeOncePerRequest property of
- FilterSecurityInterceptor. Defaults to "true"</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access-denied-page" type="xs:string">
- <xs:annotation>
- <xs:documentation>Allows the access denied page to be set (the user will be redirected here
- if an AccessDeniedException is raised).</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="intercept-url.attlist">
- <xs:attribute name="pattern" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>The pattern which defines the URL path. The content will depend on the
- type set in the containing http element, so will default to ant path
- syntax.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access" type="xs:string">
- <xs:annotation>
- <xs:documentation>The access configuration attributes that apply for the configured
- path.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="method">
- <xs:annotation>
- <xs:documentation>The HTTP Method for which the access configuration attributes should
- apply. If not specified, the attributes will apply to any method.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="GET"/>
- <xs:enumeration value="DELETE"/>
- <xs:enumeration value="HEAD"/>
- <xs:enumeration value="OPTIONS"/>
- <xs:enumeration value="POST"/>
- <xs:enumeration value="PUT"/>
- <xs:enumeration value="TRACE"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="filters">
- <xs:annotation>
- <xs:documentation>The filter list for the path. Currently can be set to "none" to remove a
- path from having any filters applied. The full filter stack (consisting of all filters
- created by the namespace configuration, and any added using 'custom-filter'), will be
- applied to any other paths.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="none"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="requires-channel">
- <xs:annotation>
- <xs:documentation>Used to specify that a URL must be accessed over http or
- https</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="http"/>
- <xs:enumeration value="https"/>
- <xs:enumeration value="any"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="logout.attlist">
- <xs:attribute name="logout-url" type="xs:string">
- <xs:annotation>
- <xs:documentation>Specifies the URL that will cause a logout. Spring Security will
- initialize a filter that responds to this particular URL. Defaults to
- /j_spring_security_logout if unspecified.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="logout-success-url" type="xs:string">
- <xs:annotation>
- <xs:documentation>Specifies the URL to display once the user has logged out. If not
- specified, defaults to /.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="invalidate-session" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Specifies whether a logout also causes HttpSession invalidation, which is
- generally desirable. If unspecified, defaults to true.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="form-login.attlist">
- <xs:attribute name="login-processing-url" type="xs:string">
- <xs:annotation>
- <xs:documentation>The URL that the login form is posted to. If unspecified, it defaults to
- /j_spring_security_check.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="default-target-url" type="xs:string">
- <xs:annotation>
- <xs:documentation>The URL that will be redirected to after successful authentication, if the
- user's previous action could not be resumed. This generally happens if the user visits a
- login page without having first requested a secured operation that triggers
- authentication. If unspecified, defaults to the root of the
- application.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="always-use-default-target" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Whether the user should always be redirected to the default-target-url
- after login. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="login-page" type="xs:string">
- <xs:annotation>
- <xs:documentation>The URL for the login page. If no login URL is specified, Spring Security
- will automatically create a login URL at /spring_security_login and a corresponding filter
- to render that login URL when requested.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="authentication-failure-url" type="xs:string">
- <xs:annotation>
- <xs:documentation>The URL for the login failure page. If no login failure URL is specified,
- Spring Security will automatically create a failure login URL at
- /spring_security_login?login_error and a corresponding filter to render that login failure
- URL when requested.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="openid-login">
- <xs:annotation>
- <xs:documentation>Sets up form login for authentication with an Open ID
- identity</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:form-login.attlist"/>
- <xs:attribute name="user-service-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean)
- Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="filter-chain-map">
- <xs:annotation>
- <xs:documentation>Used to explicitly configure a FilterChainProxy instance with a
- FilterChainMap</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" name="filter-chain">
- <xs:annotation>
- <xs:documentation>Used within filter-chain-map to define a specific URL pattern and the
- list of filters which apply to the URLs matching that pattern. When multiple
- filter-chain elements are used within a filter-chain-map element, the most specific
- patterns must be placed at the top of the list, with most general ones at the
- bottom.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:filter-chain.attlist"/>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:filter-chain-map.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="filter-chain-map.attlist">
- <xs:attributeGroup ref="security:path-type"/>
- </xs:attributeGroup>
- <xs:attributeGroup name="filter-chain.attlist">
- <xs:attribute name="pattern" use="required" type="xs:string"/>
- <xs:attribute name="filters" use="required" type="xs:string"/>
- </xs:attributeGroup>
- <xs:element name="filter-invocation-definition-source">
- <xs:annotation>
- <xs:documentation>Used to explicitly configure a FilterInvocationDefinitionSource bean for use
- with a FilterSecurityInterceptor. Usually only needed if you are configuring a
- FilterChainProxy explicitly, rather than using the <http> element. The
- intercept-url elements used should only contain pattern, method and access attributes. Any
- others will result in a configuration error. </xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" name="intercept-url">
- <xs:annotation>
- <xs:documentation>Specifies the access attributes and/or filter list for a particular
- set of URLs.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:intercept-url.attlist"/>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:fids.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="fids.attlist">
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
- context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="lowercase-comparisons" type="security:boolean">
- <xs:annotation>
- <xs:documentation>as for http element</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="path-type">
- <xs:annotation>
- <xs:documentation>Defines the type of pattern used to specify URL paths (either JDK
- 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if
- unspecified.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="ant"/>
- <xs:enumeration value="regex"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="concurrent-sessions.attlist">
- <xs:attribute name="max-sessions" type="xs:string"/>
- <xs:attribute name="expired-url" type="xs:string">
- <xs:annotation>
- <xs:documentation>The URL a user will be redirected to if they attempt to use a session
- which has been "expired" by the concurrent session controller.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="exception-if-maximum-exceeded" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Specifies that an exception should be raised when a user attempts to login
- twice. The default behaviour is to expire the original session.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="session-registry-alias" type="xs:string">
- <xs:annotation>
- <xs:documentation>Allows you to define an alias for the SessionRegistry bean in order to
- access it in your own configuration</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="session-registry-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>A reference to an external SessionRegistry implementation which will be
- used in place of the standard one. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="remember-me.attlist">
- <xs:attribute name="key" type="xs:string">
- <xs:annotation>
- <xs:documentation>The "key" used to identify cookies from a specific token-based remember-me
- application. You should set this to a unique value for your
- application.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="token-repository-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Reference to a PersistentTokenRepository bean for use with the persistent
- token remember-me implementation. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="data-source-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>A reference to a DataSource bean</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attributeGroup ref="security:remember-me-services-ref"/>
- <xs:attribute name="user-service-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean)
- Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="token-validity-seconds" type="xs:string">
- <xs:annotation>
- <xs:documentation>The period (in seconds) for which the remember-me cookie should be valid.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="token-repository-ref">
- <xs:attribute name="token-repository-ref" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Reference to a PersistentTokenRepository bean for use with the persistent
- token remember-me implementation. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="remember-me-services-ref">
- <xs:attribute name="services-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Allows a custom implementation of RememberMeServices to be used. Note that
- this implementation should return RememberMeAuthenticationToken instances with the same
- "key" value as specified in the remember-me element. Alternatively it should register its
- own AuthenticationProvider. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="remember-me-data-source-ref">
- <xs:attributeGroup ref="security:data-source-ref"/>
- </xs:attributeGroup>
- <xs:attributeGroup name="anonymous.attlist">
- <xs:attribute name="key" type="xs:string">
- <xs:annotation>
- <xs:documentation>The key shared between the provider and filter. This generally does not
- need to be set. If unset, it will default to "doesNotMatter".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="username" type="xs:string">
- <xs:annotation>
- <xs:documentation>The username that should be assigned to the anonymous request. This allows
- the principal to be identified, which may be important for logging and auditing. if unset,
- defaults to "anonymousUser".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="granted-authority" type="xs:string">
- <xs:annotation>
- <xs:documentation>The granted authority that should be assigned to the anonymous request.
- Commonly this is used to assign the anonymous request particular roles, which can
- subsequently be used in authorization decisions. If unset, defaults to
- "ROLE_ANONYMOUS".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="port-mapping">
- <xs:complexType>
- <xs:attributeGroup ref="security:http-port"/>
- <xs:attributeGroup ref="security:https-port"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="http-port">
- <xs:attribute name="http" use="required" type="xs:string"/>
- </xs:attributeGroup>
- <xs:attributeGroup name="https-port">
- <xs:attribute name="https" use="required" type="xs:string"/>
- </xs:attributeGroup>
- <xs:attributeGroup name="x509.attlist">
- <xs:attribute name="subject-principal-regex" type="xs:string">
- <xs:annotation>
- <xs:documentation>The regular expression used to obtain the username from the certificate's
- subject. Defaults to matching on the common name using the pattern
- "CN=(.*?),".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-service-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean)
- Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="authentication-manager">
- <xs:annotation>
- <xs:documentation>If you are using namespace configuration with Spring Security, an
- AuthenticationManager will automatically be registered. This element allows you to define an
- alias to allow you to reference the authentication-manager in your own beans.
- </xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:authman.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="authman.attlist">
- <xs:attribute name="alias" use="required" type="xs:ID">
- <xs:annotation>
- <xs:documentation>The alias you wish to use for the AuthenticationManager
- bean</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="session-controller-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Allows the session controller to be set on the internal
- AuthenticationManager. This should not be used with the <concurrent-session-control
- /> element</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="authentication-provider">
- <xs:annotation>
- <xs:documentation>Indicates that the contained user-service should be used as an
- authentication source. </xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="security:any-user-service"/>
- <xs:element name="password-encoder">
- <xs:annotation>
- <xs:documentation>element which defines a password encoding strategy. Used by an
- authentication provider to convert submitted passwords to hashed versions, for
- example.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="salt-source">
- <xs:complexType>
- <xs:attribute name="user-property" type="xs:string">
- <xs:annotation>
- <xs:documentation>A property of the UserDetails object which will be used as
- salt by a password encoder. Typically something like "username" might be
- used. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="system-wide" type="xs:string">
- <xs:annotation>
- <xs:documentation>A single value that will be used as the salt for a password
- encoder. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:password-encoder.attlist"/>
- </xs:complexType>
- </xs:element>
- </xs:choice>
- <xs:attributeGroup ref="security:ap.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="ap.attlist">
- <xs:attribute name="user-service-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean)
- Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="custom-authentication-provider">
- <xs:complexType/>
- </xs:element>
- <xs:element name="user-service" substitutionGroup="security:any-user-service">
- <xs:annotation>
- <xs:documentation>Creates an in-memory UserDetailsService from a properties file or a list of
- "user" child elements.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="security:user"/>
- </xs:sequence>
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
- context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attributeGroup ref="security:properties-file"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="properties-file">
- <xs:attribute name="properties" type="xs:string"/>
- </xs:attributeGroup>
- <xs:element name="user">
- <xs:annotation>
- <xs:documentation>Represents a user in the application.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:user.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="user.attlist">
- <xs:attribute name="name" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>The username assigned to the user.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="password" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>The password assigned to the user. This may be hashed if the corresponding
- authentication provider supports hashing (remember to set the "hash" attribute of the
- "user-service" element).</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="authorities" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>One of more authorities granted to the user. Separate authorities with a
- comma (but no space). For example, "ROLE_USER,ROLE_ADMINISTRATOR"</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="locked" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Can be set to "true" to mark an account as locked and
- unusable.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="disabled" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Can be set to "true" to mark an account as disabled and
- unusable.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="jdbc-user-service" substitutionGroup="security:any-user-service">
- <xs:annotation>
- <xs:documentation>Causes creation of a JDBC-based UserDetailsService.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
- context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attributeGroup ref="security:jdbc-user-service.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="jdbc-user-service.attlist">
- <xs:attribute name="data-source-ref" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>The bean ID of the DataSource which provides the required
- tables.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="cache-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Defines a reference to a cache for use with a
- UserDetailsService.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="users-by-username-query" type="xs:string">
- <xs:annotation>
- <xs:documentation>An SQL statement to query a username, password, and enabled status given a
- username</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="authorities-by-username-query" type="xs:string">
- <xs:annotation>
- <xs:documentation>An SQL statement to query for a user's granted authorities given a
- username.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-authorities-by-username-query" type="xs:string">
- <xs:annotation>
- <xs:documentation>An SQL statement to query user's group authorities given a
- username.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="role-prefix" type="xs:string">
- <xs:annotation>
- <xs:documentation>A non-empty string prefix that will be added to role strings loaded from
- persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the
- default is non-empty.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="any-user-service" abstract="true"/>
- <xs:group name="custom-filter">
- <xs:sequence>
- <xs:element minOccurs="0" ref="security:custom-filter"/>
- </xs:sequence>
- </xs:group>
- <xs:element name="custom-filter">
- <xs:annotation>
- <xs:documentation>Used to indicate that a filter bean declaration should be incorporated into
- the security filter chain. If neither the 'after' or 'before' options are supplied, then the
- filter must implement the Ordered interface directly. </xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attribute name="after" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The filter immediately after which the custom-filter should be placed in
- the chain. This feature will only be needed by advanced users who wish to mix their own
- filters into the security filter chain and have some knowledge of the standard Spring
- Security filters. The filter names map to specific Spring Security implementation
- filters. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="before" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The filter immediately before which the custom-filter should be placed
- in the chain</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="position" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The explicit position at which the custom-filter should be placed in the
- chain. Use if you are replacing a standard filter.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="after">
- <xs:attribute name="after" use="required" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The filter immediately after which the custom-filter should be placed in
- the chain. This feature will only be needed by advanced users who wish to mix their own
- filters into the security filter chain and have some knowledge of the standard Spring
- Security filters. The filter names map to specific Spring Security implementation filters.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="before">
- <xs:attribute name="before" use="required" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The filter immediately before which the custom-filter should be placed in
- the chain</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="position">
- <xs:attribute name="position" use="required" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The explicit position at which the custom-filter should be placed in the
- chain. Use if you are replacing a standard filter.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:simpleType name="named-security-filter">
- <xs:restriction base="xs:token">
- <xs:enumeration value="FIRST"/>
- <xs:enumeration value="CHANNEL_FILTER"/>
- <xs:enumeration value="CONCURRENT_SESSION_FILTER"/>
- <xs:enumeration value="SESSION_CONTEXT_INTEGRATION_FILTER"/>
- <xs:enumeration value="LOGOUT_FILTER"/>
- <xs:enumeration value="X509_FILTER"/>
- <xs:enumeration value="PRE_AUTH_FILTER"/>
- <xs:enumeration value="CAS_PROCESSING_FILTER"/>
- <xs:enumeration value="AUTHENTICATION_PROCESSING_FILTER"/>
- <xs:enumeration value="BASIC_PROCESSING_FILTER"/>
- <xs:enumeration value="SERVLET_API_SUPPORT_FILTER"/>
- <xs:enumeration value="REMEMBER_ME_FILTER"/>
- <xs:enumeration value="ANONYMOUS_FILTER"/>
- <xs:enumeration value="EXCEPTION_TRANSLATION_FILTER"/>
- <xs:enumeration value="NTLM_FILTER"/>
- <xs:enumeration value="FILTER_SECURITY_INTERCEPTOR"/>
- <xs:enumeration value="SWITCH_USER_FILTER"/>
- <xs:enumeration value="LAST"/>
- </xs:restriction>
- </xs:simpleType>
-</xs:schema>
diff --git a/dist/spring-security-config/org/springframework/security/config/spring-security-2.0.4.xsd b/dist/spring-security-config/org/springframework/security/config/spring-security-2.0.4.xsd
deleted file mode 100644
index 34844f4..0000000
--- a/dist/spring-security-config/org/springframework/security/config/spring-security-2.0.4.xsd
+++ /dev/null
@@ -1,1468 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
- xmlns:security="http://www.springframework.org/schema/security" elementFormDefault="qualified"
- targetNamespace="http://www.springframework.org/schema/security">
- <xs:attributeGroup name="hash">
- <xs:attribute name="hash" use="required">
- <xs:annotation>
- <xs:documentation>Defines the hashing algorithm used on user passwords. We recommend
- strongly against using MD4, as it is a very weak hashing algorithm.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="plaintext"/>
- <xs:enumeration value="sha"/>
- <xs:enumeration value="sha-256"/>
- <xs:enumeration value="md5"/>
- <xs:enumeration value="md4"/>
- <xs:enumeration value="{sha}"/>
- <xs:enumeration value="{ssha}"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="base64">
- <xs:attribute name="base64" use="required">
- <xs:annotation>
- <xs:documentation>Whether a string should be base64 encoded</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="true"/>
- <xs:enumeration value="false"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="path-type">
- <xs:attribute name="path-type" use="required">
- <xs:annotation>
- <xs:documentation>Defines the type of pattern used to specify URL paths (either JDK
- 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if
- unspecified.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="ant"/>
- <xs:enumeration value="regex"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="port">
- <xs:attribute name="port" use="required" type="xs:integer">
- <xs:annotation>
- <xs:documentation>Specifies an IP port number. Used to configure an embedded LDAP server,
- for example.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="url">
- <xs:attribute name="url" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Specifies a URL.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="id">
- <xs:attribute name="id" use="required" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
- context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="ref">
- <xs:attribute name="ref" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="cache-ref">
- <xs:attribute name="cache-ref" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Defines a reference to a cache for use with a
- UserDetailsService.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-service-ref">
- <xs:attribute name="user-service-ref" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean)
- Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="data-source-ref">
- <xs:attribute name="data-source-ref" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>A reference to a DataSource bean</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="password-encoder.attlist">
- <xs:attribute name="ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="hash">
- <xs:annotation>
- <xs:documentation>Defines the hashing algorithm used on user passwords. We recommend
- strongly against using MD4, as it is a very weak hashing algorithm.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="plaintext"/>
- <xs:enumeration value="sha"/>
- <xs:enumeration value="sha-256"/>
- <xs:enumeration value="md5"/>
- <xs:enumeration value="md4"/>
- <xs:enumeration value="{sha}"/>
- <xs:enumeration value="{ssha}"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="base64">
- <xs:annotation>
- <xs:documentation>Whether a string should be base64 encoded</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="true"/>
- <xs:enumeration value="false"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-property">
- <xs:attribute name="user-property" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>A property of the UserDetails object which will be used as salt by a
- password encoder. Typically something like "username" might be used. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="system-wide">
- <xs:attribute name="system-wide" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>A single value that will be used as the salt for a password encoder.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:simpleType name="boolean">
- <xs:restriction base="xs:token">
- <xs:enumeration value="true"/>
- <xs:enumeration value="false"/>
- </xs:restriction>
- </xs:simpleType>
- <xs:attributeGroup name="role-prefix">
- <xs:attribute name="role-prefix" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>A non-empty string prefix that will be added to role strings loaded from
- persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the
- default is non-empty.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="ldap-server">
- <xs:annotation>
- <xs:documentation>Defines an LDAP server location or starts an embedded server. The url
- indicates the location of a remote server. If no url is given, an embedded server will be
- started, listening on the supplied port number. The port is optional and defaults to 33389.
- A Spring LDAP ContextSource bean will be registered for the server with the id supplied.
- </xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:ldap-server.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="ldap-server.attlist">
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
- context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="url" type="xs:string">
- <xs:annotation>
- <xs:documentation>Specifies a URL.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="port" type="xs:integer">
- <xs:annotation>
- <xs:documentation>Specifies an IP port number. Used to configure an embedded LDAP server,
- for example.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="manager-dn" type="xs:string">
- <xs:annotation>
- <xs:documentation>Username (DN) of the "manager" user identity which will be used to
- authenticate to a (non-embedded) LDAP server. If omitted, anonymous access will be used.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="manager-password" type="xs:string">
- <xs:annotation>
- <xs:documentation>The password for the manager DN.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="ldif" type="xs:string">
- <xs:annotation>
- <xs:documentation>Explicitly specifies an ldif file resource to load into an embedded LDAP
- server</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="root" type="xs:string">
- <xs:annotation>
- <xs:documentation>Optional root suffix for the embedded LDAP server. Default is
- "dc=springframework,dc=org"</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="ldap-server-ref-attribute">
- <xs:attribute name="server-ref" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>The optional server to use. If omitted, and a default LDAP server is
- registered (using <ldap-server> with no Id), that server will be used.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="group-search-filter-attribute">
- <xs:attribute name="group-search-filter" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Group search filter. Defaults to (uniqueMember={0}). The substituted
- parameter is the DN of the user.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="group-search-base-attribute">
- <xs:attribute name="group-search-base" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Search base for group membership searches. Defaults to
- "ou=groups".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-search-filter-attribute">
- <xs:attribute name="user-search-filter" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>The LDAP filter used to search for users (optional). For example
- "(uid={0})". The substituted parameter is the user's login name.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-search-base-attribute">
- <xs:attribute name="user-search-base" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Search base for user searches. Defaults to "". Only used with a
- 'user-search-filter'.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="group-role-attribute-attribute">
- <xs:attribute name="group-role-attribute" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>The LDAP attribute name which contains the role name which will be used
- within Spring Security. Defaults to "cn".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-details-class-attribute">
- <xs:attribute name="user-details-class" use="required">
- <xs:annotation>
- <xs:documentation>Allows the objectClass of the user entry to be specified. If set, the
- framework will attempt to load standard attributes for the defined class into the returned
- UserDetails object</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="person"/>
- <xs:enumeration value="inetOrgPerson"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="ldap-user-service" substitutionGroup="security:any-user-service">
- <xs:complexType>
- <xs:attributeGroup ref="security:ldap-us.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="ldap-us.attlist">
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
- context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="server-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>The optional server to use. If omitted, and a default LDAP server is
- registered (using <ldap-server> with no Id), that server will be used.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-search-filter" type="xs:string">
- <xs:annotation>
- <xs:documentation>The LDAP filter used to search for users (optional). For example
- "(uid={0})". The substituted parameter is the user's login name.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-search-base" type="xs:string">
- <xs:annotation>
- <xs:documentation>Search base for user searches. Defaults to "". Only used with a
- 'user-search-filter'.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-search-filter" type="xs:string">
- <xs:annotation>
- <xs:documentation>Group search filter. Defaults to (uniqueMember={0}). The substituted
- parameter is the DN of the user.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-search-base" type="xs:string">
- <xs:annotation>
- <xs:documentation>Search base for group membership searches. Defaults to
- "ou=groups".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-role-attribute" type="xs:string">
- <xs:annotation>
- <xs:documentation>The LDAP attribute name which contains the role name which will be used
- within Spring Security. Defaults to "cn".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="cache-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Defines a reference to a cache for use with a
- UserDetailsService.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="role-prefix" type="xs:string">
- <xs:annotation>
- <xs:documentation>A non-empty string prefix that will be added to role strings loaded from
- persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the
- default is non-empty.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-details-class">
- <xs:annotation>
- <xs:documentation>Allows the objectClass of the user entry to be specified. If set, the
- framework will attempt to load standard attributes for the defined class into the returned
- UserDetails object</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="person"/>
- <xs:enumeration value="inetOrgPerson"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="ldap-authentication-provider">
- <xs:annotation>
- <xs:documentation>Sets up an ldap authentication provider</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="password-compare">
- <xs:annotation>
- <xs:documentation>Specifies that an LDAP provider should use an LDAP compare operation
- of the user's password to authenticate the user</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="password-encoder">
- <xs:annotation>
- <xs:documentation>element which defines a password encoding strategy. Used by an
- authentication provider to convert submitted passwords to hashed versions, for
- example.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="salt-source">
- <xs:annotation>
- <xs:documentation>Password salting strategy. A system-wide constant or a
- property from the UserDetails object can be used.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attribute name="user-property" type="xs:string">
- <xs:annotation>
- <xs:documentation>A property of the UserDetails object which will be
- used as salt by a password encoder. Typically something like
- "username" might be used. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="system-wide" type="xs:string">
- <xs:annotation>
- <xs:documentation>A single value that will be used as the salt for a
- password encoder. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:password-encoder.attlist"/>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:password-compare.attlist"/>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:ldap-ap.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="ldap-ap.attlist">
- <xs:attribute name="server-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>The optional server to use. If omitted, and a default LDAP server is
- registered (using <ldap-server> with no Id), that server will be used.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-search-base" type="xs:string">
- <xs:annotation>
- <xs:documentation>Search base for user searches. Defaults to "". Only used with a
- 'user-search-filter'.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-search-filter" type="xs:string">
- <xs:annotation>
- <xs:documentation>The LDAP filter used to search for users (optional). For example
- "(uid={0})". The substituted parameter is the user's login name.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-search-base" type="xs:string">
- <xs:annotation>
- <xs:documentation>Search base for group membership searches. Defaults to
- "ou=groups".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-search-filter" type="xs:string">
- <xs:annotation>
- <xs:documentation>Group search filter. Defaults to (uniqueMember={0}). The substituted
- parameter is the DN of the user.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-role-attribute" type="xs:string">
- <xs:annotation>
- <xs:documentation>The LDAP attribute name which contains the role name which will be used
- within Spring Security. Defaults to "cn".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-dn-pattern" type="xs:string">
- <xs:annotation>
- <xs:documentation>A specific pattern used to build the user's DN, for example
- "uid={0},ou=people". The key "{0}" must be present and will be substituted with the
- username.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="role-prefix" type="xs:string">
- <xs:annotation>
- <xs:documentation>A non-empty string prefix that will be added to role strings loaded from
- persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the
- default is non-empty.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-details-class">
- <xs:annotation>
- <xs:documentation>Allows the objectClass of the user entry to be specified. If set, the
- framework will attempt to load standard attributes for the defined class into the returned
- UserDetails object</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="person"/>
- <xs:enumeration value="inetOrgPerson"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="password-compare.attlist">
- <xs:attribute name="password-attribute" type="xs:string">
- <xs:annotation>
- <xs:documentation>The attribute in the directory which contains the user password. Defaults
- to "userPassword".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="hash">
- <xs:annotation>
- <xs:documentation>Defines the hashing algorithm used on user passwords. We recommend
- strongly against using MD4, as it is a very weak hashing algorithm.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="plaintext"/>
- <xs:enumeration value="sha"/>
- <xs:enumeration value="sha-256"/>
- <xs:enumeration value="md5"/>
- <xs:enumeration value="md4"/>
- <xs:enumeration value="{sha}"/>
- <xs:enumeration value="{ssha}"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="intercept-methods">
- <xs:annotation>
- <xs:documentation>Can be used inside a bean definition to add a security interceptor to the
- bean and set up access configuration attributes for the bean's methods</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" name="protect">
- <xs:annotation>
- <xs:documentation>Defines a protected method and the access control configuration
- attributes that apply to it. We strongly advise you NOT to mix "protect" declarations
- with any services provided "global-method-security".</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:protect.attlist"/>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:intercept-methods.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="intercept-methods.attlist">
- <xs:attribute name="access-decision-manager-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Optional AccessDecisionManager bean ID to be used by the created method
- security interceptor.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="protect.attlist">
- <xs:attribute name="method" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>A method name</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Access configuration attributes list that applies to the method, e.g.
- "ROLE_A,ROLE_B".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="global-method-security">
- <xs:annotation>
- <xs:documentation>Provides method security for all beans registered in the Spring application
- context. Specifically, beans will be scanned for Spring Security annotations and/or matches
- with the ordered list of "protect-pointcut" sub-elements. Where there is a match, the beans
- will automatically be proxied and security authorization applied to the methods accordingly.
- If you use and enable all three sources of method security metadata (ie "protect-pointcut"
- declarations, @Secured and also JSR 250 security annotations), the metadata sources will be
- queried in that order. In practical terms, this enables you to use XML to override method
- security metadata expressed by way of @Secured annotations, with @Secured annotations
- overriding method security metadata expressed by JSR 250 annotations. It is perfectly
- acceptable to mix and match, with a given Java type using a combination of XML, @Secured and
- JSR 250 to express method security metadata (albeit on different
- methods).</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" name="protect-pointcut">
- <xs:annotation>
- <xs:documentation>Defines a protected pointcut and the access control configuration
- attributes that apply to it. Every bean registered in the Spring application context
- that provides a method that matches the pointcut will receive security
- authorization.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:protect-pointcut.attlist"/>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:global-method-security.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="global-method-security.attlist">
- <xs:attribute name="secured-annotations">
- <xs:annotation>
- <xs:documentation>Specifies whether the use of Spring Security's @Secured annotations should
- be enabled for this application context. Please ensure you have the
- spring-security-tiger-xxx.jar on the classpath. Defaults to "disabled".</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="disabled"/>
- <xs:enumeration value="enabled"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="jsr250-annotations">
- <xs:annotation>
- <xs:documentation>Specifies whether JSR-250 style attributes are to be used (for example
- "RolesAllowed"). This will require the javax.annotation.security classes on the classpath.
- Defaults to "disabled".</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="disabled"/>
- <xs:enumeration value="enabled"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="access-decision-manager-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Optional AccessDecisionManager bean ID to override the default used for
- method security.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="custom-after-invocation-provider">
- <xs:annotation>
- <xs:documentation>Used to decorate an AfterInvocationProvider to specify that it should be
- used with method security.</xs:documentation>
- </xs:annotation>
- <xs:complexType/>
- </xs:element>
- <xs:attributeGroup name="protect-pointcut.attlist">
- <xs:attribute name="expression" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>An AspectJ expression, including the 'execution' keyword. For example,
- 'execution(int com.foo.TargetObject.countLength(String))' (without the
- quotes).</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Access configuration attributes list that applies to all methods matching
- the pointcut, e.g. "ROLE_A,ROLE_B"</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="http">
- <xs:annotation>
- <xs:documentation>Container element for HTTP security configuration</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element name="intercept-url">
- <xs:annotation>
- <xs:documentation>Specifies the access attributes and/or filter list for a particular
- set of URLs.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:intercept-url.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="form-login">
- <xs:annotation>
- <xs:documentation>Sets up a form login configuration for authentication with a username
- and password</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:form-login.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:element ref="security:openid-login"/>
- <xs:element name="x509">
- <xs:annotation>
- <xs:documentation>Adds support for X.509 client authentication.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:x509.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="http-basic">
- <xs:annotation>
- <xs:documentation>Adds support for basic authentication (this is an element to permit
- future expansion, such as supporting an "ignoreFailure" attribute)</xs:documentation>
- </xs:annotation>
- <xs:complexType/>
- </xs:element>
- <xs:element name="logout">
- <xs:annotation>
- <xs:documentation>Incorporates a logout processing filter. Most web applications require
- a logout filter, although you may not require one if you write a controller to
- provider similar logic.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:logout.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="concurrent-session-control">
- <xs:annotation>
- <xs:documentation>Adds support for concurrent session control, allowing limits to be
- placed on the number of sessions a user can have.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:concurrent-sessions.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="remember-me">
- <xs:annotation>
- <xs:documentation>Sets up remember-me authentication. If used with the "key" attribute
- (or no attributes) the cookie-only implementation will be used. Specifying
- "token-repository-ref" or "remember-me-data-source-ref" will use the more secure,
- persisten token approach. </xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:remember-me.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="anonymous">
- <xs:annotation>
- <xs:documentation>Adds support for automatically granting all anonymous web requests a
- particular principal identity and a corresponding granted
- authority.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:anonymous.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="port-mappings">
- <xs:annotation>
- <xs:documentation>Defines the list of mappings between http and https ports for use in
- redirects</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="security:port-mapping"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- </xs:choice>
- <xs:attributeGroup ref="security:http.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="http.attlist">
- <xs:attribute name="auto-config" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Automatically registers a login form, BASIC authentication, anonymous
- authentication, logout services, remember-me and servlet-api-integration. If set to
- "true", all of these capabilities are added (although you can still customize the
- configuration of each by providing the respective element). If unspecified, defaults to
- "false".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="create-session">
- <xs:annotation>
- <xs:documentation>Controls the eagerness with which an HTTP session is created. If not set,
- defaults to "ifRequired".</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="ifRequired"/>
- <xs:enumeration value="always"/>
- <xs:enumeration value="never"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="path-type">
- <xs:annotation>
- <xs:documentation>Defines the type of pattern used to specify URL paths (either JDK
- 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if
- unspecified.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="ant"/>
- <xs:enumeration value="regex"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="lowercase-comparisons" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Whether test URLs should be converted to lower case prior to comparing
- with defined path patterns. If unspecified, defaults to "true".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="servlet-api-provision" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Provides versions of HttpServletRequest security methods such as
- isUserInRole() and getPrincipal() which are implemented by accessing the Spring
- SecurityContext. Defaults to "true".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access-decision-manager-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Optional attribute specifying the ID of the AccessDecisionManager
- implementation which should be used for authorizing HTTP requests.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="realm" type="xs:string">
- <xs:annotation>
- <xs:documentation>Optional attribute specifying the realm name that will be used for all
- authentication features that require a realm name (eg BASIC and Digest authentication). If
- unspecified, defaults to "Spring Security Application".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="session-fixation-protection">
- <xs:annotation>
- <xs:documentation>Indicates whether an existing session should be invalidated when a user
- authenticates and a new session started. If set to "none" no change will be made.
- "newSession" will create a new empty session. "migrateSession" will create a new session
- and copy the session attributes to the new session. Defaults to
- "migrateSession".</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="none"/>
- <xs:enumeration value="newSession"/>
- <xs:enumeration value="migrateSession"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="entry-point-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Allows a customized AuthenticationEntryPoint to be
- used.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="once-per-request" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Corresponds to the observeOncePerRequest property of
- FilterSecurityInterceptor. Defaults to "true"</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access-denied-page" type="xs:string">
- <xs:annotation>
- <xs:documentation>Allows the access denied page to be set (the user will be redirected here
- if an AccessDeniedException is raised).</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="intercept-url.attlist">
- <xs:attribute name="pattern" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>The pattern which defines the URL path. The content will depend on the
- type set in the containing http element, so will default to ant path
- syntax.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access" type="xs:string">
- <xs:annotation>
- <xs:documentation>The access configuration attributes that apply for the configured
- path.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="method">
- <xs:annotation>
- <xs:documentation>The HTTP Method for which the access configuration attributes should
- apply. If not specified, the attributes will apply to any method.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="GET"/>
- <xs:enumeration value="DELETE"/>
- <xs:enumeration value="HEAD"/>
- <xs:enumeration value="OPTIONS"/>
- <xs:enumeration value="POST"/>
- <xs:enumeration value="PUT"/>
- <xs:enumeration value="TRACE"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="filters">
- <xs:annotation>
- <xs:documentation>The filter list for the path. Currently can be set to "none" to remove a
- path from having any filters applied. The full filter stack (consisting of all filters
- created by the namespace configuration, and any added using 'custom-filter'), will be
- applied to any other paths.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="none"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="requires-channel">
- <xs:annotation>
- <xs:documentation>Used to specify that a URL must be accessed over http or https, or that
- there is no preference.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="http"/>
- <xs:enumeration value="https"/>
- <xs:enumeration value="any"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="logout.attlist">
- <xs:attribute name="logout-url" type="xs:string">
- <xs:annotation>
- <xs:documentation>Specifies the URL that will cause a logout. Spring Security will
- initialize a filter that responds to this particular URL. Defaults to
- /j_spring_security_logout if unspecified.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="logout-success-url" type="xs:string">
- <xs:annotation>
- <xs:documentation>Specifies the URL to display once the user has logged out. If not
- specified, defaults to /.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="invalidate-session" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Specifies whether a logout also causes HttpSession invalidation, which is
- generally desirable. If unspecified, defaults to true.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="form-login.attlist">
- <xs:attribute name="login-processing-url" type="xs:string">
- <xs:annotation>
- <xs:documentation>The URL that the login form is posted to. If unspecified, it defaults to
- /j_spring_security_check.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="default-target-url" type="xs:string">
- <xs:annotation>
- <xs:documentation>The URL that will be redirected to after successful authentication, if the
- user's previous action could not be resumed. This generally happens if the user visits a
- login page without having first requested a secured operation that triggers
- authentication. If unspecified, defaults to the root of the
- application.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="always-use-default-target" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Whether the user should always be redirected to the default-target-url
- after login. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="login-page" type="xs:string">
- <xs:annotation>
- <xs:documentation>The URL for the login page. If no login URL is specified, Spring Security
- will automatically create a login URL at /spring_security_login and a corresponding filter
- to render that login URL when requested.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="authentication-failure-url" type="xs:string">
- <xs:annotation>
- <xs:documentation>The URL for the login failure page. If no login failure URL is specified,
- Spring Security will automatically create a failure login URL at
- /spring_security_login?login_error and a corresponding filter to render that login failure
- URL when requested.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="openid-login">
- <xs:annotation>
- <xs:documentation>Sets up form login for authentication with an Open ID
- identity</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:form-login.attlist"/>
- <xs:attribute name="user-service-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean)
- Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="filter-chain-map">
- <xs:annotation>
- <xs:documentation>Used to explicitly configure a FilterChainProxy instance with a
- FilterChainMap</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" name="filter-chain">
- <xs:annotation>
- <xs:documentation>Used within filter-chain-map to define a specific URL pattern and the
- list of filters which apply to the URLs matching that pattern. When multiple
- filter-chain elements are used within a filter-chain-map element, the most specific
- patterns must be placed at the top of the list, with most general ones at the
- bottom.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:filter-chain.attlist"/>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:filter-chain-map.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="filter-chain-map.attlist">
- <xs:attributeGroup ref="security:path-type"/>
- </xs:attributeGroup>
- <xs:attributeGroup name="filter-chain.attlist">
- <xs:attribute name="pattern" use="required" type="xs:string"/>
- <xs:attribute name="filters" use="required" type="xs:string"/>
- </xs:attributeGroup>
- <xs:element name="filter-invocation-definition-source">
- <xs:annotation>
- <xs:documentation>Used to explicitly configure a FilterInvocationDefinitionSource bean for use
- with a FilterSecurityInterceptor. Usually only needed if you are configuring a
- FilterChainProxy explicitly, rather than using the <http> element. The
- intercept-url elements used should only contain pattern, method and access attributes. Any
- others will result in a configuration error. </xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" name="intercept-url">
- <xs:annotation>
- <xs:documentation>Specifies the access attributes and/or filter list for a particular
- set of URLs.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:intercept-url.attlist"/>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:fids.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="fids.attlist">
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
- context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="lowercase-comparisons" type="security:boolean">
- <xs:annotation>
- <xs:documentation>as for http element</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="path-type">
- <xs:annotation>
- <xs:documentation>Defines the type of pattern used to specify URL paths (either JDK
- 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if
- unspecified.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="ant"/>
- <xs:enumeration value="regex"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="concurrent-sessions.attlist">
- <xs:attribute name="max-sessions" type="xs:positiveInteger">
- <xs:annotation>
- <xs:documentation>The maximum number of sessions a single user can have open at the same
- time. Defaults to "1".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="expired-url" type="xs:string">
- <xs:annotation>
- <xs:documentation>The URL a user will be redirected to if they attempt to use a session
- which has been "expired" by the concurrent session controller because they have logged in
- again.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="exception-if-maximum-exceeded" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Specifies that an exception should be raised when a user attempts to login
- when they already have the maximum configured sessions open. The default behaviour is to
- expire the original session.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="session-registry-alias" type="xs:string">
- <xs:annotation>
- <xs:documentation>Allows you to define an alias for the SessionRegistry bean in order to
- access it in your own configuration</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="session-registry-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>A reference to an external SessionRegistry implementation which will be
- used in place of the standard one. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="remember-me.attlist">
- <xs:attribute name="key" type="xs:string">
- <xs:annotation>
- <xs:documentation>The "key" used to identify cookies from a specific token-based remember-me
- application. You should set this to a unique value for your
- application.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="token-repository-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Reference to a PersistentTokenRepository bean for use with the persistent
- token remember-me implementation. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="data-source-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>A reference to a DataSource bean</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attributeGroup ref="security:remember-me-services-ref"/>
- <xs:attribute name="user-service-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean)
- Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="token-validity-seconds" type="xs:positiveInteger">
- <xs:annotation>
- <xs:documentation>The period (in seconds) for which the remember-me cookie should be valid.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="token-repository-ref">
- <xs:attribute name="token-repository-ref" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Reference to a PersistentTokenRepository bean for use with the persistent
- token remember-me implementation. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="remember-me-services-ref">
- <xs:attribute name="services-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Allows a custom implementation of RememberMeServices to be used. Note that
- this implementation should return RememberMeAuthenticationToken instances with the same
- "key" value as specified in the remember-me element. Alternatively it should register its
- own AuthenticationProvider. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="remember-me-data-source-ref">
- <xs:attributeGroup ref="security:data-source-ref"/>
- </xs:attributeGroup>
- <xs:attributeGroup name="anonymous.attlist">
- <xs:attribute name="key" type="xs:string">
- <xs:annotation>
- <xs:documentation>The key shared between the provider and filter. This generally does not
- need to be set. If unset, it will default to "doesNotMatter".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="username" type="xs:string">
- <xs:annotation>
- <xs:documentation>The username that should be assigned to the anonymous request. This allows
- the principal to be identified, which may be important for logging and auditing. if unset,
- defaults to "anonymousUser".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="granted-authority" type="xs:string">
- <xs:annotation>
- <xs:documentation>The granted authority that should be assigned to the anonymous request.
- Commonly this is used to assign the anonymous request particular roles, which can
- subsequently be used in authorization decisions. If unset, defaults to
- "ROLE_ANONYMOUS".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="port-mapping">
- <xs:complexType>
- <xs:attributeGroup ref="security:http-port"/>
- <xs:attributeGroup ref="security:https-port"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="http-port">
- <xs:attribute name="http" use="required" type="xs:string"/>
- </xs:attributeGroup>
- <xs:attributeGroup name="https-port">
- <xs:attribute name="https" use="required" type="xs:string"/>
- </xs:attributeGroup>
- <xs:attributeGroup name="x509.attlist">
- <xs:attribute name="subject-principal-regex" type="xs:string">
- <xs:annotation>
- <xs:documentation>The regular expression used to obtain the username from the certificate's
- subject. Defaults to matching on the common name using the pattern
- "CN=(.*?),".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-service-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean)
- Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="authentication-manager">
- <xs:annotation>
- <xs:documentation>If you are using namespace configuration with Spring Security, an
- AuthenticationManager will automatically be registered. This element allows you to define an
- alias to allow you to reference the authentication-manager in your own beans.
- </xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:authman.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="authman.attlist">
- <xs:attribute name="alias" use="required" type="xs:ID">
- <xs:annotation>
- <xs:documentation>The alias you wish to use for the AuthenticationManager
- bean</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="session-controller-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Allows the session controller to be set on the internal
- AuthenticationManager. This should not be used with the <concurrent-session-control
- /> element</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="authentication-provider">
- <xs:annotation>
- <xs:documentation>Indicates that the contained user-service should be used as an
- authentication source. </xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="security:any-user-service"/>
- <xs:element name="password-encoder">
- <xs:annotation>
- <xs:documentation>element which defines a password encoding strategy. Used by an
- authentication provider to convert submitted passwords to hashed versions, for
- example.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="salt-source">
- <xs:annotation>
- <xs:documentation>Password salting strategy. A system-wide constant or a property
- from the UserDetails object can be used.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attribute name="user-property" type="xs:string">
- <xs:annotation>
- <xs:documentation>A property of the UserDetails object which will be used as
- salt by a password encoder. Typically something like "username" might be
- used. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="system-wide" type="xs:string">
- <xs:annotation>
- <xs:documentation>A single value that will be used as the salt for a password
- encoder. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:password-encoder.attlist"/>
- </xs:complexType>
- </xs:element>
- </xs:choice>
- <xs:attributeGroup ref="security:ap.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="ap.attlist">
- <xs:attribute name="user-service-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean)
- Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="custom-authentication-provider">
- <xs:annotation>
- <xs:documentation>Element used to decorate an AuthenticationProvider bean to add it to the
- internal AuthenticationManager maintained by the namespace.</xs:documentation>
- </xs:annotation>
- <xs:complexType/>
- </xs:element>
- <xs:element name="user-service" substitutionGroup="security:any-user-service">
- <xs:annotation>
- <xs:documentation>Creates an in-memory UserDetailsService from a properties file or a list of
- "user" child elements.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="security:user"/>
- </xs:sequence>
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
- context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attributeGroup ref="security:properties-file"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="properties-file">
- <xs:attribute name="properties" type="xs:string"/>
- </xs:attributeGroup>
- <xs:element name="user">
- <xs:annotation>
- <xs:documentation>Represents a user in the application.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:user.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="user.attlist">
- <xs:attribute name="name" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>The username assigned to the user.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="password" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>The password assigned to the user. This may be hashed if the corresponding
- authentication provider supports hashing (remember to set the "hash" attribute of the
- "user-service" element).</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="authorities" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>One of more authorities granted to the user. Separate authorities with a
- comma (but no space). For example, "ROLE_USER,ROLE_ADMINISTRATOR"</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="locked" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Can be set to "true" to mark an account as locked and
- unusable.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="disabled" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Can be set to "true" to mark an account as disabled and
- unusable.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="jdbc-user-service" substitutionGroup="security:any-user-service">
- <xs:annotation>
- <xs:documentation>Causes creation of a JDBC-based UserDetailsService.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
- context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attributeGroup ref="security:jdbc-user-service.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="jdbc-user-service.attlist">
- <xs:attribute name="data-source-ref" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>The bean ID of the DataSource which provides the required
- tables.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="cache-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Defines a reference to a cache for use with a
- UserDetailsService.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="users-by-username-query" type="xs:string">
- <xs:annotation>
- <xs:documentation>An SQL statement to query a username, password, and enabled status given a
- username</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="authorities-by-username-query" type="xs:string">
- <xs:annotation>
- <xs:documentation>An SQL statement to query for a user's granted authorities given a
- username.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-authorities-by-username-query" type="xs:string">
- <xs:annotation>
- <xs:documentation>An SQL statement to query user's group authorities given a
- username.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="role-prefix" type="xs:string">
- <xs:annotation>
- <xs:documentation>A non-empty string prefix that will be added to role strings loaded from
- persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the
- default is non-empty.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="any-user-service" abstract="true"/>
- <xs:group name="custom-filter">
- <xs:sequence>
- <xs:element minOccurs="0" ref="security:custom-filter"/>
- </xs:sequence>
- </xs:group>
- <xs:element name="custom-filter">
- <xs:annotation>
- <xs:documentation>Used to indicate that a filter bean declaration should be incorporated into
- the security filter chain. If neither the 'after' or 'before' options are supplied, then the
- filter must implement the Ordered interface directly. </xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attribute name="after" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The filter immediately after which the custom-filter should be placed in
- the chain. This feature will only be needed by advanced users who wish to mix their own
- filters into the security filter chain and have some knowledge of the standard Spring
- Security filters. The filter names map to specific Spring Security implementation
- filters. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="before" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The filter immediately before which the custom-filter should be placed
- in the chain</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="position" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The explicit position at which the custom-filter should be placed in the
- chain. Use if you are replacing a standard filter.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="after">
- <xs:attribute name="after" use="required" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The filter immediately after which the custom-filter should be placed in
- the chain. This feature will only be needed by advanced users who wish to mix their own
- filters into the security filter chain and have some knowledge of the standard Spring
- Security filters. The filter names map to specific Spring Security implementation filters.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="before">
- <xs:attribute name="before" use="required" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The filter immediately before which the custom-filter should be placed in
- the chain</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="position">
- <xs:attribute name="position" use="required" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The explicit position at which the custom-filter should be placed in the
- chain. Use if you are replacing a standard filter.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:simpleType name="named-security-filter">
- <xs:restriction base="xs:token">
- <xs:enumeration value="FIRST"/>
- <xs:enumeration value="CHANNEL_FILTER"/>
- <xs:enumeration value="CONCURRENT_SESSION_FILTER"/>
- <xs:enumeration value="SESSION_CONTEXT_INTEGRATION_FILTER"/>
- <xs:enumeration value="LOGOUT_FILTER"/>
- <xs:enumeration value="X509_FILTER"/>
- <xs:enumeration value="PRE_AUTH_FILTER"/>
- <xs:enumeration value="CAS_PROCESSING_FILTER"/>
- <xs:enumeration value="AUTHENTICATION_PROCESSING_FILTER"/>
- <xs:enumeration value="OPENID_PROCESSING_FILTER"/>
- <xs:enumeration value="BASIC_PROCESSING_FILTER"/>
- <xs:enumeration value="SERVLET_API_SUPPORT_FILTER"/>
- <xs:enumeration value="REMEMBER_ME_FILTER"/>
- <xs:enumeration value="ANONYMOUS_FILTER"/>
- <xs:enumeration value="EXCEPTION_TRANSLATION_FILTER"/>
- <xs:enumeration value="NTLM_FILTER"/>
- <xs:enumeration value="FILTER_SECURITY_INTERCEPTOR"/>
- <xs:enumeration value="SWITCH_USER_FILTER"/>
- <xs:enumeration value="LAST"/>
- </xs:restriction>
- </xs:simpleType>
-</xs:schema>
diff --git a/dist/spring-security-config/org/springframework/security/config/spring-security-2.0.xsd b/dist/spring-security-config/org/springframework/security/config/spring-security-2.0.xsd
deleted file mode 100644
index 1106f7a..0000000
--- a/dist/spring-security-config/org/springframework/security/config/spring-security-2.0.xsd
+++ /dev/null
@@ -1,1251 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
- xmlns:security="http://www.springframework.org/schema/security" elementFormDefault="qualified"
- targetNamespace="http://www.springframework.org/schema/security">
- <xs:attributeGroup name="hash">
- <xs:attribute name="hash" use="required">
- <xs:annotation>
- <xs:documentation>Defines the hashing algorithm used on user passwords. We recommend
- strongly against using MD4, as it is a very weak hashing algorithm.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="plaintext"/>
- <xs:enumeration value="sha"/>
- <xs:enumeration value="md5"/>
- <xs:enumeration value="md4"/>
- <xs:enumeration value="{sha}"/>
- <xs:enumeration value="{ssha}"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="base64">
- <xs:attribute name="base64" use="required">
- <xs:annotation>
- <xs:documentation>Whether a string should be base64 encoded</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="true"/>
- <xs:enumeration value="false"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="path-type">
- <xs:attribute name="path-type" use="required">
- <xs:annotation>
- <xs:documentation>Defines the type of pattern used to specify URL paths (either JDK
- 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if
- unspecified.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="ant"/>
- <xs:enumeration value="regex"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="port">
- <xs:attribute name="port" use="required" type="xs:integer">
- <xs:annotation>
- <xs:documentation>Specifies an IP port number. Used to configure an embedded LDAP server,
- for example.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="url">
- <xs:attribute name="url" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Specifies a URL.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="id">
- <xs:attribute name="id" use="required" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
- context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="ref">
- <xs:attribute name="ref" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="cache-ref">
- <xs:attribute name="cache-ref" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Defines a reference to a cache for use with a
- UserDetailsService.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-service-ref">
- <xs:attribute name="user-service-ref" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean)
- Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="password-encoder.attlist">
- <xs:attribute name="ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="hash">
- <xs:annotation>
- <xs:documentation>Defines the hashing algorithm used on user passwords. We recommend
- strongly against using MD4, as it is a very weak hashing algorithm.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="plaintext"/>
- <xs:enumeration value="sha"/>
- <xs:enumeration value="md5"/>
- <xs:enumeration value="md4"/>
- <xs:enumeration value="{sha}"/>
- <xs:enumeration value="{ssha}"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="base64">
- <xs:annotation>
- <xs:documentation>Whether a string should be base64 encoded</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="true"/>
- <xs:enumeration value="false"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-property">
- <xs:attribute name="user-property" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>A property of the UserDetails object which will be used as salt by a
- password encoder. Typically something like "username" might be used. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="system-wide">
- <xs:attribute name="system-wide" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>A single value that will be used as the salt for a password encoder.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:simpleType name="boolean">
- <xs:restriction base="xs:token">
- <xs:enumeration value="true"/>
- <xs:enumeration value="false"/>
- </xs:restriction>
- </xs:simpleType>
- <xs:element name="ldap-server">
- <xs:annotation>
- <xs:documentation>Defines an LDAP server location or starts an embedded server. The url
- indicates the location of a remote server. If no url is given, an embedded server will be
- started, listening on the supplied port number. The port is optional and defaults to 33389.
- A Spring LDAP ContextSource bean will be registered for the server with the id supplied.
- </xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:ldap-server.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="ldap-server.attlist">
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
- context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="url" type="xs:string">
- <xs:annotation>
- <xs:documentation>Specifies a URL.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="port" type="xs:integer">
- <xs:annotation>
- <xs:documentation>Specifies an IP port number. Used to configure an embedded LDAP server,
- for example.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="manager-dn" type="xs:string">
- <xs:annotation>
- <xs:documentation>Username (DN) of the "manager" user identity which will be used to
- authenticate to a (non-embedded) LDAP server. If omitted, anonymous access will be used.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="manager-password" type="xs:string"/>
- <xs:attribute name="ldif" type="xs:string">
- <xs:annotation>
- <xs:documentation>Explicitly specifies an ldif file resource to load into an embedded LDAP
- server</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="root" type="xs:string">
- <xs:annotation>
- <xs:documentation>Optional root suffix for the embedded LDAP server. Default is
- "dc=springframework,dc=org"</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="ldap-server-ref-attribute">
- <xs:attribute name="server-ref" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>The optional server to use. If omitted, and a default LDAP server is
- registered (using <ldap-server> with no Id), that server will be used.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="group-search-filter-attribute">
- <xs:attribute name="group-search-filter" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Group search filter. Defaults to (uniqueMember={0}). The substituted
- parameter is the DN of the user.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="group-search-base-attribute">
- <xs:attribute name="group-search-base" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Search base for group membership searches. Defaults to
- "" (searching from the root).</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-search-filter-attribute">
- <xs:attribute name="user-search-filter" use="required" type="xs:string"/>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-search-base-attribute">
- <xs:attribute name="user-search-base" type="xs:string">
- <xs:annotation>
- <xs:documentation>Search base for user searches. Defaults to "".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="group-role-attribute-attribute">
- <xs:attribute name="group-role-attribute" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>The LDAP attribute name which contains the role name which will be used
- within Spring Security. Defaults to "cn".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="ldap-user-service" substitutionGroup="security:any-user-service">
- <xs:complexType>
- <xs:attributeGroup ref="security:ldap-us.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="ldap-us.attlist">
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
- context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="server-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>The optional server to use. If omitted, and a default LDAP server is
- registered (using <ldap-server> with no Id), that server will be used.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-search-filter" type="xs:string"/>
- <xs:attributeGroup ref="security:user-search-base-attribute"/>
- <xs:attribute name="group-search-filter" type="xs:string">
- <xs:annotation>
- <xs:documentation>Group search filter. Defaults to (uniqueMember={0}). The substituted
- parameter is the DN of the user.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-search-base" type="xs:string">
- <xs:annotation>
- <xs:documentation>Search base for group membership searches. Defaults to
- "ou=groups".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-role-attribute" type="xs:string">
- <xs:annotation>
- <xs:documentation>The LDAP attribute name which contains the role name which will be used
- within Spring Security. Defaults to "cn".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="cache-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Defines a reference to a cache for use with a
- UserDetailsService.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="ldap-authentication-provider">
- <xs:annotation>
- <xs:documentation>Sets up an ldap authentication provider</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="password-compare">
- <xs:annotation>
- <xs:documentation>Specifies that an LDAP provider should use an LDAP compare operation
- of the user's password to authenticate the user</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="password-encoder">
- <xs:annotation>
- <xs:documentation>element which defines a password encoding strategy. Used by an
- authentication provider to convert submitted passwords to hashed versions, for
- example.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="salt-source">
- <xs:complexType>
- <xs:attribute name="user-property" type="xs:string">
- <xs:annotation>
- <xs:documentation>A property of the UserDetails object which will be
- used as salt by a password encoder. Typically something like
- "username" might be used. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="system-wide" type="xs:string">
- <xs:annotation>
- <xs:documentation>A single value that will be used as the salt for a
- password encoder. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:password-encoder.attlist"/>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:password-compare.attlist"/>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:ldap-ap.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="ldap-ap.attlist">
- <xs:attribute name="server-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>The optional server to use. If omitted, and a default LDAP server is
- registered (using <ldap-server> with no Id), that server will be used.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attributeGroup ref="security:user-search-base-attribute"/>
- <xs:attribute name="user-search-filter" type="xs:string"/>
- <xs:attribute name="group-search-base" type="xs:string">
- <xs:annotation>
- <xs:documentation>Search base for group membership searches. Defaults to
- "ou=groups".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-search-filter" type="xs:string">
- <xs:annotation>
- <xs:documentation>Group search filter. Defaults to (uniqueMember={0}). The substituted
- parameter is the DN of the user.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-role-attribute" type="xs:string">
- <xs:annotation>
- <xs:documentation>The LDAP attribute name which contains the role name which will be used
- within Spring Security. Defaults to "cn".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-dn-pattern" type="xs:string">
- <xs:annotation>
- <xs:documentation>A specific pattern used to build the user's DN, for example
- "uid={0},ou=people". The key "{0}" must be present and will be substituted with the
- username.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="password-compare.attlist">
- <xs:attribute name="password-attribute" type="xs:string">
- <xs:annotation>
- <xs:documentation>The attribute in the directory which contains the user password. Defaults
- to "userPassword".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="hash">
- <xs:annotation>
- <xs:documentation>Defines the hashing algorithm used on user passwords. We recommend
- strongly against using MD4, as it is a very weak hashing algorithm.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="plaintext"/>
- <xs:enumeration value="sha"/>
- <xs:enumeration value="md5"/>
- <xs:enumeration value="md4"/>
- <xs:enumeration value="{sha}"/>
- <xs:enumeration value="{ssha}"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="intercept-methods">
- <xs:annotation>
- <xs:documentation>Can be used inside a bean definition to add a security interceptor to the
- bean and set up access configuration attributes for the bean's methods</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="security:protect"/>
- </xs:sequence>
- <xs:attributeGroup ref="security:intercept-methods.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="intercept-methods.attlist">
- <xs:attribute name="access-decision-manager-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Optional AccessDecisionManager bean ID to be used by the created method
- security interceptor.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="protect">
- <xs:annotation>
- <xs:documentation>Defines a protected method and the access control configuration attributes
- that apply to it. We strongly advise you NOT to mix "protect" declarations with any services
- provided "global-method-security".</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:protect.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="protect.attlist">
- <xs:attribute name="method" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>A method name</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Access configuration attributes list that applies to the method, e.g.
- "ROLE_A,ROLE_B".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="global-method-security">
- <xs:annotation>
- <xs:documentation>Provides method security for all beans registered in the Spring application
- context. Specifically, beans will be scanned for Spring Security annotations and/or matches
- with the ordered list of "protect-pointcut" sub-elements. Where there is a match, the beans
- will automatically be proxied and security authorization applied to the methods accordingly.
- If you use and enable all three sources of method security metadata (ie "protect-pointcut"
- declarations, @Secured and also JSR 250 security annotations), the metadata sources will be
- queried in that order. In practical terms, this enables you to use XML to override method
- security metadata expressed by way of @Secured annotations, with @Secured annotations
- overriding method security metadata expressed by JSR 250 annotations. It is perfectly
- acceptable to mix and match, with a given Java type using a combination of XML, @Secured and
- JSR 250 to express method security metadata (albeit on different
- methods).</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" name="protect-pointcut">
- <xs:annotation>
- <xs:documentation>Defines a protected pointcut and the access control configuration
- attributes that apply to it. Every bean registered in the Spring application context
- that provides a method that matches the pointcut will receive security
- authorization.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:protect-pointcut.attlist"/>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:global-method-security.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="global-method-security.attlist">
- <xs:attribute name="secured-annotations">
- <xs:annotation>
- <xs:documentation>Specifies whether the use of Spring Security's @Secured annotations should
- be enabled for this application context. Please ensure you have the
- spring-security-tiger-xxx.jar on the classpath. Defaults to "disabled".</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="disabled"/>
- <xs:enumeration value="enabled"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="jsr250-annotations">
- <xs:annotation>
- <xs:documentation>Specifies whether JSR-250 style attributes are to be used (for example
- "RolesAllowed"). This will require the javax.annotation.security classes on the classpath.
- Defaults to "disabled".</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="disabled"/>
- <xs:enumeration value="enabled"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="access-decision-manager-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Optional AccessDecisionManager bean ID to override the default used for
- method security.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="protect-pointcut.attlist">
- <xs:attribute name="expression" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>An AspectJ expression, including the 'execution' keyword. For example,
- 'execution(int com.foo.TargetObject.countLength(String))' (without the
- quotes).</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>Access configuration attributes list that applies to all methods matching
- the pointcut, e.g. "ROLE_A,ROLE_B"</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="http">
- <xs:annotation>
- <xs:documentation>Container element for HTTP security configuration</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element name="intercept-url">
- <xs:annotation>
- <xs:documentation>Specifies the access attributes and/or filter list for a particular
- set of URLs.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:intercept-url.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="form-login">
- <xs:annotation>
- <xs:documentation>Sets up a form login configuration for authentication with a username
- and password</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:form-login.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:element ref="security:openid-login"/>
- <xs:element name="x509">
- <xs:annotation>
- <xs:documentation>Adds support for X.509 client authentication.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:x509.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="http-basic">
- <xs:annotation>
- <xs:documentation>Adds support for basic authentication (this is an element to permit
- future expansion, such as supporting an "ignoreFailure" attribute)</xs:documentation>
- </xs:annotation>
- <xs:complexType/>
- </xs:element>
- <xs:element name="logout">
- <xs:annotation>
- <xs:documentation>Incorporates a logout processing filter. Most web applications require
- a logout filter, although you may not require one if you write a controller to
- provider similar logic.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:logout.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="concurrent-session-control">
- <xs:annotation>
- <xs:documentation>Adds support for concurrent session control, allowing limits to be
- placed on the number of sessions a user can have.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:concurrent-sessions.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="remember-me">
- <xs:complexType>
- <xs:attributeGroup ref="security:remember-me.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="anonymous">
- <xs:annotation>
- <xs:documentation>Adds support for automatically granting all anonymous web requests a
- particular principal identity and a corresponding granted
- authority.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:anonymous.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="port-mappings">
- <xs:annotation>
- <xs:documentation>Defines the list of mappings between http and https ports for use in
- redirects</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="security:port-mapping"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- </xs:choice>
- <xs:attributeGroup ref="security:http.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="http.attlist">
- <xs:attribute name="auto-config" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Automatically registers a login form, BASIC authentication, anonymous
- authentication, logout services, remember-me and servlet-api-integration. If set to
- "true", all of these capabilities are added (although you can still customize the
- configuration of each by providing the respective element). If unspecified, defaults to
- "false".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="create-session">
- <xs:annotation>
- <xs:documentation>Controls the eagerness with which an HTTP session is created. If not set,
- defaults to "ifRequired".</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="ifRequired"/>
- <xs:enumeration value="always"/>
- <xs:enumeration value="never"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="path-type">
- <xs:annotation>
- <xs:documentation>Defines the type of pattern used to specify URL paths (either JDK
- 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if
- unspecified.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="ant"/>
- <xs:enumeration value="regex"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="lowercase-comparisons" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Whether test URLs should be converted to lower case prior to comparing
- with defined path patterns. If unspecified, defaults to "true".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="servlet-api-provision" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Provides versions of HttpServletRequest security methods such as
- isUserInRole() and getPrincipal() which are implemented by accessing the Spring
- SecurityContext. Defaults to "true".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access-decision-manager-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Optional attribute specifying the ID of the AccessDecisionManager
- implementation which should be used for authorizing HTTP requests.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="realm" type="xs:string">
- <xs:annotation>
- <xs:documentation>Optional attribute specifying the realm name that will be used for all
- authentication features that require a realm name (eg BASIC and Digest authentication). If
- unspecified, defaults to "Spring Security Application".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="session-fixation-protection">
- <xs:annotation>
- <xs:documentation>Indicates whether an existing session should be invalidated when a user
- authenticates and a new session started. If set to "none" no change will be made.
- "newSession" will create a new empty session. "migrateSession" will create a new session
- and copy the session attributes to the new session. Defaults to
- "migrateSession".</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="none"/>
- <xs:enumeration value="newSession"/>
- <xs:enumeration value="migrateSession"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="entry-point-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Allows a customized AuthenticationEntryPoint to be
- used.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="once-per-request" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Corresponds to the observeOncePerRequest property of
- FilterSecurityInterceptor. Defaults to "false"</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access-denied-page" type="xs:string">
- <xs:annotation>
- <xs:documentation>Allows the access denied page to be set (the user will be redirected here
- if an AccessDeniedException is raised).</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="intercept-url.attlist">
- <xs:attribute name="pattern" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>The pattern which defines the URL path. The content will depend on the
- type set in the containing http element, so will default to ant path
- syntax.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access" type="xs:string">
- <xs:annotation>
- <xs:documentation>The access configuration attributes that apply for the configured
- path.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="method">
- <xs:annotation>
- <xs:documentation>The HTTP Method for which the access configuration attributes should
- apply. If not specified, the attributes will apply to any method.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="GET"/>
- <xs:enumeration value="DELETE"/>
- <xs:enumeration value="HEAD"/>
- <xs:enumeration value="OPTIONS"/>
- <xs:enumeration value="POST"/>
- <xs:enumeration value="PUT"/>
- <xs:enumeration value="TRACE"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="filters">
- <xs:annotation>
- <xs:documentation>The filter list for the path. Currently can be set to "none" to remove a
- path from having any filters applied. The full filter stack (consisting of all defined
- filters, will be applied to any other paths).</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="none"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="requires-channel">
- <xs:annotation>
- <xs:documentation>Used to specify that a URL must be accessed over http or
- https</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="http"/>
- <xs:enumeration value="https"/>
- <xs:enumeration value="any"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="logout.attlist">
- <xs:attribute name="logout-url" type="xs:string">
- <xs:annotation>
- <xs:documentation>Specifies the URL that will cause a logout. Spring Security will
- initialize a filter that responds to this particular URL. Defaults to
- /j_spring_security_logout if unspecified.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="logout-success-url" type="xs:string">
- <xs:annotation>
- <xs:documentation>Specifies the URL to display once the user has logged out. If not
- specified, defaults to /.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="invalidate-session" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Specifies whether a logout also causes HttpSession invalidation, which is
- generally desirable. If unspecified, defaults to true.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="form-login.attlist">
- <xs:attribute name="login-processing-url" type="xs:string">
- <xs:annotation>
- <xs:documentation>The URL that the login form is posted to. If unspecified, it defaults to
- /j_spring_security_check.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="default-target-url" type="xs:string">
- <xs:annotation>
- <xs:documentation>The URL that will be redirected to after successful authentication, if the
- user's previous action could not be resumed. This generally happens if the user visits a
- login page without having first requested a secured operation that triggers
- authentication. If unspecified, defaults to the root of the
- application.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="always-use-default-target" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Whether the user should always be redirected to the default-target-url
- after login. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="login-page" type="xs:string">
- <xs:annotation>
- <xs:documentation>The URL for the login page. If no login URL is specified, Spring Security
- will automatically create a login URL at /spring_security_login and a corresponding filter
- to render that login URL when requested.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="authentication-failure-url" type="xs:string">
- <xs:annotation>
- <xs:documentation>The URL for the login failure page. If no login failure URL is specified,
- Spring Security will automatically create a failure login URL at
- /spring_security_login?login_error and a corresponding filter to render that login failure
- URL when requested.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="openid-login">
- <xs:annotation>
- <xs:documentation>Sets up form login for authentication with an Open ID
- identity</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:form-login.attlist"/>
- <xs:attribute name="user-service-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean)
- Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="filter-chain-map">
- <xs:annotation>
- <xs:documentation>Used to explicitly configure a FilterChainProxy instance with a
- FilterChainMap</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" name="filter-chain">
- <xs:annotation>
- <xs:documentation>Used within filter-chain-map to define a specific URL pattern and the
- list of filters which apply to the URLs matching that pattern. When multiple
- filter-chain elements are used within a filter-chain-map element, the most specific
- patterns must be placed at the top of the list, with most general ones at the
- bottom.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:filter-chain.attlist"/>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:filter-chain-map.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="filter-chain-map.attlist">
- <xs:attributeGroup ref="security:path-type"/>
- </xs:attributeGroup>
- <xs:attributeGroup name="filter-chain.attlist">
- <xs:attribute name="pattern" use="required" type="xs:string"/>
- <xs:attribute name="filters" use="required" type="xs:string"/>
- </xs:attributeGroup>
- <xs:element name="filter-invocation-definition-source">
- <xs:annotation>
- <xs:documentation>Used to explicitly configure a FilterInvocationDefinitionSource bean for use
- with a FilterSecurityInterceptor. Usually only needed if you are configuring a
- FilterChainProxy explicitly, rather than using the <http> element. The
- intercept-url elements used should only contain pattern, method and access attributes. Any
- others will result in a configuration error. </xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" name="intercept-url">
- <xs:annotation>
- <xs:documentation>Specifies the access attributes and/or filter list for a particular
- set of URLs.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:intercept-url.attlist"/>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:fids.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="fids.attlist">
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
- context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="lowercase-comparisons" type="security:boolean">
- <xs:annotation>
- <xs:documentation>as for http element</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="path-type">
- <xs:annotation>
- <xs:documentation>Defines the type of pattern used to specify URL paths (either JDK
- 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if
- unspecified.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="ant"/>
- <xs:enumeration value="regex"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="concurrent-sessions.attlist">
- <xs:attribute name="max-sessions" type="xs:positiveInteger"/>
- <xs:attribute name="expired-url" type="xs:string"/>
- <xs:attribute name="exception-if-maximum-exceeded" type="security:boolean"/>
- <xs:attribute name="session-registry-alias" type="xs:string">
- <xs:annotation>
- <xs:documentation>Allows you to define an alias for the SessionRegistry bean in order to
- access it in your own configuration</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="remember-me.attlist">
- <xs:attribute name="key" type="xs:string"/>
- <xs:attribute name="token-repository-ref" type="xs:string"/>
- <xs:attribute name="data-source-ref" type="xs:string"/>
- <xs:attribute name="user-service-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean)
- Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="anonymous.attlist">
- <xs:attribute name="key" type="xs:string">
- <xs:annotation>
- <xs:documentation>The key shared between the provider and filter. This generally does not
- need to be set. If unset, it will default to "doesNotMatter".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="username" type="xs:string">
- <xs:annotation>
- <xs:documentation>The username that should be assigned to the anonymous request. This allows
- the principal to be identified, which may be important for logging and auditing. if unset,
- defaults to "anonymousUser".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="granted-authority" type="xs:string">
- <xs:annotation>
- <xs:documentation>The granted authority that should be assigned to the anonymous request.
- Commonly this is used to assign the anonymous request particular roles, which can
- subsequently be used in authorization decisions. If unset, defaults to
- "ROLE_ANONYMOUS".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="port-mapping">
- <xs:complexType>
- <xs:attributeGroup ref="security:http-port"/>
- <xs:attributeGroup ref="security:https-port"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="http-port">
- <xs:attribute name="http" use="required" type="xs:integer"/>
- </xs:attributeGroup>
- <xs:attributeGroup name="https-port">
- <xs:attribute name="https" use="required" type="xs:integer"/>
- </xs:attributeGroup>
- <xs:attributeGroup name="x509.attlist">
- <xs:attribute name="subject-principal-regex" type="xs:string">
- <xs:annotation>
- <xs:documentation>The regular expression used to obtain the username from the certificate's
- subject. Defaults to matching on the common name using the pattern
- "CN=(.*?),".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-service-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean)
- Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="authentication-manager">
- <xs:annotation>
- <xs:documentation>If you are using namespace configuration with Spring Security, an
- AuthenticationManager will automatically be registered. This element simple allows you to
- define an alias to allow you to reference the authentication-manager in your own beans.
- </xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:authman.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="authman.attlist">
- <xs:annotation>
- <xs:documentation>The alias you wish to use for the AuthenticationManager
- bean</xs:documentation>
- </xs:annotation>
- <xs:attribute name="alias" use="required" type="xs:ID"/>
- </xs:attributeGroup>
- <xs:element name="authentication-provider">
- <xs:annotation>
- <xs:documentation>Indicates that the contained user-service should be used as an
- authentication source. </xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="security:any-user-service"/>
- <xs:element name="password-encoder">
- <xs:annotation>
- <xs:documentation>element which defines a password encoding strategy. Used by an
- authentication provider to convert submitted passwords to hashed versions, for
- example.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="salt-source">
- <xs:complexType>
- <xs:attribute name="user-property" type="xs:string">
- <xs:annotation>
- <xs:documentation>A property of the UserDetails object which will be used as
- salt by a password encoder. Typically something like "username" might be
- used. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="system-wide" type="xs:string">
- <xs:annotation>
- <xs:documentation>A single value that will be used as the salt for a password
- encoder. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:password-encoder.attlist"/>
- </xs:complexType>
- </xs:element>
- </xs:choice>
- <xs:attributeGroup ref="security:ap.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="ap.attlist">
- <xs:attribute name="user-service-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean)
- Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="custom-authentication-provider">
- <xs:complexType/>
- </xs:element>
- <xs:element name="user-service" substitutionGroup="security:any-user-service">
- <xs:annotation>
- <xs:documentation>Creates an in-memory UserDetailsService from a properties file or a list of
- "user" child elements.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="security:user"/>
- </xs:sequence>
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
- context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attributeGroup ref="security:properties-file"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="properties-file">
- <xs:attribute name="properties" type="xs:string"/>
- </xs:attributeGroup>
- <xs:element name="user">
- <xs:annotation>
- <xs:documentation>Represents a user in the application.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attributeGroup ref="security:user.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="user.attlist">
- <xs:attribute name="name" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>The username assigned to the user.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="password" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>The password assigned to the user. This may be hashed if the corresponding
- authentication provider supports hashing (remember to set the "hash" attribute of the
- "user-service" element).</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="authorities" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>One of more authorities granted to the user. Separate authorities with a
- comma (but no space). For example, "ROLE_USER,ROLE_ADMINISTRATOR"</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="locked" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Can be set to "true" to mark an account as locked and
- unusable.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="jdbc-user-service" substitutionGroup="security:any-user-service">
- <xs:annotation>
- <xs:documentation>Causes creation of a JDBC-based UserDetailsService.</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
- context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attributeGroup ref="security:jdbc-user-service.attlist"/>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="jdbc-user-service.attlist">
- <xs:attribute name="data-source-ref" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>The bean ID of the DataSource which provides the required
- tables.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="cache-ref" type="xs:string">
- <xs:annotation>
- <xs:documentation>Defines a reference to a cache for use with a
- UserDetailsService.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="users-by-username-query" type="xs:string">
- <xs:annotation>
- <xs:documentation>An SQL statement to query a username, password, and enabled status given a
- username</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="authorities-by-username-query" type="xs:string">
- <xs:annotation>
- <xs:documentation>An SQL statement to query for a user's granted authorities given a
- username.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-authorities-by-username-query" type="xs:string">
- <xs:annotation>
- <xs:documentation>An SQL statement to query user's group authorities given a
- username.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="any-user-service" abstract="true"/>
- <xs:group name="custom-filter">
- <xs:sequence>
- <xs:element minOccurs="0" ref="security:custom-filter"/>
- </xs:sequence>
- </xs:group>
- <xs:element name="custom-filter">
- <xs:annotation>
- <xs:documentation>Used to indicate that a filter bean declaration should be incorporated into
- the security filter chain. If neither the 'after' or 'before' options are supplied, then the
- filter must implement the Ordered interface directly. </xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:attribute name="after" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The filter immediately after which the custom-filter should be placed in
- the chain. This feature will only be needed by advanced users who wish to mix their own
- filters into the security filter chain and have some knowledge of the standard Spring
- Security filters. The filter names map to specific Spring Security implementation
- filters. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="before" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The filter immediately before which the custom-filter should be placed
- in the chain</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="position" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The explicit position at which the custom-filter should be placed in the
- chain. Use if you are replacing a standard filter.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:attributeGroup name="after">
- <xs:attribute name="after" use="required" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The filter immediately after which the custom-filter should be placed in
- the chain. This feature will only be needed by advanced users who wish to mix their own
- filters into the security filter chain and have some knowledge of the standard Spring
- Security filters. The filter names map to specific Spring Security implementation filters.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="before">
- <xs:attribute name="before" use="required" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The filter immediately before which the custom-filter should be placed in
- the chain</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="position">
- <xs:attribute name="position" use="required" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The explicit position at which the custom-filter should be placed in the
- chain. Use if you are replacing a standard filter.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:simpleType name="named-security-filter">
- <xs:restriction base="xs:token">
- <xs:enumeration value="FIRST"/>
- <xs:enumeration value="CHANNEL_FILTER"/>
- <xs:enumeration value="CONCURRENT_SESSION_FILTER"/>
- <xs:enumeration value="SESSION_CONTEXT_INTEGRATION_FILTER"/>
- <xs:enumeration value="LOGOUT_FILTER"/>
- <xs:enumeration value="X509_FILTER"/>
- <xs:enumeration value="PRE_AUTH_FILTER"/>
- <xs:enumeration value="CAS_PROCESSING_FILTER"/>
- <xs:enumeration value="AUTHENTICATION_PROCESSING_FILTER"/>
- <xs:enumeration value="BASIC_PROCESSING_FILTER"/>
- <xs:enumeration value="SERVLET_API_SUPPORT_FILTER"/>
- <xs:enumeration value="REMEMBER_ME_FILTER"/>
- <xs:enumeration value="ANONYMOUS_FILTER"/>
- <xs:enumeration value="EXCEPTION_TRANSLATION_FILTER"/>
- <xs:enumeration value="NTLM_FILTER"/>
- <xs:enumeration value="FILTER_SECURITY_INTERCEPTOR"/>
- <xs:enumeration value="SWITCH_USER_FILTER"/>
- <xs:enumeration value="LAST"/>
- </xs:restriction>
- </xs:simpleType>
-</xs:schema>
diff --git a/dist/spring-security-config/org/springframework/security/config/spring-security-3.0.3.xsd b/dist/spring-security-config/org/springframework/security/config/spring-security-3.0.3.xsd
deleted file mode 100644
index 27bd5be..0000000
--- a/dist/spring-security-config/org/springframework/security/config/spring-security-3.0.3.xsd
+++ /dev/null
@@ -1,1381 +0,0 @@
-<?xml version="1.0"?>
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:security="http://www.springframework.org/schema/security" elementFormDefault="qualified" targetNamespace="http://www.springframework.org/schema/security">
- <xs:attributeGroup name="hash">
- <xs:attribute name="hash" use="required">
- <xs:annotation>
- <xs:documentation>Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="plaintext"/>
- <xs:enumeration value="sha"/>
- <xs:enumeration value="sha-256"/>
- <xs:enumeration value="md5"/>
- <xs:enumeration value="md4"/>
- <xs:enumeration value="{sha}"/>
- <xs:enumeration value="{ssha}"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="base64">
- <xs:attribute name="base64" use="required">
- <xs:annotation>
- <xs:documentation>Whether a string should be base64 encoded</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="true"/>
- <xs:enumeration value="false"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="path-type">
- <xs:attribute name="path-type" use="required">
- <xs:annotation>
- <xs:documentation>Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="ant"/>
- <xs:enumeration value="regex"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="port">
- <xs:attribute name="port" use="required" type="xs:positiveInteger">
- <xs:annotation>
- <xs:documentation>Specifies an IP port number. Used to configure an embedded LDAP server, for example.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="url">
- <xs:attribute name="url" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>Specifies a URL.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="id">
- <xs:attribute name="id" use="required" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="ref">
- <xs:attribute name="ref" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="cache-ref">
- <xs:attribute name="cache-ref" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>Defines a reference to a cache for use with a UserDetailsService.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-service-ref">
- <xs:attribute name="user-service-ref" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean) Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="data-source-ref">
- <xs:attribute name="data-source-ref" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>A reference to a DataSource bean</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="password-encoder.attlist">
- <xs:attribute name="ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="hash">
- <xs:annotation>
- <xs:documentation>Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="plaintext"/>
- <xs:enumeration value="sha"/>
- <xs:enumeration value="sha-256"/>
- <xs:enumeration value="md5"/>
- <xs:enumeration value="md4"/>
- <xs:enumeration value="{sha}"/>
- <xs:enumeration value="{ssha}"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="base64">
- <xs:annotation>
- <xs:documentation>Whether a string should be base64 encoded</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="true"/>
- <xs:enumeration value="false"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="user-property">
- <xs:attribute name="user-property" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="system-wide">
- <xs:attribute name="system-wide" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>A single value that will be used as the salt for a password encoder.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:simpleType name="boolean">
- <xs:restriction base="xs:token">
- <xs:enumeration value="true"/>
- <xs:enumeration value="false"/>
- </xs:restriction>
- </xs:simpleType>
- <xs:attributeGroup name="role-prefix">
- <xs:attribute name="role-prefix" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="use-expressions">
- <xs:attribute name="use-expressions" use="required" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Enables the use of expressions in the 'access' attributes in <intercept-url> elements rather than the traditional list of configuration attributes. Defaults to 'false'. If enabled, each attribute should contain a single boolean expression. If the expression evaluates to 'true', access will be granted.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="ldap-server"><xs:annotation>
- <xs:documentation>Defines an LDAP server location or starts an embedded server. The url indicates the location of a remote server. If no url is given, an embedded server will be started, listening on the supplied port number. The port is optional and defaults to 33389. A Spring LDAP ContextSource bean will be registered for the server with the id supplied.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:ldap-server.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="ldap-server.attlist">
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="url" type="xs:token">
- <xs:annotation>
- <xs:documentation>Specifies a URL.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="port" type="xs:positiveInteger">
- <xs:annotation>
- <xs:documentation>Specifies an IP port number. Used to configure an embedded LDAP server, for example.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="manager-dn" type="xs:string">
- <xs:annotation>
- <xs:documentation>Username (DN) of the "manager" user identity which will be used to authenticate to a (non-embedded) LDAP server. If omitted, anonymous access will be used.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="manager-password" type="xs:string">
- <xs:annotation>
- <xs:documentation>The password for the manager DN.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="ldif" type="xs:string">
- <xs:annotation>
- <xs:documentation>Explicitly specifies an ldif file resource to load into an embedded LDAP server</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="root" type="xs:string">
- <xs:annotation>
- <xs:documentation>Optional root suffix for the embedded LDAP server. Default is "dc=springframework,dc=org"</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="ldap-server-ref-attribute">
- <xs:attribute name="server-ref" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>The optional server to use. If omitted, and a default LDAP server is registered (using <ldap-server> with no Id), that server will be used.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="group-search-filter-attribute">
- <xs:attribute name="group-search-filter" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="group-search-base-attribute">
- <xs:attribute name="group-search-base" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>Search base for group membership searches. Defaults to "" (searching from the root).</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-search-filter-attribute">
- <xs:attribute name="user-search-filter" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>The LDAP filter used to search for users (optional). For example "(uid={0})". The substituted parameter is the user's login name.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-search-base-attribute">
- <xs:attribute name="user-search-base" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>Search base for user searches. Defaults to "". Only used with a 'user-search-filter'.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="group-role-attribute-attribute">
- <xs:attribute name="group-role-attribute" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-details-class-attribute">
- <xs:attribute name="user-details-class" use="required">
- <xs:annotation>
- <xs:documentation>Allows the objectClass of the user entry to be specified. If set, the framework will attempt to load standard attributes for the defined class into the returned UserDetails object</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="person"/>
- <xs:enumeration value="inetOrgPerson"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-context-mapper-attribute">
- <xs:attribute name="user-context-mapper-ref" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>Allows explicit customization of the loaded user object by specifying a UserDetailsContextMapper bean which will be called with the context information from the user's directory entry</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="ldap-user-service" substitutionGroup="security:any-user-service"><xs:complexType>
- <xs:attributeGroup ref="security:ldap-us.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="ldap-us.attlist">
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="server-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>The optional server to use. If omitted, and a default LDAP server is registered (using <ldap-server> with no Id), that server will be used.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-search-filter" type="xs:token">
- <xs:annotation>
- <xs:documentation>The LDAP filter used to search for users (optional). For example "(uid={0})". The substituted parameter is the user's login name.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-search-base" type="xs:token">
- <xs:annotation>
- <xs:documentation>Search base for user searches. Defaults to "". Only used with a 'user-search-filter'.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-search-filter" type="xs:token">
- <xs:annotation>
- <xs:documentation>Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-search-base" type="xs:token">
- <xs:annotation>
- <xs:documentation>Search base for group membership searches. Defaults to "" (searching from the root).</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-role-attribute" type="xs:token">
- <xs:annotation>
- <xs:documentation>The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="cache-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Defines a reference to a cache for use with a UserDetailsService.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="role-prefix" type="xs:token">
- <xs:annotation>
- <xs:documentation>A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-details-class">
- <xs:annotation>
- <xs:documentation>Allows the objectClass of the user entry to be specified. If set, the framework will attempt to load standard attributes for the defined class into the returned UserDetails object</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="person"/>
- <xs:enumeration value="inetOrgPerson"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="user-context-mapper-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Allows explicit customization of the loaded user object by specifying a UserDetailsContextMapper bean which will be called with the context information from the user's directory entry</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="ldap-ap.attlist">
- <xs:attribute name="server-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>The optional server to use. If omitted, and a default LDAP server is registered (using <ldap-server> with no Id), that server will be used.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-search-base" type="xs:token">
- <xs:annotation>
- <xs:documentation>Search base for user searches. Defaults to "". Only used with a 'user-search-filter'.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-search-filter" type="xs:token">
- <xs:annotation>
- <xs:documentation>The LDAP filter used to search for users (optional). For example "(uid={0})". The substituted parameter is the user's login name.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-search-base" type="xs:token">
- <xs:annotation>
- <xs:documentation>Search base for group membership searches. Defaults to "" (searching from the root).</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-search-filter" type="xs:token">
- <xs:annotation>
- <xs:documentation>Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-role-attribute" type="xs:token">
- <xs:annotation>
- <xs:documentation>The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-dn-pattern" type="xs:token">
- <xs:annotation>
- <xs:documentation>A specific pattern used to build the user's DN, for example "uid={0},ou=people". The key "{0}" must be present and will be substituted with the username.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="role-prefix" type="xs:token">
- <xs:annotation>
- <xs:documentation>A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-details-class">
- <xs:annotation>
- <xs:documentation>Allows the objectClass of the user entry to be specified. If set, the framework will attempt to load standard attributes for the defined class into the returned UserDetails object</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="person"/>
- <xs:enumeration value="inetOrgPerson"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="user-context-mapper-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Allows explicit customization of the loaded user object by specifying a UserDetailsContextMapper bean which will be called with the context information from the user's directory entry</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="password-compare.attlist">
- <xs:attribute name="password-attribute" type="xs:token">
- <xs:annotation>
- <xs:documentation>The attribute in the directory which contains the user password. Defaults to "userPassword".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="hash">
- <xs:annotation>
- <xs:documentation>Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="plaintext"/>
- <xs:enumeration value="sha"/>
- <xs:enumeration value="sha-256"/>
- <xs:enumeration value="md5"/>
- <xs:enumeration value="md4"/>
- <xs:enumeration value="{sha}"/>
- <xs:enumeration value="{ssha}"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="intercept-methods"><xs:annotation>
- <xs:documentation>Can be used inside a bean definition to add a security interceptor to the bean and set up access configuration attributes for the bean's methods</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" name="protect"><xs:annotation>
- <xs:documentation>Defines a protected method and the access control configuration attributes that apply to it. We strongly advise you NOT to mix "protect" declarations with any services provided "global-method-security".</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:protect.attlist"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:intercept-methods.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="intercept-methods.attlist">
- <xs:attribute name="access-decision-manager-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Optional AccessDecisionManager bean ID to be used by the created method security interceptor.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="protect.attlist">
- <xs:attribute name="method" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>A method name</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>Access configuration attributes list that applies to the method, e.g. "ROLE_A,ROLE_B".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="global-method-security"><xs:annotation>
- <xs:documentation>Provides method security for all beans registered in the Spring application context. Specifically, beans will be scanned for matches with the ordered list of "protect-pointcut" sub-elements, Spring Security annotations and/or. Where there is a match, the beans will automatically be proxied and security authorization applied to the methods accordingly. If you use and enable all four sources of method security metadata (ie "protect-pointcut" declarations, expression annotations, @Secured and also JSR250 security annotations), the metadata sources will be queried in that order. In practical terms, this enables you to use XML to override method security metadata expressed in annotations. If using annotations, the order of precedence is EL-based (@PreAuthorize etc.), @Secured and finally JSR-250.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:choice minOccurs="0">
- <xs:element name="pre-post-annotation-handling"><xs:annotation>
- <xs:documentation>Allows the default expression-based mechanism for handling Spring Security's pre and post invocation annotations (@PreFilter, @PreAuthorize, @PostFilter, @PostAuthorize) to be replace entirely. Only applies if these annotations are enabled.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element name="invocation-attribute-factory"><xs:annotation>
- <xs:documentation>Defines the PrePostInvocationAttributeFactory instance which is used to generate pre and post invocation metadata from the annotated methods.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:ref"/>
- </xs:complexType></xs:element>
- <xs:element name="pre-invocation-advice"><xs:complexType>
- <xs:attributeGroup ref="security:ref"/>
- </xs:complexType></xs:element>
- <xs:element name="post-invocation-advice"><xs:complexType>
- <xs:attributeGroup ref="security:ref"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- </xs:complexType></xs:element>
- <xs:element name="expression-handler"><xs:annotation>
- <xs:documentation>Defines the SecurityExpressionHandler instance which will be used if expression-based access-control is enabled. A default implementation (with no ACL support) will be used if not supplied.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:ref"/>
- </xs:complexType></xs:element>
- </xs:choice>
- <xs:element minOccurs="0" maxOccurs="unbounded" name="protect-pointcut"><xs:annotation>
- <xs:documentation>Defines a protected pointcut and the access control configuration attributes that apply to it. Every bean registered in the Spring application context that provides a method that matches the pointcut will receive security authorization.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:protect-pointcut.attlist"/>
- </xs:complexType></xs:element>
- <xs:element minOccurs="0" maxOccurs="unbounded" name="after-invocation-provider"><xs:annotation>
- <xs:documentation>Allows addition of extra AfterInvocationProvider beans which should be called by the MethodSecurityInterceptor created by global-method-security.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:ref"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:global-method-security.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="global-method-security.attlist">
- <xs:attribute name="pre-post-annotations">
- <xs:annotation>
- <xs:documentation>Specifies whether the use of Spring Security's pre and post invocation annotations (@PreFilter, @PreAuthorize, @PostFilter, @PostAuthorize) should be enabled for this application context. Defaults to "disabled".</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="disabled"/>
- <xs:enumeration value="enabled"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="secured-annotations">
- <xs:annotation>
- <xs:documentation>Specifies whether the use of Spring Security's @Secured annotations should be enabled for this application context. Defaults to "disabled".</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="disabled"/>
- <xs:enumeration value="enabled"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="jsr250-annotations">
- <xs:annotation>
- <xs:documentation>Specifies whether JSR-250 style attributes are to be used (for example "RolesAllowed"). This will require the javax.annotation.security classes on the classpath. Defaults to "disabled".</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="disabled"/>
- <xs:enumeration value="enabled"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="access-decision-manager-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Optional AccessDecisionManager bean ID to override the default used for method security.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="run-as-manager-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Optional RunAsmanager implementation which will be used by the configured MethodSecurityInterceptor</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="order" type="xs:token">
- <xs:annotation>
- <xs:documentation>Allows the advice "order" to be set for the method security interceptor.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="proxy-target-class" type="security:boolean"/>
- <xs:attribute name="mode">
- <xs:annotation>
- <xs:documentation>Can be used to specify that AspectJ should be used instead of the default Spring AOP. If set, secured classes must be woven with the AnnotationSecurityAspect from the spring-security-aspects module.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="aspectj"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
-
-
-
-
-
-
-
- <xs:attributeGroup name="protect-pointcut.attlist">
- <xs:attribute name="expression" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>An AspectJ expression, including the 'execution' keyword. For example, 'execution(int com.foo.TargetObject.countLength(String))' (without the quotes).</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>Access configuration attributes list that applies to all methods matching the pointcut, e.g. "ROLE_A,ROLE_B"</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="http"><xs:annotation>
- <xs:documentation>Container element for HTTP security configuration</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element name="intercept-url"><xs:annotation>
- <xs:documentation>Specifies the access attributes and/or filter list for a particular set of URLs.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:intercept-url.attlist"/>
- </xs:complexType></xs:element>
- <xs:element name="access-denied-handler"><xs:annotation>
- <xs:documentation>Defines the access-denied strategy that should be used. An access denied page can be defined or a reference to an AccessDeniedHandler instance.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:access-denied-handler.attlist"/>
- </xs:complexType></xs:element>
- <xs:element name="form-login"><xs:annotation>
- <xs:documentation>Sets up a form login configuration for authentication with a username and password</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:form-login.attlist"/>
- </xs:complexType></xs:element>
- <xs:element name="openid-login"><xs:annotation>
- <xs:documentation>Sets up form login for authentication with an Open ID identity</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="security:attribute-exchange"/>
- </xs:sequence>
- <xs:attributeGroup ref="security:form-login.attlist"/>
- <xs:attribute name="user-service-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean) Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:complexType></xs:element>
- <xs:element name="x509"><xs:annotation>
- <xs:documentation>Adds support for X.509 client authentication.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:x509.attlist"/>
- </xs:complexType></xs:element>
- <xs:element name="http-basic"><xs:annotation>
- <xs:documentation>Adds support for basic authentication (this is an element to permit future expansion, such as supporting an "ignoreFailure" attribute)</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:http-basic.attlist"/>
- </xs:complexType></xs:element>
- <xs:element name="logout"><xs:annotation>
- <xs:documentation>Incorporates a logout processing filter. Most web applications require a logout filter, although you may not require one if you write a controller to provider similar logic.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:logout.attlist"/>
- </xs:complexType></xs:element>
- <xs:element name="session-management"><xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="concurrency-control"><xs:annotation>
- <xs:documentation>Enables concurrent session control, limiting the number of authenticated sessions a user may have at the same time.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:concurrency-control.attlist"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:session-management.attlist"/>
- </xs:complexType></xs:element>
- <xs:element name="remember-me"><xs:annotation>
- <xs:documentation>Sets up remember-me authentication. If used with the "key" attribute (or no attributes) the cookie-only implementation will be used. Specifying "token-repository-ref" or "remember-me-data-source-ref" will use the more secure, persisten token approach.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:remember-me.attlist"/>
- </xs:complexType></xs:element>
- <xs:element name="anonymous"><xs:annotation>
- <xs:documentation>Adds support for automatically granting all anonymous web requests a particular principal identity and a corresponding granted authority.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:anonymous.attlist"/>
- </xs:complexType></xs:element>
- <xs:element name="port-mappings"><xs:annotation>
- <xs:documentation>Defines the list of mappings between http and https ports for use in redirects</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" name="port-mapping"><xs:complexType>
- <xs:attributeGroup ref="security:http-port"/>
- <xs:attributeGroup ref="security:https-port"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- </xs:complexType></xs:element>
- <xs:element ref="security:custom-filter"/>
- <xs:element ref="security:request-cache"/>
- </xs:choice>
- <xs:attributeGroup ref="security:http.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="http.attlist">
- <xs:attribute name="auto-config" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Automatically registers a login form, BASIC authentication, anonymous authentication, logout services, remember-me and servlet-api-integration. If set to "true", all of these capabilities are added (although you can still customize the configuration of each by providing the respective element). If unspecified, defaults to "false".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="use-expressions" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Enables the use of expressions in the 'access' attributes in <intercept-url> elements rather than the traditional list of configuration attributes. Defaults to 'false'. If enabled, each attribute should contain a single boolean expression. If the expression evaluates to 'true', access will be granted.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="create-session">
- <xs:annotation>
- <xs:documentation>Controls the eagerness with which an HTTP session is created. If not set, defaults to "ifRequired". Note that if a custom SecurityContextRepository is set using security-context-repository-ref, then the only value which can be set is "always". Otherwise the session creation behaviour will be determined by the repository bean implementation.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="ifRequired"/>
- <xs:enumeration value="always"/>
- <xs:enumeration value="never"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="security-context-repository-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>A reference to a SecurityContextRepository bean. This can be used to customize how the SecurityContext is stored between requests.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="path-type">
- <xs:annotation>
- <xs:documentation>Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="ant"/>
- <xs:enumeration value="regex"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="lowercase-comparisons" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Whether test URLs should be converted to lower case prior to comparing with defined path patterns. If unspecified, defaults to "true".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="servlet-api-provision" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Provides versions of HttpServletRequest security methods such as isUserInRole() and getPrincipal() which are implemented by accessing the Spring SecurityContext. Defaults to "true".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access-decision-manager-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Optional attribute specifying the ID of the AccessDecisionManager implementation which should be used for authorizing HTTP requests.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="realm" type="xs:token">
- <xs:annotation>
- <xs:documentation>Optional attribute specifying the realm name that will be used for all authentication features that require a realm name (eg BASIC and Digest authentication). If unspecified, defaults to "Spring Security Application".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="entry-point-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Allows a customized AuthenticationEntryPoint to be set on the ExceptionTranslationFilter.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="once-per-request" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Corresponds to the observeOncePerRequest property of FilterSecurityInterceptor. Defaults to "true"</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access-denied-page" type="xs:token">
- <xs:annotation>
- <xs:documentation>Deprecated in favour of the access-denied-handler element.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="disable-url-rewriting" type="security:boolean">
- <xs:annotation>
- <xs:documentation/>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="access-denied-handler.attlist">
- <xs:attribute name="ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="error-page" type="xs:token">
- <xs:annotation>
- <xs:documentation>The access denied page that an authenticated user will be redirected to if they request a page which they don't have the authority to access.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="access-denied-handler-page">
- <xs:attribute name="error-page" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>The access denied page that an authenticated user will be redirected to if they request a page which they don't have the authority to access.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="intercept-url.attlist">
- <xs:attribute name="pattern" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>The pattern which defines the URL path. The content will depend on the type set in the containing http element, so will default to ant path syntax.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access" type="xs:token">
- <xs:annotation>
- <xs:documentation>The access configuration attributes that apply for the configured path.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="method">
- <xs:annotation>
- <xs:documentation>The HTTP Method for which the access configuration attributes should apply. If not specified, the attributes will apply to any method.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="GET"/>
- <xs:enumeration value="DELETE"/>
- <xs:enumeration value="HEAD"/>
- <xs:enumeration value="OPTIONS"/>
- <xs:enumeration value="POST"/>
- <xs:enumeration value="PUT"/>
- <xs:enumeration value="TRACE"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="filters">
- <xs:annotation>
- <xs:documentation>The filter list for the path. Currently can be set to "none" to remove a path from having any filters applied. The full filter stack (consisting of all filters created by the namespace configuration, and any added using 'custom-filter'), will be applied to any other paths.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="none"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="requires-channel" type="xs:token">
- <xs:annotation>
- <xs:documentation>Used to specify that a URL must be accessed over http or https, or that there is no preference. The value should be "http", "https" or "any", respectively.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="logout.attlist">
- <xs:attribute name="logout-url" type="xs:token">
- <xs:annotation>
- <xs:documentation>Specifies the URL that will cause a logout. Spring Security will initialize a filter that responds to this particular URL. Defaults to /j_spring_security_logout if unspecified.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="logout-success-url" type="xs:token">
- <xs:annotation>
- <xs:documentation>Specifies the URL to display once the user has logged out. If not specified, defaults to /.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="invalidate-session" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Specifies whether a logout also causes HttpSession invalidation, which is generally desirable. If unspecified, defaults to true.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="success-handler-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>A reference to a LogoutSuccessHandler implementation which will be used to determine the destination to which the user is taken after logging out.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="request-cache"><xs:annotation>
- <xs:documentation>Allow the RequestCache used for saving requests during the login process to be set</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:ref"/>
- </xs:complexType></xs:element>
-
- <xs:attributeGroup name="form-login.attlist">
- <xs:attribute name="login-processing-url" type="xs:token">
- <xs:annotation>
- <xs:documentation>The URL that the login form is posted to. If unspecified, it defaults to /j_spring_security_check.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="default-target-url" type="xs:token">
- <xs:annotation>
- <xs:documentation>The URL that will be redirected to after successful authentication, if the user's previous action could not be resumed. This generally happens if the user visits a login page without having first requested a secured operation that triggers authentication. If unspecified, defaults to the root of the application.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="always-use-default-target" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Whether the user should always be redirected to the default-target-url after login.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="login-page" type="xs:token">
- <xs:annotation>
- <xs:documentation>The URL for the login page. If no login URL is specified, Spring Security will automatically create a login URL at /spring_security_login and a corresponding filter to render that login URL when requested.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="authentication-failure-url" type="xs:token">
- <xs:annotation>
- <xs:documentation>The URL for the login failure page. If no login failure URL is specified, Spring Security will automatically create a failure login URL at /spring_security_login?login_error and a corresponding filter to render that login failure URL when requested.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="authentication-success-handler-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Reference to an AuthenticationSuccessHandler bean which should be used to handle a successful authentication request. Should not be used in combination with default-target-url (or always-use-default-target-url) as the implementation should always deal with navigation to the subsequent destination</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="authentication-failure-handler-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Reference to an AuthenticationFailureHandler bean which should be used to handle a failed authentication request. Should not be used in combination with authentication-failure-url as the implementation should always deal with navigation to the subsequent destination</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:element name="attribute-exchange"><xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="security:openid-attribute"/>
- </xs:sequence>
- </xs:complexType></xs:element>
- <xs:element name="openid-attribute"><xs:complexType>
- <xs:attributeGroup ref="security:openid-attribute.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="openid-attribute.attlist">
- <xs:attribute name="name" use="required" type="xs:token"/>
- <xs:attribute name="type" use="required" type="xs:token"/>
- <xs:attribute name="required" type="security:boolean"/>
- <xs:attribute name="count" type="xs:int"/>
- </xs:attributeGroup>
- <xs:element name="filter-chain-map"><xs:annotation>
- <xs:documentation>Used to explicitly configure a FilterChainProxy instance with a FilterChainMap</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" name="filter-chain"><xs:annotation>
- <xs:documentation>Used within filter-chain-map to define a specific URL pattern and the list of filters which apply to the URLs matching that pattern. When multiple filter-chain elements are used within a filter-chain-map element, the most specific patterns must be placed at the top of the list, with most general ones at the bottom.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:filter-chain.attlist"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:filter-chain-map.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="filter-chain-map.attlist">
- <xs:attributeGroup ref="security:path-type"/>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="filter-chain.attlist">
- <xs:attribute name="pattern" use="required" type="xs:token"/>
- <xs:attribute name="filters" use="required" type="xs:token"/>
- </xs:attributeGroup>
- <xs:element name="filter-security-metadata-source"><xs:annotation>
- <xs:documentation>Used to explicitly configure a FilterSecurityMetadataSource bean for use with a FilterSecurityInterceptor. Usually only needed if you are configuring a FilterChainProxy explicitly, rather than using the <http> element. The intercept-url elements used should only contain pattern, method and access attributes. Any others will result in a configuration error.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" name="intercept-url"><xs:annotation>
- <xs:documentation>Specifies the access attributes and/or filter list for a particular set of URLs.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:intercept-url.attlist"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:fsmds.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="fsmds.attlist">
- <xs:attribute name="use-expressions" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Enables the use of expressions in the 'access' attributes in <intercept-url> elements rather than the traditional list of configuration attributes. Defaults to 'false'. If enabled, each attribute should contain a single boolean expression. If the expression evaluates to 'true', access will be granted.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="lowercase-comparisons" type="security:boolean">
- <xs:annotation>
- <xs:documentation>as for http element</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="path-type">
- <xs:annotation>
- <xs:documentation>Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="ant"/>
- <xs:enumeration value="regex"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="filter-invocation-definition-source"><xs:annotation>
- <xs:documentation>Deprecated synonym for filter-security-metadata-source</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" name="intercept-url"><xs:annotation>
- <xs:documentation>Specifies the access attributes and/or filter list for a particular set of URLs.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:intercept-url.attlist"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:fsmds.attlist"/>
- </xs:complexType></xs:element>
-
- <xs:attributeGroup name="http-basic.attlist">
- <xs:attribute name="entry-point-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Sets the AuthenticationEntryPoint which is used by the BasicAuthenticationFilter.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="session-management.attlist">
- <xs:attribute name="session-fixation-protection">
- <xs:annotation>
- <xs:documentation>Indicates whether an existing session should be invalidated when a user authenticates and a new session started. If set to "none" no change will be made. "newSession" will create a new empty session. "migrateSession" will create a new session and copy the session attributes to the new session. Defaults to "migrateSession".</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="none"/>
- <xs:enumeration value="newSession"/>
- <xs:enumeration value="migrateSession"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="invalid-session-url" type="xs:token">
- <xs:annotation>
- <xs:documentation>The URL to which a user will be redirected if they submit an invalid session indentifier. Typically used to detect session timeouts.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="session-authentication-strategy-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Allows injection of the SessionAuthenticationStrategy instance used by the SessionManagementFilter</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="session-authentication-error-url" type="xs:token">
- <xs:annotation>
- <xs:documentation>Defines the URL of the error page which should be shown when the SessionAuthenticationStrategy raises an exception. If not set, an unauthorized (402) error code will be returned to the client. Note that this attribute doesn't apply if the error occurs during a form-based login, where the URL for authentication failure will take precedence.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="concurrency-control.attlist">
- <xs:attribute name="max-sessions" type="xs:positiveInteger">
- <xs:annotation>
- <xs:documentation>The maximum number of sessions a single authenticated user can have open at the same time. Defaults to "1".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="expired-url" type="xs:token">
- <xs:annotation>
- <xs:documentation>The URL a user will be redirected to if they attempt to use a session which has been "expired" because they have logged in again.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="error-if-maximum-exceeded" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Specifies that an unauthorized error should be reported when a user attempts to login when they already have the maximum configured sessions open. The default behaviour is to expire the original session. If the session-authentication-error-url attribute is set on the session-management URL, the user will be redirected to this URL.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="session-registry-alias" type="xs:token">
- <xs:annotation>
- <xs:documentation>Allows you to define an alias for the SessionRegistry bean in order to access it in your own configuration.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="session-registry-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Allows you to define an external SessionRegistry bean to be used by the concurrency control setup.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="remember-me.attlist">
- <xs:attribute name="key" type="xs:token">
- <xs:annotation>
- <xs:documentation>The "key" used to identify cookies from a specific token-based remember-me application. You should set this to a unique value for your application.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="token-repository-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Reference to a PersistentTokenRepository bean for use with the persistent token remember-me implementation.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="data-source-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>A reference to a DataSource bean</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attributeGroup ref="security:remember-me-services-ref"/>
- <xs:attribute name="user-service-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean) Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="services-alias" type="xs:token">
- <xs:annotation>
- <xs:documentation>Exports the internally defined RememberMeServices as a bean alias, allowing it to be used by other beans in the application context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="use-secure-cookie" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Determines whether the "secure" flag will be set on the remember-me cookie. If set to true, the cookie will only be submitted over HTTPS. Defaults to false.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="token-validity-seconds" type="xs:integer">
- <xs:annotation>
- <xs:documentation>The period (in seconds) for which the remember-me cookie should be valid.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="token-repository-ref">
- <xs:attribute name="token-repository-ref" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>Reference to a PersistentTokenRepository bean for use with the persistent token remember-me implementation.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="remember-me-services-ref">
- <xs:attribute name="services-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Allows a custom implementation of RememberMeServices to be used. Note that this implementation should return RememberMeAuthenticationToken instances with the same "key" value as specified in the remember-me element. Alternatively it should register its own AuthenticationProvider.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="remember-me-data-source-ref">
- <xs:attributeGroup ref="security:data-source-ref"/>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="anonymous.attlist">
- <xs:attribute name="key" type="xs:token">
- <xs:annotation>
- <xs:documentation>The key shared between the provider and filter. This generally does not need to be set. If unset, it will default to "doesNotMatter".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="username" type="xs:token">
- <xs:annotation>
- <xs:documentation>The username that should be assigned to the anonymous request. This allows the principal to be identified, which may be important for logging and auditing. if unset, defaults to "anonymousUser".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="granted-authority" type="xs:token">
- <xs:annotation>
- <xs:documentation>The granted authority that should be assigned to the anonymous request. Commonly this is used to assign the anonymous request particular roles, which can subsequently be used in authorization decisions. If unset, defaults to "ROLE_ANONYMOUS".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="enabled" type="security:boolean">
- <xs:annotation>
- <xs:documentation>With the default namespace setup, the anonymous "authentication" facility is automatically enabled. You can disable it using this property.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
-
- <xs:attributeGroup name="http-port">
- <xs:attribute name="http" use="required" type="xs:token"/>
- </xs:attributeGroup>
- <xs:attributeGroup name="https-port">
- <xs:attribute name="https" use="required" type="xs:token"/>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="x509.attlist">
- <xs:attribute name="subject-principal-regex" type="xs:token">
- <xs:annotation>
- <xs:documentation>The regular expression used to obtain the username from the certificate's subject. Defaults to matching on the common name using the pattern "CN=(.*?),".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-service-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean) Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="authentication-manager"><xs:annotation>
- <xs:documentation>Registers the AuthenticationManager instance and allows its list of AuthenticationProviders to be defined. Also allows you to define an alias to allow you to reference the AuthenticationManager in your own beans.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element name="authentication-provider"><xs:annotation>
- <xs:documentation>Indicates that the contained user-service should be used as an authentication source.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="security:any-user-service"/>
- <xs:element name="password-encoder"><xs:annotation>
- <xs:documentation>element which defines a password encoding strategy. Used by an authentication provider to convert submitted passwords to hashed versions, for example.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="salt-source"><xs:annotation>
- <xs:documentation>Password salting strategy. A system-wide constant or a property from the UserDetails object can be used.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attribute name="user-property" type="xs:token">
- <xs:annotation>
- <xs:documentation>A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="system-wide" type="xs:token">
- <xs:annotation>
- <xs:documentation>A single value that will be used as the salt for a password encoder.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:password-encoder.attlist"/>
- </xs:complexType></xs:element>
- </xs:choice>
- <xs:attributeGroup ref="security:ap.attlist"/>
- </xs:complexType></xs:element>
- <xs:element name="ldap-authentication-provider"><xs:annotation>
- <xs:documentation>Sets up an ldap authentication provider</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="password-compare"><xs:annotation>
- <xs:documentation>Specifies that an LDAP provider should use an LDAP compare operation of the user's password to authenticate the user</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="password-encoder"><xs:annotation>
- <xs:documentation>element which defines a password encoding strategy. Used by an authentication provider to convert submitted passwords to hashed versions, for example.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="salt-source"><xs:annotation>
- <xs:documentation>Password salting strategy. A system-wide constant or a property from the UserDetails object can be used.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attribute name="user-property" type="xs:token">
- <xs:annotation>
- <xs:documentation>A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="system-wide" type="xs:token">
- <xs:annotation>
- <xs:documentation>A single value that will be used as the salt for a password encoder.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:password-encoder.attlist"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:password-compare.attlist"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:ldap-ap.attlist"/>
- </xs:complexType></xs:element>
- </xs:choice>
- <xs:attributeGroup ref="security:authman.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="authman.attlist">
- <xs:attribute name="alias" type="xs:ID">
- <xs:annotation>
- <xs:documentation>The alias you wish to use for the AuthenticationManager bean</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="erase-credentials" type="security:boolean">
- <xs:annotation>
- <xs:documentation>If set to true, the AuthenticationManger will attempt to clear any credentials data in the returned Authentication object, once the user has been authenticated. Defaults to false.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="ap.attlist">
- <xs:attribute name="ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-service-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean) Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="user-service" substitutionGroup="security:any-user-service"><xs:annotation>
- <xs:documentation>Creates an in-memory UserDetailsService from a properties file or a list of "user" child elements.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" name="user"><xs:annotation>
- <xs:documentation>Represents a user in the application.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:user.attlist"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attributeGroup ref="security:properties-file"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="properties-file">
- <xs:attribute name="properties" type="xs:token"/>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="user.attlist">
- <xs:attribute name="name" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>The username assigned to the user.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="password" type="xs:string">
- <xs:annotation>
- <xs:documentation>The password assigned to the user. This may be hashed if the corresponding authentication provider supports hashing (remember to set the "hash" attribute of the "user-service" element). This attribute be omitted in the case where the data will not be used for authentication, but only for accessing authorities. If omitted, the namespace will generate a random value, preventing its accidental use for authentication. Cannot be empty.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="authorities" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>One of more authorities granted to the user. Separate authorities with a comma (but no space). For example, "ROLE_USER,ROLE_ADMINISTRATOR"</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="locked" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Can be set to "true" to mark an account as locked and unusable.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="disabled" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Can be set to "true" to mark an account as disabled and unusable.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="jdbc-user-service" substitutionGroup="security:any-user-service"><xs:annotation>
- <xs:documentation>Causes creation of a JDBC-based UserDetailsService.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attributeGroup ref="security:jdbc-user-service.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="jdbc-user-service.attlist">
- <xs:attribute name="data-source-ref" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>The bean ID of the DataSource which provides the required tables.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="cache-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Defines a reference to a cache for use with a UserDetailsService.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="users-by-username-query" type="xs:token">
- <xs:annotation>
- <xs:documentation>An SQL statement to query a username, password, and enabled status given a username</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="authorities-by-username-query" type="xs:token">
- <xs:annotation>
- <xs:documentation>An SQL statement to query for a user's granted authorities given a username.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-authorities-by-username-query" type="xs:token">
- <xs:annotation>
- <xs:documentation>An SQL statement to query user's group authorities given a username.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="role-prefix" type="xs:token">
- <xs:annotation>
- <xs:documentation>A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="any-user-service" abstract="true"/>
- <xs:element name="custom-filter"><xs:annotation>
- <xs:documentation>Used to indicate that a filter bean declaration should be incorporated into the security filter chain.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:custom-filter.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="custom-filter.attlist">
- <xs:attributeGroup ref="security:ref"/>
- <xs:attribute name="after" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The filter immediately after which the custom-filter should be placed in the chain. This feature will only be needed by advanced users who wish to mix their own filters into the security filter chain and have some knowledge of the standard Spring Security filters. The filter names map to specific Spring Security implementation filters.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="before" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The filter immediately before which the custom-filter should be placed in the chain</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="position" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The explicit position at which the custom-filter should be placed in the chain. Use if you are replacing a standard filter.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="after">
- <xs:attribute name="after" use="required" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The filter immediately after which the custom-filter should be placed in the chain. This feature will only be needed by advanced users who wish to mix their own filters into the security filter chain and have some knowledge of the standard Spring Security filters. The filter names map to specific Spring Security implementation filters.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="before">
- <xs:attribute name="before" use="required" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The filter immediately before which the custom-filter should be placed in the chain</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="position">
- <xs:attribute name="position" use="required" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The explicit position at which the custom-filter should be placed in the chain. Use if you are replacing a standard filter.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:simpleType name="named-security-filter">
- <xs:restriction base="xs:token">
- <xs:enumeration value="FIRST"/>
- <xs:enumeration value="CHANNEL_FILTER"/>
- <xs:enumeration value="CONCURRENT_SESSION_FILTER"/>
- <xs:enumeration value="SECURITY_CONTEXT_FILTER"/>
- <xs:enumeration value="LOGOUT_FILTER"/>
- <xs:enumeration value="X509_FILTER"/>
- <xs:enumeration value="PRE_AUTH_FILTER"/>
- <xs:enumeration value="CAS_FILTER"/>
- <xs:enumeration value="FORM_LOGIN_FILTER"/>
- <xs:enumeration value="OPENID_FILTER"/>
- <xs:enumeration value="BASIC_AUTH_FILTER"/>
- <xs:enumeration value="SERVLET_API_SUPPORT_FILTER"/>
- <xs:enumeration value="REMEMBER_ME_FILTER"/>
- <xs:enumeration value="ANONYMOUS_FILTER"/>
- <xs:enumeration value="EXCEPTION_TRANSLATION_FILTER"/>
- <xs:enumeration value="SESSION_MANAGEMENT_FILTER"/>
- <xs:enumeration value="FILTER_SECURITY_INTERCEPTOR"/>
- <xs:enumeration value="SWITCH_USER_FILTER"/>
- <xs:enumeration value="LAST"/>
- </xs:restriction>
- </xs:simpleType>
-</xs:schema>
diff --git a/dist/spring-security-config/org/springframework/security/config/spring-security-3.0.4.rnc b/dist/spring-security-config/org/springframework/security/config/spring-security-3.0.4.rnc
deleted file mode 100644
index 7ad0dce..0000000
--- a/dist/spring-security-config/org/springframework/security/config/spring-security-3.0.4.rnc
+++ /dev/null
@@ -1,633 +0,0 @@
-namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
-datatypes xsd = "http://www.w3.org/2001/XMLSchema-datatypes"
-
-default namespace = "http://www.springframework.org/schema/security"
-
-start = http | ldap-server | authentication-provider | ldap-authentication-provider | any-user-service | ldap-server | ldap-authentication-provider
-
-hash =
- ## Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm.
- attribute hash {"plaintext" | "sha" | "sha-256" | "md5" | "md4" | "{sha}" | "{ssha}"}
-base64 =
- ## Whether a string should be base64 encoded
- attribute base64 {"true" | "false"}
-path-type =
- ## Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified.
- attribute path-type {"ant" | "regex"}
-port =
- ## Specifies an IP port number. Used to configure an embedded LDAP server, for example.
- attribute port { xsd:positiveInteger }
-url =
- ## Specifies a URL.
- attribute url { xsd:token }
-id =
- ## A bean identifier, used for referring to the bean elsewhere in the context.
- attribute id {xsd:ID}
-ref =
- ## Defines a reference to a Spring bean Id.
- attribute ref {xsd:token}
-
-cache-ref =
- ## Defines a reference to a cache for use with a UserDetailsService.
- attribute cache-ref {xsd:token}
-
-user-service-ref =
- ## A reference to a user-service (or UserDetailsService bean) Id
- attribute user-service-ref {xsd:token}
-
-data-source-ref =
- ## A reference to a DataSource bean
- attribute data-source-ref {xsd:token}
-
-password-encoder =
- ## element which defines a password encoding strategy. Used by an authentication provider to convert submitted passwords to hashed versions, for example.
- element password-encoder {password-encoder.attlist, salt-source?}
-password-encoder.attlist &=
- ref | (hash? & base64?)
-
-salt-source =
- ## Password salting strategy. A system-wide constant or a property from the UserDetails object can be used.
- element salt-source {user-property | system-wide | ref}
-user-property =
- ## A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used.
- attribute user-property {xsd:token}
-system-wide =
- ## A single value that will be used as the salt for a password encoder.
- attribute system-wide {xsd:token}
-
-boolean = "true" | "false"
-
-role-prefix =
- ## A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty.
- attribute role-prefix {xsd:token}
-
-use-expressions =
- ## Enables the use of expressions in the 'access' attributes in <intercept-url> elements rather than the traditional list of configuration attributes. Defaults to 'false'. If enabled, each attribute should contain a single boolean expression. If the expression evaluates to 'true', access will be granted.
- attribute use-expressions {boolean}
-
-ldap-server =
- ## Defines an LDAP server location or starts an embedded server. The url indicates the location of a remote server. If no url is given, an embedded server will be started, listening on the supplied port number. The port is optional and defaults to 33389. A Spring LDAP ContextSource bean will be registered for the server with the id supplied.
- element ldap-server {ldap-server.attlist}
-ldap-server.attlist &= id?
-ldap-server.attlist &= (url | port)?
-ldap-server.attlist &=
- ## Username (DN) of the "manager" user identity which will be used to authenticate to a (non-embedded) LDAP server. If omitted, anonymous access will be used.
- attribute manager-dn {xsd:string}?
-ldap-server.attlist &=
- ## The password for the manager DN.
- attribute manager-password {xsd:string}?
-ldap-server.attlist &=
- ## Explicitly specifies an ldif file resource to load into an embedded LDAP server
- attribute ldif { xsd:string }?
-ldap-server.attlist &=
- ## Optional root suffix for the embedded LDAP server. Default is "dc=springframework,dc=org"
- attribute root { xsd:string }?
-
-ldap-server-ref-attribute =
- ## The optional server to use. If omitted, and a default LDAP server is registered (using <ldap-server> with no Id), that server will be used.
- attribute server-ref {xsd:token}
-
-
-group-search-filter-attribute =
- ## Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user.
- attribute group-search-filter {xsd:token}
-group-search-base-attribute =
- ## Search base for group membership searches. Defaults to "" (searching from the root).
- attribute group-search-base {xsd:token}
-user-search-filter-attribute =
- ## The LDAP filter used to search for users (optional). For example "(uid={0})". The substituted parameter is the user's login name.
- attribute user-search-filter {xsd:token}
-user-search-base-attribute =
- ## Search base for user searches. Defaults to "". Only used with a 'user-search-filter'.
- attribute user-search-base {xsd:token}
-group-role-attribute-attribute =
- ## The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn".
- attribute group-role-attribute {xsd:token}
-user-details-class-attribute =
- ## Allows the objectClass of the user entry to be specified. If set, the framework will attempt to load standard attributes for the defined class into the returned UserDetails object
- attribute user-details-class {"person" | "inetOrgPerson"}
-user-context-mapper-attribute =
- ## Allows explicit customization of the loaded user object by specifying a UserDetailsContextMapper bean which will be called with the context information from the user's directory entry
- attribute user-context-mapper-ref {xsd:token}
-
-
-ldap-user-service =
- element ldap-user-service {ldap-us.attlist}
-ldap-us.attlist &= id?
-ldap-us.attlist &=
- ldap-server-ref-attribute?
-ldap-us.attlist &=
- user-search-filter-attribute?
-ldap-us.attlist &=
- user-search-base-attribute?
-ldap-us.attlist &=
- group-search-filter-attribute?
-ldap-us.attlist &=
- group-search-base-attribute?
-ldap-us.attlist &=
- group-role-attribute-attribute?
-ldap-us.attlist &=
- cache-ref?
-ldap-us.attlist &=
- role-prefix?
-ldap-us.attlist &=
- (user-details-class-attribute | user-context-mapper-attribute)?
-
-ldap-authentication-provider =
- ## Sets up an ldap authentication provider
- element ldap-authentication-provider {ldap-ap.attlist, password-compare-element?}
-ldap-ap.attlist &=
- ldap-server-ref-attribute?
-ldap-ap.attlist &=
- user-search-base-attribute?
-ldap-ap.attlist &=
- user-search-filter-attribute?
-ldap-ap.attlist &=
- group-search-base-attribute?
-ldap-ap.attlist &=
- group-search-filter-attribute?
-ldap-ap.attlist &=
- group-role-attribute-attribute?
-ldap-ap.attlist &=
- ## A specific pattern used to build the user's DN, for example "uid={0},ou=people". The key "{0}" must be present and will be substituted with the username.
- attribute user-dn-pattern {xsd:token}?
-ldap-ap.attlist &=
- role-prefix?
-ldap-ap.attlist &=
- (user-details-class-attribute | user-context-mapper-attribute)?
-
-password-compare-element =
- ## Specifies that an LDAP provider should use an LDAP compare operation of the user's password to authenticate the user
- element password-compare {password-compare.attlist, password-encoder?}
-
-password-compare.attlist &=
- ## The attribute in the directory which contains the user password. Defaults to "userPassword".
- attribute password-attribute {xsd:token}?
-password-compare.attlist &=
- hash?
-
-intercept-methods =
- ## Can be used inside a bean definition to add a security interceptor to the bean and set up access configuration attributes for the bean's methods
- element intercept-methods {intercept-methods.attlist, protect+}
-intercept-methods.attlist &=
- ## Optional AccessDecisionManager bean ID to be used by the created method security interceptor.
- attribute access-decision-manager-ref {xsd:token}?
-
-
-protect =
- ## Defines a protected method and the access control configuration attributes that apply to it. We strongly advise you NOT to mix "protect" declarations with any services provided "global-method-security".
- element protect {protect.attlist, empty}
-protect.attlist &=
- ## A method name
- attribute method {xsd:token}
-protect.attlist &=
- ## Access configuration attributes list that applies to the method, e.g. "ROLE_A,ROLE_B".
- attribute access {xsd:token}
-
-
-global-method-security =
- ## Provides method security for all beans registered in the Spring application context. Specifically, beans will be scanned for matches with the ordered list of "protect-pointcut" sub-elements, Spring Security annotations and/or. Where there is a match, the beans will automatically be proxied and security authorization applied to the methods accordingly. If you use and enable all four sources of method security metadata (ie "protect-pointcut" declarations, expression annotations, @Secured and also JSR250 security annotations), the metadata sources will be queried in that order. In practical terms, this enables you to use XML to override method security metadata expressed in annotations. If using annotations, the order of precedence is EL-based (@PreAuthorize etc.), @Secured and finally JSR-250.
- element global-method-security {global-method-security.attlist, (pre-post-annotation-handling | expression-handler)?, protect-pointcut*, after-invocation-provider*}
-global-method-security.attlist &=
- ## Specifies whether the use of Spring Security's pre and post invocation annotations (@PreFilter, @PreAuthorize, @PostFilter, @PostAuthorize) should be enabled for this application context. Defaults to "disabled".
- attribute pre-post-annotations {"disabled" | "enabled" }?
-global-method-security.attlist &=
- ## Specifies whether the use of Spring Security's @Secured annotations should be enabled for this application context. Defaults to "disabled".
- attribute secured-annotations {"disabled" | "enabled" }?
-global-method-security.attlist &=
- ## Specifies whether JSR-250 style attributes are to be used (for example "RolesAllowed"). This will require the javax.annotation.security classes on the classpath. Defaults to "disabled".
- attribute jsr250-annotations {"disabled" | "enabled" }?
-global-method-security.attlist &=
- ## Optional AccessDecisionManager bean ID to override the default used for method security.
- attribute access-decision-manager-ref {xsd:token}?
-global-method-security.attlist &=
- ## Optional RunAsmanager implementation which will be used by the configured MethodSecurityInterceptor
- attribute run-as-manager-ref {xsd:token}?
-global-method-security.attlist &=
- ## Allows the advice "order" to be set for the method security interceptor.
- attribute order {xsd:token}?
-global-method-security.attlist &=
- attribute proxy-target-class {boolean}?
-global-method-security.attlist &=
- ## Can be used to specify that AspectJ should be used instead of the default Spring AOP. If set, secured classes must be woven with the AnnotationSecurityAspect from the spring-security-aspects module.
- attribute mode {"aspectj"}?
-
-after-invocation-provider =
- ## Allows addition of extra AfterInvocationProvider beans which should be called by the MethodSecurityInterceptor created by global-method-security.
- element after-invocation-provider {ref}
-
-pre-post-annotation-handling =
- ## Allows the default expression-based mechanism for handling Spring Security's pre and post invocation annotations (@PreFilter, @PreAuthorize, @PostFilter, @PostAuthorize) to be replace entirely. Only applies if these annotations are enabled.
- element pre-post-annotation-handling {invocation-attribute-factory, pre-invocation-advice, post-invocation-advice}
-
-invocation-attribute-factory =
- ## Defines the PrePostInvocationAttributeFactory instance which is used to generate pre and post invocation metadata from the annotated methods.
- element invocation-attribute-factory {ref}
-
-pre-invocation-advice =
- element pre-invocation-advice {ref}
-
-post-invocation-advice =
- element post-invocation-advice {ref}
-
-
-expression-handler =
- ## Defines the SecurityExpressionHandler instance which will be used if expression-based access-control is enabled. A default implementation (with no ACL support) will be used if not supplied.
- element expression-handler {ref}
-
-protect-pointcut =
- ## Defines a protected pointcut and the access control configuration attributes that apply to it. Every bean registered in the Spring application context that provides a method that matches the pointcut will receive security authorization.
- element protect-pointcut {protect-pointcut.attlist, empty}
-protect-pointcut.attlist &=
- ## An AspectJ expression, including the 'execution' keyword. For example, 'execution(int com.foo.TargetObject.countLength(String))' (without the quotes).
- attribute expression {xsd:string}
-protect-pointcut.attlist &=
- ## Access configuration attributes list that applies to all methods matching the pointcut, e.g. "ROLE_A,ROLE_B"
- attribute access {xsd:token}
-
-http-firewall =
- ## Allows a custom instance of HttpFirewall to be injected into the FilterChainProxy created by the namespace.
- element http-firewall {ref}
-
-http =
- ## Container element for HTTP security configuration
- element http {http.attlist, (intercept-url+ & access-denied-handler? & form-login? & openid-login? & x509? & http-basic? & logout? & session-management & remember-me? & anonymous? & port-mappings & custom-filter* & request-cache?) }
-http.attlist &=
- ## Automatically registers a login form, BASIC authentication, anonymous authentication, logout services, remember-me and servlet-api-integration. If set to "true", all of these capabilities are added (although you can still customize the configuration of each by providing the respective element). If unspecified, defaults to "false".
- attribute auto-config {boolean}?
-http.attlist &=
- use-expressions?
-http.attlist &=
- ## Controls the eagerness with which an HTTP session is created. If not set, defaults to "ifRequired". Note that if a custom SecurityContextRepository is set using security-context-repository-ref, then the only value which can be set is "always". Otherwise the session creation behaviour will be determined by the repository bean implementation.
- attribute create-session {"ifRequired" | "always" | "never" }?
-http.attlist &=
- ## A reference to a SecurityContextRepository bean. This can be used to customize how the SecurityContext is stored between requests.
- attribute security-context-repository-ref {xsd:token}?
-http.attlist &=
- ## The path format used to define the paths in child elements.
- path-type?
-http.attlist &=
- ## Whether test URLs should be converted to lower case prior to comparing with defined path patterns. If unspecified, defaults to "true".
- attribute lowercase-comparisons {boolean}?
-http.attlist &=
- ## Provides versions of HttpServletRequest security methods such as isUserInRole() and getPrincipal() which are implemented by accessing the Spring SecurityContext. Defaults to "true".
- attribute servlet-api-provision {boolean}?
-http.attlist &=
- ## Optional attribute specifying the ID of the AccessDecisionManager implementation which should be used for authorizing HTTP requests.
- attribute access-decision-manager-ref {xsd:token}?
-http.attlist &=
- ## Optional attribute specifying the realm name that will be used for all authentication features that require a realm name (eg BASIC and Digest authentication). If unspecified, defaults to "Spring Security Application".
- attribute realm {xsd:token}?
-http.attlist &=
- ## Allows a customized AuthenticationEntryPoint to be set on the ExceptionTranslationFilter.
- attribute entry-point-ref {xsd:token}?
-http.attlist &=
- ## Corresponds to the observeOncePerRequest property of FilterSecurityInterceptor. Defaults to "true"
- attribute once-per-request {boolean}?
-http.attlist &=
- ## Deprecated in favour of the access-denied-handler element.
- attribute access-denied-page {xsd:token}?
-http.attlist &=
- ##
- attribute disable-url-rewriting {boolean}?
-
-
-access-denied-handler =
- ## Defines the access-denied strategy that should be used. An access denied page can be defined or a reference to an AccessDeniedHandler instance.
- element access-denied-handler {access-denied-handler.attlist, empty}
-access-denied-handler.attlist &= (ref | access-denied-handler-page)
-
-access-denied-handler-page =
- ## The access denied page that an authenticated user will be redirected to if they request a page which they don't have the authority to access.
- attribute error-page {xsd:token}
-
-intercept-url =
- ## Specifies the access attributes and/or filter list for a particular set of URLs.
- element intercept-url {intercept-url.attlist, empty}
-intercept-url.attlist &=
- ## The pattern which defines the URL path. The content will depend on the type set in the containing http element, so will default to ant path syntax.
- attribute pattern {xsd:token}
-intercept-url.attlist &=
- ## The access configuration attributes that apply for the configured path.
- attribute access {xsd:token}?
-intercept-url.attlist &=
- ## The HTTP Method for which the access configuration attributes should apply. If not specified, the attributes will apply to any method.
- attribute method {"GET" | "DELETE" | "HEAD" | "OPTIONS" | "POST" | "PUT" | "TRACE"}?
-
-intercept-url.attlist &=
- ## The filter list for the path. Currently can be set to "none" to remove a path from having any filters applied. The full filter stack (consisting of all filters created by the namespace configuration, and any added using 'custom-filter'), will be applied to any other paths.
- attribute filters {"none"}?
-intercept-url.attlist &=
- ## Used to specify that a URL must be accessed over http or https, or that there is no preference. The value should be "http", "https" or "any", respectively.
- attribute requires-channel {xsd:token}?
-
-logout =
- ## Incorporates a logout processing filter. Most web applications require a logout filter, although you may not require one if you write a controller to provider similar logic.
- element logout {logout.attlist, empty}
-logout.attlist &=
- ## Specifies the URL that will cause a logout. Spring Security will initialize a filter that responds to this particular URL. Defaults to /j_spring_security_logout if unspecified.
- attribute logout-url {xsd:token}?
-logout.attlist &=
- ## Specifies the URL to display once the user has logged out. If not specified, defaults to /.
- attribute logout-success-url {xsd:token}?
-logout.attlist &=
- ## Specifies whether a logout also causes HttpSession invalidation, which is generally desirable. If unspecified, defaults to true.
- attribute invalidate-session {boolean}?
-logout.attlist &=
- ## A reference to a LogoutSuccessHandler implementation which will be used to determine the destination to which the user is taken after logging out.
- attribute success-handler-ref {xsd:token}?
-
-
-request-cache =
- ## Allow the RequestCache used for saving requests during the login process to be set
- element request-cache {ref}
-
-form-login =
- ## Sets up a form login configuration for authentication with a username and password
- element form-login {form-login.attlist, empty}
-form-login.attlist &=
- ## The URL that the login form is posted to. If unspecified, it defaults to /j_spring_security_check.
- attribute login-processing-url {xsd:token}?
-form-login.attlist &=
- ## The URL that will be redirected to after successful authentication, if the user's previous action could not be resumed. This generally happens if the user visits a login page without having first requested a secured operation that triggers authentication. If unspecified, defaults to the root of the application.
- attribute default-target-url {xsd:token}?
-form-login.attlist &=
- ## Whether the user should always be redirected to the default-target-url after login.
- attribute always-use-default-target {boolean}?
-form-login.attlist &=
- ## The URL for the login page. If no login URL is specified, Spring Security will automatically create a login URL at /spring_security_login and a corresponding filter to render that login URL when requested.
- attribute login-page {xsd:token}?
-form-login.attlist &=
- ## The URL for the login failure page. If no login failure URL is specified, Spring Security will automatically create a failure login URL at /spring_security_login?login_error and a corresponding filter to render that login failure URL when requested.
- attribute authentication-failure-url {xsd:token}?
-form-login.attlist &=
- ## Reference to an AuthenticationSuccessHandler bean which should be used to handle a successful authentication request. Should not be used in combination with default-target-url (or always-use-default-target-url) as the implementation should always deal with navigation to the subsequent destination
- attribute authentication-success-handler-ref {xsd:token}?
-form-login.attlist &=
- ## Reference to an AuthenticationFailureHandler bean which should be used to handle a failed authentication request. Should not be used in combination with authentication-failure-url as the implementation should always deal with navigation to the subsequent destination
- attribute authentication-failure-handler-ref {xsd:token}?
-
-
-openid-login =
- ## Sets up form login for authentication with an Open ID identity
- element openid-login {form-login.attlist, user-service-ref?, attribute-exchange?}
-
-attribute-exchange =
- element attribute-exchange {openid-attribute+}
-
-openid-attribute =
- element openid-attribute {openid-attribute.attlist}
-
-openid-attribute.attlist &=
- attribute name {xsd:token}
-openid-attribute.attlist &=
- attribute type {xsd:token}
-openid-attribute.attlist &=
- attribute required {boolean}?
-openid-attribute.attlist &=
- attribute count {xsd:int}?
-
-
-filter-chain-map =
- ## Used to explicitly configure a FilterChainProxy instance with a FilterChainMap
- element filter-chain-map {filter-chain-map.attlist, filter-chain+}
-filter-chain-map.attlist &=
- path-type
-
-filter-chain =
- ## Used within filter-chain-map to define a specific URL pattern and the list of filters which apply to the URLs matching that pattern. When multiple filter-chain elements are used within a filter-chain-map element, the most specific patterns must be placed at the top of the list, with most general ones at the bottom.
- element filter-chain {filter-chain.attlist, empty}
-filter-chain.attlist &=
- attribute pattern {xsd:token}
-filter-chain.attlist &=
- attribute filters {xsd:token}
-
-filter-security-metadata-source =
- ## Used to explicitly configure a FilterSecurityMetadataSource bean for use with a FilterSecurityInterceptor. Usually only needed if you are configuring a FilterChainProxy explicitly, rather than using the <http> element. The intercept-url elements used should only contain pattern, method and access attributes. Any others will result in a configuration error.
- element filter-security-metadata-source {fsmds.attlist, intercept-url+}
-fsmds.attlist &=
- use-expressions?
-fsmds.attlist &=
- id?
-fsmds.attlist &=
- ## as for http element
- attribute lowercase-comparisons {boolean}?
-fsmds.attlist &=
- ## as for http element
- path-type?
-
-filter-invocation-definition-source =
- ## Deprecated synonym for filter-security-metadata-source
- element filter-invocation-definition-source {fsmds.attlist, intercept-url+}
-
-http-basic =
- ## Adds support for basic authentication (this is an element to permit future expansion, such as supporting an "ignoreFailure" attribute)
- element http-basic {http-basic.attlist, empty}
-http-basic.attlist &=
- ## Sets the AuthenticationEntryPoint which is used by the BasicAuthenticationFilter.
- attribute entry-point-ref {xsd:token}?
-
-session-management =
- element session-management {session-management.attlist, concurrency-control?}
-
-session-management.attlist &=
- ## Indicates whether an existing session should be invalidated when a user authenticates and a new session started. If set to "none" no change will be made. "newSession" will create a new empty session. "migrateSession" will create a new session and copy the session attributes to the new session. Defaults to "migrateSession".
- attribute session-fixation-protection {"none" | "newSession" | "migrateSession" }?
-session-management.attlist &=
- ## The URL to which a user will be redirected if they submit an invalid session indentifier. Typically used to detect session timeouts.
- attribute invalid-session-url {xsd:token}?
-session-management.attlist &=
- ## Allows injection of the SessionAuthenticationStrategy instance used by the SessionManagementFilter
- attribute session-authentication-strategy-ref {xsd:token}?
-session-management.attlist &=
- ## Defines the URL of the error page which should be shown when the SessionAuthenticationStrategy raises an exception. If not set, an unauthorized (402) error code will be returned to the client. Note that this attribute doesn't apply if the error occurs during a form-based login, where the URL for authentication failure will take precedence.
- attribute session-authentication-error-url {xsd:token}?
-
-
-concurrency-control =
- ## Enables concurrent session control, limiting the number of authenticated sessions a user may have at the same time.
- element concurrency-control {concurrency-control.attlist, empty}
-
-concurrency-control.attlist &=
- ## The maximum number of sessions a single authenticated user can have open at the same time. Defaults to "1".
- attribute max-sessions {xsd:positiveInteger}?
-concurrency-control.attlist &=
- ## The URL a user will be redirected to if they attempt to use a session which has been "expired" because they have logged in again.
- attribute expired-url {xsd:token}?
-concurrency-control.attlist &=
- ## Specifies that an unauthorized error should be reported when a user attempts to login when they already have the maximum configured sessions open. The default behaviour is to expire the original session. If the session-authentication-error-url attribute is set on the session-management URL, the user will be redirected to this URL.
- attribute error-if-maximum-exceeded {boolean}?
-concurrency-control.attlist &=
- ## Allows you to define an alias for the SessionRegistry bean in order to access it in your own configuration.
- attribute session-registry-alias {xsd:token}?
-concurrency-control.attlist &=
- ## Allows you to define an external SessionRegistry bean to be used by the concurrency control setup.
- attribute session-registry-ref {xsd:token}?
-
-
-remember-me =
- ## Sets up remember-me authentication. If used with the "key" attribute (or no attributes) the cookie-only implementation will be used. Specifying "token-repository-ref" or "remember-me-data-source-ref" will use the more secure, persisten token approach.
- element remember-me {remember-me.attlist}
-remember-me.attlist &=
- ## The "key" used to identify cookies from a specific token-based remember-me application. You should set this to a unique value for your application.
- attribute key {xsd:token}?
-
-remember-me.attlist &=
- (token-repository-ref | remember-me-data-source-ref | remember-me-services-ref)
-
-remember-me.attlist &=
- user-service-ref?
-
-remember-me.attlist &=
- ## Exports the internally defined RememberMeServices as a bean alias, allowing it to be used by other beans in the application context.
- attribute services-alias {xsd:token}?
-
-remember-me.attlist &=
- ## Determines whether the "secure" flag will be set on the remember-me cookie. If set to true, the cookie will only be submitted over HTTPS. Defaults to false.
- attribute use-secure-cookie {boolean}?
-
-remember-me.attlist &=
- ## The period (in seconds) for which the remember-me cookie should be valid.
- attribute token-validity-seconds {xsd:integer}?
-
-token-repository-ref =
- ## Reference to a PersistentTokenRepository bean for use with the persistent token remember-me implementation.
- attribute token-repository-ref {xsd:token}
-remember-me-services-ref =
- ## Allows a custom implementation of RememberMeServices to be used. Note that this implementation should return RememberMeAuthenticationToken instances with the same "key" value as specified in the remember-me element. Alternatively it should register its own AuthenticationProvider.
- attribute services-ref {xsd:token}?
-remember-me-data-source-ref =
- ## DataSource bean for the database that contains the token repository schema.
- data-source-ref
-
-anonymous =
- ## Adds support for automatically granting all anonymous web requests a particular principal identity and a corresponding granted authority.
- element anonymous {anonymous.attlist}
-anonymous.attlist &=
- ## The key shared between the provider and filter. This generally does not need to be set. If unset, it will default to "doesNotMatter".
- attribute key {xsd:token}?
-anonymous.attlist &=
- ## The username that should be assigned to the anonymous request. This allows the principal to be identified, which may be important for logging and auditing. if unset, defaults to "anonymousUser".
- attribute username {xsd:token}?
-anonymous.attlist &=
- ## The granted authority that should be assigned to the anonymous request. Commonly this is used to assign the anonymous request particular roles, which can subsequently be used in authorization decisions. If unset, defaults to "ROLE_ANONYMOUS".
- attribute granted-authority {xsd:token}?
-anonymous.attlist &=
- ## With the default namespace setup, the anonymous "authentication" facility is automatically enabled. You can disable it using this property.
- attribute enabled {boolean}?
-
-
-port-mappings =
- ## Defines the list of mappings between http and https ports for use in redirects
- element port-mappings {port-mappings.attlist, port-mapping+}
-
-port-mappings.attlist &= empty
-
-port-mapping =
- element port-mapping {http-port, https-port}
-
-http-port = attribute http {xsd:token}
-
-https-port = attribute https {xsd:token}
-
-
-x509 =
- ## Adds support for X.509 client authentication.
- element x509 {x509.attlist}
-x509.attlist &=
- ## The regular expression used to obtain the username from the certificate's subject. Defaults to matching on the common name using the pattern "CN=(.*?),".
- attribute subject-principal-regex {xsd:token}?
-x509.attlist &=
- ## Explicitly specifies which user-service should be used to load user data for X.509 authenticated clients. If ommitted, the default user-service will be used.
- user-service-ref?
-
-authentication-manager =
- ## Registers the AuthenticationManager instance and allows its list of AuthenticationProviders to be defined. Also allows you to define an alias to allow you to reference the AuthenticationManager in your own beans.
- element authentication-manager {authman.attlist & authentication-provider* & ldap-authentication-provider*}
-authman.attlist &=
- ## The alias you wish to use for the AuthenticationManager bean
- attribute alias {xsd:ID}?
-authman.attlist &=
- ## If set to true, the AuthenticationManger will attempt to clear any credentials data in the returned Authentication object, once the user has been authenticated. Defaults to false.
- attribute erase-credentials {boolean}?
-
-authentication-provider =
- ## Indicates that the contained user-service should be used as an authentication source.
- element authentication-provider {ap.attlist & any-user-service & password-encoder?}
-ap.attlist &=
- ## Specifies a reference to a separately configured AuthenticationProvider instance which should be registered within the AuthenticationManager.
- ref?
-ap.attlist &=
- ## Specifies a reference to a separately configured UserDetailsService from which to obtain authentication data.
- user-service-ref?
-
-user-service =
- ## Creates an in-memory UserDetailsService from a properties file or a list of "user" child elements.
- element user-service {id? & (properties-file | (user*))}
-properties-file =
- attribute properties {xsd:token}?
-
-user =
- ## Represents a user in the application.
- element user {user.attlist, empty}
-user.attlist &=
- ## The username assigned to the user.
- attribute name {xsd:token}
-user.attlist &=
- ## The password assigned to the user. This may be hashed if the corresponding authentication provider supports hashing (remember to set the "hash" attribute of the "user-service" element). This attribute be omitted in the case where the data will not be used for authentication, but only for accessing authorities. If omitted, the namespace will generate a random value, preventing its accidental use for authentication. Cannot be empty.
- attribute password {xsd:string}?
-user.attlist &=
- ## One of more authorities granted to the user. Separate authorities with a comma (but no space). For example, "ROLE_USER,ROLE_ADMINISTRATOR"
- attribute authorities {xsd:token}
-user.attlist &=
- ## Can be set to "true" to mark an account as locked and unusable.
- attribute locked {boolean}?
-user.attlist &=
- ## Can be set to "true" to mark an account as disabled and unusable.
- attribute disabled {boolean}?
-
-jdbc-user-service =
- ## Causes creation of a JDBC-based UserDetailsService.
- element jdbc-user-service {id? & jdbc-user-service.attlist}
-jdbc-user-service.attlist &=
- ## The bean ID of the DataSource which provides the required tables.
- attribute data-source-ref {xsd:token}
-jdbc-user-service.attlist &=
- cache-ref?
-jdbc-user-service.attlist &=
- ## An SQL statement to query a username, password, and enabled status given a username
- attribute users-by-username-query {xsd:token}?
-jdbc-user-service.attlist &=
- ## An SQL statement to query for a user's granted authorities given a username.
- attribute authorities-by-username-query {xsd:token}?
-jdbc-user-service.attlist &=
- ## An SQL statement to query user's group authorities given a username.
- attribute group-authorities-by-username-query {xsd:token}?
-jdbc-user-service.attlist &=
- role-prefix?
-
-
-any-user-service = user-service | jdbc-user-service | ldap-user-service
-
-custom-filter =
- ## Used to indicate that a filter bean declaration should be incorporated into the security filter chain.
- element custom-filter {custom-filter.attlist}
-
-custom-filter.attlist &=
- ref
-
-custom-filter.attlist &=
- (after | before | position)
-
-after =
- ## The filter immediately after which the custom-filter should be placed in the chain. This feature will only be needed by advanced users who wish to mix their own filters into the security filter chain and have some knowledge of the standard Spring Security filters. The filter names map to specific Spring Security implementation filters.
- attribute after {named-security-filter}
-before =
- ## The filter immediately before which the custom-filter should be placed in the chain
- attribute before {named-security-filter}
-position =
- ## The explicit position at which the custom-filter should be placed in the chain. Use if you are replacing a standard filter.
- attribute position {named-security-filter}
-
-
-named-security-filter = "FIRST" | "CHANNEL_FILTER" | "CONCURRENT_SESSION_FILTER" | "SECURITY_CONTEXT_FILTER" | "LOGOUT_FILTER" | "X509_FILTER" | "PRE_AUTH_FILTER" | "CAS_FILTER" | "FORM_LOGIN_FILTER" | "OPENID_FILTER" |"BASIC_AUTH_FILTER" | "SERVLET_API_SUPPORT_FILTER" | "REMEMBER_ME_FILTER" | "ANONYMOUS_FILTER" | "EXCEPTION_TRANSLATION_FILTER" | "SESSION_MANAGEMENT_FILTER" | "FILTER_SECURITY_INTERCEPTOR" | "SWITCH_USER_FILTER" | "LAST"
diff --git a/dist/spring-security-config/org/springframework/security/config/spring-security-3.0.4.xsd b/dist/spring-security-config/org/springframework/security/config/spring-security-3.0.4.xsd
deleted file mode 100644
index 15d02c4..0000000
--- a/dist/spring-security-config/org/springframework/security/config/spring-security-3.0.4.xsd
+++ /dev/null
@@ -1,1386 +0,0 @@
-<?xml version="1.0"?>
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:security="http://www.springframework.org/schema/security" elementFormDefault="qualified" targetNamespace="http://www.springframework.org/schema/security">
- <xs:attributeGroup name="hash">
- <xs:attribute name="hash" use="required">
- <xs:annotation>
- <xs:documentation>Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="plaintext"/>
- <xs:enumeration value="sha"/>
- <xs:enumeration value="sha-256"/>
- <xs:enumeration value="md5"/>
- <xs:enumeration value="md4"/>
- <xs:enumeration value="{sha}"/>
- <xs:enumeration value="{ssha}"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="base64">
- <xs:attribute name="base64" use="required">
- <xs:annotation>
- <xs:documentation>Whether a string should be base64 encoded</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="true"/>
- <xs:enumeration value="false"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="path-type">
- <xs:attribute name="path-type" use="required">
- <xs:annotation>
- <xs:documentation>Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="ant"/>
- <xs:enumeration value="regex"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="port">
- <xs:attribute name="port" use="required" type="xs:positiveInteger">
- <xs:annotation>
- <xs:documentation>Specifies an IP port number. Used to configure an embedded LDAP server, for example.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="url">
- <xs:attribute name="url" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>Specifies a URL.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="id">
- <xs:attribute name="id" use="required" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="ref">
- <xs:attribute name="ref" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="cache-ref">
- <xs:attribute name="cache-ref" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>Defines a reference to a cache for use with a UserDetailsService.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-service-ref">
- <xs:attribute name="user-service-ref" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean) Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="data-source-ref">
- <xs:attribute name="data-source-ref" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>A reference to a DataSource bean</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="password-encoder.attlist">
- <xs:attribute name="ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="hash">
- <xs:annotation>
- <xs:documentation>Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="plaintext"/>
- <xs:enumeration value="sha"/>
- <xs:enumeration value="sha-256"/>
- <xs:enumeration value="md5"/>
- <xs:enumeration value="md4"/>
- <xs:enumeration value="{sha}"/>
- <xs:enumeration value="{ssha}"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="base64">
- <xs:annotation>
- <xs:documentation>Whether a string should be base64 encoded</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="true"/>
- <xs:enumeration value="false"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="user-property">
- <xs:attribute name="user-property" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="system-wide">
- <xs:attribute name="system-wide" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>A single value that will be used as the salt for a password encoder.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:simpleType name="boolean">
- <xs:restriction base="xs:token">
- <xs:enumeration value="true"/>
- <xs:enumeration value="false"/>
- </xs:restriction>
- </xs:simpleType>
- <xs:attributeGroup name="role-prefix">
- <xs:attribute name="role-prefix" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="use-expressions">
- <xs:attribute name="use-expressions" use="required" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Enables the use of expressions in the 'access' attributes in <intercept-url> elements rather than the traditional list of configuration attributes. Defaults to 'false'. If enabled, each attribute should contain a single boolean expression. If the expression evaluates to 'true', access will be granted.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="ldap-server"><xs:annotation>
- <xs:documentation>Defines an LDAP server location or starts an embedded server. The url indicates the location of a remote server. If no url is given, an embedded server will be started, listening on the supplied port number. The port is optional and defaults to 33389. A Spring LDAP ContextSource bean will be registered for the server with the id supplied.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:ldap-server.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="ldap-server.attlist">
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="url" type="xs:token">
- <xs:annotation>
- <xs:documentation>Specifies a URL.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="port" type="xs:positiveInteger">
- <xs:annotation>
- <xs:documentation>Specifies an IP port number. Used to configure an embedded LDAP server, for example.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="manager-dn" type="xs:string">
- <xs:annotation>
- <xs:documentation>Username (DN) of the "manager" user identity which will be used to authenticate to a (non-embedded) LDAP server. If omitted, anonymous access will be used.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="manager-password" type="xs:string">
- <xs:annotation>
- <xs:documentation>The password for the manager DN.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="ldif" type="xs:string">
- <xs:annotation>
- <xs:documentation>Explicitly specifies an ldif file resource to load into an embedded LDAP server</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="root" type="xs:string">
- <xs:annotation>
- <xs:documentation>Optional root suffix for the embedded LDAP server. Default is "dc=springframework,dc=org"</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="ldap-server-ref-attribute">
- <xs:attribute name="server-ref" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>The optional server to use. If omitted, and a default LDAP server is registered (using <ldap-server> with no Id), that server will be used.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="group-search-filter-attribute">
- <xs:attribute name="group-search-filter" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="group-search-base-attribute">
- <xs:attribute name="group-search-base" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>Search base for group membership searches. Defaults to "" (searching from the root).</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-search-filter-attribute">
- <xs:attribute name="user-search-filter" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>The LDAP filter used to search for users (optional). For example "(uid={0})". The substituted parameter is the user's login name.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-search-base-attribute">
- <xs:attribute name="user-search-base" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>Search base for user searches. Defaults to "". Only used with a 'user-search-filter'.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="group-role-attribute-attribute">
- <xs:attribute name="group-role-attribute" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-details-class-attribute">
- <xs:attribute name="user-details-class" use="required">
- <xs:annotation>
- <xs:documentation>Allows the objectClass of the user entry to be specified. If set, the framework will attempt to load standard attributes for the defined class into the returned UserDetails object</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="person"/>
- <xs:enumeration value="inetOrgPerson"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-context-mapper-attribute">
- <xs:attribute name="user-context-mapper-ref" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>Allows explicit customization of the loaded user object by specifying a UserDetailsContextMapper bean which will be called with the context information from the user's directory entry</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="ldap-user-service" substitutionGroup="security:any-user-service"><xs:complexType>
- <xs:attributeGroup ref="security:ldap-us.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="ldap-us.attlist">
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="server-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>The optional server to use. If omitted, and a default LDAP server is registered (using <ldap-server> with no Id), that server will be used.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-search-filter" type="xs:token">
- <xs:annotation>
- <xs:documentation>The LDAP filter used to search for users (optional). For example "(uid={0})". The substituted parameter is the user's login name.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-search-base" type="xs:token">
- <xs:annotation>
- <xs:documentation>Search base for user searches. Defaults to "". Only used with a 'user-search-filter'.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-search-filter" type="xs:token">
- <xs:annotation>
- <xs:documentation>Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-search-base" type="xs:token">
- <xs:annotation>
- <xs:documentation>Search base for group membership searches. Defaults to "" (searching from the root).</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-role-attribute" type="xs:token">
- <xs:annotation>
- <xs:documentation>The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="cache-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Defines a reference to a cache for use with a UserDetailsService.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="role-prefix" type="xs:token">
- <xs:annotation>
- <xs:documentation>A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-details-class">
- <xs:annotation>
- <xs:documentation>Allows the objectClass of the user entry to be specified. If set, the framework will attempt to load standard attributes for the defined class into the returned UserDetails object</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="person"/>
- <xs:enumeration value="inetOrgPerson"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="user-context-mapper-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Allows explicit customization of the loaded user object by specifying a UserDetailsContextMapper bean which will be called with the context information from the user's directory entry</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="ldap-ap.attlist">
- <xs:attribute name="server-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>The optional server to use. If omitted, and a default LDAP server is registered (using <ldap-server> with no Id), that server will be used.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-search-base" type="xs:token">
- <xs:annotation>
- <xs:documentation>Search base for user searches. Defaults to "". Only used with a 'user-search-filter'.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-search-filter" type="xs:token">
- <xs:annotation>
- <xs:documentation>The LDAP filter used to search for users (optional). For example "(uid={0})". The substituted parameter is the user's login name.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-search-base" type="xs:token">
- <xs:annotation>
- <xs:documentation>Search base for group membership searches. Defaults to "" (searching from the root).</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-search-filter" type="xs:token">
- <xs:annotation>
- <xs:documentation>Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-role-attribute" type="xs:token">
- <xs:annotation>
- <xs:documentation>The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-dn-pattern" type="xs:token">
- <xs:annotation>
- <xs:documentation>A specific pattern used to build the user's DN, for example "uid={0},ou=people". The key "{0}" must be present and will be substituted with the username.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="role-prefix" type="xs:token">
- <xs:annotation>
- <xs:documentation>A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-details-class">
- <xs:annotation>
- <xs:documentation>Allows the objectClass of the user entry to be specified. If set, the framework will attempt to load standard attributes for the defined class into the returned UserDetails object</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="person"/>
- <xs:enumeration value="inetOrgPerson"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="user-context-mapper-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Allows explicit customization of the loaded user object by specifying a UserDetailsContextMapper bean which will be called with the context information from the user's directory entry</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="password-compare.attlist">
- <xs:attribute name="password-attribute" type="xs:token">
- <xs:annotation>
- <xs:documentation>The attribute in the directory which contains the user password. Defaults to "userPassword".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="hash">
- <xs:annotation>
- <xs:documentation>Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="plaintext"/>
- <xs:enumeration value="sha"/>
- <xs:enumeration value="sha-256"/>
- <xs:enumeration value="md5"/>
- <xs:enumeration value="md4"/>
- <xs:enumeration value="{sha}"/>
- <xs:enumeration value="{ssha}"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="intercept-methods"><xs:annotation>
- <xs:documentation>Can be used inside a bean definition to add a security interceptor to the bean and set up access configuration attributes for the bean's methods</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" name="protect"><xs:annotation>
- <xs:documentation>Defines a protected method and the access control configuration attributes that apply to it. We strongly advise you NOT to mix "protect" declarations with any services provided "global-method-security".</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:protect.attlist"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:intercept-methods.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="intercept-methods.attlist">
- <xs:attribute name="access-decision-manager-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Optional AccessDecisionManager bean ID to be used by the created method security interceptor.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="protect.attlist">
- <xs:attribute name="method" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>A method name</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>Access configuration attributes list that applies to the method, e.g. "ROLE_A,ROLE_B".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="global-method-security"><xs:annotation>
- <xs:documentation>Provides method security for all beans registered in the Spring application context. Specifically, beans will be scanned for matches with the ordered list of "protect-pointcut" sub-elements, Spring Security annotations and/or. Where there is a match, the beans will automatically be proxied and security authorization applied to the methods accordingly. If you use and enable all four sources of method security metadata (ie "protect-pointcut" declarations, expression annotations, @Secured and also JSR250 security annotations), the metadata sources will be queried in that order. In practical terms, this enables you to use XML to override method security metadata expressed in annotations. If using annotations, the order of precedence is EL-based (@PreAuthorize etc.), @Secured and finally JSR-250.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:choice minOccurs="0">
- <xs:element name="pre-post-annotation-handling"><xs:annotation>
- <xs:documentation>Allows the default expression-based mechanism for handling Spring Security's pre and post invocation annotations (@PreFilter, @PreAuthorize, @PostFilter, @PostAuthorize) to be replace entirely. Only applies if these annotations are enabled.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element name="invocation-attribute-factory"><xs:annotation>
- <xs:documentation>Defines the PrePostInvocationAttributeFactory instance which is used to generate pre and post invocation metadata from the annotated methods.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:ref"/>
- </xs:complexType></xs:element>
- <xs:element name="pre-invocation-advice"><xs:complexType>
- <xs:attributeGroup ref="security:ref"/>
- </xs:complexType></xs:element>
- <xs:element name="post-invocation-advice"><xs:complexType>
- <xs:attributeGroup ref="security:ref"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- </xs:complexType></xs:element>
- <xs:element name="expression-handler"><xs:annotation>
- <xs:documentation>Defines the SecurityExpressionHandler instance which will be used if expression-based access-control is enabled. A default implementation (with no ACL support) will be used if not supplied.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:ref"/>
- </xs:complexType></xs:element>
- </xs:choice>
- <xs:element minOccurs="0" maxOccurs="unbounded" name="protect-pointcut"><xs:annotation>
- <xs:documentation>Defines a protected pointcut and the access control configuration attributes that apply to it. Every bean registered in the Spring application context that provides a method that matches the pointcut will receive security authorization.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:protect-pointcut.attlist"/>
- </xs:complexType></xs:element>
- <xs:element minOccurs="0" maxOccurs="unbounded" name="after-invocation-provider"><xs:annotation>
- <xs:documentation>Allows addition of extra AfterInvocationProvider beans which should be called by the MethodSecurityInterceptor created by global-method-security.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:ref"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:global-method-security.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="global-method-security.attlist">
- <xs:attribute name="pre-post-annotations">
- <xs:annotation>
- <xs:documentation>Specifies whether the use of Spring Security's pre and post invocation annotations (@PreFilter, @PreAuthorize, @PostFilter, @PostAuthorize) should be enabled for this application context. Defaults to "disabled".</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="disabled"/>
- <xs:enumeration value="enabled"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="secured-annotations">
- <xs:annotation>
- <xs:documentation>Specifies whether the use of Spring Security's @Secured annotations should be enabled for this application context. Defaults to "disabled".</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="disabled"/>
- <xs:enumeration value="enabled"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="jsr250-annotations">
- <xs:annotation>
- <xs:documentation>Specifies whether JSR-250 style attributes are to be used (for example "RolesAllowed"). This will require the javax.annotation.security classes on the classpath. Defaults to "disabled".</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="disabled"/>
- <xs:enumeration value="enabled"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="access-decision-manager-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Optional AccessDecisionManager bean ID to override the default used for method security.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="run-as-manager-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Optional RunAsmanager implementation which will be used by the configured MethodSecurityInterceptor</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="order" type="xs:token">
- <xs:annotation>
- <xs:documentation>Allows the advice "order" to be set for the method security interceptor.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="proxy-target-class" type="security:boolean"/>
- <xs:attribute name="mode">
- <xs:annotation>
- <xs:documentation>Can be used to specify that AspectJ should be used instead of the default Spring AOP. If set, secured classes must be woven with the AnnotationSecurityAspect from the spring-security-aspects module.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="aspectj"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
-
-
-
-
-
-
-
- <xs:attributeGroup name="protect-pointcut.attlist">
- <xs:attribute name="expression" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>An AspectJ expression, including the 'execution' keyword. For example, 'execution(int com.foo.TargetObject.countLength(String))' (without the quotes).</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>Access configuration attributes list that applies to all methods matching the pointcut, e.g. "ROLE_A,ROLE_B"</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="http-firewall"><xs:annotation>
- <xs:documentation>Allows a custom instance of HttpFirewall to be injected into the FilterChainProxy created by the namespace.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:ref"/>
- </xs:complexType></xs:element>
- <xs:element name="http"><xs:annotation>
- <xs:documentation>Container element for HTTP security configuration</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element name="intercept-url"><xs:annotation>
- <xs:documentation>Specifies the access attributes and/or filter list for a particular set of URLs.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:intercept-url.attlist"/>
- </xs:complexType></xs:element>
- <xs:element name="access-denied-handler"><xs:annotation>
- <xs:documentation>Defines the access-denied strategy that should be used. An access denied page can be defined or a reference to an AccessDeniedHandler instance.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:access-denied-handler.attlist"/>
- </xs:complexType></xs:element>
- <xs:element name="form-login"><xs:annotation>
- <xs:documentation>Sets up a form login configuration for authentication with a username and password</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:form-login.attlist"/>
- </xs:complexType></xs:element>
- <xs:element name="openid-login"><xs:annotation>
- <xs:documentation>Sets up form login for authentication with an Open ID identity</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="security:attribute-exchange"/>
- </xs:sequence>
- <xs:attributeGroup ref="security:form-login.attlist"/>
- <xs:attribute name="user-service-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean) Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:complexType></xs:element>
- <xs:element name="x509"><xs:annotation>
- <xs:documentation>Adds support for X.509 client authentication.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:x509.attlist"/>
- </xs:complexType></xs:element>
- <xs:element name="http-basic"><xs:annotation>
- <xs:documentation>Adds support for basic authentication (this is an element to permit future expansion, such as supporting an "ignoreFailure" attribute)</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:http-basic.attlist"/>
- </xs:complexType></xs:element>
- <xs:element name="logout"><xs:annotation>
- <xs:documentation>Incorporates a logout processing filter. Most web applications require a logout filter, although you may not require one if you write a controller to provider similar logic.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:logout.attlist"/>
- </xs:complexType></xs:element>
- <xs:element name="session-management"><xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="concurrency-control"><xs:annotation>
- <xs:documentation>Enables concurrent session control, limiting the number of authenticated sessions a user may have at the same time.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:concurrency-control.attlist"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:session-management.attlist"/>
- </xs:complexType></xs:element>
- <xs:element name="remember-me"><xs:annotation>
- <xs:documentation>Sets up remember-me authentication. If used with the "key" attribute (or no attributes) the cookie-only implementation will be used. Specifying "token-repository-ref" or "remember-me-data-source-ref" will use the more secure, persisten token approach.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:remember-me.attlist"/>
- </xs:complexType></xs:element>
- <xs:element name="anonymous"><xs:annotation>
- <xs:documentation>Adds support for automatically granting all anonymous web requests a particular principal identity and a corresponding granted authority.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:anonymous.attlist"/>
- </xs:complexType></xs:element>
- <xs:element name="port-mappings"><xs:annotation>
- <xs:documentation>Defines the list of mappings between http and https ports for use in redirects</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" name="port-mapping"><xs:complexType>
- <xs:attributeGroup ref="security:http-port"/>
- <xs:attributeGroup ref="security:https-port"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- </xs:complexType></xs:element>
- <xs:element ref="security:custom-filter"/>
- <xs:element ref="security:request-cache"/>
- </xs:choice>
- <xs:attributeGroup ref="security:http.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="http.attlist">
- <xs:attribute name="auto-config" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Automatically registers a login form, BASIC authentication, anonymous authentication, logout services, remember-me and servlet-api-integration. If set to "true", all of these capabilities are added (although you can still customize the configuration of each by providing the respective element). If unspecified, defaults to "false".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="use-expressions" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Enables the use of expressions in the 'access' attributes in <intercept-url> elements rather than the traditional list of configuration attributes. Defaults to 'false'. If enabled, each attribute should contain a single boolean expression. If the expression evaluates to 'true', access will be granted.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="create-session">
- <xs:annotation>
- <xs:documentation>Controls the eagerness with which an HTTP session is created. If not set, defaults to "ifRequired". Note that if a custom SecurityContextRepository is set using security-context-repository-ref, then the only value which can be set is "always". Otherwise the session creation behaviour will be determined by the repository bean implementation.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="ifRequired"/>
- <xs:enumeration value="always"/>
- <xs:enumeration value="never"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="security-context-repository-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>A reference to a SecurityContextRepository bean. This can be used to customize how the SecurityContext is stored between requests.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="path-type">
- <xs:annotation>
- <xs:documentation>Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="ant"/>
- <xs:enumeration value="regex"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="lowercase-comparisons" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Whether test URLs should be converted to lower case prior to comparing with defined path patterns. If unspecified, defaults to "true".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="servlet-api-provision" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Provides versions of HttpServletRequest security methods such as isUserInRole() and getPrincipal() which are implemented by accessing the Spring SecurityContext. Defaults to "true".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access-decision-manager-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Optional attribute specifying the ID of the AccessDecisionManager implementation which should be used for authorizing HTTP requests.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="realm" type="xs:token">
- <xs:annotation>
- <xs:documentation>Optional attribute specifying the realm name that will be used for all authentication features that require a realm name (eg BASIC and Digest authentication). If unspecified, defaults to "Spring Security Application".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="entry-point-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Allows a customized AuthenticationEntryPoint to be set on the ExceptionTranslationFilter.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="once-per-request" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Corresponds to the observeOncePerRequest property of FilterSecurityInterceptor. Defaults to "true"</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access-denied-page" type="xs:token">
- <xs:annotation>
- <xs:documentation>Deprecated in favour of the access-denied-handler element.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="disable-url-rewriting" type="security:boolean">
- <xs:annotation>
- <xs:documentation/>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="access-denied-handler.attlist">
- <xs:attribute name="ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="error-page" type="xs:token">
- <xs:annotation>
- <xs:documentation>The access denied page that an authenticated user will be redirected to if they request a page which they don't have the authority to access.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="access-denied-handler-page">
- <xs:attribute name="error-page" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>The access denied page that an authenticated user will be redirected to if they request a page which they don't have the authority to access.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="intercept-url.attlist">
- <xs:attribute name="pattern" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>The pattern which defines the URL path. The content will depend on the type set in the containing http element, so will default to ant path syntax.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access" type="xs:token">
- <xs:annotation>
- <xs:documentation>The access configuration attributes that apply for the configured path.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="method">
- <xs:annotation>
- <xs:documentation>The HTTP Method for which the access configuration attributes should apply. If not specified, the attributes will apply to any method.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="GET"/>
- <xs:enumeration value="DELETE"/>
- <xs:enumeration value="HEAD"/>
- <xs:enumeration value="OPTIONS"/>
- <xs:enumeration value="POST"/>
- <xs:enumeration value="PUT"/>
- <xs:enumeration value="TRACE"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="filters">
- <xs:annotation>
- <xs:documentation>The filter list for the path. Currently can be set to "none" to remove a path from having any filters applied. The full filter stack (consisting of all filters created by the namespace configuration, and any added using 'custom-filter'), will be applied to any other paths.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="none"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="requires-channel" type="xs:token">
- <xs:annotation>
- <xs:documentation>Used to specify that a URL must be accessed over http or https, or that there is no preference. The value should be "http", "https" or "any", respectively.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="logout.attlist">
- <xs:attribute name="logout-url" type="xs:token">
- <xs:annotation>
- <xs:documentation>Specifies the URL that will cause a logout. Spring Security will initialize a filter that responds to this particular URL. Defaults to /j_spring_security_logout if unspecified.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="logout-success-url" type="xs:token">
- <xs:annotation>
- <xs:documentation>Specifies the URL to display once the user has logged out. If not specified, defaults to /.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="invalidate-session" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Specifies whether a logout also causes HttpSession invalidation, which is generally desirable. If unspecified, defaults to true.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="success-handler-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>A reference to a LogoutSuccessHandler implementation which will be used to determine the destination to which the user is taken after logging out.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="request-cache"><xs:annotation>
- <xs:documentation>Allow the RequestCache used for saving requests during the login process to be set</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:ref"/>
- </xs:complexType></xs:element>
-
- <xs:attributeGroup name="form-login.attlist">
- <xs:attribute name="login-processing-url" type="xs:token">
- <xs:annotation>
- <xs:documentation>The URL that the login form is posted to. If unspecified, it defaults to /j_spring_security_check.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="default-target-url" type="xs:token">
- <xs:annotation>
- <xs:documentation>The URL that will be redirected to after successful authentication, if the user's previous action could not be resumed. This generally happens if the user visits a login page without having first requested a secured operation that triggers authentication. If unspecified, defaults to the root of the application.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="always-use-default-target" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Whether the user should always be redirected to the default-target-url after login.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="login-page" type="xs:token">
- <xs:annotation>
- <xs:documentation>The URL for the login page. If no login URL is specified, Spring Security will automatically create a login URL at /spring_security_login and a corresponding filter to render that login URL when requested.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="authentication-failure-url" type="xs:token">
- <xs:annotation>
- <xs:documentation>The URL for the login failure page. If no login failure URL is specified, Spring Security will automatically create a failure login URL at /spring_security_login?login_error and a corresponding filter to render that login failure URL when requested.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="authentication-success-handler-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Reference to an AuthenticationSuccessHandler bean which should be used to handle a successful authentication request. Should not be used in combination with default-target-url (or always-use-default-target-url) as the implementation should always deal with navigation to the subsequent destination</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="authentication-failure-handler-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Reference to an AuthenticationFailureHandler bean which should be used to handle a failed authentication request. Should not be used in combination with authentication-failure-url as the implementation should always deal with navigation to the subsequent destination</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:element name="attribute-exchange"><xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="security:openid-attribute"/>
- </xs:sequence>
- </xs:complexType></xs:element>
- <xs:element name="openid-attribute"><xs:complexType>
- <xs:attributeGroup ref="security:openid-attribute.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="openid-attribute.attlist">
- <xs:attribute name="name" use="required" type="xs:token"/>
- <xs:attribute name="type" use="required" type="xs:token"/>
- <xs:attribute name="required" type="security:boolean"/>
- <xs:attribute name="count" type="xs:int"/>
- </xs:attributeGroup>
- <xs:element name="filter-chain-map"><xs:annotation>
- <xs:documentation>Used to explicitly configure a FilterChainProxy instance with a FilterChainMap</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" name="filter-chain"><xs:annotation>
- <xs:documentation>Used within filter-chain-map to define a specific URL pattern and the list of filters which apply to the URLs matching that pattern. When multiple filter-chain elements are used within a filter-chain-map element, the most specific patterns must be placed at the top of the list, with most general ones at the bottom.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:filter-chain.attlist"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:filter-chain-map.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="filter-chain-map.attlist">
- <xs:attributeGroup ref="security:path-type"/>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="filter-chain.attlist">
- <xs:attribute name="pattern" use="required" type="xs:token"/>
- <xs:attribute name="filters" use="required" type="xs:token"/>
- </xs:attributeGroup>
- <xs:element name="filter-security-metadata-source"><xs:annotation>
- <xs:documentation>Used to explicitly configure a FilterSecurityMetadataSource bean for use with a FilterSecurityInterceptor. Usually only needed if you are configuring a FilterChainProxy explicitly, rather than using the <http> element. The intercept-url elements used should only contain pattern, method and access attributes. Any others will result in a configuration error.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" name="intercept-url"><xs:annotation>
- <xs:documentation>Specifies the access attributes and/or filter list for a particular set of URLs.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:intercept-url.attlist"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:fsmds.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="fsmds.attlist">
- <xs:attribute name="use-expressions" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Enables the use of expressions in the 'access' attributes in <intercept-url> elements rather than the traditional list of configuration attributes. Defaults to 'false'. If enabled, each attribute should contain a single boolean expression. If the expression evaluates to 'true', access will be granted.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="lowercase-comparisons" type="security:boolean">
- <xs:annotation>
- <xs:documentation>as for http element</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="path-type">
- <xs:annotation>
- <xs:documentation>Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="ant"/>
- <xs:enumeration value="regex"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="filter-invocation-definition-source"><xs:annotation>
- <xs:documentation>Deprecated synonym for filter-security-metadata-source</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" name="intercept-url"><xs:annotation>
- <xs:documentation>Specifies the access attributes and/or filter list for a particular set of URLs.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:intercept-url.attlist"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:fsmds.attlist"/>
- </xs:complexType></xs:element>
-
- <xs:attributeGroup name="http-basic.attlist">
- <xs:attribute name="entry-point-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Sets the AuthenticationEntryPoint which is used by the BasicAuthenticationFilter.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="session-management.attlist">
- <xs:attribute name="session-fixation-protection">
- <xs:annotation>
- <xs:documentation>Indicates whether an existing session should be invalidated when a user authenticates and a new session started. If set to "none" no change will be made. "newSession" will create a new empty session. "migrateSession" will create a new session and copy the session attributes to the new session. Defaults to "migrateSession".</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="none"/>
- <xs:enumeration value="newSession"/>
- <xs:enumeration value="migrateSession"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="invalid-session-url" type="xs:token">
- <xs:annotation>
- <xs:documentation>The URL to which a user will be redirected if they submit an invalid session indentifier. Typically used to detect session timeouts.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="session-authentication-strategy-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Allows injection of the SessionAuthenticationStrategy instance used by the SessionManagementFilter</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="session-authentication-error-url" type="xs:token">
- <xs:annotation>
- <xs:documentation>Defines the URL of the error page which should be shown when the SessionAuthenticationStrategy raises an exception. If not set, an unauthorized (402) error code will be returned to the client. Note that this attribute doesn't apply if the error occurs during a form-based login, where the URL for authentication failure will take precedence.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="concurrency-control.attlist">
- <xs:attribute name="max-sessions" type="xs:positiveInteger">
- <xs:annotation>
- <xs:documentation>The maximum number of sessions a single authenticated user can have open at the same time. Defaults to "1".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="expired-url" type="xs:token">
- <xs:annotation>
- <xs:documentation>The URL a user will be redirected to if they attempt to use a session which has been "expired" because they have logged in again.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="error-if-maximum-exceeded" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Specifies that an unauthorized error should be reported when a user attempts to login when they already have the maximum configured sessions open. The default behaviour is to expire the original session. If the session-authentication-error-url attribute is set on the session-management URL, the user will be redirected to this URL.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="session-registry-alias" type="xs:token">
- <xs:annotation>
- <xs:documentation>Allows you to define an alias for the SessionRegistry bean in order to access it in your own configuration.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="session-registry-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Allows you to define an external SessionRegistry bean to be used by the concurrency control setup.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="remember-me.attlist">
- <xs:attribute name="key" type="xs:token">
- <xs:annotation>
- <xs:documentation>The "key" used to identify cookies from a specific token-based remember-me application. You should set this to a unique value for your application.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="token-repository-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Reference to a PersistentTokenRepository bean for use with the persistent token remember-me implementation.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="data-source-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>A reference to a DataSource bean</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attributeGroup ref="security:remember-me-services-ref"/>
- <xs:attribute name="user-service-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean) Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="services-alias" type="xs:token">
- <xs:annotation>
- <xs:documentation>Exports the internally defined RememberMeServices as a bean alias, allowing it to be used by other beans in the application context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="use-secure-cookie" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Determines whether the "secure" flag will be set on the remember-me cookie. If set to true, the cookie will only be submitted over HTTPS. Defaults to false.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="token-validity-seconds" type="xs:integer">
- <xs:annotation>
- <xs:documentation>The period (in seconds) for which the remember-me cookie should be valid.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="token-repository-ref">
- <xs:attribute name="token-repository-ref" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>Reference to a PersistentTokenRepository bean for use with the persistent token remember-me implementation.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="remember-me-services-ref">
- <xs:attribute name="services-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Allows a custom implementation of RememberMeServices to be used. Note that this implementation should return RememberMeAuthenticationToken instances with the same "key" value as specified in the remember-me element. Alternatively it should register its own AuthenticationProvider.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="remember-me-data-source-ref">
- <xs:attributeGroup ref="security:data-source-ref"/>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="anonymous.attlist">
- <xs:attribute name="key" type="xs:token">
- <xs:annotation>
- <xs:documentation>The key shared between the provider and filter. This generally does not need to be set. If unset, it will default to "doesNotMatter".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="username" type="xs:token">
- <xs:annotation>
- <xs:documentation>The username that should be assigned to the anonymous request. This allows the principal to be identified, which may be important for logging and auditing. if unset, defaults to "anonymousUser".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="granted-authority" type="xs:token">
- <xs:annotation>
- <xs:documentation>The granted authority that should be assigned to the anonymous request. Commonly this is used to assign the anonymous request particular roles, which can subsequently be used in authorization decisions. If unset, defaults to "ROLE_ANONYMOUS".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="enabled" type="security:boolean">
- <xs:annotation>
- <xs:documentation>With the default namespace setup, the anonymous "authentication" facility is automatically enabled. You can disable it using this property.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
-
- <xs:attributeGroup name="http-port">
- <xs:attribute name="http" use="required" type="xs:token"/>
- </xs:attributeGroup>
- <xs:attributeGroup name="https-port">
- <xs:attribute name="https" use="required" type="xs:token"/>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="x509.attlist">
- <xs:attribute name="subject-principal-regex" type="xs:token">
- <xs:annotation>
- <xs:documentation>The regular expression used to obtain the username from the certificate's subject. Defaults to matching on the common name using the pattern "CN=(.*?),".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-service-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean) Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="authentication-manager"><xs:annotation>
- <xs:documentation>Registers the AuthenticationManager instance and allows its list of AuthenticationProviders to be defined. Also allows you to define an alias to allow you to reference the AuthenticationManager in your own beans.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element name="authentication-provider"><xs:annotation>
- <xs:documentation>Indicates that the contained user-service should be used as an authentication source.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="security:any-user-service"/>
- <xs:element name="password-encoder"><xs:annotation>
- <xs:documentation>element which defines a password encoding strategy. Used by an authentication provider to convert submitted passwords to hashed versions, for example.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="salt-source"><xs:annotation>
- <xs:documentation>Password salting strategy. A system-wide constant or a property from the UserDetails object can be used.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attribute name="user-property" type="xs:token">
- <xs:annotation>
- <xs:documentation>A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="system-wide" type="xs:token">
- <xs:annotation>
- <xs:documentation>A single value that will be used as the salt for a password encoder.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:password-encoder.attlist"/>
- </xs:complexType></xs:element>
- </xs:choice>
- <xs:attributeGroup ref="security:ap.attlist"/>
- </xs:complexType></xs:element>
- <xs:element name="ldap-authentication-provider"><xs:annotation>
- <xs:documentation>Sets up an ldap authentication provider</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="password-compare"><xs:annotation>
- <xs:documentation>Specifies that an LDAP provider should use an LDAP compare operation of the user's password to authenticate the user</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="password-encoder"><xs:annotation>
- <xs:documentation>element which defines a password encoding strategy. Used by an authentication provider to convert submitted passwords to hashed versions, for example.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="salt-source"><xs:annotation>
- <xs:documentation>Password salting strategy. A system-wide constant or a property from the UserDetails object can be used.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attribute name="user-property" type="xs:token">
- <xs:annotation>
- <xs:documentation>A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="system-wide" type="xs:token">
- <xs:annotation>
- <xs:documentation>A single value that will be used as the salt for a password encoder.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:password-encoder.attlist"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:password-compare.attlist"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:ldap-ap.attlist"/>
- </xs:complexType></xs:element>
- </xs:choice>
- <xs:attributeGroup ref="security:authman.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="authman.attlist">
- <xs:attribute name="alias" type="xs:ID">
- <xs:annotation>
- <xs:documentation>The alias you wish to use for the AuthenticationManager bean</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="erase-credentials" type="security:boolean">
- <xs:annotation>
- <xs:documentation>If set to true, the AuthenticationManger will attempt to clear any credentials data in the returned Authentication object, once the user has been authenticated. Defaults to false.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="ap.attlist">
- <xs:attribute name="ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-service-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean) Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="user-service" substitutionGroup="security:any-user-service"><xs:annotation>
- <xs:documentation>Creates an in-memory UserDetailsService from a properties file or a list of "user" child elements.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" name="user"><xs:annotation>
- <xs:documentation>Represents a user in the application.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:user.attlist"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attributeGroup ref="security:properties-file"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="properties-file">
- <xs:attribute name="properties" type="xs:token"/>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="user.attlist">
- <xs:attribute name="name" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>The username assigned to the user.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="password" type="xs:string">
- <xs:annotation>
- <xs:documentation>The password assigned to the user. This may be hashed if the corresponding authentication provider supports hashing (remember to set the "hash" attribute of the "user-service" element). This attribute be omitted in the case where the data will not be used for authentication, but only for accessing authorities. If omitted, the namespace will generate a random value, preventing its accidental use for authentication. Cannot be empty.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="authorities" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>One of more authorities granted to the user. Separate authorities with a comma (but no space). For example, "ROLE_USER,ROLE_ADMINISTRATOR"</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="locked" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Can be set to "true" to mark an account as locked and unusable.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="disabled" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Can be set to "true" to mark an account as disabled and unusable.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="jdbc-user-service" substitutionGroup="security:any-user-service"><xs:annotation>
- <xs:documentation>Causes creation of a JDBC-based UserDetailsService.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attributeGroup ref="security:jdbc-user-service.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="jdbc-user-service.attlist">
- <xs:attribute name="data-source-ref" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>The bean ID of the DataSource which provides the required tables.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="cache-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Defines a reference to a cache for use with a UserDetailsService.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="users-by-username-query" type="xs:token">
- <xs:annotation>
- <xs:documentation>An SQL statement to query a username, password, and enabled status given a username</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="authorities-by-username-query" type="xs:token">
- <xs:annotation>
- <xs:documentation>An SQL statement to query for a user's granted authorities given a username.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-authorities-by-username-query" type="xs:token">
- <xs:annotation>
- <xs:documentation>An SQL statement to query user's group authorities given a username.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="role-prefix" type="xs:token">
- <xs:annotation>
- <xs:documentation>A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="any-user-service" abstract="true"/>
- <xs:element name="custom-filter"><xs:annotation>
- <xs:documentation>Used to indicate that a filter bean declaration should be incorporated into the security filter chain.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:custom-filter.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="custom-filter.attlist">
- <xs:attributeGroup ref="security:ref"/>
- <xs:attribute name="after" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The filter immediately after which the custom-filter should be placed in the chain. This feature will only be needed by advanced users who wish to mix their own filters into the security filter chain and have some knowledge of the standard Spring Security filters. The filter names map to specific Spring Security implementation filters.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="before" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The filter immediately before which the custom-filter should be placed in the chain</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="position" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The explicit position at which the custom-filter should be placed in the chain. Use if you are replacing a standard filter.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="after">
- <xs:attribute name="after" use="required" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The filter immediately after which the custom-filter should be placed in the chain. This feature will only be needed by advanced users who wish to mix their own filters into the security filter chain and have some knowledge of the standard Spring Security filters. The filter names map to specific Spring Security implementation filters.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="before">
- <xs:attribute name="before" use="required" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The filter immediately before which the custom-filter should be placed in the chain</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="position">
- <xs:attribute name="position" use="required" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The explicit position at which the custom-filter should be placed in the chain. Use if you are replacing a standard filter.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:simpleType name="named-security-filter">
- <xs:restriction base="xs:token">
- <xs:enumeration value="FIRST"/>
- <xs:enumeration value="CHANNEL_FILTER"/>
- <xs:enumeration value="CONCURRENT_SESSION_FILTER"/>
- <xs:enumeration value="SECURITY_CONTEXT_FILTER"/>
- <xs:enumeration value="LOGOUT_FILTER"/>
- <xs:enumeration value="X509_FILTER"/>
- <xs:enumeration value="PRE_AUTH_FILTER"/>
- <xs:enumeration value="CAS_FILTER"/>
- <xs:enumeration value="FORM_LOGIN_FILTER"/>
- <xs:enumeration value="OPENID_FILTER"/>
- <xs:enumeration value="BASIC_AUTH_FILTER"/>
- <xs:enumeration value="SERVLET_API_SUPPORT_FILTER"/>
- <xs:enumeration value="REMEMBER_ME_FILTER"/>
- <xs:enumeration value="ANONYMOUS_FILTER"/>
- <xs:enumeration value="EXCEPTION_TRANSLATION_FILTER"/>
- <xs:enumeration value="SESSION_MANAGEMENT_FILTER"/>
- <xs:enumeration value="FILTER_SECURITY_INTERCEPTOR"/>
- <xs:enumeration value="SWITCH_USER_FILTER"/>
- <xs:enumeration value="LAST"/>
- </xs:restriction>
- </xs:simpleType>
-</xs:schema>
diff --git a/dist/spring-security-config/org/springframework/security/config/spring-security-3.0.xsd b/dist/spring-security-config/org/springframework/security/config/spring-security-3.0.xsd
deleted file mode 100644
index de2df47..0000000
--- a/dist/spring-security-config/org/springframework/security/config/spring-security-3.0.xsd
+++ /dev/null
@@ -1,1357 +0,0 @@
-<?xml version="1.0"?>
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:security="http://www.springframework.org/schema/security" elementFormDefault="qualified" targetNamespace="http://www.springframework.org/schema/security">
- <xs:attributeGroup name="hash">
- <xs:attribute name="hash" use="required">
- <xs:annotation>
- <xs:documentation>Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="plaintext"/>
- <xs:enumeration value="sha"/>
- <xs:enumeration value="sha-256"/>
- <xs:enumeration value="md5"/>
- <xs:enumeration value="md4"/>
- <xs:enumeration value="{sha}"/>
- <xs:enumeration value="{ssha}"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="base64">
- <xs:attribute name="base64" use="required">
- <xs:annotation>
- <xs:documentation>Whether a string should be base64 encoded</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="true"/>
- <xs:enumeration value="false"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="path-type">
- <xs:attribute name="path-type" use="required">
- <xs:annotation>
- <xs:documentation>Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="ant"/>
- <xs:enumeration value="regex"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="port">
- <xs:attribute name="port" use="required" type="xs:positiveInteger">
- <xs:annotation>
- <xs:documentation>Specifies an IP port number. Used to configure an embedded LDAP server, for example.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="url">
- <xs:attribute name="url" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>Specifies a URL.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="id">
- <xs:attribute name="id" use="required" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="ref">
- <xs:attribute name="ref" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="cache-ref">
- <xs:attribute name="cache-ref" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>Defines a reference to a cache for use with a UserDetailsService.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-service-ref">
- <xs:attribute name="user-service-ref" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean) Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="data-source-ref">
- <xs:attribute name="data-source-ref" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>A reference to a DataSource bean</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="password-encoder.attlist">
- <xs:attribute name="ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="hash">
- <xs:annotation>
- <xs:documentation>Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="plaintext"/>
- <xs:enumeration value="sha"/>
- <xs:enumeration value="sha-256"/>
- <xs:enumeration value="md5"/>
- <xs:enumeration value="md4"/>
- <xs:enumeration value="{sha}"/>
- <xs:enumeration value="{ssha}"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="base64">
- <xs:annotation>
- <xs:documentation>Whether a string should be base64 encoded</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="true"/>
- <xs:enumeration value="false"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="user-property">
- <xs:attribute name="user-property" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="system-wide">
- <xs:attribute name="system-wide" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>A single value that will be used as the salt for a password encoder. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:simpleType name="boolean">
- <xs:restriction base="xs:token">
- <xs:enumeration value="true"/>
- <xs:enumeration value="false"/>
- </xs:restriction>
- </xs:simpleType>
- <xs:attributeGroup name="role-prefix">
- <xs:attribute name="role-prefix" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="use-expressions">
- <xs:attribute name="use-expressions" use="required" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Enables the use of expressions in the 'access' attributes in <intercept-url> elements rather than the traditional list of configuration attributes. Defaults to 'false'. If enabled, each attribute should contain a single boolean expression. If the expression evaluates to 'true', access will be granted. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="ldap-server"><xs:annotation>
- <xs:documentation>Defines an LDAP server location or starts an embedded server. The url indicates the location of a remote server. If no url is given, an embedded server will be started, listening on the supplied port number. The port is optional and defaults to 33389. A Spring LDAP ContextSource bean will be registered for the server with the id supplied. </xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:ldap-server.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="ldap-server.attlist">
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="url" type="xs:token">
- <xs:annotation>
- <xs:documentation>Specifies a URL.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="port" type="xs:positiveInteger">
- <xs:annotation>
- <xs:documentation>Specifies an IP port number. Used to configure an embedded LDAP server, for example.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="manager-dn" type="xs:string">
- <xs:annotation>
- <xs:documentation>Username (DN) of the "manager" user identity which will be used to authenticate to a (non-embedded) LDAP server. If omitted, anonymous access will be used. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="manager-password" type="xs:string">
- <xs:annotation>
- <xs:documentation>The password for the manager DN.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="ldif" type="xs:string">
- <xs:annotation>
- <xs:documentation>Explicitly specifies an ldif file resource to load into an embedded LDAP server</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="root" type="xs:string">
- <xs:annotation>
- <xs:documentation>Optional root suffix for the embedded LDAP server. Default is "dc=springframework,dc=org"</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="ldap-server-ref-attribute">
- <xs:attribute name="server-ref" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>The optional server to use. If omitted, and a default LDAP server is registered (using <ldap-server> with no Id), that server will be used. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="group-search-filter-attribute">
- <xs:attribute name="group-search-filter" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="group-search-base-attribute">
- <xs:attribute name="group-search-base" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>Search base for group membership searches. Defaults to "" (searching from the root).</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-search-filter-attribute">
- <xs:attribute name="user-search-filter" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>The LDAP filter used to search for users (optional). For example "(uid={0})". The substituted parameter is the user's login name.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-search-base-attribute">
- <xs:attribute name="user-search-base" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>Search base for user searches. Defaults to "". Only used with a 'user-search-filter'.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="group-role-attribute-attribute">
- <xs:attribute name="group-role-attribute" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-details-class-attribute">
- <xs:attribute name="user-details-class" use="required">
- <xs:annotation>
- <xs:documentation>Allows the objectClass of the user entry to be specified. If set, the framework will attempt to load standard attributes for the defined class into the returned UserDetails object</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="person"/>
- <xs:enumeration value="inetOrgPerson"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="user-context-mapper-attribute">
- <xs:attribute name="user-context-mapper-ref" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>Allows explicit customization of the loaded user object by specifying a UserDetailsContextMapper bean which will be called with the context information from the user's directory entry</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="ldap-user-service" substitutionGroup="security:any-user-service"><xs:complexType>
- <xs:attributeGroup ref="security:ldap-us.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="ldap-us.attlist">
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="server-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>The optional server to use. If omitted, and a default LDAP server is registered (using <ldap-server> with no Id), that server will be used. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-search-filter" type="xs:token">
- <xs:annotation>
- <xs:documentation>The LDAP filter used to search for users (optional). For example "(uid={0})". The substituted parameter is the user's login name.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-search-base" type="xs:token">
- <xs:annotation>
- <xs:documentation>Search base for user searches. Defaults to "". Only used with a 'user-search-filter'.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-search-filter" type="xs:token">
- <xs:annotation>
- <xs:documentation>Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-search-base" type="xs:token">
- <xs:annotation>
- <xs:documentation>Search base for group membership searches. Defaults to "" (searching from the root).</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-role-attribute" type="xs:token">
- <xs:annotation>
- <xs:documentation>The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="cache-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Defines a reference to a cache for use with a UserDetailsService.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="role-prefix" type="xs:token">
- <xs:annotation>
- <xs:documentation>A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-details-class">
- <xs:annotation>
- <xs:documentation>Allows the objectClass of the user entry to be specified. If set, the framework will attempt to load standard attributes for the defined class into the returned UserDetails object</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="person"/>
- <xs:enumeration value="inetOrgPerson"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="user-context-mapper-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Allows explicit customization of the loaded user object by specifying a UserDetailsContextMapper bean which will be called with the context information from the user's directory entry</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="ldap-ap.attlist">
- <xs:attribute name="server-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>The optional server to use. If omitted, and a default LDAP server is registered (using <ldap-server> with no Id), that server will be used. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-search-base" type="xs:token">
- <xs:annotation>
- <xs:documentation>Search base for user searches. Defaults to "". Only used with a 'user-search-filter'.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-search-filter" type="xs:token">
- <xs:annotation>
- <xs:documentation>The LDAP filter used to search for users (optional). For example "(uid={0})". The substituted parameter is the user's login name.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-search-base" type="xs:token">
- <xs:annotation>
- <xs:documentation>Search base for group membership searches. Defaults to "" (searching from the root).</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-search-filter" type="xs:token">
- <xs:annotation>
- <xs:documentation>Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-role-attribute" type="xs:token">
- <xs:annotation>
- <xs:documentation>The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-dn-pattern" type="xs:token">
- <xs:annotation>
- <xs:documentation>A specific pattern used to build the user's DN, for example "uid={0},ou=people". The key "{0}" must be present and will be substituted with the username.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="role-prefix" type="xs:token">
- <xs:annotation>
- <xs:documentation>A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-details-class">
- <xs:annotation>
- <xs:documentation>Allows the objectClass of the user entry to be specified. If set, the framework will attempt to load standard attributes for the defined class into the returned UserDetails object</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="person"/>
- <xs:enumeration value="inetOrgPerson"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="user-context-mapper-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Allows explicit customization of the loaded user object by specifying a UserDetailsContextMapper bean which will be called with the context information from the user's directory entry</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="password-compare.attlist">
- <xs:attribute name="password-attribute" type="xs:token">
- <xs:annotation>
- <xs:documentation>The attribute in the directory which contains the user password. Defaults to "userPassword".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="hash">
- <xs:annotation>
- <xs:documentation>Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="plaintext"/>
- <xs:enumeration value="sha"/>
- <xs:enumeration value="sha-256"/>
- <xs:enumeration value="md5"/>
- <xs:enumeration value="md4"/>
- <xs:enumeration value="{sha}"/>
- <xs:enumeration value="{ssha}"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="intercept-methods"><xs:annotation>
- <xs:documentation>Can be used inside a bean definition to add a security interceptor to the bean and set up access configuration attributes for the bean's methods</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" name="protect"><xs:annotation>
- <xs:documentation>Defines a protected method and the access control configuration attributes that apply to it. We strongly advise you NOT to mix "protect" declarations with any services provided "global-method-security".</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:protect.attlist"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:intercept-methods.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="intercept-methods.attlist">
- <xs:attribute name="access-decision-manager-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Optional AccessDecisionManager bean ID to be used by the created method security interceptor.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="protect.attlist">
- <xs:attribute name="method" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>A method name</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>Access configuration attributes list that applies to the method, e.g. "ROLE_A,ROLE_B".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="global-method-security"><xs:annotation>
- <xs:documentation>Provides method security for all beans registered in the Spring application context. Specifically, beans will be scanned for matches with the ordered list of "protect-pointcut" sub-elements, Spring Security annotations and/or. Where there is a match, the beans will automatically be proxied and security authorization applied to the methods accordingly. If you use and enable all four sources of method security metadata (ie "protect-pointcut" declarations, expression annotations, @Secured and also JSR250 security annotations), the metadata sources will be queried in that order. In practical terms, this enables you to use XML to override method security metadata expressed in annotations. If using annotations, the order of precedence is EL-based (@PreAuthorize etc.), @Secured and finally JSR-250.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:choice minOccurs="0">
- <xs:element name="pre-post-annotation-handling"><xs:annotation>
- <xs:documentation>Allows the default expression-based mechanism for handling Spring Security's pre and post invocation annotations (@PreFilter, @PreAuthorize, @PostFilter, @PostAuthorize) to be replace entirely. Only applies if these annotations are enabled. </xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element name="invocation-attribute-factory"><xs:annotation>
- <xs:documentation>Defines the PrePostInvocationAttributeFactory instance which is used to generate pre and post invocation metadata from the annotated methods. </xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:ref"/>
- </xs:complexType></xs:element>
- <xs:element name="pre-invocation-advice"><xs:complexType>
- <xs:attributeGroup ref="security:ref"/>
- </xs:complexType></xs:element>
- <xs:element name="post-invocation-advice"><xs:complexType>
- <xs:attributeGroup ref="security:ref"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- </xs:complexType></xs:element>
- <xs:element name="expression-handler"><xs:annotation>
- <xs:documentation>Defines the SecurityExpressionHandler instance which will be used if expression-based access-control is enabled. A default implementation (with no ACL support) will be used if not supplied.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:ref"/>
- </xs:complexType></xs:element>
- </xs:choice>
- <xs:element minOccurs="0" maxOccurs="unbounded" name="protect-pointcut"><xs:annotation>
- <xs:documentation>Defines a protected pointcut and the access control configuration attributes that apply to it. Every bean registered in the Spring application context that provides a method that matches the pointcut will receive security authorization.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:protect-pointcut.attlist"/>
- </xs:complexType></xs:element>
- <xs:element minOccurs="0" maxOccurs="unbounded" name="after-invocation-provider"><xs:annotation>
- <xs:documentation>Allows addition of extra AfterInvocationProvider beans which should be called by the MethodSecurityInterceptor created by global-method-security.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:ref"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:global-method-security.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="global-method-security.attlist">
- <xs:attribute name="pre-post-annotations">
- <xs:annotation>
- <xs:documentation>Specifies whether the use of Spring Security's pre and post invocation annotations (@PreFilter, @PreAuthorize, @PostFilter, @PostAuthorize) should be enabled for this application context. Defaults to "disabled".</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="disabled"/>
- <xs:enumeration value="enabled"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="secured-annotations">
- <xs:annotation>
- <xs:documentation>Specifies whether the use of Spring Security's @Secured annotations should be enabled for this application context. Defaults to "disabled".</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="disabled"/>
- <xs:enumeration value="enabled"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="jsr250-annotations">
- <xs:annotation>
- <xs:documentation>Specifies whether JSR-250 style attributes are to be used (for example "RolesAllowed"). This will require the javax.annotation.security classes on the classpath. Defaults to "disabled".</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="disabled"/>
- <xs:enumeration value="enabled"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="access-decision-manager-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Optional AccessDecisionManager bean ID to override the default used for method security.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="run-as-manager-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Optional RunAsmanager implementation which will be used by the configured MethodSecurityInterceptor</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="order" type="xs:token">
- <xs:annotation>
- <xs:documentation>Allows the advice "order" to be set for the method security interceptor.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="proxy-target-class" type="security:boolean"/>
- </xs:attributeGroup>
-
-
-
-
-
-
-
- <xs:attributeGroup name="protect-pointcut.attlist">
- <xs:attribute name="expression" use="required" type="xs:string">
- <xs:annotation>
- <xs:documentation>An AspectJ expression, including the 'execution' keyword. For example, 'execution(int com.foo.TargetObject.countLength(String))' (without the quotes).</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>Access configuration attributes list that applies to all methods matching the pointcut, e.g. "ROLE_A,ROLE_B"</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="http"><xs:annotation>
- <xs:documentation>Container element for HTTP security configuration</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element name="intercept-url"><xs:annotation>
- <xs:documentation>Specifies the access attributes and/or filter list for a particular set of URLs.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:intercept-url.attlist"/>
- </xs:complexType></xs:element>
- <xs:element name="access-denied-handler"><xs:annotation>
- <xs:documentation>Defines the access-denied strategy that should be used. An access denied page can be defined or a reference to an AccessDeniedHandler instance. </xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:access-denied-handler.attlist"/>
- </xs:complexType></xs:element>
- <xs:element name="form-login"><xs:annotation>
- <xs:documentation>Sets up a form login configuration for authentication with a username and password</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:form-login.attlist"/>
- </xs:complexType></xs:element>
- <xs:element name="openid-login"><xs:annotation>
- <xs:documentation>Sets up form login for authentication with an Open ID identity</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="security:attribute-exchange"/>
- </xs:sequence>
- <xs:attributeGroup ref="security:form-login.attlist"/>
- <xs:attribute name="user-service-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean) Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:complexType></xs:element>
- <xs:element name="x509"><xs:annotation>
- <xs:documentation>Adds support for X.509 client authentication.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:x509.attlist"/>
- </xs:complexType></xs:element>
- <xs:element name="http-basic"><xs:annotation>
- <xs:documentation>Adds support for basic authentication (this is an element to permit future expansion, such as supporting an "ignoreFailure" attribute)</xs:documentation>
- </xs:annotation><xs:complexType/></xs:element>
- <xs:element name="logout"><xs:annotation>
- <xs:documentation>Incorporates a logout processing filter. Most web applications require a logout filter, although you may not require one if you write a controller to provider similar logic.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:logout.attlist"/>
- </xs:complexType></xs:element>
- <xs:element name="session-management"><xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="concurrency-control"><xs:annotation>
- <xs:documentation>Enables concurrent session control, limiting the number of authenticated sessions a user may have at the same time.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:concurrency-control.attlist"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:session-management.attlist"/>
- </xs:complexType></xs:element>
- <xs:element name="remember-me"><xs:annotation>
- <xs:documentation>Sets up remember-me authentication. If used with the "key" attribute (or no attributes) the cookie-only implementation will be used. Specifying "token-repository-ref" or "remember-me-data-source-ref" will use the more secure, persisten token approach. </xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:remember-me.attlist"/>
- </xs:complexType></xs:element>
- <xs:element name="anonymous"><xs:annotation>
- <xs:documentation>Adds support for automatically granting all anonymous web requests a particular principal identity and a corresponding granted authority.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:anonymous.attlist"/>
- </xs:complexType></xs:element>
- <xs:element name="port-mappings"><xs:annotation>
- <xs:documentation>Defines the list of mappings between http and https ports for use in redirects</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" name="port-mapping"><xs:complexType>
- <xs:attributeGroup ref="security:http-port"/>
- <xs:attributeGroup ref="security:https-port"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- </xs:complexType></xs:element>
- <xs:element ref="security:custom-filter"/>
- <xs:element ref="security:request-cache"/>
- </xs:choice>
- <xs:attributeGroup ref="security:http.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="http.attlist">
- <xs:attribute name="auto-config" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Automatically registers a login form, BASIC authentication, anonymous authentication, logout services, remember-me and servlet-api-integration. If set to "true", all of these capabilities are added (although you can still customize the configuration of each by providing the respective element). If unspecified, defaults to "false".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="use-expressions" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Enables the use of expressions in the 'access' attributes in <intercept-url> elements rather than the traditional list of configuration attributes. Defaults to 'false'. If enabled, each attribute should contain a single boolean expression. If the expression evaluates to 'true', access will be granted. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="create-session">
- <xs:annotation>
- <xs:documentation>Controls the eagerness with which an HTTP session is created. If not set, defaults to "ifRequired". Note that if a custom SecurityContextRepository is set using security-context-repository-ref, then the only value which can be set is "always". Otherwise the session creation behaviour will be determined by the repository bean implementation.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="ifRequired"/>
- <xs:enumeration value="always"/>
- <xs:enumeration value="never"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="security-context-repository-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>A reference to a SecurityContextRepository bean. This can be used to customize how the SecurityContext is stored between requests.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="path-type">
- <xs:annotation>
- <xs:documentation>Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="ant"/>
- <xs:enumeration value="regex"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="lowercase-comparisons" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Whether test URLs should be converted to lower case prior to comparing with defined path patterns. If unspecified, defaults to "true".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="servlet-api-provision" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Provides versions of HttpServletRequest security methods such as isUserInRole() and getPrincipal() which are implemented by accessing the Spring SecurityContext. Defaults to "true".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access-decision-manager-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Optional attribute specifying the ID of the AccessDecisionManager implementation which should be used for authorizing HTTP requests.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="realm" type="xs:token">
- <xs:annotation>
- <xs:documentation>Optional attribute specifying the realm name that will be used for all authentication features that require a realm name (eg BASIC and Digest authentication). If unspecified, defaults to "Spring Security Application".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="entry-point-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Allows a customized AuthenticationEntryPoint to be used.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="once-per-request" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Corresponds to the observeOncePerRequest property of FilterSecurityInterceptor. Defaults to "true"</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access-denied-page" type="xs:token">
- <xs:annotation>
- <xs:documentation>Deprecated in favour of the access-denied-handler element.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="disable-url-rewriting" type="security:boolean">
- <xs:annotation>
- <xs:documentation> </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="access-denied-handler.attlist">
- <xs:attribute name="ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="error-page" type="xs:token">
- <xs:annotation>
- <xs:documentation>The access denied page that an authenticated user will be redirected to if they request a page which they don't have the authority to access. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="access-denied-handler-page">
- <xs:attribute name="error-page" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>The access denied page that an authenticated user will be redirected to if they request a page which they don't have the authority to access. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="intercept-url.attlist">
- <xs:attribute name="pattern" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>The pattern which defines the URL path. The content will depend on the type set in the containing http element, so will default to ant path syntax.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="access" type="xs:token">
- <xs:annotation>
- <xs:documentation>The access configuration attributes that apply for the configured path.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="method">
- <xs:annotation>
- <xs:documentation>The HTTP Method for which the access configuration attributes should apply. If not specified, the attributes will apply to any method.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="GET"/>
- <xs:enumeration value="DELETE"/>
- <xs:enumeration value="HEAD"/>
- <xs:enumeration value="OPTIONS"/>
- <xs:enumeration value="POST"/>
- <xs:enumeration value="PUT"/>
- <xs:enumeration value="TRACE"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="filters">
- <xs:annotation>
- <xs:documentation>The filter list for the path. Currently can be set to "none" to remove a path from having any filters applied. The full filter stack (consisting of all filters created by the namespace configuration, and any added using 'custom-filter'), will be applied to any other paths.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="none"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="requires-channel" type="xs:token">
- <xs:annotation>
- <xs:documentation>Used to specify that a URL must be accessed over http or https, or that there is no preference. The value should be "http", "https" or "any", respectively.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="logout.attlist">
- <xs:attribute name="logout-url" type="xs:token">
- <xs:annotation>
- <xs:documentation>Specifies the URL that will cause a logout. Spring Security will initialize a filter that responds to this particular URL. Defaults to /j_spring_security_logout if unspecified.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="logout-success-url" type="xs:token">
- <xs:annotation>
- <xs:documentation>Specifies the URL to display once the user has logged out. If not specified, defaults to /.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="invalidate-session" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Specifies whether a logout also causes HttpSession invalidation, which is generally desirable. If unspecified, defaults to true.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="success-handler-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>A reference to a LogoutSuccessHandler implementation which will be used to determine the destination to which the user is taken after logging out.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="request-cache"><xs:annotation>
- <xs:documentation>Allow the RequestCache used for saving requests during the login process to be set</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:ref"/>
- </xs:complexType></xs:element>
-
- <xs:attributeGroup name="form-login.attlist">
- <xs:attribute name="login-processing-url" type="xs:token">
- <xs:annotation>
- <xs:documentation>The URL that the login form is posted to. If unspecified, it defaults to /j_spring_security_check.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="default-target-url" type="xs:token">
- <xs:annotation>
- <xs:documentation>The URL that will be redirected to after successful authentication, if the user's previous action could not be resumed. This generally happens if the user visits a login page without having first requested a secured operation that triggers authentication. If unspecified, defaults to the root of the application.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="always-use-default-target" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Whether the user should always be redirected to the default-target-url after login. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="login-page" type="xs:token">
- <xs:annotation>
- <xs:documentation>The URL for the login page. If no login URL is specified, Spring Security will automatically create a login URL at /spring_security_login and a corresponding filter to render that login URL when requested.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="authentication-failure-url" type="xs:token">
- <xs:annotation>
- <xs:documentation>The URL for the login failure page. If no login failure URL is specified, Spring Security will automatically create a failure login URL at /spring_security_login?login_error and a corresponding filter to render that login failure URL when requested.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="authentication-success-handler-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Reference to an AuthenticationSuccessHandler bean which should be used to handle a successful authentication request. Should not be used in combination with default-target-url (or always-use-default-target-url) as the implementation should always deal with navigation to the subsequent destination</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="authentication-failure-handler-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Reference to an AuthenticationFailureHandler bean which should be used to handle a failed authentication request. Should not be used in combination with authentication-failure-url as the implementation should always deal with navigation to the subsequent destination</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:element name="attribute-exchange"><xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="security:openid-attribute"/>
- </xs:sequence>
- </xs:complexType></xs:element>
- <xs:element name="openid-attribute"><xs:complexType>
- <xs:attributeGroup ref="security:openid-attribute.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="openid-attribute.attlist">
- <xs:attribute name="name" use="required" type="xs:token"/>
- <xs:attribute name="type" use="required" type="xs:token"/>
- <xs:attribute name="required" type="security:boolean"/>
- <xs:attribute name="count" type="xs:int"/>
- </xs:attributeGroup>
- <xs:element name="filter-chain-map"><xs:annotation>
- <xs:documentation>Used to explicitly configure a FilterChainProxy instance with a FilterChainMap</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" name="filter-chain"><xs:annotation>
- <xs:documentation>Used within filter-chain-map to define a specific URL pattern and the list of filters which apply to the URLs matching that pattern. When multiple filter-chain elements are used within a filter-chain-map element, the most specific patterns must be placed at the top of the list, with most general ones at the bottom.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:filter-chain.attlist"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:filter-chain-map.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="filter-chain-map.attlist">
- <xs:attributeGroup ref="security:path-type"/>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="filter-chain.attlist">
- <xs:attribute name="pattern" use="required" type="xs:token"/>
- <xs:attribute name="filters" use="required" type="xs:token"/>
- </xs:attributeGroup>
- <xs:element name="filter-security-metadata-source"><xs:annotation>
- <xs:documentation>Used to explicitly configure a FilterSecurityMetadataSource bean for use with a FilterSecurityInterceptor. Usually only needed if you are configuring a FilterChainProxy explicitly, rather than using the <http> element. The intercept-url elements used should only contain pattern, method and access attributes. Any others will result in a configuration error. </xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" name="intercept-url"><xs:annotation>
- <xs:documentation>Specifies the access attributes and/or filter list for a particular set of URLs.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:intercept-url.attlist"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:fsmds.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="fsmds.attlist">
- <xs:attribute name="use-expressions" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Enables the use of expressions in the 'access' attributes in <intercept-url> elements rather than the traditional list of configuration attributes. Defaults to 'false'. If enabled, each attribute should contain a single boolean expression. If the expression evaluates to 'true', access will be granted. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="lowercase-comparisons" type="security:boolean">
- <xs:annotation>
- <xs:documentation>as for http element</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="path-type">
- <xs:annotation>
- <xs:documentation>Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="ant"/>
- <xs:enumeration value="regex"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="filter-invocation-definition-source"><xs:annotation>
- <xs:documentation>Deprecated synonym for filter-security-metadata-source</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" name="intercept-url"><xs:annotation>
- <xs:documentation>Specifies the access attributes and/or filter list for a particular set of URLs.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:intercept-url.attlist"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:fsmds.attlist"/>
- </xs:complexType></xs:element>
-
-
- <xs:attributeGroup name="session-management.attlist">
- <xs:attribute name="session-fixation-protection">
- <xs:annotation>
- <xs:documentation>Indicates whether an existing session should be invalidated when a user authenticates and a new session started. If set to "none" no change will be made. "newSession" will create a new empty session. "migrateSession" will create a new session and copy the session attributes to the new session. Defaults to "migrateSession".</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="none"/>
- <xs:enumeration value="newSession"/>
- <xs:enumeration value="migrateSession"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="invalid-session-url" type="xs:token">
- <xs:annotation>
- <xs:documentation>The URL to which a user will be redirected if they submit an invalid session indentifier. Typically used to detect session timeouts.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="session-authentication-strategy-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Allows injection of the SessionAuthenticationStrategy instance used by the SessionManagementFilter</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="session-authentication-error-url" type="xs:token">
- <xs:annotation>
- <xs:documentation>Defines the URL of the error page which should be shown when the SessionAuthenticationStrategy raises an exception. If not set, an unauthorized (402) error code will be returned to the client. Note that this attribute doesn't apply if the error occurs during a form-based login, where the URL for authentication failure will take precedence. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="concurrency-control.attlist">
- <xs:attribute name="max-sessions" type="xs:positiveInteger">
- <xs:annotation>
- <xs:documentation>The maximum number of sessions a single authenticated user can have open at the same time. Defaults to "1".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="expired-url" type="xs:token">
- <xs:annotation>
- <xs:documentation>The URL a user will be redirected to if they attempt to use a session which has been "expired" because they have logged in again.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="error-if-maximum-exceeded" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Specifies that an unauthorized error should be reported when a user attempts to login when they already have the maximum configured sessions open. The default behaviour is to expire the original session. If the session-authentication-error-url attribute is set on the session-management URL, the user will be redirected to this URL.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="session-registry-alias" type="xs:token">
- <xs:annotation>
- <xs:documentation>Allows you to define an alias for the SessionRegistry bean in order to access it in your own configuration.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="session-registry-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Allows you to define an external SessionRegistry bean to be used by the concurrency control setup.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="remember-me.attlist">
- <xs:attribute name="key" type="xs:token">
- <xs:annotation>
- <xs:documentation>The "key" used to identify cookies from a specific token-based remember-me application. You should set this to a unique value for your application.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="token-repository-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Reference to a PersistentTokenRepository bean for use with the persistent token remember-me implementation. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="data-source-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>A reference to a DataSource bean</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attributeGroup ref="security:remember-me-services-ref"/>
- <xs:attribute name="user-service-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean) Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="services-alias" type="xs:token">
- <xs:annotation>
- <xs:documentation>Exports the internally defined RememberMeServices as a bean alias, allowing it to be used by other beans in the application context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="use-secure-cookie" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Determines whether the "secure" flag will be set on the remember-me cookie. If set to true, the cookie will only be submitted over HTTPS. Defaults to false.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="token-validity-seconds" type="xs:integer">
- <xs:annotation>
- <xs:documentation>The period (in seconds) for which the remember-me cookie should be valid.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="token-repository-ref">
- <xs:attribute name="token-repository-ref" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>Reference to a PersistentTokenRepository bean for use with the persistent token remember-me implementation. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="remember-me-services-ref">
- <xs:attribute name="services-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Allows a custom implementation of RememberMeServices to be used. Note that this implementation should return RememberMeAuthenticationToken instances with the same "key" value as specified in the remember-me element. Alternatively it should register its own AuthenticationProvider. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="remember-me-data-source-ref">
- <xs:attributeGroup ref="security:data-source-ref"/>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="anonymous.attlist">
- <xs:attribute name="key" type="xs:token">
- <xs:annotation>
- <xs:documentation>The key shared between the provider and filter. This generally does not need to be set. If unset, it will default to "doesNotMatter".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="username" type="xs:token">
- <xs:annotation>
- <xs:documentation>The username that should be assigned to the anonymous request. This allows the principal to be identified, which may be important for logging and auditing. if unset, defaults to "anonymousUser".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="granted-authority" type="xs:token">
- <xs:annotation>
- <xs:documentation>The granted authority that should be assigned to the anonymous request. Commonly this is used to assign the anonymous request particular roles, which can subsequently be used in authorization decisions. If unset, defaults to "ROLE_ANONYMOUS".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="enabled" type="security:boolean">
- <xs:annotation>
- <xs:documentation>With the default namespace setup, the anonymous "authentication" facility is automatically enabled. You can disable it using this property. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
-
- <xs:attributeGroup name="http-port">
- <xs:attribute name="http" use="required" type="xs:token"/>
- </xs:attributeGroup>
- <xs:attributeGroup name="https-port">
- <xs:attribute name="https" use="required" type="xs:token"/>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="x509.attlist">
- <xs:attribute name="subject-principal-regex" type="xs:token">
- <xs:annotation>
- <xs:documentation>The regular expression used to obtain the username from the certificate's subject. Defaults to matching on the common name using the pattern "CN=(.*?),".</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-service-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean) Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="authentication-manager"><xs:annotation>
- <xs:documentation>Registers the AuthenticationManager instance and allows its list of AuthenticationProviders to be defined. Also allows you to define an alias to allow you to reference the AuthenticationManager in your own beans. </xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element name="authentication-provider"><xs:annotation>
- <xs:documentation>Indicates that the contained user-service should be used as an authentication source. </xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="security:any-user-service"/>
- <xs:element name="password-encoder"><xs:annotation>
- <xs:documentation>element which defines a password encoding strategy. Used by an authentication provider to convert submitted passwords to hashed versions, for example.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="salt-source"><xs:annotation>
- <xs:documentation>Password salting strategy. A system-wide constant or a property from the UserDetails object can be used.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attribute name="user-property" type="xs:token">
- <xs:annotation>
- <xs:documentation>A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="system-wide" type="xs:token">
- <xs:annotation>
- <xs:documentation>A single value that will be used as the salt for a password encoder. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:password-encoder.attlist"/>
- </xs:complexType></xs:element>
- </xs:choice>
- <xs:attributeGroup ref="security:ap.attlist"/>
- </xs:complexType></xs:element>
- <xs:element name="ldap-authentication-provider"><xs:annotation>
- <xs:documentation>Sets up an ldap authentication provider</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="password-compare"><xs:annotation>
- <xs:documentation>Specifies that an LDAP provider should use an LDAP compare operation of the user's password to authenticate the user</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="password-encoder"><xs:annotation>
- <xs:documentation>element which defines a password encoding strategy. Used by an authentication provider to convert submitted passwords to hashed versions, for example.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="salt-source"><xs:annotation>
- <xs:documentation>Password salting strategy. A system-wide constant or a property from the UserDetails object can be used.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attribute name="user-property" type="xs:token">
- <xs:annotation>
- <xs:documentation>A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="system-wide" type="xs:token">
- <xs:annotation>
- <xs:documentation>A single value that will be used as the salt for a password encoder. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:password-encoder.attlist"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:password-compare.attlist"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attributeGroup ref="security:ldap-ap.attlist"/>
- </xs:complexType></xs:element>
- </xs:choice>
- <xs:attributeGroup ref="security:authman.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="authman.attlist">
- <xs:attribute name="alias" type="xs:ID">
- <xs:annotation>
- <xs:documentation>The alias you wish to use for the AuthenticationManager bean</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="ap.attlist">
- <xs:attribute name="ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="user-service-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>A reference to a user-service (or UserDetailsService bean) Id</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="user-service" substitutionGroup="security:any-user-service"><xs:annotation>
- <xs:documentation>Creates an in-memory UserDetailsService from a properties file or a list of "user" child elements.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" name="user"><xs:annotation>
- <xs:documentation>Represents a user in the application.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:user.attlist"/>
- </xs:complexType></xs:element>
- </xs:sequence>
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attributeGroup ref="security:properties-file"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="properties-file">
- <xs:attribute name="properties" type="xs:token"/>
- </xs:attributeGroup>
-
- <xs:attributeGroup name="user.attlist">
- <xs:attribute name="name" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>The username assigned to the user.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="password" type="xs:string">
- <xs:annotation>
- <xs:documentation>The password assigned to the user. This may be hashed if the corresponding authentication provider supports hashing (remember to set the "hash" attribute of the "user-service" element). This attribute be omitted in the case where the data will not be used for authentication, but only for accessing authorities. If omitted, the namespace will generate a random value, preventing its accidental use for authentication. Cannot be empty.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="authorities" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>One of more authorities granted to the user. Separate authorities with a comma (but no space). For example, "ROLE_USER,ROLE_ADMINISTRATOR"</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="locked" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Can be set to "true" to mark an account as locked and unusable.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="disabled" type="security:boolean">
- <xs:annotation>
- <xs:documentation>Can be set to "true" to mark an account as disabled and unusable.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="jdbc-user-service" substitutionGroup="security:any-user-service"><xs:annotation>
- <xs:documentation>Causes creation of a JDBC-based UserDetailsService.</xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attribute name="id" type="xs:ID">
- <xs:annotation>
- <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attributeGroup ref="security:jdbc-user-service.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="jdbc-user-service.attlist">
- <xs:attribute name="data-source-ref" use="required" type="xs:token">
- <xs:annotation>
- <xs:documentation>The bean ID of the DataSource which provides the required tables.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="cache-ref" type="xs:token">
- <xs:annotation>
- <xs:documentation>Defines a reference to a cache for use with a UserDetailsService.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="users-by-username-query" type="xs:token">
- <xs:annotation>
- <xs:documentation>An SQL statement to query a username, password, and enabled status given a username</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="authorities-by-username-query" type="xs:token">
- <xs:annotation>
- <xs:documentation>An SQL statement to query for a user's granted authorities given a username.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="group-authorities-by-username-query" type="xs:token">
- <xs:annotation>
- <xs:documentation>An SQL statement to query user's group authorities given a username.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="role-prefix" type="xs:token">
- <xs:annotation>
- <xs:documentation>A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:element name="any-user-service" abstract="true"/>
- <xs:element name="custom-filter"><xs:annotation>
- <xs:documentation>Used to indicate that a filter bean declaration should be incorporated into the security filter chain. </xs:documentation>
- </xs:annotation><xs:complexType>
- <xs:attributeGroup ref="security:custom-filter.attlist"/>
- </xs:complexType></xs:element>
- <xs:attributeGroup name="custom-filter.attlist">
- <xs:attributeGroup ref="security:ref"/>
- <xs:attribute name="after" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The filter immediately after which the custom-filter should be placed in the chain. This feature will only be needed by advanced users who wish to mix their own filters into the security filter chain and have some knowledge of the standard Spring Security filters. The filter names map to specific Spring Security implementation filters. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="before" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The filter immediately before which the custom-filter should be placed in the chain</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="position" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The explicit position at which the custom-filter should be placed in the chain. Use if you are replacing a standard filter.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="after">
- <xs:attribute name="after" use="required" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The filter immediately after which the custom-filter should be placed in the chain. This feature will only be needed by advanced users who wish to mix their own filters into the security filter chain and have some knowledge of the standard Spring Security filters. The filter names map to specific Spring Security implementation filters. </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="before">
- <xs:attribute name="before" use="required" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The filter immediately before which the custom-filter should be placed in the chain</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:attributeGroup name="position">
- <xs:attribute name="position" use="required" type="security:named-security-filter">
- <xs:annotation>
- <xs:documentation>The explicit position at which the custom-filter should be placed in the chain. Use if you are replacing a standard filter.</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:attributeGroup>
- <xs:simpleType name="named-security-filter">
- <xs:restriction base="xs:token">
- <xs:enumeration value="FIRST"/>
- <xs:enumeration value="CHANNEL_FILTER"/>
- <xs:enumeration value="CONCURRENT_SESSION_FILTER"/>
- <xs:enumeration value="SECURITY_CONTEXT_FILTER"/>
- <xs:enumeration value="LOGOUT_FILTER"/>
- <xs:enumeration value="X509_FILTER"/>
- <xs:enumeration value="PRE_AUTH_FILTER"/>
- <xs:enumeration value="CAS_FILTER"/>
- <xs:enumeration value="FORM_LOGIN_FILTER"/>
- <xs:enumeration value="OPENID_FILTER"/>
- <xs:enumeration value="BASIC_AUTH_FILTER"/>
- <xs:enumeration value="SERVLET_API_SUPPORT_FILTER"/>
- <xs:enumeration value="REMEMBER_ME_FILTER"/>
- <xs:enumeration value="ANONYMOUS_FILTER"/>
- <xs:enumeration value="EXCEPTION_TRANSLATION_FILTER"/>
- <xs:enumeration value="SESSION_MANAGEMENT_FILTER"/>
- <xs:enumeration value="FILTER_SECURITY_INTERCEPTOR"/>
- <xs:enumeration value="SWITCH_USER_FILTER"/>
- <xs:enumeration value="LAST"/>
- </xs:restriction>
- </xs:simpleType>
-</xs:schema>
diff --git a/dist/spring-security-config/org/springframework/security/config/spring-security.xsl b/dist/spring-security-config/org/springframework/security/config/spring-security.xsl
deleted file mode 100644
index 7f8922d..0000000
--- a/dist/spring-security-config/org/springframework/security/config/spring-security.xsl
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!--
- XSL to manipulate trang's output XSD file. Contributed by Brian Ewins.
-
--->
-
-<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0">
- <xsl:output method="xml" indent="yes"/>
-
- <xsl:variable name="elts-to-inline">
- <xsl:text>,access-denied-handler,anonymous,session-management,concurrency-control,after-invocation-provider,authentication-provider,ldap-authentication-provider,user,port-mapping,openid-login,expression-handler,filter-chain,form-login,http-basic,intercept-url,logout,password-encoder,port-mappings,port-mapper,password-compare,protect,protect-pointcut,pre-post-annotation-handling,pre-invocation-advice,post-invocation-advice,invocation-attribute-factory,remember-me,salt-source,x509,</xsl:text>
- </xsl:variable>
-
- <xsl:template match="xs:element">
- <xsl:choose>
- <xsl:when test="contains($elts-to-inline, concat(',',substring-after(current()/@ref, ':'),','))">
- <xsl:variable name="node" select="."/>
- <xsl:for-each select="/xs:schema/xs:element[@name=substring-after(current()/@ref, ':')]">
- <xsl:copy>
- <xsl:apply-templates select="$node/@*[local-name() != 'ref']"/>
- <xsl:apply-templates select="@*|*"/>
- </xsl:copy>
- </xsl:for-each>
- </xsl:when>
- <!-- Ignore global elements which have been inlined -->
- <xsl:when test="contains($elts-to-inline, concat(',', at name,','))">
- </xsl:when>
-
- <xsl:otherwise>
- <xsl:copy>
- <xsl:apply-templates select="@*|*"/>
- </xsl:copy>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:template>
-
- <!-- Copy any non-element content -->
- <xsl:template match="text()|@*|*">
- <xsl:copy>
- <xsl:apply-templates select="text()|@*|*"/>
- </xsl:copy>
- </xsl:template>
-
-</xsl:stylesheet>
diff --git a/dist/spring-security-core/META-INF/MANIFEST.MF b/dist/spring-security-core/META-INF/MANIFEST.MF
index 351fd34..58630c0 100644
--- a/dist/spring-security-core/META-INF/MANIFEST.MF
+++ b/dist/spring-security-core/META-INF/MANIFEST.MF
@@ -1,4 +1,2 @@
Manifest-Version: 1.0
-Archiver-Version: Plexus Archiver
-Created-By: 17.1-b03-307 (Apple Inc.)
diff --git a/dist/spring-security-core/org/springframework/security/access/AccessDecisionVoter.java b/dist/spring-security-core/org/springframework/security/access/AccessDecisionVoter.java
index e38bf1c..cfc3715 100644
--- a/dist/spring-security-core/org/springframework/security/access/AccessDecisionVoter.java
+++ b/dist/spring-security-core/org/springframework/security/access/AccessDecisionVoter.java
@@ -22,16 +22,14 @@ import org.springframework.security.core.Authentication;
/**
* Indicates a class is responsible for voting on authorization decisions.
- *
* <p>
- * The coordination of voting (ie polling <code>AccessDecisionVoter</code>s,
+ * The coordination of voting (ie polling {@code AccessDecisionVoter}s,
* tallying their responses, and making the final authorization decision) is
* performed by an {@link org.springframework.security.access.AccessDecisionManager}.
- * </p>
*
* @author Ben Alex
*/
-public interface AccessDecisionVoter {
+public interface AccessDecisionVoter<S> {
//~ Static fields/initializers =====================================================================================
int ACCESS_GRANTED = 1;
@@ -41,20 +39,20 @@ public interface AccessDecisionVoter {
//~ Methods ========================================================================================================
/**
- * Indicates whether this <code>AccessDecisionVoter</code> is able to vote on the passed
- * <code>ConfigAttribute</code>.<p>This allows the <code>AbstractSecurityInterceptor</code> to check every
- * configuration attribute can be consumed by the configured <code>AccessDecisionManager</code> and/or
- * <code>RunAsManager</code> and/or <code>AfterInvocationManager</code>.</p>
+ * Indicates whether this {@code AccessDecisionVoter} is able to vote on the passed {@code ConfigAttribute}.
+ * <p>
+ * This allows the {@code AbstractSecurityInterceptor} to check every configuration attribute can be consumed by
+ * the configured {@code AccessDecisionManager} and/or {@code RunAsManager} and/or {@code AfterInvocationManager}.
*
* @param attribute a configuration attribute that has been configured against the
- * <code>AbstractSecurityInterceptor</code>
+ * {@code AbstractSecurityInterceptor}
*
- * @return true if this <code>AccessDecisionVoter</code> can support the passed configuration attribute
+ * @return true if this {@code AccessDecisionVoter} can support the passed configuration attribute
*/
boolean supports(ConfigAttribute attribute);
/**
- * Indicates whether the <code>AccessDecisionVoter</code> implementation is able to provide access control
+ * Indicates whether the {@code AccessDecisionVoter} implementation is able to provide access control
* votes for the indicated secured object type.
*
* @param clazz the class that is being queried
@@ -65,26 +63,27 @@ public interface AccessDecisionVoter {
/**
* Indicates whether or not access is granted.
- * <p>The decision must be affirmative (<code>ACCESS_GRANTED</code>), negative (<code>ACCESS_DENIED</code>)
- * or the <code>AccessDecisionVoter</code> can abstain (<code>ACCESS_ABSTAIN</code>) from voting.
+ * <p>
+ * The decision must be affirmative ({@code ACCESS_GRANTED}), negative ({@code ACCESS_DENIED})
+ * or the {@code AccessDecisionVoter} can abstain ({@code ACCESS_ABSTAIN}) from voting.
* Under no circumstances should implementing classes return any other value. If a weighting of results is desired,
* this should be handled in a custom {@link org.springframework.security.access.AccessDecisionManager} instead.
- * </p>
- * <p>Unless an <code>AccessDecisionVoter</code> is specifically intended to vote on an access control
+ * <p>
+ * Unless an {@code AccessDecisionVoter} is specifically intended to vote on an access control
* decision due to a passed method invocation or configuration attribute parameter, it must return
- * <code>ACCESS_ABSTAIN</code>. This prevents the coordinating <code>AccessDecisionManager</code> from counting
- * votes from those <code>AccessDecisionVoter</code>s without a legitimate interest in the access control
+ * {@code ACCESS_ABSTAIN}. This prevents the coordinating {@code AccessDecisionManager} from counting
+ * votes from those {@code AccessDecisionVoter}s without a legitimate interest in the access control
* decision.
- * </p>
- * <p>Whilst the method invocation is passed as a parameter to maximise flexibility in making access
- * control decisions, implementing classes must never modify the behaviour of the method invocation (such as
- * calling <Code>MethodInvocation.proceed()</code>).</p>
+ * <p>
+ * Whilst the secured object (such as a {@code MethodInvocation}) is passed as a parameter to maximise flexibility
+ * in making access control decisions, implementing classes should not modify it or cause the represented invocation
+ * to take place (for example, by calling {@code MethodInvocation.proceed()}).
*
- * @param authentication the caller invoking the method
- * @param object the secured object
- * @param attributes the configuration attributes associated with the method being invoked
+ * @param authentication the caller making the invocation
+ * @param object the secured object being invoked
+ * @param attributes the configuration attributes associated with the secured object
*
* @return either {@link #ACCESS_GRANTED}, {@link #ACCESS_ABSTAIN} or {@link #ACCESS_DENIED}
*/
- int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes);
+ int vote(Authentication authentication, S object, Collection<ConfigAttribute> attributes);
}
diff --git a/dist/spring-security-core/org/springframework/security/access/SecurityConfig.java b/dist/spring-security-core/org/springframework/security/access/SecurityConfig.java
index 2254436..8f799a3 100644
--- a/dist/spring-security-core/org/springframework/security/access/SecurityConfig.java
+++ b/dist/spring-security-core/org/springframework/security/access/SecurityConfig.java
@@ -29,7 +29,7 @@ import org.springframework.util.StringUtils;
public class SecurityConfig implements ConfigAttribute {
//~ Instance fields ================================================================================================
- private String attrib;
+ private final String attrib;
//~ Constructors ===================================================================================================
@@ -62,15 +62,19 @@ public class SecurityConfig implements ConfigAttribute {
return this.attrib;
}
- public final static List<ConfigAttribute> createListFromCommaDelimitedString(String access) {
+ public static List<ConfigAttribute> createListFromCommaDelimitedString(String access) {
return createList(StringUtils.commaDelimitedListToStringArray(access));
}
- public final static List<ConfigAttribute> createSingleAttributeList(String access) {
+ /**
+ * @deprecated Use createList instead
+ */
+ @Deprecated
+ public static List<ConfigAttribute> createSingleAttributeList(String access) {
return createList(access);
}
- public final static List<ConfigAttribute> createList(String... attributeNames) {
+ public static List<ConfigAttribute> createList(String... attributeNames) {
Assert.notNull(attributeNames, "You must supply an array of attribute names");
List<ConfigAttribute> attributes = new ArrayList<ConfigAttribute>(attributeNames.length);
diff --git a/dist/spring-security-core/org/springframework/security/access/SecurityMetadataSource.java b/dist/spring-security-core/org/springframework/security/access/SecurityMetadataSource.java
index b063314..efc018d 100644
--- a/dist/spring-security-core/org/springframework/security/access/SecurityMetadataSource.java
+++ b/dist/spring-security-core/org/springframework/security/access/SecurityMetadataSource.java
@@ -31,13 +31,12 @@ public interface SecurityMetadataSource extends AopInfrastructureBean {
//~ Methods ========================================================================================================
/**
- * Accesses the <code>ConfigAttribute</code>s that apply to a given secure object.
- * <p>
- * Returns <code>null</code> if no attributes apply.
+ * Accesses the {@code ConfigAttribute}s that apply to a given secure object.
*
* @param object the object being secured
*
- * @return the attributes that apply to the passed in secured object or null if there are no applicable attributes.
+ * @return the attributes that apply to the passed in secured object. Should return an empty collection if there
+ * are no applicable attributes.
*
* @throws IllegalArgumentException if the passed object is not of a type supported by the
* <code>SecurityMetadataSource</code> implementation
@@ -45,18 +44,18 @@ public interface SecurityMetadataSource extends AopInfrastructureBean {
Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException;
/**
- * If available, returns all of the <code>ConfigAttribute</code>s defined by the implementing class.
+ * If available, returns all of the {@code ConfigAttribute}s defined by the implementing class.
* <p>
* This is used by the {@link AbstractSecurityInterceptor} to perform startup time validation of each
- * <code>ConfigAttribute</code> configured against it.
+ * {@code ConfigAttribute} configured against it.
*
- * @return the <code>ConfigAttribute</code>s or <code>null</code> if unsupported
+ * @return the {@code ConfigAttribute}s or {@code null} if unsupported
*/
Collection<ConfigAttribute> getAllConfigAttributes();
/**
- * Indicates whether the <code>SecurityMetadataSource</code> implementation is able to provide
- * <code>ConfigAttribute</code>s for the indicated secure object type.
+ * Indicates whether the {@code SecurityMetadataSource} implementation is able to provide
+ * {@code ConfigAttribute}s for the indicated secure object type.
*
* @param clazz the class that is being queried
*
diff --git a/dist/spring-security-core/org/springframework/security/access/annotation/Jsr250Voter.java b/dist/spring-security-core/org/springframework/security/access/annotation/Jsr250Voter.java
index 7e21b48..82f6948 100644
--- a/dist/spring-security-core/org/springframework/security/access/annotation/Jsr250Voter.java
+++ b/dist/spring-security-core/org/springframework/security/access/annotation/Jsr250Voter.java
@@ -13,7 +13,7 @@ import org.springframework.security.core.GrantedAuthority;
* @author Ryan Heaton
* @since 2.0
*/
-public class Jsr250Voter implements AccessDecisionVoter {
+public class Jsr250Voter implements AccessDecisionVoter<Object> {
/**
* The specified config attribute is supported if its an instance of a {@link Jsr250SecurityConfig}.
diff --git a/dist/spring-security-core/org/springframework/security/access/annotation/SecuredAnnotationSecurityMetadataSource.java b/dist/spring-security-core/org/springframework/security/access/annotation/SecuredAnnotationSecurityMetadataSource.java
index 162eeb5..f9a8d42 100644
--- a/dist/spring-security-core/org/springframework/security/access/annotation/SecuredAnnotationSecurityMetadataSource.java
+++ b/dist/spring-security-core/org/springframework/security/access/annotation/SecuredAnnotationSecurityMetadataSource.java
@@ -17,41 +17,68 @@ package org.springframework.security.access.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
+import java.util.*;
+import org.springframework.core.GenericTypeResolver;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.access.method.AbstractFallbackMethodSecurityMetadataSource;
+import org.springframework.util.Assert;
/**
* Sources method security metadata from Spring Security's {@link Secured} annotation.
+ * <p>
+ * Can also be used with custom security annotations by injecting an {@link AnnotationMetadataExtractor}.
+ * The annotation type will then be obtained from the generic parameter type supplied to this interface
*
* @author Ben Alex
+ * @author Luke Taylor
*/
+ at SuppressWarnings({"unchecked"})
public class SecuredAnnotationSecurityMetadataSource extends AbstractFallbackMethodSecurityMetadataSource {
+ private AnnotationMetadataExtractor annotationExtractor;
+ private Class<? extends Annotation> annotationType;
+
+ public SecuredAnnotationSecurityMetadataSource() {
+ this(new SecuredAnnotationMetadataExtractor());
+ }
+
+ public SecuredAnnotationSecurityMetadataSource(AnnotationMetadataExtractor annotationMetadataExtractor) {
+ Assert.notNull(annotationMetadataExtractor);
+ annotationExtractor = annotationMetadataExtractor;
+ annotationType = (Class<? extends Annotation>) GenericTypeResolver.resolveTypeArgument(
+ annotationExtractor.getClass(), AnnotationMetadataExtractor.class);
+ Assert.notNull(annotationType, annotationExtractor.getClass().getName()
+ + " must supply a generic parameter for AnnotationMetadataExtractor");
+ }
protected Collection<ConfigAttribute> findAttributes(Class<?> clazz) {
- return processAnnotation(clazz.getAnnotation(Secured.class));
+ return processAnnotation(AnnotationUtils.findAnnotation(clazz, annotationType));
}
protected Collection<ConfigAttribute> findAttributes(Method method, Class<?> targetClass) {
- return processAnnotation(AnnotationUtils.findAnnotation(method, Secured.class));
+ return processAnnotation(AnnotationUtils.findAnnotation(method, annotationType));
}
public Collection<ConfigAttribute> getAllConfigAttributes() {
return null;
}
- private List<ConfigAttribute> processAnnotation(Annotation a) {
- if (a == null || !(a instanceof Secured)) {
+ private Collection<ConfigAttribute> processAnnotation(Annotation a) {
+ if (a == null) {
return null;
}
- String[] attributeTokens = ((Secured) a).value();
+ return annotationExtractor.extractAttributes(a);
+ }
+}
+
+class SecuredAnnotationMetadataExtractor implements AnnotationMetadataExtractor<Secured> {
+
+ public Collection<ConfigAttribute> extractAttributes(Secured secured) {
+ String[] attributeTokens = secured.value();
List<ConfigAttribute> attributes = new ArrayList<ConfigAttribute>(attributeTokens.length);
for(String token : attributeTokens) {
diff --git a/dist/spring-security-core/org/springframework/security/access/expression/SecurityExpressionRoot.java b/dist/spring-security-core/org/springframework/security/access/expression/SecurityExpressionRoot.java
index ac6a10e..3c7b965 100644
--- a/dist/spring-security-core/org/springframework/security/access/expression/SecurityExpressionRoot.java
+++ b/dist/spring-security-core/org/springframework/security/access/expression/SecurityExpressionRoot.java
@@ -1,9 +1,12 @@
package org.springframework.security.access.expression;
+import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
+import org.springframework.context.ApplicationContext;
+import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.core.Authentication;
@@ -28,6 +31,12 @@ public abstract class SecurityExpressionRoot {
/** Allows "denyAll" expression */
public final boolean denyAll = false;
+ private PermissionEvaluator permissionEvaluator;
+ public final String read = "read";
+ public final String write = "write";
+ public final String create = "create";
+ public final String delete = "delete";
+ public final String admin = "administration";
public SecurityExpressionRoot(Authentication a) {
if (a == null) {
@@ -103,7 +112,7 @@ public abstract class SecurityExpressionRoot {
private Set<String> getAuthoritySet() {
if (roles == null) {
roles = new HashSet<String>();
- Collection<GrantedAuthority> userAuthorities = authentication.getAuthorities();
+ Collection<? extends GrantedAuthority> userAuthorities = authentication.getAuthorities();
if (roleHierarchy != null) {
userAuthorities = roleHierarchy.getReachableGrantedAuthorities(userAuthorities);
@@ -114,4 +123,16 @@ public abstract class SecurityExpressionRoot {
return roles;
}
+
+ public boolean hasPermission(Object target, Object permission) {
+ return permissionEvaluator.hasPermission(authentication, target, permission);
+ }
+
+ public boolean hasPermission(Object targetId, String targetType, Object permission) {
+ return permissionEvaluator.hasPermission(authentication, (Serializable)targetId, targetType, permission);
+ }
+
+ public void setPermissionEvaluator(PermissionEvaluator permissionEvaluator) {
+ this.permissionEvaluator = permissionEvaluator;
+ }
}
diff --git a/dist/spring-security-core/org/springframework/security/access/expression/method/DefaultMethodSecurityExpressionHandler.java b/dist/spring-security-core/org/springframework/security/access/expression/method/DefaultMethodSecurityExpressionHandler.java
index b12b0d6..6de5802 100644
--- a/dist/spring-security-core/org/springframework/security/access/expression/method/DefaultMethodSecurityExpressionHandler.java
+++ b/dist/spring-security-core/org/springframework/security/access/expression/method/DefaultMethodSecurityExpressionHandler.java
@@ -1,9 +1,7 @@
package org.springframework.security.access.expression.method;
import java.lang.reflect.Array;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
+import java.util.*;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
@@ -12,57 +10,63 @@ import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
-import org.springframework.expression.ExpressionParser;
-import org.springframework.expression.spel.standard.SpelExpressionParser;
+import org.springframework.expression.spel.support.StandardEvaluationContext;
+import org.springframework.security.access.PermissionCacheOptimizer;
import org.springframework.security.access.PermissionEvaluator;
+import org.springframework.security.access.expression.AbstractSecurityExpressionHandler;
+import org.springframework.security.access.expression.DenyAllPermissionEvaluator;
import org.springframework.security.access.expression.ExpressionUtils;
-import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
-import org.springframework.security.authentication.AuthenticationTrustResolver;
-import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
+import org.springframework.security.access.expression.SecurityExpressionRoot;
import org.springframework.security.core.Authentication;
/**
- * The standard implementation of <tt>SecurityExpressionHandler</tt>.
+ * The standard implementation of {@code MethodSecurityExpressionHandler}.
* <p>
* A single instance should usually be shared amongst the beans that require expression support.
*
* @author Luke Taylor
* @since 3.0
*/
-public class DefaultMethodSecurityExpressionHandler implements MethodSecurityExpressionHandler {
+public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpressionHandler<MethodInvocation> implements MethodSecurityExpressionHandler {
protected final Log logger = LogFactory.getLog(getClass());
private ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
- private PermissionEvaluator permissionEvaluator = new DenyAllPermissionEvaluator();
- private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
- private ExpressionParser expressionParser = new SpelExpressionParser();
- private RoleHierarchy roleHierarchy;
+ private PermissionCacheOptimizer permissionCacheOptimizer = null;
public DefaultMethodSecurityExpressionHandler() {
}
/**
- * Uses a {@link MethodSecurityEvaluationContext} as the <tt>EvaluationContext</tt> implementation and
- * configures it with a {@link MethodSecurityExpressionRoot} instance as the expression root object.
+ * Uses a {@link MethodSecurityEvaluationContext} as the <tt>EvaluationContext</tt> implementation.
*/
- public EvaluationContext createEvaluationContext(Authentication auth, MethodInvocation mi) {
- MethodSecurityEvaluationContext ctx = new MethodSecurityEvaluationContext(auth, mi, parameterNameDiscoverer);
- MethodSecurityExpressionRoot root = new MethodSecurityExpressionRoot(auth);
- root.setTrustResolver(trustResolver);
- root.setPermissionEvaluator(permissionEvaluator);
- root.setRoleHierarchy(roleHierarchy);
- ctx.setRootObject(root);
-
- return ctx;
+ public StandardEvaluationContext createEvaluationContextInternal(Authentication auth, MethodInvocation mi) {
+ return new MethodSecurityEvaluationContext(auth, mi, parameterNameDiscoverer);
}
+ @Override
+ protected SecurityExpressionRoot createSecurityExpressionRoot(Authentication authentication, MethodInvocation invocation) {
+ MethodSecurityExpressionRoot root = new MethodSecurityExpressionRoot(authentication);
+ root.setThis(invocation.getThis());
+ root.setPermissionEvaluator(getPermissionEvaluator());
+
+ return root;
+ }
+
+ /**
+ * Filters the {@code filterTarget} object (which must be either a collection or an array), by evaluating the
+ * supplied expression.
+ * <p>
+ * If a {@code Collection} is used, the original instance will be modified to contain the elements for which
+ * the permission expression evaluates to {@code true}. For an array, a new array instance will be returned.
+ */
@SuppressWarnings("unchecked")
public Object filter(Object filterTarget, Expression filterExpression, EvaluationContext ctx) {
MethodSecurityExpressionRoot rootObject = (MethodSecurityExpressionRoot) ctx.getRootObject().getValue();
+ final boolean debug = logger.isDebugEnabled();
List retainList;
- if (logger.isDebugEnabled()) {
+ if (debug) {
logger.debug("Filtering with expression: " + filterExpression.getExpressionString());
}
@@ -70,9 +74,14 @@ public class DefaultMethodSecurityExpressionHandler implements MethodSecurityExp
Collection collection = (Collection)filterTarget;
retainList = new ArrayList(collection.size());
- if (logger.isDebugEnabled()) {
+ if (debug) {
logger.debug("Filtering collection with " + collection.size() + " elements");
}
+
+ if (permissionCacheOptimizer != null) {
+ permissionCacheOptimizer.cachePermissionsFor(rootObject.getAuthentication(), collection);
+ }
+
for (Object filterObject : (Collection)filterTarget) {
rootObject.setFilterObject(filterObject);
@@ -81,7 +90,7 @@ public class DefaultMethodSecurityExpressionHandler implements MethodSecurityExp
}
}
- if (logger.isDebugEnabled()) {
+ if (debug) {
logger.debug("Retaining elements: " + retainList);
}
@@ -95,19 +104,23 @@ public class DefaultMethodSecurityExpressionHandler implements MethodSecurityExp
Object[] array = (Object[])filterTarget;
retainList = new ArrayList(array.length);
- if (logger.isDebugEnabled()) {
- logger.debug("Filtering collection with " + array.length + " elements");
+ if (debug) {
+ logger.debug("Filtering array with " + array.length + " elements");
}
- for (int i = 0; i < array.length; i++) {
- rootObject.setFilterObject(array[i]);
+ if (permissionCacheOptimizer != null) {
+ permissionCacheOptimizer.cachePermissionsFor(rootObject.getAuthentication(), Arrays.asList(array));
+ }
+
+ for (Object o : array) {
+ rootObject.setFilterObject(o);
if (ExpressionUtils.evaluateAsBoolean(filterExpression, ctx)) {
- retainList.add(array[i]);
+ retainList.add(o);
}
}
- if (logger.isDebugEnabled()) {
+ if (debug) {
logger.debug("Retaining elements: " + retainList);
}
@@ -123,27 +136,15 @@ public class DefaultMethodSecurityExpressionHandler implements MethodSecurityExp
throw new IllegalArgumentException("Filter target must be a collection or array type, but was " + filterTarget);
}
- public ExpressionParser getExpressionParser() {
- return expressionParser;
- }
-
public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) {
this.parameterNameDiscoverer = parameterNameDiscoverer;
}
- public void setPermissionEvaluator(PermissionEvaluator permissionEvaluator) {
- this.permissionEvaluator = permissionEvaluator;
- }
-
- public void setTrustResolver(AuthenticationTrustResolver trustResolver) {
- this.trustResolver = trustResolver;
+ public void setPermissionCacheOptimizer(PermissionCacheOptimizer permissionCacheOptimizer) {
+ this.permissionCacheOptimizer = permissionCacheOptimizer;
}
public void setReturnObject(Object returnObject, EvaluationContext ctx) {
((MethodSecurityExpressionRoot)ctx.getRootObject().getValue()).setReturnObject(returnObject);
}
-
- public void setRoleHierarchy(RoleHierarchy roleHierarchy) {
- this.roleHierarchy = roleHierarchy;
- }
}
diff --git a/dist/spring-security-core/org/springframework/security/access/expression/method/DenyAllPermissionEvaluator.java b/dist/spring-security-core/org/springframework/security/access/expression/method/DenyAllPermissionEvaluator.java
deleted file mode 100644
index 0c1783d..0000000
--- a/dist/spring-security-core/org/springframework/security/access/expression/method/DenyAllPermissionEvaluator.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.springframework.security.access.expression.method;
-
-import java.io.Serializable;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.security.access.PermissionEvaluator;
-import org.springframework.security.core.Authentication;
-
-/**
- * A null PermissionEvaluator which denies all access. Used by default for situations when permission
- * evaluation should not be required.
- *
- * @author Luke Taylor
- * @since 3.0
- */
-class DenyAllPermissionEvaluator implements PermissionEvaluator {
-
- private final Log logger = LogFactory.getLog(getClass());
-
- /**
- * @return false always
- */
- public boolean hasPermission(Authentication authentication, Object target, Object permission) {
- logger.warn("Denying user " + authentication.getName() + " permission '" + permission + "' on object " + target);
- return false;
- }
-
- /**
- * @return false always
- */
- public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType,
- Object permission) {
- logger.warn("Denying user " + authentication.getName() + " permission '" + permission + "' on object with Id '"
- + targetId);
- return false;
- }
-
-}
diff --git a/dist/spring-security-core/org/springframework/security/access/expression/method/ExpressionBasedAnnotationAttributeFactory.java b/dist/spring-security-core/org/springframework/security/access/expression/method/ExpressionBasedAnnotationAttributeFactory.java
index 48b2c50..1617b80 100644
--- a/dist/spring-security-core/org/springframework/security/access/expression/method/ExpressionBasedAnnotationAttributeFactory.java
+++ b/dist/spring-security-core/org/springframework/security/access/expression/method/ExpressionBasedAnnotationAttributeFactory.java
@@ -6,11 +6,7 @@ package org.springframework.security.access.expression.method;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.ParseException;
-import org.springframework.security.access.prepost.PostAuthorize;
-import org.springframework.security.access.prepost.PostFilter;
import org.springframework.security.access.prepost.PostInvocationAttribute;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.security.access.prepost.PreFilter;
import org.springframework.security.access.prepost.PreInvocationAttribute;
import org.springframework.security.access.prepost.PrePostInvocationAttributeFactory;
@@ -22,28 +18,27 @@ import org.springframework.security.access.prepost.PrePostInvocationAttributeFac
* @since 3.0
*/
public class ExpressionBasedAnnotationAttributeFactory implements PrePostInvocationAttributeFactory {
- private ExpressionParser parser;
+ private final ExpressionParser parser;
public ExpressionBasedAnnotationAttributeFactory(MethodSecurityExpressionHandler handler) {
parser = handler.getExpressionParser();
}
- public PreInvocationAttribute createPreInvocationAttribute(PreFilter preFilter, PreAuthorize preAuthorize) {
+ public PreInvocationAttribute createPreInvocationAttribute(String preFilterAttribute, String filterObject, String preAuthorizeAttribute) {
try {
// TODO: Optimization of permitAll
- Expression preAuthorizeExpression = preAuthorize == null ? parser.parseExpression("permitAll") : parser.parseExpression(preAuthorize.value());
- Expression preFilterExpression = preFilter == null ? null : parser.parseExpression(preFilter.value());
- String filterObject = preFilter == null ? null : preFilter.filterTarget();
+ Expression preAuthorizeExpression = preAuthorizeAttribute == null ? parser.parseExpression("permitAll") : parser.parseExpression(preAuthorizeAttribute);
+ Expression preFilterExpression = preFilterAttribute == null ? null : parser.parseExpression(preFilterAttribute);
return new PreInvocationExpressionAttribute(preFilterExpression, filterObject, preAuthorizeExpression);
} catch (ParseException e) {
throw new IllegalArgumentException("Failed to parse expression '" + e.getExpressionString() + "'", e);
}
}
- public PostInvocationAttribute createPostInvocationAttribute(PostFilter postFilter, PostAuthorize postAuthorize) {
+ public PostInvocationAttribute createPostInvocationAttribute(String postFilterAttribute, String postAuthorizeAttribute) {
try {
- Expression postAuthorizeExpression = postAuthorize == null ? null : parser.parseExpression(postAuthorize.value());
- Expression postFilterExpression = postFilter == null ? null : parser.parseExpression(postFilter.value());
+ Expression postAuthorizeExpression = postAuthorizeAttribute == null ? null : parser.parseExpression(postAuthorizeAttribute);
+ Expression postFilterExpression = postFilterAttribute == null ? null : parser.parseExpression(postFilterAttribute);
if (postFilterExpression != null || postAuthorizeExpression != null) {
return new PostInvocationExpressionAttribute(postFilterExpression, postAuthorizeExpression);
diff --git a/dist/spring-security-core/org/springframework/security/access/expression/method/ExpressionBasedPostInvocationAdvice.java b/dist/spring-security-core/org/springframework/security/access/expression/method/ExpressionBasedPostInvocationAdvice.java
index ec73a04..890e1ed 100644
--- a/dist/spring-security-core/org/springframework/security/access/expression/method/ExpressionBasedPostInvocationAdvice.java
+++ b/dist/spring-security-core/org/springframework/security/access/expression/method/ExpressionBasedPostInvocationAdvice.java
@@ -19,7 +19,7 @@ import org.springframework.security.core.Authentication;
public class ExpressionBasedPostInvocationAdvice implements PostInvocationAuthorizationAdvice{
protected final Log logger = LogFactory.getLog(getClass());
- private MethodSecurityExpressionHandler expressionHandler;
+ private final MethodSecurityExpressionHandler expressionHandler;
public ExpressionBasedPostInvocationAdvice(MethodSecurityExpressionHandler expressionHandler) {
this.expressionHandler = expressionHandler;
diff --git a/dist/spring-security-core/org/springframework/security/access/expression/method/ExpressionBasedPreInvocationAdvice.java b/dist/spring-security-core/org/springframework/security/access/expression/method/ExpressionBasedPreInvocationAdvice.java
index c772088..4a61308 100644
--- a/dist/spring-security-core/org/springframework/security/access/expression/method/ExpressionBasedPreInvocationAdvice.java
+++ b/dist/spring-security-core/org/springframework/security/access/expression/method/ExpressionBasedPreInvocationAdvice.java
@@ -17,7 +17,7 @@ import org.springframework.security.core.Authentication;
* Method pre-invocation handling based on expressions.
*
* @author Luke Taylor
- * @since
+ * @since 3.0
*/
public class ExpressionBasedPreInvocationAdvice implements PreInvocationAuthorizationAdvice {
private MethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
diff --git a/dist/spring-security-core/org/springframework/security/access/expression/method/MethodSecurityEvaluationContext.java b/dist/spring-security-core/org/springframework/security/access/expression/method/MethodSecurityEvaluationContext.java
index 30cfab4..1be1457 100644
--- a/dist/spring-security-core/org/springframework/security/access/expression/method/MethodSecurityEvaluationContext.java
+++ b/dist/spring-security-core/org/springframework/security/access/expression/method/MethodSecurityEvaluationContext.java
@@ -5,6 +5,7 @@ import java.lang.reflect.Method;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.aop.support.AopUtils;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
@@ -20,11 +21,11 @@ import org.springframework.security.core.Authentication;
* @since 3.0
*/
class MethodSecurityEvaluationContext extends StandardEvaluationContext {
- private static Log logger = LogFactory.getLog(MethodSecurityEvaluationContext.class);
+ private static final Log logger = LogFactory.getLog(MethodSecurityEvaluationContext.class);
private ParameterNameDiscoverer parameterNameDiscoverer;
+ private final MethodInvocation mi;
private boolean argumentsAdded;
- private MethodInvocation mi;
/**
* Intended for testing. Don't use in practice as it creates a new parameter resolver
@@ -44,6 +45,7 @@ class MethodSecurityEvaluationContext extends StandardEvaluationContext {
@Override
public Object lookupVariable(String name) {
Object variable = super.lookupVariable(name);
+
if (variable != null) {
return variable;
}
@@ -53,7 +55,13 @@ class MethodSecurityEvaluationContext extends StandardEvaluationContext {
argumentsAdded = true;
}
- return super.lookupVariable(name);
+ variable = super.lookupVariable(name);
+
+ if (variable != null) {
+ return variable;
+ }
+
+ return null;
}
public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) {
@@ -68,7 +76,15 @@ class MethodSecurityEvaluationContext extends StandardEvaluationContext {
}
Object targetObject = mi.getThis();
- Method method = AopUtils.getMostSpecificMethod(mi.getMethod(), targetObject.getClass());
+ // SEC-1454
+ Class<?> targetClass = AopProxyUtils.ultimateTargetClass(targetObject);
+
+ if (targetClass == null) {
+ // TODO: Spring should do this, but there's a bug in ultimateTargetClass() which returns null
+ targetClass = targetObject.getClass();
+ }
+
+ Method method = AopUtils.getMostSpecificMethod(mi.getMethod(), targetClass);
String[] paramNames = parameterNameDiscoverer.getParameterNames(method);
if (paramNames == null) {
diff --git a/dist/spring-security-core/org/springframework/security/access/expression/method/MethodSecurityExpressionHandler.java b/dist/spring-security-core/org/springframework/security/access/expression/method/MethodSecurityExpressionHandler.java
index a58f45f..4560009 100644
--- a/dist/spring-security-core/org/springframework/security/access/expression/method/MethodSecurityExpressionHandler.java
+++ b/dist/spring-security-core/org/springframework/security/access/expression/method/MethodSecurityExpressionHandler.java
@@ -1,30 +1,17 @@
package org.springframework.security.access.expression.method;
import org.aopalliance.intercept.MethodInvocation;
-import org.springframework.aop.framework.AopInfrastructureBean;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
-import org.springframework.expression.ExpressionParser;
-import org.springframework.security.core.Authentication;
+import org.springframework.security.access.expression.SecurityExpressionHandler;
/**
- * Facade which isolates Spring Security's requirements for evaluation method-security expressions
- * from the implementation of the underlying expression objects.
+ * Extended expression-handler facade which adds methods which are specific to securing method invocations.
*
* @author Luke Taylor
* @since 3.0
*/
-public interface MethodSecurityExpressionHandler extends AopInfrastructureBean {
- /**
- * @return an expression parser for the expressions used by the implementation.
- */
- ExpressionParser getExpressionParser();
-
- /**
- * Provides an evaluation context in which to evaluate security expressions for a method invocation.
- */
- EvaluationContext createEvaluationContext(Authentication authentication, MethodInvocation mi);
-
+public interface MethodSecurityExpressionHandler extends SecurityExpressionHandler<MethodInvocation> {
/**
* Filters a target collection or array.
* Only applies to method invocations.
@@ -33,7 +20,7 @@ public interface MethodSecurityExpressionHandler extends AopInfrastructureBean {
* @param filterExpression the expression which should be used as the filter condition. If it returns false on
* evaluation, the object will be removed from the returned collection
* @param ctx the current evaluation context (as created through a call to
- * {@link #createEvaluationContext(Authentication, MethodInvocation)}
+ * {@link #createEvaluationContext(org.springframework.security.core.Authentication, Object)}
* @return the filtered collection or array
*/
Object filter(Object filterTarget, Expression filterExpression, EvaluationContext ctx);
@@ -44,7 +31,7 @@ public interface MethodSecurityExpressionHandler extends AopInfrastructureBean {
*
* @param returnObject the return object value
* @param ctx the context within which the object should be set (as created through a call to
- * {@link #createEvaluationContext(Authentication, MethodInvocation)}
+ * {@link #createEvaluationContext(org.springframework.security.core.Authentication, Object)}
*/
void setReturnObject(Object returnObject, EvaluationContext ctx);
diff --git a/dist/spring-security-core/org/springframework/security/access/expression/method/MethodSecurityExpressionRoot.java b/dist/spring-security-core/org/springframework/security/access/expression/method/MethodSecurityExpressionRoot.java
index 44052f9..d689408 100644
--- a/dist/spring-security-core/org/springframework/security/access/expression/method/MethodSecurityExpressionRoot.java
+++ b/dist/spring-security-core/org/springframework/security/access/expression/method/MethodSecurityExpressionRoot.java
@@ -1,8 +1,5 @@
package org.springframework.security.access.expression.method;
-import java.io.Serializable;
-
-import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.access.expression.SecurityExpressionRoot;
import org.springframework.security.core.Authentication;
@@ -14,27 +11,14 @@ import org.springframework.security.core.Authentication;
* @since 3.0
*/
class MethodSecurityExpressionRoot extends SecurityExpressionRoot {
- private PermissionEvaluator permissionEvaluator;
private Object filterObject;
private Object returnObject;
- public final String read = "read";
- public final String write = "write";
- public final String create = "create";
- public final String delete = "delete";
- public final String admin = "administration";
+ private Object target;
MethodSecurityExpressionRoot(Authentication a) {
super(a);
}
- public boolean hasPermission(Object target, Object permission) {
- return permissionEvaluator.hasPermission(authentication, target, permission);
- }
-
- public boolean hasPermission(Object targetId, String targetType, Object permission) {
- return permissionEvaluator.hasPermission(authentication, (Serializable)targetId, targetType, permission);
- }
-
public void setFilterObject(Object filterObject) {
this.filterObject = filterObject;
}
@@ -51,8 +35,17 @@ class MethodSecurityExpressionRoot extends SecurityExpressionRoot {
return returnObject;
}
- public void setPermissionEvaluator(PermissionEvaluator permissionEvaluator) {
- this.permissionEvaluator = permissionEvaluator;
+ /**
+ * Sets the "this" property for use in expressions. Typically this will be the "this" property of
+ * the {@code JoinPoint} representing the method invocation which is being protected.
+ *
+ * @param target the target object on which the method in is being invoked.
+ */
+ void setThis(Object target) {
+ this.target = target;
}
+ public Object getThis() {
+ return target;
+ }
}
diff --git a/dist/spring-security-core/org/springframework/security/access/hierarchicalroles/NullRoleHierarchy.java b/dist/spring-security-core/org/springframework/security/access/hierarchicalroles/NullRoleHierarchy.java
index 84654cf..8003c67 100644
--- a/dist/spring-security-core/org/springframework/security/access/hierarchicalroles/NullRoleHierarchy.java
+++ b/dist/spring-security-core/org/springframework/security/access/hierarchicalroles/NullRoleHierarchy.java
@@ -11,7 +11,7 @@ import org.springframework.security.core.GrantedAuthority;
*/
public final class NullRoleHierarchy implements RoleHierarchy {
- public Collection<GrantedAuthority> getReachableGrantedAuthorities(Collection<GrantedAuthority> authorities) {
+ public Collection<? extends GrantedAuthority> getReachableGrantedAuthorities(Collection<? extends GrantedAuthority> authorities) {
return authorities;
}
diff --git a/dist/spring-security-core/org/springframework/security/access/hierarchicalroles/RoleHierarchy.java b/dist/spring-security-core/org/springframework/security/access/hierarchicalroles/RoleHierarchy.java
index 2dc14e2..9e86c52 100644
--- a/dist/spring-security-core/org/springframework/security/access/hierarchicalroles/RoleHierarchy.java
+++ b/dist/spring-security-core/org/springframework/security/access/hierarchicalroles/RoleHierarchy.java
@@ -40,6 +40,6 @@ public interface RoleHierarchy {
* @param authorities - List of the directly assigned authorities.
* @return List of all reachable authorities given the assigned authorities.
*/
- public Collection<GrantedAuthority> getReachableGrantedAuthorities(Collection<GrantedAuthority> authorities);
+ public Collection<? extends GrantedAuthority> getReachableGrantedAuthorities(Collection<? extends GrantedAuthority> authorities);
}
diff --git a/dist/spring-security-core/org/springframework/security/access/hierarchicalroles/RoleHierarchyImpl.java b/dist/spring-security-core/org/springframework/security/access/hierarchicalroles/RoleHierarchyImpl.java
index 581c6b0..abf1dc8 100644
--- a/dist/spring-security-core/org/springframework/security/access/hierarchicalroles/RoleHierarchyImpl.java
+++ b/dist/spring-security-core/org/springframework/security/access/hierarchicalroles/RoleHierarchyImpl.java
@@ -15,22 +15,15 @@
package org.springframework.security.access.hierarchicalroles;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
-import org.springframework.security.core.authority.GrantedAuthorityImpl;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
* <p>
@@ -105,7 +98,7 @@ public class RoleHierarchyImpl implements RoleHierarchy {
buildRolesReachableInOneOrMoreStepsMap();
}
- public Collection<GrantedAuthority> getReachableGrantedAuthorities(Collection<GrantedAuthority> authorities) {
+ public Collection<GrantedAuthority> getReachableGrantedAuthorities(Collection<? extends GrantedAuthority> authorities) {
if (authorities == null || authorities.isEmpty()) {
return AuthorityUtils.NO_AUTHORITIES;
}
@@ -135,9 +128,7 @@ public class RoleHierarchyImpl implements RoleHierarchy {
private void addReachableRoles(Set<GrantedAuthority> reachableRoles,
GrantedAuthority authority) {
- Iterator<GrantedAuthority> iterator = reachableRoles.iterator();
- while (iterator.hasNext()) {
- GrantedAuthority testAuthority = iterator.next();
+ for (GrantedAuthority testAuthority : reachableRoles) {
String testKey = testAuthority.getAuthority();
if ((testKey != null) && (testKey.equals(authority.getAuthority()))) {
return;
@@ -154,9 +145,7 @@ public class RoleHierarchyImpl implements RoleHierarchy {
return null;
}
- Iterator<GrantedAuthority> iterator = rolesReachableInOneOrMoreStepsMap.keySet().iterator();
- while (iterator.hasNext()) {
- GrantedAuthority testAuthority = iterator.next();
+ for (GrantedAuthority testAuthority : rolesReachableInOneOrMoreStepsMap.keySet()) {
String testKey = testAuthority.getAuthority();
if ((testKey != null) && (testKey.equals(authority.getAuthority()))) {
return rolesReachableInOneOrMoreStepsMap.get(testAuthority);
@@ -171,15 +160,15 @@ public class RoleHierarchyImpl implements RoleHierarchy {
* references a set of the reachable lower roles.
*/
private void buildRolesReachableInOneStepMap() {
- Pattern pattern = Pattern.compile("(\\s*([^\\s>]+)\\s*\\>\\s*([^\\s>]+))");
+ Pattern pattern = Pattern.compile("(\\s*([^\\s>]+)\\s*>\\s*([^\\s>]+))");
Matcher roleHierarchyMatcher = pattern.matcher(roleHierarchyStringRepresentation);
rolesReachableInOneStepMap = new HashMap<GrantedAuthority, Set<GrantedAuthority>>();
while (roleHierarchyMatcher.find()) {
- GrantedAuthority higherRole = new GrantedAuthorityImpl(roleHierarchyMatcher.group(2));
- GrantedAuthority lowerRole = new GrantedAuthorityImpl(roleHierarchyMatcher.group(3));
- Set<GrantedAuthority> rolesReachableInOneStepSet = null;
+ GrantedAuthority higherRole = new SimpleGrantedAuthority(roleHierarchyMatcher.group(2));
+ GrantedAuthority lowerRole = new SimpleGrantedAuthority(roleHierarchyMatcher.group(3));
+ Set<GrantedAuthority> rolesReachableInOneStepSet;
if (!rolesReachableInOneStepMap.containsKey(higherRole)) {
rolesReachableInOneStepSet = new HashSet<GrantedAuthority>();
@@ -214,7 +203,7 @@ public class RoleHierarchyImpl implements RoleHierarchy {
while (!rolesToVisitSet.isEmpty()) {
// take a role from the rolesToVisit set
- GrantedAuthority aRole = (GrantedAuthority) rolesToVisitSet.iterator().next();
+ GrantedAuthority aRole = rolesToVisitSet.iterator().next();
rolesToVisitSet.remove(aRole);
addReachableRoles(visitedRolesSet, aRole);
if (rolesReachableInOneStepMap.containsKey(aRole)) {
diff --git a/dist/spring-security-core/org/springframework/security/access/hierarchicalroles/UserDetailsServiceWrapper.java b/dist/spring-security-core/org/springframework/security/access/hierarchicalroles/UserDetailsServiceWrapper.java
index d6afddd..d4b18bc 100644
--- a/dist/spring-security-core/org/springframework/security/access/hierarchicalroles/UserDetailsServiceWrapper.java
+++ b/dist/spring-security-core/org/springframework/security/access/hierarchicalroles/UserDetailsServiceWrapper.java
@@ -16,8 +16,6 @@ package org.springframework.security.access.hierarchicalroles;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
-import org.springframework.security.core.userdetails.UsernameNotFoundException;
-import org.springframework.dao.DataAccessException;
/**
* This class wraps Spring Security's <tt>UserDetailsService</tt> in a way that its <tt>loadUserByUsername()</tt>
@@ -25,8 +23,8 @@ import org.springframework.dao.DataAccessException;
* instead of only the directly assigned authorities.
*
* @author Michael Mayr
- * @deprecated use a {@code RoleHierarchyVoter} instead of populating the user Authentication object
- * with the additional authorities.
+ * @deprecated use a {@code RoleHierarchyVoter} or use a {@code RoleHierarchyAuthoritiesMapper} to populate the
+ * Authentication object with the additional authorities.
*/
public class UserDetailsServiceWrapper implements UserDetailsService {
@@ -42,7 +40,7 @@ public class UserDetailsServiceWrapper implements UserDetailsService {
this.userDetailsService = userDetailsService;
}
- public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
+ public UserDetails loadUserByUsername(String username) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
// wrapped UserDetailsService might throw UsernameNotFoundException or DataAccessException which will then bubble up
return new UserDetailsWrapper(userDetails, roleHierarchy);
diff --git a/dist/spring-security-core/org/springframework/security/access/hierarchicalroles/UserDetailsWrapper.java b/dist/spring-security-core/org/springframework/security/access/hierarchicalroles/UserDetailsWrapper.java
index 939a12e..6d0c226 100644
--- a/dist/spring-security-core/org/springframework/security/access/hierarchicalroles/UserDetailsWrapper.java
+++ b/dist/spring-security-core/org/springframework/security/access/hierarchicalroles/UserDetailsWrapper.java
@@ -26,7 +26,7 @@ import org.springframework.security.core.userdetails.UserDetails;
* delegated to the <tt>UserDetails</tt> implementation.
*
* @author Michael Mayr
- * @deprecated use a {@link RoleHierarchyVoter} instead.
+ * @deprecated use a {@link RoleHierarchyVoter} or {@code RoleHierarchyAuthoritiesMapper} instead.
*/
public class UserDetailsWrapper implements UserDetails {
@@ -49,7 +49,7 @@ public class UserDetailsWrapper implements UserDetails {
return userDetails.isAccountNonLocked();
}
- public Collection<GrantedAuthority> getAuthorities() {
+ public Collection<? extends GrantedAuthority> getAuthorities() {
return roleHierarchy.getReachableGrantedAuthorities(userDetails.getAuthorities());
}
diff --git a/dist/spring-security-core/org/springframework/security/access/intercept/AbstractSecurityInterceptor.java b/dist/spring-security-core/org/springframework/security/access/intercept/AbstractSecurityInterceptor.java
index e40172a..b263230 100644
--- a/dist/spring-security-core/org/springframework/security/access/intercept/AbstractSecurityInterceptor.java
+++ b/dist/spring-security-core/org/springframework/security/access/intercept/AbstractSecurityInterceptor.java
@@ -40,6 +40,7 @@ import org.springframework.security.authentication.AuthenticationCredentialsNotF
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.SpringSecurityMessageSource;
+import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.Assert;
@@ -109,6 +110,7 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, A
private boolean alwaysReauthenticate = false;
private boolean rejectPublicInvocations = false;
private boolean validateConfigAttributes = true;
+ private boolean publishAuthorizationSuccess = false;
//~ Methods ========================================================================================================
@@ -153,7 +155,7 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, A
throw new IllegalArgumentException("Unsupported configuration attributes: " + unsupportedAttrs);
}
- logger.info("Validated configuration attributes");
+ logger.debug("Validated configuration attributes");
}
}
@@ -170,7 +172,7 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, A
Collection<ConfigAttribute> attributes = this.obtainSecurityMetadataSource().getAttributes(object);
- if (attributes == null) {
+ if (attributes == null || attributes.isEmpty()) {
if (rejectPublicInvocations) {
throw new IllegalArgumentException("Secure object invocation " + object +
" was denied as public invocations are not allowed via this interceptor. "
@@ -203,8 +205,7 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, A
this.accessDecisionManager.decide(authenticated, object, attributes);
}
catch (AccessDeniedException accessDeniedException) {
- publishEvent(new AuthorizationFailureEvent(object, attributes, authenticated,
- accessDeniedException));
+ publishEvent(new AuthorizationFailureEvent(object, attributes, authenticated, accessDeniedException));
throw accessDeniedException;
}
@@ -213,7 +214,9 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, A
logger.debug("Authorization successful");
}
- publishEvent(new AuthorizedEvent(object, attributes, authenticated));
+ if (publishAuthorizationSuccess) {
+ publishEvent(new AuthorizedEvent(object, attributes, authenticated));
+ }
// Attempt to run as a different user
Authentication runAs = this.runAsManager.buildRunAs(authenticated, object, attributes);
@@ -224,16 +227,18 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, A
}
// no further work post-invocation
- return new InterceptorStatusToken(authenticated, false, attributes, object);
+ return new InterceptorStatusToken(SecurityContextHolder.getContext(), false, attributes, object);
} else {
if (debug) {
logger.debug("Switching to RunAs Authentication: " + runAs);
}
+ SecurityContext origCtx = SecurityContextHolder.getContext();
+ SecurityContextHolder.setContext(SecurityContextHolder.createEmptyContext());
SecurityContextHolder.getContext().setAuthentication(runAs);
// need to revert to token.Authenticated post-invocation
- return new InterceptorStatusToken(authenticated, true, attributes, object);
+ return new InterceptorStatusToken(origCtx, true, attributes, object);
}
}
@@ -253,21 +258,22 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, A
if (token.isContextHolderRefreshRequired()) {
if (logger.isDebugEnabled()) {
- logger.debug("Reverting to original Authentication: " + token.getAuthentication().toString());
+ logger.debug("Reverting to original Authentication: " + token.getSecurityContext().getAuthentication());
}
- SecurityContextHolder.getContext().setAuthentication(token.getAuthentication());
+ SecurityContextHolder.setContext(token.getSecurityContext());
}
if (afterInvocationManager != null) {
// Attempt after invocation handling
try {
- returnedObject = afterInvocationManager.decide(token.getAuthentication(), token.getSecureObject(),
+ returnedObject = afterInvocationManager.decide(token.getSecurityContext().getAuthentication(),
+ token.getSecureObject(),
token.getAttributes(), returnedObject);
}
catch (AccessDeniedException accessDeniedException) {
AuthorizationFailureEvent event = new AuthorizationFailureEvent(token.getSecureObject(), token
- .getAttributes(), token.getAuthentication(), accessDeniedException);
+ .getAttributes(), token.getSecurityContext().getAuthentication(), accessDeniedException);
publishEvent(event);
throw accessDeniedException;
@@ -310,7 +316,7 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, A
/**
* Helper method which generates an exception containing the passed reason,
* and publishes an event to the application context.
- * <p/>
+ * <p>
* Always throws an exception.
*
* @param reason to be provided in the exception detail
@@ -346,12 +352,12 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, A
/**
* 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
+ * wired to the {@code AbstractSecurityInterceptor} all support the
* indicated secure object class.
*
* @return the type of secure object the subclass provides services for
*/
- public abstract Class<? extends Object> getSecureObjectClass();
+ public abstract Class<?> getSecureObjectClass();
public boolean isAlwaysReauthenticate() {
return alwaysReauthenticate;
@@ -404,6 +410,16 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, A
}
/**
+ * Only {@code AuthorizationFailureEvent} will be published.
+ * If you set this property to {@code true}, {@code AuthorizedEvent}s will also be published.
+ *
+ * @param publishAuthorizationSuccess default value is {@code false}
+ */
+ public void setPublishAuthorizationSuccess(boolean publishAuthorizationSuccess) {
+ this.publishAuthorizationSuccess = publishAuthorizationSuccess;
+ }
+
+ /**
* By rejecting public invocations (and setting this property to <tt>true</tt>), 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
diff --git a/dist/spring-security-core/org/springframework/security/access/intercept/InterceptorStatusToken.java b/dist/spring-security-core/org/springframework/security/access/intercept/InterceptorStatusToken.java
index eef02d8..4102e52 100644
--- a/dist/spring-security-core/org/springframework/security/access/intercept/InterceptorStatusToken.java
+++ b/dist/spring-security-core/org/springframework/security/access/intercept/InterceptorStatusToken.java
@@ -19,6 +19,7 @@ import java.util.Collection;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContext;
/**
@@ -33,16 +34,16 @@ import org.springframework.security.core.Authentication;
public class InterceptorStatusToken {
//~ Instance fields ================================================================================================
- private Authentication authentication;
+ private SecurityContext securityContext;
private Collection<ConfigAttribute> attr;
private Object secureObject;
private boolean contextHolderRefreshRequired;
//~ Constructors ===================================================================================================
- public InterceptorStatusToken(Authentication authentication, boolean contextHolderRefreshRequired,
+ public InterceptorStatusToken(SecurityContext securityContext, boolean contextHolderRefreshRequired,
Collection<ConfigAttribute> attributes, Object secureObject) {
- this.authentication = authentication;
+ this.securityContext = securityContext;
this.contextHolderRefreshRequired = contextHolderRefreshRequired;
this.attr = attributes;
this.secureObject = secureObject;
@@ -54,8 +55,8 @@ public class InterceptorStatusToken {
return attr;
}
- public Authentication getAuthentication() {
- return authentication;
+ public SecurityContext getSecurityContext() {
+ return securityContext;
}
public Object getSecureObject() {
diff --git a/dist/spring-security-core/org/springframework/security/access/intercept/RunAsImplAuthenticationProvider.java b/dist/spring-security-core/org/springframework/security/access/intercept/RunAsImplAuthenticationProvider.java
index 9bd5396..df4bfda 100644
--- a/dist/spring-security-core/org/springframework/security/access/intercept/RunAsImplAuthenticationProvider.java
+++ b/dist/spring-security-core/org/springframework/security/access/intercept/RunAsImplAuthenticationProvider.java
@@ -74,11 +74,7 @@ public class RunAsImplAuthenticationProvider implements InitializingBean, Authen
this.messages = new MessageSourceAccessor(messageSource);
}
- public boolean supports(Class<? extends Object> authentication) {
- if (RunAsUserToken.class.isAssignableFrom(authentication)) {
- return true;
- } else {
- return false;
- }
+ public boolean supports(Class<?> authentication) {
+ return RunAsUserToken.class.isAssignableFrom(authentication);
}
}
diff --git a/dist/spring-security-core/org/springframework/security/access/intercept/RunAsManagerImpl.java b/dist/spring-security-core/org/springframework/security/access/intercept/RunAsManagerImpl.java
index 7706060..665bb69 100644
--- a/dist/spring-security-core/org/springframework/security/access/intercept/RunAsManagerImpl.java
+++ b/dist/spring-security-core/org/springframework/security/access/intercept/RunAsManagerImpl.java
@@ -23,7 +23,7 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.authority.GrantedAuthorityImpl;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.util.Assert;
@@ -32,8 +32,8 @@ import org.springframework.util.Assert;
* <p>
* Is activated if any {@link ConfigAttribute#getAttribute()} is prefixed with <Code>RUN_AS_</code>.
* If found, it generates a new {@link RunAsUserToken} containing the same principal, credentials and granted
- * authorities as the original {@link Authentication} object, along with {@link GrantedAuthorityImpl}s for each
- * <code>RUN_AS_</code> indicated. The created <code>GrantedAuthorityImpl</code>s will be prefixed with a special
+ * authorities as the original {@link Authentication} object, along with {@link SimpleGrantedAuthority}s for each
+ * <code>RUN_AS_</code> indicated. The created <code>SimpleGrantedAuthority</code>s will be prefixed with a special
* prefix indicating that it is a role (default prefix value is <code>ROLE_</code>), and then the remainder of the
* <code>RUN_AS_</code> keyword. For example, <code>RUN_AS_FOO</code> will result in the creation of a granted
* authority of <code>ROLE_RUN_AS_FOO</code>.
@@ -66,7 +66,7 @@ public class RunAsManagerImpl implements RunAsManager, InitializingBean {
for (ConfigAttribute attribute : attributes) {
if (this.supports(attribute)) {
- GrantedAuthority extraAuthority = new GrantedAuthorityImpl(getRolePrefix() + attribute.getAttribute());
+ GrantedAuthority extraAuthority = new SimpleGrantedAuthority(getRolePrefix() + attribute.getAttribute());
newAuthorities.add(extraAuthority);
}
}
diff --git a/dist/spring-security-core/org/springframework/security/access/intercept/RunAsUserToken.java b/dist/spring-security-core/org/springframework/security/access/intercept/RunAsUserToken.java
index c71fdc4..47d58e2 100644
--- a/dist/spring-security-core/org/springframework/security/access/intercept/RunAsUserToken.java
+++ b/dist/spring-security-core/org/springframework/security/access/intercept/RunAsUserToken.java
@@ -15,12 +15,12 @@
package org.springframework.security.access.intercept;
-import java.util.Arrays;
import java.util.Collection;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.SpringSecurityCoreVersion;
/**
@@ -29,6 +29,9 @@ import org.springframework.security.core.GrantedAuthority;
* @author Ben Alex
*/
public class RunAsUserToken extends AbstractAuthenticationToken {
+
+ private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
+
//~ Instance fields ================================================================================================
private final Class<? extends Authentication> originalAuthentication;
@@ -38,12 +41,7 @@ public class RunAsUserToken extends AbstractAuthenticationToken {
//~ Constructors ===================================================================================================
- public RunAsUserToken(String key, Object principal, Object credentials, GrantedAuthority[] authorities,
- Class<? extends Authentication> originalAuthentication) {
- this(key, principal, credentials, Arrays.asList(authorities), originalAuthentication);
- }
-
- public RunAsUserToken(String key, Object principal, Object credentials, Collection<GrantedAuthority> authorities,
+ public RunAsUserToken(String key, Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities,
Class<? extends Authentication> originalAuthentication) {
super(authorities);
this.keyHash = key.hashCode();
@@ -73,7 +71,8 @@ public class RunAsUserToken extends AbstractAuthenticationToken {
public String toString() {
StringBuilder sb = new StringBuilder(super.toString());
- sb.append("; Original Class: ").append(this.originalAuthentication.getName());
+ String className = this.originalAuthentication == null ? null : this.originalAuthentication.getName();
+ sb.append("; Original Class: ").append(className);
return sb.toString();
}
diff --git a/dist/spring-security-core/org/springframework/security/access/intercept/aopalliance/MethodSecurityInterceptor.java b/dist/spring-security-core/org/springframework/security/access/intercept/aopalliance/MethodSecurityInterceptor.java
index 9705820..a18a265 100644
--- a/dist/spring-security-core/org/springframework/security/access/intercept/aopalliance/MethodSecurityInterceptor.java
+++ b/dist/spring-security-core/org/springframework/security/access/intercept/aopalliance/MethodSecurityInterceptor.java
@@ -42,11 +42,7 @@ public class MethodSecurityInterceptor extends AbstractSecurityInterceptor imple
//~ Methods ========================================================================================================
- public MethodSecurityMetadataSource getSecurityMetadataSource() {
- return this.securityMetadataSource;
- }
-
- public Class<? extends Object> getSecureObjectClass() {
+ public Class<?> getSecureObjectClass() {
return MethodInvocation.class;
}
@@ -55,21 +51,20 @@ public class MethodSecurityInterceptor extends AbstractSecurityInterceptor imple
*
* @param mi The method being invoked which requires a security decision
*
- * @return The returned value from the method invocation
+ * @return The returned value from the method invocation (possibly modified by the {@code AfterInvocationManager}).
*
* @throws Throwable if any error occurs
*/
public Object invoke(MethodInvocation mi) throws Throwable {
- Object result = null;
InterceptorStatusToken token = super.beforeInvocation(mi);
- try {
- result = mi.proceed();
- } finally {
- result = super.afterInvocation(token, result);
- }
+ Object result = mi.proceed();
- return result;
+ return super.afterInvocation(token, result);
+ }
+
+ public MethodSecurityMetadataSource getSecurityMetadataSource() {
+ return this.securityMetadataSource;
}
public SecurityMetadataSource obtainSecurityMetadataSource() {
diff --git a/dist/spring-security-core/org/springframework/security/access/intercept/aopalliance/MethodSecurityMetadataSourceAdvisor.java b/dist/spring-security-core/org/springframework/security/access/intercept/aopalliance/MethodSecurityMetadataSourceAdvisor.java
index 819340d..d7e3054 100644
--- a/dist/spring-security-core/org/springframework/security/access/intercept/aopalliance/MethodSecurityMetadataSourceAdvisor.java
+++ b/dist/spring-security-core/org/springframework/security/access/intercept/aopalliance/MethodSecurityMetadataSourceAdvisor.java
@@ -18,11 +18,10 @@ package org.springframework.security.access.intercept.aopalliance;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
-import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
+import java.util.*;
import org.aopalliance.aop.Advice;
-import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.Pointcut;
import org.springframework.aop.support.AbstractPointcutAdvisor;
import org.springframework.aop.support.StaticMethodMatcherPointcut;
@@ -56,24 +55,13 @@ public class MethodSecurityMetadataSourceAdvisor extends AbstractPointcutAdvisor
private transient MethodSecurityInterceptor interceptor;
private final Pointcut pointcut = new MethodSecurityMetadataSourcePointcut();
private BeanFactory beanFactory;
- private String adviceBeanName;
- private String metadataSourceBeanName;
+ private final String adviceBeanName;
+ private final String metadataSourceBeanName;
private transient volatile Object adviceMonitor = new Object();
//~ Constructors ===================================================================================================
/**
- * @deprecated use the decoupled approach instead
- */
- MethodSecurityMetadataSourceAdvisor(MethodSecurityInterceptor advice) {
- Assert.notNull(advice.getSecurityMetadataSource(), "Cannot construct a MethodSecurityMetadataSourceAdvisor using a " +
- "MethodSecurityInterceptor that has no SecurityMetadataSource configured");
-
- this.interceptor = advice;
- this.attributeSource = advice.getSecurityMetadataSource();
- }
-
- /**
* Alternative constructor for situations where we want the advisor decoupled from the advice. Instead the advice
* bean name should be set. This prevents eager instantiation of the interceptor
* (and hence the AuthenticationManager). See SEC-773, for example. The metadataSourceBeanName is used rather than
@@ -126,47 +114,8 @@ public class MethodSecurityMetadataSourceAdvisor extends AbstractPointcutAdvisor
class MethodSecurityMetadataSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
@SuppressWarnings("unchecked")
public boolean matches(Method m, Class targetClass) {
- return attributeSource.getAttributes(m, targetClass) != null;
- }
- }
-
- /**
- * Represents a <code>MethodInvocation</code>.
- * <p>
- * Required as <code>MethodSecurityMetadataSource</code> only supports lookup of configuration attributes for
- * <code>MethodInvocation</code>s.
- */
- class InternalMethodInvocation implements MethodInvocation {
- private Method method;
- private Class<?> targetClass;
-
- public InternalMethodInvocation(Method method, Class<?> targetClass) {
- this.method = method;
- this.targetClass = targetClass;
- }
-
- protected InternalMethodInvocation() {
- throw new UnsupportedOperationException();
- }
-
- public Object[] getArguments() {
- throw new UnsupportedOperationException();
- }
-
- public Method getMethod() {
- return this.method;
- }
-
- public AccessibleObject getStaticPart() {
- throw new UnsupportedOperationException();
- }
-
- public Object getThis() {
- return this.targetClass;
- }
-
- public Object proceed() throws Throwable {
- throw new UnsupportedOperationException();
+ Collection attributes = attributeSource.getAttributes(m, targetClass);
+ return attributes != null && !attributes.isEmpty();
}
}
}
diff --git a/dist/spring-security-core/org/springframework/security/access/intercept/aspectj/AspectJAnnotationCallback.java b/dist/spring-security-core/org/springframework/security/access/intercept/aspectj/AspectJAnnotationCallback.java
deleted file mode 100644
index 0fd833b..0000000
--- a/dist/spring-security-core/org/springframework/security/access/intercept/aspectj/AspectJAnnotationCallback.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.springframework.security.access.intercept.aspectj;
-
-
-/**
- * Called by the {@link AspectJAnnotationSecurityInterceptor} when it wishes for the
- * AspectJ processing to continue.
- *
- * @author Mike Wiesner
- * @deprecated
- */
- at Deprecated
-public interface AspectJAnnotationCallback {
- //~ Methods ========================================================================================================
-
- Object proceedWithObject() throws Throwable;
-}
diff --git a/dist/spring-security-core/org/springframework/security/access/intercept/aspectj/AspectJAnnotationSecurityInterceptor.java b/dist/spring-security-core/org/springframework/security/access/intercept/aspectj/AspectJAnnotationSecurityInterceptor.java
deleted file mode 100644
index 20018f6..0000000
--- a/dist/spring-security-core/org/springframework/security/access/intercept/aspectj/AspectJAnnotationSecurityInterceptor.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package org.springframework.security.access.intercept.aspectj;
-
-import org.springframework.security.access.SecurityMetadataSource;
-import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
-import org.springframework.security.access.intercept.InterceptorStatusToken;
-import org.springframework.security.access.method.MethodSecurityMetadataSource;
-
-import org.aspectj.lang.JoinPoint;
-
-/**
- * AspectJ interceptor that supports @Aspect notation.
- *
- * @author Mike Wiesner
- * @deprecated Use AspectJMethodSecurityInterceptor instead
- */
- at Deprecated
-public class AspectJAnnotationSecurityInterceptor extends AbstractSecurityInterceptor {
- //~ Instance fields ================================================================================================
-
- private MethodSecurityMetadataSource securityMetadataSource;
-
- //~ Methods ========================================================================================================
-
- public MethodSecurityMetadataSource getSecurityMetadataSource() {
- return this.securityMetadataSource;
- }
-
- public Class<? extends Object> getSecureObjectClass() {
- return JoinPoint.class;
- }
-
- /**
- * This method should be used to enforce security on a <code>JoinPoint</code>.
- *
- * @param jp The AspectJ joint point being invoked which requires a security decision
- * @param advisorProceed the advice-defined anonymous class that implements <code>AspectJCallback</code> containing
- * a simple <code>return proceed();</code> statement
- *
- * @return The returned value from the method invocation
- */
- public Object invoke(JoinPoint jp, AspectJAnnotationCallback advisorProceed) throws Throwable {
- Object result = null;
- InterceptorStatusToken token = super.beforeInvocation(jp);
-
- try {
- result = advisorProceed.proceedWithObject();
- } finally {
- result = super.afterInvocation(token, result);
- }
-
- return result;
- }
-
- public SecurityMetadataSource obtainSecurityMetadataSource() {
- return this.securityMetadataSource;
- }
-
- public void setSecurityMetadataSource(MethodSecurityMetadataSource newSource) {
- this.securityMetadataSource = newSource;
- }
-
-}
diff --git a/dist/spring-security-core/org/springframework/security/access/intercept/aspectj/AspectJCallback.java b/dist/spring-security-core/org/springframework/security/access/intercept/aspectj/AspectJCallback.java
index c332bfb..6fabacd 100644
--- a/dist/spring-security-core/org/springframework/security/access/intercept/aspectj/AspectJCallback.java
+++ b/dist/spring-security-core/org/springframework/security/access/intercept/aspectj/AspectJCallback.java
@@ -16,7 +16,7 @@
package org.springframework.security.access.intercept.aspectj;
/**
- * Called by the {@link AspectJSecurityInterceptor} when it wishes for the
+ * Called by the {@link AspectJMethodSecurityInterceptor} when it wishes for the
* AspectJ processing to continue. Typically implemented in the
* <code>around()</code> advice as a simple <code>return proceed();</code>
* statement.
diff --git a/dist/spring-security-core/org/springframework/security/access/intercept/aspectj/AspectJMethodSecurityInterceptor.java b/dist/spring-security-core/org/springframework/security/access/intercept/aspectj/AspectJMethodSecurityInterceptor.java
index 8682056..3ea0231 100644
--- a/dist/spring-security-core/org/springframework/security/access/intercept/aspectj/AspectJMethodSecurityInterceptor.java
+++ b/dist/spring-security-core/org/springframework/security/access/intercept/aspectj/AspectJMethodSecurityInterceptor.java
@@ -37,15 +37,10 @@ public final class AspectJMethodSecurityInterceptor extends MethodSecurityInterc
* @return The returned value from the method invocation
*/
public Object invoke(JoinPoint jp, AspectJCallback advisorProceed) {
- Object result = null;
InterceptorStatusToken token = super.beforeInvocation(new MethodInvocationAdapter(jp));
- try {
- result = advisorProceed.proceedWithObject();
- } finally {
- result = super.afterInvocation(token, result);
- }
+ Object result = advisorProceed.proceedWithObject();
- return result;
+ return super.afterInvocation(token, result);
}
}
diff --git a/dist/spring-security-core/org/springframework/security/access/intercept/aspectj/AspectJSecurityInterceptor.java b/dist/spring-security-core/org/springframework/security/access/intercept/aspectj/AspectJSecurityInterceptor.java
deleted file mode 100644
index 3e23102..0000000
--- a/dist/spring-security-core/org/springframework/security/access/intercept/aspectj/AspectJSecurityInterceptor.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/* Copyright 2004, 2005, 2006 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.access.intercept.aspectj;
-
-import org.springframework.security.access.SecurityMetadataSource;
-import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
-import org.springframework.security.access.intercept.InterceptorStatusToken;
-import org.springframework.security.access.method.MethodSecurityMetadataSource;
-
-import org.aspectj.lang.JoinPoint;
-
-
-/**
- * Provides security interception of AspectJ method invocations.
- * <p>
- * The <code>SecurityMetadataSource</code> required by this security interceptor is of type
- * {@link MethodSecurityMetadataSource}. This is shared with the AOP Alliance based security interceptor
- * (<code>MethodSecurityInterceptor</code>), since both work with Java <code>Method</code>s.
- * <p>
- * The secure object type is <code>org.aspectj.lang.JoinPoint</code>, which is passed from the relevant
- * <code>around()</code> advice. The <code>around()</code> advice also passes an anonymous implementation of {@link
- * AspectJCallback} which contains the call for AspectJ to continue processing: <code>return proceed();</code>.
- * <p>
- * Refer to {@link AbstractSecurityInterceptor} for details on the workflow.
- *
- * @author Ben Alex
- * @deprecated Use AspectJMethodSecurityInterceptor instead
- */
- at Deprecated
-public class AspectJSecurityInterceptor extends AbstractSecurityInterceptor {
- //~ Instance fields ================================================================================================
-
- private MethodSecurityMetadataSource securityMetadataSource;
-
- //~ Methods ========================================================================================================
-
- public Class<? extends Object> getSecureObjectClass() {
- return JoinPoint.class;
- }
-
- /**
- * This method should be used to enforce security on a <code>JoinPoint</code>.
- *
- * @param jp The AspectJ joint point being invoked which requires a security decision
- * @param advisorProceed the advice-defined anonymous class that implements <code>AspectJCallback</code> containing
- * a simple <code>return proceed();</code> statement
- *
- * @return The returned value from the method invocation
- */
- public Object invoke(JoinPoint jp, AspectJCallback advisorProceed) {
- Object result = null;
- InterceptorStatusToken token = super.beforeInvocation(jp);
-
- try {
- result = advisorProceed.proceedWithObject();
- } finally {
- result = super.afterInvocation(token, result);
- }
-
- return result;
- }
-
- public SecurityMetadataSource obtainSecurityMetadataSource() {
- return this.securityMetadataSource;
- }
-
- public void setSecurityMetadataSource(MethodSecurityMetadataSource newSource) {
- this.securityMetadataSource = newSource;
- }
-}
diff --git a/dist/spring-security-core/org/springframework/security/access/intercept/aspectj/MethodInvocationAdapter.java b/dist/spring-security-core/org/springframework/security/access/intercept/aspectj/MethodInvocationAdapter.java
index a664c7c..271df0a 100644
--- a/dist/spring-security-core/org/springframework/security/access/intercept/aspectj/MethodInvocationAdapter.java
+++ b/dist/spring-security-core/org/springframework/security/access/intercept/aspectj/MethodInvocationAdapter.java
@@ -32,11 +32,31 @@ public final class MethodInvocationAdapter implements MethodInvocation {
}
String targetMethodName = jp.getStaticPart().getSignature().getName();
Class<?>[] types = ((CodeSignature) jp.getStaticPart().getSignature()).getParameterTypes();
- Class<?> declaringType = ((CodeSignature) jp.getStaticPart().getSignature()).getDeclaringType();
+ Class<?> declaringType = jp.getStaticPart().getSignature().getDeclaringType();
- method = ClassUtils.getMethodIfAvailable(declaringType, targetMethodName, types);
- Assert.notNull(method, "Could not obtain target method from JoinPoint: '"+ jp + "'");
+ method = findMethod(targetMethodName, declaringType, types);
+ if(method == null) {
+ throw new IllegalArgumentException("Could not obtain target method from JoinPoint: '"+ jp + "'");
+ }
+ }
+
+ private Method findMethod(String name, Class<?> declaringType, Class<?>[] params) {
+ Method method = null;
+
+ try {
+ method = declaringType.getMethod(name, params);
+ } catch (NoSuchMethodException ignored) {
+ }
+
+ if (method == null) {
+ try {
+ method = declaringType.getDeclaredMethod(name, params);
+ } catch (NoSuchMethodException ignored) {
+ }
+ }
+
+ return method;
}
public Method getMethod() {
diff --git a/dist/spring-security-core/org/springframework/security/access/method/AbstractFallbackMethodSecurityMetadataSource.java b/dist/spring-security-core/org/springframework/security/access/method/AbstractFallbackMethodSecurityMetadataSource.java
index 343faea..5dfd646 100644
--- a/dist/spring-security-core/org/springframework/security/access/method/AbstractFallbackMethodSecurityMetadataSource.java
+++ b/dist/spring-security-core/org/springframework/security/access/method/AbstractFallbackMethodSecurityMetadataSource.java
@@ -1,7 +1,7 @@
package org.springframework.security.access.method;
import java.lang.reflect.Method;
-import java.util.Collection;
+import java.util.*;
import org.springframework.aop.support.AopUtils;
import org.springframework.security.access.ConfigAttribute;
@@ -51,7 +51,7 @@ public abstract class AbstractFallbackMethodSecurityMetadataSource extends Abstr
// Last fallback is the class of the original method.
return findAttributes(method.getDeclaringClass());
}
- return null;
+ return Collections.emptyList();
}
/**
diff --git a/dist/spring-security-core/org/springframework/security/access/method/AbstractMethodSecurityMetadataSource.java b/dist/spring-security-core/org/springframework/security/access/method/AbstractMethodSecurityMetadataSource.java
index 63ec450..50259d2 100644
--- a/dist/spring-security-core/org/springframework/security/access/method/AbstractMethodSecurityMetadataSource.java
+++ b/dist/spring-security-core/org/springframework/security/access/method/AbstractMethodSecurityMetadataSource.java
@@ -15,26 +15,18 @@
package org.springframework.security.access.method;
-import org.springframework.security.access.ConfigAttribute;
+import java.util.Collection;
import org.aopalliance.intercept.MethodInvocation;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-
-import org.aspectj.lang.JoinPoint;
-import org.aspectj.lang.reflect.CodeSignature;
-
-import org.springframework.util.Assert;
-import org.springframework.util.ClassUtils;
-
-import java.lang.reflect.Method;
-import java.util.Collection;
+import org.springframework.aop.framework.AopProxyUtils;
+import org.springframework.security.access.ConfigAttribute;
/**
* Abstract implementation of <tt>MethodSecurityMetadataSource</tt> which resolves the secured object type to
- * either a MethodInvocation or a JoinPoint.
+ * a MethodInvocation.
*
* @author Ben Alex
* @author Luke Taylor
@@ -52,36 +44,16 @@ public abstract class AbstractMethodSecurityMetadataSource implements MethodSecu
Class<?> targetClass = null;
if (target != null) {
- targetClass = target instanceof Class<?> ? (Class<?>)target : target.getClass();
+ targetClass = target instanceof Class<?> ? (Class<?>)target : AopProxyUtils.ultimateTargetClass(target);
}
return getAttributes(mi.getMethod(), targetClass);
}
- if (object instanceof JoinPoint) {
- JoinPoint jp = (JoinPoint) object;
- Class<?> targetClass;
-
- if (jp.getTarget() != null) {
- targetClass = jp.getTarget().getClass();
- } else {
- // SEC-1295: target may be null if an ITD is in use
- targetClass = jp.getSignature().getDeclaringType();
- }
- String targetMethodName = jp.getStaticPart().getSignature().getName();
- Class<?>[] types = ((CodeSignature) jp.getStaticPart().getSignature()).getParameterTypes();
- Class<?> declaringType = ((CodeSignature) jp.getStaticPart().getSignature()).getDeclaringType();
-
- Method method = ClassUtils.getMethodIfAvailable(declaringType, targetMethodName, types);
- Assert.notNull(method, "Could not obtain target method from JoinPoint: '"+ jp + "'");
-
- return getAttributes(method, targetClass);
- }
-
- throw new IllegalArgumentException("Object must be a non-null MethodInvocation or JoinPoint");
+ throw new IllegalArgumentException("Object must be a non-null MethodInvocation");
}
public final boolean supports(Class<?> clazz) {
- return (MethodInvocation.class.isAssignableFrom(clazz) || JoinPoint.class.isAssignableFrom(clazz));
+ return (MethodInvocation.class.isAssignableFrom(clazz));
}
}
diff --git a/dist/spring-security-core/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSource.java b/dist/spring-security-core/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSource.java
index f2aeeab..553c8f5 100644
--- a/dist/spring-security-core/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSource.java
+++ b/dist/spring-security-core/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSource.java
@@ -9,39 +9,38 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
-import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
/**
* Automatically tries a series of method definition sources, relying on the first source of metadata
- * that provides a non-null response. Provides automatic caching of the retrieved metadata.
+ * that provides a non-null/non-empty response. Provides automatic caching of the retrieved metadata.
*
* @author Ben Alex
* @author Luke Taylor
*/
-public final class DelegatingMethodSecurityMetadataSource extends AbstractMethodSecurityMetadataSource implements InitializingBean {
+public final class DelegatingMethodSecurityMetadataSource extends AbstractMethodSecurityMetadataSource {
private final static List<ConfigAttribute> NULL_CONFIG_ATTRIBUTE = Collections.emptyList();
- private List<MethodSecurityMetadataSource> methodSecurityMetadataSources;
+ private final List<MethodSecurityMetadataSource> methodSecurityMetadataSources;
private final Map<DefaultCacheKey, Collection<ConfigAttribute>> attributeCache =
new HashMap<DefaultCacheKey, Collection<ConfigAttribute>>();
- //~ Methods ========================================================================================================
+ //~ Constructor ====================================================================================================
- public void afterPropertiesSet() throws Exception {
- Assert.notNull(methodSecurityMetadataSources, "A list of MethodSecurityMetadataSources is required");
+ public DelegatingMethodSecurityMetadataSource(List<MethodSecurityMetadataSource> methodSecurityMetadataSources) {
+ Assert.notNull(methodSecurityMetadataSources, "MethodSecurityMetadataSources cannot be null");
+ this.methodSecurityMetadataSources = methodSecurityMetadataSources;
}
+ //~ Methods ========================================================================================================
+
public Collection<ConfigAttribute> getAttributes(Method method, Class<?> targetClass) {
DefaultCacheKey cacheKey = new DefaultCacheKey(method, targetClass);
synchronized (attributeCache) {
Collection<ConfigAttribute> cached = attributeCache.get(cacheKey);
// Check for canonical value indicating there is no config attribute,
- if (cached == NULL_CONFIG_ATTRIBUTE) {
- return null;
- }
if (cached != null) {
return cached;
@@ -51,19 +50,19 @@ public final class DelegatingMethodSecurityMetadataSource extends AbstractMethod
Collection<ConfigAttribute> attributes = null;
for (MethodSecurityMetadataSource s : methodSecurityMetadataSources) {
attributes = s.getAttributes(method, targetClass);
- if (attributes != null) {
+ if (attributes != null && !attributes.isEmpty()) {
break;
}
}
// Put it in the cache.
- if (attributes == null) {
+ if (attributes == null || attributes.isEmpty()) {
this.attributeCache.put(cacheKey, NULL_CONFIG_ATTRIBUTE);
- return null;
+ return NULL_CONFIG_ATTRIBUTE;
}
if (logger.isDebugEnabled()) {
- logger.debug("Adding security method [" + cacheKey + "] with attributes " + attributes);
+ logger.debug("Caching method [" + cacheKey + "] with attributes " + attributes);
}
this.attributeCache.put(cacheKey, attributes);
@@ -83,9 +82,8 @@ public final class DelegatingMethodSecurityMetadataSource extends AbstractMethod
return set;
}
- @SuppressWarnings("unchecked")
- public void setMethodSecurityMetadataSources(List methodSecurityMetadataSources) {
- this.methodSecurityMetadataSources = methodSecurityMetadataSources;
+ public List<MethodSecurityMetadataSource> getMethodSecurityMetadataSources() {
+ return methodSecurityMetadataSources;
}
//~ Inner Classes ==================================================================================================
@@ -100,12 +98,6 @@ public final class DelegatingMethodSecurityMetadataSource extends AbstractMethod
}
public boolean equals(Object other) {
- if (this == other) {
- return true;
- }
- if (!(other instanceof DefaultCacheKey)) {
- return false;
- }
DefaultCacheKey otherKey = (DefaultCacheKey) other;
return (this.method.equals(otherKey.method) &&
ObjectUtils.nullSafeEquals(this.targetClass, otherKey.targetClass));
diff --git a/dist/spring-security-core/org/springframework/security/access/method/MapBasedMethodSecurityMetadataSource.java b/dist/spring-security-core/org/springframework/security/access/method/MapBasedMethodSecurityMetadataSource.java
index 04d8bd7..9f6edcc 100644
--- a/dist/spring-security-core/org/springframework/security/access/method/MapBasedMethodSecurityMetadataSource.java
+++ b/dist/spring-security-core/org/springframework/security/access/method/MapBasedMethodSecurityMetadataSource.java
@@ -50,10 +50,10 @@ public class MapBasedMethodSecurityMetadataSource extends AbstractFallbackMethod
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
/** Map from RegisteredMethod to ConfigAttribute list */
- protected Map<RegisteredMethod, List<ConfigAttribute>> methodMap = new HashMap<RegisteredMethod, List<ConfigAttribute>>();
+ protected final Map<RegisteredMethod, List<ConfigAttribute>> methodMap = new HashMap<RegisteredMethod, List<ConfigAttribute>>();
/** Map from RegisteredMethod to name pattern used for registration */
- private Map<RegisteredMethod, String> nameMap = new HashMap<RegisteredMethod, String>();
+ private final Map<RegisteredMethod, String> nameMap = new HashMap<RegisteredMethod, String>();
//~ Methods ========================================================================================================
@@ -141,9 +141,9 @@ public class MapBasedMethodSecurityMetadataSource extends AbstractFallbackMethod
Method[] methods = javaType.getMethods();
List<Method> matchingMethods = new ArrayList<Method>();
- for (int i = 0; i < methods.length; i++) {
- if (methods[i].getName().equals(mappedName) || isMatch(methods[i].getName(), mappedName)) {
- matchingMethods.add(methods[i]);
+ for (Method m : methods) {
+ if (m.getName().equals(mappedName) || isMatch(m.getName(), mappedName)) {
+ matchingMethods.add(m);
}
}
@@ -256,8 +256,8 @@ public class MapBasedMethodSecurityMetadataSource extends AbstractFallbackMethod
* Class will be the Class we're invoking against and the Method will provide details of the declared class.
*/
private class RegisteredMethod {
- private Method method;
- private Class<?> registeredJavaType;
+ private final Method method;
+ private final Class<?> registeredJavaType;
public RegisteredMethod(Method method, Class<?> registeredJavaType) {
Assert.notNull(method, "Method required");
diff --git a/dist/spring-security-core/org/springframework/security/access/method/MethodSecurityMetadataSourceEditor.java b/dist/spring-security-core/org/springframework/security/access/method/MethodSecurityMetadataSourceEditor.java
deleted file mode 100644
index 7856ba8..0000000
--- a/dist/spring-security-core/org/springframework/security/access/method/MethodSecurityMetadataSourceEditor.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/* Copyright 2004, 2005, 2006 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.access.method;
-
-import java.beans.PropertyEditorSupport;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-
-import org.springframework.beans.propertyeditors.PropertiesEditor;
-import org.springframework.security.access.ConfigAttribute;
-import org.springframework.security.access.SecurityConfig;
-import org.springframework.util.StringUtils;
-
-
-/**
- * Property editor to assist with the setup of a {@link MethodSecurityMetadataSource}.
- * <p>
- * The class creates and populates a {@link MapBasedMethodSecurityMetadataSource}.
- *
- * @author Ben Alex
- * @deprecated use method annotations or the protect-pointcut support from the namespace
- */
-public class MethodSecurityMetadataSourceEditor extends PropertyEditorSupport {
- //~ Methods ========================================================================================================
-
- @SuppressWarnings("unchecked")
- public void setAsText(String s) throws IllegalArgumentException {
- if ((s == null) || "".equals(s)) {
- setValue(new MapBasedMethodSecurityMetadataSource());
- return;
- }
-
- // Use properties editor to tokenize the string
- PropertiesEditor propertiesEditor = new PropertiesEditor();
- propertiesEditor.setAsText(s);
-
- Properties props = (Properties) propertiesEditor.getValue();
-
- // Now we have properties, process each one individually
- Map<String, List<ConfigAttribute>> mappings = new LinkedHashMap<String, List<ConfigAttribute>>();
-
- for (Iterator iter = props.keySet().iterator(); iter.hasNext();) {
- String name = (String) iter.next();
- String value = props.getProperty(name);
-
- String[] tokens = StringUtils.commaDelimitedListToStringArray(value);
- List<ConfigAttribute> attributes = new ArrayList<ConfigAttribute>(tokens.length);
-
- for(String token : tokens) {
- attributes.add(new SecurityConfig(token));
- }
-
- mappings.put(name, attributes);
- }
-
- setValue(new MapBasedMethodSecurityMetadataSource(mappings));
- }
-}
diff --git a/dist/spring-security-core/org/springframework/security/access/prepost/PostInvocationAdviceProvider.java b/dist/spring-security-core/org/springframework/security/access/prepost/PostInvocationAdviceProvider.java
index 88016b2..55a6d88 100644
--- a/dist/spring-security-core/org/springframework/security/access/prepost/PostInvocationAdviceProvider.java
+++ b/dist/spring-security-core/org/springframework/security/access/prepost/PostInvocationAdviceProvider.java
@@ -20,7 +20,7 @@ import org.springframework.security.core.Authentication;
public class PostInvocationAdviceProvider implements AfterInvocationProvider {
protected final Log logger = LogFactory.getLog(getClass());
- private PostInvocationAuthorizationAdvice postAdvice;
+ private final PostInvocationAuthorizationAdvice postAdvice;
public PostInvocationAdviceProvider(PostInvocationAuthorizationAdvice postAdvice) {
this.postAdvice = postAdvice;
diff --git a/dist/spring-security-core/org/springframework/security/access/prepost/PreInvocationAuthorizationAdviceVoter.java b/dist/spring-security-core/org/springframework/security/access/prepost/PreInvocationAuthorizationAdviceVoter.java
index 4904e9e..7132ad2 100644
--- a/dist/spring-security-core/org/springframework/security/access/prepost/PreInvocationAuthorizationAdviceVoter.java
+++ b/dist/spring-security-core/org/springframework/security/access/prepost/PreInvocationAuthorizationAdviceVoter.java
@@ -21,24 +21,24 @@ import org.springframework.security.core.Authentication;
* @author Luke Taylor
* @since 3.0
*/
-public class PreInvocationAuthorizationAdviceVoter implements AccessDecisionVoter {
+public class PreInvocationAuthorizationAdviceVoter implements AccessDecisionVoter<MethodInvocation> {
protected final Log logger = LogFactory.getLog(getClass());
- private PreInvocationAuthorizationAdvice preAdvice;
+ private final PreInvocationAuthorizationAdvice preAdvice;
public PreInvocationAuthorizationAdviceVoter(PreInvocationAuthorizationAdvice pre) {
this.preAdvice = pre;
}
public boolean supports(ConfigAttribute attribute) {
- return attribute instanceof PreInvocationAuthorizationAdvice;
+ return attribute instanceof PreInvocationAttribute;
}
public boolean supports(Class<?> clazz) {
return clazz.isAssignableFrom(MethodInvocation.class);
}
- public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) {
+ public int vote(Authentication authentication, MethodInvocation method, Collection<ConfigAttribute> attributes) {
// Find prefilter and preauth (or combined) attributes
// if both null, abstain
@@ -51,7 +51,7 @@ public class PreInvocationAuthorizationAdviceVoter implements AccessDecisionVote
return ACCESS_ABSTAIN;
}
- boolean allowed = preAdvice.before(authentication, (MethodInvocation)object, preAttr);
+ boolean allowed = preAdvice.before(authentication, method, preAttr);
return allowed ? ACCESS_GRANTED : ACCESS_DENIED;
}
diff --git a/dist/spring-security-core/org/springframework/security/access/prepost/PrePostAnnotationSecurityMetadataSource.java b/dist/spring-security-core/org/springframework/security/access/prepost/PrePostAnnotationSecurityMetadataSource.java
index 5138f5f..d8f852e 100644
--- a/dist/spring-security-core/org/springframework/security/access/prepost/PrePostAnnotationSecurityMetadataSource.java
+++ b/dist/spring-security-core/org/springframework/security/access/prepost/PrePostAnnotationSecurityMetadataSource.java
@@ -2,8 +2,7 @@ package org.springframework.security.access.prepost;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Collection;
+import java.util.*;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.security.access.ConfigAttribute;
@@ -38,7 +37,7 @@ public class PrePostAnnotationSecurityMetadataSource extends AbstractMethodSecur
public Collection<ConfigAttribute> getAttributes(Method method, Class<?> targetClass) {
if (method.getDeclaringClass() == Object.class) {
- return null;
+ return Collections.emptyList();
}
logger.trace("Looking for Pre/Post annotations for method '" +
@@ -52,18 +51,24 @@ public class PrePostAnnotationSecurityMetadataSource extends AbstractMethodSecur
if (preFilter == null && preAuthorize == null && postFilter == null && postAuthorize == null ) {
// There is no meta-data so return
logger.trace("No expression annotations found");
- return null;
+ return Collections.emptyList();
}
- ArrayList<ConfigAttribute> attrs = new ArrayList<ConfigAttribute>();
+ String preFilterAttribute = preFilter == null ? null : preFilter.value();
+ String filterObject = preFilter == null ? null : preFilter.filterTarget();
+ String preAuthorizeAttribute = preAuthorize == null ? null : preAuthorize.value();
+ String postFilterAttribute = postFilter == null ? null : postFilter.value();
+ String postAuthorizeAttribute = postAuthorize == null ? null : postAuthorize.value();
- PreInvocationAttribute pre = attributeFactory.createPreInvocationAttribute(preFilter, preAuthorize);
+ ArrayList<ConfigAttribute> attrs = new ArrayList<ConfigAttribute>(2);
+
+ PreInvocationAttribute pre = attributeFactory.createPreInvocationAttribute(preFilterAttribute, filterObject, preAuthorizeAttribute);
if (pre != null) {
attrs.add(pre);
}
- PostInvocationAttribute post = attributeFactory.createPostInvocationAttribute(postFilter, postAuthorize);
+ PostInvocationAttribute post = attributeFactory.createPostInvocationAttribute(postFilterAttribute, postAuthorizeAttribute);
if (post != null) {
attrs.add(post);
@@ -71,7 +76,7 @@ public class PrePostAnnotationSecurityMetadataSource extends AbstractMethodSecur
attrs.trimToSize();
- return attrs.isEmpty() ? null : attrs;
+ return attrs;
}
public Collection<ConfigAttribute> getAllConfigAttributes() {
@@ -105,23 +110,13 @@ public class PrePostAnnotationSecurityMetadataSource extends AbstractMethodSecur
}
// Check the class-level (note declaringClass, not targetClass, which may not actually implement the method)
- annotation = specificMethod.getDeclaringClass().getAnnotation(annotationClass);
+ annotation = AnnotationUtils.findAnnotation(specificMethod.getDeclaringClass(), annotationClass);
if (annotation != null) {
logger.debug(annotation + " found on: " + specificMethod.getDeclaringClass().getName());
return annotation;
}
- // Check for a possible interface annotation which would not be inherited by the declaring class
- if (specificMethod != method) {
- annotation = method.getDeclaringClass().getAnnotation(annotationClass);
-
- if (annotation != null) {
- logger.debug(annotation + " found on: " + method.getDeclaringClass().getName());
- return annotation;
- }
- }
-
return null;
}
diff --git a/dist/spring-security-core/org/springframework/security/access/prepost/PrePostInvocationAttributeFactory.java b/dist/spring-security-core/org/springframework/security/access/prepost/PrePostInvocationAttributeFactory.java
index 5c34e03..c353a07 100644
--- a/dist/spring-security-core/org/springframework/security/access/prepost/PrePostInvocationAttributeFactory.java
+++ b/dist/spring-security-core/org/springframework/security/access/prepost/PrePostInvocationAttributeFactory.java
@@ -9,7 +9,7 @@ import org.springframework.aop.framework.AopInfrastructureBean;
*/
public interface PrePostInvocationAttributeFactory extends AopInfrastructureBean {
- PreInvocationAttribute createPreInvocationAttribute(PreFilter preFilter, PreAuthorize preAuthorize);
+ PreInvocationAttribute createPreInvocationAttribute(String preFilterAttribute, String filterObject, String preAuthorizeAttribute);
- PostInvocationAttribute createPostInvocationAttribute(PostFilter postFilter, PostAuthorize postAuthorize);
+ PostInvocationAttribute createPostInvocationAttribute(String postFilterAttribute, String postAuthorizeAttribute);
}
diff --git a/dist/spring-security-core/org/springframework/security/access/vote/AbstractAccessDecisionManager.java b/dist/spring-security-core/org/springframework/security/access/vote/AbstractAccessDecisionManager.java
index 372b753..9e824af 100644
--- a/dist/spring-security-core/org/springframework/security/access/vote/AbstractAccessDecisionManager.java
+++ b/dist/spring-security-core/org/springframework/security/access/vote/AbstractAccessDecisionManager.java
@@ -50,6 +50,14 @@ public abstract class AbstractAccessDecisionManager implements AccessDecisionMan
private boolean allowIfAllAbstainDecisions = false;
+ protected AbstractAccessDecisionManager() {
+ }
+
+ protected AbstractAccessDecisionManager(List<AccessDecisionVoter> decisionVoters) {
+ Assert.notEmpty(decisionVoters, "A list of AccessDecisionVoters is required");
+ this.decisionVoters = decisionVoters;
+ }
+
//~ Methods ========================================================================================================
public void afterPropertiesSet() throws Exception {
@@ -76,6 +84,10 @@ public abstract class AbstractAccessDecisionManager implements AccessDecisionMan
this.allowIfAllAbstainDecisions = allowIfAllAbstainDecisions;
}
+ /**
+ * @deprecated Use constructor
+ */
+ @Deprecated
public void setDecisionVoters(List<AccessDecisionVoter> newList) {
Assert.notEmpty(newList);
@@ -95,11 +107,7 @@ public abstract class AbstractAccessDecisionManager implements AccessDecisionMan
}
public boolean supports(ConfigAttribute attribute) {
- Iterator<AccessDecisionVoter> iter = this.decisionVoters.iterator();
-
- while (iter.hasNext()) {
- AccessDecisionVoter voter = iter.next();
-
+ for (AccessDecisionVoter voter : this.decisionVoters) {
if (voter.supports(attribute)) {
return true;
}
@@ -118,11 +126,7 @@ public abstract class AbstractAccessDecisionManager implements AccessDecisionMan
* @return true if this type is supported
*/
public boolean supports(Class<?> clazz) {
- Iterator<AccessDecisionVoter> iter = this.decisionVoters.iterator();
-
- while (iter.hasNext()) {
- AccessDecisionVoter voter = iter.next();
-
+ for (AccessDecisionVoter voter : this.decisionVoters) {
if (!voter.supports(clazz)) {
return false;
}
diff --git a/dist/spring-security-core/org/springframework/security/access/vote/AbstractAclVoter.java b/dist/spring-security-core/org/springframework/security/access/vote/AbstractAclVoter.java
index 16cd0fc..b24ef14 100644
--- a/dist/spring-security-core/org/springframework/security/access/vote/AbstractAclVoter.java
+++ b/dist/spring-security-core/org/springframework/security/access/vote/AbstractAclVoter.java
@@ -14,14 +14,9 @@
*/
package org.springframework.security.access.vote;
+import org.aopalliance.intercept.MethodInvocation;
import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.AuthorizationServiceException;
-
-import org.aopalliance.intercept.MethodInvocation;
-
-import org.aspectj.lang.JoinPoint;
-import org.aspectj.lang.reflect.CodeSignature;
-
import org.springframework.util.Assert;
@@ -31,26 +26,19 @@ import org.springframework.util.Assert;
*
* @author Ben Alex
*/
-public abstract class AbstractAclVoter implements AccessDecisionVoter {
+public abstract class AbstractAclVoter implements AccessDecisionVoter<MethodInvocation> {
//~ Instance fields ================================================================================================
private Class<?> processDomainObjectClass;
//~ Methods ========================================================================================================
- protected Object getDomainObjectInstance(Object secureObject) {
+ protected Object getDomainObjectInstance(MethodInvocation invocation) {
Object[] args;
Class<?>[] params;
- if (secureObject instanceof MethodInvocation) {
- MethodInvocation invocation = (MethodInvocation) secureObject;
- params = invocation.getMethod().getParameterTypes();
- args = invocation.getArguments();
- } else {
- JoinPoint jp = (JoinPoint) secureObject;
- params = ((CodeSignature) jp.getStaticPart().getSignature()).getParameterTypes();
- args = jp.getArgs();
- }
+ params = invocation.getMethod().getParameterTypes();
+ args = invocation.getArguments();
for (int i = 0; i < params.length; i++) {
if (processDomainObjectClass.isAssignableFrom(params[i])) {
@@ -58,7 +46,7 @@ public abstract class AbstractAclVoter implements AccessDecisionVoter {
}
}
- throw new AuthorizationServiceException("Secure object: " + secureObject
+ throw new AuthorizationServiceException("MethodInvocation: " + invocation
+ " did not provide any argument of type: " + processDomainObjectClass);
}
@@ -80,12 +68,6 @@ public abstract class AbstractAclVoter implements AccessDecisionVoter {
* @return <code>true</code> if the secure object is <code>MethodInvocation</code>, <code>false</code> otherwise
*/
public boolean supports(Class<?> clazz) {
- if (MethodInvocation.class.isAssignableFrom(clazz)) {
- return true;
- } else if (JoinPoint.class.isAssignableFrom(clazz)) {
- return true;
- } else {
- return false;
- }
+ return (MethodInvocation.class.isAssignableFrom(clazz));
}
}
diff --git a/dist/spring-security-core/org/springframework/security/access/vote/AffirmativeBased.java b/dist/spring-security-core/org/springframework/security/access/vote/AffirmativeBased.java
index 4bf7a72..f47734c 100644
--- a/dist/spring-security-core/org/springframework/security/access/vote/AffirmativeBased.java
+++ b/dist/spring-security-core/org/springframework/security/access/vote/AffirmativeBased.java
@@ -15,7 +15,7 @@
package org.springframework.security.access.vote;
-import java.util.Collection;
+import java.util.*;
import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.AccessDeniedException;
@@ -28,6 +28,18 @@ import org.springframework.security.core.Authentication;
* <code>AccessDecisionVoter</code> returns an affirmative response.
*/
public class AffirmativeBased extends AbstractAccessDecisionManager {
+
+ /**
+ * @deprecated Use constructor which takes voter list
+ */
+ @Deprecated
+ public AffirmativeBased() {
+ }
+
+ public AffirmativeBased(List<AccessDecisionVoter> decisionVoters) {
+ super(decisionVoters);
+ }
+
//~ Methods ========================================================================================================
/**
diff --git a/dist/spring-security-core/org/springframework/security/access/vote/AuthenticatedVoter.java b/dist/spring-security-core/org/springframework/security/access/vote/AuthenticatedVoter.java
index d4ea93d..f08df32 100644
--- a/dist/spring-security-core/org/springframework/security/access/vote/AuthenticatedVoter.java
+++ b/dist/spring-security-core/org/springframework/security/access/vote/AuthenticatedVoter.java
@@ -41,7 +41,7 @@ import org.springframework.util.Assert;
*
* @author Ben Alex
*/
-public class AuthenticatedVoter implements AccessDecisionVoter {
+public class AuthenticatedVoter implements AccessDecisionVoter<Object> {
//~ Static fields/initializers =====================================================================================
public static final String IS_AUTHENTICATED_FULLY = "IS_AUTHENTICATED_FULLY";
@@ -77,9 +77,9 @@ public class AuthenticatedVoter implements AccessDecisionVoter {
/**
* This implementation supports any type of class, because it does not query the presented secure object.
*
- * @param clazz the secure object
+ * @param clazz the secure object type
*
- * @return always <code>true</code>
+ * @return always {@code true}
*/
public boolean supports(Class<?> clazz) {
return true;
diff --git a/dist/spring-security-core/org/springframework/security/access/vote/ConsensusBased.java b/dist/spring-security-core/org/springframework/security/access/vote/ConsensusBased.java
index d340034..e7bbeb7 100644
--- a/dist/spring-security-core/org/springframework/security/access/vote/ConsensusBased.java
+++ b/dist/spring-security-core/org/springframework/security/access/vote/ConsensusBased.java
@@ -15,7 +15,7 @@
package org.springframework.security.access.vote;
-import java.util.Collection;
+import java.util.*;
import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.AccessDeniedException;
@@ -34,6 +34,17 @@ public class ConsensusBased extends AbstractAccessDecisionManager {
private boolean allowIfEqualGrantedDeniedDecisions = true;
+ /**
+ * @deprecated Use constructor which takes voter list
+ */
+ @Deprecated
+ public ConsensusBased() {
+ }
+
+ public ConsensusBased(List<AccessDecisionVoter> decisionVoters) {
+ super(decisionVoters);
+ }
+
//~ Methods ========================================================================================================
/**
diff --git a/dist/spring-security-core/org/springframework/security/access/vote/InterfaceBasedLabelParameterStrategy.java b/dist/spring-security-core/org/springframework/security/access/vote/InterfaceBasedLabelParameterStrategy.java
deleted file mode 100644
index 6dca070..0000000
--- a/dist/spring-security-core/org/springframework/security/access/vote/InterfaceBasedLabelParameterStrategy.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/* Copyright 2004, 2005, 2006 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.access.vote;
-
-import java.lang.reflect.Method;
-
-
-/**
- * This is a very useful implementation of the LabelParameterStrategy. Data objects which are meant to be labeled
- * should implement the LabeledData interface. This strategy will then castdown to that interface for either testing
- * or retrieval of the label.
- *
- * @author Greg Turnquist
- */
-public class InterfaceBasedLabelParameterStrategy implements LabelParameterStrategy {
- //~ Instance fields ================================================================================================
-
- private String noLabel = "";
-
- //~ Methods ========================================================================================================
-
- /**
- * Test if the argument is labeled, and if so, downcast to LabeledData and retrieve the domain object's
- * labeled value. Otherwise, return an empty string. NOTE: The default for no label is an empty string. If somehow
- * the user wants to make that a label itself, he or she must inject an alternate value to the noLabel property.
- *
- * @param method DOCUMENT ME!
- * @param arg DOCUMENT ME!
- *
- * @return DOCUMENT ME!
- */
- public String getLabel(Method method, Object arg) {
- if (isLabeled(method, arg)) {
- return ((LabeledData) arg).getLabel();
- } else {
- return noLabel;
- }
- }
-
- public String getNoLabel() {
- return noLabel;
- }
-
- /**
- * Test if the argument implemented the LabeledData interface. NOTE: The invoking method has no bearing for
- * this strategy, only the argument itself.
- *
- * @param method DOCUMENT ME!
- * @param arg DOCUMENT ME!
- *
- * @return DOCUMENT ME!
- */
- public boolean isLabeled(Method method, Object arg) {
- return (arg instanceof LabeledData);
- }
-
- public void setNoLabel(String noLabel) {
- this.noLabel = noLabel;
- }
-}
diff --git a/dist/spring-security-core/org/springframework/security/access/vote/LabelBasedAclVoter.java b/dist/spring-security-core/org/springframework/security/access/vote/LabelBasedAclVoter.java
deleted file mode 100644
index 71fbcfa..0000000
--- a/dist/spring-security-core/org/springframework/security/access/vote/LabelBasedAclVoter.java
+++ /dev/null
@@ -1,269 +0,0 @@
-/* Copyright 2004, 2005, 2006 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.security.access.vote;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import org.aopalliance.intercept.MethodInvocation;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.security.access.ConfigAttribute;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.util.Assert;
-
-
-/**
- * <p>This Acl voter will evaluate methods based on labels applied to incoming arguments. It will only check
- * methods that have been properly tagged in the MethodSecurityInterceptor with the value stored in
- * <tt>attributeIndicatingLabeledOperation</tt>. If a method has been tagged, then it examines each argument, and if the
- * argument implements {@link LabeledData}, then it will asses if the user's list of granted authorities matches.
- * </p>
- *
- * <p>By default, if none of the arguments are labeled, then the access will be granted. This can be overridden by
- * setting <tt>allowAccessIfNoAttributesAreLabeled</tt> to false in the Spring context file.</p>
- *
- * <p>In many situations, different values are linked together to define a common label, it is necessary to
- * define a map in the application context that links user-assigned label access to domain object labels. This is done
- * by setting up the <tt>labelMap</tt> in the application context.</p>
- *
- * @author Greg Turnquist
- *
- * @see org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor
- * @deprecated Use new spring-security-acl module instead
- */
-public class LabelBasedAclVoter extends AbstractAclVoter {
- //~ Static fields/initializers =====================================================================================
-
- private static final Log logger = LogFactory.getLog(LabelBasedAclVoter.class);
-
- //~ Instance fields ================================================================================================
-
- private Map<String, List<String>> labelMap = null;
- private String attributeIndicatingLabeledOperation = null;
- private boolean allowAccessIfNoAttributesAreLabeled = true;
-
- //~ Methods ========================================================================================================
-
- /**
- * Set whether or not to allow the user to run methods in which none of the incoming arguments are labeled.
- *
- * <p>Default value: <b>true, users can run such methods.</b></p>
- *
- * @param allowAccessIfNoAttributesAreLabeled boolean
- */
- public void setAllowAccessIfNoAttributesAreLabeled(boolean allowAccessIfNoAttributesAreLabeled) {
- this.allowAccessIfNoAttributesAreLabeled = allowAccessIfNoAttributesAreLabeled;
- }
-
- /**
- * Each method intended for evaluation by this voter must include this tag name in the definition of the
- * MethodSecurityInterceptor, indicating if this voter should evaluate the arguments and compare them against the
- * label map.
- *
- * @param attributeIndicatingLabeledOperation string
- */
- public void setAttributeIndicatingLabeledOperation(String attributeIndicatingLabeledOperation) {
- this.attributeIndicatingLabeledOperation = attributeIndicatingLabeledOperation;
- }
-
- /**
- * Set the map that correlate a user's assigned label against domain object values that are considered data
- * labels. An example application context configuration of a <tt>labelMap</tt>:
- *
- * <pre>
- * <bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased">
- * <property name="allowIfAllAbstainDecisions"><value>false</value></property>
- * <property name="decisionVoters">
- * <list>
- * <bean class="org.springframework.security.access.vote.RoleVoter"/>
- * <bean class="org.springframework.security.access.vote.LabelBasedAclVoter">
- * <property name="attributeIndicatingLabeledOperation">
- * <value>LABELED_OPERATION</value>
- * </property>
- * <property name="labelMap">
- * <map>
- * <entry key="DATA_LABEL_BLUE">
- * <list>
- * <value>blue</value>
- * <value>indigo</value>
- * <value>purple</value>
- * </list>
- * </entry>
- * <entry key="LABEL_ORANGE">
- * <list>
- * <value>orange</value>
- * <value>sunshine</value>
- * <value>amber</value>
- * </list>
- * </entry>
- * <entry key="LABEL_ADMIN">
- * <list>
- * <value>blue</value>
- * <value>indigo</value>
- * <value>purple</value>
- * <value>orange</value>
- * <value>sunshine</value>
- * <value>amber</value>
- * </list>
- * </entry>
- * </map>
- * </property>
- * </bean>
- * </list>
- * </property>
- * </bean>
- * </pre>
- *
- * @param labelMap a map structured as in the above example.
- *
- */
- public void setLabelMap(Map<String, List<String>> labelMap) {
- this.labelMap = labelMap;
- }
-
- /**
- * This acl voter will only evaluate labeled methods if they are marked in the security interceptor's
- * configuration with the attribute stored in attributeIndicatingLabeledOperation.
- *
- * @see org.springframework.security.access.vote.AbstractAclVoter
- * @see org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor
- */
- public boolean supports(ConfigAttribute attribute) {
- if (attribute.getAttribute().equals(attributeIndicatingLabeledOperation)) {
- logger.debug(attribute + " is supported.");
-
- return true;
- }
-
- if (logger.isDebugEnabled()) {
- logger.debug(attribute + " is unsupported.");
- }
-
- return false;
- }
-
- /**
- * Vote on whether or not the user has all the labels necessary to match the method argument's labeled data.
- *
- * @return ACCESS_ABSTAIN, ACCESS_GRANTED, or ACCESS_DENIED.
- */
- public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) {
- int result = ACCESS_ABSTAIN;
-
- if (logger.isDebugEnabled()) {
- logger.debug("==========================================================");
- }
-
- if (this.supports(attributes.iterator().next())) {
- result = ACCESS_DENIED;
-
- /* Parse out the user's labels by examining the security context, and checking
- * for matches against the label map.
- */
- List<String> userLabels = new ArrayList<String>();
-
- for (GrantedAuthority authority : authentication.getAuthorities()) {
- String userLabel = authority.getAuthority();
- if (labelMap.containsKey(userLabel)) {
- userLabels.add(userLabel);
- logger.debug("Adding " + userLabel + " to <<<" + authentication.getName()
- + "'s>>> authorized label list");
- }
- }
-
- MethodInvocation invocation = (MethodInvocation) object;
-
- int matches = 0;
- int misses = 0;
- int labeledArguments = 0;
-
- for (int j = 0; j < invocation.getArguments().length; j++) {
- if (invocation.getArguments()[j] instanceof LabeledData) {
- labeledArguments++;
-
- boolean matched = false;
-
- String argumentDataLabel = ((LabeledData) invocation.getArguments()[j]).getLabel();
- logger.debug("Argument[" + j + "/" + invocation.getArguments()[j].getClass().getName()
- + "] has a data label of " + argumentDataLabel);
-
- List<String> validDataLabels = new ArrayList<String>();
-
- for (int i = 0; i < userLabels.size(); i++) {
- validDataLabels.addAll(labelMap.get(userLabels.get(i)));
- }
-
- logger.debug("The valid labels for user label " + userLabels + " are " + validDataLabels);
-
- for (String validDataLabel : validDataLabels) {
- if (argumentDataLabel.equals(validDataLabel)) {
- logger.debug(userLabels + " maps to " + validDataLabel + " which matches the argument");
- matched = true;
- }
- }
-
- if (matched) {
- logger.debug("We have a match!");
- matches++;
- } else {
- logger.debug("We have a miss!");
- misses++;
- }
- }
- }
- Assert.isTrue((matches + misses) == labeledArguments,
- "The matches (" + matches + ") and misses (" + misses + " ) don't add up (" + labeledArguments + ")");
-
- logger.debug("We have " + matches + " matches and " + misses + " misses and " + labeledArguments
- + " labeled arguments.");
-
- /* The result has already been set to ACCESS_DENIED. Only if there is a proper match of
- * labels will this be overturned. However, if none of the attributes are actually labeled,
- * the result is dependent on allowAccessIfNoAttributesAreLabeled.
- */
- if ((matches > 0) && (misses == 0)) {
- result = ACCESS_GRANTED;
- } else if (labeledArguments == 0) {
- if (allowAccessIfNoAttributesAreLabeled) {
- result = ACCESS_GRANTED;
- } else {
- result = ACCESS_DENIED;
- }
- }
- }
-
- if (logger.isDebugEnabled()) {
- switch (result) {
- case ACCESS_GRANTED:
- logger.debug("===== Access is granted =====");
- break;
-
- case ACCESS_DENIED:
- logger.debug("===== Access is denied =====");
- break;
-
- case ACCESS_ABSTAIN:
- logger.debug("===== Abstaining =====");
- break;
- }
- }
-
- return result;
- }
-}
diff --git a/dist/spring-security-core/org/springframework/security/access/vote/LabelParameterStrategy.java b/dist/spring-security-core/org/springframework/security/access/vote/LabelParameterStrategy.java
deleted file mode 100644
index 531574f..0000000
--- a/dist/spring-security-core/org/springframework/security/access/vote/LabelParameterStrategy.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/* Copyright 2004, 2005, 2006 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.security.access.vote;
-
-import java.lang.reflect.Method;
-
-
-/**
- * This is a strategy interface for determining which parts of a method invocation
- * are labeled. Not all arguments are necessarily labeled. This offers a plugabble
- * mechanism to define various ways to label data.
- *
- * @author Greg Turnquist
- */
-public interface LabelParameterStrategy {
- //~ Methods ========================================================================================================
-
- /**
- * Get the actual label associated with the argument. NOTE: This currently only supports one label per
- * argument.
- *
- * @param method
- * @param arg
- *
- * @return string value of the label
- */
- String getLabel(Method method, Object arg);
-
- /**
- * Evaluate if one particular argument is labeled. The context of the method is also provided should that
- * have bearing on the label.
- *
- * @param method
- * @param arg
- *
- * @return boolean
- */
- boolean isLabeled(Method method, Object arg);
-}
diff --git a/dist/spring-security-core/org/springframework/security/access/vote/LabeledData.java b/dist/spring-security-core/org/springframework/security/access/vote/LabeledData.java
deleted file mode 100644
index 3517dc9..0000000
--- a/dist/spring-security-core/org/springframework/security/access/vote/LabeledData.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Copyright 2004, 2005, 2006 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.access.vote;
-
-/**
- * This interface indicates data objects that carry a label. The purpose is to support
- * the {@link LabelBasedAclVoter}. When it votes, it evaluates all method arguments
- * tagged with this interface, and votes if they match the user's granted authorities list.
- *
- * @author Greg Turnquist
- */
-public interface LabeledData {
- //~ Methods ========================================================================================================
-
- /**
- * Retrieve the domain object's data label. NOTE: This implementation only supports one data label per
- * object.
- *
- * @return The label value of data object as a string.
- */
- String getLabel();
-}
diff --git a/dist/spring-security-core/org/springframework/security/access/vote/RoleHierarchyVoter.java b/dist/spring-security-core/org/springframework/security/access/vote/RoleHierarchyVoter.java
index 6efee48..2a4ab0f 100644
--- a/dist/spring-security-core/org/springframework/security/access/vote/RoleHierarchyVoter.java
+++ b/dist/spring-security-core/org/springframework/security/access/vote/RoleHierarchyVoter.java
@@ -26,7 +26,7 @@ public class RoleHierarchyVoter extends RoleVoter {
* Calls the <tt>RoleHierarchy</tt> to obtain the complete set of user authorities.
*/
@Override
- Collection<GrantedAuthority> extractAuthorities(Authentication authentication) {
+ Collection<? extends GrantedAuthority> extractAuthorities(Authentication authentication) {
return roleHierarchy.getReachableGrantedAuthorities(authentication.getAuthorities());
}
}
diff --git a/dist/spring-security-core/org/springframework/security/access/vote/RoleVoter.java b/dist/spring-security-core/org/springframework/security/access/vote/RoleVoter.java
index 5f3b165..29b5af2 100644
--- a/dist/spring-security-core/org/springframework/security/access/vote/RoleVoter.java
+++ b/dist/spring-security-core/org/springframework/security/access/vote/RoleVoter.java
@@ -49,7 +49,7 @@ import org.springframework.security.core.GrantedAuthority;
* @author Ben Alex
* @author colin sampaleanu
*/
-public class RoleVoter implements AccessDecisionVoter {
+public class RoleVoter implements AccessDecisionVoter<Object> {
//~ Instance fields ================================================================================================
private String rolePrefix = "ROLE_";
@@ -93,7 +93,7 @@ public class RoleVoter implements AccessDecisionVoter {
public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) {
int result = ACCESS_ABSTAIN;
- Collection<GrantedAuthority> authorities = extractAuthorities(authentication);
+ Collection<? extends GrantedAuthority> authorities = extractAuthorities(authentication);
for (ConfigAttribute attribute : attributes) {
if (this.supports(attribute)) {
@@ -111,7 +111,7 @@ public class RoleVoter implements AccessDecisionVoter {
return result;
}
- Collection<GrantedAuthority> extractAuthorities(Authentication authentication) {
+ Collection<? extends GrantedAuthority> extractAuthorities(Authentication authentication) {
return authentication.getAuthorities();
}
}
diff --git a/dist/spring-security-core/org/springframework/security/access/vote/UnanimousBased.java b/dist/spring-security-core/org/springframework/security/access/vote/UnanimousBased.java
index 821c7c2..9f2718b 100644
--- a/dist/spring-security-core/org/springframework/security/access/vote/UnanimousBased.java
+++ b/dist/spring-security-core/org/springframework/security/access/vote/UnanimousBased.java
@@ -30,6 +30,18 @@ import org.springframework.security.core.Authentication;
* voters to abstain or grant access.
*/
public class UnanimousBased extends AbstractAccessDecisionManager {
+
+ /**
+ * @deprecated Use constructor which takes voter list
+ */
+ @Deprecated
+ public UnanimousBased() {
+ }
+
+ public UnanimousBased(List<AccessDecisionVoter> decisionVoters) {
+ super(decisionVoters);
+ }
+
//~ Methods ========================================================================================================
/**
diff --git a/dist/spring-security-core/org/springframework/security/authentication/AbstractAuthenticationManager.java b/dist/spring-security-core/org/springframework/security/authentication/AbstractAuthenticationManager.java
deleted file mode 100644
index 5574ebb..0000000
--- a/dist/spring-security-core/org/springframework/security/authentication/AbstractAuthenticationManager.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/* Copyright 2004, 2005, 2006 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.authentication;
-
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.AuthenticationException;
-
-/**
- * An abstract implementation of the {@link AuthenticationManager}.
- *
- * @author Wesley Hall
- */
-public abstract class AbstractAuthenticationManager implements AuthenticationManager {
-
- //~ Instance fields ================================================================================================
- private boolean clearExtraInformation = false;
-
- //~ Methods ========================================================================================================
-
- /**
- * An implementation of the <code>authenticate</code> method that calls the abstract method
- * <code>doAuthenticatation</code> to do its work.
- * <p>
- * If doAuthenticate throws an <code>AuthenticationException</code> then the exception is populated
- * with the failed <code>Authentication</code> object that failed.
- *
- * @param authRequest the authentication request object
- *
- * @return a fully authenticated object including credentials
- *
- * @throws AuthenticationException if authentication fails
- */
- public final Authentication authenticate(Authentication authRequest) throws AuthenticationException {
- try {
- return doAuthentication(authRequest);
- } catch (AuthenticationException e) {
- e.setAuthentication(authRequest);
-
- if (clearExtraInformation) {
- e.clearExtraInformation();
- }
-
- throw e;
- }
- }
-
- /**
- * Concrete implementations of this class override this method to provide the authentication service.
- * <p>
- * The contract for this method is documented in the
- * {@link AuthenticationManager#authenticate(Authentication)}.
- *
- * @param authentication the authentication request object
- *
- * @return a fully authenticated object including credentials
- *
- * @throws AuthenticationException if authentication fails
- */
- protected abstract Authentication doAuthentication(Authentication authentication) throws AuthenticationException;
-
- /**
- * If set to true, the <tt>extraInformation</tt> set on an <tt>AuthenticationException</tt> will be cleared
- * before rethrowing it. This is useful for use with remoting protocols where the information shouldn't
- * be serialized to the client. Defaults to 'false'.
- *
- * @see org.springframework.security.core.AuthenticationException#getExtraInformation()
- */
- public void setClearExtraInformation(boolean clearExtraInformation) {
- this.clearExtraInformation = clearExtraInformation;
- }
-}
diff --git a/dist/spring-security-core/org/springframework/security/authentication/AccountExpiredException.java b/dist/spring-security-core/org/springframework/security/authentication/AccountExpiredException.java
index 2ff1745..8123b50 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/AccountExpiredException.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/AccountExpiredException.java
@@ -45,6 +45,7 @@ public class AccountExpiredException extends AccountStatusException {
super(msg, t);
}
+ @Deprecated
public AccountExpiredException(String msg, Object extraInformation) {
super(msg, extraInformation);
}
diff --git a/dist/spring-security-core/org/springframework/security/authentication/AccountStatusException.java b/dist/spring-security-core/org/springframework/security/authentication/AccountStatusException.java
index bf3e1d9..57c64b4 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/AccountStatusException.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/AccountStatusException.java
@@ -17,6 +17,7 @@ public abstract class AccountStatusException extends AuthenticationException {
super(msg, t);
}
+ @Deprecated
protected AccountStatusException(String msg, Object extraInformation) {
super(msg, extraInformation);
}
diff --git a/dist/spring-security-core/org/springframework/security/authentication/AccountStatusUserDetailsChecker.java b/dist/spring-security-core/org/springframework/security/authentication/AccountStatusUserDetailsChecker.java
index 6801edc..096751f 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/AccountStatusUserDetailsChecker.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/AccountStatusUserDetailsChecker.java
@@ -10,24 +10,24 @@ import org.springframework.context.support.MessageSourceAccessor;
*/
public class AccountStatusUserDetailsChecker implements UserDetailsChecker {
- protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
+ protected final MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
public void check(UserDetails user) {
if (!user.isAccountNonLocked()) {
- throw new LockedException(messages.getMessage("UserDetailsService.locked", "User account is locked"), user);
+ throw new LockedException(messages.getMessage("AccountStatusUserDetailsChecker.locked", "User account is locked"), user);
}
if (!user.isEnabled()) {
- throw new DisabledException(messages.getMessage("UserDetailsService.disabled", "User is disabled"), user);
+ throw new DisabledException(messages.getMessage("AccountStatusUserDetailsChecker.disabled", "User is disabled"), user);
}
if (!user.isAccountNonExpired()) {
- throw new AccountExpiredException(messages.getMessage("UserDetailsService.expired",
+ throw new AccountExpiredException(messages.getMessage("AccountStatusUserDetailsChecker.expired",
"User account has expired"), user);
}
if (!user.isCredentialsNonExpired()) {
- throw new CredentialsExpiredException(messages.getMessage("UserDetailsService.credentialsExpired",
+ throw new CredentialsExpiredException(messages.getMessage("AccountStatusUserDetailsChecker.credentialsExpired",
"User credentials have expired"), user);
}
}
diff --git a/dist/spring-security-core/org/springframework/security/authentication/AnonymousAuthenticationProvider.java b/dist/spring-security-core/org/springframework/security/authentication/AnonymousAuthenticationProvider.java
index f385bb2..b9bfde8 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/AnonymousAuthenticationProvider.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/AnonymousAuthenticationProvider.java
@@ -40,11 +40,22 @@ public class AnonymousAuthenticationProvider implements AuthenticationProvider,
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
private String key;
+ /**
+ *
+ * @deprecated Use constructor injection
+ */
+ @Deprecated
+ public AnonymousAuthenticationProvider() {
+ }
+
+ public AnonymousAuthenticationProvider(String key) {
+ this.key = key;
+ }
+
//~ Methods ========================================================================================================
public void afterPropertiesSet() throws Exception {
Assert.hasLength(key, "A Key is required");
- Assert.notNull(this.messages, "A message source must be set");
}
public Authentication authenticate(Authentication authentication)
@@ -65,15 +76,21 @@ public class AnonymousAuthenticationProvider implements AuthenticationProvider,
return key;
}
+ /**
+ *
+ * @deprecated Use constructor injection
+ */
+ @Deprecated
public void setKey(String key) {
this.key = key;
}
public void setMessageSource(MessageSource messageSource) {
+ Assert.notNull(messageSource, "messageSource cannot be null");
this.messages = new MessageSourceAccessor(messageSource);
}
- public boolean supports(Class<? extends Object> authentication) {
+ public boolean supports(Class<?> authentication) {
return (AnonymousAuthenticationToken.class.isAssignableFrom(authentication));
}
}
diff --git a/dist/spring-security-core/org/springframework/security/authentication/AnonymousAuthenticationToken.java b/dist/spring-security-core/org/springframework/security/authentication/AnonymousAuthenticationToken.java
index 6d42b33..9afc10c 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/AnonymousAuthenticationToken.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/AnonymousAuthenticationToken.java
@@ -15,13 +15,12 @@
package org.springframework.security.authentication;
-import org.springframework.security.core.GrantedAuthority;
-
-
import java.io.Serializable;
-import java.util.Arrays;
+import java.util.Collection;
import java.util.List;
+import org.springframework.security.core.GrantedAuthority;
+
/**
* Represents an anonymous <code>Authentication</code>.
@@ -38,13 +37,6 @@ public class AnonymousAuthenticationToken extends AbstractAuthenticationToken im
//~ Constructors ===================================================================================================
/**
- * @deprecated use the second constructor
- */
- public AnonymousAuthenticationToken(String key, Object principal, GrantedAuthority[] authorities) {
- this(key, principal, Arrays.asList(authorities));
- }
-
- /**
* Constructor.
*
* @param key to identify if this object made by an authorised client
@@ -53,7 +45,7 @@ public class AnonymousAuthenticationToken extends AbstractAuthenticationToken im
*
* @throws IllegalArgumentException if a <code>null</code> was passed
*/
- public AnonymousAuthenticationToken(String key, Object principal, List<GrantedAuthority> authorities) {
+ public AnonymousAuthenticationToken(String key, Object principal, Collection<? extends GrantedAuthority> authorities) {
super(authorities);
if ((key == null) || ("".equals(key)) || (principal == null) || "".equals(principal) || (authorities == null)
diff --git a/dist/spring-security-core/org/springframework/security/authentication/AuthenticationDetails.java b/dist/spring-security-core/org/springframework/security/authentication/AuthenticationDetails.java
index a910f8b..cb6a44f 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/AuthenticationDetails.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/AuthenticationDetails.java
@@ -1,5 +1,7 @@
package org.springframework.security.authentication;
+import org.springframework.security.core.SpringSecurityCoreVersion;
+
import java.io.Serializable;
/**
@@ -8,10 +10,14 @@ import java.io.Serializable;
* @author Ruud Senden
* @since 2.0
*/
+ at Deprecated
public class AuthenticationDetails implements Serializable {
+
+ private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
+
//~ Instance fields ================================================================================================
- private String context;
+ private final String context;
//~ Constructors ===================================================================================================
diff --git a/dist/spring-security-core/org/springframework/security/authentication/AuthenticationDetailsSource.java b/dist/spring-security-core/org/springframework/security/authentication/AuthenticationDetailsSource.java
index 0b01c41..b8865e0 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/AuthenticationDetailsSource.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/AuthenticationDetailsSource.java
@@ -21,7 +21,7 @@ package org.springframework.security.authentication;
*
* @author Ben Alex
*/
-public interface AuthenticationDetailsSource {
+public interface AuthenticationDetailsSource<C, T> {
//~ Methods ========================================================================================================
/**
@@ -31,5 +31,5 @@ public interface AuthenticationDetailsSource {
*
* @return a fully-configured authentication details instance
*/
- Object buildDetails(Object context);
+ T buildDetails(C context);
}
diff --git a/dist/spring-security-core/org/springframework/security/authentication/AuthenticationDetailsSourceImpl.java b/dist/spring-security-core/org/springframework/security/authentication/AuthenticationDetailsSourceImpl.java
index f444b10..0d774b6 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/AuthenticationDetailsSourceImpl.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/AuthenticationDetailsSourceImpl.java
@@ -1,11 +1,10 @@
package org.springframework.security.authentication;
-import java.lang.reflect.Constructor;
-
-import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
+import java.lang.reflect.Constructor;
+
/**
* Base implementation of {@link AuthenticationDetailsSource}.
* <p>
@@ -16,8 +15,10 @@ import org.springframework.util.ReflectionUtils;
*
* @author Ruud Senden
* @since 2.0
+ * @deprecated Write an implementation of AuthenticationDetailsSource which returns the desired type directly.
*/
-public class AuthenticationDetailsSourceImpl implements AuthenticationDetailsSource {
+ at Deprecated
+public class AuthenticationDetailsSourceImpl implements AuthenticationDetailsSource<Object, Object> {
//~ Instance fields ================================================================================================
private Class<?> clazz = AuthenticationDetails.class;
@@ -50,10 +51,10 @@ public class AuthenticationDetailsSourceImpl implements AuthenticationDetailsSou
private Constructor<?> getFirstMatchingConstructor(Object object) throws NoSuchMethodException {
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
Constructor<?> constructor = null;
- for (int i = 0; i < constructors.length; i++) {
- Class<?>[] parameterTypes = constructors[i].getParameterTypes();
+ for (Constructor<?> tryMe : constructors) {
+ Class<?>[] parameterTypes = tryMe.getParameterTypes();
if (parameterTypes.length == 1 && (object == null || parameterTypes[0].isInstance(object))) {
- constructor = constructors[i];
+ constructor = tryMe;
break;
}
}
diff --git a/dist/spring-security-core/org/springframework/security/authentication/AuthenticationProvider.java b/dist/spring-security-core/org/springframework/security/authentication/AuthenticationProvider.java
index 2186903..38c6a02 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/AuthenticationProvider.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/AuthenticationProvider.java
@@ -57,10 +57,10 @@ public interface AuthenticationProvider {
* <p>Selection of an <code>AuthenticationProvider</code> capable of performing authentication is
* conducted at runtime the <code>ProviderManager</code>.</p>
*
- * @param authentication DOCUMENT ME!
+ * @param authentication
*
* @return <code>true</code> if the implementation can more closely evaluate the <code>Authentication</code> class
* presented
*/
- boolean supports(Class<? extends Object> authentication);
+ boolean supports(Class<?> authentication);
}
diff --git a/dist/spring-security-core/org/springframework/security/authentication/AuthenticationServiceException.java b/dist/spring-security-core/org/springframework/security/authentication/AuthenticationServiceException.java
index b44f67a..6a6de15 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/AuthenticationServiceException.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/AuthenticationServiceException.java
@@ -18,15 +18,16 @@ package org.springframework.security.authentication;
import org.springframework.security.core.AuthenticationException;
/**
- * Thrown if an authentication request could not be processed due to a system problem.<p>This might be thrown if a
- * backend authentication repository is unavailable.</p>
+ * Thrown if an authentication request could not be processed due to a system problem.
+ * <p>
+ * This might be thrown if a backend authentication repository is unavailable, for example.
*
* @author Ben Alex
*/
public class AuthenticationServiceException extends AuthenticationException {
//~ Constructors ===================================================================================================
-/**
+ /**
* Constructs an <code>AuthenticationServiceException</code> with the
* specified message.
*
@@ -36,7 +37,7 @@ public class AuthenticationServiceException extends AuthenticationException {
super(msg);
}
-/**
+ /**
* Constructs an <code>AuthenticationServiceException</code> with the
* specified message and root cause.
*
diff --git a/dist/spring-security-core/org/springframework/security/authentication/BadCredentialsException.java b/dist/spring-security-core/org/springframework/security/authentication/BadCredentialsException.java
index 7733942..9543a90 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/BadCredentialsException.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/BadCredentialsException.java
@@ -36,6 +36,7 @@ public class BadCredentialsException extends AuthenticationException {
super(msg);
}
+ @Deprecated
public BadCredentialsException(String msg, Object extraInformation) {
super(msg, extraInformation);
}
diff --git a/dist/spring-security-core/org/springframework/security/authentication/CredentialsExpiredException.java b/dist/spring-security-core/org/springframework/security/authentication/CredentialsExpiredException.java
index 7972f50..cbd90fa 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/CredentialsExpiredException.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/CredentialsExpiredException.java
@@ -45,6 +45,7 @@ public class CredentialsExpiredException extends AccountStatusException {
super(msg, t);
}
+ @Deprecated
public CredentialsExpiredException(String msg, Object extraInformation) {
super(msg, extraInformation);
}
diff --git a/dist/spring-security-core/org/springframework/security/authentication/DefaultAuthenticationEventPublisher.java b/dist/spring-security-core/org/springframework/security/authentication/DefaultAuthenticationEventPublisher.java
index 5a7a718..c889978 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/DefaultAuthenticationEventPublisher.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/DefaultAuthenticationEventPublisher.java
@@ -2,13 +2,14 @@ package org.springframework.security.authentication;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
-import java.util.Properties;
+import java.util.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.security.authentication.event.AbstractAuthenticationEvent;
+import org.springframework.security.authentication.event.AbstractAuthenticationFailureEvent;
import org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent;
import org.springframework.security.authentication.event.AuthenticationFailureCredentialsExpiredEvent;
import org.springframework.security.authentication.event.AuthenticationFailureDisabledEvent;
@@ -44,7 +45,8 @@ public class DefaultAuthenticationEventPublisher implements AuthenticationEventP
private final Log logger = LogFactory.getLog(getClass());
private ApplicationEventPublisher applicationEventPublisher;
- private final Properties exceptionMappings;
+ private final HashMap<String,Constructor<? extends AbstractAuthenticationEvent>> exceptionMappings
+ = new HashMap<String,Constructor<? extends AbstractAuthenticationEvent>>();
public DefaultAuthenticationEventPublisher() {
this(null);
@@ -52,25 +54,17 @@ public class DefaultAuthenticationEventPublisher implements AuthenticationEventP
public DefaultAuthenticationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
- exceptionMappings = new Properties();
- exceptionMappings.put(AccountExpiredException.class.getName(),
- AuthenticationFailureExpiredEvent.class.getName());
- exceptionMappings.put(AuthenticationServiceException.class.getName(),
- AuthenticationFailureServiceExceptionEvent.class.getName());
- exceptionMappings.put(LockedException.class.getName(),
- AuthenticationFailureLockedEvent.class.getName());
- exceptionMappings.put(CredentialsExpiredException.class.getName(),
- AuthenticationFailureCredentialsExpiredEvent.class.getName());
- exceptionMappings.put(DisabledException.class.getName(),
- AuthenticationFailureDisabledEvent.class.getName());
- exceptionMappings.put(BadCredentialsException.class.getName(),
- AuthenticationFailureBadCredentialsEvent.class.getName());
- exceptionMappings.put(UsernameNotFoundException.class.getName(),
- AuthenticationFailureBadCredentialsEvent.class.getName());
- exceptionMappings.put(ProviderNotFoundException.class.getName(),
- AuthenticationFailureProviderNotFoundEvent.class.getName());
- exceptionMappings.put("org.springframework.security.authentication.cas.ProxyUntrustedException",
- AuthenticationFailureProxyUntrustedEvent.class.getName());
+
+ addMapping(BadCredentialsException.class.getName(), AuthenticationFailureBadCredentialsEvent.class);
+ addMapping(UsernameNotFoundException.class.getName(), AuthenticationFailureBadCredentialsEvent.class);
+ addMapping(AccountExpiredException.class.getName(), AuthenticationFailureExpiredEvent.class);
+ addMapping(ProviderNotFoundException.class.getName(), AuthenticationFailureProviderNotFoundEvent.class);
+ addMapping(DisabledException.class.getName(), AuthenticationFailureDisabledEvent.class);
+ addMapping(LockedException.class.getName(), AuthenticationFailureLockedEvent.class);
+ addMapping(AuthenticationServiceException.class.getName(), AuthenticationFailureServiceExceptionEvent.class);
+ addMapping(CredentialsExpiredException.class.getName(), AuthenticationFailureCredentialsExpiredEvent.class);
+ addMapping("org.springframework.security.authentication.cas.ProxyUntrustedException",
+ AuthenticationFailureProxyUntrustedEvent.class);
}
public void publishAuthenticationSuccess(Authentication authentication) {
@@ -79,23 +73,14 @@ public class DefaultAuthenticationEventPublisher implements AuthenticationEventP
}
}
- public void publishAuthenticationFailure(AuthenticationException exception,
- Authentication authentication) {
- String className = exceptionMappings.getProperty(exception.getClass().getName());
+ public void publishAuthenticationFailure(AuthenticationException exception, Authentication authentication) {
+ Constructor<? extends AbstractAuthenticationEvent> constructor = exceptionMappings.get(exception.getClass().getName());
AbstractAuthenticationEvent event = null;
- if (className != null) {
+ if (constructor != null) {
try {
- Class<?> clazz = getClass().getClassLoader().loadClass(className);
- Constructor<?> constructor = clazz.getConstructor(new Class[] {
- Authentication.class, AuthenticationException.class
- });
- Object obj = constructor.newInstance(authentication, exception);
- Assert.isInstanceOf(AbstractAuthenticationEvent.class, obj, "Must be an AbstractAuthenticationEvent");
- event = (AbstractAuthenticationEvent) obj;
- } catch (ClassNotFoundException ignored) {}
- catch (NoSuchMethodException ignored) {}
- catch (IllegalAccessException ignored) {}
+ event = constructor.newInstance(authentication, exception);
+ } catch (IllegalAccessException ignored) {}
catch (InstantiationException ignored) {}
catch (InvocationTargetException ignored) {}
}
@@ -122,8 +107,29 @@ public class DefaultAuthenticationEventPublisher implements AuthenticationEventP
* @param additionalExceptionMappings where keys are the fully-qualified string name of the exception class and the
* values are the fully-qualified string name of the event class to fire.
*/
+ @SuppressWarnings({"unchecked"})
public void setAdditionalExceptionMappings(Properties additionalExceptionMappings) {
Assert.notNull(additionalExceptionMappings, "The exceptionMappings object must not be null");
- exceptionMappings.putAll(additionalExceptionMappings);
+ for(Object exceptionClass : additionalExceptionMappings.keySet()) {
+ String eventClass = (String) additionalExceptionMappings.get(exceptionClass);
+ try {
+ Class<?> clazz = getClass().getClassLoader().loadClass(eventClass);
+ Assert.isAssignable(AbstractAuthenticationFailureEvent.class, clazz);
+ addMapping((String) exceptionClass, (Class<? extends AbstractAuthenticationFailureEvent>) clazz);
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException("Failed to load authentication event class " + eventClass);
+ }
+ }
+ }
+
+ private void addMapping(String exceptionClass,
+ Class<? extends AbstractAuthenticationFailureEvent> eventClass) {
+ try {
+ Constructor<? extends AbstractAuthenticationEvent> constructor =
+ eventClass.getConstructor(Authentication.class, AuthenticationException.class);
+ exceptionMappings.put(exceptionClass, constructor);
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException("Authentication event class " + eventClass.getName() + " has no suitable constructor");
+ }
}
}
diff --git a/dist/spring-security-core/org/springframework/security/authentication/DisabledException.java b/dist/spring-security-core/org/springframework/security/authentication/DisabledException.java
index 05648e2..2f423ad 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/DisabledException.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/DisabledException.java
@@ -44,6 +44,7 @@ public class DisabledException extends AccountStatusException {
super(msg, t);
}
+ @Deprecated
public DisabledException(String msg, Object extraInformation) {
super(msg, extraInformation);
}
diff --git a/dist/spring-security-core/org/springframework/security/authentication/InsufficientAuthenticationException.java b/dist/spring-security-core/org/springframework/security/authentication/InsufficientAuthenticationException.java
index 1e794ed..8fea876 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/InsufficientAuthenticationException.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/InsufficientAuthenticationException.java
@@ -23,9 +23,8 @@ import org.springframework.security.core.AuthenticationException;
* <p>
* {@link org.springframework.security.access.AccessDecisionVoter}s will typically throw this exception if
* they are dissatisfied with the level of the authentication, such as if performed using a remember-me mechanism or
- * anonymously. The commonly used {@link org.springframework.security.web.access.ExceptionTranslationFilter
- * ExceptionTranslationFilter} will thus cause the <code>AuthenticationEntryPoint</code> to be called, allowing
- * the principal to authenticate with a stronger level of authentication.
+ * anonymously. The {@code ExceptionTranslationFilter} will then typically cause the {@code AuthenticationEntryPoint}
+ * to be called, allowing the principal to authenticate with a stronger level of authentication.
*
* @author Ben Alex
*/
diff --git a/dist/spring-security-core/org/springframework/security/authentication/LockedException.java b/dist/spring-security-core/org/springframework/security/authentication/LockedException.java
index cc8e582..9db269e 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/LockedException.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/LockedException.java
@@ -45,6 +45,7 @@ public class LockedException extends AccountStatusException {
super(msg, t);
}
+ @Deprecated
public LockedException(String msg, Object extraInformation) {
super(msg, extraInformation);
}
diff --git a/dist/spring-security-core/org/springframework/security/authentication/ProviderManager.java b/dist/spring-security-core/org/springframework/security/authentication/ProviderManager.java
index e969c2c..6a2732c 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/ProviderManager.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/ProviderManager.java
@@ -74,7 +74,7 @@ import org.springframework.util.Assert;
*
* @see DefaultAuthenticationEventPublisher
*/
-public class ProviderManager extends AbstractAuthenticationManager implements MessageSourceAware, InitializingBean {
+public class ProviderManager implements AuthenticationManager, MessageSourceAware, InitializingBean {
//~ Static fields/initializers =====================================================================================
private static final Log logger = LogFactory.getLog(ProviderManager.class);
@@ -85,11 +85,34 @@ public class ProviderManager extends AbstractAuthenticationManager implements Me
private List<AuthenticationProvider> providers = Collections.emptyList();
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
private AuthenticationManager parent;
- private boolean eraseCredentialsAfterAuthentication = false;
+ private boolean eraseCredentialsAfterAuthentication = true;
+ private boolean clearExtraInformation = false;
+
+ /**
+ * @deprecated Use constructor which takes provider list
+ */
+ @Deprecated
+ public ProviderManager() {
+ }
+
+ public ProviderManager(List<AuthenticationProvider> providers) {
+ this(providers, null);
+ }
+
+ public ProviderManager(List<AuthenticationProvider> providers, AuthenticationManager parent) {
+ Assert.notNull(providers, "providers list cannot be null");
+ this.providers = providers;
+ this.parent = parent;
+ checkState();
+ }
//~ Methods ========================================================================================================
public void afterPropertiesSet() throws Exception {
+ checkState();
+ }
+
+ private void checkState() {
if (parent == null && providers.isEmpty()) {
throw new IllegalArgumentException("A parent AuthenticationManager or a list " +
"of AuthenticationProviders is required");
@@ -114,17 +137,20 @@ public class ProviderManager extends AbstractAuthenticationManager implements Me
*
* @throws AuthenticationException if authentication fails.
*/
- public Authentication doAuthentication(Authentication authentication) throws AuthenticationException {
+ public Authentication authenticate(Authentication authentication) throws AuthenticationException {
Class<? extends Authentication> toTest = authentication.getClass();
AuthenticationException lastException = null;
Authentication result = null;
+ boolean debug = logger.isDebugEnabled();
for (AuthenticationProvider provider : getProviders()) {
if (!provider.supports(toTest)) {
continue;
}
- logger.debug("Authentication attempt using " + provider.getClass().getName());
+ if (debug) {
+ logger.debug("Authentication attempt using " + provider.getClass().getName());
+ }
try {
result = provider.authenticate(authentication);
@@ -134,8 +160,8 @@ public class ProviderManager extends AbstractAuthenticationManager implements Me
break;
}
} catch (AccountStatusException e) {
+ prepareException(e, authentication);
// SEC-546: Avoid polling additional providers if auth failure is due to invalid account status
- eventPublisher.publishAuthenticationFailure(e, authentication);
throw e;
} catch (AuthenticationException e) {
lastException = e;
@@ -172,10 +198,20 @@ public class ProviderManager extends AbstractAuthenticationManager implements Me
}
eventPublisher.publishAuthenticationFailure(lastException, authentication);
+ prepareException(lastException, authentication);
throw lastException;
}
+ @SuppressWarnings("deprecation")
+ private void prepareException(AuthenticationException ex, Authentication auth) {
+ ex.setAuthentication(auth);
+
+ if (clearExtraInformation) {
+ ex.clearExtraInformation();
+ }
+ }
+
/**
* Copies the authentication details from a source Authentication object to a destination one, provided the
* latter does not already have one set.
@@ -199,6 +235,10 @@ public class ProviderManager extends AbstractAuthenticationManager implements Me
this.messages = new MessageSourceAccessor(messageSource);
}
+ /**
+ * @deprecated Use constructor injection
+ */
+ @Deprecated
public void setParent(AuthenticationManager parent) {
this.parent = parent;
}
@@ -231,8 +271,10 @@ public class ProviderManager extends AbstractAuthenticationManager implements Me
*
* @throws IllegalArgumentException if the list is empty or null, or any of the elements in the list is not an
* AuthenticationProvider instance.
+ * @deprecated Use constructor injection
*/
- @SuppressWarnings("unchecked")
+ @Deprecated
+ @SuppressWarnings({ "unchecked", "rawtypes" })
public void setProviders(List providers) {
Assert.notNull(providers, "Providers list cannot be null");
for(Object currentObject : providers) {
@@ -242,6 +284,19 @@ public class ProviderManager extends AbstractAuthenticationManager implements Me
this.providers = providers;
}
+ /**
+ * If set to true, the {@code extraInformation} set on an {@code AuthenticationException} will be cleared
+ * before rethrowing it. This is useful for use with remoting protocols where the information shouldn't
+ * be serialized to the client. Defaults to 'false'.
+ *
+ * @see org.springframework.security.core.AuthenticationException#getExtraInformation()
+ * @deprecated the {@code extraInformation} property is deprecated
+ */
+ @Deprecated
+ public void setClearExtraInformation(boolean clearExtraInformation) {
+ this.clearExtraInformation = clearExtraInformation;
+ }
+
private static final class NullEventPublisher implements AuthenticationEventPublisher {
public void publishAuthenticationFailure(AuthenticationException exception, Authentication authentication) {}
public void publishAuthenticationSuccess(Authentication authentication) {}
diff --git a/dist/spring-security-core/org/springframework/security/authentication/ProviderNotFoundException.java b/dist/spring-security-core/org/springframework/security/authentication/ProviderNotFoundException.java
index 305fffa..a1f7916 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/ProviderNotFoundException.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/ProviderNotFoundException.java
@@ -37,15 +37,4 @@ public class ProviderNotFoundException extends AuthenticationException {
public ProviderNotFoundException(String msg) {
super(msg);
}
-
- /**
- * Constructs a <code>ProviderNotFoundException</code> with the specified
- * message and root cause.
- *
- * @param msg the detail message
- * @param t root cause
- */
- public ProviderNotFoundException(String msg, Throwable t) {
- super(msg, t);
- }
}
diff --git a/dist/spring-security-core/org/springframework/security/authentication/RememberMeAuthenticationProvider.java b/dist/spring-security-core/org/springframework/security/authentication/RememberMeAuthenticationProvider.java
index e4cf311..e412ba4 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/RememberMeAuthenticationProvider.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/RememberMeAuthenticationProvider.java
@@ -37,6 +37,17 @@ public class RememberMeAuthenticationProvider implements AuthenticationProvider,
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
private String key;
+ /**
+ * @deprecated Use constructor injection
+ */
+ @Deprecated
+ public RememberMeAuthenticationProvider() {
+ }
+
+ public RememberMeAuthenticationProvider(String key) {
+ this.key = key;
+ }
+
//~ Methods ========================================================================================================
public void afterPropertiesSet() throws Exception {
@@ -61,6 +72,11 @@ public class RememberMeAuthenticationProvider implements AuthenticationProvider,
return key;
}
+ /**
+ *
+ * @deprecated Use constructor injection
+ */
+ @Deprecated
public void setKey(String key) {
this.key = key;
}
@@ -69,7 +85,7 @@ public class RememberMeAuthenticationProvider implements AuthenticationProvider,
this.messages = new MessageSourceAccessor(messageSource);
}
- public boolean supports(Class<? extends Object> authentication) {
+ public boolean supports(Class<?> authentication) {
return (RememberMeAuthenticationToken.class.isAssignableFrom(authentication));
}
}
diff --git a/dist/spring-security-core/org/springframework/security/authentication/RememberMeAuthenticationToken.java b/dist/spring-security-core/org/springframework/security/authentication/RememberMeAuthenticationToken.java
index a720829..2315f0f 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/RememberMeAuthenticationToken.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/RememberMeAuthenticationToken.java
@@ -18,6 +18,7 @@ package org.springframework.security.authentication;
import java.util.Collection;
import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.SpringSecurityCoreVersion;
/**
@@ -30,6 +31,9 @@ import org.springframework.security.core.GrantedAuthority;
* @author Luke Taylor
*/
public class RememberMeAuthenticationToken extends AbstractAuthenticationToken {
+
+ private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
+
//~ Instance fields ================================================================================================
private final Object principal;
diff --git a/dist/spring-security-core/org/springframework/security/authentication/TestingAuthenticationProvider.java b/dist/spring-security-core/org/springframework/security/authentication/TestingAuthenticationProvider.java
index 3db3400..f19f8d8 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/TestingAuthenticationProvider.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/TestingAuthenticationProvider.java
@@ -36,7 +36,7 @@ public class TestingAuthenticationProvider implements AuthenticationProvider {
return authentication;
}
- public boolean supports(Class<? extends Object> authentication) {
+ public boolean supports(Class<?> authentication) {
return TestingAuthenticationToken.class.isAssignableFrom(authentication);
}
}
diff --git a/dist/spring-security-core/org/springframework/security/authentication/TestingAuthenticationToken.java b/dist/spring-security-core/org/springframework/security/authentication/TestingAuthenticationToken.java
index ba50e6d..fe2f0b4 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/TestingAuthenticationToken.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/TestingAuthenticationToken.java
@@ -33,8 +33,8 @@ public class TestingAuthenticationToken extends AbstractAuthenticationToken {
//~ Instance fields ================================================================================================
private static final long serialVersionUID = 1L;
- private Object credentials;
- private Object principal;
+ private final Object credentials;
+ private final Object principal;
//~ Constructors ===================================================================================================
@@ -49,10 +49,6 @@ public class TestingAuthenticationToken extends AbstractAuthenticationToken {
setAuthenticated(true);
}
- public TestingAuthenticationToken(Object principal, Object credentials, GrantedAuthority[] authorities) {
- this(principal, credentials, Arrays.asList(authorities));
- }
-
public TestingAuthenticationToken(Object principal, Object credentials, List<GrantedAuthority> authorities) {
super(authorities);
this.principal = principal;
diff --git a/dist/spring-security-core/org/springframework/security/authentication/UsernamePasswordAuthenticationToken.java b/dist/spring-security-core/org/springframework/security/authentication/UsernamePasswordAuthenticationToken.java
index 75fa959..2e4181f 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/UsernamePasswordAuthenticationToken.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/UsernamePasswordAuthenticationToken.java
@@ -15,10 +15,10 @@
package org.springframework.security.authentication;
-import java.util.Arrays;
import java.util.Collection;
import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.SpringSecurityCoreVersion;
/**
@@ -32,6 +32,9 @@ import org.springframework.security.core.GrantedAuthority;
* @author Ben Alex
*/
public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationToken {
+
+ private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
+
//~ Instance fields ================================================================================================
private final Object principal;
@@ -53,13 +56,6 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT
}
/**
- * @deprecated use the list of authorities version
- */
- public UsernamePasswordAuthenticationToken(Object principal, Object credentials, GrantedAuthority[] authorities) {
- this(principal, credentials, Arrays.asList(authorities));
- }
-
- /**
* This constructor should only be used by <code>AuthenticationManager</code> or <code>AuthenticationProvider</code>
* implementations that are satisfied with producing a trusted (i.e. {@link #isAuthenticated()} = <code>true</code>)
* authentication token.
diff --git a/dist/spring-security-core/org/springframework/security/authentication/dao/AbstractUserDetailsAuthenticationProvider.java b/dist/spring-security-core/org/springframework/security/authentication/dao/AbstractUserDetailsAuthenticationProvider.java
index ce1e84f..62dbda6 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/dao/AbstractUserDetailsAuthenticationProvider.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/dao/AbstractUserDetailsAuthenticationProvider.java
@@ -28,6 +28,8 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticatio
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.SpringSecurityMessageSource;
+import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
+import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper;
import org.springframework.security.core.userdetails.UserCache;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsChecker;
@@ -84,6 +86,7 @@ public abstract class AbstractUserDetailsAuthenticationProvider implements Authe
protected boolean hideUserNotFoundExceptions = true;
private UserDetailsChecker preAuthenticationChecks = new DefaultPreAuthenticationChecks();
private UserDetailsChecker postAuthenticationChecks = new DefaultPostAuthenticationChecks();
+ private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper();
//~ Methods ========================================================================================================
@@ -191,7 +194,7 @@ public abstract class AbstractUserDetailsAuthenticationProvider implements Authe
// 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());
+ authentication.getCredentials(), authoritiesMapper.mapAuthorities(user.getAuthorities()));
result.setDetails(authentication.getDetails());
return result;
@@ -269,7 +272,7 @@ public abstract class AbstractUserDetailsAuthenticationProvider implements Authe
this.userCache = userCache;
}
- public boolean supports(Class<? extends Object> authentication) {
+ public boolean supports(Class<?> authentication) {
return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
}
@@ -295,6 +298,10 @@ public abstract class AbstractUserDetailsAuthenticationProvider implements Authe
this.postAuthenticationChecks = postAuthenticationChecks;
}
+ public void setAuthoritiesMapper(GrantedAuthoritiesMapper authoritiesMapper) {
+ this.authoritiesMapper = authoritiesMapper;
+ }
+
private class DefaultPreAuthenticationChecks implements UserDetailsChecker {
public void check(UserDetails user) {
if (!user.isAccountNonLocked()) {
diff --git a/dist/spring-security-core/org/springframework/security/authentication/dao/DaoAuthenticationProvider.java b/dist/spring-security-core/org/springframework/security/authentication/dao/DaoAuthenticationProvider.java
index a0fe5ee..aa918a5 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/dao/DaoAuthenticationProvider.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/dao/DaoAuthenticationProvider.java
@@ -24,12 +24,11 @@ import org.springframework.security.authentication.encoding.PlaintextPasswordEnc
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
-import org.springframework.dao.DataAccessException;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.util.Assert;
/**
- * An {@link AuthenticationProvider} implementation that retrieves user details
- * from an {@link UserDetailsService}.
+ * An {@link AuthenticationProvider} implementation that retrieves user details from a {@link UserDetailsService}.
*
* @author Ben Alex
*/
@@ -43,8 +42,6 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
private UserDetailsService userDetailsService;
- private boolean includeDetailsObject = true;
-
//~ Methods ========================================================================================================
protected void additionalAuthenticationChecks(UserDetails userDetails,
@@ -59,8 +56,7 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
logger.debug("Authentication failed: no credentials provided");
throw new BadCredentialsException(messages.getMessage(
- "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"),
- includeDetailsObject ? userDetails : null);
+ "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"), userDetails);
}
String presentedPassword = authentication.getCredentials().toString();
@@ -69,8 +65,7 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
logger.debug("Authentication failed: password does not match stored value");
throw new BadCredentialsException(messages.getMessage(
- "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"),
- includeDetailsObject ? userDetails : null);
+ "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"), userDetails);
}
}
@@ -84,8 +79,9 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
try {
loadedUser = this.getUserDetailsService().loadUserByUsername(username);
- }
- catch (DataAccessException repositoryProblem) {
+ } catch (UsernameNotFoundException notFound) {
+ throw notFound;
+ } catch (Exception repositoryProblem) {
throw new AuthenticationServiceException(repositoryProblem.getMessage(), repositoryProblem);
}
@@ -98,12 +94,45 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
/**
* Sets the PasswordEncoder instance to be used to encode and validate passwords.
- * If not set, {@link PlaintextPasswordEncoder} will be used by default.
+ * If not set, the password will be compared as plain text.
+ * <p>
+ * For systems which are already using salted password which are encoded with a previous release, the encoder
+ * should be of type {@code org.springframework.security.authentication.encoding.PasswordEncoder}. Otherwise,
+ * the recommended approach is to use {@code org.springframework.security.crypto.password.PasswordEncoder}.
*
- * @param passwordEncoder The passwordEncoder to use
+ * @param passwordEncoder must be an instance of one of the {@code PasswordEncoder} types.
*/
- public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
- this.passwordEncoder = passwordEncoder;
+ public void setPasswordEncoder(Object passwordEncoder) {
+ Assert.notNull(passwordEncoder, "passwordEncoder cannot be null");
+
+ if (passwordEncoder instanceof PasswordEncoder) {
+ this.passwordEncoder = (PasswordEncoder) passwordEncoder;
+ return;
+ }
+
+ if (passwordEncoder instanceof org.springframework.security.crypto.password.PasswordEncoder) {
+ final org.springframework.security.crypto.password.PasswordEncoder delegate =
+ (org.springframework.security.crypto.password.PasswordEncoder)passwordEncoder;
+ this.passwordEncoder = new PasswordEncoder() {
+ public String encodePassword(String rawPass, Object salt) {
+ checkSalt(salt);
+ return delegate.encode(rawPass);
+ }
+
+ public boolean isPasswordValid(String encPass, String rawPass, Object salt) {
+ checkSalt(salt);
+ return delegate.matches(rawPass, encPass);
+ }
+
+ private void checkSalt(Object salt) {
+ Assert.isNull(salt, "Salt value must be null when used with crypto module PasswordEncoder");
+ }
+ };
+
+ return;
+ }
+
+ throw new IllegalArgumentException("passwordEncoder must be a PasswordEncoder instance");
}
protected PasswordEncoder getPasswordEncoder() {
@@ -114,6 +143,10 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
* 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>.
+ * <p>
+ * Instead, it is recommended that you use an encoder which uses a random salt and combines it with
+ * the password field. This is the default approach taken in the
+ * {@code org.springframework.security.crypto.password} package.
*
* @param saltSource to use when attempting to decode passwords via the <code>PasswordEncoder</code>
*/
@@ -132,20 +165,4 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
protected UserDetailsService getUserDetailsService() {
return userDetailsService;
}
-
- protected boolean isIncludeDetailsObject() {
- return includeDetailsObject;
- }
-
- /**
- * Determines whether the UserDetails will be included in the <tt>extraInformation</tt> field of a
- * thrown BadCredentialsException. Defaults to true, but can be set to false if the exception will be
- * used with a remoting protocol, for example.
- *
- * @deprecated use {@link org.springframework.security.authentication.ProviderManager#setClearExtraInformation(boolean)}
- */
- public void setIncludeDetailsObject(boolean includeDetailsObject) {
- this.includeDetailsObject = includeDetailsObject;
- }
-
}
diff --git a/dist/spring-security-core/org/springframework/security/authentication/dao/ReflectionSaltSource.java b/dist/spring-security-core/org/springframework/security/authentication/dao/ReflectionSaltSource.java
index 679dc71..c27169e 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/dao/ReflectionSaltSource.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/dao/ReflectionSaltSource.java
@@ -66,7 +66,7 @@ public class ReflectionSaltSource implements SaltSource, InitializingBean {
Method saltMethod = findSaltMethod(user);
try {
- return saltMethod.invoke(user, new Object[] {});
+ return saltMethod.invoke(user);
} catch (Exception exception) {
throw new AuthenticationServiceException(exception.getMessage(), exception);
}
diff --git a/dist/spring-security-core/org/springframework/security/authentication/encoding/LdapShaPasswordEncoder.java b/dist/spring-security-core/org/springframework/security/authentication/encoding/LdapShaPasswordEncoder.java
index fbe5eed..30a79bc 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/encoding/LdapShaPasswordEncoder.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/encoding/LdapShaPasswordEncoder.java
@@ -19,7 +19,8 @@ package org.springframework.security.authentication.encoding;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
-import org.springframework.security.core.codec.Base64;
+import org.springframework.security.crypto.codec.Base64;
+import org.springframework.security.crypto.codec.Utf8;
import org.springframework.util.Assert;
@@ -79,11 +80,9 @@ public class LdapShaPasswordEncoder implements PasswordEncoder {
try {
sha = MessageDigest.getInstance("SHA");
- sha.update(rawPass.getBytes("UTF-8"));
+ sha.update(Utf8.encode(rawPass));
} catch (java.security.NoSuchAlgorithmException e) {
throw new IllegalStateException("No SHA implementation available!");
- } catch (UnsupportedEncodingException ue) {
- throw new IllegalStateException("UTF-8 not supported!");
}
if (salt != null) {
@@ -101,7 +100,7 @@ public class LdapShaPasswordEncoder implements PasswordEncoder {
prefix = forceLowerCasePrefix ? SSHA_PREFIX_LC : SSHA_PREFIX;
}
- return prefix + new String(Base64.encode(hash));
+ return prefix + Utf8.decode(Base64.encode(hash));
}
private byte[] extractSalt(String encPass) {
@@ -145,7 +144,7 @@ public class LdapShaPasswordEncoder implements PasswordEncoder {
String encodedRawPass = encodePassword(rawPass, salt).substring(startOfHash);
- return encodedRawPass.equals(encPass.substring(startOfHash));
+ return PasswordEncoderUtils.equals(encodedRawPass,encPass.substring(startOfHash));
}
/**
diff --git a/dist/spring-security-core/org/springframework/security/authentication/encoding/Md4.java b/dist/spring-security-core/org/springframework/security/authentication/encoding/Md4.java
index bab8c0c..6690390 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/encoding/Md4.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/encoding/Md4.java
@@ -25,8 +25,8 @@ class Md4 {
private final byte[] buffer = new byte[BLOCK_SIZE];
private int bufferOffset;
private long byteCount;
- private int[] state = new int[4];
- private int[] tmp = new int[16];
+ private final int[] state = new int[4];
+ private final int[] tmp = new int[16];
Md4() {
reset();
diff --git a/dist/spring-security-core/org/springframework/security/authentication/encoding/Md4PasswordEncoder.java b/dist/spring-security-core/org/springframework/security/authentication/encoding/Md4PasswordEncoder.java
index c9422c5..66c696b 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/encoding/Md4PasswordEncoder.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/encoding/Md4PasswordEncoder.java
@@ -16,8 +16,9 @@ package org.springframework.security.authentication.encoding;
import java.io.UnsupportedEncodingException;
-import org.springframework.security.core.codec.Base64;
-import org.springframework.security.core.codec.Hex;
+import org.springframework.security.crypto.codec.Base64;
+import org.springframework.security.crypto.codec.Hex;
+import org.springframework.security.crypto.codec.Utf8;
/**
* MD4 implementation of PasswordEncoder.
@@ -46,13 +47,7 @@ public class Md4PasswordEncoder extends BaseDigestPasswordEncoder {
public String encodePassword(String rawPass, Object salt) {
String saltedPass = mergePasswordAndSalt(rawPass, salt, false);
- byte[] passBytes;
-
- try {
- passBytes = saltedPass.getBytes("UTF-8");
- } catch (UnsupportedEncodingException e) {
- throw new IllegalStateException("UTF-8 not supported!");
- }
+ byte[] passBytes = Utf8.encode(saltedPass);
Md4 md4 = new Md4();
md4.update(passBytes, 0, passBytes.length);
@@ -60,7 +55,7 @@ public class Md4PasswordEncoder extends BaseDigestPasswordEncoder {
byte[] resBuf = md4.digest();
if (getEncodeHashAsBase64()) {
- return new String(Base64.encode(resBuf));
+ return Utf8.decode(Base64.encode(resBuf));
} else {
return new String(Hex.encode(resBuf));
}
@@ -78,7 +73,7 @@ public class Md4PasswordEncoder extends BaseDigestPasswordEncoder {
public boolean isPasswordValid(String encPass, String rawPass, Object salt) {
String pass1 = "" + encPass;
String pass2 = encodePassword(rawPass, salt);
- return pass1.equals(pass2);
+ return PasswordEncoderUtils.equals(pass1,pass2);
}
public String getAlgorithm() {
diff --git a/dist/spring-security-core/org/springframework/security/authentication/encoding/MessageDigestPasswordEncoder.java b/dist/spring-security-core/org/springframework/security/authentication/encoding/MessageDigestPasswordEncoder.java
index cda9494..d8f5973 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/encoding/MessageDigestPasswordEncoder.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/encoding/MessageDigestPasswordEncoder.java
@@ -4,8 +4,9 @@ import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
-import org.springframework.security.core.codec.Base64;
-import org.springframework.security.core.codec.Hex;
+import org.springframework.security.crypto.codec.Base64;
+import org.springframework.security.crypto.codec.Hex;
+import org.springframework.security.crypto.codec.Utf8;
import org.springframework.util.Assert;
/**
@@ -78,13 +79,7 @@ public class MessageDigestPasswordEncoder extends BaseDigestPasswordEncoder {
MessageDigest messageDigest = getMessageDigest();
- byte[] digest;
-
- try {
- digest = messageDigest.digest(saltedPass.getBytes("UTF-8"));
- } catch (UnsupportedEncodingException e) {
- throw new IllegalStateException("UTF-8 not supported!");
- }
+ byte[] digest = messageDigest.digest(Utf8.encode(saltedPass));
// "stretch" the encoded value if configured to do so
for (int i = 1; i < iterations; i++) {
@@ -92,7 +87,7 @@ public class MessageDigestPasswordEncoder extends BaseDigestPasswordEncoder {
}
if (getEncodeHashAsBase64()) {
- return new String(Base64.encode(digest));
+ return Utf8.decode(Base64.encode(digest));
} else {
return new String(Hex.encode(digest));
}
@@ -126,7 +121,7 @@ public class MessageDigestPasswordEncoder extends BaseDigestPasswordEncoder {
String pass1 = "" + encPass;
String pass2 = encodePassword(rawPass, salt);
- return pass1.equals(pass2);
+ return PasswordEncoderUtils.equals(pass1,pass2);
}
public String getAlgorithm() {
diff --git a/dist/spring-security-core/org/springframework/security/authentication/encoding/PasswordEncoder.java b/dist/spring-security-core/org/springframework/security/authentication/encoding/PasswordEncoder.java
index 54f1069..9f51da8 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/encoding/PasswordEncoder.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/encoding/PasswordEncoder.java
@@ -15,13 +15,9 @@
package org.springframework.security.authentication.encoding;
-import org.springframework.dao.DataAccessException;
-
/**
- * <p>
* Interface for performing authentication operations on a password.
- * </p>
*
* @author colin sampaleanu
*/
@@ -48,11 +44,8 @@ public interface PasswordEncoder {
* <code>null</code> value is legal.
*
* @return encoded password
- *
- * @throws DataAccessException DOCUMENT ME!
*/
- String encodePassword(String rawPass, Object salt)
- throws DataAccessException;
+ String encodePassword(String rawPass, Object salt);
/**
* <p>Validates a specified "raw" password against an encoded password.</p>
@@ -67,9 +60,6 @@ public interface PasswordEncoder {
* <code>null</code> value is legal.
*
* @return true if the password is valid , false otherwise
- *
- * @throws DataAccessException DOCUMENT ME!
*/
- boolean isPasswordValid(String encPass, String rawPass, Object salt)
- throws DataAccessException;
+ boolean isPasswordValid(String encPass, String rawPass, Object salt);
}
diff --git a/dist/spring-security-core/org/springframework/security/authentication/encoding/PlaintextPasswordEncoder.java b/dist/spring-security-core/org/springframework/security/authentication/encoding/PlaintextPasswordEncoder.java
index f414182..14a996c 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/encoding/PlaintextPasswordEncoder.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/encoding/PlaintextPasswordEncoder.java
@@ -15,6 +15,8 @@
package org.springframework.security.authentication.encoding;
+import java.util.Locale;
+
/**
* <p>Plaintext implementation of PasswordEncoder.</p>
* <P>As callers may wish to extract the password and salts separately from the encoded password, the salt must
@@ -46,11 +48,12 @@ public class PlaintextPasswordEncoder extends BasePasswordEncoder {
// authentication will fail as the encodePassword never allows them)
String pass2 = mergePasswordAndSalt(rawPass, salt, false);
- if (!ignorePasswordCase) {
- return pass1.equals(pass2);
- } else {
- return pass1.equalsIgnoreCase(pass2);
+ if (ignorePasswordCase) {
+ // Note: per String javadoc to get correct results for Locale insensitive, use English
+ pass1 = pass1.toLowerCase(Locale.ENGLISH);
+ pass2 = pass2.toLowerCase(Locale.ENGLISH);
}
+ return PasswordEncoderUtils.equals(pass1,pass2);
}
/**
diff --git a/dist/spring-security-core/org/springframework/security/authentication/event/AbstractAuthenticationFailureEvent.java b/dist/spring-security-core/org/springframework/security/authentication/event/AbstractAuthenticationFailureEvent.java
index 3b5025c..0a3f652 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/event/AbstractAuthenticationFailureEvent.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/event/AbstractAuthenticationFailureEvent.java
@@ -29,7 +29,7 @@ import org.springframework.util.Assert;
public abstract class AbstractAuthenticationFailureEvent extends AbstractAuthenticationEvent {
//~ Instance fields ================================================================================================
- private AuthenticationException exception;
+ private final AuthenticationException exception;
//~ Constructors ===================================================================================================
diff --git a/dist/spring-security-core/org/springframework/security/authentication/event/InteractiveAuthenticationSuccessEvent.java b/dist/spring-security-core/org/springframework/security/authentication/event/InteractiveAuthenticationSuccessEvent.java
index db7f76b..8b76a71 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/event/InteractiveAuthenticationSuccessEvent.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/event/InteractiveAuthenticationSuccessEvent.java
@@ -29,7 +29,7 @@ import org.springframework.util.Assert;
public class InteractiveAuthenticationSuccessEvent extends AbstractAuthenticationEvent {
//~ Instance fields ================================================================================================
- private Class<?> generatedBy;
+ private final Class<?> generatedBy;
//~ Constructors ===================================================================================================
diff --git a/dist/spring-security-core/org/springframework/security/authentication/jaas/JaasAuthenticationProvider.java b/dist/spring-security-core/org/springframework/security/authentication/jaas/JaasAuthenticationProvider.java
index aac91b6..baa5fe5 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/jaas/JaasAuthenticationProvider.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/jaas/JaasAuthenticationProvider.java
@@ -15,40 +15,25 @@
package org.springframework.security.authentication.jaas;
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-import java.security.Principal;
-import java.security.Security;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Set;
-
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.UnsupportedCallbackException;
-import javax.security.auth.login.Configuration;
-import javax.security.auth.login.LoginContext;
-import javax.security.auth.login.LoginException;
-
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.ApplicationListener;
import org.springframework.core.io.Resource;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.jaas.event.JaasAuthenticationFailedEvent;
-import org.springframework.security.authentication.jaas.event.JaasAuthenticationSuccessEvent;
-import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.context.SecurityContext;
-import org.springframework.security.core.session.SessionDestroyedEvent;
import org.springframework.util.Assert;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.Configuration;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.security.Security;
+
/**
* An {@link AuthenticationProvider} implementation that retrieves user details from a JAAS login configuration.
@@ -125,101 +110,38 @@ import org.springframework.util.Assert;
* </p>
*
* @author Ray Krueger
+ * @author Rob Winch
*/
-public class JaasAuthenticationProvider implements AuthenticationProvider, ApplicationEventPublisherAware,
- InitializingBean, ApplicationListener<SessionDestroyedEvent> {
+public class JaasAuthenticationProvider extends AbstractJaasAuthenticationProvider {
//~ Static fields/initializers =====================================================================================
+ // exists for passivity
protected static final Log log = LogFactory.getLog(JaasAuthenticationProvider.class);
//~ Instance fields ================================================================================================
- private LoginExceptionResolver loginExceptionResolver = new DefaultLoginExceptionResolver();
private Resource loginConfig;
- private String loginContextName = "SPRINGSECURITY";
- private AuthorityGranter[] authorityGranters;
- private JaasAuthenticationCallbackHandler[] callbackHandlers;
- private ApplicationEventPublisher applicationEventPublisher;
private boolean refreshConfigurationOnStartup = true;
//~ Methods ========================================================================================================
public void afterPropertiesSet() throws Exception {
+ // the superclass is not called because it does additional checks that are non-passive
+ Assert.hasLength(getLoginContextName(), "loginContextName must be set on " + getClass());
Assert.notNull(loginConfig, "loginConfig must be set on " + getClass());
- Assert.hasLength(loginContextName, "loginContextName must be set on " + getClass());
-
configureJaas(loginConfig);
- Assert.notNull(Configuration.getConfiguration(),
- "As per http://java.sun.com/j2se/1.5.0/docs/api/javax/security/auth/login/Configuration.html "
- + "\"If a Configuration object was set via the Configuration.setConfiguration method, then that object is "
- + "returned. Otherwise, a default Configuration object is returned\". Your JRE returned null to "
- + "Configuration.getConfiguration().");
+ Assert.notNull(
+ Configuration.getConfiguration(),
+ "As per http://java.sun.com/j2se/1.5.0/docs/api/javax/security/auth/login/Configuration.html "
+ + "\"If a Configuration object was set via the Configuration.setConfiguration method, then that object is "
+ + "returned. Otherwise, a default Configuration object is returned\". Your JRE returned null to "
+ + "Configuration.getConfiguration().");
}
- /**
- * Attempts to login the user given the Authentication objects principal and credential
- *
- * @param auth The Authentication object to be authenticated.
- *
- * @return The authenticated Authentication object, with it's grantedAuthorities set.
- *
- * @throws AuthenticationException This implementation does not handle 'locked' or 'disabled' accounts. This method
- * only throws a AuthenticationServiceException, with the message of the LoginException that will be
- * thrown, should the loginContext.login() method fail.
- */
- public Authentication authenticate(Authentication auth) throws AuthenticationException {
- if (!(auth instanceof UsernamePasswordAuthenticationToken)) {
- return null;
- }
-
- UsernamePasswordAuthenticationToken request = (UsernamePasswordAuthenticationToken) auth;
- Set<GrantedAuthority> authorities;
-
- try {
- // Create the LoginContext object, and pass our InternallCallbackHandler
- LoginContext loginContext = new LoginContext(loginContextName, new InternalCallbackHandler(auth));
-
- // Attempt to login the user, the LoginContext will call our InternalCallbackHandler at this point.
- loginContext.login();
-
- // Create a set to hold the authorities, and add any that have already been applied.
- authorities = new HashSet<GrantedAuthority>();
- authorities.addAll(request.getAuthorities());
-
- // Get the subject principals and pass them to each of the AuthorityGranters
- Set<Principal> principals = loginContext.getSubject().getPrincipals();
-
- for (Principal principal : principals) {
- for (int i = 0; i < authorityGranters.length; i++) {
- AuthorityGranter granter = authorityGranters[i];
- Set<String> roles = granter.grant(principal);
-
- // If the granter doesn't wish to grant any authorities, it should return null.
- if ((roles != null) && !roles.isEmpty()) {
- for (String role : roles) {
- authorities.add(new JaasGrantedAuthority(role, principal));
- }
- }
- }
- }
-
- //Convert the authorities set back to an array and apply it to the token.
- JaasAuthenticationToken result = new JaasAuthenticationToken(request.getPrincipal(),
- request.getCredentials(), new ArrayList<GrantedAuthority>(authorities), loginContext);
-
- //Publish the success event
- publishSuccessEvent(result);
-
- //we're done, return the token.
- return result;
-
- } catch (LoginException loginException) {
- AuthenticationException ase = loginExceptionResolver.resolveException(loginException);
-
- publishFailureEvent(request, ase);
- throw ase;
- }
+ @Override
+ protected LoginContext createLoginContext(CallbackHandler handler) throws LoginException {
+ return new LoginContext(getLoginContextName(), handler);
}
/**
@@ -249,7 +171,7 @@ public class JaasAuthenticationProvider implements AuthenticationProvider, Appli
int n = 1;
final String prefix = "login.config.url.";
- String existing = null;
+ String existing;
while ((existing = Security.getProperty(prefix + n)) != null) {
alreadySet = existing.equals(loginConfigUrl);
@@ -269,54 +191,20 @@ public class JaasAuthenticationProvider implements AuthenticationProvider, Appli
}
private String convertLoginConfigToUrl() throws IOException {
- String loginConfigPath = loginConfig.getFile().getAbsolutePath();
- loginConfigPath.replace(File.separatorChar, '/');
+ String loginConfigPath;
- if (!loginConfigPath.startsWith("/")) {
- loginConfigPath = "/" + loginConfigPath;
- }
-
- return new URL("file", "", loginConfigPath).toString();
- }
-
- /**
- * Handles the logout by getting the SecurityContext for the session that was destroyed. <b>MUST NOT use
- * SecurityContextHolder as we are logging out a session that is not related to the current user.</b>
- *
- * @param event
- */
- protected void handleLogout(SessionDestroyedEvent event) {
- SecurityContext context = event.getSecurityContext();
-
- if (context == null) {
- log.debug("The destroyed session has no SecurityContext");
-
- return;
- }
-
- Authentication auth = context.getAuthentication();
-
- if ((auth != null) && (auth instanceof JaasAuthenticationToken)) {
- JaasAuthenticationToken token = (JaasAuthenticationToken) auth;
-
- try {
- LoginContext loginContext = token.getLoginContext();
+ try {
+ loginConfigPath = loginConfig.getFile().getAbsolutePath().replace(File.separatorChar, '/');
- if (loginContext != null) {
- log.debug("Logging principal: [" + token.getPrincipal() + "] out of LoginContext");
- loginContext.logout();
- } else {
- log.debug("Cannot logout principal: [" + token.getPrincipal() + "] from LoginContext. "
- + "The LoginContext is unavailable");
- }
- } catch (LoginException e) {
- log.warn("Error error logging out of LoginContext", e);
+ if (!loginConfigPath.startsWith("/")) {
+ loginConfigPath = "/" + loginConfigPath;
}
- }
- }
- public void onApplicationEvent(SessionDestroyedEvent event) {
- handleLogout(event);
+ return new URL("file", "", loginConfigPath).toString();
+ } catch (IOException e) {
+ // SEC-1700: May be inside a jar
+ return loginConfig.getURL().toString();
+ }
}
/**
@@ -327,63 +215,8 @@ public class JaasAuthenticationProvider implements AuthenticationProvider, Appli
* @param ase The excetion that caused the authentication failure
*/
protected void publishFailureEvent(UsernamePasswordAuthenticationToken token, AuthenticationException ase) {
- applicationEventPublisher.publishEvent(new JaasAuthenticationFailedEvent(token, ase));
- }
-
- /**
- * Publishes the {@link JaasAuthenticationSuccessEvent}. Can be overridden by subclasses for different
- * functionality.
- *
- * @param token The token being processed
- */
- protected void publishSuccessEvent(UsernamePasswordAuthenticationToken token) {
- if (applicationEventPublisher != null) {
- applicationEventPublisher.publishEvent(new JaasAuthenticationSuccessEvent(token));
- }
- }
-
- /**
- * Returns the AuthorityGrannter array that was passed to the {@link
- * #setAuthorityGranters(AuthorityGranter[])} method, or null if it none were ever set.
- *
- * @return The AuthorityGranter array, or null
- *
- * @see #setAuthorityGranters(AuthorityGranter[])
- */
- AuthorityGranter[] getAuthorityGranters() {
- return authorityGranters;
- }
-
- /**
- * Set the AuthorityGranters that should be consulted for role names to be granted to the Authentication.
- *
- * @param authorityGranters AuthorityGranter array
- *
- * @see JaasAuthenticationProvider
- */
- public void setAuthorityGranters(AuthorityGranter[] authorityGranters) {
- this.authorityGranters = authorityGranters;
- }
-
- /**
- * Returns the current JaasAuthenticationCallbackHandler array, or null if none are set.
- *
- * @return the JAASAuthenticationCallbackHandlers.
- *
- * @see #setCallbackHandlers(JaasAuthenticationCallbackHandler[])
- */
- JaasAuthenticationCallbackHandler[] getCallbackHandlers() {
- return callbackHandlers;
- }
-
- /**
- * Set the JAASAuthentcationCallbackHandler array to handle callback objects generated by the
- * LoginContext.login method.
- *
- * @param callbackHandlers Array of JAASAuthenticationCallbackHandlers
- */
- public void setCallbackHandlers(JaasAuthenticationCallbackHandler[] callbackHandlers) {
- this.callbackHandlers = callbackHandlers;
+ // exists for passivity (the superclass does a null check before publishing)
+ getApplicationEventPublisher().publishEvent(new JaasAuthenticationFailedEvent(token, ase));
}
public Resource getLoginConfig() {
@@ -401,33 +234,11 @@ public class JaasAuthenticationProvider implements AuthenticationProvider, Appli
this.loginConfig = loginConfig;
}
- String getLoginContextName() {
- return loginContextName;
- }
-
- /**
- * Set the loginContextName, this name is used as the index to the configuration specified in the
- * loginConfig property.
- *
- * @param loginContextName
- */
- public void setLoginContextName(String loginContextName) {
- this.loginContextName = loginContextName;
- }
-
- LoginExceptionResolver getLoginExceptionResolver() {
- return loginExceptionResolver;
- }
-
- public void setLoginExceptionResolver(LoginExceptionResolver loginExceptionResolver) {
- this.loginExceptionResolver = loginExceptionResolver;
- }
-
/**
* If set, a call to {@code Configuration#refresh()} will be made by {@code #configureJaas(Resource) }
* method. Defaults to {@code true}.
*
- * @see <a href="https://jira.springsource.org/browse/SEC-1320">SEC-1230</a>
+ * @see <a href="https://jira.springsource.org/browse/SEC-1320">SEC-1320</a>
*
* @param refresh set to {@code false} to disable reloading of the configuration.
* May be useful in some environments.
@@ -435,41 +246,4 @@ public class JaasAuthenticationProvider implements AuthenticationProvider, Appli
public void setRefreshConfigurationOnStartup(boolean refresh) {
this.refreshConfigurationOnStartup = refresh;
}
-
- public boolean supports(Class<? extends Object> aClass) {
- return UsernamePasswordAuthenticationToken.class.isAssignableFrom(aClass);
- }
-
- public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
- this.applicationEventPublisher = applicationEventPublisher;
- }
-
- protected ApplicationEventPublisher getApplicationEventPublisher() {
- return applicationEventPublisher;
- }
-
- //~ Inner Classes ==================================================================================================
-
- /**
- * Wrapper class for JAASAuthenticationCallbackHandlers
- */
- private class InternalCallbackHandler implements CallbackHandler {
- private Authentication authentication;
-
- public InternalCallbackHandler(Authentication authentication) {
- this.authentication = authentication;
- }
-
- public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
- for (int i = 0; i < callbackHandlers.length; i++) {
- JaasAuthenticationCallbackHandler handler = callbackHandlers[i];
-
- for (int j = 0; j < callbacks.length; j++) {
- Callback callback = callbacks[j];
-
- handler.handle(callback, authentication);
- }
- }
- }
- }
}
diff --git a/dist/spring-security-core/org/springframework/security/authentication/jaas/JaasAuthenticationToken.java b/dist/spring-security-core/org/springframework/security/authentication/jaas/JaasAuthenticationToken.java
index a7d18ea..59299d8 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/jaas/JaasAuthenticationToken.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/jaas/JaasAuthenticationToken.java
@@ -20,6 +20,7 @@ import java.util.List;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.SpringSecurityCoreVersion;
import javax.security.auth.login.LoginContext;
@@ -30,6 +31,9 @@ import javax.security.auth.login.LoginContext;
* @author Ray Krueger
*/
public class JaasAuthenticationToken extends UsernamePasswordAuthenticationToken {
+
+ private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
+
//~ Instance fields ================================================================================================
private final transient LoginContext loginContext;
diff --git a/dist/spring-security-core/org/springframework/security/authentication/jaas/JaasGrantedAuthority.java b/dist/spring-security-core/org/springframework/security/authentication/jaas/JaasGrantedAuthority.java
index b835250..f35e457 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/jaas/JaasGrantedAuthority.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/jaas/JaasGrantedAuthority.java
@@ -15,29 +15,29 @@
package org.springframework.security.authentication.jaas;
-import org.springframework.security.core.authority.GrantedAuthorityImpl;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.SpringSecurityCoreVersion;
import java.security.Principal;
/**
- * Extends GrantedAuthorityImpl to hold the principal that an AuthorityGranter justified as a reason to grant this
- * Authority. <br>
+ * {@code GrantedAuthority} which, in addition to the assigned role, holds the principal that an
+ * {@link AuthorityGranter} used as a reason to grant this authority.
*
* @author Ray Krueger
*
* @see AuthorityGranter
*/
-public class JaasGrantedAuthority extends GrantedAuthorityImpl {
- //~ Instance fields ================================================================================================
+public final class JaasGrantedAuthority implements GrantedAuthority {
- private static final long serialVersionUID = 1L;
- private Principal principal;
+ private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
- //~ Constructors ===================================================================================================
+ private final String role;
+ private final Principal principal;
public JaasGrantedAuthority(String role, Principal principal) {
- super(role);
+ this.role = role;
this.principal = principal;
}
@@ -46,4 +46,29 @@ public class JaasGrantedAuthority extends GrantedAuthorityImpl {
public Principal getPrincipal() {
return principal;
}
+
+ public String getAuthority() {
+ return role;
+ }
+
+ public int hashCode() {
+ return 31 ^ principal.hashCode() ^ role.hashCode();
+ }
+
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj instanceof JaasGrantedAuthority) {
+ JaasGrantedAuthority jga = (JaasGrantedAuthority) obj;
+ return this.role.equals(jga.role) && this.principal.equals(jga.principal);
+ }
+
+ return false;
+ }
+
+ public String toString() {
+ return "Jaas Authority [" + role + "," + principal + "]" ;
+ }
}
diff --git a/dist/spring-security-core/org/springframework/security/authentication/jaas/JaasNameCallbackHandler.java b/dist/spring-security-core/org/springframework/security/authentication/jaas/JaasNameCallbackHandler.java
index b57ce7c..9dda17b 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/jaas/JaasNameCallbackHandler.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/jaas/JaasNameCallbackHandler.java
@@ -54,7 +54,7 @@ public class JaasNameCallbackHandler implements JaasAuthenticationCallbackHandle
throws IOException, UnsupportedCallbackException {
if (callback instanceof NameCallback) {
NameCallback ncb = (NameCallback) callback;
- String username = "";
+ String username;
Object principal = authentication.getPrincipal();
diff --git a/dist/spring-security-core/org/springframework/security/authentication/jaas/event/JaasAuthenticationFailedEvent.java b/dist/spring-security-core/org/springframework/security/authentication/jaas/event/JaasAuthenticationFailedEvent.java
index 4e35b6b..c7dcb7e 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/jaas/event/JaasAuthenticationFailedEvent.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/jaas/event/JaasAuthenticationFailedEvent.java
@@ -26,7 +26,7 @@ import org.springframework.security.core.Authentication;
public class JaasAuthenticationFailedEvent extends JaasAuthenticationEvent {
//~ Instance fields ================================================================================================
- private Exception exception;
+ private final Exception exception;
//~ Constructors ===================================================================================================
diff --git a/dist/spring-security-core/org/springframework/security/authentication/rcp/RemoteAuthenticationException.java b/dist/spring-security-core/org/springframework/security/authentication/rcp/RemoteAuthenticationException.java
index de73f62..ab4e013 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/rcp/RemoteAuthenticationException.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/rcp/RemoteAuthenticationException.java
@@ -16,6 +16,7 @@
package org.springframework.security.authentication.rcp;
import org.springframework.core.NestedRuntimeException;
+import org.springframework.security.core.SpringSecurityCoreVersion;
/**
* Thrown if a <code>RemoteAuthenticationManager</code> cannot validate the presented authentication request.
@@ -27,6 +28,9 @@ import org.springframework.core.NestedRuntimeException;
* @author Ben Alex
*/
public class RemoteAuthenticationException extends NestedRuntimeException {
+
+ private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
+
//~ Constructors ===================================================================================================
/**
diff --git a/dist/spring-security-core/org/springframework/security/authentication/rcp/RemoteAuthenticationManager.java b/dist/spring-security-core/org/springframework/security/authentication/rcp/RemoteAuthenticationManager.java
index 0fe3211..5c87135 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/rcp/RemoteAuthenticationManager.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/rcp/RemoteAuthenticationManager.java
@@ -30,7 +30,7 @@ public interface RemoteAuthenticationManager {
/**
* Attempts to authenticate the remote client using the presented username and password. If authentication
- * is successful, an array of <code>GrantedAuthority[]</code> objects will be returned.
+ * is successful, a collection of {@code GrantedAuthority} objects will be returned.
* <p>
* In order to maximise remoting protocol compatibility, a design decision was taken to operate with minimal
* arguments and return only the minimal amount of information required for remote clients to enable/disable
@@ -44,6 +44,6 @@ public interface RemoteAuthenticationManager {
*
* @throws RemoteAuthenticationException if the authentication failed.
*/
- Collection<GrantedAuthority> attemptAuthentication(String username, String password)
+ Collection<? extends GrantedAuthority> attemptAuthentication(String username, String password)
throws RemoteAuthenticationException;
}
diff --git a/dist/spring-security-core/org/springframework/security/authentication/rcp/RemoteAuthenticationManagerImpl.java b/dist/spring-security-core/org/springframework/security/authentication/rcp/RemoteAuthenticationManagerImpl.java
index 528f1a8..2983bc7 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/rcp/RemoteAuthenticationManagerImpl.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/rcp/RemoteAuthenticationManagerImpl.java
@@ -44,20 +44,18 @@ public class RemoteAuthenticationManagerImpl implements RemoteAuthenticationMana
Assert.notNull(this.authenticationManager, "authenticationManager is required");
}
- public Collection<GrantedAuthority> attemptAuthentication(String username, String password)
+ public Collection<? extends GrantedAuthority> attemptAuthentication(String username, String password)
throws RemoteAuthenticationException {
UsernamePasswordAuthenticationToken request = new UsernamePasswordAuthenticationToken(username, password);
try {
- Collection<GrantedAuthority> authorities = authenticationManager.authenticate(request).getAuthorities();
-
- return authorities;
+ return authenticationManager.authenticate(request).getAuthorities();
} catch (AuthenticationException authEx) {
throw new RemoteAuthenticationException(authEx.getMessage());
}
}
- public AuthenticationManager getAuthenticationManager() {
+ protected AuthenticationManager getAuthenticationManager() {
return authenticationManager;
}
diff --git a/dist/spring-security-core/org/springframework/security/authentication/rcp/RemoteAuthenticationProvider.java b/dist/spring-security-core/org/springframework/security/authentication/rcp/RemoteAuthenticationProvider.java
index a3fd2c0..be9a328 100644
--- a/dist/spring-security-core/org/springframework/security/authentication/rcp/RemoteAuthenticationProvider.java
+++ b/dist/spring-security-core/org/springframework/security/authentication/rcp/RemoteAuthenticationProvider.java
@@ -58,7 +58,7 @@ public class RemoteAuthenticationProvider implements AuthenticationProvider, Ini
throws AuthenticationException {
String username = authentication.getPrincipal().toString();
String password = authentication.getCredentials().toString();
- Collection<GrantedAuthority> authorities = remoteAuthenticationManager.attemptAuthentication(username, password);
+ Collection<? extends GrantedAuthority> authorities = remoteAuthenticationManager.attemptAuthentication(username, password);
return new UsernamePasswordAuthenticationToken(username, password, authorities);
}
@@ -71,7 +71,7 @@ public class RemoteAuthenticationProvider implements AuthenticationProvider, Ini
this.remoteAuthenticationManager = remoteAuthenticationManager;
}
- public boolean supports(Class<? extends Object> authentication) {
+ public boolean supports(Class<?> authentication) {
return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
}
}
diff --git a/dist/spring-security-core/org/springframework/security/core/Authentication.java b/dist/spring-security-core/org/springframework/security/core/Authentication.java
index 7d39bd4..cc106d5 100644
--- a/dist/spring-security-core/org/springframework/security/core/Authentication.java
+++ b/dist/spring-security-core/org/springframework/security/core/Authentication.java
@@ -59,7 +59,7 @@ public interface Authentication extends Principal, Serializable {
* @return the authorities granted to the principal, or an empty collection if the token has not been authenticated.
* Never null.
*/
- Collection<GrantedAuthority> getAuthorities();
+ Collection<? extends GrantedAuthority> getAuthorities();
/**
* The credentials that prove the principal is correct. This is usually a password, but could be anything
diff --git a/dist/spring-security-core/org/springframework/security/core/AuthenticationException.java b/dist/spring-security-core/org/springframework/security/core/AuthenticationException.java
index 5f14900..8a14b4d 100644
--- a/dist/spring-security-core/org/springframework/security/core/AuthenticationException.java
+++ b/dist/spring-security-core/org/springframework/security/core/AuthenticationException.java
@@ -25,12 +25,12 @@ public abstract class AuthenticationException extends RuntimeException {
//~ Instance fields ================================================================================================
private Authentication authentication;
- private Object extraInformation;
+ private transient Object extraInformation;
//~ Constructors ===================================================================================================
/**
- * Constructs an <code>AuthenticationException</code> with the specified message and root cause.
+ * Constructs an {@code AuthenticationException} with the specified message and root cause.
*
* @param msg the detail message
* @param t the root cause
@@ -40,7 +40,7 @@ public abstract class AuthenticationException extends RuntimeException {
}
/**
- * Constructs an <code>AuthenticationException</code> with the specified message and no root cause.
+ * Constructs an {@code AuthenticationException} with the specified message and no root cause.
*
* @param msg the detail message
*/
@@ -48,33 +48,46 @@ public abstract class AuthenticationException extends RuntimeException {
super(msg);
}
+ /**
+ * @deprecated Use the exception message or use a custom exception if you really need additional information.
+ */
+ @Deprecated
public AuthenticationException(String msg, Object extraInformation) {
super(msg);
+ if (extraInformation instanceof CredentialsContainer) {
+ ((CredentialsContainer) extraInformation).eraseCredentials();
+ }
this.extraInformation = extraInformation;
}
//~ Methods ========================================================================================================
/**
- * The authentication request which this exception corresponds to (may be <code>null</code>)
+ * The authentication request which this exception corresponds to (may be {@code null})
+ * @deprecated to avoid potential leaking of sensitive information (e.g. through serialization/remoting).
*/
+ @Deprecated
public Authentication getAuthentication() {
return authentication;
}
+ @Deprecated
public void setAuthentication(Authentication authentication) {
this.authentication = authentication;
}
/**
- * Any additional information about the exception. Generally a <code>UserDetails</code> object.
+ * Any additional information about the exception. Generally a {@code UserDetails} object.
*
- * @return extra information or <code>null</code>
+ * @return extra information or {@code null}
+ * @deprecated Use the exception message or use a custom exception if you really need additional information.
*/
+ @Deprecated
public Object getExtraInformation() {
return extraInformation;
}
+ @Deprecated
public void clearExtraInformation() {
this.extraInformation = null;
}
diff --git a/dist/spring-security-core/org/springframework/security/core/SpringSecurityCoreVersion.java b/dist/spring-security-core/org/springframework/security/core/SpringSecurityCoreVersion.java
index 434d89b..10fa656 100644
--- a/dist/spring-security-core/org/springframework/security/core/SpringSecurityCoreVersion.java
+++ b/dist/spring-security-core/org/springframework/security/core/SpringSecurityCoreVersion.java
@@ -12,22 +12,34 @@ import org.springframework.core.SpringVersion;
public class SpringSecurityCoreVersion {
private static final Log logger = LogFactory.getLog(SpringSecurityCoreVersion.class);
+ /**
+ * Global Serialization value for Spring Security classes.
+ *
+ * N.B. Classes are not intended to be serializable between different versions.
+ * See SEC-1709 for why we still need a serial version.
+ */
+ public static final long SERIAL_VERSION_UID = 310L;
+
+ static final String SPRING_MAJOR_VERSION = "3";
+
+ static final String MIN_SPRING_VERSION = "3.0.6.RELEASE";
+
static {
// Check Spring Compatibility
String springVersion = SpringVersion.getVersion();
String version = getVersion();
if (springVersion != null) {
- // TODO: Generate version class and information dynamically from a template in the build file
logger.info("You are running with Spring Security Core " + version);
- if (!springVersion.startsWith("3")) {
- logger.error("Spring Major version '3' expected, but you are running with version: "
- + springVersion + ". Please check your classpath for unwanted jar files.");
+ if (!springVersion.startsWith(SPRING_MAJOR_VERSION)) {
+ logger.error("*** Spring Major version '" + SPRING_MAJOR_VERSION +
+ "' expected, but you are running with version: " + springVersion +
+ ". Please check your classpath for unwanted jar files.");
}
- if (springVersion.compareTo("3.0.3") < 0) {
- logger.warn("You are advised to use Spring 3.0.3 or later with this version. You are running: " +
- springVersion);
+ if (springVersion.compareTo(MIN_SPRING_VERSION) < 0) {
+ logger.warn("**** You are advised to use Spring " + MIN_SPRING_VERSION +
+ " or later with this version. You are running: " + springVersion);
}
}
}
diff --git a/dist/spring-security-core/org/springframework/security/core/authority/AuthorityUtils.java b/dist/spring-security-core/org/springframework/security/core/authority/AuthorityUtils.java
index 50de8f7..25a9bdb 100644
--- a/dist/spring-security-core/org/springframework/security/core/authority/AuthorityUtils.java
+++ b/dist/spring-security-core/org/springframework/security/core/authority/AuthorityUtils.java
@@ -35,7 +35,7 @@ public abstract class AuthorityUtils {
* Converts an array of GrantedAuthority objects to a Set.
* @return a Set of the Strings obtained from each call to GrantedAuthority.getAuthority()
*/
- public static Set<String> authorityListToSet(Collection<GrantedAuthority> userAuthorities) {
+ public static Set<String> authorityListToSet(Collection<? extends GrantedAuthority> userAuthorities) {
Set<String> set = new HashSet<String>(userAuthorities.size());
for (GrantedAuthority authority: userAuthorities) {
@@ -48,8 +48,8 @@ public abstract class AuthorityUtils {
public static List<GrantedAuthority> createAuthorityList(String... roles) {
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(roles.length);
- for (int i=0; i < roles.length; i++) {
- authorities.add(new GrantedAuthorityImpl(roles[i]));
+ for (String role : roles) {
+ authorities.add(new SimpleGrantedAuthority(role));
}
return authorities;
diff --git a/dist/spring-security-core/org/springframework/security/core/authority/GrantedAuthoritiesContainer.java b/dist/spring-security-core/org/springframework/security/core/authority/GrantedAuthoritiesContainer.java
index 514af0d..02de085 100644
--- a/dist/spring-security-core/org/springframework/security/core/authority/GrantedAuthoritiesContainer.java
+++ b/dist/spring-security-core/org/springframework/security/core/authority/GrantedAuthoritiesContainer.java
@@ -1,7 +1,7 @@
package org.springframework.security.core.authority;
import java.io.Serializable;
-import java.util.List;
+import java.util.*;
import org.springframework.security.core.GrantedAuthority;
@@ -16,5 +16,5 @@ import org.springframework.security.core.GrantedAuthority;
* @since 2.0
*/
public interface GrantedAuthoritiesContainer extends Serializable {
- List<GrantedAuthority> getGrantedAuthorities();
+ Collection<? extends GrantedAuthority> getGrantedAuthorities();
}
diff --git a/dist/spring-security-core/org/springframework/security/core/authority/GrantedAuthoritiesContainerImpl.java b/dist/spring-security-core/org/springframework/security/core/authority/GrantedAuthoritiesContainerImpl.java
index bb898a9..2cfc281 100644
--- a/dist/spring-security-core/org/springframework/security/core/authority/GrantedAuthoritiesContainerImpl.java
+++ b/dist/spring-security-core/org/springframework/security/core/authority/GrantedAuthoritiesContainerImpl.java
@@ -1,16 +1,22 @@
package org.springframework.security.core.authority;
-import java.util.Collections;
-import java.util.List;
+import java.util.*;
import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.SpringSecurityCoreVersion;
import org.springframework.util.Assert;
+ at Deprecated
public class GrantedAuthoritiesContainerImpl implements MutableGrantedAuthoritiesContainer {
+
+ private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
+
private List<GrantedAuthority> authorities;
- public void setGrantedAuthorities(List<GrantedAuthority> newAuthorities) {
- authorities = Collections.unmodifiableList(newAuthorities);
+ public void setGrantedAuthorities(Collection<? extends GrantedAuthority> newAuthorities) {
+ ArrayList<GrantedAuthority> temp = new ArrayList<GrantedAuthority>(newAuthorities.size());
+ temp.addAll(newAuthorities);
+ authorities = Collections.unmodifiableList(temp);
}
public List<GrantedAuthority> getGrantedAuthorities() {
diff --git a/dist/spring-security-core/org/springframework/security/core/authority/GrantedAuthorityImpl.java b/dist/spring-security-core/org/springframework/security/core/authority/GrantedAuthorityImpl.java
index aa20c7e..30cf605 100644
--- a/dist/spring-security-core/org/springframework/security/core/authority/GrantedAuthorityImpl.java
+++ b/dist/spring-security-core/org/springframework/security/core/authority/GrantedAuthorityImpl.java
@@ -15,10 +15,9 @@
package org.springframework.security.core.authority;
-import java.io.Serializable;
-
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.SpringSecurityCoreVersion;
import org.springframework.util.Assert;
@@ -27,17 +26,18 @@ import org.springframework.util.Assert;
*
* <p>
* Stores a <code>String</code> representation of an authority granted to the {@link Authentication} object.
- * <p>
- * If compared to a custom authority which returns null from {@link #getAuthority}, the <tt>compareTo</tt>
- * method will return -1, so the custom authority will take precedence.
*
* @author Ben Alex
+ * @deprecated Use the final class {@link SimpleGrantedAuthority} or implement your own.
*/
-public class GrantedAuthorityImpl implements GrantedAuthority, Serializable {
+ at Deprecated
+public class GrantedAuthorityImpl implements GrantedAuthority {
+
+ private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
+
//~ Instance fields ================================================================================================
- private static final long serialVersionUID = 1L;
- private String role;
+ private final String role;
//~ Constructors ===================================================================================================
diff --git a/dist/spring-security-core/org/springframework/security/core/authority/MutableGrantedAuthoritiesContainer.java b/dist/spring-security-core/org/springframework/security/core/authority/MutableGrantedAuthoritiesContainer.java
index 30d9cd1..c9906ef 100644
--- a/dist/spring-security-core/org/springframework/security/core/authority/MutableGrantedAuthoritiesContainer.java
+++ b/dist/spring-security-core/org/springframework/security/core/authority/MutableGrantedAuthoritiesContainer.java
@@ -1,9 +1,9 @@
package org.springframework.security.core.authority;
-import java.util.List;
-
import org.springframework.security.core.GrantedAuthority;
+import java.util.*;
+
/**
* Indicates that a object can be used to store and retrieve GrantedAuthority objects.
* <p>
@@ -14,9 +14,10 @@ import org.springframework.security.core.GrantedAuthority;
* @author Luke Taylor
* @since 2.0
*/
+ at Deprecated
public interface MutableGrantedAuthoritiesContainer extends GrantedAuthoritiesContainer {
/**
* Used to store authorities in the containing object.
*/
- void setGrantedAuthorities(List<GrantedAuthority> authorities);
+ void setGrantedAuthorities(Collection<? extends GrantedAuthority> authorities);
}
diff --git a/dist/spring-security-core/org/springframework/security/core/authority/mapping/Attributes2GrantedAuthoritiesMapper.java b/dist/spring-security-core/org/springframework/security/core/authority/mapping/Attributes2GrantedAuthoritiesMapper.java
index ac755e0..c456473 100644
--- a/dist/spring-security-core/org/springframework/security/core/authority/mapping/Attributes2GrantedAuthoritiesMapper.java
+++ b/dist/spring-security-core/org/springframework/security/core/authority/mapping/Attributes2GrantedAuthoritiesMapper.java
@@ -7,21 +7,21 @@ import org.springframework.security.core.GrantedAuthority;
/**
* Interface to be implemented by classes that can map a list of security attributes (such as roles or
- * group names) to a list of Spring Security GrantedAuthorities.
+ * group names) to a collection of Spring Security {@code GrantedAuthority}s.
*
* @author Ruud Senden
* @since 2.0
*/
public interface Attributes2GrantedAuthoritiesMapper {
/**
- * Implementations of this method should map the given list of attributes to a
- * list of Spring Security GrantedAuthorities. There are no restrictions for the
+ * Implementations of this method should map the given collection of attributes to a
+ * collection of Spring Security GrantedAuthorities. There are no restrictions for the
* mapping process; a single attribute can be mapped to multiple Spring Security
* GrantedAuthorities, all attributes can be mapped to a single Spring Security
- * GrantedAuthority, some attributes may not be mapped, etc.
+ * {@code GrantedAuthority}, some attributes may not be mapped, etc.
*
* @param attributes the attributes to be mapped
- * @return the list of mapped GrantedAuthorities
+ * @return the collection of authorities created from the attributes
*/
- public List<GrantedAuthority> getGrantedAuthorities(Collection<String> attributes);
+ public Collection<? extends GrantedAuthority> getGrantedAuthorities(Collection<String> attributes);
}
diff --git a/dist/spring-security-core/org/springframework/security/core/authority/mapping/MapBasedAttributes2GrantedAuthoritiesMapper.java b/dist/spring-security-core/org/springframework/security/core/authority/mapping/MapBasedAttributes2GrantedAuthoritiesMapper.java
index ff3d2f5..0f98ba5 100644
--- a/dist/spring-security-core/org/springframework/security/core/authority/mapping/MapBasedAttributes2GrantedAuthoritiesMapper.java
+++ b/dist/spring-security-core/org/springframework/security/core/authority/mapping/MapBasedAttributes2GrantedAuthoritiesMapper.java
@@ -1,17 +1,10 @@
package org.springframework.security.core.authority.mapping;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.StringTokenizer;
+import java.util.*;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.authority.GrantedAuthorityImpl;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -127,8 +120,8 @@ public class MapBasedAttributes2GrantedAuthoritiesMapper implements Attributes2G
}
private void addGrantedAuthorityCollection(Collection<GrantedAuthority> result, Object[] value) {
- for ( int i = 0 ; i < value.length ; i++ ) {
- addGrantedAuthorityCollection(result,value[i]);
+ for (Object aValue : value) {
+ addGrantedAuthorityCollection(result, aValue);
}
}
@@ -137,7 +130,7 @@ public class MapBasedAttributes2GrantedAuthoritiesMapper implements Attributes2G
while ( st.hasMoreTokens() ) {
String nextToken = st.nextToken();
if ( StringUtils.hasText(nextToken) ) {
- result.add(new GrantedAuthorityImpl(nextToken));
+ result.add(new SimpleGrantedAuthority(nextToken));
}
}
}
diff --git a/dist/spring-security-core/org/springframework/security/core/authority/mapping/SimpleAttributes2GrantedAuthoritiesMapper.java b/dist/spring-security-core/org/springframework/security/core/authority/mapping/SimpleAttributes2GrantedAuthoritiesMapper.java
index 723eb2e..5ec87b9 100644
--- a/dist/spring-security-core/org/springframework/security/core/authority/mapping/SimpleAttributes2GrantedAuthoritiesMapper.java
+++ b/dist/spring-security-core/org/springframework/security/core/authority/mapping/SimpleAttributes2GrantedAuthoritiesMapper.java
@@ -1,7 +1,7 @@
package org.springframework.security.core.authority.mapping;
import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.authority.GrantedAuthorityImpl;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
import java.util.ArrayList;
import java.util.Collection;
@@ -67,9 +67,9 @@ public class SimpleAttributes2GrantedAuthoritiesMapper implements Attributes2Gra
attribute = attribute.toUpperCase(Locale.getDefault());
}
if (isAddPrefixIfAlreadyExisting() || !attribute.startsWith(getAttributePrefix())) {
- return new GrantedAuthorityImpl(getAttributePrefix() + attribute);
+ return new SimpleGrantedAuthority(getAttributePrefix() + attribute);
} else {
- return new GrantedAuthorityImpl(attribute);
+ return new SimpleGrantedAuthority(attribute);
}
}
diff --git a/dist/spring-security-core/org/springframework/security/core/authority/mapping/SimpleMappableAttributesRetriever.java b/dist/spring-security-core/org/springframework/security/core/authority/mapping/SimpleMappableAttributesRetriever.java
index b49c85c..bab867e 100644
--- a/dist/spring-security-core/org/springframework/security/core/authority/mapping/SimpleMappableAttributesRetriever.java
+++ b/dist/spring-security-core/org/springframework/security/core/authority/mapping/SimpleMappableAttributesRetriever.java
@@ -24,8 +24,7 @@ public class SimpleMappableAttributesRetriever implements MappableAttributesRetr
return mappableAttributes;
}
- @SuppressWarnings("unchecked")
- public void setMappableAttributes(Set aMappableRoles) {
+ public void setMappableAttributes(Set<String> aMappableRoles) {
mappableAttributes = new HashSet<String>();
mappableAttributes.addAll(aMappableRoles);
mappableAttributes = Collections.unmodifiableSet(mappableAttributes);
diff --git a/dist/spring-security-core/org/springframework/security/core/codec/Base64.java b/dist/spring-security-core/org/springframework/security/core/codec/Base64.java
deleted file mode 100644
index b4f11fa..0000000
--- a/dist/spring-security-core/org/springframework/security/core/codec/Base64.java
+++ /dev/null
@@ -1,648 +0,0 @@
-package org.springframework.security.core.codec;
-
-
-/**
- * Base64 encoder which is a reduced version of Robert Harder's public domain implementation.
- * See <a href="http://iharder.net/base64">http://iharder.net/base64</a> for more information.
- * <p>
- * For internal use only.
- *
- * @author Luke Taylor
- * @since 3.0
- */
-public final class Base64 {
-
- /** No options specified. Value is zero. */
- public final static int NO_OPTIONS = 0;
-
- /** Specify encoding in first bit. Value is one. */
- public final static int ENCODE = 1;
-
-
- /** Specify decoding in first bit. Value is zero. */
- public final static int DECODE = 0;
-
- /** Do break lines when encoding. Value is 8. */
- public final static int DO_BREAK_LINES = 8;
-
- /**
- * Encode using Base64-like encoding that is URL- and Filename-safe as described
- * in Section 4 of RFC3548:
- * <a href="http://www.faqs.org/rfcs/rfc3548.html">http://www.faqs.org/rfcs/rfc3548.html</a>.
- * It is important to note that data encoded this way is <em>not</em> officially valid Base64,
- * or at the very least should not be called Base64 without also specifying that is
- * was encoded using the URL- and Filename-safe dialect.
- */
- public final static int URL_SAFE = 16;
-
-
- /**
- * Encode using the special "ordered" dialect of Base64 described here:
- * <a href="http://www.faqs.org/qa/rfcc-1940.html">http://www.faqs.org/qa/rfcc-1940.html</a>.
- */
- public final static int ORDERED = 32;
-
-
- /** Maximum line length (76) of Base64 output. */
- private final static int MAX_LINE_LENGTH = 76;
-
-
- /** The equals sign (=) as a byte. */
- private final static byte EQUALS_SIGN = (byte)'=';
-
-
- /** The new line character (\n) as a byte. */
- private final static byte NEW_LINE = (byte)'\n';
-
- private final static byte WHITE_SPACE_ENC = -5; // Indicates white space in encoding
- private final static byte EQUALS_SIGN_ENC = -1; // Indicates equals sign in encoding
-
-
-/* ******** S T A N D A R D B A S E 6 4 A L P H A B E T ******** */
-
- /** The 64 valid Base64 values. */
- /* Host platform me be something funny like EBCDIC, so we hardcode these values. */
- private final static byte[] _STANDARD_ALPHABET = {
- (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
- (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
- (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
- (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
- (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
- (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
- (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
- (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z',
- (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5',
- (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'+', (byte)'/'
- };
-
-
- /**
- * Translates a Base64 value to either its 6-bit reconstruction value
- * or a negative number indicating some other meaning.
- **/
- private final static byte[] _STANDARD_DECODABET = {
- -9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 0 - 8
- -5,-5, // Whitespace: Tab and Linefeed
- -9,-9, // Decimal 11 - 12
- -5, // Whitespace: Carriage Return
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 14 - 26
- -9,-9,-9,-9,-9, // Decimal 27 - 31
- -5, // Whitespace: Space
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 33 - 42
- 62, // Plus sign at decimal 43
- -9,-9,-9, // Decimal 44 - 46
- 63, // Slash at decimal 47
- 52,53,54,55,56,57,58,59,60,61, // Numbers zero through nine
- -9,-9,-9, // Decimal 58 - 60
- -1, // Equals sign at decimal 61
- -9,-9,-9, // Decimal 62 - 64
- 0,1,2,3,4,5,6,7,8,9,10,11,12,13, // Letters 'A' through 'N'
- 14,15,16,17,18,19,20,21,22,23,24,25, // Letters 'O' through 'Z'
- -9,-9,-9,-9,-9,-9, // Decimal 91 - 96
- 26,27,28,29,30,31,32,33,34,35,36,37,38, // Letters 'a' through 'm'
- 39,40,41,42,43,44,45,46,47,48,49,50,51, // Letters 'n' through 'z'
- -9,-9,-9,-9 // Decimal 123 - 126
- /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */
- };
-
-
-/* ******** U R L S A F E B A S E 6 4 A L P H A B E T ******** */
-
- /**
- * Used in the URL- and Filename-safe dialect described in Section 4 of RFC3548:
- * <a href="http://www.faqs.org/rfcs/rfc3548.html">http://www.faqs.org/rfcs/rfc3548.html</a>.
- * Notice that the last two bytes become "hyphen" and "underscore" instead of "plus" and "slash."
- */
- private final static byte[] _URL_SAFE_ALPHABET = {
- (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
- (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
- (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
- (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
- (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
- (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
- (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
- (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z',
- (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5',
- (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'-', (byte)'_'
- };
-
- /**
- * Used in decoding URL- and Filename-safe dialects of Base64.
- */
- private final static byte[] _URL_SAFE_DECODABET = {
- -9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 0 - 8
- -5,-5, // Whitespace: Tab and Linefeed
- -9,-9, // Decimal 11 - 12
- -5, // Whitespace: Carriage Return
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 14 - 26
- -9,-9,-9,-9,-9, // Decimal 27 - 31
- -5, // Whitespace: Space
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 33 - 42
- -9, // Plus sign at decimal 43
- -9, // Decimal 44
- 62, // Minus sign at decimal 45
- -9, // Decimal 46
- -9, // Slash at decimal 47
- 52,53,54,55,56,57,58,59,60,61, // Numbers zero through nine
- -9,-9,-9, // Decimal 58 - 60
- -1, // Equals sign at decimal 61
- -9,-9,-9, // Decimal 62 - 64
- 0,1,2,3,4,5,6,7,8,9,10,11,12,13, // Letters 'A' through 'N'
- 14,15,16,17,18,19,20,21,22,23,24,25, // Letters 'O' through 'Z'
- -9,-9,-9,-9, // Decimal 91 - 94
- 63, // Underscore at decimal 95
- -9, // Decimal 96
- 26,27,28,29,30,31,32,33,34,35,36,37,38, // Letters 'a' through 'm'
- 39,40,41,42,43,44,45,46,47,48,49,50,51, // Letters 'n' through 'z'
- -9,-9,-9,-9 // Decimal 123 - 126
- /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */
- };
-
-
-
-/* ******** O R D E R E D B A S E 6 4 A L P H A B E T ******** */
-
- /**
- * I don't get the point of this technique, but someone requested it,
- * and it is described here:
- * <a href="http://www.faqs.org/qa/rfcc-1940.html">http://www.faqs.org/qa/rfcc-1940.html</a>.
- */
- private final static byte[] _ORDERED_ALPHABET = {
- (byte)'-',
- (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4',
- (byte)'5', (byte)'6', (byte)'7', (byte)'8', (byte)'9',
- (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
- (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
- (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
- (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
- (byte)'_',
- (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
- (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
- (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
- (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z'
- };
-
- /**
- * Used in decoding the "ordered" dialect of Base64.
- */
- private final static byte[] _ORDERED_DECODABET = {
- -9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 0 - 8
- -5,-5, // Whitespace: Tab and Linefeed
- -9,-9, // Decimal 11 - 12
- -5, // Whitespace: Carriage Return
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 14 - 26
- -9,-9,-9,-9,-9, // Decimal 27 - 31
- -5, // Whitespace: Space
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 33 - 42
- -9, // Plus sign at decimal 43
- -9, // Decimal 44
- 0, // Minus sign at decimal 45
- -9, // Decimal 46
- -9, // Slash at decimal 47
- 1,2,3,4,5,6,7,8,9,10, // Numbers zero through nine
- -9,-9,-9, // Decimal 58 - 60
- -1, // Equals sign at decimal 61
- -9,-9,-9, // Decimal 62 - 64
- 11,12,13,14,15,16,17,18,19,20,21,22,23, // Letters 'A' through 'M'
- 24,25,26,27,28,29,30,31,32,33,34,35,36, // Letters 'N' through 'Z'
- -9,-9,-9,-9, // Decimal 91 - 94
- 37, // Underscore at decimal 95
- -9, // Decimal 96
- 38,39,40,41,42,43,44,45,46,47,48,49,50, // Letters 'a' through 'm'
- 51,52,53,54,55,56,57,58,59,60,61,62,63, // Letters 'n' through 'z'
- -9,-9,-9,-9 // Decimal 123 - 126
- /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */
- };
-
-
- public static byte[] decode(byte[] bytes) {
- return decode(bytes, 0, bytes.length, NO_OPTIONS);
- }
-
- public static byte[] encode(byte[] bytes) {
- return encodeBytesToBytes(bytes, 0, bytes.length, NO_OPTIONS);
- }
-
- public static boolean isBase64(byte[] bytes) {
- try {
- decode(bytes);
- } catch (InvalidBase64CharacterException e) {
- return false;
- }
- return true;
- }
-
- /**
- * Returns one of the _SOMETHING_ALPHABET byte arrays depending on
- * the options specified.
- * It's possible, though silly, to specify ORDERED <b>and</b> URLSAFE
- * in which case one of them will be picked, though there is
- * no guarantee as to which one will be picked.
- */
- private final static byte[] getAlphabet( int options ) {
- if ((options & URL_SAFE) == URL_SAFE) {
- return _URL_SAFE_ALPHABET;
- } else if ((options & ORDERED) == ORDERED) {
- return _ORDERED_ALPHABET;
- } else {
- return _STANDARD_ALPHABET;
- }
- }
-
- /**
- * Returns one of the _SOMETHING_DECODABET byte arrays depending on
- * the options specified.
- * It's possible, though silly, to specify ORDERED and URL_SAFE
- * in which case one of them will be picked, though there is
- * no guarantee as to which one will be picked.
- */
- private final static byte[] getDecodabet( int options ) {
- if( (options & URL_SAFE) == URL_SAFE) {
- return _URL_SAFE_DECODABET;
- } else if ((options & ORDERED) == ORDERED) {
- return _ORDERED_DECODABET;
- } else {
- return _STANDARD_DECODABET;
- }
- }
-
-
-/* ******** E N C O D I N G M E T H O D S ******** */
-
- /**
- * <p>Encodes up to three bytes of the array <var>source</var>
- * and writes the resulting four Base64 bytes to <var>destination</var>.
- * The source and destination arrays can be manipulated
- * anywhere along their length by specifying
- * <var>srcOffset</var> and <var>destOffset</var>.
- * This method does not check to make sure your arrays
- * are large enough to accomodate <var>srcOffset</var> + 3 for
- * the <var>source</var> array or <var>destOffset</var> + 4 for
- * the <var>destination</var> array.
- * The actual number of significant bytes in your array is
- * given by <var>numSigBytes</var>.</p>
- * <p>This is the lowest level of the encoding methods with
- * all possible parameters.</p>
- *
- * @param source the array to convert
- * @param srcOffset the index where conversion begins
- * @param numSigBytes the number of significant bytes in your array
- * @param destination the array to hold the conversion
- * @param destOffset the index where output will be put
- * @return the <var>destination</var> array
- * @since 1.3
- */
- private static byte[] encode3to4(
- byte[] source, int srcOffset, int numSigBytes,
- byte[] destination, int destOffset, int options ) {
-
- byte[] ALPHABET = getAlphabet( options );
-
- // 1 2 3
- // 01234567890123456789012345678901 Bit position
- // --------000000001111111122222222 Array position from threeBytes
- // --------| || || || | Six bit groups to index ALPHABET
- // >>18 >>12 >> 6 >> 0 Right shift necessary
- // 0x3f 0x3f 0x3f Additional AND
-
- // Create buffer with zero-padding if there are only one or two
- // significant bytes passed in the array.
- // We have to shift left 24 in order to flush out the 1's that appear
- // when Java treats a value as negative that is cast from a byte to an int.
- int inBuff = ( numSigBytes > 0 ? ((source[ srcOffset ] << 24) >>> 8) : 0 )
- | ( numSigBytes > 1 ? ((source[ srcOffset + 1 ] << 24) >>> 16) : 0 )
- | ( numSigBytes > 2 ? ((source[ srcOffset + 2 ] << 24) >>> 24) : 0 );
-
- switch( numSigBytes )
- {
- case 3:
- destination[ destOffset ] = ALPHABET[ (inBuff >>> 18) ];
- destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ];
- destination[ destOffset + 2 ] = ALPHABET[ (inBuff >>> 6) & 0x3f ];
- destination[ destOffset + 3 ] = ALPHABET[ (inBuff ) & 0x3f ];
- return destination;
-
- case 2:
- destination[ destOffset ] = ALPHABET[ (inBuff >>> 18) ];
- destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ];
- destination[ destOffset + 2 ] = ALPHABET[ (inBuff >>> 6) & 0x3f ];
- destination[ destOffset + 3 ] = EQUALS_SIGN;
- return destination;
-
- case 1:
- destination[ destOffset ] = ALPHABET[ (inBuff >>> 18) ];
- destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ];
- destination[ destOffset + 2 ] = EQUALS_SIGN;
- destination[ destOffset + 3 ] = EQUALS_SIGN;
- return destination;
-
- default:
- return destination;
- }
- }
-
-
- /**
- * Similar to {@link #encodeBytes(byte[], int, int, int)} but returns
- * a byte array instead of instantiating a String. This is more efficient
- * if you're working with I/O streams and have large data sets to encode.
- *
- *
- * @param source The data to convert
- * @param off Offset in array where conversion should begin
- * @param len Length of data to convert
- * @param options Specified options
- * @return The Base64-encoded data as a String
- * @see Base64#DO_BREAK_LINES
- * @throws java.io.IOException if there is an error
- * @throws NullPointerException if source array is null
- * @throws IllegalArgumentException if source array, offset, or length are invalid
- * @since 2.3.1
- */
- private static byte[] encodeBytesToBytes( byte[] source, int off, int len, int options ) {
-
- if( source == null ){
- throw new NullPointerException( "Cannot serialize a null array." );
- } // end if: null
-
- if( off < 0 ){
- throw new IllegalArgumentException( "Cannot have negative offset: " + off );
- } // end if: off < 0
-
- if( len < 0 ){
- throw new IllegalArgumentException( "Cannot have length offset: " + len );
- } // end if: len < 0
-
- if( off + len > source.length ){
- throw new IllegalArgumentException(
- String.format( "Cannot have offset of %d and length of %d with array of length %d", off,len,source.length));
- } // end if: off < 0
-
- boolean breakLines = (options & DO_BREAK_LINES) > 0;
-
- //int len43 = len * 4 / 3;
- //byte[] outBuff = new byte[ ( len43 ) // Main 4:3
- // + ( (len % 3) > 0 ? 4 : 0 ) // Account for padding
- // + (breakLines ? ( len43 / MAX_LINE_LENGTH ) : 0) ]; // New lines
- // Try to determine more precisely how big the array needs to be.
- // If we get it right, we don't have to do an array copy, and
- // we save a bunch of memory.
- int encLen = ( len / 3 ) * 4 + ( len % 3 > 0 ? 4 : 0 ); // Bytes needed for actual encoding
- if( breakLines ){
- encLen += encLen / MAX_LINE_LENGTH; // Plus extra newline characters
- }
- byte[] outBuff = new byte[ encLen ];
-
-
- int d = 0;
- int e = 0;
- int len2 = len - 2;
- int lineLength = 0;
- for( ; d < len2; d+=3, e+=4 ) {
- encode3to4( source, d+off, 3, outBuff, e, options );
-
- lineLength += 4;
- if( breakLines && lineLength >= MAX_LINE_LENGTH )
- {
- outBuff[e+4] = NEW_LINE;
- e++;
- lineLength = 0;
- } // end if: end of line
- } // en dfor: each piece of array
-
- if( d < len ) {
- encode3to4( source, d+off, len - d, outBuff, e, options );
- e += 4;
- } // end if: some padding needed
-
-
- // Only resize array if we didn't guess it right.
- if( e < outBuff.length - 1 ){
- byte[] finalOut = new byte[e];
- System.arraycopy(outBuff,0, finalOut,0,e);
- //System.err.println("Having to resize array from " + outBuff.length + " to " + e );
- return finalOut;
- } else {
- //System.err.println("No need to resize array.");
- return outBuff;
- }
- }
-
-
-/* ******** D E C O D I N G M E T H O D S ******** */
-
-
- /**
- * Decodes four bytes from array <var>source</var>
- * and writes the resulting bytes (up to three of them)
- * to <var>destination</var>.
- * The source and destination arrays can be manipulated
- * anywhere along their length by specifying
- * <var>srcOffset</var> and <var>destOffset</var>.
- * This method does not check to make sure your arrays
- * are large enough to accomodate <var>srcOffset</var> + 4 for
- * the <var>source</var> array or <var>destOffset</var> + 3 for
- * the <var>destination</var> array.
- * This method returns the actual number of bytes that
- * were converted from the Base64 encoding.
- * <p>This is the lowest level of the decoding methods with
- * all possible parameters.</p>
- *
- *
- * @param source the array to convert
- * @param srcOffset the index where conversion begins
- * @param destination the array to hold the conversion
- * @param destOffset the index where output will be put
- * @param options alphabet type is pulled from this (standard, url-safe, ordered)
- * @return the number of decoded bytes converted
- * @throws NullPointerException if source or destination arrays are null
- * @throws IllegalArgumentException if srcOffset or destOffset are invalid
- * or there is not enough room in the array.
- * @since 1.3
- */
- private static int decode4to3(
- byte[] source, int srcOffset,
- byte[] destination, int destOffset, int options ) {
-
- // Lots of error checking and exception throwing
- if( source == null ){
- throw new NullPointerException( "Source array was null." );
- } // end if
- if( destination == null ){
- throw new NullPointerException( "Destination array was null." );
- } // end if
- if( srcOffset < 0 || srcOffset + 3 >= source.length ){
- throw new IllegalArgumentException( String.format(
- "Source array with length %d cannot have offset of %d and still process four bytes.", source.length, srcOffset ) );
- } // end if
- if( destOffset < 0 || destOffset +2 >= destination.length ){
- throw new IllegalArgumentException( String.format(
- "Destination array with length %d cannot have offset of %d and still store three bytes.", destination.length, destOffset ) );
- } // end if
-
-
- byte[] DECODABET = getDecodabet( options );
-
- // Example: Dk==
- if( source[ srcOffset + 2] == EQUALS_SIGN ) {
- // Two ways to do the same thing. Don't know which way I like best.
- //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 )
- // | ( ( DECODABET[ source[ srcOffset + 1] ] << 24 ) >>> 12 );
- int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 )
- | ( ( DECODABET[ source[ srcOffset + 1] ] & 0xFF ) << 12 );
-
- destination[ destOffset ] = (byte)( outBuff >>> 16 );
- return 1;
- }
-
- // Example: DkL=
- else if( source[ srcOffset + 3 ] == EQUALS_SIGN ) {
- // Two ways to do the same thing. Don't know which way I like best.
- //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 )
- // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 )
- // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 );
- int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 )
- | ( ( DECODABET[ source[ srcOffset + 1 ] ] & 0xFF ) << 12 )
- | ( ( DECODABET[ source[ srcOffset + 2 ] ] & 0xFF ) << 6 );
-
- destination[ destOffset ] = (byte)( outBuff >>> 16 );
- destination[ destOffset + 1 ] = (byte)( outBuff >>> 8 );
- return 2;
- }
-
- // Example: DkLE
- else {
- // Two ways to do the same thing. Don't know which way I like best.
- //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 )
- // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 )
- // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 )
- // | ( ( DECODABET[ source[ srcOffset + 3 ] ] << 24 ) >>> 24 );
- int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 )
- | ( ( DECODABET[ source[ srcOffset + 1 ] ] & 0xFF ) << 12 )
- | ( ( DECODABET[ source[ srcOffset + 2 ] ] & 0xFF ) << 6)
- | ( ( DECODABET[ source[ srcOffset + 3 ] ] & 0xFF ) );
-
-
- destination[ destOffset ] = (byte)( outBuff >> 16 );
- destination[ destOffset + 1 ] = (byte)( outBuff >> 8 );
- destination[ destOffset + 2 ] = (byte)( outBuff );
-
- return 3;
- }
- }
-
- /**
- * Low-level access to decoding ASCII characters in
- * the form of a byte array. <strong>Ignores GUNZIP option, if
- * it's set.</strong> This is not generally a recommended method,
- * although it is used internally as part of the decoding process.
- * Special case: if len = 0, an empty array is returned. Still,
- * if you need more speed and reduced memory footprint (and aren't
- * gzipping), consider this method.
- *
- * @param source The Base64 encoded data
- * @param off The offset of where to begin decoding
- * @param len The length of characters to decode
- * @param options Can specify options such as alphabet type to use
- * @return decoded data
- * @throws IllegalArgumentException If bogus characters exist in source data
- */
- private static byte[] decode( byte[] source, int off, int len, int options ) {
-
- // Lots of error checking and exception throwing
- if( source == null ){
- throw new NullPointerException( "Cannot decode null source array." );
- } // end if
- if( off < 0 || off + len > source.length ){
- throw new IllegalArgumentException( String.format(
- "Source array with length %d cannot have offset of %d and process %d bytes.", source.length, off, len ) );
- } // end if
-
- if( len == 0 ){
- return new byte[0];
- }else if( len < 4 ){
- throw new IllegalArgumentException(
- "Base64-encoded string must have at least four characters, but length specified was " + len );
- } // end if
-
- byte[] DECODABET = getDecodabet( options );
-
- int len34 = len * 3 / 4; // Estimate on array size
- byte[] outBuff = new byte[ len34 ]; // Upper limit on size of output
- int outBuffPosn = 0; // Keep track of where we're writing
-
- byte[] b4 = new byte[4]; // Four byte buffer from source, eliminating white space
- int b4Posn = 0; // Keep track of four byte input buffer
- int i = 0; // Source array counter
- byte sbiCrop = 0; // Low seven bits (ASCII) of input
- byte sbiDecode = 0; // Special value from DECODABET
-
- for( i = off; i < off+len; i++ ) { // Loop through source
-
- sbiCrop = (byte)(source[i] & 0x7f); // Only the low seven bits
- sbiDecode = DECODABET[ sbiCrop ]; // Special value
-
- // White space, Equals sign, or legit Base64 character
- // Note the values such as -5 and -9 in the
- // DECODABETs at the top of the file.
- if( sbiDecode >= WHITE_SPACE_ENC ) {
- if( sbiDecode >= EQUALS_SIGN_ENC ) {
- b4[ b4Posn++ ] = sbiCrop; // Save non-whitespace
- if( b4Posn > 3 ) { // Time to decode?
- outBuffPosn += decode4to3( b4, 0, outBuff, outBuffPosn, options );
- b4Posn = 0;
-
- // If that was the equals sign, break out of 'for' loop
- if( sbiCrop == EQUALS_SIGN ) {
- break;
- }
- }
- }
- }
- else {
- // There's a bad input character in the Base64 stream.
- throw new InvalidBase64CharacterException( String.format(
- "Bad Base64 input character '%c' in array position %d", source[i], i ) );
- }
- }
-
- byte[] out = new byte[ outBuffPosn ];
- System.arraycopy( outBuff, 0, out, 0, outBuffPosn );
- return out;
- }
-}
-
-
-class InvalidBase64CharacterException extends IllegalArgumentException {
-
- InvalidBase64CharacterException(String message) {
- super(message);
- }
-}
diff --git a/dist/spring-security-core/org/springframework/security/core/codec/Hex.java b/dist/spring-security-core/org/springframework/security/core/codec/Hex.java
deleted file mode 100644
index d1d3105..0000000
--- a/dist/spring-security-core/org/springframework/security/core/codec/Hex.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.springframework.security.core.codec;
-
-/**
- * Hex data encoder. Converts byte arrays (such as those obtained from message digests)
- * into hexadecimal string representation.
- * <p>
- * For internal use only.
- *
- * @author Luke Taylor
- * @since 3.0
- */
-public final class Hex {
-
- private static final char[] HEX = {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
- };
-
- public static char[] encode(byte[] bytes) {
- final int nBytes = bytes.length;
- char[] result = new char[2*nBytes];
-
- int j = 0;
- for (int i=0; i < nBytes; i++) {
- // Char for top 4 bits
- result[j++] = HEX[(0xF0 & bytes[i]) >>> 4 ];
- // Bottom 4
- result[j++] = HEX[(0x0F & bytes[i])];
- }
-
- return result;
- }
-
-// public static byte[] decode(char[] hex) {
-//
-// }
-}
diff --git a/dist/spring-security-core/org/springframework/security/core/codec/package-info.java b/dist/spring-security-core/org/springframework/security/core/codec/package-info.java
deleted file mode 100644
index b1cfa6a..0000000
--- a/dist/spring-security-core/org/springframework/security/core/codec/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * Internal codec classes. Only intended for use within the framework.
- */
-package org.springframework.security.core.codec;
diff --git a/dist/spring-security-core/org/springframework/security/core/context/InheritableThreadLocalSecurityContextHolderStrategy.java b/dist/spring-security-core/org/springframework/security/core/context/InheritableThreadLocalSecurityContextHolderStrategy.java
index 2f20146..837e51d 100644
--- a/dist/spring-security-core/org/springframework/security/core/context/InheritableThreadLocalSecurityContextHolderStrategy.java
+++ b/dist/spring-security-core/org/springframework/security/core/context/InheritableThreadLocalSecurityContextHolderStrategy.java
@@ -25,7 +25,6 @@ import org.springframework.util.Assert;
* @author Ben Alex
*
* @see java.lang.ThreadLocal
- * @see org.springframework.security.core.context.web.SecurityContextPersistenceFilter
*/
final class InheritableThreadLocalSecurityContextHolderStrategy implements SecurityContextHolderStrategy {
//~ Static fields/initializers =====================================================================================
diff --git a/dist/spring-security-core/org/springframework/security/core/context/SecurityContextImpl.java b/dist/spring-security-core/org/springframework/security/core/context/SecurityContextImpl.java
index e60bdf2..0018fdd 100644
--- a/dist/spring-security-core/org/springframework/security/core/context/SecurityContextImpl.java
+++ b/dist/spring-security-core/org/springframework/security/core/context/SecurityContextImpl.java
@@ -16,6 +16,7 @@
package org.springframework.security.core.context;
import org.springframework.security.core.Authentication;
+import org.springframework.security.core.SpringSecurityCoreVersion;
/**
@@ -26,6 +27,9 @@ import org.springframework.security.core.Authentication;
* @author Ben Alex
*/
public class SecurityContextImpl implements SecurityContext {
+
+ private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
+
//~ Instance fields ================================================================================================
private Authentication authentication;
diff --git a/dist/spring-security-core/org/springframework/security/core/session/SessionDestroyedEvent.java b/dist/spring-security-core/org/springframework/security/core/session/SessionDestroyedEvent.java
index 6b34903..c288cae 100644
--- a/dist/spring-security-core/org/springframework/security/core/session/SessionDestroyedEvent.java
+++ b/dist/spring-security-core/org/springframework/security/core/session/SessionDestroyedEvent.java
@@ -3,6 +3,8 @@ package org.springframework.security.core.session;
import org.springframework.context.ApplicationEvent;
import org.springframework.security.core.context.SecurityContext;
+import java.util.*;
+
/**
* Generic "session termination" event which indicates that a session (potentially
* represented by a security context) has ended.
@@ -17,11 +19,13 @@ public abstract class SessionDestroyedEvent extends ApplicationEvent {
}
/**
- * Provides the <tt>SecurityContext</tt> under which the session was running.
+ * Provides the {@code SecurityContext} instances which were associated with the destroyed session. Usually there
+ * will be only one security context per session.
*
- * @return the <tt>SecurityContext</tt> associated with the session, or null if there is no context.
+ * @return the {@code SecurityContext} instances which were stored in the current session (an empty list if there
+ * are none).
*/
- public abstract SecurityContext getSecurityContext();
+ public abstract List<SecurityContext> getSecurityContexts();
/**
* @return the identifier associated with the destroyed session.
diff --git a/dist/spring-security-core/org/springframework/security/core/session/SessionIdentifierAware.java b/dist/spring-security-core/org/springframework/security/core/session/SessionIdentifierAware.java
index b61f519..18ed0ac 100644
--- a/dist/spring-security-core/org/springframework/security/core/session/SessionIdentifierAware.java
+++ b/dist/spring-security-core/org/springframework/security/core/session/SessionIdentifierAware.java
@@ -22,7 +22,9 @@ package org.springframework.security.core.session;
* Used to extract the session ID from an <code>Authentication</code> object.
*
* @author Ben Alex
+ * @deprecated Legacy of former concurrency control implementation. Will be removed in a future version.
*/
+ at Deprecated
public interface SessionIdentifierAware {
//~ Methods ========================================================================================================
diff --git a/dist/spring-security-core/org/springframework/security/core/session/SessionInformation.java b/dist/spring-security-core/org/springframework/security/core/session/SessionInformation.java
index 9cc142c..496a987 100644
--- a/dist/spring-security-core/org/springframework/security/core/session/SessionInformation.java
+++ b/dist/spring-security-core/org/springframework/security/core/session/SessionInformation.java
@@ -15,6 +15,7 @@
package org.springframework.security.core.session;
+import org.springframework.security.core.SpringSecurityCoreVersion;
import org.springframework.util.Assert;
import java.util.Date;
@@ -35,11 +36,14 @@ import java.io.Serializable;
* @author Ben Alex
*/
public class SessionInformation implements Serializable {
+
+ private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
+
//~ Instance fields ================================================================================================
private Date lastRequest;
- private Object principal;
- private String sessionId;
+ private final Object principal;
+ private final String sessionId;
private boolean expired = false;
//~ Constructors ===================================================================================================
diff --git a/dist/spring-security-core/org/springframework/security/core/session/SessionRegistryImpl.java b/dist/spring-security-core/org/springframework/security/core/session/SessionRegistryImpl.java
index 8d0e330..566b869 100644
--- a/dist/spring-security-core/org/springframework/security/core/session/SessionRegistryImpl.java
+++ b/dist/spring-security-core/org/springframework/security/core/session/SessionRegistryImpl.java
@@ -15,21 +15,16 @@
package org.springframework.security.core.session;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.util.Assert;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CopyOnWriteArraySet;
+
/**
* Default implementation of {@link org.springframework.security.core.session.SessionRegistry SessionRegistry}
* which listens for {@link org.springframework.security.core.session.SessionDestroyedEvent SessionDestroyedEvent}s
@@ -49,14 +44,14 @@ public class SessionRegistryImpl implements SessionRegistry, ApplicationListener
protected final Log logger = LogFactory.getLog(SessionRegistryImpl.class);
/** <principal:Object,SessionIdSet> */
- private final Map<Object,Set<String>> principals = Collections.synchronizedMap(new HashMap<Object,Set<String>>());
+ private final ConcurrentMap<Object,Set<String>> principals = new ConcurrentHashMap<Object,Set<String>>();
/** <sessionId:Object,SessionInformation> */
- private final Map<String, SessionInformation> sessionIds = Collections.synchronizedMap(new HashMap<String, SessionInformation>());
+ private final Map<String, SessionInformation> sessionIds = new ConcurrentHashMap<String, SessionInformation>();
//~ Methods ========================================================================================================
public List<Object> getAllPrincipals() {
- return Arrays.asList(principals.keySet().toArray());
+ return new ArrayList<Object>(principals.keySet());
}
public List<SessionInformation> getAllSessions(Object principal, boolean includeExpiredSessions) {
@@ -68,17 +63,15 @@ public class SessionRegistryImpl implements SessionRegistry, ApplicationListener
List<SessionInformation> list = new ArrayList<SessionInformation>(sessionsUsedByPrincipal.size());
- synchronized (sessionsUsedByPrincipal) {
- for (String sessionId : sessionsUsedByPrincipal) {
- SessionInformation sessionInformation = getSessionInformation(sessionId);
+ for (String sessionId : sessionsUsedByPrincipal) {
+ SessionInformation sessionInformation = getSessionInformation(sessionId);
- if (sessionInformation == null) {
- continue;
- }
+ if (sessionInformation == null) {
+ continue;
+ }
- if (includeExpiredSessions || !sessionInformation.isExpired()) {
- list.add(sessionInformation);
- }
+ if (includeExpiredSessions || !sessionInformation.isExpired()) {
+ list.add(sessionInformation);
}
}
@@ -88,7 +81,7 @@ public class SessionRegistryImpl implements SessionRegistry, ApplicationListener
public SessionInformation getSessionInformation(String sessionId) {
Assert.hasText(sessionId, "SessionId required as per interface contract");
- return (SessionInformation) sessionIds.get(sessionId);
+ return sessionIds.get(sessionId);
}
public void onApplicationEvent(SessionDestroyedEvent event) {
@@ -106,7 +99,7 @@ public class SessionRegistryImpl implements SessionRegistry, ApplicationListener
}
}
- public synchronized void registerNewSession(String sessionId, Object principal) {
+ public void registerNewSession(String sessionId, Object principal) {
Assert.hasText(sessionId, "SessionId required as per interface contract");
Assert.notNull(principal, "Principal required as per interface contract");
@@ -123,8 +116,12 @@ public class SessionRegistryImpl implements SessionRegistry, ApplicationListener
Set<String> sessionsUsedByPrincipal = principals.get(principal);
if (sessionsUsedByPrincipal == null) {
- sessionsUsedByPrincipal = Collections.synchronizedSet(new HashSet<String>(4));
- principals.put(principal, sessionsUsedByPrincipal);
+ sessionsUsedByPrincipal = new CopyOnWriteArraySet<String>();
+ Set<String> prevSessionsUsedByPrincipal = principals.putIfAbsent(principal,
+ sessionsUsedByPrincipal);
+ if (prevSessionsUsedByPrincipal != null) {
+ sessionsUsedByPrincipal = prevSessionsUsedByPrincipal;
+ }
}
sessionsUsedByPrincipal.add(sessionId);
@@ -159,20 +156,19 @@ public class SessionRegistryImpl implements SessionRegistry, ApplicationListener
logger.debug("Removing session " + sessionId + " from principal's set of registered sessions");
}
- synchronized (sessionsUsedByPrincipal) {
- sessionsUsedByPrincipal.remove(sessionId);
+ sessionsUsedByPrincipal.remove(sessionId);
- if (sessionsUsedByPrincipal.size() == 0) {
- // No need to keep object in principals Map anymore
- if (logger.isDebugEnabled()) {
- logger.debug("Removing principal " + info.getPrincipal() + " from registry");
- }
- principals.remove(info.getPrincipal());
+ if (sessionsUsedByPrincipal.isEmpty()) {
+ // No need to keep object in principals Map anymore
+ if (logger.isDebugEnabled()) {
+ logger.debug("Removing principal " + info.getPrincipal() + " from registry");
}
+ principals.remove(info.getPrincipal());
}
if (logger.isTraceEnabled()) {
logger.trace("Sessions used by '" + info.getPrincipal() + "' : " + sessionsUsedByPrincipal);
}
}
+
}
diff --git a/dist/spring-security-core/org/springframework/security/core/token/DefaultToken.java b/dist/spring-security-core/org/springframework/security/core/token/DefaultToken.java
index 6bdd655..6e3e444 100644
--- a/dist/spring-security-core/org/springframework/security/core/token/DefaultToken.java
+++ b/dist/spring-security-core/org/springframework/security/core/token/DefaultToken.java
@@ -11,9 +11,9 @@ import org.springframework.util.Assert;
* @since 2.0.1
*/
public class DefaultToken implements Token {
- private String key;
- private long keyCreationTime;
- private String extendedInformation;
+ private final String key;
+ private final long keyCreationTime;
+ private final String extendedInformation;
public DefaultToken(String key, long keyCreationTime, String extendedInformation) {
Assert.hasText(key, "Key required");
@@ -52,7 +52,7 @@ public class DefaultToken implements Token {
}
public String toString() {
- return "DefaultToken[key=" + new String(key) + "; creation=" + new Date(keyCreationTime) + "; extended=" + extendedInformation + "]";
+ return "DefaultToken[key=" + key + "; creation=" + new Date(keyCreationTime) + "; extended=" + extendedInformation + "]";
}
diff --git a/dist/spring-security-core/org/springframework/security/core/token/KeyBasedPersistenceTokenService.java b/dist/spring-security-core/org/springframework/security/core/token/KeyBasedPersistenceTokenService.java
index 7fe62ad..48f6ba3 100644
--- a/dist/spring-security-core/org/springframework/security/core/token/KeyBasedPersistenceTokenService.java
+++ b/dist/spring-security-core/org/springframework/security/core/token/KeyBasedPersistenceTokenService.java
@@ -1,12 +1,12 @@
package org.springframework.security.core.token;
-import java.io.UnsupportedEncodingException;
import java.security.SecureRandom;
import java.util.Date;
import org.springframework.beans.factory.InitializingBean;
-import org.springframework.security.core.codec.Base64;
-import org.springframework.security.core.codec.Hex;
+import org.springframework.security.crypto.codec.Base64;
+import org.springframework.security.crypto.codec.Hex;
+import org.springframework.security.crypto.codec.Utf8;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -63,12 +63,12 @@ public class KeyBasedPersistenceTokenService implements TokenService, Initializi
long creationTime = new Date().getTime();
String serverSecret = computeServerSecretApplicableAt(creationTime);
String pseudoRandomNumber = generatePseudoRandomNumber();
- String content = new Long(creationTime).toString() + ":" + pseudoRandomNumber + ":" + extendedInformation;
+ String content = Long.toString(creationTime) + ":" + pseudoRandomNumber + ":" + extendedInformation;
// Compute key
String sha512Hex = Sha512DigestUtils.shaHex(content + ":" + serverSecret);
String keyPayload = content + ":" + sha512Hex;
- String key = convertToString(Base64.encode(convertToBytes(keyPayload)));
+ String key = Utf8.decode(Base64.encode(Utf8.encode(keyPayload)));
return new DefaultToken(key, creationTime, extendedInformation);
}
@@ -77,7 +77,7 @@ public class KeyBasedPersistenceTokenService implements TokenService, Initializi
if (key == null || "".equals(key)) {
return null;
}
- String[] tokens = StringUtils.delimitedListToStringArray(convertToString(Base64.decode(convertToBytes(key))), ":");
+ String[] tokens = StringUtils.delimitedListToStringArray(Utf8.decode(Base64.decode(Utf8.encode(key))), ":");
Assert.isTrue(tokens.length >= 4, "Expected 4 or more tokens but found " + tokens.length);
long creationTime;
@@ -102,29 +102,13 @@ public class KeyBasedPersistenceTokenService implements TokenService, Initializi
String sha1Hex = tokens[tokens.length-1];
// Verification
- String content = new Long(creationTime).toString() + ":" + pseudoRandomNumber + ":" + extendedInfo.toString();
+ String content = Long.toString(creationTime) + ":" + pseudoRandomNumber + ":" + extendedInfo.toString();
String expectedSha512Hex = Sha512DigestUtils.shaHex(content + ":" + serverSecret);
Assert.isTrue(expectedSha512Hex.equals(sha1Hex), "Key verification failure");
return new DefaultToken(key, creationTime, extendedInfo.toString());
}
- private byte[] convertToBytes(String input) {
- try {
- return input.getBytes("UTF-8");
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException(e);
- }
- }
-
- private String convertToString(byte[] bytes) {
- try {
- return new String(bytes, "UTF-8");
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
/**
* @return a pseduo random number (hex encoded)
*/
diff --git a/dist/spring-security-core/org/springframework/security/core/token/Sha512DigestUtils.java b/dist/spring-security-core/org/springframework/security/core/token/Sha512DigestUtils.java
index dfd8447..f7fce26 100644
--- a/dist/spring-security-core/org/springframework/security/core/token/Sha512DigestUtils.java
+++ b/dist/spring-security-core/org/springframework/security/core/token/Sha512DigestUtils.java
@@ -3,7 +3,7 @@ package org.springframework.security.core.token;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
-import org.springframework.security.core.codec.Hex;
+import org.springframework.security.crypto.codec.Hex;
/**
* Provides SHA512 digest methods.
@@ -17,29 +17,19 @@ import org.springframework.security.core.codec.Hex;
*
*/
public abstract class Sha512DigestUtils {
- /**
- * Returns a MessageDigest for the given <code>algorithm</code>.
- *
- * @param algorithm The MessageDigest algorithm name.
- * @return An MD5 digest instance.
- * @throws RuntimeException when a {@link java.security.NoSuchAlgorithmException} is caught,
- */
- static MessageDigest getDigest(String algorithm) {
- try {
- return MessageDigest.getInstance(algorithm);
- } catch (NoSuchAlgorithmException e) {
- throw new RuntimeException(e.getMessage());
- }
- }
/**
* Returns an SHA digest.
*
* @return An SHA digest instance.
- * @throws RuntimeException when a {@link java.security.NoSuchAlgorithmException} is caught,
+ * @throws RuntimeException when a {@link java.security.NoSuchAlgorithmException} is caught.
*/
private static MessageDigest getSha512Digest() {
- return getDigest("SHA-512");
+ try {
+ return MessageDigest.getInstance("SHA-512");
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException(e.getMessage());
+ }
}
/**
diff --git a/dist/spring-security-core/org/springframework/security/core/userdetails/AuthenticationUserDetailsService.java b/dist/spring-security-core/org/springframework/security/core/userdetails/AuthenticationUserDetailsService.java
index 56d10d9..db50d58 100644
--- a/dist/spring-security-core/org/springframework/security/core/userdetails/AuthenticationUserDetailsService.java
+++ b/dist/spring-security-core/org/springframework/security/core/userdetails/AuthenticationUserDetailsService.java
@@ -9,7 +9,7 @@ import org.springframework.security.core.Authentication;
* @author Ruud Senden
* @since 2.0
*/
-public interface AuthenticationUserDetailsService {
+public interface AuthenticationUserDetailsService<T extends Authentication> {
/**
*
@@ -19,5 +19,5 @@ public interface AuthenticationUserDetailsService {
* if no user details can be found for the given authentication
* token
*/
- UserDetails loadUserDetails(Authentication token) throws UsernameNotFoundException;
+ UserDetails loadUserDetails(T token) throws UsernameNotFoundException;
}
diff --git a/dist/spring-security-core/org/springframework/security/core/userdetails/User.java b/dist/spring-security-core/org/springframework/security/core/userdetails/User.java
index dd40ac1..7fb1a60 100644
--- a/dist/spring-security-core/org/springframework/security/core/userdetails/User.java
+++ b/dist/spring-security-core/org/springframework/security/core/userdetails/User.java
@@ -16,7 +16,6 @@
package org.springframework.security.core.userdetails;
import java.io.Serializable;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
@@ -26,12 +25,12 @@ import java.util.TreeSet;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.CredentialsContainer;
+import org.springframework.security.core.SpringSecurityCoreVersion;
import org.springframework.util.Assert;
/**
* Models core user information retrieved by a {@link UserDetailsService}.
* <p>
- * Implemented with value object semantics (immutable after construction, like a <code>String</code>).
* Developers may use this class directly, subclass it, or write their own {@link UserDetails} implementation from
* scratch.
* <p>
@@ -39,11 +38,19 @@ import org.springframework.util.Assert;
* intention is that lookups of the same user principal object (in a user registry, for example) will match
* where the objects represent the same user, not just when all the properties (authorities, password for
* example) are the same.
+ * <p>
+ * Note that this implementation is not immutable. It implements the {@code CredentialsContainer} interface, in order
+ * to allow the password to be erased after authentication. This may cause side-effects if you are storing instances
+ * in-memory and reusing them. If so, make sure you return a copy from your {@code UserDetailsService} each time it is
+ * invoked.
*
* @author Ben Alex
* @author Luke Taylor
*/
public class User implements UserDetails, CredentialsContainer {
+
+ private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
+
//~ Instance fields ================================================================================================
private String password;
private final String username;
@@ -56,12 +63,10 @@ public class User implements UserDetails, CredentialsContainer {
//~ Constructors ===================================================================================================
/**
- * @deprecated
+ * Calls the more complex constructor with all boolean arguments set to {@code true}.
*/
- public User(String username, String password, boolean enabled, boolean accountNonExpired,
- boolean credentialsNonExpired, boolean accountNonLocked, GrantedAuthority[] authorities) {
- this(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked,
- authorities == null ? null : Arrays.asList(authorities));
+ public User(String username, String password, Collection<? extends GrantedAuthority> authorities) {
+ this(username, password, true, true, true, true, authorities);
}
/**
@@ -152,6 +157,8 @@ public class User implements UserDetails, CredentialsContainer {
}
private static class AuthorityComparator implements Comparator<GrantedAuthority>, Serializable {
+ private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
+
public int compare(GrantedAuthority g1, GrantedAuthority g2) {
// Neither should ever be null as each entry is checked before adding it to the set.
// If the authority is null, it is a custom authority and should precede others.
diff --git a/dist/spring-security-core/org/springframework/security/core/userdetails/UserDetails.java b/dist/spring-security-core/org/springframework/security/core/userdetails/UserDetails.java
index 689c17d..a91e433 100644
--- a/dist/spring-security-core/org/springframework/security/core/userdetails/UserDetails.java
+++ b/dist/spring-security-core/org/springframework/security/core/userdetails/UserDetails.java
@@ -35,16 +35,7 @@ import java.util.Collection;
* Concrete implementations must take particular care to ensure the non-null
* contract detailed for each method is enforced. See
* {@link org.springframework.security.core.userdetails.User} for a
- * reference implementation (which you might like to extend).
- * <p>
- * Concrete implementations should be preferably be immutable – they should
- * have value object semantics, like a String. The <code>UserDetails</code> may be
- * stored in a cache and multiple threads may use the same instance. Immutable
- * objects are more robust and are guaranteed to be thread-safe. This is not strictly
- * essential (there's nothing within Spring Security itself which absolutely requires it),
- * but if your <tt>UserDetails</tt> object <em>can</em> be modified then it's up to you to make
- * sure that you do so safely and that you manage any caches which may contain copies of
- * the object.
+ * reference implementation (which you might like to extend or use in your code).
*
* @see UserDetailsService
* @see UserCache
@@ -59,7 +50,7 @@ public interface UserDetails extends Serializable {
*
* @return the authorities, sorted by natural key (never <code>null</code>)
*/
- Collection<GrantedAuthority> getAuthorities();
+ Collection<? extends GrantedAuthority> getAuthorities();
/**
* Returns the password used to authenticate the user. Cannot return <code>null</code>.
diff --git a/dist/spring-security-core/org/springframework/security/core/userdetails/UserDetailsByNameServiceWrapper.java b/dist/spring-security-core/org/springframework/security/core/userdetails/UserDetailsByNameServiceWrapper.java
index 44118df..6410edd 100644
--- a/dist/spring-security-core/org/springframework/security/core/userdetails/UserDetailsByNameServiceWrapper.java
+++ b/dist/spring-security-core/org/springframework/security/core/userdetails/UserDetailsByNameServiceWrapper.java
@@ -1,8 +1,7 @@
package org.springframework.security.core.userdetails;
-import org.springframework.security.core.Authentication;
import org.springframework.beans.factory.InitializingBean;
-import org.springframework.dao.DataAccessException;
+import org.springframework.security.core.Authentication;
import org.springframework.util.Assert;
/**
@@ -14,7 +13,7 @@ import org.springframework.util.Assert;
* @author Scott Battaglia
* @since 2.0
*/
-public class UserDetailsByNameServiceWrapper implements AuthenticationUserDetailsService, InitializingBean {
+public class UserDetailsByNameServiceWrapper<T extends Authentication> implements AuthenticationUserDetailsService<T>, InitializingBean {
private UserDetailsService userDetailsService = null;
/**
@@ -48,8 +47,7 @@ public class UserDetailsByNameServiceWrapper implements AuthenticationUserDetail
* Get the UserDetails object from the wrapped UserDetailsService
* implementation
*/
- public UserDetails loadUserDetails(Authentication authentication) throws UsernameNotFoundException,
- DataAccessException {
+ public UserDetails loadUserDetails(T authentication) throws UsernameNotFoundException {
return this.userDetailsService.loadUserByUsername(authentication.getName());
}
diff --git a/dist/spring-security-core/org/springframework/security/core/userdetails/UserDetailsService.java b/dist/spring-security-core/org/springframework/security/core/userdetails/UserDetailsService.java
index b16c1c5..bdab2b8 100644
--- a/dist/spring-security-core/org/springframework/security/core/userdetails/UserDetailsService.java
+++ b/dist/spring-security-core/org/springframework/security/core/userdetails/UserDetailsService.java
@@ -15,8 +15,6 @@
package org.springframework.security.core.userdetails;
-import org.springframework.dao.DataAccessException;
-
/**
* Core interface which loads user-specific data.
@@ -46,8 +44,6 @@ public interface UserDetailsService {
* @return a fully populated user record (never <code>null</code>)
*
* @throws UsernameNotFoundException if the user could not be found or the user has no GrantedAuthority
- * @throws DataAccessException if user could not be found for a repository-specific reason
*/
- UserDetails loadUserByUsername(String username)
- throws UsernameNotFoundException, DataAccessException;
+ UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}
diff --git a/dist/spring-security-core/org/springframework/security/core/userdetails/UsernameNotFoundException.java b/dist/spring-security-core/org/springframework/security/core/userdetails/UsernameNotFoundException.java
index 30080cb..b2fd117 100644
--- a/dist/spring-security-core/org/springframework/security/core/userdetails/UsernameNotFoundException.java
+++ b/dist/spring-security-core/org/springframework/security/core/userdetails/UsernameNotFoundException.java
@@ -37,19 +37,19 @@ public class UsernameNotFoundException extends AuthenticationException {
}
/**
- * Constructs a <code>UsernameNotFoundException</code>, making use of the <tt>extraInformation</tt>
+ * Constructs a {@code UsernameNotFoundException}, making use of the {@code extraInformation}
* property of the superclass.
*
* @param msg the detail message
* @param extraInformation additional information such as the username.
*/
+ @Deprecated
public UsernameNotFoundException(String msg, Object extraInformation) {
super(msg, extraInformation);
}
/**
- * Constructs a <code>UsernameNotFoundException</code> with the specified
- * message and root cause.
+ * Constructs a {@code UsernameNotFoundException} with the specified message and root cause.
*
* @param msg the detail message.
* @param t root cause
diff --git a/dist/spring-security-core/org/springframework/security/core/userdetails/cache/EhCacheBasedUserCache.java b/dist/spring-security-core/org/springframework/security/core/userdetails/cache/EhCacheBasedUserCache.java
index 7c729ab..9b76035 100644
--- a/dist/spring-security-core/org/springframework/security/core/userdetails/cache/EhCacheBasedUserCache.java
+++ b/dist/spring-security-core/org/springframework/security/core/userdetails/cache/EhCacheBasedUserCache.java
@@ -15,21 +15,14 @@
package org.springframework.security.core.userdetails.cache;
-import net.sf.ehcache.CacheException;
-import net.sf.ehcache.Element;
import net.sf.ehcache.Ehcache;
-
-
-import org.springframework.security.core.userdetails.UserCache;
-import org.springframework.security.core.userdetails.UserDetails;
+import net.sf.ehcache.Element;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-
import org.springframework.beans.factory.InitializingBean;
-
-import org.springframework.dao.DataRetrievalFailureException;
-
+import org.springframework.security.core.userdetails.UserCache;
+import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.Assert;
@@ -59,13 +52,7 @@ public class EhCacheBasedUserCache implements UserCache, InitializingBean {
}
public UserDetails getUserFromCache(String username) {
- Element element = null;
-
- try {
- element = cache.get(username);
- } catch (CacheException cacheException) {
- throw new DataRetrievalFailureException("Cache failure: " + cacheException.getMessage());
- }
+ Element element = cache.get(username);
if (logger.isDebugEnabled()) {
logger.debug("Cache hit: " + (element != null) + "; username: " + username);
diff --git a/dist/spring-security-core/org/springframework/security/core/userdetails/jdbc/JdbcDaoImpl.java b/dist/spring-security-core/org/springframework/security/core/userdetails/jdbc/JdbcDaoImpl.java
index 11ad260..aff4939 100644
--- a/dist/spring-security-core/org/springframework/security/core/userdetails/jdbc/JdbcDaoImpl.java
+++ b/dist/spring-security-core/org/springframework/security/core/userdetails/jdbc/JdbcDaoImpl.java
@@ -24,13 +24,12 @@ import java.util.Set;
import org.springframework.context.ApplicationContextException;
import org.springframework.context.support.MessageSourceAccessor;
-import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.SpringSecurityMessageSource;
import org.springframework.security.core.authority.AuthorityUtils;
-import org.springframework.security.core.authority.GrantedAuthorityImpl;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
@@ -111,7 +110,7 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements UserDetailsService {
//~ Instance fields ================================================================================================
- protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
+ protected final MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
private String authoritiesByUsernameQuery;
private String groupAuthoritiesByUsernameQuery;
@@ -148,7 +147,7 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements UserDetailsService {
Assert.isTrue(enableAuthorities || enableGroups, "Use of either authorities or groups must be enabled");
}
- public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
+ public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
List<UserDetails> users = loadUsersByUsername(username);
if (users.size() == 0) {
@@ -210,9 +209,8 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements UserDetailsService {
return getJdbcTemplate().query(authoritiesByUsernameQuery, new String[] {username}, new RowMapper<GrantedAuthority>() {
public GrantedAuthority mapRow(ResultSet rs, int rowNum) throws SQLException {
String roleName = rolePrefix + rs.getString(2);
- GrantedAuthorityImpl authority = new GrantedAuthorityImpl(roleName);
- return authority;
+ return new SimpleGrantedAuthority(roleName);
}
});
}
@@ -226,9 +224,8 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements UserDetailsService {
return getJdbcTemplate().query(groupAuthoritiesByUsernameQuery, new String[] {username}, new RowMapper<GrantedAuthority>() {
public GrantedAuthority mapRow(ResultSet rs, int rowNum) throws SQLException {
String roleName = getRolePrefix() + rs.getString(3);
- GrantedAuthorityImpl authority = new GrantedAuthorityImpl(roleName);
- return authority;
+ return new SimpleGrantedAuthority(roleName);
}
});
}
diff --git a/dist/spring-security-core/org/springframework/security/core/userdetails/memory/InMemoryDaoImpl.java b/dist/spring-security-core/org/springframework/security/core/userdetails/memory/InMemoryDaoImpl.java
index 6fcb545..b4a8ad3 100644
--- a/dist/spring-security-core/org/springframework/security/core/userdetails/memory/InMemoryDaoImpl.java
+++ b/dist/spring-security-core/org/springframework/security/core/userdetails/memory/InMemoryDaoImpl.java
@@ -21,22 +21,18 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.beans.factory.InitializingBean;
-import org.springframework.dao.DataAccessException;
-
import org.springframework.util.Assert;
import java.util.Properties;
/**
- * Retrieves user details from an in-memory list created in the application context.
- * <p>
- * Username lookups are case-insensitive.
+ * Retrieves user details from an in-memory list created by the bean context.
*
* @author Ben Alex
- * @author Luke Taylor
+ * @deprecated Use InMemoryUserDetailsManager instead (or write your own implementation)
*/
- at SuppressWarnings("deprecation")
+ at Deprecated
public class InMemoryDaoImpl implements UserDetailsService, InitializingBean {
//~ Instance fields ================================================================================================
@@ -53,8 +49,7 @@ public class InMemoryDaoImpl implements UserDetailsService, InitializingBean {
return userMap;
}
- public UserDetails loadUserByUsername(String username)
- throws UsernameNotFoundException, DataAccessException {
+ public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return userMap.getUser(username);
}
diff --git a/dist/spring-security-core/org/springframework/security/core/userdetails/memory/UserAttribute.java b/dist/spring-security-core/org/springframework/security/core/userdetails/memory/UserAttribute.java
index 3f67100..88e7569 100644
--- a/dist/spring-security-core/org/springframework/security/core/userdetails/memory/UserAttribute.java
+++ b/dist/spring-security-core/org/springframework/security/core/userdetails/memory/UserAttribute.java
@@ -20,7 +20,7 @@ import java.util.List;
import java.util.Vector;
import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.authority.GrantedAuthorityImpl;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
/**
@@ -65,7 +65,7 @@ public class UserAttribute {
public void setAuthoritiesAsString(List<String> authoritiesAsStrings) {
setAuthorities(new ArrayList<GrantedAuthority>(authoritiesAsStrings.size()));
for(String authority : authoritiesAsStrings) {
- addAuthority(new GrantedAuthorityImpl(authority));
+ addAuthority(new SimpleGrantedAuthority(authority));
}
}
diff --git a/dist/spring-security-core/org/springframework/security/core/userdetails/memory/UserMap.java b/dist/spring-security-core/org/springframework/security/core/userdetails/memory/UserMap.java
index b791549..77092e3 100644
--- a/dist/spring-security-core/org/springframework/security/core/userdetails/memory/UserMap.java
+++ b/dist/spring-security-core/org/springframework/security/core/userdetails/memory/UserMap.java
@@ -18,15 +18,18 @@ package org.springframework.security.core.userdetails.memory;
import java.util.HashMap;
import java.util.Map;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.util.Assert;
/**
* Used by {@link InMemoryDaoImpl} to store a list of users and their corresponding granted authorities.
+ * <p>
+ * Usernames are used as the lookup key and are stored in lower case, to allow case-insensitive lookups. So this class
+ * should not be used if usernames need to be case-sensitive.
*
* @author Ben Alex
* @deprecated Use a plain map instead
@@ -39,7 +42,7 @@ public class UserMap {
//~ Instance fields ================================================================================================
- private Map<String, UserDetails> userMap = new HashMap<String, UserDetails>();
+ private final Map<String, UserDetails> userMap = new HashMap<String, UserDetails>();
//~ Methods ========================================================================================================
@@ -92,6 +95,9 @@ public class UserMap {
* @since 1.1
*/
public void setUsers(Map<String, UserDetails> users) {
- this.userMap = users;
+ userMap.clear();
+ for (Map.Entry<String, UserDetails> entry : users.entrySet()) {
+ userMap.put(entry.getKey().toLowerCase(), entry.getValue());
+ }
}
}
diff --git a/dist/spring-security-core/org/springframework/security/core/userdetails/memory/UserMapEditor.java b/dist/spring-security-core/org/springframework/security/core/userdetails/memory/UserMapEditor.java
index ce1873e..25c42b3 100644
--- a/dist/spring-security-core/org/springframework/security/core/userdetails/memory/UserMapEditor.java
+++ b/dist/spring-security-core/org/springframework/security/core/userdetails/memory/UserMapEditor.java
@@ -41,7 +41,7 @@ import java.util.Properties;
*
* @author Ben Alex
*/
- at SuppressWarnings("deprecation")
+ at Deprecated
public class UserMapEditor extends PropertyEditorSupport {
//~ Methods ========================================================================================================
@@ -49,8 +49,8 @@ public class UserMapEditor extends PropertyEditorSupport {
// Now we have properties, process each one individually
UserAttributeEditor configAttribEd = new UserAttributeEditor();
- for (Iterator<?> iter = props.keySet().iterator(); iter.hasNext();) {
- String username = (String) iter.next();
+ for (Object o : props.keySet()) {
+ String username = (String) o;
String value = props.getProperty(username);
// Convert value to a password, enabled setting, and list of granted authorities
diff --git a/dist/spring-security-core/org/springframework/security/messages.properties b/dist/spring-security-core/org/springframework/security/messages.properties
deleted file mode 100644
index 26fd15b..0000000
--- a/dist/spring-security-core/org/springframework/security/messages.properties
+++ /dev/null
@@ -1,54 +0,0 @@
-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
-JdbcDaoImpl.notFound=User {0} not found
-JdbcDaoImpl.noAuthority=User {0} has no GrantedAuthority
-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
-LdapAuthenticationProvider.emptyUsername=Empty username not allowed
-LdapAuthenticationProvider.emptyPassword=Bad credentials
-DefaultIntitalDirContextFactory.communicationFailure=Unable to connect to LDAP server
-DefaultIntitalDirContextFactory.badCredentials=Bad credentials
-DefaultIntitalDirContextFactory.unexpectedException=Failed to obtain InitialDirContext due to unexpected exception
-PasswordComparisonAuthenticator.badCredentials=Bad credentials
-BindAuthenticator.badCredentials=Bad credentials
-BindAuthenticator.failedToLoadAttributes=Bad credentials
-UserDetailsService.locked=User account is locked
-UserDetailsService.disabled=User is disabled
-UserDetailsService.expired=User account has expired
-UserDetailsService.credentialsExpired=User credentials have expired
-
diff --git a/dist/spring-security-core/org/springframework/security/messages_cs_CZ.properties b/dist/spring-security-core/org/springframework/security/messages_cs_CZ.properties
deleted file mode 100644
index b29fdff..0000000
--- a/dist/spring-security-core/org/springframework/security/messages_cs_CZ.properties
+++ /dev/null
@@ -1,47 +0,0 @@
-AuthByAdapterProvider.incorrectKey=Pou\u017eit\u00e1 implementace AuthByAdapter neobsahuje o\u010dek\u00e1van\u00fd kl\u00ed\u010d
-BasicAclEntryAfterInvocationProvider.noPermission=Autentizovan\u00fd u\u017eivatel {0} nem\u00e1 \u017d\u00c1DN\u00c1 pr\u00e1va k objektu {1}
-BasicAclEntryAfterInvocationProvider.insufficientPermission=Autentizovan\u00fd u\u017eivatel {0} nem\u00e1 po\u017eadovan\u00e1 opr\u00e1vn\u011bn\u00ed k objektu {1}
-ConcurrentSessionControllerImpl.exceededAllowed=Maxim\u00e1ln\u00ed po\u010det sou\u010dasn\u00fdch p\u0159ihl\u00e1\u0161en\u00ed {0} tohoto u\u017eivatele je p\u0159ekro\u010den.
-ProviderManager.providerNotFound=Nebyl nalezen \u017e\u00e1dn\u00fd AuthenticationProvider pro {0}
-AnonymousAuthenticationProvider.incorrectKey=Pou\u017eit\u00fd AnonymousAuthenticationToken neobsahuje o\u010dek\u00e1van\u00fd kl\u00ed\u010d
-CasAuthenticationProvider.incorrectKey=Pou\u017eit\u00fd CasAuthenticationToken neobsahuje o\u010dek\u00e1van\u00fd kl\u00ed\u010d
-CasAuthenticationProvider.noServiceTicket=Nepoda\u0159ilo se z\u00edskat otisk CAS (centr\u00e1ln\u00ed autentiza\u010dn\u00ed autority) k ov\u011b\u0159en\u00ed autenticity u\u017eivatele.
-NamedCasProxyDecider.untrusted=Nelze v\u011b\u0159it nejbli\u017e\u0161\u00ed proxy {0}
-RejectProxyTickets.reject=Otisky proxy jsou odm\u00edtnuty
-AbstractSecurityInterceptor.authenticationNotFound=Nebyl nalezen \u017e\u00e1dn\u00fd Authentication objekt v SecurityContext
-AbstractUserDetailsAuthenticationProvider.onlySupports=Je podporov\u00e1n pouze UsernamePasswordAuthenticationToken
-AbstractUserDetailsAuthenticationProvider.locked=U\u017eivatelsk\u00fd \u00fa\u010det je uzam\u010den
-AbstractUserDetailsAuthenticationProvider.disabled=U\u017eivatelsk\u00fd \u00fa\u010det nen\u00ed aktivn\u00ed
-AbstractUserDetailsAuthenticationProvider.expired=Platnost u\u017eivatelsk\u00e9ho \u00fa\u010dtu vypr\u0161ela
-AbstractUserDetailsAuthenticationProvider.credentialsExpired=Platnost u\u017eivatelsk\u00e9ho hesla vypr\u0161ela
-AbstractUserDetailsAuthenticationProvider.badCredentials=\u0160patn\u00e9 p\u0159ihla\u0161ovac\u00ed \u00fadaje
-X509AuthenticationProvider.certificateNull=Certifik\u00e1t je pr\u00e1zdn\u00fd
-DaoX509AuthoritiesPopulator.noMatching=V subjectDN nebyl nalezen \u017e\u00e1dn\u00fd \u0159et\u011bzec odpov\u00eddaj\u00edc\u00ed vy\u017eadovan\u00e9 masce: {0}
-RememberMeAuthenticationProvider.incorrectKey=Pou\u017eit\u00fd RememberMeAuthenticationToken neobsahuje o\u010dek\u00e1van\u00fd kl\u00ed\u010d
-RunAsImplAuthenticationProvider.incorrectKey=Pou\u017eit\u00fd RunAsUserToken neobsahuje o\u010dek\u00e1van\u00fd kl\u00ed\u010d
-DigestProcessingFilter.missingMandatory=Chyb\u00ed povinn\u00e1 kl\u00ed\u010dov\u00e1 polo\u017eka; p\u0159ijat\u00e1 hlavi\u010dka {0}
-DigestProcessingFilter.missingAuth=Chyb\u00ed povinn\u00e1 kl\u00ed\u010dov\u00e1 polo\u017eka 'auth' QOP (\u00farove\u0148 bezpe\u010dnosti RFC 2617); p\u0159ijat\u00e1 hlavi\u010dka {0}
-DigestProcessingFilter.incorrectRealm=Oblast odpov\u011bdi {0} neodpov\u00edd\u00e1 syst\u00e9mov\u00e9 oblasti {1}
-DigestProcessingFilter.nonceExpired=Kryptovan\u00fd kl\u00ed\u010d (nonce) vypr\u0161el
-DigestProcessingFilter.nonceEncoding=Kryptovan\u00fd kl\u00ed\u010d (nonce) nen\u00ed p\u0159ek\u00e9dov\u00e1n do Base60; p\u0159ijat\u00fd kl\u00ed\u010d {0}
-DigestProcessingFilter.nonceNotTwoTokens=Kryptovan\u00fd kl\u00ed\u010d (nonce) by m\u011bl b\u00fdt slo\u017een ze dvou \u010d\u00e1st\u00ed {0}
-DigestProcessingFilter.nonceNotNumeric=Kryptovan\u00fd kl\u00ed\u010d (nonce) by m\u011bl m\u00edt prvn\u00ed \u010d\u00e1st \u010d\u00edselnou, ale je {0}
-DigestProcessingFilter.nonceCompromised=Kryptovan\u00fd kl\u00ed\u010d (nonce) je znehodnocen\u00fd {0}
-DigestProcessingFilter.usernameNotFound=U\u017eivatelsk\u00e9 jm\u00e9no {0} nebylo nalezeno
-DigestProcessingFilter.incorrectResponse=Vadn\u00e1 odpov\u011b\u010f
-SwitchUserProcessingFilter.noCurrentUser=\u017d\u00e1dn\u00fd u\u017eivatel nen\u00ed asociov\u00e1n s t\u00edmto po\u017eadavkem
-SwitchUserProcessingFilter.noOriginalAuthentication=Nepoda\u0159ilo se nal\u00e9zt p\u016fvodn\u00ed Authentication objekt
-SwitchUserProcessingFilter.usernameNotFound=U\u017eivatelsk\u00e9 jm\u00e9no {0} nebylo nalezeno
-SwitchUserProcessingFilter.locked=U\u017eivatelsk\u00fd \u00fa\u010det je uzam\u010den
-SwitchUserProcessingFilter.disabled=U\u017eivatelsk\u00fd \u00fa\u010det nen\u00ed aktivn\u00ed
-SwitchUserProcessingFilter.expired=Platnost u\u017eivatelsk\u00e9ho \u00fa\u010dtu vypr\u0161ela
-SwitchUserProcessingFilter.credentialsExpired=Platnost u\u017eivatelsk\u00e9ho hesla vypr\u0161ela
-AbstractAccessDecisionManager.accessDenied=P\u0159\u00edstup odep\u0159en
-LdapAuthenticationProvider.emptyUsername=Nen\u00ed povoleno pr\u00e1zdn\u00e9 u\u017eivatelsk\u00e9 jm\u00e9no
-LdapAuthenticationProvider.emptyPassword=\u0160patn\u00e9 p\u0159ihla\u0161ovac\u00ed \u00fadaje
-DefaultIntitalDirContextFactory.communicationFailure=Nen\u00ed mo\u017en\u00e9 se p\u0159ipojit k LDAP serveru
-DefaultIntitalDirContextFactory.badCredentials=\u0160patn\u00e9 p\u0159ihla\u0161ovac\u00ed \u00fadaje
-DefaultIntitalDirContextFactory.unexpectedException=Nepoda\u0159ilo se z\u00edskat InitialDirContext d\u00edky neo\u010dek\u00e1van\u00e9 vyj\u00edmce
-PasswordComparisonAuthenticator.badCredentials=\u0160patn\u00e9 p\u0159ihla\u0161ovac\u00ed \u00fadaje
-BindAuthenticator.badCredentials=\u0160patn\u00e9 p\u0159ihla\u0161ovac\u00ed \u00fadaje
-BindAuthenticator.failedToLoadAttributes=\u0160patn\u00e9 p\u0159ihla\u0161ovac\u00ed \u00fadaje
diff --git a/dist/spring-security-core/org/springframework/security/messages_de.properties b/dist/spring-security-core/org/springframework/security/messages_de.properties
deleted file mode 100644
index 1d2effd..0000000
--- a/dist/spring-security-core/org/springframework/security/messages_de.properties
+++ /dev/null
@@ -1,48 +0,0 @@
-AuthByAdapterProvider.incorrectKey=Die angegebene AuthByAdapter-Implementierung enthält nicht den erwarteten Schlüssel
-BasicAclEntryAfterInvocationProvider.noPermission=Authentifikation {0} hat KEINE Berechtigungen bezüglich des Domänen-Objekts {1}
-BasicAclEntryAfterInvocationProvider.insufficientPermission=Authentifikation {0} hat keine ausreichenden ACL-Berechtigungen bezüglich des Domänen-Objekts {1}
-ConcurrentSessionControllerImpl.exceededAllowed=Die maximale Sitzungs-Anzahl von {0} für diesen Nutzer wurde überschritten
-ProviderManager.providerNotFound=Für {0} wurde kein AuthenticationProvider gefunden
-AnonymousAuthenticationProvider.incorrectKey=Das angegebene AnonymousAuthenticationToken enthält nicht den erwarteten Schlüssel
-CasAuthenticationProvider.incorrectKey=Das angegebene CasAuthenticationToken enthält nicht den erwarteten Schlüssel
-CasAuthenticationProvider.noServiceTicket=Es konnte kein CAS Service-Ticket zur Prüfung geliefert werden
-NamedCasProxyDecider.untrusted=Der nächste Proxy {0} ist nicht vertrauenswürdig
-RejectProxyTickets.reject=Proxy-Tickets sind abgelehnt
-AbstractSecurityInterceptor.authenticationNotFound=Im SecurityContext wurde keine Authentifikation gefunden
-AbstractUserDetailsAuthenticationProvider.onlySupports=Nur UsernamePasswordAuthenticationToken wird unterstützt
-AbstractUserDetailsAuthenticationProvider.locked=Das Benutzerkonto ist gesperrt
-AbstractUserDetailsAuthenticationProvider.disabled=Der Benutzer ist deaktiviert
-AbstractUserDetailsAuthenticationProvider.expired=Die Gültigkeit des Benutzerkontos ist abgelaufen
-AbstractUserDetailsAuthenticationProvider.credentialsExpired=Die Gültigkeit der Benutzerberechtigungen ist abgelaufen
-AbstractUserDetailsAuthenticationProvider.badCredentials=Ungültige Benutzerberechtigungen
-X509AuthenticationProvider.certificateNull=Zertifikat ist nicht gesetzt
-DaoX509AuthoritiesPopulator.noMatching=Kein passendes Muster gefunden in subjectDN: {0}
-RememberMeAuthenticationProvider.incorrectKey=Das angegebene RememberMeAuthenticationToken enthält nicht den erwarteten Schlüssel
-RunAsImplAuthenticationProvider.incorrectKey=Das angegebene RunAsUserToken enthält nicht den erwarteten Schlüssel
-DigestProcessingFilter.missingMandatory=Erforderlicher Digest-Wert fehlt; Empfangener Header {0}
-DigestProcessingFilter.missingAuth=Erforderlicher Digest-Wert fehlt für 'auth' QOP; Empfangener Header {0}
-DigestProcessingFilter.incorrectRealm=Realm-Name in Antwort {0} entspricht nicht dem Namen des System-Realms {1}
-DigestProcessingFilter.nonceExpired=Die Nonce ist nicht mehr gültig
-DigestProcessingFilter.nonceEncoding=Die Nonce ist nicht in Base64 kodiert; Empfangene Nonce {0}
-DigestProcessingFilter.nonceNotTwoTokens=Nonce sollte zwei Elemente beinhalten. Gefundener Inhalt: {0}
-DigestProcessingFilter.nonceNotNumeric=Das erste Element der Nonce sollte numerisch sein. Gefundener Inhalt: {0}
-DigestProcessingFilter.nonceCompromised=Das Nonce-Element ist kompromittiert {0}
-DigestProcessingFilter.usernameNotFound=Benutzername {0} wurde nicht gefunden
-DigestProcessingFilter.incorrectResponse=Fehlerhafte Antwort
-SwitchUserProcessingFilter.noCurrentUser=Mit dieser Anfrage ist kein aktueller Benutzer assoziiert
-SwitchUserProcessingFilter.noOriginalAuthentication=Kann das ursprüngliche Authentifikationsobjekt nicht finden
-SwitchUserProcessingFilter.usernameNotFound=Benutzername {0} wurde nicht gefunden
-SwitchUserProcessingFilter.locked=Das Benutzerkonto ist gesperrt
-SwitchUserProcessingFilter.disabled=Der Benutzer ist deaktiviert
-SwitchUserProcessingFilter.expired=Die Gültigkeit des Benutzerkontos ist abgelaufen
-SwitchUserProcessingFilter.credentialsExpired=Die Gültigkeit der Benutzerberechtigungen ist abgelaufen
-AbstractAccessDecisionManager.accessDenied=Zugriff verweigert
-LdapAuthenticationProvider.emptyUsername=Ein leerer Benutzername ist nicht erlaubt
-LdapAuthenticationProvider.emptyPassword=Ungültige Benutzerberechtigungen
-DefaultIntitalDirContextFactory.communicationFailure=Kann keine Verbindung zum LDAP-Server herstellen
-DefaultIntitalDirContextFactory.badCredentials=Ungültige Benutzerberechtigungen
-DefaultIntitalDirContextFactory.unexpectedException=Auf den InitialDirContext kann aufgrund eines unerwarteten Fehlers nicht zugegriffen werden
-PasswordComparisonAuthenticator.badCredentials=Ungültige Benutzerberechtigungen
-BindAuthenticator.badCredentials=Ungültige Benutzerberechtigungen
-BindAuthenticator.failedToLoadAttributes=Ungültige Benutzerberechtigungen
-
diff --git a/dist/spring-security-core/org/springframework/security/messages_es_ES.properties b/dist/spring-security-core/org/springframework/security/messages_es_ES.properties
deleted file mode 100644
index 13aec13..0000000
--- a/dist/spring-security-core/org/springframework/security/messages_es_ES.properties
+++ /dev/null
@@ -1,53 +0,0 @@
-AuthByAdapterProvider.incorrectKey=La actual implementación de AuthByAdapter no contiene la clave esperada
-BasicAclEntryAfterInvocationProvider.noPermission=Authentication {0} NO tiene permisos para el objeto de dominio {1}
-BasicAclEntryAfterInvocationProvider.insufficientPermission=Authentication {0} tiene permisos ACL para objeto de dominio, pero no los permisos ACL requeridos para el objeto de dominio {1}
-ConcurrentSessionControllerImpl.exceededAllowed=Sesiones máximas de {0} para esta Identificación excedidas
-ProviderManager.providerNotFound=AuthenticationProvider no encontrado para {0}
-AnonymousAuthenticationProvider.incorrectKey=El actual AnonymousAuthenticationToken no contiene la clave esperada
-CasAuthenticationProvider.incorrectKey=El actual CasAuthenticationToken no contiene la clave esperada
-CasAuthenticationProvider.noServiceTicket=No se ha podido proporcionar un billete de servicio CAS para validar
-NamedCasProxyDecider.untrusted=El proxy más cercano {0} no es confiable
-RejectProxyTickets.reject=Las entradas del proxy han sido rechazadas
-AbstractSecurityInterceptor.authenticationNotFound=El objeto Authentication no ha sido encontrado en el SecurityContext
-AbstractUserDetailsAuthenticationProvider.onlySupports=Sólo UsernamePasswordAuthenticationToken es soportada
-AbstractUserDetailsAuthenticationProvider.locked=La cuenta del usuario está bloqueada
-AbstractUserDetailsAuthenticationProvider.disabled=El usuario está deshabilitado
-AbstractUserDetailsAuthenticationProvider.expired=La cuenta del usuario ha expirado
-AbstractUserDetailsAuthenticationProvider.credentialsExpired=Las credenciales del usuario han expirado
-AbstractUserDetailsAuthenticationProvider.badCredentials=Credenciales erróneas
-X509AuthenticationProvider.certificateNull=Cerfificado nulo
-DaoX509AuthoritiesPopulator.noMatching=No se ha encontrado un patrón coincidente en subjectDN: {0}
-RememberMeAuthenticationProvider.incorrectKey=El actual RememberMeAuthenticationToken no contiene la clave esperada
-RunAsImplAuthenticationProvider.incorrectKey=El actual RunAsUserToken no contiene la clave esperada
-DigestProcessingFilter.missingMandatory=Valor digest obligatorio perdido; header recibido {0}
-DigestProcessingFilter.missingAuth=Valor digest obligatorio perdido para 'auth' QOP; header recibido {0}
-DigestProcessingFilter.incorrectRealm=Respuesta realm de nombre {0} no coincide con realm del sistema de nombre {1}
-DigestProcessingFilter.nonceExpired=Nonce ha expirado/fuera de tiempo
-DigestProcessingFilter.nonceEncoding=Nonce no está codificado en Base64; nonce recibido {0}
-DigestProcessingFilter.nonceNotTwoTokens=Nonce token debería tener dos fichas pero tenía {0}
-DigestProcessingFilter.nonceNotNumeric=Nonce token debería tener primero un token numérico, pero tenía {0}
-DigestProcessingFilter.nonceCompromised=Nonce token comprometido {0}
-DigestProcessingFilter.usernameNotFound=Usuario y nombre {0} no encontrado
-DigestProcessingFilter.incorrectResponse=Respuesta incorrecta
-JdbcDaoImpl.notFound=Usuario {0} no encontrado
-JdbcDaoImpl.noAuthority=Usuario {0} no tiene GrantedAuthority
-SwitchUserProcessingFilter.noCurrentUser=No hay usuario actual asociado con esta petición
-SwitchUserProcessingFilter.noOriginalAuthentication=No se puede encontrar el objeto Authentication original
-SwitchUserProcessingFilter.usernameNotFound=Usuario y nombre {0} no encontrado
-SwitchUserProcessingFilter.locked=La cuenta del usuario está bloqueada
-SwitchUserProcessingFilter.disabled=El usuario está deshabilitado
-SwitchUserProcessingFilter.expired=La cuenta del usuario ha expirado
-SwitchUserProcessingFilter.credentialsExpired=Las credenciales del usuario han expirado
-AbstractAccessDecisionManager.accessDenied=Acceso denegado
-LdapAuthenticationProvider.emptyUsername=Usuario y nombre no permitido
-LdapAuthenticationProvider.emptyPassword=Credenciales erróneas
-DefaultIntitalDirContextFactory.communicationFailure=No se puede conectar con el servidor LDAP
-DefaultIntitalDirContextFactory.badCredentials=Credenciales erróneas
-DefaultIntitalDirContextFactory.unexpectedException=Error al obtener el InitialDirContext debido a una excepción inesperada
-PasswordComparisonAuthenticator.badCredentials=Credenciales erróneas
-BindAuthenticator.badCredentials=Credenciales erróneas
-BindAuthenticator.failedToLoadAttributes=Credenciales erróneas
-UserDetailsService.locked=La cuenta del usuario está bloqueada
-UserDetailsService.disabled=El usuario está deshabilitado
-UserDetailsService.expired=La cuenta del usuario ha expirado
-UserDetailsService.credentialsExpired=Las credenciales del usuario han expirado
\ No newline at end of file
diff --git a/dist/spring-security-core/org/springframework/security/messages_fr.properties b/dist/spring-security-core/org/springframework/security/messages_fr.properties
deleted file mode 100644
index bd8dfe1..0000000
--- a/dist/spring-security-core/org/springframework/security/messages_fr.properties
+++ /dev/null
@@ -1,58 +0,0 @@
-# Spring security
-# Messages in French
-# Translation by Laurent Pireyn (laurent.pireyn at pisolutions.eu)
-# Translation by Valentin Crettaz (valentin.crettaz at consulthys.com)
-
-AuthByAdapterProvider.incorrectKey=L'implémentation de AuthByAdapter présentée ne contient pas la clé attendue
-BasicAclEntryAfterInvocationProvider.noPermission=L'authentification {0} n'a AUCUNE permission pour l'objet de domaine {1}
-BasicAclEntryAfterInvocationProvider.insufficientPermission=L'authentification {0} a des permissions ACL pour l'objet de domaine, mais pas la permission ACL requise pour l'objet de domaine {1}
-ConcurrentSessionControllerImpl.exceededAllowed=Le maximum de {0} sessions a été dépassé pour cet utilisateur
-ProviderManager.providerNotFound=Aucun AuthenticationProvider n'a été trouvé pour {0}
-AnonymousAuthenticationProvider.incorrectKey=L'AnonymousAuthenticationToken présenté ne contient pas la clé attendue
-CasAuthenticationProvider.incorrectKey=Le CasAuthenticationToken présenté ne contient pas la clé attendue
-CasAuthenticationProvider.noServiceTicket=Echec d'obtention d'un ticket CAS à valider
-NamedCasProxyDecider.untrusted=Le proxy {0} le plus proche n'est pas fiable
-RejectProxyTickets.reject=Des tickets proxy ont été rejetés
-AbstractSecurityInterceptor.authenticationNotFound=Aucun objet Authentication n'a été trouvé dans le SecurityContext
-AbstractUserDetailsAuthenticationProvider.onlySupports=Seul UsernamePasswordAuthenticationToken est pris en charge
-AbstractUserDetailsAuthenticationProvider.locked=Le compte utilisateur est bloqué
-AbstractUserDetailsAuthenticationProvider.disabled=Le compte utilisateur est désactivé
-AbstractUserDetailsAuthenticationProvider.expired=Le compte utilisateur a expiré
-AbstractUserDetailsAuthenticationProvider.credentialsExpired=Les créances de l'utilisateur ont expiré
-AbstractUserDetailsAuthenticationProvider.badCredentials=Les créances sont erronées
-X509AuthenticationProvider.certificateNull=Le certificat est null
-DaoX509AuthoritiesPopulator.noMatching=Aucun motif concordant n'a été trouvé dans le subjectDN: {0}
-RememberMeAuthenticationProvider.incorrectKey=Le RememberMeAuthenticationToken présenté ne contient pas la clé attendue
-RunAsImplAuthenticationProvider.incorrectKey=Le RunAsUserToken présenté ne contient pas la clé attendue
-DigestProcessingFilter.missingMandatory=Une valeur obligatoire manque au condensé; reçu l'entête {0}
-DigestProcessingFilter.missingAuth=Une valeur obligatoire manque au condensé pour 'auth' QOP; reçu l'entête {0}
-DigestProcessingFilter.incorrectRealm=Le nom de domaine de la réponse {0} ne correspond pas au nom de domaine du système {1}
-DigestProcessingFilter.nonceExpired=Le nonce a expiré
-DigestProcessingFilter.nonceEncoding=Le nonce n'est pas encodé en Base64; reçu le nonce {0}
-DigestProcessingFilter.nonceNotTwoTokens=Le nonce aurait dû générer deux jetons, mais était {0}
-DigestProcessingFilter.nonceNotNumeric=Le jeton nonce aurait dû générer d'abord un jeton numérique, mais était {0}
-DigestProcessingFilter.nonceCompromised=Le jeton nonce est compromis {0}
-DigestProcessingFilter.usernameNotFound=Le nom d'utilisateur {0} n'a pas été trouvé
-DigestProcessingFilter.incorrectResponse=Réponse incorrecte
-JdbcDaoImpl.notFound=Le nom d'utilisateur {0} n'a pas été trouvé
-JdbcDaoImpl.noAuthority=Le compte utilisateur {0} n'a pas de permission
-SwitchUserProcessingFilter.noCurrentUser=Aucun utilisateur n'est associé à la requête en cours
-SwitchUserProcessingFilter.noOriginalAuthentication=L'objet Authentication original n'a pas été trouvé
-SwitchUserProcessingFilter.usernameNotFound=Le nom d'utilisateur {0} n'a pas été trouvé
-SwitchUserProcessingFilter.locked=Le compte utilisateur est bloqué
-SwitchUserProcessingFilter.disabled=Le compte utilisateur est désactivé
-SwitchUserProcessingFilter.expired=Le compte utilisateur a expiré
-SwitchUserProcessingFilter.credentialsExpired=Les créances de l'utilisateur ont expiré
-AbstractAccessDecisionManager.accessDenied=Accès refusé
-LdapAuthenticationProvider.emptyUsername=Le nom d'utilisateur est obligatoire
-LdapAuthenticationProvider.emptyPassword=Le mot de passe est obligatoire
-DefaultIntitalDirContextFactory.communicationFailure=Impossible de se connecter au serveur LDAP
-DefaultIntitalDirContextFactory.badCredentials=Les créances sont erronées
-DefaultIntitalDirContextFactory.unexpectedException=Impossible d'obtenir un InitialDirContext à cause d'une erreur inattendue
-PasswordComparisonAuthenticator.badCredentials=Les créances sont erronées
-BindAuthenticator.badCredentials=Les créances sont erronées
-BindAuthenticator.failedToLoadAttributes=Les créances sont erronées
-UserDetailsService.locked=Le compte utilisateur est bloqué
-UserDetailsService.disabled=Le compte utilisateur est désactivé
-UserDetailsService.expired=Le compte utilisateur a expiré
-UserDetailsService.credentialsExpired=Les créances de l'utilisateur ont expiré
diff --git a/dist/spring-security-core/org/springframework/security/messages_it.properties b/dist/spring-security-core/org/springframework/security/messages_it.properties
deleted file mode 100644
index f3c9369..0000000
--- a/dist/spring-security-core/org/springframework/security/messages_it.properties
+++ /dev/null
@@ -1,47 +0,0 @@
-AbstractAccessDecisionManager.accessDenied=Accesso negato
-AbstractSecurityInterceptor.authenticationNotFound=Nessuna autenticazione trovata dentro il Security Context
-AbstractUserDetailsAuthenticationProvider.badCredentials=Credenziali non valide
-AbstractUserDetailsAuthenticationProvider.credentialsExpired=Credenziali dell'utente scadute
-AbstractUserDetailsAuthenticationProvider.disabled=Utente disabilitato
-AbstractUserDetailsAuthenticationProvider.expired=Account dell'utente scadute
-AbstractUserDetailsAuthenticationProvider.locked=Account dell'utente bloccato
-AbstractUserDetailsAuthenticationProvider.onlySupports=Solo UsernamePasswordAuthenticationToken è supportata
-AnonymousAuthenticationProvider.incorrectKey=AnonymousAuthenticationToken non contiene la chiave prevista
-AuthByAdapterProvider.incorrectKey=AuthByAdapter non contiene la chiave prevista
-BasicAclEntryAfterInvocationProvider.noPermission=L'autenticazione {0} non ha nessun permesso sull'oggetto di dominio {1}
-BasicAclEntryAfterInvocationProvider.insufficientPermission=L'autenticazione {0} ha permessi ACL sull'oggetto di dominio, ma non il permesso ACL richiesto dall'oggetto {1}
-BindAuthenticator.badCredentials=Credenziali non valide
-BindAuthenticator.failedToLoadAttributes=Credenziali non valide
-CasAuthenticationProvider.incorrectKey=CasAuthenticationToken non contiene la chiave prevista
-CasAuthenticationProvider.noServiceTicket=Non e' stato fornito un CAS service ticket valido
-ConcurrentSessionControllerImpl.exceededAllowed=Il numero massimo delle sessioni ({0}) per questo utente sono state superate
-DaoX509AuthoritiesPopulator.noMatching=Non e' stato validato correttamente il subjectDN: {0}
-DefaultIntitalDirContextFactory.communicationFailure=Impossibile connettersi al server LDAP
-DefaultIntitalDirContextFactory.badCredentials=Credenziali non valide
-DefaultIntitalDirContextFactory.unexpectedException=Impossibile creare l'InitialDirContext a causa di un errore imprevisto
-DigestProcessingFilter.missingMandatory=Valore digest obbligatorio mancante; ricevuto header {0}
-DigestProcessingFilter.missingAuth=Valore digest obbligatorio mancante per 'auth' QOP; ricevuto header {0}
-DigestProcessingFilter.incorrectRealm=Il response realm name {0} non corrisponde al realm name di sistema {1}
-DigestProcessingFilter.nonceExpired=Nonce scaduto/in timeout
-DigestProcessingFilter.nonceEncoding=Nonce non codificato in Base64; ricevuto nonce {0}
-DigestProcessingFilter.nonceNotTwoTokens=Nonce avrebbe dovuto dare due token invece di {0}
-DigestProcessingFilter.nonceNotNumeric=Nonce token avrebbe dovuto dare un primo token numerico invece di {0}
-DigestProcessingFilter.nonceCompromised=Nonce token corrotto {0}
-DigestProcessingFilter.usernameNotFound=Username {0} non trovato
-DigestProcessingFilter.incorrectResponse=Replica non corretta
-LdapAuthenticationProvider.emptyUsername=Username vuoto non consentito
-LdapAuthenticationProvider.emptyPassword=Credenziali non valide
-NamedCasProxyDecider.untrusted=Il Proxy piu' vicino {0} non e' trusted
-PasswordComparisonAuthenticator.badCredentials=Credenziali non valide
-ProviderManager.providerNotFound=Nessun Provider di autenticazione trovato per {0}
-RejectProxyTickets.reject=Proxy tickets rifiutati
-RememberMeAuthenticationProvider.incorrectKey=RememberMeAuthenticationToken non contiene la chiave prevista
-RunAsImplAuthenticationProvider.incorrectKey=RunAsUserToken non contiene la chiave prevista
-SwitchUserProcessingFilter.noCurrentUser=Nessun utente corrente associato con questa richiesta
-SwitchUserProcessingFilter.noOriginalAuthentication=Impossibile trovare l'Authentication object originale
-SwitchUserProcessingFilter.usernameNotFound=Username {0} non trovato
-SwitchUserProcessingFilter.locked=Account dell'utente bloccato
-SwitchUserProcessingFilter.disabled=Account dell'utente disabilitato
-SwitchUserProcessingFilter.expired=Account dell'utente scaduto
-SwitchUserProcessingFilter.credentialsExpired=Credenziali dell'utente scadute
-X509AuthenticationProvider.certificateNull=Il certificato e' nullo
diff --git a/dist/spring-security-core/org/springframework/security/messages_ko_KR.properties b/dist/spring-security-core/org/springframework/security/messages_ko_KR.properties
deleted file mode 100644
index 4db6c91..0000000
--- a/dist/spring-security-core/org/springframework/security/messages_ko_KR.properties
+++ /dev/null
@@ -1,54 +0,0 @@
-AuthByAdapterProvider.incorrectKey=\uc81c\uacf5\ub41c AuthByAdapter \uad6c\ud604\uc5d0\ub294 \ucc3e\ub294 key\uac00 \uc5c6\uc2b5\ub2c8\ub2e4.
-BasicAclEntryAfterInvocationProvider.noPermission=Authentication {0}\uc740/\ub294 domain object {1}\uc5d0 \ub300\ud55c \uad8c\ud55c\uc774 \uc5c6\uc2b5\ub2c8\ub2e4.
-BasicAclEntryAfterInvocationProvider.insufficientPermission=domain object {1}\uc5d0 \ub300\ud55c Authentication {0}\uc758 ACL \uad8c\ud55c\uc774 \ubd88\ucda9\ubd84\ud569\ub2c8\ub2e4.
-ConcurrentSessionControllerImpl.exceededAllowed={0}\uc758 \ucd5c\ub300 \uc138\uc158 \ud5c8\uc6a9 \uc218\ub97c \ucd08\uacfc\ud558\uc600\uc2b5\ub2c8\ub2e4.
-ProviderManager.providerNotFound={0}\uc744 \uc704\ud55c AuthenticationProvider\ub97c \ucc3e\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
-AnonymousAuthenticationProvider.incorrectKey=\uc81c\uacf5\ub41c AnonymousAuthenticationToken\uc5d0\ub294 \ucc3e\ub294 key\uac00 \uc5c6\uc2b5\ub2c8\ub2e4.
-CasAuthenticationProvider.incorrectKey=\uc81c\uacf5\ub41c CasAuthenticationToken\uc5d0\ub294 \ucc3e\ub294 key\uac00 \uc5c6\uc2b5\ub2c8\ub2e4.
-CasAuthenticationProvider.noServiceTicket=\uac80\uc99d\uc744 \uc704\ud55c CAS \uc11c\ube44\uc2a4 \ud2f0\ucf13\uc744 \uc81c\uacf5\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
-NamedCasProxyDecider.untrusted=\uac00\uc7a5 \uac00\uae4c\uc6b4 \ud504\ub77d\uc2dc {0}\ub294 \uc2e0\ub8b0\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
-RejectProxyTickets.reject=\ud504\ub77d\uc2dc \ud2f0\ucf13\uc774 \uac70\ubd80\ub418\uc5c8\uc2b5\ub2c8\ub2e4.
-AbstractSecurityInterceptor.authenticationNotFound=SecurityContext\uc5d0\uc11c Authentication \uac1d\uccb4\ub97c \ucc3e\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
-AbstractUserDetailsAuthenticationProvider.onlySupports=UsernamePasswordAuthenticationToken\ub9cc \uc9c0\uc6d0\ud569\ub2c8\ub2e4.
-AbstractUserDetailsAuthenticationProvider.locked=\uc0ac\uc6a9\uc790 \uacc4\uc815\uc774 \uc7a0\uaca8 \uc788\uc2b5\ub2c8\ub2e4.
-AbstractUserDetailsAuthenticationProvider.disabled=\uc874\uc7ac\ud558\uc9c0 \uc54a\ub294 \uc0ac\uc6a9\uc790 \uc785\ub2c8\ub2e4.
-AbstractUserDetailsAuthenticationProvider.expired=\uc0ac\uc6a9\uc790 \uacc4\uc815\uc758 \uc720\ud6a8 \uae30\uac04\uc774 \ub9cc\ub8cc \ub418\uc5c8\uc2b5\ub2c8\ub2e4.
-AbstractUserDetailsAuthenticationProvider.credentialsExpired=\ube44\ubc00\ubc88\ud638(credential)\uc758 \uc720\ud6a8 \uae30\uac04\uc774 \ub9cc\ub8cc\ub418\uc5c8\uc2b5\ub2c8\ub2e4.
-AbstractUserDetailsAuthenticationProvider.badCredentials=\ube44\ubc00\ubc88\ud638(credential)\uac00 \ub9de\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
-X509AuthenticationProvider.certificateNull=\ube44\ubc00\ubc88\ud638(credential)\uac00 null \uc785\ub2c8\ub2e4.
-DaoX509AuthoritiesPopulator.noMatching=subjectDN: {0}\uc5d0\uc11c \ub9e4\uce6d\ub418\ub294 \ud328\ud134\uc774 \uc5c6\uc2b5\ub2c8\ub2e4.
-RememberMeAuthenticationProvider.incorrectKey=\uc81c\uacf5\ub41c RememberMeAuthenticationToken\uc5d0\ub294 \ucc3e\ub294 key\uac00 \uc5c6\uc2b5\ub2c8\ub2e4.
-RunAsImplAuthenticationProvider.incorrectKey=\uc81c\uacf5\ub41c RunAsUserToken\uc5d0\ub294 \ucc3e\ub294 key\uac00 \uc5c6\uc2b5\ub2c8\ub2e4.
-DigestProcessingFilter.missingMandatory=\ud544\uc218 digest \ud30c\ub77c\ubbf8\ud130 \uac12\uc774 \ub204\ub77d\ub418\uc5c8\uc2b5\ub2c8\ub2e4. \ud604\uc7ac header\ub294 {0}\uc785\ub2c8\ub2e4.
-DigestProcessingFilter.missingAuth='auth' QOP\ub97c \uc704\ud55c \ud544\uc218 digest \ud30c\ub77c\ubbf8\ud130 \uac12\uc774 \ub204\ub77d\ub418\uc5c8\uc2b5\ub2c8\ub2e4. \ud604\uc7ac header\ub294 {0}\uc785\ub2c8\ub2e4.
-DigestProcessingFilter.incorrectRealm=\uc751\ub2f5 realm \uc774\ub984 {0}\uc774 \uc2dc\uc2a4\ud15c realm \uc774\ub984 {1}\uacfc \uc77c\uce58 \ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
-DigestProcessingFilter.nonceExpired=Nonce\uc758 \uc720\ud6a8 \uae30\uac04\uc774 \ub9cc\ub8cc\ub418\uc5c8\uc2b5\ub2c8\ub2e4.
-DigestProcessingFilter.nonceEncoding=Nonce\uac00 Base64\ub85c \uc778\ucf54\ub529 \ub418\uc5b4\uc788\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. \ud604\uc7ac nonce\ub294 {0}\uc785\ub2c8\ub2e4.
-DigestProcessingFilter.nonceNotTwoTokens=Nonce\ub294 2\uac1c\uc758 \ud1a0\ud070\uc744 \ub9cc\ub4e4\uc5b4\uc57c \ud569\ub2c8\ub2e4. \ud604\uc7ac nonce\ub294 {0}\uc785\ub2c8\ub2e4.
-DigestProcessingFilter.nonceNotNumeric=Nonce \ud1a0\ud070\uc758 \uccab \uae00\uc790\ub294 \uc22b\uc790\ub85c \uc2dc\uc791\ud574\uc57c \ud569\ub2c8\ub2e4. \ud604\uc7ac nonce\ub294 {0}\uc785\ub2c8\ub2e4.
-DigestProcessingFilter.nonceCompromised=Nonce \ud1a0\ud070\uc774 \ud6fc\uc190\ub418\uc5c8\uc2b5\ub2c8\ub2e4. \ud604\uc7ac nonce\ub294 {0}\uc785\ub2c8\ub2e4.
-DigestProcessingFilter.usernameNotFound=\uc0ac\uc6a9\uc790 {0}\uc744/\ub97c \ucc3e\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
-DigestProcessingFilter.incorrectResponse=\uc751\ub2f5\uc774 \uc815\ud655\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
-JdbcDaoImpl.notFound=\uc0ac\uc6a9\uc790 {0}\uc744/\ub97c \ucc3e\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
-JdbcDaoImpl.noAuthority=\uc0ac\uc6a9\uc790 {0}\uc740/\ub294 \uad8c\ud55c\uc774 \uc5c6\uc2b5\ub2c8\ub2e4.
-SwitchUserProcessingFilter.noCurrentUser=\uc0ac\uc6a9\uc790\uac00 \uc874\uc7ac\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
-SwitchUserProcessingFilter.noOriginalAuthentication=Authentication\uc758 \uc6d0\ubcf8\uc744 \ucc3e\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
-SwitchUserProcessingFilter.usernameNotFound=\uc0ac\uc6a9\uc790\uba85(username) {0}\uc744/\ub97c \ucc3e\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
-SwitchUserProcessingFilter.locked=\uc0ac\uc6a9\uc790 \uacc4\uc815\uc774 \uc7a0\uaca8 \uc788\uc2b5\ub2c8\ub2e4.
-SwitchUserProcessingFilter.disabled=\uc0ac\uc6a9\uc790 \uacc4\uc815\uc744 \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
-SwitchUserProcessingFilter.expired=\uc0ac\uc6a9\uc790 \uacc4\uc815\uc758 \uc720\ud6a8 \uae30\uac04\uc774 \ub9cc\ub8cc \ub418\uc5c8\uc2b5\ub2c8\ub2e4.
-SwitchUserProcessingFilter.credentialsExpired=\ube44\ubc00\ubc88\ud638(credential)\uc758 \uc720\ud6a8 \uae30\uac04\uc774 \ub9cc\ub8cc\ub418\uc5c8\uc2b5\ub2c8\ub2e4.
-AbstractAccessDecisionManager.accessDenied=\uc811\uadfc\uc774 \uac70\ubd80\ub418\uc5c8\uc2b5\ub2c8\ub2e4.
-LdapAuthenticationProvider.emptyUsername=\uc0ac\uc6a9\uc790\uba85(username)\uc5d0 \uacf5\ubc31\uc740 \ud5c8\uc6a9\ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
-LdapAuthenticationProvider.emptyPassword=\ube44\ubc00\ubc88\ud638(credential)\uac00 \ub9de\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
-DefaultIntitalDirContextFactory.communicationFailure=LDAP \uc11c\ubc84\ub85c \uc811\uc18d\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
-DefaultIntitalDirContextFactory.badCredentials=\ube44\ubc00\ubc88\ud638\uac00 \ub9de\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
-DefaultIntitalDirContextFactory.unexpectedException=\uc54c \uc218 \uc5c6\ub294 \uc608\uc678\uac00 \ubc1c\uc0dd\ud558\uc5ec InitialDirContext\ub97c \uc5bb\uc5b4\uc62c \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
-PasswordComparisonAuthenticator.badCredentials=\ube44\ubc00\ubc88\ud638\uac00 \ub9de\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
-BindAuthenticator.badCredentials=\ube44\ubc00\ubc88\ud638\uac00 \ub9de\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
-BindAuthenticator.failedToLoadAttributes=\ube44\ubc00\ubc88\ud638\uac00 \ub9de\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
-UserDetailsService.locked=\uc0ac\uc6a9\uc790 \uacc4\uc815\uc774 \uc7a0\uaca8 \uc788\uc2b5\ub2c8\ub2e4.
-UserDetailsService.disabled=\uc0ac\uc6a9\uc790 \uacc4\uc815\uc744 \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
-UserDetailsService.expired=\uc0ac\uc6a9\uc790 \uacc4\uc815\uc758 \uc720\ud6a8 \uae30\uac04\uc774 \ub9cc\ub8cc \ub418\uc5c8\uc2b5\ub2c8\ub2e4.
-UserDetailsService.credentialsExpired=\ube44\ubc00\ubc88\ud638\uc758 \uc720\ud6a8 \uae30\uac04\uc774 \ub9cc\ub8cc\ub418\uc5c8\uc2b5\ub2c8\ub2e4.
-
diff --git a/dist/spring-security-core/org/springframework/security/messages_pl.properties b/dist/spring-security-core/org/springframework/security/messages_pl.properties
deleted file mode 100644
index faa16fd..0000000
--- a/dist/spring-security-core/org/springframework/security/messages_pl.properties
+++ /dev/null
@@ -1,53 +0,0 @@
-AuthByAdapterProvider.incorrectKey=Podana implementacja AuthByAdapter nie zawiera oczekiwanego klucza
-BasicAclEntryAfterInvocationProvider.noPermission=U\u017cytkownik {0} nie posiada \u017bADNYCH uprawnie\u0144 do obiektu {1}
-BasicAclEntryAfterInvocationProvider.insufficientPermission=U\u017cytkownik {0} nie posiada wymaganych uprawnie\u0144 do obiektu {1}
-ConcurrentSessionControllerImpl.exceededAllowed=Maksymalna liczba sesji ({0}) dla tego u\u017cytkownika zosta\u0142a przekroczona
-ProviderManager.providerNotFound=AuthenticationProvider dla {0} nie zosta\u0142 znaleziony
-AnonymousAuthenticationProvider.incorrectKey=Podany AnonymousAuthenticationToken nie zawiera oczekiwanego klucza
-CasAuthenticationProvider.incorrectKey=Podany CasAuthenticationToken nie zawiera oczekiwanego klucza
-CasAuthenticationProvider.noServiceTicket=Dostarczenie biletu serwisu CAS do walidacji nie powiod\u0142o si\u0119
-NamedCasProxyDecider.untrusted=Najbli\u017cszy serwer po\u015brednicz\u0105cy {0} jest niezaufany
-RejectProxyTickets.reject=Bilety serwera po\u015brednicz\u0105cego zosta\u0142y odrzucone
-AbstractSecurityInterceptor.authenticationNotFound=Obiekt Authentication nie zosta\u0142 odnaleziony w SecurityContext
-AbstractUserDetailsAuthenticationProvider.onlySupports=Tylko UsernamePasswordAuthenticationToken jest obs\u0142ugiwany
-AbstractUserDetailsAuthenticationProvider.locked=Konto u\u017cytkownika jest zablokowane
-AbstractUserDetailsAuthenticationProvider.disabled=Konto u\u017cytkownika jest wy\u0142\u0105czone
-AbstractUserDetailsAuthenticationProvider.expired=Wa\u017cno\u015b\u0107 konta u\u017cytkownika wygas\u0142a
-AbstractUserDetailsAuthenticationProvider.credentialsExpired=Wa\u017cno\u015b\u0107 danych uwierzytelniaj\u0105cych wygas\u0142a
-AbstractUserDetailsAuthenticationProvider.badCredentials=Niepoprawne dane uwierzytelniaj\u0105ce
-X509AuthenticationProvider.certificateNull=Certyfikat jest pusty
-DaoX509AuthoritiesPopulator.noMatching=Nie odnaleziono pasuj\u0105cego wzorca w subjectDN: {0}
-RememberMeAuthenticationProvider.incorrectKey=Podany RememberMeAuthenticationToken nie zawiera oczekiwanego klucza
-RunAsImplAuthenticationProvider.incorrectKey=Podany RunAsUserToken nie zawiera oczekiwanego klucza
-DigestProcessingFilter.missingMandatory=Brakuje wymaganej warto\u015bci skr\u00f3tu; otrzymany nag\u0142\u00f3wek {0}
-DigestProcessingFilter.missingAuth=Brakuje wymaganej warto\u015bci skr\u00f3tu dla 'auth' QOP; otrzymany nag\u0142\u00f3wek {0}
-DigestProcessingFilter.incorrectRealm=Nazwa domeny {0} w odpowiedzi nie jest zgodna z nazw\u0105 domeny {1} w systemie
-DigestProcessingFilter.nonceExpired=Wa\u017cno\u015b\u0107 kodu jednorazowego (nonce) wygas\u0142a
-DigestProcessingFilter.nonceEncoding=Kod jednorazowy (nonce) nie jest zakodowany w Base64; otrzymany kod {0}
-DigestProcessingFilter.nonceNotTwoTokens=Kod jednorazowy (nonce) powinien zawiera\u0107 dwie warto\u015bci {0}
-DigestProcessingFilter.nonceNotNumeric=Pierwsza warto\u015b\u0107 kodu jednorazowego (nonce) nie jest warto\u015bci\u0105 numeryczn\u0105: {0}
-DigestProcessingFilter.nonceCompromised=Niepoprawny kod jednorazowy (nonce) {0}
-DigestProcessingFilter.usernameNotFound=Nazwa u\u017cytkownika {0} nie zosta\u0142a odnaleziona
-DigestProcessingFilter.incorrectResponse=Niepoprawna odpowied\u017a
-JdbcDaoImpl.notFound=Nazwa u\u017cytkownika {0} nie zosta\u0142a odnaleziona
-JdbcDaoImpl.noAuthority=U\u017cytkownik {0} nie posiada \u017cadnych uprawnie\u0144 (GrantedAuthority)
-SwitchUserProcessingFilter.noCurrentUser=\u017baden aktualny u\u017cytkownik nie jest powi\u0105zany z tym zapytaniem
-SwitchUserProcessingFilter.noOriginalAuthentication=Nie mo\u017cna by\u0142o odnale\u017a\u0107 oryginalnego obiektu Authentication
-SwitchUserProcessingFilter.usernameNotFound=Nazwa u\u017cytkownika {0} nie zosta\u0142a odnaleziona
-SwitchUserProcessingFilter.locked=Konto u\u017cytkownika jest zablokowane
-SwitchUserProcessingFilter.disabled=Konto u\u017cytkownika jest wy\u0142\u0105czone
-SwitchUserProcessingFilter.expired=Wa\u017cno\u015b\u0107 konta u\u017cytkownika wygas\u0142a
-SwitchUserProcessingFilter.credentialsExpired=Wa\u017cno\u015b\u0107 danych uwierzytelniaj\u0105cych wygas\u0142a
-AbstractAccessDecisionManager.accessDenied=Dost\u0119p zabroniony
-LdapAuthenticationProvider.emptyUsername=Pusta nazwa u\u017cytkownika jest niedozwolona
-LdapAuthenticationProvider.emptyPassword=Niepoprawne dane uwierzytelniaj\u0105ce
-DefaultIntitalDirContextFactory.communicationFailure=Po\u0142\u0105czenie z serwerem LDAP nie powiod\u0142o si\u0119
-DefaultIntitalDirContextFactory.badCredentials=Niepoprawne dane uwierzytelniaj\u0105ce
-DefaultIntitalDirContextFactory.unexpectedException=Nie mo\u017cna by\u0142o uzyska\u0107 InitialDirContext z powodu nieoczekiwanego wyj\u0105tku
-PasswordComparisonAuthenticator.badCredentials=Niepoprawne dane uwierzytelniaj\u0105ce
-BindAuthenticator.badCredentials=Niepoprawne dane uwierzytelniaj\u0105ce
-BindAuthenticator.failedToLoadAttributes=Niepoprawne dane uwierzytelniaj\u0105ce
-UserDetailsService.locked=Konto u\u017cytkownika jest zablokowane
-UserDetailsService.disabled=Konto u\u017cytkownika jest wy\u0142\u0105czone
-UserDetailsService.expired=Wa\u017cno\u015b\u0107 konta u\u017cytkownika wygas\u0142a
-UserDetailsService.credentialsExpired=Wa\u017cno\u015b\u0107 danych uwierzytelniaj\u0105cych wygas\u0142a
diff --git a/dist/spring-security-core/org/springframework/security/messages_pt_BR.properties b/dist/spring-security-core/org/springframework/security/messages_pt_BR.properties
deleted file mode 100644
index fc423d1..0000000
--- a/dist/spring-security-core/org/springframework/security/messages_pt_BR.properties
+++ /dev/null
@@ -1,58 +0,0 @@
-# Spring security
-# Messages in Brazilian Portuguese
-# Translation by Leonardo Pinto (leoviveiros at gmail.com)
-
-AuthByAdapterProvider.incorrectKey=A implementa\u00E7\u00E3o de AuthByAdapter apresentada n\u00E3o cont\u00E9m a chave esperada
-BasicAclEntryAfterInvocationProvider.noPermission=Autentica\u00E7\u00E3o {0} n\u00E3o possui permiss\u00F5es no objeto de dom\u00EDnio {1}
-BasicAclEntryAfterInvocationProvider.insufficientPermission=Autentica\u00E7\u00E3o {0} possui permiss\u00F5es ACL para o objeto de dom\u00EDnio, mas n\u00E3o a permiss\u00E3o ACL requerida para o objeto de dom\u00EDnio {1}
-ConcurrentSessionControllerImpl.exceededAllowed=Excedidas as sess\u00F5es m\u00E1ximas de {0} para este usu\u00E1rio
-ProviderManager.providerNotFound=Nenhum AuthenticationProvider encontrado para {0}
-AnonymousAuthenticationProvider.incorrectKey=O AnonymousAuthenticationToken apresentado n\u00E3o cont\u00E9m a chave esperada
-CasAuthenticationProvider.incorrectKey=O CasAuthenticationToken apresentado n\u00E3o cont\u00E9m a chave esperada
-CasAuthenticationProvider.noServiceTicket=N\u00E3o foi poss\u00EDvel prover um ticket de servi\u00E7o CAS para validar
-NamedCasProxyDecider.untrusted=O proxy mais pr\u00F3ximo {0} n\u00E3o \u00E9 confi\u00E1vel
-RejectProxyTickets.reject=Os tickets do proxy foram rejeitados
-AbstractSecurityInterceptor.authenticationNotFound=Um objeto de autentica\u00E7\u00E3o n\u00E3o foi encontrado no SecurityContext
-AbstractUserDetailsAuthenticationProvider.onlySupports=Somente UsernamePasswordAuthenticationToken \u00E9 suportado
-AbstractUserDetailsAuthenticationProvider.locked=Conta bloqueada
-AbstractUserDetailsAuthenticationProvider.disabled=Usu\u00E1rio desabilitado
-AbstractUserDetailsAuthenticationProvider.expired=Conta expirada
-AbstractUserDetailsAuthenticationProvider.credentialsExpired=Credenciais expiradas
-AbstractUserDetailsAuthenticationProvider.badCredentials=Usu\u00E1rio inexistente ou senha inv\u00E1lida
-X509AuthenticationProvider.certificateNull=Certificado nulo
-DaoX509AuthoritiesPopulator.noMatching=Nenhum padr\u00E3o compat\u00EDvel foi encontrado em subjectDN: {0}
-RememberMeAuthenticationProvider.incorrectKey=O RememberMeAuthenticationToken apresentado n\u00E3o cont\u00E9m a chave esperada
-RunAsImplAuthenticationProvider.incorrectKey=O RunAsUserToken apresentado n\u00E3o cont\u00E9m a chave esperada
-DigestProcessingFilter.missingMandatory=Valor digest obrigat\u00F3rio perdido; header recibido {0}
-DigestProcessingFilter.missingAuth=Valor digest obrigat\u00F3rio perdido para 'auth' QOP; header recibido {0}
-DigestProcessingFilter.incorrectRealm=Resposta realm de nome {0} n\u00E3o coincide com realm de sistema de nome {1}
-DigestProcessingFilter.nonceExpired=Nonce expirou/tempo esgotado
-DigestProcessingFilter.nonceEncoding=Nonce n\u00E3o est\u00E1 codificado em Base64; nonce recibido {0}
-DigestProcessingFilter.nonceNotTwoTokens=Nonce token deveria ter dois tokens mas tem {0}
-DigestProcessingFilter.nonceNotNumeric=Nonce token deveria ter um primero token num\u00E9rico, mas tem {0}
-DigestProcessingFilter.nonceCompromised=Nonce token comprometido {0}
-DigestProcessingFilter.usernameNotFound=Usu\u00E1rio {0} n\u00E3o encontrado
-DigestProcessingFilter.incorrectResponse=Resposta incorreta
-JdbcDaoImpl.notFound=Usu\u00E1rio {0} n\u00E3o encontrado
-JdbcDaoImpl.noAuthority=Usu\u00E1rio {0} n\u00E3o tem permiss\u00E3o
-SwitchUserProcessingFilter.noCurrentUser=Nenhum usu\u00E1rio associado a esta requisi\u00E7\u00E3o
-SwitchUserProcessingFilter.noOriginalAuthentication=N\u00E3o foi poss\u00EDvel encontrar o objeto Authentication original
-SwitchUserProcessingFilter.usernameNotFound=Usu\u00E1rio {0} n\u00E3o encontrado
-SwitchUserProcessingFilter.locked=Conta bloqueada
-SwitchUserProcessingFilter.disabled=Usu\u00E1rio desabilitado
-SwitchUserProcessingFilter.expired=Conta expirada
-SwitchUserProcessingFilter.credentialsExpired=Credenciais expiradas
-AbstractAccessDecisionManager.accessDenied=Acesso negado
-LdapAuthenticationProvider.emptyUsername=Nome vazio n\u00E3o permitido
-LdapAuthenticationProvider.emptyPassword=Usu\u00E1rio inexistente ou senha inv\u00E1lida
-DefaultIntitalDirContextFactory.communicationFailure=N\u00E3o foi poss\u00EDvel conectar ao servidor LDAP
-DefaultIntitalDirContextFactory.badCredentials=Usu\u00E1rio inexistente ou senha inv\u00E1lida
-DefaultIntitalDirContextFactory.unexpectedException=Falha ao obter InitialDirContext devido a uma exce\u00E7\u00E3o n\u00E3o esperada
-PasswordComparisonAuthenticator.badCredentials=Usu\u00E1rio inexistente ou senha inv\u00E1lida
-BindAuthenticator.badCredentials=Usu\u00E1rio inexistente ou senha inv\u00E1lida
-BindAuthenticator.failedToLoadAttributes=Usu\u00E1rio inexistente ou senha inv\u00E1lida
-UserDetailsService.locked=Conta bloqueada
-UserDetailsService.disabled=Usu\u00E1rio desabilitado
-UserDetailsService.expired=Conta expirada
-UserDetailsService.credentialsExpired=Credenciais expiradas
-
diff --git a/dist/spring-security-core/org/springframework/security/messages_pt_PT.properties b/dist/spring-security-core/org/springframework/security/messages_pt_PT.properties
deleted file mode 100644
index 22102aa..0000000
--- a/dist/spring-security-core/org/springframework/security/messages_pt_PT.properties
+++ /dev/null
@@ -1,56 +0,0 @@
-# Spring Security Portuguese Resource Bundle
-# Author: José Santos
-
-AuthByAdapterProvider.incorrectKey=A implementação do AuthByAdapter especificado não contém a chave esperada
-BasicAclEntryAfterInvocationProvider.noPermission=A autenticação {0} não tem QUALQUER permissão para o objecto de domínio {1}
-BasicAclEntryAfterInvocationProvider.insufficientPermission=A autenticação {0} tem permissões ACL para o objecto de domínio {1}, mas não a permissão ACL requerida
-ConcurrentSessionControllerImpl.exceededAllowed=Número máximo de sessões ({0}) excedido para este utilizador
-ProviderManager.providerNotFound=Nenhum AuthenticationProvider encontrado para {0}
-AnonymousAuthenticationProvider.incorrectKey=O AnonymousAuthenticationToken especificado não contém a chave esperada
-CasAuthenticationProvider.incorrectKey=O CasAuthenticationToken especificado não contém a chave esperada
-CasAuthenticationProvider.noServiceTicket=Falha na obtenção de um ticket de serviço CAS de validação
-NamedCasProxyDecider.untrusted=O proxy mais próximo {0} não é fiável
-RejectProxyTickets.reject=Tickets proxy rejeitados
-AbstractSecurityInterceptor.authenticationNotFound=Objecto Authentication não encontrado em SecurityContext
-AbstractUserDetailsAuthenticationProvider.onlySupports=Apenas UsernamePasswordAuthenticationToken é suportado
-AbstractUserDetailsAuthenticationProvider.locked=A conta de utilizador está bloqueada
-AbstractUserDetailsAuthenticationProvider.disabled=O utilizador está desactivado
-AbstractUserDetailsAuthenticationProvider.expired=A conta de utilizador expirou
-AbstractUserDetailsAuthenticationProvider.credentialsExpired=As credenciais do utilizador expiraram
-AbstractUserDetailsAuthenticationProvider.badCredentials=Credenciais inválidas
-X509AuthenticationProvider.certificateNull=Certificado nulo
-DaoX509AuthoritiesPopulator.noMatching=Formato do subjectDN {0} incorrecto
-RememberMeAuthenticationProvider.incorrectKey=O RememberMeAuthenticationToken especificado não contém a chave esperada
-RunAsImplAuthenticationProvider.incorrectKey=O RunAsUserToken especificado não contém a chave esperada
-DigestProcessingFilter.missingMandatory=Valor digest obrigatório em falta; cabeçalho recebido {0}
-DigestProcessingFilter.missingAuth=Valor digest obrigatório em falta para 'auth' QOP; cabeçalho recebido {0}
-DigestProcessingFilter.incorrectRealm=Nome de domínio na resposta {0} não corresponde ao nome de domínio do sistema {1}
-DigestProcessingFilter.nonceExpired=O nonce expirou
-DigestProcessingFilter.nonceEncoding=O nonce não está codificado em Base64; nonce recebido {0}
-DigestProcessingFilter.nonceNotTwoTokens=O nonce deve ser constituído por 2 tokens, não por {0}
-DigestProcessingFilter.nonceNotNumeric=O primeiro elemento do token nonce ({0}) deve ser numérico
-DigestProcessingFilter.nonceCompromised=Token nonce comprometido {0}
-DigestProcessingFilter.usernameNotFound=Nome de utilizador {0} não encontrado
-DigestProcessingFilter.incorrectResponse=Resposta incorrecta
-JdbcDaoImpl.notFound=Utilizador {0} não encontrado
-JdbcDaoImpl.noAuthority=Utilizador {0} não tem GrantedAuthority
-SwitchUserProcessingFilter.noCurrentUser=Nenhum utilizador associado a este pedido
-SwitchUserProcessingFilter.noOriginalAuthentication=Objecto Authentication original não encontrado
-SwitchUserProcessingFilter.usernameNotFound=Nome de utilizador {0} não encontrado
-SwitchUserProcessingFilter.locked=A conta de utilizador está bloqueada
-SwitchUserProcessingFilter.disabled=O utilizador está desactivado
-SwitchUserProcessingFilter.expired=A conta de utilizador expirou
-SwitchUserProcessingFilter.credentialsExpired=As credenciais do utilizador expiraram
-AbstractAccessDecisionManager.accessDenied=Acesso negado
-LdapAuthenticationProvider.emptyUsername=Nome de utilizador vazio não permitido
-LdapAuthenticationProvider.emptyPassword=Credenciais inválidas
-DefaultIntitalDirContextFactory.communicationFailure=Falha na ligação ao servidor LDAP
-DefaultIntitalDirContextFactory.badCredentials=Credenciais inválidas
-DefaultIntitalDirContextFactory.unexpectedException=Falha na obtenção do InitialDirContext devido a erro desconhecido
-PasswordComparisonAuthenticator.badCredentials=Credenciais inválidas
-BindAuthenticator.badCredentials=Credenciais inválidas
-BindAuthenticator.failedToLoadAttributes=Credenciais inválidas
-UserDetailsService.locked=A conta de utilizador está bloqueada
-UserDetailsService.disabled=O utilizador está desactivado
-UserDetailsService.expired=A conta de utilizador expirou
-UserDetailsService.credentialsExpired=As credenciais do utilizador expiraram
diff --git a/dist/spring-security-core/org/springframework/security/messages_uk_UA.properties b/dist/spring-security-core/org/springframework/security/messages_uk_UA.properties
deleted file mode 100644
index a88a7ab..0000000
--- a/dist/spring-security-core/org/springframework/security/messages_uk_UA.properties
+++ /dev/null
@@ -1,53 +0,0 @@
-AuthByAdapterProvider.incorrectKey=\u0414\u0430\u043D\u0430 \u0456\u043C\u043F\u043B\u0435\u043C\u0435\u043D\u0442\u0430\u0446\u0456\u044F AuthByAdapter \u043D\u0435 \u043C\u0456\u0441\u0442\u0438\u0442\u044C \u043E\u0447\u0456\u043A\u0443\u0432\u0430\u043D\u043E\u0433\u043E \u043A\u043B\u044E\u0447\u0430
-BasicAclEntryAfterInvocationProvider.noPermission=\u0410\u0443\u0442\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u044F {0} \u043D\u0435 \u043C\u0430\u0454 \u0436\u043E\u0434\u043D\u043E\u0433\u043E \u0434\u043E\u0437\u0432\u043E\u043B\u0443 \u0434\u043B\u044F \u0434\u043E\u0441\u0442\u0443\u043F\u0443 \u0434\u043E \u043E\u0431'\u0454\u043A\u0442\u0443 \u0434\u043E\u043C\u0435\u043D\u0443 {1}
-BasicAclEntryAfterInvocationProvider.insufficientPermission=\u0410\u0443\u0442\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u044F {0} \u043C\u0430\u0454 ACL \u0434\u043E\u0437\u0432\u043E\u043B\u0438, \u0430\u043B\u0435 \u043D\u0435 \u043C\u0430\u0454 \u043D\u0435\u043E\u0431\u0445\u0456\u0434\u043D\u043E\u0433\u043E \u0434\u043E\u0437\u0432\u043E\u043B\u0443 \u0434\u043B\u044F \u0434\u043E\u0441\u0442\u0443\u043F\u0443 \u0434\u043E \u043E\u0431'\u0454\u043A\u0442\u0443 \u0434\u043E\u043C\u0435\u043D\u0443 {1}
-ConcurrentSessionControllerImpl.exceededAllowed=\u041C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u0430 \u043A\u0456\u043B\u044C\u043A\u0456\u0441\u0442\u044C \u0441\u0435\u0441\u0456\u0439 ({0}) \u0434\u043B\u044F \u0446\u044C\u043E\u0433\u043E \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0432\u0438\u0447\u0435\u0440\u043F\u0430\u043D\u0430
-ProviderManager.providerNotFound=AuthenticationProvider \u0434\u043B\u044F {0} \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u0438\u0439
-AnonymousAuthenticationProvider.incorrectKey=\u0414\u0430\u043D\u0438\u0439 AnonymousAuthenticationToken \u043D\u0435 \u043C\u0456\u0441\u0442\u0438\u0442\u044C \u043E\u0447\u0456\u043A\u0443\u0432\u0430\u043D\u043E\u0433\u043E \u043A\u043B\u044E\u0447\u0430
-CasAuthenticationProvider.incorrectKey=\u0414\u0430\u043D\u0438\u0439 CasAuthenticationToken \u043D\u0435 \u043C\u0456\u0441\u0442\u0438\u0442\u044C \u043E\u0447\u0456\u043A\u0443\u0432\u0430\u043D\u043E\u0433\u043E \u043A\u043B\u044E\u0447\u0430
-CasAuthenticationProvider.noServiceTicket=\u041D\u0435 \u043C\u043E\u0436\u043B\u0438\u0432\u043E \u043D\u0430\u0434\u0430\u0442\u0438 \u0431\u0456\u043B\u0435\u0442 \u0441\u0435\u0440\u0432\u0456\u0441\u0443 CAS \u0434\u043B\u044F \u0432\u0430\u043B\u0456\u0434\u0430\u0446\u0456\u0457
-NamedCasProxyDecider.untrusted=\u041D\u0430\u0439\u0431\u043B\u0438\u0436\u0447\u0438\u0439 \u043F\u0440\u043E\u043A\u0441\u0456-\u0441\u0435\u0440\u0432\u0435\u0440 {0} \u0454 \u043D\u0435\u043D\u0430\u0434\u0456\u0439\u043D\u0438\u043C
-RejectProxyTickets.reject=\u0411\u0456\u043B\u0435\u0442\u0438 \u043F\u0440\u043E\u043A\u0441\u0456-\u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0432\u0456\u0434\u0445\u0438\u043B\u0435\u043D\u0456
-AbstractSecurityInterceptor.authenticationNotFound=\u041E\u0431'\u0454\u043A\u0442 Authentication \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u0438\u0439 \u0432 SecurityContext
-AbstractUserDetailsAuthenticationProvider.onlySupports=\u0422\u0456\u043B\u044C\u043A\u0438 UsernamePasswordAuthenticationToken \u043F\u0456\u0434\u0442\u0440\u0438\u043C\u0443\u0454\u0442\u044C\u0441\u044F
-AbstractUserDetailsAuthenticationProvider.locked=\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043A\u043E\u0440\u0443\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0437\u0430\u0431\u043B\u043E\u043A\u043E\u0432\u0430\u043D\u0438\u0439
-AbstractUserDetailsAuthenticationProvider.disabled=\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043A\u043E\u0440\u0443\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0437\u0430\u0431\u043E\u0440\u043E\u043D\u0435\u043D\u0438\u0439
-AbstractUserDetailsAuthenticationProvider.expired=\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043A\u043E\u0440\u0443\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0432\u0438\u0447\u0435\u0440\u043F\u0430\u0432 \u0442\u0435\u0440\u043C\u0456\u043D \u0434\u0456\u0457
-AbstractUserDetailsAuthenticationProvider.credentialsExpired=\u041F\u043E\u0432\u043D\u043E\u0432\u0430\u0436\u0435\u043D\u043D\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0432\u0438\u0447\u0435\u0440\u043F\u0430\u043B\u0438 \u0442\u0435\u0440\u043C\u0456\u043D \u0434\u0456\u0457
-AbstractUserDetailsAuthenticationProvider.badCredentials=\u0414\u0430\u043D\u0456 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u043D\u0435\u043A\u043E\u0440\u0435\u043A\u0442\u043D\u0456
-X509AuthenticationProvider.certificateNull=\u0421\u0435\u0440\u0442\u0438\u0444\u0456\u043A\u0430\u0442 \u043F\u043E\u0440\u043E\u0436\u043D\u0456\u0439
-DaoX509AuthoritiesPopulator.noMatching=\u041D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E \u0432\u0456\u0434\u043F\u043E\u0432\u0456\u0434\u043D\u043E\u0433\u043E \u0448\u0430\u0431\u043B\u043E\u043D\u0443 \u0432 subjectDN: {0}
-RememberMeAuthenticationProvider.incorrectKey=\u0414\u0430\u043D\u0438\u0439 RememberMeAuthenticationToken \u043D\u0435 \u043C\u0456\u0441\u0442\u0438\u0442\u044C \u043E\u0447\u0456\u043A\u0443\u0432\u0430\u043D\u043E\u0433\u043E \u043A\u043B\u044E\u0447\u0430
-RunAsImplAuthenticationProvider.incorrectKey=\u0414\u0430\u043D\u0438\u0439 RunAsUserToken \u043D\u0435 \u043C\u0456\u0441\u0442\u0438\u0442\u044C \u043E\u0447\u0456\u043A\u0443\u0432\u0430\u043D\u043E\u0433\u043E \u043A\u043B\u044E\u0447\u0430
-DigestProcessingFilter.missingMandatory=\u0412\u0456\u0434\u0441\u0443\u0442\u043D\u0454 \u043E\u0431\u043E\u0432'\u044F\u0437\u043A\u043E\u0432\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u043D\u044F \u0434\u0430\u0439\u0434\u0436\u0435\u0441\u0442\u0430; \u043E\u0442\u0440\u0438\u043C\u0430\u043D\u0438\u0439 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A {0}
-DigestProcessingFilter.missingAuth=\u0412\u0456\u0434\u0441\u0443\u0442\u043D\u0454 \u043E\u0431\u043E\u0432'\u044F\u0437\u043A\u043E\u0432\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u043D\u044F \u0434\u0430\u0439\u0434\u0436\u0435\u0441\u0442\u0430 \u0434\u043B\u044F 'auth' QOP; \u043E\u0442\u0440\u0438\u043C\u0430\u043D\u0438\u0439 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A {0}
-DigestProcessingFilter.incorrectRealm=\u041D\u0430\u0437\u0432\u0430 \u0434\u043E\u043C\u0435\u043D\u0443 {0} \u0443 \u0432\u0456\u0434\u043F\u043E\u0432\u0456\u0434\u0456 \u043D\u0435 \u0432\u0456\u0434\u043F\u043E\u0432\u0456\u0434\u0430\u0454 \u043D\u0430\u0437\u0432\u0456 \u0434\u043E\u043C\u0435\u043D\u0443 {1} \u0432 \u0441\u0438\u0441\u0442\u0435\u043C\u0456
-DigestProcessingFilter.nonceExpired=\u041A\u043E\u0434 (nonce) \u0432\u0438\u0447\u0435\u0440\u043F\u0430\u0432 \u0442\u0435\u0440\u043C\u0456\u043D \u0434\u0456\u0457
-DigestProcessingFilter.nonceEncoding=\u041A\u043E\u0434 (nonce) \u043D\u0435 \u0437\u0430\u0448\u0438\u0444\u0440\u043E\u0432\u0430\u043D\u0438\u0439 \u0432 Base64; \u043E\u0442\u0440\u0438\u043C\u0430\u043D\u0438\u0439 \u043A\u043E\u0434 {0}
-DigestProcessingFilter.nonceNotTwoTokens=\u041A\u043E\u0434 (nonce) \u043F\u043E\u0432\u0438\u043D\u0435\u043D \u043C\u0456\u0441\u0442\u0438\u0442\u0438 \u0434\u0432\u0430 \u0441\u0438\u043C\u0432\u043E\u043B\u0438 (tokens), \u0430\u043B\u0435 \u043C\u0456\u0441\u0442\u0438\u0442\u044C {0}
-DigestProcessingFilter.nonceNotNumeric=\u041F\u0435\u0440\u0448\u0438\u0439 \u0441\u0438\u043C\u0432\u043E\u043B (token) \u043A\u043E\u0434 \u043F\u043E\u0432\u0438\u043D\u0435\u043D \u043C\u0456\u0441\u0442\u0438\u0442\u0438 \u0446\u0438\u0444\u0440\u043E\u0432\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u043D\u044F, \u0430 \u043C\u0456\u0441\u0442\u0438\u0442\u044C: {0}
-DigestProcessingFilter.nonceCompromised=\u041A\u043E\u0434 (nonce) \u0441\u043A\u043E\u043C\u043F\u0440\u043E\u043C\u0435\u0442\u043E\u0432\u0430\u043D\u0438\u0439 {0}
-DigestProcessingFilter.usernameNotFound=\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 {0} \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u0438\u0439
-DigestProcessingFilter.incorrectResponse=\u041D\u0435\u043A\u043E\u0440\u0435\u043A\u0442\u043D\u0430 \u0432\u0456\u0434\u043F\u043E\u0432\u0456\u0434\u044C
-JdbcDaoImpl.notFound=\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 {0} \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u0438\u0439
-JdbcDaoImpl.noAuthority=\u041A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447 {0} \u043D\u0435 \u043C\u0430\u0454 \u043F\u043E\u0432\u043D\u043E\u0432\u0430\u0436\u0435\u043D\u044C (GrantedAuthority)
-SwitchUserProcessingFilter.noCurrentUser=\u041D\u0435\u043C\u0430\u0454 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430, \u043F\u043E\u0432'\u044F\u0437\u0430\u043D\u043E\u0433\u043E \u0456\u0437 \u0434\u0430\u043D\u0438\u043C \u0437\u0430\u043F\u0438\u0442\u043E\u043C
-SwitchUserProcessingFilter.noOriginalAuthentication=\u041D\u0435 \u043C\u043E\u0436\u043B\u0438\u0432\u043E \u0437\u043D\u0430\u0439\u0442\u0438 \u043E\u0440\u0438\u0433\u0456\u043D\u0430\u043B\u044C\u043D\u0438\u0439 \u043E\u0431'\u0454\u043A\u0442 Authentication
-SwitchUserProcessingFilter.usernameNotFound=\u0406\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 {0} \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u0435
-SwitchUserProcessingFilter.locked=\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0437\u0430\u0431\u043B\u043E\u043A\u043E\u0432\u0430\u043D\u0438\u0439
-SwitchUserProcessingFilter.disabled=\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043A\u043E\u0440\u0443\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0437\u0430\u0431\u043E\u0440\u043E\u043D\u0435\u043D\u0438\u0439
-SwitchUserProcessingFilter.expired=\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043A\u043E\u0440\u0443\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0432\u0438\u0447\u0435\u0440\u043F\u0430\u0432 \u0442\u0435\u0440\u043C\u0456\u043D \u0434\u0456\u0457
-SwitchUserProcessingFilter.credentialsExpired=\u041F\u043E\u0432\u043D\u043E\u0432\u0430\u0436\u0435\u043D\u043D\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0432\u0438\u0447\u0435\u0440\u043F\u0430\u043B\u0438 \u0442\u0435\u0440\u043C\u0456\u043D \u0434\u0456\u0457
-AbstractAccessDecisionManager.accessDenied=\u0414\u043E\u0441\u0442\u0443\u043F \u0437\u0430\u0431\u043E\u0440\u043E\u043D\u0435\u043D\u0438\u0439
-LdapAuthenticationProvider.emptyUsername=\u041F\u043E\u0440\u043E\u0436\u043D\u0454 \u0456\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0454 \u0437\u0430\u0431\u043E\u0440\u043E\u043D\u0435\u043D\u0438\u043C
-LdapAuthenticationProvider.emptyPassword=\u0414\u0430\u043D\u0456 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u043D\u0435\u043A\u043E\u0440\u0435\u043A\u0442\u043D\u0456
-DefaultIntitalDirContextFactory.communicationFailure=\u041D\u0435\u043C\u043E\u0436\u043B\u0438\u0432\u043E \u0437'\u0454\u0434\u043D\u0430\u0442\u0438\u0441\u044F \u0437 LDAP \u0441\u0435\u0440\u0432\u0435\u0440\u043E\u043C
-DefaultIntitalDirContextFactory.badCredentials=\u0414\u0430\u043D\u0456 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u043D\u0435\u043A\u043E\u0440\u0435\u043A\u0442\u043D\u0456
-DefaultIntitalDirContextFactory.unexpectedException=\u041D\u0435\u043C\u043E\u0436\u043B\u0438\u0432\u043E \u043E\u0442\u0440\u0438\u043C\u0430\u0442\u0438 InitialDirContext \u0447\u0435\u0440\u0435\u0437 \u0432\u0438\u043D\u0438\u043A\u043D\u0435\u043D\u043D\u044F \u043D\u0435\u043E\u0447\u0456\u043A\u0443\u0432\u0430\u043D\u043E\u0457 \u043F\u043E\u043C\u0438\u043B\u043A\u0438
-PasswordComparisonAuthenticator.badCredentials=\u0414\u0430\u043D\u0456 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u043D\u0435\u043A\u043E\u0440\u0435\u043A\u0442\u043D\u0456
-BindAuthenticator.badCredentials=\u0414\u0430\u043D\u0456 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u043D\u0435\u043A\u043E\u0440\u0435\u043A\u0442\u043D\u0456
-BindAuthenticator.failedToLoadAttributes=\u0414\u0430\u043D\u0456 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u043D\u0435\u043A\u043E\u0440\u0435\u043A\u0442\u043D\u0456
-UserDetailsService.locked=\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0437\u0430\u0431\u043B\u043E\u043A\u043E\u0432\u0430\u043D\u0438\u0439
-UserDetailsService.disabled=\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043A\u043E\u0440\u0443\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0437\u0430\u0431\u043E\u0440\u043E\u043D\u0435\u043D\u0438\u0439
-UserDetailsService.expired=\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043A\u043E\u0440\u0443\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0432\u0438\u0447\u0435\u0440\u043F\u0430\u0432 \u0442\u0435\u0440\u043C\u0456\u043D \u0434\u0456\u0457
-UserDetailsService.credentialsExpired=\u041F\u043E\u0432\u043D\u043E\u0432\u0430\u0436\u0435\u043D\u043D\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0432\u0438\u0447\u0435\u0440\u043F\u0430\u043B\u0438 \u0442\u0435\u0440\u043C\u0456\u043D \u0434\u0456\u0457
diff --git a/dist/spring-security-core/org/springframework/security/messages_zh_CN.properties b/dist/spring-security-core/org/springframework/security/messages_zh_CN.properties
deleted file mode 100644
index 9579dc6..0000000
--- a/dist/spring-security-core/org/springframework/security/messages_zh_CN.properties
+++ /dev/null
@@ -1,54 +0,0 @@
-AuthByAdapterProvider.incorrectKey=\u5c55\u793a\u7684AuthByAdapter\u5b9e\u73b0\u4e0d\u542b\u6709\u9884\u671f\u7684key
-BasicAclEntryAfterInvocationProvider.noPermission=\u7ed9\u5b9a\u7684Authentication\u5bf9\u8c61({0})\u6839\u672c\u65e0\u6743\u64cd\u63a7\u9886\u57df\u5bf9\u8c61({1})
-BasicAclEntryAfterInvocationProvider.insufficientPermission=Authentication\u5bf9\u8c61({0})\u786e\u5b9e\u542b\u6709ACL\u6743\u9650\uff0c\u4f46\u5e76\u4e0d\u662f\u76ee\u6807\u9886\u57df\u5bf9\u8c61\u6240\u8981\u6c42\u7684({1})
-ConcurrentSessionControllerImpl.exceededAllowed=\u5df2\u7ecf\u8d85\u8fc7\u4e86\u5f53\u524d\u4e3b\u4f53({0})\u88ab\u5141\u8bb8\u7684\u6700\u5927\u4f1a\u8bdd\u6570\u91cf
-ProviderManager.providerNotFound=\u672a\u67e5\u627e\u5230\u9488\u5bf9{0}\u7684AuthenticationProvider
-AnonymousAuthenticationProvider.incorrectKey=\u5c55\u793a\u7684AnonymousAuthenticationToken\u4e0d\u542b\u6709\u9884\u671f\u7684key
-CasAuthenticationProvider.incorrectKey=\u5c55\u793a\u7684CasAuthenticationToken\u4e0d\u542b\u6709\u9884\u671f\u7684key
-CasAuthenticationProvider.noServiceTicket=\u672a\u80fd\u591f\u6b63\u786e\u63d0\u4f9b\u5f85\u9a8c\u8bc1\u7684CAS\u670d\u52a1\u7968\u6839
-NamedCasProxyDecider.untrusted=\u4ee3\u7406({0})\u4e0d\u53d7\u4fe1\u4efb
-RejectProxyTickets.reject=Proxy\u7968\u6839\u88ab\u62d2\u7edd
-AbstractSecurityInterceptor.authenticationNotFound=\u672a\u5728SecurityContext\u4e2d\u67e5\u627e\u5230\u8ba4\u8bc1\u5bf9\u8c61
-AbstractUserDetailsAuthenticationProvider.onlySupports=\u4ec5\u4ec5\u652f\u6301UsernamePasswordAuthenticationToken
-AbstractUserDetailsAuthenticationProvider.locked=\u7528\u6237\u5e10\u53f7\u5df2\u88ab\u9501\u5b9a
-AbstractUserDetailsAuthenticationProvider.disabled=\u7528\u6237\u5df2\u5931\u6548
-AbstractUserDetailsAuthenticationProvider.expired=\u7528\u6237\u5e10\u53f7\u5df2\u8fc7\u671f
-AbstractUserDetailsAuthenticationProvider.credentialsExpired=\u7528\u6237\u51ed\u8bc1\u5df2\u8fc7\u671f
-AbstractUserDetailsAuthenticationProvider.badCredentials=\u574f\u7684\u51ed\u8bc1
-X509AuthenticationProvider.certificateNull=\u672a\u63d0\u4f9b\u8bc1\u4e66
-DaoX509AuthoritiesPopulator.noMatching=\u672a\u5728subjectDN: {0}\u4e2d\u627e\u5230\u5339\u914d\u7684\u6a21\u5f0f
-RememberMeAuthenticationProvider.incorrectKey=\u5c55\u793aRememberMeAuthenticationToken\u4e0d\u542b\u6709\u9884\u671f\u7684key
-RunAsImplAuthenticationProvider.incorrectKey=\u5c55\u793a\u7684RunAsUserToken\u4e0d\u542b\u6709\u9884\u671f\u7684key
-DigestProcessingFilter.missingMandatory=\u9057\u6f0f\u4e86\u5fc5\u987b\u7ed9\u5b9a\u7684\u6458\u8981\u53d6\u503c; \u63a5\u6536\u5230\u7684\u5934\u4fe1\u606f\u4e3a{0}
-DigestProcessingFilter.missingAuth=\u9057\u6f0f\u4e86\u9488\u5bf9'auth' QOP\u7684\u3001\u5fc5\u987b\u7ed9\u5b9a\u7684\u6458\u8981\u53d6\u503c; \u63a5\u6536\u5230\u7684\u5934\u4fe1\u606f\u4e3a{0}
-DigestProcessingFilter.incorrectRealm=\u54cd\u5e94\u7ed3\u679c\u4e2d\u7684Realm\u540d\u5b57({0})\u540c\u7cfb\u7edf\u6307\u5b9a\u7684Realm\u540d\u5b57({1})\u4e0d\u543b\u5408
-DigestProcessingFilter.nonceExpired=Nonce\u5df2\u7ecf\u8fc7\u671f/\u8d85\u65f6
-DigestProcessingFilter.nonceEncoding=Nonce\u672a\u7ecf\u8fc7Base64\u7f16\u7801; \u76f8\u5e94\u7684nonce\u53d6\u503c\u4e3a {0}
-DigestProcessingFilter.nonceNotTwoTokens=Nonce\u5e94\u8be5\u7531\u4e24\u90e8\u5206\u53d6\u503c\u6784\u6210\uff0c\u4f46\u7ed3\u679c\u5374\u662f{0}
-DigestProcessingFilter.nonceNotNumeric=Nonce\u4ee4\u724c\u7684\u7b2c1\u90e8\u5206\u5e94\u8be5\u662f\u6570\u5b57\uff0c\u4f46\u7ed3\u679c\u5374\u662f{0}
-DigestProcessingFilter.nonceCompromised=Nonce\u4ee4\u724c\u5df2\u7ecf\u5b58\u5728\u95ee\u9898\u4e86\uff0c{0}
-DigestProcessingFilter.usernameNotFound=\u7528\u6237\u540d{0}\u672a\u627e\u5230
-DigestProcessingFilter.incorrectResponse=\u9519\u8bef\u7684\u54cd\u5e94\u7ed3\u679c
-JdbcDaoImpl.notFound=\u672a\u627e\u5230\u7528\u6237{0}
-JdbcDaoImpl.noAuthority=\u6ca1\u6709\u4e3a\u7528\u6237{0}\u6307\u5b9a\u89d2\u8272
-SwitchUserProcessingFilter.noCurrentUser=\u4e0d\u5b58\u5728\u5f53\u524d\u7528\u6237
-SwitchUserProcessingFilter.noOriginalAuthentication=\u4e0d\u80fd\u591f\u67e5\u627e\u5230\u539f\u5148\u7684\u5df2\u8ba4\u8bc1\u5bf9\u8c61
-SwitchUserProcessingFilter.usernameNotFound=\u7528\u6237\u540d{0}\u672a\u627e\u5230
-SwitchUserProcessingFilter.locked=\u7528\u6237\u5e10\u53f7\u5df2\u88ab\u9501\u5b9a
-SwitchUserProcessingFilter.disabled=\u7528\u6237\u5df2\u5931\u6548
-SwitchUserProcessingFilter.expired=\u7528\u6237\u5e10\u53f7\u5df2\u8fc7\u671f
-SwitchUserProcessingFilter.credentialsExpired=\u7528\u6237\u51ed\u8bc1\u5df2\u8fc7\u671f
-AbstractAccessDecisionManager.accessDenied=\u4e0d\u5141\u8bb8\u8bbf\u95ee
-LdapAuthenticationProvider.emptyUsername=\u7528\u6237\u540d\u4e0d\u5141\u8bb8\u4e3a\u7a7a
-LdapAuthenticationProvider.emptyPassword=\u574f\u7684\u51ed\u8bc1
-DefaultIntitalDirContextFactory.communicationFailure=\u4e0d\u80fd\u591f\u8fde\u63a5\u5230LDAP\u670d\u52a1\u5668
-DefaultIntitalDirContextFactory.badCredentials=\u574f\u7684\u51ed\u8bc1
-DefaultIntitalDirContextFactory.unexpectedException=\u7531\u4e8e\u672a\u9884\u671f\u5f02\u5e38\u800c\u4e0d\u80fd\u591f\u83b7\u5f97InitialDirContext
-PasswordComparisonAuthenticator.badCredentials=\u574f\u7684\u51ed\u8bc1
-BindAuthenticator.badCredentials=\u574f\u7684\u51ed\u8bc1
-BindAuthenticator.failedToLoadAttributes=\u574f\u7684\u51ed\u8bc1
-UserDetailsService.locked=\u7528\u6237\u5e10\u53f7\u5df2\u88ab\u9501\u5b9a
-UserDetailsService.disabled=\u7528\u6237\u5df2\u5931\u6548
-UserDetailsService.expired=\u7528\u6237\u5e10\u53f7\u5df2\u8fc7\u671f
-UserDetailsService.credentialsExpired=\u7528\u6237\u51ed\u8bc1\u5df2\u8fc7\u671f
-
diff --git a/dist/spring-security-core/org/springframework/security/provisioning/JdbcUserDetailsManager.java b/dist/spring-security-core/org/springframework/security/provisioning/JdbcUserDetailsManager.java
index 7291acc..25d3cae 100644
--- a/dist/spring-security-core/org/springframework/security/provisioning/JdbcUserDetailsManager.java
+++ b/dist/spring-security-core/org/springframework/security/provisioning/JdbcUserDetailsManager.java
@@ -7,7 +7,7 @@ import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
-import org.springframework.security.core.authority.GrantedAuthorityImpl;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserCache;
import org.springframework.security.core.userdetails.UserDetails;
@@ -180,12 +180,12 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
if (getEnableAuthorities()) {
deleteUserAuthorities(username);
}
- getJdbcTemplate().update(deleteUserSql, new Object[] {username});
+ getJdbcTemplate().update(deleteUserSql, username);
userCache.removeUserFromCache(username);
}
private void deleteUserAuthorities(String username) {
- getJdbcTemplate().update(deleteUserAuthoritiesSql, new Object[] {username});
+ getJdbcTemplate().update(deleteUserAuthoritiesSql, username);
}
public void changePassword(String oldPassword, String newPassword) throws AuthenticationException {
@@ -255,12 +255,12 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
logger.debug("Creating new group '" + groupName + "' with authorities " +
AuthorityUtils.authorityListToSet(authorities));
- getJdbcTemplate().update(insertGroupSql, new Object[] {groupName});
+ getJdbcTemplate().update(insertGroupSql, groupName);
final int groupId = findGroupId(groupName);
- for (int i=0; i < authorities.size(); i++) {
- final String authority = authorities.get(i).getAuthority();
+ for (GrantedAuthority a : authorities) {
+ final String authority = a.getAuthority();
getJdbcTemplate().update(insertGroupAuthoritySql, new PreparedStatementSetter() {
public void setValues(PreparedStatement ps) throws SQLException {
ps.setInt(1, groupId);
@@ -290,7 +290,7 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
Assert.hasText(oldName);
Assert.hasText(newName);
- getJdbcTemplate().update(renameGroupSql, new Object[] {newName, oldName});
+ getJdbcTemplate().update(renameGroupSql, newName, oldName);
}
public void addUserToGroup(final String username, final String groupName) {
@@ -326,21 +326,17 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
userCache.removeUserFromCache(username);
}
- @SuppressWarnings("unchecked")
public List<GrantedAuthority> findGroupAuthorities(String groupName) {
logger.debug("Loading authorities for group '" + groupName + "'");
Assert.hasText(groupName);
- List<GrantedAuthority> authorities = getJdbcTemplate().query(groupAuthoritiesSql, new String[] {groupName}, new RowMapper() {
- public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
+ return getJdbcTemplate().query(groupAuthoritiesSql, new String[] {groupName}, new RowMapper<GrantedAuthority>() {
+ public GrantedAuthority mapRow(ResultSet rs, int rowNum) throws SQLException {
String roleName = getRolePrefix() + rs.getString(3);
- GrantedAuthorityImpl authority = new GrantedAuthorityImpl(roleName);
- return authority;
+ return new SimpleGrantedAuthority(roleName);
}
});
-
- return authorities;
}
public void removeGroupAuthority(String groupName, final GrantedAuthority authority) {
@@ -374,7 +370,7 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
}
private int findGroupId(String group) {
- return getJdbcTemplate().queryForInt(findGroupIdSql, new Object[] {group});
+ return getJdbcTemplate().queryForInt(findGroupIdSql, group);
}
public void setAuthenticationManager(AuthenticationManager authenticationManager) {
@@ -417,9 +413,70 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
}
public void setFindAllGroupsSql(String findAllGroupsSql) {
+ Assert.hasText(findAllGroupsSql);
this.findAllGroupsSql = findAllGroupsSql;
}
+ public void setFindUsersInGroupSql(String findUsersInGroupSql) {
+ Assert.hasText(findUsersInGroupSql);
+ this.findUsersInGroupSql = findUsersInGroupSql;
+ }
+
+ public void setInsertGroupSql(String insertGroupSql) {
+ Assert.hasText(insertGroupSql);
+ this.insertGroupSql = insertGroupSql;
+ }
+
+ public void setFindGroupIdSql(String findGroupIdSql) {
+ Assert.hasText(findGroupIdSql);
+ this.findGroupIdSql = findGroupIdSql;
+ }
+
+ public void setInsertGroupAuthoritySql(String insertGroupAuthoritySql) {
+ Assert.hasText(insertGroupAuthoritySql);
+ this.insertGroupAuthoritySql = insertGroupAuthoritySql;
+ }
+
+ public void setDeleteGroupSql(String deleteGroupSql) {
+ Assert.hasText(deleteGroupSql);
+ this.deleteGroupSql = deleteGroupSql;
+ }
+
+ public void setDeleteGroupAuthoritiesSql(String deleteGroupAuthoritiesSql) {
+ Assert.hasText(deleteGroupAuthoritiesSql);
+ this.deleteGroupAuthoritiesSql = deleteGroupAuthoritiesSql;
+ }
+
+ public void setDeleteGroupMembersSql(String deleteGroupMembersSql) {
+ Assert.hasText(deleteGroupMembersSql);
+ this.deleteGroupMembersSql = deleteGroupMembersSql;
+ }
+
+ public void setRenameGroupSql(String renameGroupSql) {
+ Assert.hasText(renameGroupSql);
+ this.renameGroupSql = renameGroupSql;
+ }
+
+ public void setInsertGroupMemberSql(String insertGroupMemberSql) {
+ Assert.hasText(insertGroupMemberSql);
+ this.insertGroupMemberSql = insertGroupMemberSql;
+ }
+
+ public void setDeleteGroupMemberSql(String deleteGroupMemberSql) {
+ Assert.hasText(deleteGroupMemberSql);
+ this.deleteGroupMemberSql = deleteGroupMemberSql;
+ }
+
+ public void setGroupAuthoritiesSql(String groupAuthoritiesSql) {
+ Assert.hasText(groupAuthoritiesSql);
+ this.groupAuthoritiesSql = groupAuthoritiesSql;
+ }
+
+ public void setDeleteGroupAuthoritySql(String deleteGroupAuthoritySql) {
+ Assert.hasText(deleteGroupAuthoritySql);
+ this.deleteGroupAuthoritySql = deleteGroupAuthoritySql;
+ }
+
/**
* Optionally sets the UserCache if one is in use in the application.
* This allows the user to be removed from the cache after updates have taken place to avoid stale data.
@@ -436,7 +493,7 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
validateAuthorities(user.getAuthorities());
}
- private void validateAuthorities(Collection<GrantedAuthority> authorities) {
+ private void validateAuthorities(Collection<? extends GrantedAuthority> authorities) {
Assert.notNull(authorities, "Authorities list must not be null");
for (GrantedAuthority authority : authorities) {
diff --git a/dist/spring-security-core/org/springframework/security/provisioning/UserDetailsManager.java b/dist/spring-security-core/org/springframework/security/provisioning/UserDetailsManager.java
index c9ec100..46f8a9f 100644
--- a/dist/spring-security-core/org/springframework/security/provisioning/UserDetailsManager.java
+++ b/dist/spring-security-core/org/springframework/security/provisioning/UserDetailsManager.java
@@ -29,8 +29,7 @@ public interface UserDetailsManager extends UserDetailsService {
/**
* Modify the current user's password. This should change the user's password in
- * the persistent user repository (datbase, LDAP etc) and should also modify the
- * current security context to contain the new password.
+ * the persistent user repository (datbase, LDAP etc).
*
* @param oldPassword current password (for re-authentication if required)
* @param newPassword the password to change to
diff --git a/dist/spring-security-core/org/springframework/security/remoting/dns/DnsEntryNotFoundException.java b/dist/spring-security-core/org/springframework/security/remoting/dns/DnsEntryNotFoundException.java
deleted file mode 100644
index 7410b72..0000000
--- a/dist/spring-security-core/org/springframework/security/remoting/dns/DnsEntryNotFoundException.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.remoting.dns;
-
-
-/**
- * This will be thrown if no entry matches the specified DNS query.
- *
- * @author Mike Wiesner
- * @since 3.0
- */
-public class DnsEntryNotFoundException extends DnsLookupException {
-
- private static final long serialVersionUID = -947232730426775162L;
-
- public DnsEntryNotFoundException(String msg) {
- super(msg);
- }
-
- public DnsEntryNotFoundException(String msg, Throwable cause) {
- super(msg, cause);
- }
-
-
-}
diff --git a/dist/spring-security-core/org/springframework/security/remoting/dns/DnsLookupException.java b/dist/spring-security-core/org/springframework/security/remoting/dns/DnsLookupException.java
deleted file mode 100644
index f70f11a..0000000
--- a/dist/spring-security-core/org/springframework/security/remoting/dns/DnsLookupException.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.remoting.dns;
-
-import org.springframework.dao.DataAccessException;
-
-/**
- * This will be thrown for unknown DNS errors.
- *
- * @author Mike Wiesner
- * @since 3.0
- */
-public class DnsLookupException extends DataAccessException {
-
- private static final long serialVersionUID = -7538424279394361310L;
-
- public DnsLookupException(String msg, Throwable cause) {
- super(msg, cause);
- }
-
- public DnsLookupException(String msg) {
- super(msg);
- }
-
-}
diff --git a/dist/spring-security-core/org/springframework/security/remoting/dns/DnsResolver.java b/dist/spring-security-core/org/springframework/security/remoting/dns/DnsResolver.java
deleted file mode 100644
index cfa558b..0000000
--- a/dist/spring-security-core/org/springframework/security/remoting/dns/DnsResolver.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.remoting.dns;
-
-/**
- * Helper class for DNS operations.
- *
- * @author Mike Wiesner
- * @since 3.0
- */
-public interface DnsResolver {
-
- /**
- * Resolves the IP Address (A record) to the specified host name.
- * Throws DnsEntryNotFoundException if there is no record.
- *
- * @param hostname The hostname for which you need the IP Address
- * @return IP Address as a String
- * @throws DnsEntryNotFoundException No record found
- * @throws DnsLookupException Unknown DNS error
- */
- public String resolveIpAddress(String hostname) throws DnsEntryNotFoundException, DnsLookupException;
-
- /**
- * <p>Resolves the host name for the specified service in the specified domain</p>
- * <p>For example, if you need the host name for an LDAP server running in the
- * domain springsource.com, you would call <b>resolveServiceEntry("ldap", "springsource.com")</b>.</p>
- *
- * <p>The DNS server needs to provide the service records for this, in the example above, it
- * would look like this:
- *
- * <pre>_ldap._tcp.springsource.com IN SRV 10 0 88 ldap.springsource.com.</pre>
- *
- * The method will return the record with highest priority (which means the lowest number in the DNS record)
- * and if there are more than one records with the same priority, it will return the one with the highest weight.
- * You will find more informatione about DNS service records at <a href="http://en.wikipedia.org/wiki/SRV_record">Wikipedia</a>.</p>
- *
- * @param serviceType The service type you are searching for, e.g. ldap, kerberos, ...
- * @param domain The domain, in which you are searching for the service
- * @return The hostname of the service
- * @throws DnsEntryNotFoundException No record found
- * @throws DnsLookupException Unknown DNS error
- */
- public String resolveServiceEntry(String serviceType, String domain) throws DnsEntryNotFoundException, DnsLookupException;
-
- /**
- * Resolves the host name for the specified service and then the IP Address for this host in one call.
- *
- * @param serviceType The service type you are searching for, e.g. ldap, kerberos, ...
- * @param domain The domain, in which you are searching for the service
- * @return IP Address of the service
- * @throws DnsEntryNotFoundException No record found
- * @throws DnsLookupException Unknown DNS error
- * @see #resolveServiceEntry(String, String)
- * @see #resolveIpAddress(String)
- */
- public String resolveServiceIpAddress(String serviceType, String domain) throws DnsEntryNotFoundException, DnsLookupException;
-
-}
diff --git a/dist/spring-security-core/org/springframework/security/remoting/dns/InitialContextFactory.java b/dist/spring-security-core/org/springframework/security/remoting/dns/InitialContextFactory.java
deleted file mode 100644
index da8c030..0000000
--- a/dist/spring-security-core/org/springframework/security/remoting/dns/InitialContextFactory.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.remoting.dns;
-
-
-import javax.naming.directory.DirContext;
-import javax.naming.directory.InitialDirContext;
-
-/**
- * This is used in JndiDnsResolver to get an InitialDirContext for DNS queries.
- *
- * @author Mike Wiesner
- * @since 3.0
- * @see InitialDirContext
- * @see DirContext
- * @see JndiDnsResolver
- */
-public interface InitialContextFactory {
-
-
- /**
- * Must return a DirContext which can be used for DNS queries
- * @return JNDI DirContext
- */
- public DirContext getCtx();
-
-}
diff --git a/dist/spring-security-core/org/springframework/security/remoting/dns/JndiDnsResolver.java b/dist/spring-security-core/org/springframework/security/remoting/dns/JndiDnsResolver.java
deleted file mode 100644
index 1f51c91..0000000
--- a/dist/spring-security-core/org/springframework/security/remoting/dns/JndiDnsResolver.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright 2009 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.remoting.dns;
-
-import java.util.Hashtable;
-
-import javax.naming.Context;
-import javax.naming.NameNotFoundException;
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.Attributes;
-import javax.naming.directory.DirContext;
-import javax.naming.directory.InitialDirContext;
-
-
-/**
- * Implementation of DnsResolver which uses JNDI for the DNS queries.
- *
- * Uses an <b>InitialContextFactory</b> to get the JNDI DirContext. The default implementation
- * will just create a new Context with the context factory <b>com.sun.jndi.dns.DnsContextFactory</b>
- *
- * @author Mike Wiesner
- * @since 3.0
- * @see DnsResolver
- * @see InitialContextFactory
- */
-public class JndiDnsResolver implements DnsResolver {
-
- private InitialContextFactory ctxFactory = new DefaultInitialContextFactory();
-
- /**
- * Allows to inject an own JNDI context factory.
- *
- * @param ctxFactory factory to use, when a DirContext is needed
- * @see InitialDirContext
- * @see DirContext
- */
- public void setCtxFactory(InitialContextFactory ctxFactory) {
- this.ctxFactory = ctxFactory;
- }
-
- /* (non-Javadoc)
- * @see org.springframework.security.remoting.dns.DnsResolver#resolveIpAddress(java.lang.String)
- */
- public String resolveIpAddress(String hostname) {
- return resolveIpAddress(hostname, ctxFactory.getCtx());
- }
-
- /* (non-Javadoc)
- * @see org.springframework.security.remoting.dns.DnsResolver#resolveServiceEntry(java.lang.String, java.lang.String)
- */
- public String resolveServiceEntry(String serviceType, String domain) {
- return resolveServiceEntry(serviceType, domain, ctxFactory.getCtx());
- }
-
- /* (non-Javadoc)
- * @see org.springframework.security.remoting.dns.DnsResolver#resolveServiceIpAddress(java.lang.String, java.lang.String)
- */
- public String resolveServiceIpAddress(String serviceType, String domain) {
- DirContext ctx = ctxFactory.getCtx();
- String hostname = resolveServiceEntry(serviceType, domain, ctx);
- return resolveIpAddress(hostname, ctx);
- }
-
-
-
- // This method is needed, so that we can use only one DirContext for
- // resolveServiceIpAddress().
- private String resolveIpAddress(String hostname, DirContext ctx) {
- try {
- Attribute dnsRecord = lookup(hostname, ctx, "A");
- // There should be only one A record, therefore it is save to return
- // only the first.
- return dnsRecord.get().toString();
- } catch (NamingException e) {
- throw new DnsLookupException("DNS lookup failed for: "+ hostname, e);
- }
-
- }
-
- // This method is needed, so that we can use only one DirContext for
- // resolveServiceIpAddress().
- private String resolveServiceEntry(String serviceType, String domain, DirContext ctx) {
- String result = null;
- try {
- String query = new StringBuilder("_").append(serviceType).append("._tcp.").append(domain).toString();
- Attribute dnsRecord = lookup(query, ctx, "SRV");
- // There are maybe more records defined, we will return the one
- // with the highest priority (lowest number) and the highest weight
- // (highest number)
- int highestPriority = -1;
- int highestWeight = -1;
-
- for (NamingEnumeration<?> recordEnum = dnsRecord.getAll(); recordEnum.hasMoreElements();) {
- String[] record = recordEnum.next().toString().split(" ");
- if (record.length != 4) {
- throw new DnsLookupException("Wrong service record for query " + query + ": [" + record + "]");
- }
- int priority = Integer.parseInt(record[0]);
- int weight = Integer.parseInt(record[1]);
- // we have a new highest Priority, so forget also the highest weight
- if (priority < highestPriority || highestPriority == -1) {
- highestPriority = priority;
- highestWeight = weight;
- result = record[3].trim();
- }
- // same priority, but higher weight
- if (priority == highestPriority && weight > highestWeight) {
- highestWeight = weight;
- result = record[3].trim();
- }
- }
- } catch (NamingException e) {
- throw new DnsLookupException("DNS lookup failed for service " + serviceType + " at " + domain, e);
- }
-
- // remove the "." at the end
- if (result.endsWith(".")) {
- result = result.substring(0, result.length() - 1);
- }
- return result;
- }
-
- private Attribute lookup(String query, DirContext ictx, String recordType) {
- try {
- Attributes dnsResult = ictx.getAttributes(query, new String[] { recordType });
- Attribute dnsRecord = dnsResult.get(recordType);
- return dnsRecord;
- } catch (NamingException e) {
- if (e instanceof NameNotFoundException) {
- throw new DnsEntryNotFoundException("DNS entry not found for:" + query, e);
- }
- throw new DnsLookupException("DNS lookup failed for: " + query, e);
- }
- }
-
-
- private static class DefaultInitialContextFactory implements InitialContextFactory {
-
- public DirContext getCtx() {
- Hashtable<String, String> env = new Hashtable<String, String>();
- env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.dns.DnsContextFactory");
- env.put(Context.PROVIDER_URL, "dns:"); // This is needed for IBM JDK/JRE
- InitialDirContext ictx;
- try {
- ictx = new InitialDirContext(env);
- } catch (NamingException e) {
- throw new DnsLookupException("Cannot create InitialDirContext for DNS lookup", e);
- }
- return ictx;
- }
- }
-}
diff --git a/dist/spring-security-core/org/springframework/security/remoting/dns/package-info.java b/dist/spring-security-core/org/springframework/security/remoting/dns/package-info.java
deleted file mode 100644
index 3144434..0000000
--- a/dist/spring-security-core/org/springframework/security/remoting/dns/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * DNS resolution.
- */
-package org.springframework.security.remoting.dns;
diff --git a/dist/spring-security-core/org/springframework/security/remoting/httpinvoker/AuthenticationSimpleHttpInvokerRequestExecutor.java b/dist/spring-security-core/org/springframework/security/remoting/httpinvoker/AuthenticationSimpleHttpInvokerRequestExecutor.java
deleted file mode 100644
index 6bde4a9..0000000
--- a/dist/spring-security-core/org/springframework/security/remoting/httpinvoker/AuthenticationSimpleHttpInvokerRequestExecutor.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/* Copyright 2004, 2005, 2006 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.remoting.httpinvoker;
-
-import java.io.IOException;
-import java.net.HttpURLConnection;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.remoting.httpinvoker.SimpleHttpInvokerRequestExecutor;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.codec.Base64;
-import org.springframework.security.core.context.SecurityContextHolder;
-
-
-/**
- * Adds BASIC authentication support to <code>SimpleHttpInvokerRequestExecutor</code>.
- *
- * @author Ben Alex
- */
-public class AuthenticationSimpleHttpInvokerRequestExecutor extends SimpleHttpInvokerRequestExecutor {
- //~ Static fields/initializers =====================================================================================
-
- private static final Log logger = LogFactory.getLog(AuthenticationSimpleHttpInvokerRequestExecutor.class);
-
- //~ Methods ========================================================================================================
-
- /**
- * Provided so subclasses can perform additional configuration if required (eg set additional request
- * headers for non-security related information etc).
- *
- * @param con the HTTP connection to prepare
- * @param contentLength the length of the content to send
- *
- * @throws IOException if thrown by HttpURLConnection methods
- */
- protected void doPrepareConnection(HttpURLConnection con, int contentLength)
- throws IOException {}
-
- /**
- * Called every time a HTTP invocation is made.<p>Simply allows the parent to setup the connection, and
- * then adds an <code>Authorization</code> HTTP header property that will be used for BASIC authentication.</p>
- * <p>The <code>SecurityContextHolder</code> is used to obtain the relevant principal and credentials.</p>
- *
- * @param con the HTTP connection to prepare
- * @param contentLength the length of the content to send
- *
- * @throws IOException if thrown by HttpURLConnection methods
- */
- protected void prepareConnection(HttpURLConnection con, int contentLength) throws IOException {
- super.prepareConnection(con, contentLength);
-
- Authentication auth = SecurityContextHolder.getContext().getAuthentication();
-
- if ((auth != null) && (auth.getName() != null) && (auth.getCredentials() != null)) {
- String base64 = auth.getName() + ":" + auth.getCredentials().toString();
- con.setRequestProperty("Authorization", "Basic " + new String(Base64.encode(base64.getBytes())));
-
- if (logger.isDebugEnabled()) {
- logger.debug("HttpInvocation now presenting via BASIC authentication SecurityContextHolder-derived: "
- + auth.toString());
- }
- } else {
- if (logger.isDebugEnabled()) {
- logger.debug("Unable to set BASIC authentication header as SecurityContext did not provide "
- + "valid Authentication: " + auth);
- }
- }
-
- doPrepareConnection(con, contentLength);
- }
-}
diff --git a/dist/spring-security-core/org/springframework/security/remoting/httpinvoker/package-info.java b/dist/spring-security-core/org/springframework/security/remoting/httpinvoker/package-info.java
deleted file mode 100644
index c8a9b99..0000000
--- a/dist/spring-security-core/org/springframework/security/remoting/httpinvoker/package-info.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Enables use of Spring's <code>HttpInvoker</code> extension points to
- * present the <code>principal</code> and <code>credentials</code> located
- * in the <code>ContextHolder</code> via BASIC authentication.
- * <p>
- * The beans are wired as follows:
- *
- * <pre>
- * <bean id="test" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
- * <property name="serviceUrl"><value>http://localhost/Test</value></property>
- * <property name="serviceInterface"><value>test.TargetInterface</value></property>
- * <property name="httpInvokerRequestExecutor"><ref bean="httpInvokerRequestExecutor"/></property>
- * </bean>
- *
- * <bean id="httpInvokerRequestExecutor"
- * class="org.springframework.security.core.context.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor"/>
- * </pre>
- */
-package org.springframework.security.remoting.httpinvoker;
diff --git a/dist/spring-security-core/org/springframework/security/remoting/package-info.java b/dist/spring-security-core/org/springframework/security/remoting/package-info.java
deleted file mode 100644
index caa6c8a..0000000
--- a/dist/spring-security-core/org/springframework/security/remoting/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * Remote client related functionality.
- */
-package org.springframework.security.remoting;
diff --git a/dist/spring-security-core/org/springframework/security/remoting/rmi/ContextPropagatingRemoteInvocation.java b/dist/spring-security-core/org/springframework/security/remoting/rmi/ContextPropagatingRemoteInvocation.java
deleted file mode 100644
index 3822e45..0000000
--- a/dist/spring-security-core/org/springframework/security/remoting/rmi/ContextPropagatingRemoteInvocation.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/* Copyright 2004, 2005, 2006 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.remoting.rmi;
-
-import org.springframework.security.core.context.SecurityContext;
-import org.springframework.security.core.context.SecurityContextHolder;
-
-import org.aopalliance.intercept.MethodInvocation;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.springframework.remoting.support.RemoteInvocation;
-
-import java.lang.reflect.InvocationTargetException;
-
-
-/**
- * The actual <code>RemoteInvocation</code> that is passed from the client to the server, which contains the
- * contents of {@link SecurityContextHolder}, being a {@link SecurityContext} object.
- * <p>
- * When constructed on the client via {@link ContextPropagatingRemoteInvocationFactory}, the contents of the
- * <code>SecurityContext</code> are stored inside the object. The object is then passed to the server that is
- * processing the remote invocation. Upon the server invoking the remote invocation, it will retrieve the passed
- * contents of the <code>SecurityContextHolder</code> and set them on the server-side
- * <code>SecurityContextHolder</code> while the target object is invoked. When the target invocation has been
- * completed, the security context will be cleared using a call to {@link SecurityContextHolder#clearContext()}.
- *
- * @author James Monaghan
- * @author Ben Alex
- */
-public class ContextPropagatingRemoteInvocation extends RemoteInvocation {
- //~ Static fields/initializers =====================================================================================
-
- private static final Log logger = LogFactory.getLog(ContextPropagatingRemoteInvocation.class);
-
- //~ Instance fields ================================================================================================
-
- private SecurityContext securityContext;
-
- //~ Constructors ===================================================================================================
-
- /**
- * Constructs the object, storing the value of the client-side
- * <code>SecurityContextHolder</code> inside the object.
- *
- * @param methodInvocation the method to invoke
- */
- public ContextPropagatingRemoteInvocation(MethodInvocation methodInvocation) {
- super(methodInvocation);
- securityContext = SecurityContextHolder.getContext();
-
- if (logger.isDebugEnabled()) {
- logger.debug("RemoteInvocation now has SecurityContext: " + securityContext);
- }
- }
-
- //~ Methods ========================================================================================================
-
- /**
- * Invoked on the server-side as described in the class JavaDocs.
- * <p>
- * Invocations will always have their {@link org.springframework.security.core.Authentication#setAuthenticated(boolean)}
- * set to <code>false</code>, which is guaranteed to always be accepted by <code>Authentication</code>
- * implementations. This ensures that even remotely authenticated <code>Authentication</code>s will be untrusted by
- * the server-side, which is an appropriate security measure.
- *
- * @param targetObject the target object to apply the invocation to
- *
- * @return the invocation result
- *
- * @throws NoSuchMethodException if the method name could not be resolved
- * @throws IllegalAccessException if the method could not be accessed
- * @throws InvocationTargetException if the method invocation resulted in an exception
- */
- public Object invoke(Object targetObject)
- throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
- SecurityContextHolder.setContext(securityContext);
-
- if ((SecurityContextHolder.getContext() != null)
- && (SecurityContextHolder.getContext().getAuthentication() != null)) {
- SecurityContextHolder.getContext().getAuthentication().setAuthenticated(false);
- }
-
- if (logger.isDebugEnabled()) {
- logger.debug("Set SecurityContextHolder to contain: " + securityContext);
- }
-
- try {
- return super.invoke(targetObject);
- } finally {
- SecurityContextHolder.clearContext();
-
- if (logger.isDebugEnabled()) {
- logger.debug("Cleared SecurityContextHolder.");
- }
- }
- }
-}
diff --git a/dist/spring-security-core/org/springframework/security/remoting/rmi/ContextPropagatingRemoteInvocationFactory.java b/dist/spring-security-core/org/springframework/security/remoting/rmi/ContextPropagatingRemoteInvocationFactory.java
deleted file mode 100644
index 300ae3e..0000000
--- a/dist/spring-security-core/org/springframework/security/remoting/rmi/ContextPropagatingRemoteInvocationFactory.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/* Copyright 2004, 2005, 2006 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.remoting.rmi;
-
-import org.aopalliance.intercept.MethodInvocation;
-
-import org.springframework.remoting.support.RemoteInvocation;
-import org.springframework.remoting.support.RemoteInvocationFactory;
-
-
-/**
- * Called by a client-side instance of <code>org.springframework.remoting.rmi.RmiProxyFactoryBean</code> when it
- * wishes to create a remote invocation.<P>Set an instance of this bean against the above class'
- * <code>remoteInvocationFactory</code> property.</p>
- *
- * @author James Monaghan
- * @author Ben Alex
- */
-public class ContextPropagatingRemoteInvocationFactory implements RemoteInvocationFactory {
- //~ Methods ========================================================================================================
-
- public RemoteInvocation createRemoteInvocation(MethodInvocation methodInvocation) {
- return new ContextPropagatingRemoteInvocation(methodInvocation);
- }
-}
diff --git a/dist/spring-security-core/org/springframework/security/remoting/rmi/package-info.java b/dist/spring-security-core/org/springframework/security/remoting/rmi/package-info.java
deleted file mode 100644
index 4ed18fc..0000000
--- a/dist/spring-security-core/org/springframework/security/remoting/rmi/package-info.java
+++ /dev/null
@@ -1,18 +0,0 @@
-/**
- * Enables use of Spring's RMI remoting extension points to propagate the <code>SecurityContextHolder</code> (which
- * should contain an <code>Authentication</code> request token) from one JVM to the remote JVM.
- * <p>
- * The beans are wired as follows:
- * <pre>
- * <bean id="test" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
- * <property name="serviceUrl"><value>rmi://localhost/Test</value></property>
- * <property name="serviceInterface"><value>test.TargetInterface</value></property>
- * <property name="refreshStubOnConnectFailure"><value>true</value></property>
- * <property name="remoteInvocationFactory"><ref bean="remoteInvocationFactory"/></property>
- * </bean>
- *
- * <bean id="remoteInvocationFactory"
- * class="org.springframework.security.remoting.rmi.ContextPropagatingRemoteInvocationFactory"/>
- * </pre>
- */
-package org.springframework.security.remoting.rmi;
diff --git a/dist/spring-security-core/org/springframework/security/util/EncryptionUtils.java b/dist/spring-security-core/org/springframework/security/util/EncryptionUtils.java
deleted file mode 100644
index 0d6da09..0000000
--- a/dist/spring-security-core/org/springframework/security/util/EncryptionUtils.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/* Copyright 2004, 2005, 2006 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.util;
-
-import java.io.UnsupportedEncodingException;
-import java.security.spec.KeySpec;
-
-import javax.crypto.Cipher;
-import javax.crypto.SecretKey;
-import javax.crypto.SecretKeyFactory;
-import javax.crypto.spec.DESedeKeySpec;
-
-import org.springframework.core.NestedRuntimeException;
-import org.springframework.security.core.codec.Base64;
-import org.springframework.util.Assert;
-
-/**
- * A static utility class that can encrypt and decrypt text.
- *
- * <p>This class is useful if you have simple needs and wish to use the DESede
- * encryption cipher. More sophisticated requirements will need to use the
- * Java crypto libraries directly.
- *
- * @author Alan Stewart
- * @author Ben Alex
- * @deprecated Use a dedicated encryption library instead.
- */
- at Deprecated
-public final class EncryptionUtils {
-
- /**
- * This is a static class that should not be instantiated.
- */
- private EncryptionUtils() {}
-
- /**
- * Converts a String into a byte array using UTF-8, falling back to the
- * platform's default character set if UTF-8 fails.
- *
- * @param input the input (required)
- * @return a byte array representation of the input string
- */
- public static byte[] stringToByteArray(String input) {
- Assert.hasLength(input, "Input required");
- try {
- return input.getBytes("UTF-8");
- } catch (UnsupportedEncodingException fallbackToDefault) {
- return input.getBytes();
- }
- }
-
- /**
- * Converts a byte array into a String using UTF-8, falling back to the
- * platform's default character set if UTF-8 fails.
- *
- * @param byteArray the byte array to convert (required)
- * @return a string representation of the byte array
- */
- public static String byteArrayToString(byte[] byteArray) {
- Assert.notNull(byteArray, "ByteArray required");
- Assert.isTrue(byteArray.length > 0, "ByteArray cannot be empty");
- try {
- return new String(byteArray, "UTF8");
- } catch (final UnsupportedEncodingException e) {
- return new String(byteArray);
- }
- }
-
- private static byte[] cipher(String key, byte[] passedBytes, int cipherMode) throws EncryptionException {
- try {
- final KeySpec keySpec = new DESedeKeySpec(stringToByteArray(key));
- final SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
- final Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
- final SecretKey secretKey = keyFactory.generateSecret(keySpec);
- cipher.init(cipherMode, secretKey);
- return cipher.doFinal(passedBytes);
- } catch (final Exception e) {
- throw new EncryptionException(e.getMessage(), e);
- }
- }
-
- /**
- * Encrypts the inputString using the key.
- *
- * @param key at least 24 character long key (required)
- * @param inputString the string to encrypt (required)
- * @return the encrypted version of the inputString
- * @throws EncryptionException in the event of an encryption failure
- */
- public static String encrypt(String key, String inputString) throws EncryptionException {
- isValidKey(key);
- final byte[] cipherText = cipher(key, stringToByteArray(inputString), Cipher.ENCRYPT_MODE);
- return byteArrayToString(Base64.encode(cipherText));
- }
-
- /**
- * Encrypts the inputBytes using the key.
- *
- * @param key at least 24 character long key (required)
- * @param inputBytes the bytes to encrypt (required)
- * @return the encrypted version of the inputBytes
- * @throws EncryptionException in the event of an encryption failure
- */
- public static byte[] encrypt(String key, byte[] inputBytes) throws EncryptionException {
- isValidKey(key);
- return Base64.encode(cipher(key, inputBytes, Cipher.ENCRYPT_MODE));
- }
-
- /**
- * Decrypts the inputString using the key.
- *
- * @param key the key used to originally encrypt the string (required)
- * @param inputString the encrypted string (required)
- * @return the decrypted version of inputString
- * @throws EncryptionException in the event of an encryption failure
- */
- public static String decrypt(String key, String inputString) throws EncryptionException {
- Assert.hasText(key, "A key is required to attempt decryption");
- final byte[] cipherText = cipher(key, Base64.decode(stringToByteArray(inputString)), Cipher.DECRYPT_MODE);
- return byteArrayToString(cipherText);
- }
-
- /**
- * Decrypts the inputBytes using the key.
- *
- * @param key the key used to originally encrypt the string (required)
- * @param inputBytes the encrypted bytes (required)
- * @return the decrypted version of inputBytes
- * @throws EncryptionException in the event of an encryption failure
- */
- public static byte[] decrypt(String key, byte[] inputBytes) throws EncryptionException {
- Assert.hasText(key, "A key is required to attempt decryption");
- return cipher(key, Base64.decode(inputBytes), Cipher.DECRYPT_MODE);
- }
-
- private static void isValidKey(String key) {
- Assert.hasText(key, "A key to perform the encryption is required");
- Assert.isTrue(key.length() >= 24, "Key must be at least 24 characters long");
- }
-
- public static class EncryptionException extends NestedRuntimeException {
- private static final long serialVersionUID = 1L;
-
- public EncryptionException(String message, Throwable t) {
- super(message, t);
- }
-
- public EncryptionException(String message) {
- super(message);
- }
- }
-}
diff --git a/dist/spring-security-core/org/springframework/security/util/FieldUtils.java b/dist/spring-security-core/org/springframework/security/util/FieldUtils.java
index 6387a7f..3be3091 100644
--- a/dist/spring-security-core/org/springframework/security/util/FieldUtils.java
+++ b/dist/spring-security-core/org/springframework/security/util/FieldUtils.java
@@ -23,29 +23,13 @@ import java.lang.reflect.Field;
/**
- * Offers static methods for directly manipulating static fields.
+ * Offers static methods for directly manipulating fields.
*
* @author Ben Alex
*/
public final class FieldUtils {
- //~ Constructors ===================================================================================================
-
- private FieldUtils() {
- }
//~ Methods ========================================================================================================
-
- public static String getAccessorName(String fieldName, Class<?> type) {
- Assert.hasText(fieldName, "FieldName required");
- Assert.notNull(type, "Type required");
-
- if (type.getName().equals("boolean")) {
- return "is" + org.springframework.util.StringUtils.capitalize(fieldName);
- } else {
- return "get" + org.springframework.util.StringUtils.capitalize(fieldName);
- }
- }
-
/**
* Attempts to locate the specified field on the class.
*
@@ -83,11 +67,10 @@ public final class FieldUtils {
Assert.hasText(fieldName, "Field name required");
String[] nestedFields = StringUtils.tokenizeToStringArray(fieldName, ".");
Class<?> componentClass = bean.getClass();
- Field field = null;
Object value = bean;
- for (int i=0; i < nestedFields.length; i++) {
- field = getField(componentClass, nestedFields[i]);
+ for (String nestedField : nestedFields) {
+ Field field = getField(componentClass, nestedField);
field.setAccessible(true);
value = field.get(value);
if (value != null) {
@@ -99,12 +82,6 @@ public final class FieldUtils {
}
- public static String getMutatorName(String fieldName) {
- Assert.hasText(fieldName, "FieldName required");
-
- return "set" + org.springframework.util.StringUtils.capitalize(fieldName);
- }
-
public static Object getProtectedFieldValue(String protectedField, Object object) {
Field field = FieldUtils.getField(object.getClass(), protectedField);
diff --git a/dist/spring-security-core/org/springframework/security/util/InMemoryResource.java b/dist/spring-security-core/org/springframework/security/util/InMemoryResource.java
index b595536..7821009 100644
--- a/dist/spring-security-core/org/springframework/security/util/InMemoryResource.java
+++ b/dist/spring-security-core/org/springframework/security/util/InMemoryResource.java
@@ -33,8 +33,8 @@ import java.util.Arrays;
public class InMemoryResource extends AbstractResource {
//~ Instance fields ================================================================================================
- private byte[] source;
- private String description;
+ private final byte[] source;
+ private final String description;
//~ Constructors ===================================================================================================
@@ -63,7 +63,7 @@ public class InMemoryResource extends AbstractResource {
}
public int hashCode() {
- return source.hashCode();
+ return 1;
}
public boolean equals(Object res) {
diff --git a/dist/spring-security-core/org/springframework/security/util/MethodInvocationUtils.java b/dist/spring-security-core/org/springframework/security/util/MethodInvocationUtils.java
index 99a079a..0d98741 100644
--- a/dist/spring-security-core/org/springframework/security/util/MethodInvocationUtils.java
+++ b/dist/spring-security-core/org/springframework/security/util/MethodInvocationUtils.java
@@ -31,10 +31,6 @@ import org.springframework.util.Assert;
* @author Ben Alex
*/
public final class MethodInvocationUtils {
- //~ Constructors ===================================================================================================
-
- private MethodInvocationUtils() {
- }
//~ Methods ========================================================================================================
@@ -67,13 +63,15 @@ public final class MethodInvocationUtils {
Advised a = (Advised) object;
if (!a.isProxyTargetClass()) {
Class<?>[] possibleInterfaces = a.getProxiedInterfaces();
- for (int i = 0; i < possibleInterfaces.length; i++) {
+ for (Class<?> possibleInterface : possibleInterfaces) {
try {
- possibleInterfaces[i].getMethod(methodName, classArgs);
+ possibleInterface.getMethod(methodName, classArgs);
// to get here means no exception happened
- target = possibleInterfaces[i];
+ target = possibleInterface;
break;
- } catch (Exception tryTheNextOne) {}
+ } catch (Exception ignored) {
+ // try the next one
+ }
}
}
}
diff --git a/dist/spring-security-ldap/META-INF/MANIFEST.MF b/dist/spring-security-ldap/META-INF/MANIFEST.MF
index 351fd34..58630c0 100644
--- a/dist/spring-security-ldap/META-INF/MANIFEST.MF
+++ b/dist/spring-security-ldap/META-INF/MANIFEST.MF
@@ -1,4 +1,2 @@
Manifest-Version: 1.0
-Archiver-Version: Plexus Archiver
-Created-By: 17.1-b03-307 (Apple Inc.)
diff --git a/dist/spring-security-ldap/org/springframework/security/ldap/DefaultLdapUsernameToDnMapper.java b/dist/spring-security-ldap/org/springframework/security/ldap/DefaultLdapUsernameToDnMapper.java
index f936058..282629d 100644
--- a/dist/spring-security-ldap/org/springframework/security/ldap/DefaultLdapUsernameToDnMapper.java
+++ b/dist/spring-security-ldap/org/springframework/security/ldap/DefaultLdapUsernameToDnMapper.java
@@ -11,8 +11,8 @@ import org.springframework.ldap.core.DistinguishedName;
* @author Luke Taylor
*/
public class DefaultLdapUsernameToDnMapper implements LdapUsernameToDnMapper {
- private String userDnBase;
- private String usernameAttribute;
+ private final String userDnBase;
+ private final String usernameAttribute;
/**
* @param userDnBase the base name of the DN
diff --git a/dist/spring-security-ldap/org/springframework/security/ldap/DefaultSpringSecurityContextSource.java b/dist/spring-security-ldap/org/springframework/security/ldap/DefaultSpringSecurityContextSource.java
index 719380f..d7492c9 100644
--- a/dist/spring-security-ldap/org/springframework/security/ldap/DefaultSpringSecurityContextSource.java
+++ b/dist/spring-security-ldap/org/springframework/security/ldap/DefaultSpringSecurityContextSource.java
@@ -2,6 +2,7 @@ package org.springframework.security.ldap;
import java.util.ArrayList;
import java.util.Hashtable;
+import java.util.List;
import java.util.StringTokenizer;
import org.apache.commons.logging.Log;
@@ -15,7 +16,7 @@ import org.springframework.util.Assert;
* ContextSource implementation which uses Spring LDAP's <tt>LdapContextSource</tt> as a base
* class. Used internally by the Spring Security LDAP namespace configuration.
* <p>
- * From Spring Security 2.5, Spring LDAP 1.3 is used and the <tt>ContextSource</tt> interface
+ * From Spring Security 3.0, Spring LDAP 1.3 is used and the <tt>ContextSource</tt> interface
* provides support for binding with a username and password. As a result, Spring LDAP <tt>ContextSource</tt>
* implementations such as <tt>LdapContextSource</tt> may be used directly with Spring Security.
* <p>
@@ -33,7 +34,9 @@ public class DefaultSpringSecurityContextSource extends LdapContextSource {
private String rootDn;
/**
- * Create and initialize an instance which will connect to the supplied LDAP URL.
+ * Create and initialize an instance which will connect to the supplied LDAP URL. If you
+ * want to use more than one server for fail-over, rather use
+ * the {@link #DefaultSpringSecurityContextSource(List, String)} constructor.
*
* @param providerUrl an LDAP URL of the form <code>ldap://localhost:389/base_dn<code>
*/
@@ -76,4 +79,64 @@ public class DefaultSpringSecurityContextSource extends LdapContextSource {
}
});
}
+
+ /**
+ * Create and initialize an instance which will connect of the LDAP Spring Security
+ * Context Source. It will connect to any of the provided LDAP server URLs.
+ *
+ * @param urls
+ * A list of string values which are LDAP server URLs. An example would be
+ * <code>ldap://ldap.company.com:389</code>. LDAPS URLs (SSL-secured) may be used as well,
+ * given that Spring Security is able to connect to the server.
+ * Note that these <b>URLs must not include the base DN</b>!
+ * @param baseDn
+ * The common Base DN for all provided servers, e.g.
+ * <pre>dc=company,dc=com</pre>.
+ */
+ public DefaultSpringSecurityContextSource(List<String> urls, String baseDn) {
+ this(buildProviderUrl(urls, baseDn));
+ }
+
+ /**
+ * Builds a Spring LDAP-compliant Provider URL string, i.e. a space-separated list of LDAP servers
+ * with their base DNs. As the base DN must be identical for all servers, it needs to be supplied
+ * only once.
+ *
+ * @param urls
+ * A list of string values which are LDAP server URLs. An example would be
+ * <pre>ldap://ldap.company.com:389</pre>. LDAPS URLs may be used as well,
+ * given that Spring Security is able to connect to the server.
+ * @param baseDn
+ * The common Base DN for all provided servers, e.g.
+ * <pre>dc=company,dc=com</pre>.
+ * @return A Spring Security/Spring LDAP-compliant Provider URL string.
+ */
+ private static String buildProviderUrl(List<String> urls, String baseDn) {
+ Assert.notNull(baseDn, "The Base DN for the LDAP server must not be null.");
+ Assert.notEmpty(urls, "At least one LDAP server URL must be provided.");
+
+ String trimmedBaseDn = baseDn.trim();
+ StringBuilder providerUrl = new StringBuilder();
+
+ for (String serverUrl : urls) {
+ String trimmedUrl = serverUrl.trim();
+ if ("".equals(trimmedUrl)) {
+ continue;
+ }
+ if (trimmedUrl.contains(trimmedBaseDn)) {
+ throw new IllegalArgumentException("LDAP URL string must not include the base DN! '" + trimmedUrl + "'");
+ }
+
+ providerUrl.append(trimmedUrl);
+ if (! trimmedUrl.endsWith("/")) {
+ providerUrl.append("/");
+ }
+ providerUrl.append(trimmedBaseDn);
+ providerUrl.append(" ");
+ }
+
+ return providerUrl.toString();
+
+ }
+
}
diff --git a/dist/spring-security-ldap/org/springframework/security/ldap/LdapUtils.java b/dist/spring-security-ldap/org/springframework/security/ldap/LdapUtils.java
index 3d88557..4254002 100644
--- a/dist/spring-security-ldap/org/springframework/security/ldap/LdapUtils.java
+++ b/dist/spring-security-ldap/org/springframework/security/ldap/LdapUtils.java
@@ -17,6 +17,7 @@ package org.springframework.security.ldap;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DistinguishedName;
+import org.springframework.security.crypto.codec.Utf8;
import org.springframework.util.Assert;
import org.apache.commons.logging.Log;
@@ -25,7 +26,6 @@ import org.apache.commons.logging.LogFactory;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
-import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
@@ -123,29 +123,11 @@ public final class LdapUtils {
return baseDn;
}
- public static byte[] getUtf8Bytes(String s) {
- try {
- return s.getBytes("UTF-8");
- } catch (UnsupportedEncodingException e) {
- // Should be impossible since UTF-8 is required by all implementations
- throw new IllegalStateException("Failed to convert string to UTF-8 bytes. Shouldn't be possible");
- }
- }
-
- public static String getUtf8BytesAsString(byte[] utf8) {
- try {
- return new String(utf8, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- // Should be impossible since UTF-8 is required by all implementations
- throw new IllegalStateException("Failed to convert string to UTF-8 bytes. Shouldn't be possible");
- }
- }
-
public static String convertPasswordToString(Object passObj) {
Assert.notNull(passObj, "Password object to convert must not be null");
if(passObj instanceof byte[]) {
- return getUtf8BytesAsString((byte[])passObj);
+ return Utf8.decode((byte[])passObj);
} else if (passObj instanceof String) {
return (String)passObj;
} else {
@@ -164,7 +146,7 @@ public final class LdapUtils {
public static String parseRootDnFromUrl(String url) {
Assert.hasLength(url);
- String urlRootDn = "";
+ String urlRootDn;
if (url.startsWith("ldap:") || url.startsWith("ldaps:")) {
URI uri = parseLdapUrl(url);
diff --git a/dist/spring-security-ldap/org/springframework/security/ldap/SpringSecurityLdapTemplate.java b/dist/spring-security-ldap/org/springframework/security/ldap/SpringSecurityLdapTemplate.java
index 384de30..835c658 100644
--- a/dist/spring-security-ldap/org/springframework/security/ldap/SpringSecurityLdapTemplate.java
+++ b/dist/spring-security-ldap/org/springframework/security/ldap/SpringSecurityLdapTemplate.java
@@ -20,6 +20,7 @@ import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
+import javax.naming.CompositeName;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.PartialResultException;
@@ -194,45 +195,55 @@ public class SpringSecurityLdapTemplate extends LdapTemplate {
return (DirContextOperations) executeReadOnly(new ContextExecutor() {
public Object executeWithContext(DirContext ctx) throws NamingException {
- DistinguishedName ctxBaseDn = new DistinguishedName(ctx.getNameInNamespace());
- NamingEnumeration<SearchResult> resultsEnum = ctx.search(base, filter, params, searchControls);
- if (logger.isDebugEnabled()) {
- logger.debug("Searching for entry in under DN '" + ctxBaseDn
- + "', base = '" + base + "', filter = '" + filter + "'");
- }
-
- Set<DirContextOperations> results = new HashSet<DirContextOperations>();
- try {
- while (resultsEnum.hasMore()) {
- SearchResult searchResult = resultsEnum.next();
- // Work out the DN of the matched entry
- DistinguishedName dn = new DistinguishedName(searchResult.getName());
-
- if (base.length() > 0) {
- dn.prepend(new DistinguishedName(base));
- }
-
- if (logger.isDebugEnabled()) {
- logger.debug("Found DN: " + dn);
- }
- results.add(new DirContextAdapter(searchResult.getAttributes(), dn, ctxBaseDn));
- }
- } catch (PartialResultException e) {
- LdapUtils.closeEnumeration(resultsEnum);
- logger.info("Ignoring PartialResultException");
- }
-
- if (results.size() == 0) {
- throw new IncorrectResultSizeDataAccessException(1, 0);
- }
-
- if (results.size() > 1) {
- throw new IncorrectResultSizeDataAccessException(1, results.size());
- }
-
- return results.toArray()[0];
+ return searchForSingleEntryInternal(ctx, searchControls, base, filter, params);
}
- });
+ });
+ }
+
+ /**
+ * Internal method extracted to avoid code duplication in AD search.
+ */
+ public static DirContextOperations searchForSingleEntryInternal(DirContext ctx, SearchControls searchControls,
+ String base, String filter, Object[] params) throws NamingException {
+ final DistinguishedName ctxBaseDn = new DistinguishedName(ctx.getNameInNamespace());
+ final DistinguishedName searchBaseDn = new DistinguishedName(base);
+ final NamingEnumeration<SearchResult> resultsEnum = ctx.search(searchBaseDn, filter, params, searchControls);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Searching for entry under DN '" + ctxBaseDn
+ + "', base = '" + searchBaseDn + "', filter = '" + filter + "'");
+ }
+
+ Set<DirContextOperations> results = new HashSet<DirContextOperations>();
+ try {
+ while (resultsEnum.hasMore()) {
+ SearchResult searchResult = resultsEnum.next();
+ // Work out the DN of the matched entry
+ DistinguishedName dn = new DistinguishedName(new CompositeName(searchResult.getName()));
+
+ if (base.length() > 0) {
+ dn.prepend(searchBaseDn);
+ }
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Found DN: " + dn);
+ }
+ results.add(new DirContextAdapter(searchResult.getAttributes(), dn, ctxBaseDn));
+ }
+ } catch (PartialResultException e) {
+ LdapUtils.closeEnumeration(resultsEnum);
+ logger.info("Ignoring PartialResultException");
+ }
+
+ if (results.size() == 0) {
+ throw new IncorrectResultSizeDataAccessException(1, 0);
+ }
+
+ if (results.size() > 1) {
+ throw new IncorrectResultSizeDataAccessException(1, results.size());
+ }
+
+ return results.iterator().next();
}
/**
diff --git a/dist/spring-security-ldap/org/springframework/security/ldap/authentication/AbstractLdapAuthenticator.java b/dist/spring-security-ldap/org/springframework/security/ldap/authentication/AbstractLdapAuthenticator.java
index 580b367..23e3072 100644
--- a/dist/spring-security-ldap/org/springframework/security/ldap/authentication/AbstractLdapAuthenticator.java
+++ b/dist/spring-security-ldap/org/springframework/security/ldap/authentication/AbstractLdapAuthenticator.java
@@ -15,6 +15,7 @@
package org.springframework.security.ldap.authentication;
+import org.springframework.ldap.core.LdapEncoder;
import org.springframework.security.core.SpringSecurityMessageSource;
import org.springframework.security.ldap.search.LdapUserSearch;
import org.springframework.beans.factory.InitializingBean;
@@ -38,7 +39,7 @@ import java.util.List;
public abstract class AbstractLdapAuthenticator implements LdapAuthenticator, InitializingBean, MessageSourceAware {
//~ Instance fields ================================================================================================
- private ContextSource contextSource;
+ private final ContextSource contextSource;
/** Optional search object which can be used to locate a user when a simple DN match isn't sufficient */
private LdapUserSearch userSearch;
@@ -91,11 +92,11 @@ public abstract class AbstractLdapAuthenticator implements LdapAuthenticator, In
}
List<String> userDns = new ArrayList<String>(userDnFormat.length);
- String[] args = new String[] {username};
+ String[] args = new String[] {LdapEncoder.nameEncode(username)};
synchronized (userDnFormat) {
- for (int i = 0; i < userDnFormat.length; i++) {
- userDns.add(userDnFormat[i].format(args));
+ for (MessageFormat formatter : userDnFormat) {
+ userDns.add(formatter.format(args));
}
}
diff --git a/dist/spring-security-ldap/org/springframework/security/ldap/authentication/BindAuthenticator.java b/dist/spring-security-ldap/org/springframework/security/ldap/authentication/BindAuthenticator.java
index 662023c..9ab1c79 100644
--- a/dist/spring-security-ldap/org/springframework/security/ldap/authentication/BindAuthenticator.java
+++ b/dist/spring-security-ldap/org/springframework/security/ldap/authentication/BindAuthenticator.java
@@ -72,7 +72,7 @@ public class BindAuthenticator extends AbstractLdapAuthenticator {
if (!StringUtils.hasLength(password)) {
logger.debug("Rejecting empty password for user " + username);
- throw new BadCredentialsException(messages.getMessage("LdapAuthenticationProvider.emptyPassword",
+ throw new BadCredentialsException(messages.getMessage("BindAuthenticator.emptyPassword",
"Empty Password"));
}
@@ -113,6 +113,8 @@ public class BindAuthenticator extends AbstractLdapAuthenticator {
// Check for password policy control
PasswordPolicyControl ppolicy = PasswordPolicyControlExtractor.extractControl(ctx);
+ logger.debug("Retrieving attributes...");
+
Attributes attrs = ctx.getAttributes(userDn, getUserAttributes());
DirContextAdapter result = new DirContextAdapter(attrs, userDn, ctxSource.getBaseLdapPath());
diff --git a/dist/spring-security-ldap/org/springframework/security/ldap/authentication/LdapAuthenticationProvider.java b/dist/spring-security-ldap/org/springframework/security/ldap/authentication/LdapAuthenticationProvider.java
index 7895675..e205c85 100644
--- a/dist/spring-security-ldap/org/springframework/security/ldap/authentication/LdapAuthenticationProvider.java
+++ b/dist/spring-security-ldap/org/springframework/security/ldap/authentication/LdapAuthenticationProvider.java
@@ -15,25 +15,13 @@
package org.springframework.security.ldap.authentication;
-import java.util.Collection;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.context.MessageSource;
-import org.springframework.context.MessageSourceAware;
-import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.ldap.NamingException;
import org.springframework.ldap.core.DirContextOperations;
-import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.SpringSecurityMessageSource;
-import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.ldap.ppolicy.PasswordPolicyException;
import org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator;
@@ -41,7 +29,8 @@ import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator;
import org.springframework.security.ldap.userdetails.LdapUserDetailsMapper;
import org.springframework.security.ldap.userdetails.UserDetailsContextMapper;
import org.springframework.util.Assert;
-import org.springframework.util.StringUtils;
+
+import java.util.*;
/**
@@ -87,15 +76,15 @@ import org.springframework.util.StringUtils;
* </bean>
*
* <bean id="ldapAuthProvider"
- * class="org.springframework.security.authentication.ldap.LdapAuthenticationProvider">
+ * class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
* <constructor-arg>
- * <bean class="org.springframework.security.authentication.ldap.authenticator.BindAuthenticator">
+ * <bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
* <constructor-arg ref="contextSource"/>
* <property name="userDnPatterns"><list><value>uid={0},ou=people</value></list></property>
* </bean>
* </constructor-arg>
* <constructor-arg>
- * <bean class="org.springframework.security.ldap.populator.DefaultLdapAuthoritiesPopulator">
+ * <bean class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
* <constructor-arg ref="contextSource"/>
* <constructor-arg value="ou=groups"/>
* <property name="groupRoleAttribute" value="ou"/>
@@ -126,19 +115,11 @@ import org.springframework.util.StringUtils;
* @see BindAuthenticator
* @see DefaultLdapAuthoritiesPopulator
*/
-public class LdapAuthenticationProvider implements AuthenticationProvider, MessageSourceAware {
- //~ Static fields/initializers =====================================================================================
-
- private static final Log logger = LogFactory.getLog(LdapAuthenticationProvider.class);
-
+public class LdapAuthenticationProvider extends AbstractLdapAuthenticationProvider {
//~ Instance fields ================================================================================================
- protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
-
private LdapAuthenticator authenticator;
private LdapAuthoritiesPopulator authoritiesPopulator;
- private UserDetailsContextMapper userDetailsContextMapper = new LdapUserDetailsMapper();
- private boolean useAuthenticationRequestCredentials = true;
private boolean hideUserNotFoundExceptions = true;
//~ Constructors ===================================================================================================
@@ -187,75 +168,14 @@ public class LdapAuthenticationProvider implements AuthenticationProvider, Messa
return authoritiesPopulator;
}
- /**
- * Allows a custom strategy to be used for creating the <tt>UserDetails</tt> which will be stored as the principal
- * in the <tt>Authentication</tt> returned by the
- * {@link #createSuccessfulAuthentication(UsernamePasswordAuthenticationToken, UserDetails)} method.
- *
- * @param userDetailsContextMapper the strategy instance. If not set, defaults to a simple
- * <tt>LdapUserDetailsMapper</tt>.
- */
- public void setUserDetailsContextMapper(UserDetailsContextMapper userDetailsContextMapper) {
- Assert.notNull(userDetailsContextMapper, "UserDetailsContextMapper must not be null");
- this.userDetailsContextMapper = userDetailsContextMapper;
- }
-
- /**
- * Provides access to the injected <tt>UserDetailsContextMapper</tt> strategy for use by subclasses.
- */
- protected UserDetailsContextMapper getUserDetailsContextMapper() {
- return userDetailsContextMapper;
- }
-
public void setHideUserNotFoundExceptions(boolean hideUserNotFoundExceptions) {
this.hideUserNotFoundExceptions = hideUserNotFoundExceptions;
}
- /**
- * Determines whether the supplied password will be used as the credentials in the successful authentication
- * token. If set to false, then the password will be obtained from the UserDetails object
- * created by the configured <tt>UserDetailsContextMapper</tt>.
- * Often it will not be possible to read the password from the directory, so defaults to true.
- *
- * @param useAuthenticationRequestCredentials
- */
- public void setUseAuthenticationRequestCredentials(boolean useAuthenticationRequestCredentials) {
- this.useAuthenticationRequestCredentials = useAuthenticationRequestCredentials;
- }
-
- public void setMessageSource(MessageSource messageSource) {
- this.messages = new MessageSourceAccessor(messageSource);
- }
-
- public Authentication authenticate(Authentication authentication) throws AuthenticationException {
- Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication,
- messages.getMessage("AbstractUserDetailsAuthenticationProvider.onlySupports",
- "Only UsernamePasswordAuthenticationToken is supported"));
-
- final UsernamePasswordAuthenticationToken userToken = (UsernamePasswordAuthenticationToken)authentication;
-
- String username = userToken.getName();
- String password = (String) authentication.getCredentials();
-
- if (logger.isDebugEnabled()) {
- logger.debug("Processing authentication request for user: " + username);
- }
-
- if (!StringUtils.hasLength(username)) {
- throw new BadCredentialsException(messages.getMessage("LdapAuthenticationProvider.emptyUsername",
- "Empty Username"));
- }
-
- Assert.notNull(password, "Null password was supplied in authentication token");
-
+ @Override
+ protected DirContextOperations doAuthentication(UsernamePasswordAuthenticationToken authentication) {
try {
- DirContextOperations userData = getAuthenticator().authenticate(authentication);
-
- Collection<GrantedAuthority> extraAuthorities = loadUserAuthorities(userData, username, password);
-
- UserDetails user = userDetailsContextMapper.mapUserFromContext(userData, username, extraAuthorities);
-
- return createSuccessfulAuthentication(userToken, user);
+ return getAuthenticator().authenticate(authentication);
} catch (PasswordPolicyException ppe) {
// The only reason a ppolicy exception can occur during a bind is that the account is locked.
throw new LockedException(messages.getMessage(ppe.getStatus().getErrorCode(),
@@ -272,29 +192,10 @@ public class LdapAuthenticationProvider implements AuthenticationProvider, Messa
}
}
- protected Collection<GrantedAuthority> loadUserAuthorities(DirContextOperations userData, String username, String password) {
+ @Override
+ protected Collection<? extends GrantedAuthority> loadUserAuthorities(DirContextOperations userData, String username, String password) {
return getAuthoritiesPopulator().getGrantedAuthorities(userData, username);
}
- /**
- * Creates the final <tt>Authentication</tt> object which will be returned from the <tt>authenticate</tt> method.
- *
- * @param authentication the original authentication request token
- * @param user the <tt>UserDetails</tt> instance returned by the configured <tt>UserDetailsContextMapper</tt>.
- * @return the Authentication object for the fully authenticated user.
- */
- protected Authentication createSuccessfulAuthentication(UsernamePasswordAuthenticationToken authentication,
- UserDetails user) {
- Object password = useAuthenticationRequestCredentials ? authentication.getCredentials() : user.getPassword();
-
- UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(user, password, user.getAuthorities());
- result.setDetails(authentication.getDetails());
-
- return result;
- }
-
- public boolean supports(Class<? extends Object> authentication) {
- return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
- }
}
diff --git a/dist/spring-security-ldap/org/springframework/security/ldap/authentication/PasswordComparisonAuthenticator.java b/dist/spring-security-ldap/org/springframework/security/ldap/authentication/PasswordComparisonAuthenticator.java
index e4faf24..9ce5da4 100644
--- a/dist/spring-security-ldap/org/springframework/security/ldap/authentication/PasswordComparisonAuthenticator.java
+++ b/dist/spring-security-ldap/org/springframework/security/ldap/authentication/PasswordComparisonAuthenticator.java
@@ -26,7 +26,7 @@ import org.springframework.security.authentication.encoding.LdapShaPasswordEncod
import org.springframework.security.authentication.encoding.PasswordEncoder;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
-import org.springframework.security.ldap.LdapUtils;
+import org.springframework.security.crypto.codec.Utf8;
import org.springframework.security.ldap.SpringSecurityLdapTemplate;
import org.springframework.util.Assert;
@@ -96,7 +96,7 @@ public final class PasswordComparisonAuthenticator extends AbstractLdapAuthentic
}
String encodedPassword = passwordEncoder.encodePassword(password, null);
- byte[] passwordBytes = LdapUtils.getUtf8Bytes(encodedPassword);
+ byte[] passwordBytes = Utf8.encode(encodedPassword);
if (!ldapTemplate.compare(user.getDn().toString(), passwordAttributeName, passwordBytes)) {
throw new BadCredentialsException(messages.getMessage("PasswordComparisonAuthenticator.badCredentials",
diff --git a/dist/spring-security-ldap/org/springframework/security/ldap/authentication/UserDetailsServiceLdapAuthoritiesPopulator.java b/dist/spring-security-ldap/org/springframework/security/ldap/authentication/UserDetailsServiceLdapAuthoritiesPopulator.java
index ce32d70..f95cb3f 100644
--- a/dist/spring-security-ldap/org/springframework/security/ldap/authentication/UserDetailsServiceLdapAuthoritiesPopulator.java
+++ b/dist/spring-security-ldap/org/springframework/security/ldap/authentication/UserDetailsServiceLdapAuthoritiesPopulator.java
@@ -17,14 +17,14 @@ import org.springframework.util.Assert;
* @since 2.0
*/
public class UserDetailsServiceLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator {
- private UserDetailsService userDetailsService;
+ private final UserDetailsService userDetailsService;
public UserDetailsServiceLdapAuthoritiesPopulator(UserDetailsService userService) {
Assert.notNull(userService, "userDetailsService cannot be null");
this.userDetailsService = userService;
}
- public Collection<GrantedAuthority> getGrantedAuthorities(DirContextOperations userData, String username) {
+ public Collection<? extends GrantedAuthority> getGrantedAuthorities(DirContextOperations userData, String username) {
return userDetailsService.loadUserByUsername(username).getAuthorities();
}
}
diff --git a/dist/spring-security-ldap/org/springframework/security/ldap/ppolicy/PasswordPolicyAwareContextSource.java b/dist/spring-security-ldap/org/springframework/security/ldap/ppolicy/PasswordPolicyAwareContextSource.java
index cde9522..63f04ea 100644
--- a/dist/spring-security-ldap/org/springframework/security/ldap/ppolicy/PasswordPolicyAwareContextSource.java
+++ b/dist/spring-security-ldap/org/springframework/security/ldap/ppolicy/PasswordPolicyAwareContextSource.java
@@ -53,7 +53,7 @@ public class PasswordPolicyAwareContextSource extends DefaultSpringSecurityConte
PasswordPolicyResponseControl ctrl = PasswordPolicyControlExtractor.extractControl(ctx);
if (debug) {
logger.debug("Failed to obtain context", ne);
- logger.debug("Pasword policy response: " + ctrl);
+ logger.debug("Password policy response: " + ctrl);
}
LdapUtils.closeContext(ctx);
diff --git a/dist/spring-security-ldap/org/springframework/security/ldap/ppolicy/PasswordPolicyControl.java b/dist/spring-security-ldap/org/springframework/security/ldap/ppolicy/PasswordPolicyControl.java
index cf1642c..8a276b5 100644
--- a/dist/spring-security-ldap/org/springframework/security/ldap/ppolicy/PasswordPolicyControl.java
+++ b/dist/spring-security-ldap/org/springframework/security/ldap/ppolicy/PasswordPolicyControl.java
@@ -39,7 +39,7 @@ public class PasswordPolicyControl implements Control {
//~ Instance fields ================================================================================================
- private boolean critical;
+ private final boolean critical;
//~ Constructors ===================================================================================================
diff --git a/dist/spring-security-ldap/org/springframework/security/ldap/ppolicy/PasswordPolicyErrorStatus.java b/dist/spring-security-ldap/org/springframework/security/ldap/ppolicy/PasswordPolicyErrorStatus.java
index a727270..0a26109 100644
--- a/dist/spring-security-ldap/org/springframework/security/ldap/ppolicy/PasswordPolicyErrorStatus.java
+++ b/dist/spring-security-ldap/org/springframework/security/ldap/ppolicy/PasswordPolicyErrorStatus.java
@@ -35,8 +35,8 @@ public enum PasswordPolicyErrorStatus {
PASSWORD_TOO_YOUNG ("ppolicy.password.too.young", "Your password was changed too recently to be changed again"),
PASSWORD_IN_HISTORY ("ppolicy.password.in.history", "The supplied password has already been used");
- private String errorCode;
- private String defaultMessage;
+ private final String errorCode;
+ private final String defaultMessage;
private PasswordPolicyErrorStatus(String errorCode, String defaultMessage) {
this.errorCode = errorCode;
diff --git a/dist/spring-security-ldap/org/springframework/security/ldap/ppolicy/PasswordPolicyException.java b/dist/spring-security-ldap/org/springframework/security/ldap/ppolicy/PasswordPolicyException.java
index 3964232..50d13bb 100644
--- a/dist/spring-security-ldap/org/springframework/security/ldap/ppolicy/PasswordPolicyException.java
+++ b/dist/spring-security-ldap/org/springframework/security/ldap/ppolicy/PasswordPolicyException.java
@@ -9,7 +9,7 @@ package org.springframework.security.ldap.ppolicy;
* @since 3.0
*/
public class PasswordPolicyException extends RuntimeException {
- private PasswordPolicyErrorStatus status;
+ private final PasswordPolicyErrorStatus status;
public PasswordPolicyException(PasswordPolicyErrorStatus status) {
super(status.getDefaultMessage());
diff --git a/dist/spring-security-ldap/org/springframework/security/ldap/ppolicy/PasswordPolicyResponseControl.java b/dist/spring-security-ldap/org/springframework/security/ldap/ppolicy/PasswordPolicyResponseControl.java
index 3883e9f..08120eb 100644
--- a/dist/spring-security-ldap/org/springframework/security/ldap/ppolicy/PasswordPolicyResponseControl.java
+++ b/dist/spring-security-ldap/org/springframework/security/ldap/ppolicy/PasswordPolicyResponseControl.java
@@ -55,7 +55,7 @@ public class PasswordPolicyResponseControl extends PasswordPolicyControl {
//~ Instance fields ================================================================================================
- private byte[] encodedValue;
+ private final byte[] encodedValue;
private PasswordPolicyErrorStatus errorStatus;
@@ -279,7 +279,7 @@ public class PasswordPolicyResponseControl extends PasswordPolicyControl {
}
private void setInChoice(boolean inChoice) {
- this.inChoice = new Boolean(inChoice);
+ this.inChoice = Boolean.valueOf(inChoice);
}
}
}
diff --git a/dist/spring-security-ldap/org/springframework/security/ldap/search/FilterBasedLdapUserSearch.java b/dist/spring-security-ldap/org/springframework/security/ldap/search/FilterBasedLdapUserSearch.java
index cefe847..8ea6f89 100644
--- a/dist/spring-security-ldap/org/springframework/security/ldap/search/FilterBasedLdapUserSearch.java
+++ b/dist/spring-security-ldap/org/springframework/security/ldap/search/FilterBasedLdapUserSearch.java
@@ -48,13 +48,13 @@ public class FilterBasedLdapUserSearch implements LdapUserSearch {
//~ Instance fields ================================================================================================
- private ContextSource contextSource;
+ private final ContextSource contextSource;
/**
* The LDAP SearchControls object used for the search. Shared between searches so shouldn't be modified
* once the bean has been configured.
*/
- private SearchControls searchControls = new SearchControls();
+ private final SearchControls searchControls = new SearchControls();
/** Context name to search in, relative to the base of the configured ContextSource. */
private String searchBase = "";
@@ -70,7 +70,7 @@ public class FilterBasedLdapUserSearch implements LdapUserSearch {
* <li>(uid={0}) - this would search for a username match on the uid attribute.</li>
* </ul>
*/
- private String searchFilter;
+ private final String searchFilter;
//~ Constructors ===================================================================================================
diff --git a/dist/spring-security-ldap/org/springframework/security/ldap/server/ApacheDSContainer.java b/dist/spring-security-ldap/org/springframework/security/ldap/server/ApacheDSContainer.java
index 398789c..cf8c2b0 100644
--- a/dist/spring-security-ldap/org/springframework/security/ldap/server/ApacheDSContainer.java
+++ b/dist/spring-security-ldap/org/springframework/security/ldap/server/ApacheDSContainer.java
@@ -1,6 +1,8 @@
package org.springframework.security.ldap.server;
import java.io.File;
+import java.io.IOException;
+import java.net.URI;
import java.util.ArrayList;
import java.util.List;
@@ -50,18 +52,18 @@ import org.springframework.util.Assert;
* @author Luke Taylor
*/
public class ApacheDSContainer implements InitializingBean, DisposableBean, Lifecycle, ApplicationContextAware {
- private Log logger = LogFactory.getLog(getClass());
+ private final Log logger = LogFactory.getLog(getClass());
- DefaultDirectoryService service;
+ final DefaultDirectoryService service;
LdapServer server;
private ApplicationContext ctxt;
private File workingDir;
private boolean running;
- private String ldifResources;
- private JdbmPartition partition;
- private String root;
+ private final String ldifResources;
+ private final JdbmPartition partition;
+ private final String root;
private int port = 53389;
public ApacheDSContainer(String root, String ldifs) throws Exception {
@@ -226,23 +228,35 @@ public class ApacheDSContainer implements InitializingBean, DisposableBean, Life
}
// Note that we can't just import using the ServerContext returned
- // from starting Apace DS, apparently because of the long-running issue DIRSERVER-169.
+ // from starting Apache DS, apparently because of the long-running issue DIRSERVER-169.
// We need a standard context.
//DirContext dirContext = contextSource.getReadWriteContext();
- if(ldifs != null && ldifs.length > 0) {
- String ldifFile = ldifs[0].getFile().getAbsolutePath();
+ if (ldifs == null || ldifs.length == 0) {
+ return;
+ }
+
+ if(ldifs.length == 1) {
+ String ldifFile;
+
+ try {
+ ldifFile = ldifs[0].getFile().getAbsolutePath();
+ } catch (IOException e) {
+ ldifFile = ldifs[0].getURI().toString();
+ }
logger.info("Loading LDIF file: " + ldifFile);
LdifFileLoader loader = new LdifFileLoader(service.getAdminSession(), ldifFile);
loader.execute();
+ } else {
+ throw new IllegalArgumentException("More than one LDIF resource found with the supplied pattern:" + ldifResources);
}
}
private boolean deleteDir(File dir) {
if (dir.isDirectory()) {
String[] children = dir.list();
- for (int i=0; i < children.length; i++) {
- boolean success = deleteDir(new File(dir, children[i]));
+ for (String child : children) {
+ boolean success = deleteDir(new File(dir, child));
if (!success) {
return false;
}
diff --git a/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/DefaultLdapAuthoritiesPopulator.java b/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/DefaultLdapAuthoritiesPopulator.java
index c35fec5..faad03d 100644
--- a/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/DefaultLdapAuthoritiesPopulator.java
+++ b/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/DefaultLdapAuthoritiesPopulator.java
@@ -16,7 +16,7 @@
package org.springframework.security.ldap.userdetails;
import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.authority.GrantedAuthorityImpl;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.ldap.SpringSecurityLdapTemplate;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.core.DirContextOperations;
@@ -63,7 +63,7 @@ import java.util.Set;
* </pre>
* <p>
* The group search is performed within a DN specified by the <tt>groupSearchBase</tt> property, which should
- * be relative to the root DN of its <tt>InitialDirContextFactory</tt>. If the search base is null, group searching is
+ * be relative to the root DN of its <tt>ContextSource</tt>. If the search base is null, group searching is
* disabled. The filter used in the search is defined by the <tt>groupSearchFilter</tt> property, with the filter
* argument {0} being the full DN of the user. You can also optionally use the parameter {1}, which will be substituted
* with the username. You can also specify which attribute defines the role name by setting
@@ -85,6 +85,9 @@ import java.util.Set;
* A search for roles for user "uid=ben,ou=people,dc=springframework,dc=org" would return the single granted authority
* "ROLE_DEVELOPER".
* <p>
+ * Note that case-conversion, use of the role prefix and setting a default role are better performed using a
+ * {@code GrantedAuthoritiesMapper} and are now deprecated.
+ * <p>
* The single-level search is performed by default. Setting the <tt>searchSubTree</tt> property to true will enable
* a search of the entire subtree under <tt>groupSearchBase</tt>.
*
@@ -102,13 +105,13 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
*/
private GrantedAuthority defaultRole;
- private SpringSecurityLdapTemplate ldapTemplate;
+ private final SpringSecurityLdapTemplate ldapTemplate;
/**
* Controls used to determine whether group searches should be performed over the full sub-tree from the
* base DN. Modified by searchSubTree property
*/
- private SearchControls searchControls = new SearchControls();
+ private final SearchControls searchControls = new SearchControls();
/**
* The ID of the attribute which contains the role name for a group
@@ -124,12 +127,6 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
* The pattern to be used for the user search. {0} is the user's DN
*/
private String groupSearchFilter = "(member={0})";
-
- /**
- * Attributes of the User's LDAP Object that contain role name information.
- */
-
-// private String[] userRoleAttributes = null;
private String rolePrefix = "ROLE_";
private boolean convertToUpperCase = true;
@@ -141,13 +138,19 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
*
* @param contextSource supplies the contexts used to search for user roles.
* @param groupSearchBase if this is an empty string the search will be performed from the root DN of the
- * context factory.
+ * context factory. If null, no search will be performed.
*/
public DefaultLdapAuthoritiesPopulator(ContextSource contextSource, String groupSearchBase) {
Assert.notNull(contextSource, "contextSource must not be null");
ldapTemplate = new SpringSecurityLdapTemplate(contextSource);
ldapTemplate.setSearchControls(searchControls);
- setGroupSearchBase(groupSearchBase);
+ this.groupSearchBase = groupSearchBase;
+
+ if (groupSearchBase == null) {
+ logger.info("groupSearchBase is null. No group search will be performed.");
+ } else if (groupSearchBase.length() == 0) {
+ logger.info("groupSearchBase is empty. Searches will be performed from the context source base");
+ }
}
//~ Methods ========================================================================================================
@@ -199,7 +202,7 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
public Set<GrantedAuthority> getGroupMembershipRoles(String userDn, String username) {
if (getGroupSearchBase() == null) {
- return Collections.emptySet();
+ return new HashSet<GrantedAuthority>();
}
Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
@@ -222,7 +225,7 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
role = role.toUpperCase();
}
- authorities.add(new GrantedAuthorityImpl(rolePrefix + role));
+ authorities.add(new SimpleGrantedAuthority(rolePrefix + role));
}
return authorities;
@@ -232,24 +235,14 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
return ldapTemplate.getContextSource();
}
- /**
- * Set the group search base (name to search under)
- *
- * @param groupSearchBase if this is an empty string the search will be performed from the root DN of the context
- * factory.
- */
- private void setGroupSearchBase(String groupSearchBase) {
- Assert.notNull(groupSearchBase, "The groupSearchBase (name to search under), must not be null.");
- this.groupSearchBase = groupSearchBase;
- if (groupSearchBase.length() == 0) {
- logger.info("groupSearchBase is empty. Searches will be performed from the context source base");
- }
- }
-
protected String getGroupSearchBase() {
return groupSearchBase;
}
+ /**
+ * @deprecated Convert case in the {@code AuthenticationProvider} using a {@code GrantedAuthoritiesMapper}.
+ */
+ @Deprecated
public void setConvertToUpperCase(boolean convertToUpperCase) {
this.convertToUpperCase = convertToUpperCase;
}
@@ -258,10 +251,12 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
* The default role which will be assigned to all users.
*
* @param defaultRole the role name, including any desired prefix.
+ * @deprecated Assign a default role in the {@code AuthenticationProvider} using a {@code GrantedAuthoritiesMapper}.
*/
+ @Deprecated
public void setDefaultRole(String defaultRole) {
Assert.notNull(defaultRole, "The defaultRole property cannot be set to null");
- this.defaultRole = new GrantedAuthorityImpl(defaultRole);
+ this.defaultRole = new SimpleGrantedAuthority(defaultRole);
}
public void setGroupRoleAttribute(String groupRoleAttribute) {
@@ -277,7 +272,10 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
/**
* Sets the prefix which will be prepended to the values loaded from the directory.
* Defaults to "ROLE_" for compatibility with <tt>RoleVoter/tt>.
+ *
+ * @deprecated Map the authorities in the {@code AuthenticationProvider} using a {@code GrantedAuthoritiesMapper}.
*/
+ @Deprecated
public void setRolePrefix(String rolePrefix) {
Assert.notNull(rolePrefix, "rolePrefix must not be null");
this.rolePrefix = rolePrefix;
diff --git a/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/InetOrgPerson.java b/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/InetOrgPerson.java
index f9309f7..d4e0262 100644
--- a/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/InetOrgPerson.java
+++ b/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/InetOrgPerson.java
@@ -16,6 +16,7 @@ package org.springframework.security.ldap.userdetails;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DirContextOperations;
+import org.springframework.security.core.SpringSecurityCoreVersion;
/**
@@ -28,6 +29,9 @@ import org.springframework.ldap.core.DirContextOperations;
* @author Luke
*/
public class InetOrgPerson extends Person {
+
+ private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
+
private String carLicense;
// Person.cn
private String destinationIndicator;
diff --git a/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/InetOrgPersonContextMapper.java b/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/InetOrgPersonContextMapper.java
index 38e7ae8..05e19e8 100644
--- a/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/InetOrgPersonContextMapper.java
+++ b/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/InetOrgPersonContextMapper.java
@@ -28,7 +28,7 @@ import org.springframework.util.Assert;
*/
public class InetOrgPersonContextMapper implements UserDetailsContextMapper {
- public UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<GrantedAuthority> authorities) {
+ public UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<? extends GrantedAuthority> authorities) {
InetOrgPerson.Essence p = new InetOrgPerson.Essence(ctx);
p.setUsername(username);
diff --git a/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/LdapAuthoritiesPopulator.java b/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/LdapAuthoritiesPopulator.java
index 1249af4..4c34f38 100644
--- a/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/LdapAuthoritiesPopulator.java
+++ b/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/LdapAuthoritiesPopulator.java
@@ -42,5 +42,5 @@ public interface LdapAuthoritiesPopulator {
* @return the granted authorities for the given user.
*
*/
- Collection<GrantedAuthority> getGrantedAuthorities(DirContextOperations userData, String username);
+ Collection<? extends GrantedAuthority> getGrantedAuthorities(DirContextOperations userData, String username);
}
diff --git a/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/LdapUserDetailsImpl.java b/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/LdapUserDetailsImpl.java
index 6e58c1f..1ea0ed9 100644
--- a/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/LdapUserDetailsImpl.java
+++ b/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/LdapUserDetailsImpl.java
@@ -24,6 +24,7 @@ import javax.naming.Name;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.SpringSecurityCoreVersion;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.ldap.ppolicy.PasswordPolicyData;
import org.springframework.util.Assert;
@@ -46,6 +47,8 @@ import org.springframework.util.Assert;
*/
public class LdapUserDetailsImpl implements LdapUserDetails, PasswordPolicyData {
+ private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
+
//~ Instance fields ================================================================================================
private String dn;
@@ -222,7 +225,7 @@ public class LdapUserDetailsImpl implements LdapUserDetails, PasswordPolicyData
instance.accountNonLocked = accountNonLocked;
}
- public void setAuthorities(Collection<GrantedAuthority> authorities) {
+ public void setAuthorities(Collection<? extends GrantedAuthority> authorities) {
mutableAuthorities = new ArrayList<GrantedAuthority>();
mutableAuthorities.addAll(authorities);
}
diff --git a/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/LdapUserDetailsManager.java b/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/LdapUserDetailsManager.java
index 8e22d97..68351eb 100644
--- a/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/LdapUserDetailsManager.java
+++ b/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/LdapUserDetailsManager.java
@@ -14,30 +14,11 @@
*/
package org.springframework.security.ldap.userdetails;
-import org.springframework.security.authentication.BadCredentialsException;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.authority.GrantedAuthorityImpl;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.security.core.userdetails.UsernameNotFoundException;
-import org.springframework.security.ldap.LdapUsernameToDnMapper;
-import org.springframework.security.ldap.LdapUtils;
-import org.springframework.security.ldap.DefaultLdapUsernameToDnMapper;
-import org.springframework.security.provisioning.UserDetailsManager;
-import org.springframework.dao.DataAccessException;
-import org.springframework.ldap.core.AttributesMapper;
-import org.springframework.ldap.core.AttributesMapperCallbackHandler;
-import org.springframework.ldap.core.ContextExecutor;
-import org.springframework.ldap.core.ContextSource;
-import org.springframework.ldap.core.DirContextAdapter;
-import org.springframework.ldap.core.DistinguishedName;
-import org.springframework.ldap.core.LdapTemplate;
-import org.springframework.ldap.core.SearchExecutor;
-import org.springframework.util.Assert;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
import javax.naming.Context;
import javax.naming.NameNotFoundException;
@@ -51,11 +32,29 @@ import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.LdapContext;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.ListIterator;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.ldap.core.AttributesMapper;
+import org.springframework.ldap.core.AttributesMapperCallbackHandler;
+import org.springframework.ldap.core.ContextExecutor;
+import org.springframework.ldap.core.ContextSource;
+import org.springframework.ldap.core.DirContextAdapter;
+import org.springframework.ldap.core.DistinguishedName;
+import org.springframework.ldap.core.LdapTemplate;
+import org.springframework.ldap.core.SearchExecutor;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.ldap.DefaultLdapUsernameToDnMapper;
+import org.springframework.security.ldap.LdapUsernameToDnMapper;
+import org.springframework.security.ldap.LdapUtils;
+import org.springframework.security.provisioning.UserDetailsManager;
+import org.springframework.util.Assert;
/**
* An Ldap implementation of UserDetailsManager.
@@ -90,7 +89,7 @@ public class LdapUserDetailsManager implements UserDetailsManager {
/** The attribute which contains members of a group */
private String groupMemberAttributeName = "uniquemember";
- private String rolePrefix = "ROLE_";
+ private final String rolePrefix = "ROLE_";
/** The pattern to be used for the user search. {0} is the user's DN */
private String groupSearchFilter = "(uniquemember={0})";
@@ -100,7 +99,7 @@ public class LdapUserDetailsManager implements UserDetailsManager {
*/
private UserDetailsContextMapper userDetailsMapper = new InetOrgPersonContextMapper();
- private LdapTemplate template;
+ private final LdapTemplate template;
/** Default context mapper used to create a set of roles from a list of attributes */
private AttributesMapper roleMapper = new AttributesMapper() {
@@ -113,7 +112,7 @@ public class LdapUserDetailsManager implements UserDetailsManager {
Object group = ne.next();
String role = group.toString();
- return new GrantedAuthorityImpl(rolePrefix + role.toUpperCase());
+ return new SimpleGrantedAuthority(rolePrefix + role.toUpperCase());
}
};
@@ -123,7 +122,7 @@ public class LdapUserDetailsManager implements UserDetailsManager {
template = new LdapTemplate(contextSource);
}
- public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
+ public UserDetails loadUserByUsername(String username) {
DistinguishedName dn = usernameMapper.buildDn(username);
List<GrantedAuthority> authorities = getUserAuthorities(dn, username);
@@ -311,15 +310,15 @@ public class LdapUserDetailsManager implements UserDetailsManager {
userDetailsMapper.mapUserToContext(user, ctx);
}
- protected void addAuthorities(DistinguishedName userDn, Collection<GrantedAuthority> authorities) {
+ protected void addAuthorities(DistinguishedName userDn, Collection<? extends GrantedAuthority> authorities) {
modifyAuthorities(userDn, authorities, DirContext.ADD_ATTRIBUTE);
}
- protected void removeAuthorities(DistinguishedName userDn, List<GrantedAuthority> authorities) {
+ protected void removeAuthorities(DistinguishedName userDn, Collection<? extends GrantedAuthority> authorities) {
modifyAuthorities(userDn, authorities, DirContext.REMOVE_ATTRIBUTE);
}
- private void modifyAuthorities(final DistinguishedName userDn, final Collection<GrantedAuthority> authorities, final int modType) {
+ private void modifyAuthorities(final DistinguishedName userDn, final Collection<? extends GrantedAuthority> authorities, final int modType) {
template.executeReadWrite(new ContextExecutor() {
public Object executeWithContext(DirContext ctx) throws NamingException {
for(GrantedAuthority authority : authorities) {
diff --git a/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/LdapUserDetailsMapper.java b/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/LdapUserDetailsMapper.java
index d4fd2e4..963c9fa 100644
--- a/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/LdapUserDetailsMapper.java
+++ b/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/LdapUserDetailsMapper.java
@@ -22,7 +22,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.authority.GrantedAuthorityImpl;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.ldap.ppolicy.PasswordPolicyControl;
import org.springframework.security.ldap.ppolicy.PasswordPolicyResponseControl;
@@ -45,7 +45,7 @@ public class LdapUserDetailsMapper implements UserDetailsContextMapper {
//~ Methods ========================================================================================================
- public UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<GrantedAuthority> authorities) {
+ public UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<? extends GrantedAuthority> authorities) {
String dn = ctx.getNameInNamespace();
logger.debug("Mapping user details from context with DN: " + dn);
@@ -70,8 +70,8 @@ public class LdapUserDetailsMapper implements UserDetailsContextMapper {
continue;
}
- for (int j = 0; j < rolesForAttribute.length; j++) {
- GrantedAuthority authority = createAuthority(rolesForAttribute[j]);
+ for (String role : rolesForAttribute) {
+ GrantedAuthority authority = createAuthority(role);
if (authority != null) {
essence.addAuthority(authority);
@@ -138,7 +138,7 @@ public class LdapUserDetailsMapper implements UserDetailsContextMapper {
if (convertToUpperCase) {
role = ((String) role).toUpperCase();
}
- return new GrantedAuthorityImpl(rolePrefix + role);
+ return new SimpleGrantedAuthority(rolePrefix + role);
}
return null;
}
diff --git a/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/Person.java b/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/Person.java
index cce9ad1..4217780 100644
--- a/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/Person.java
+++ b/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/Person.java
@@ -15,6 +15,7 @@
package org.springframework.security.ldap.userdetails;
+import org.springframework.security.core.SpringSecurityCoreVersion;
import org.springframework.util.Assert;
import org.springframework.ldap.core.DirContextAdapter;
@@ -33,6 +34,9 @@ import java.util.Arrays;
* @since 2.0
*/
public class Person extends LdapUserDetailsImpl {
+
+ private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
+
private String sn;
private String description;
private String telephoneNumber;
diff --git a/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/PersonContextMapper.java b/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/PersonContextMapper.java
index 227308a..444c6d7 100644
--- a/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/PersonContextMapper.java
+++ b/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/PersonContextMapper.java
@@ -13,7 +13,7 @@ import org.springframework.util.Assert;
*/
public class PersonContextMapper implements UserDetailsContextMapper {
- public UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<GrantedAuthority> authorities) {
+ public UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<? extends GrantedAuthority> authorities) {
Person.Essence p = new Person.Essence(ctx);
p.setUsername(username);
diff --git a/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/UserDetailsContextMapper.java b/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/UserDetailsContextMapper.java
index 3ff020f..79c3f60 100644
--- a/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/UserDetailsContextMapper.java
+++ b/dist/spring-security-ldap/org/springframework/security/ldap/userdetails/UserDetailsContextMapper.java
@@ -22,7 +22,7 @@ import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.core.DirContextAdapter;
/**
- * Operations to map a UserDetails object to and from a Spring LDAP <tt>DirContextOperations</tt> implementation.
+ * Operations to map a UserDetails object to and from a Spring LDAP {@code DirContextOperations} implementation.
* Used by {@code LdapUserDetailsManager} when loading and saving/creating user information, and also by the
* {@code LdapAuthenticationProvider} to allow customization of the user data loaded during authentication.
*
@@ -36,10 +36,10 @@ public interface UserDetailsContextMapper {
*
* @param ctx the context object which contains the user information.
* @param username the user's supplied login name.
- * @param authority the list of authorities which the user should be given.
+ * @param authorities
* @return the user object.
*/
- UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<GrantedAuthority> authority);
+ UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<? extends GrantedAuthority> authorities);
/**
* Reverse of the above operation. Populates a context object from the supplied user object.
diff --git a/dist/spring-security-openid/META-INF/MANIFEST.MF b/dist/spring-security-openid/META-INF/MANIFEST.MF
index 351fd34..58630c0 100644
--- a/dist/spring-security-openid/META-INF/MANIFEST.MF
+++ b/dist/spring-security-openid/META-INF/MANIFEST.MF
@@ -1,4 +1,2 @@
Manifest-Version: 1.0
-Archiver-Version: Plexus Archiver
-Created-By: 17.1-b03-307 (Apple Inc.)
diff --git a/dist/spring-security-openid/org/springframework/security/openid/OpenID4JavaConsumer.java b/dist/spring-security-openid/org/springframework/security/openid/OpenID4JavaConsumer.java
index ed44c5d..1700927 100644
--- a/dist/spring-security-openid/org/springframework/security/openid/OpenID4JavaConsumer.java
+++ b/dist/spring-security-openid/org/springframework/security/openid/OpenID4JavaConsumer.java
@@ -37,40 +37,64 @@ import org.openid4java.message.ParameterList;
import org.openid4java.message.ax.AxMessage;
import org.openid4java.message.ax.FetchRequest;
import org.openid4java.message.ax.FetchResponse;
+import org.springframework.util.StringUtils;
/**
* @author Ray Krueger
+ * @author Luke Taylor
*/
+ at SuppressWarnings("unchecked")
public class OpenID4JavaConsumer implements OpenIDConsumer {
private static final String DISCOVERY_INFO_KEY = DiscoveryInformation.class.getName();
+ private static final String ATTRIBUTE_LIST_KEY = "SPRING_SECURITY_OPEN_ID_ATTRIBUTES_FETCH_LIST";
//~ Instance fields ================================================================================================
protected final Log logger = LogFactory.getLog(getClass());
private final ConsumerManager consumerManager;
- private List<OpenIDAttribute> attributesToFetch = Collections.emptyList();
+ private final AxFetchListFactory attributesToFetchFactory;
//~ Constructors ===================================================================================================
public OpenID4JavaConsumer() throws ConsumerException {
- this.consumerManager = new ConsumerManager();
+ this(new ConsumerManager(), new NullAxFetchListFactory());
}
+ /**
+ * @deprecated use the {@link AxFetchListFactory} version instead.
+ */
+ @Deprecated
public OpenID4JavaConsumer(List<OpenIDAttribute> attributes) throws ConsumerException {
this(new ConsumerManager(), attributes);
}
- public OpenID4JavaConsumer(ConsumerManager consumerManager, List<OpenIDAttribute> attributes)
+ @Deprecated
+ public OpenID4JavaConsumer(ConsumerManager consumerManager, final List<OpenIDAttribute> attributes)
throws ConsumerException {
this.consumerManager = consumerManager;
- this.attributesToFetch = Collections.unmodifiableList(attributes);
+ this.attributesToFetchFactory = new AxFetchListFactory() {
+ private final List<OpenIDAttribute> fetchAttrs = Collections.unmodifiableList(attributes);
+
+ public List<OpenIDAttribute> createAttributeList(String identifier) {
+ return fetchAttrs;
+ }
+ };
+ }
+
+ public OpenID4JavaConsumer(AxFetchListFactory attributesToFetchFactory) throws ConsumerException {
+ this(new ConsumerManager(), attributesToFetchFactory);
+ }
+
+ public OpenID4JavaConsumer(ConsumerManager consumerManager, AxFetchListFactory attributesToFetchFactory)
+ throws ConsumerException {
+ this.consumerManager = consumerManager;
+ this.attributesToFetchFactory = attributesToFetchFactory;
}
//~ Methods ========================================================================================================
- @SuppressWarnings("unchecked")
public String beginConsumption(HttpServletRequest req, String identityUrl, String returnToUrl, String realm)
throws OpenIDConsumerException {
List<DiscoveryInformation> discoveries;
@@ -88,9 +112,18 @@ public class OpenID4JavaConsumer implements OpenIDConsumer {
try {
authReq = consumerManager.authenticate(information, returnToUrl, realm);
+
+ logger.debug("Looking up attribute fetch list for identifier: " + identityUrl);
+
+ List<OpenIDAttribute> attributesToFetch = attributesToFetchFactory.createAttributeList(identityUrl);
+
if (!attributesToFetch.isEmpty()) {
+ req.getSession().setAttribute(ATTRIBUTE_LIST_KEY, attributesToFetch);
FetchRequest fetchRequest = FetchRequest.createFetchRequest();
for (OpenIDAttribute attr : attributesToFetch) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Adding attribute " + attr.getType() + " to fetch request");
+ }
fetchRequest.addAttribute(attr.getName(), attr.getType(), attr.isRequired(), attr.getCount());
}
authReq.addExtension(fetchRequest);
@@ -104,9 +137,7 @@ public class OpenID4JavaConsumer implements OpenIDConsumer {
return authReq.getDestinationUrl(true);
}
- @SuppressWarnings("unchecked")
public OpenIDAuthenticationToken endConsumption(HttpServletRequest request) throws OpenIDConsumerException {
- final boolean debug = logger.isDebugEnabled();
// extract the parameters from the authentication response
// (which comes in as a HTTP request from the OpenID provider)
ParameterList openidResp = new ParameterList(request.getParameterMap());
@@ -114,11 +145,20 @@ public class OpenID4JavaConsumer implements OpenIDConsumer {
// retrieve the previously stored discovery information
DiscoveryInformation discovered = (DiscoveryInformation) request.getSession().getAttribute(DISCOVERY_INFO_KEY);
+ if (discovered == null) {
+ throw new OpenIDConsumerException("DiscoveryInformation is not available. Possible causes are lost session or replay attack");
+ }
+
+ List<OpenIDAttribute> attributesToFetch = (List<OpenIDAttribute>) request.getSession().getAttribute(ATTRIBUTE_LIST_KEY);
+
+ request.getSession().removeAttribute(DISCOVERY_INFO_KEY);
+ request.getSession().removeAttribute(ATTRIBUTE_LIST_KEY);
+
// extract the receiving URL from the HTTP request
StringBuffer receivingURL = request.getRequestURL();
String queryString = request.getQueryString();
- if ((queryString != null) && (queryString.length() > 0)) {
+ if (StringUtils.hasLength(queryString)) {
receivingURL.append("?").append(request.getQueryString());
}
@@ -135,36 +175,6 @@ public class OpenID4JavaConsumer implements OpenIDConsumer {
throw new OpenIDConsumerException("Error verifying openid response", e);
}
- // fetch the attributesToFetch of the response
- Message authSuccess = verification.getAuthResponse();
- List<OpenIDAttribute> attributes = new ArrayList<OpenIDAttribute>(this.attributesToFetch.size());
-
- if (authSuccess.hasExtension(AxMessage.OPENID_NS_AX)) {
- if (debug) {
- logger.debug("Extracting attributes retrieved by attribute exchange");
- }
- try {
- MessageExtension ext = authSuccess.getExtension(AxMessage.OPENID_NS_AX);
- if (ext instanceof FetchResponse) {
- FetchResponse fetchResp = (FetchResponse) ext;
- for (OpenIDAttribute attr : attributesToFetch) {
- List<String> values = fetchResp.getAttributeValues(attr.getName());
- if (!values.isEmpty()) {
- OpenIDAttribute fetched = new OpenIDAttribute(attr.getName(), attr.getType(), values);
- fetched.setRequired(attr.isRequired());
- attributes.add(fetched);
- }
- }
- }
- } catch (MessageException e) {
- attributes.clear();
- throw new OpenIDConsumerException("Attribute retrieval failed", e);
- }
- if (debug) {
- logger.debug("Retrieved attributes" + attributes);
- }
- }
-
// examine the verification result and extract the verified identifier
Identifier verified = verification.getVerifiedId();
@@ -172,10 +182,50 @@ public class OpenID4JavaConsumer implements OpenIDConsumer {
Identifier id = discovered.getClaimedIdentifier();
return new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.FAILURE,
id == null ? "Unknown" : id.getIdentifier(),
- "Verification status message: [" + verification.getStatusMsg() + "]", attributes);
+ "Verification status message: [" + verification.getStatusMsg() + "]",
+ Collections.<OpenIDAttribute>emptyList());
}
+ List<OpenIDAttribute> attributes = fetchAxAttributes(verification.getAuthResponse(), attributesToFetch);
+
return new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.SUCCESS, verified.getIdentifier(),
"some message", attributes);
}
+
+ List<OpenIDAttribute> fetchAxAttributes(Message authSuccess, List<OpenIDAttribute> attributesToFetch)
+ throws OpenIDConsumerException {
+
+ if (attributesToFetch == null || !authSuccess.hasExtension(AxMessage.OPENID_NS_AX)) {
+ return Collections.emptyList();
+ }
+
+ logger.debug("Extracting attributes retrieved by attribute exchange");
+
+ List<OpenIDAttribute> attributes = Collections.emptyList();
+
+ try {
+ MessageExtension ext = authSuccess.getExtension(AxMessage.OPENID_NS_AX);
+ if (ext instanceof FetchResponse) {
+ FetchResponse fetchResp = (FetchResponse) ext;
+ attributes = new ArrayList<OpenIDAttribute>(attributesToFetch.size());
+
+ for (OpenIDAttribute attr : attributesToFetch) {
+ List<String> values = fetchResp.getAttributeValues(attr.getName());
+ if (!values.isEmpty()) {
+ OpenIDAttribute fetched = new OpenIDAttribute(attr.getName(), attr.getType(), values);
+ fetched.setRequired(attr.isRequired());
+ attributes.add(fetched);
+ }
+ }
+ }
+ } catch (MessageException e) {
+ throw new OpenIDConsumerException("Attribute retrieval failed", e);
+ }
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Retrieved attributes" + attributes);
+ }
+
+ return attributes;
+ }
}
diff --git a/dist/spring-security-openid/org/springframework/security/openid/OpenIDAuthenticationFilter.java b/dist/spring-security-openid/org/springframework/security/openid/OpenIDAuthenticationFilter.java
index 4522981..99bd806 100644
--- a/dist/spring-security-openid/org/springframework/security/openid/OpenIDAuthenticationFilter.java
+++ b/dist/spring-security-openid/org/springframework/security/openid/OpenIDAuthenticationFilter.java
@@ -15,29 +15,22 @@
package org.springframework.security.openid;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-
import org.openid4java.consumer.ConsumerException;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
-import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.*;
+
/**
* Filter which processes OpenID authentication requests.
@@ -123,8 +116,6 @@ public class OpenIDAuthenticationFilter extends AbstractAuthenticationProcessing
if (!StringUtils.hasText(identity)) {
String claimedIdentity = obtainUsername(request);
- // Make the username available to the view
- setLastUsername(claimedIdentity, request);
try {
String returnToUrl = buildReturnToUrl(request);
@@ -159,21 +150,9 @@ public class OpenIDAuthenticationFilter extends AbstractAuthenticationProcessing
// delegate to the authentication provider
Authentication authentication = this.getAuthenticationManager().authenticate(token);
- if (authentication.isAuthenticated()) {
- setLastUsername(token.getIdentityUrl(), request);
- }
-
return authentication;
}
- private void setLastUsername(String username, HttpServletRequest request) {
- HttpSession session = request.getSession(false);
-
- if (session != null || getAllowSessionCreation()) {
- request.getSession().setAttribute(UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_USERNAME_KEY, username);
- }
- }
-
protected String lookupRealm(String returnToUrl) {
String mapping = realmMapping.get(returnToUrl);
@@ -239,7 +218,14 @@ public class OpenIDAuthenticationFilter extends AbstractAuthenticationProcessing
* Reads the <tt>claimedIdentityFieldName</tt> from the submitted request.
*/
protected String obtainUsername(HttpServletRequest req) {
- return req.getParameter(claimedIdentityFieldName);
+ String claimedIdentity = req.getParameter(claimedIdentityFieldName);
+
+ if (!StringUtils.hasText(claimedIdentity)) {
+ logger.error("No claimed identity supplied in authentication request");
+ return "";
+ }
+
+ return claimedIdentity.trim();
}
/**
diff --git a/dist/spring-security-openid/org/springframework/security/openid/OpenIDAuthenticationProvider.java b/dist/spring-security-openid/org/springframework/security/openid/OpenIDAuthenticationProvider.java
index bf18685..b1b03f5 100644
--- a/dist/spring-security-openid/org/springframework/security/openid/OpenIDAuthenticationProvider.java
+++ b/dist/spring-security-openid/org/springframework/security/openid/OpenIDAuthenticationProvider.java
@@ -20,7 +20,11 @@ import org.springframework.security.authentication.AuthenticationServiceExceptio
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
+import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper;
+import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.util.Assert;
@@ -28,21 +32,23 @@ import org.springframework.util.Assert;
/**
* Finalises the OpenID authentication by obtaining local authorities for the authenticated user.
* <p>
- * The authorities are obtained by calling the configured <tt>UserDetailsService</tt>.
- * The <code>UserDetails</code> it returns must, at minimum, contain the username and <code>GrantedAuthority[]</code>
+ * The authorities are obtained by calling the configured {@code UserDetailsService}.
+ * The {@code UserDetails} it returns must, at minimum, contain the username and {@code GrantedAuthority}
* objects applicable to the authenticated user. Note that by default, Spring Security ignores the password and
- * enabled/disabled status of the <code>UserDetails</code> because this is
- * authentication-related and should have been enforced by another provider server.
+ * enabled/disabled status of the {@code UserDetails} because this is authentication-related and should have been
+ * enforced by another provider server.
* <p>
- * The <code>UserDetails</code> returned by implementations is stored in the generated <code>AuthenticationToken</code>,
+ * The {@code UserDetails} returned by implementations is stored in the generated {@code Authentication} token,
* so additional properties such as email addresses, telephone numbers etc can easily be stored.
*
* @author Robin Bramley, Opsera Ltd.
+ * @author Luke Taylor
*/
public class OpenIDAuthenticationProvider implements AuthenticationProvider, InitializingBean {
//~ Instance fields ================================================================================================
- private UserDetailsService userDetailsService;
+ private AuthenticationUserDetailsService<OpenIDAuthenticationToken> userDetailsService;
+ private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper();
//~ Methods ========================================================================================================
@@ -66,7 +72,7 @@ public class OpenIDAuthenticationProvider implements AuthenticationProvider, Ini
// handle the various possibilities
if (status == OpenIDAuthenticationStatus.SUCCESS) {
// Lookup user details
- UserDetails userDetails = userDetailsService.loadUserByUsername(response.getIdentityUrl());
+ UserDetails userDetails = userDetailsService.loadUserDetails(response);
return createSuccessfulAuthentication(userDetails, response);
@@ -98,21 +104,32 @@ public class OpenIDAuthenticationProvider implements AuthenticationProvider, Ini
* @return the token which will represent the authenticated user.
*/
protected Authentication createSuccessfulAuthentication(UserDetails userDetails, OpenIDAuthenticationToken auth) {
- return new OpenIDAuthenticationToken(userDetails, userDetails.getAuthorities(),
+ return new OpenIDAuthenticationToken(userDetails, authoritiesMapper.mapAuthorities(userDetails.getAuthorities()),
auth.getIdentityUrl(), auth.getAttributes());
}
/**
- * Used to load the authorities for the authenticated OpenID user.
+ * Used to load the {@code UserDetails} for the authenticated OpenID user.
*/
public void setUserDetailsService(UserDetailsService userDetailsService) {
+ this.userDetailsService = new UserDetailsByNameServiceWrapper<OpenIDAuthenticationToken>(userDetailsService);
+ }
+
+ /**
+ * Used to load the {@code UserDetails} for the authenticated OpenID user.
+ */
+ public void setAuthenticationUserDetailsService(AuthenticationUserDetailsService<OpenIDAuthenticationToken> userDetailsService) {
this.userDetailsService = userDetailsService;
}
/* (non-Javadoc)
* @see org.springframework.security.authentication.AuthenticationProvider#supports(java.lang.Class)
*/
- public boolean supports(Class<? extends Object> authentication) {
+ public boolean supports(Class<?> authentication) {
return OpenIDAuthenticationToken.class.isAssignableFrom(authentication);
}
+
+ public void setAuthoritiesMapper(GrantedAuthoritiesMapper authoritiesMapper) {
+ this.authoritiesMapper = authoritiesMapper;
+ }
}
diff --git a/dist/spring-security-openid/org/springframework/security/openid/OpenIDAuthenticationStatus.java b/dist/spring-security-openid/org/springframework/security/openid/OpenIDAuthenticationStatus.java
index 99d6f29..9d7eecc 100644
--- a/dist/spring-security-openid/org/springframework/security/openid/OpenIDAuthenticationStatus.java
+++ b/dist/spring-security-openid/org/springframework/security/openid/OpenIDAuthenticationStatus.java
@@ -14,42 +14,31 @@
*/
package org.springframework.security.openid;
-import java.io.ObjectStreamException;
-import java.io.Serializable;
-
-
/**
- * Based on JanRain status codes
+ * Authentication status codes, based on JanRain status codes
*
* @author JanRain Inc.
* @author Robin Bramley, Opsera Ltd
+ * @author Luke Taylor
*/
-public class OpenIDAuthenticationStatus implements Serializable {
- //~ Static fields/initializers =====================================================================================
-
- private static final long serialVersionUID = -998877665544332211L;
- private static int nextOrdinal = 0;
+public enum OpenIDAuthenticationStatus {
/** This code indicates a successful authentication request */
- public static final OpenIDAuthenticationStatus SUCCESS = new OpenIDAuthenticationStatus("success");
+ SUCCESS("success"),
/** This code indicates a failed authentication request */
- public static final OpenIDAuthenticationStatus FAILURE = new OpenIDAuthenticationStatus("failure");
+ FAILURE("failure"),
/** This code indicates the server reported an error */
- public static final OpenIDAuthenticationStatus ERROR = new OpenIDAuthenticationStatus("error");
+ ERROR("error"),
/** This code indicates that the user needs to do additional work to prove their identity */
- public static final OpenIDAuthenticationStatus SETUP_NEEDED = new OpenIDAuthenticationStatus("setup needed");
+ SETUP_NEEDED("setup needed"),
/** This code indicates that the user cancelled their login request */
- public static final OpenIDAuthenticationStatus CANCELLED = new OpenIDAuthenticationStatus("cancelled");
- private static final OpenIDAuthenticationStatus[] PRIVATE_VALUES = {SUCCESS, FAILURE, ERROR, SETUP_NEEDED, CANCELLED};
-
- //~ Instance fields ================================================================================================
+ CANCELLED("cancelled");
- private String name;
- private final int ordinal = nextOrdinal++;
+ private final String name;
//~ Constructors ===================================================================================================
@@ -57,12 +46,6 @@ public class OpenIDAuthenticationStatus implements Serializable {
this.name = name;
}
- //~ Methods ========================================================================================================
-
- private Object readResolve() throws ObjectStreamException {
- return PRIVATE_VALUES[ordinal];
- }
-
public String toString() {
return name;
}
diff --git a/dist/spring-security-openid/org/springframework/security/openid/OpenIDAuthenticationToken.java b/dist/spring-security-openid/org/springframework/security/openid/OpenIDAuthenticationToken.java
index 48332a4..c0d7dac 100644
--- a/dist/spring-security-openid/org/springframework/security/openid/OpenIDAuthenticationToken.java
+++ b/dist/spring-security-openid/org/springframework/security/openid/OpenIDAuthenticationToken.java
@@ -20,6 +20,7 @@ import java.util.List;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.SpringSecurityCoreVersion;
/**
* OpenID Authentication Token
@@ -27,6 +28,9 @@ import org.springframework.security.core.GrantedAuthority;
* @author Robin Bramley
*/
public class OpenIDAuthenticationToken extends AbstractAuthenticationToken {
+
+ private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
+
//~ Instance fields ================================================================================================
private final OpenIDAuthenticationStatus status;
diff --git a/dist/spring-security-openid/org/springframework/security/openid/package.html b/dist/spring-security-openid/org/springframework/security/openid/package.html
deleted file mode 100644
index c940ab8..0000000
--- a/dist/spring-security-openid/org/springframework/security/openid/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body>
-Authenticates standard web browser users via <a href="http://openid.net">OpenID</a>.
-</body>
-</html>
\ No newline at end of file
diff --git a/dist/spring-security-taglibs/META-INF/MANIFEST.MF b/dist/spring-security-taglibs/META-INF/MANIFEST.MF
index 351fd34..58630c0 100644
--- a/dist/spring-security-taglibs/META-INF/MANIFEST.MF
+++ b/dist/spring-security-taglibs/META-INF/MANIFEST.MF
@@ -1,4 +1,2 @@
Manifest-Version: 1.0
-Archiver-Version: Plexus Archiver
-Created-By: 17.1-b03-307 (Apple Inc.)
diff --git a/dist/spring-security-taglibs/META-INF/security.tld b/dist/spring-security-taglibs/META-INF/security.tld
deleted file mode 100644
index 30ced3a..0000000
--- a/dist/spring-security-taglibs/META-INF/security.tld
+++ /dev/null
@@ -1,157 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1" ?>
-<!DOCTYPE taglib
- PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
- "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
-<taglib>
- <tlib-version>1.1.1</tlib-version>
- <jsp-version>1.2</jsp-version>
- <short-name>security</short-name>
- <uri>http://www.springframework.org/security/tags</uri>
- <description>
- Spring Security Authorization Tag Library
- </description>
-
- <tag>
- <name>authorize</name>
- <tag-class>org.springframework.security.taglibs.authz.AuthorizeTag</tag-class>
- <description>
- A tag which outputs the body of the tag if the configured access expression
- evaluates to true for the currently authenticated principal.
- </description>
-
- <attribute>
- <name>access</name>
- <required>false</required>
- <rtexprvalue>false</rtexprvalue>
- <description>
- A Spring-EL expression which is supported by the WebSecurityExpressionHandler
- in the application context. The latter will be used to evaluate the expression.
- </description>
- </attribute>
-
- <attribute>
- <name>url</name>
- <required>false</required>
- <rtexprvalue>true</rtexprvalue>
- <description>
- A URL within the application. If the user has access to this URL (as determined by
- the AccessDecisionManager), the tag body will be evaluated. If not, it will
- be skipped.
- </description>
- </attribute>
-
- <attribute>
- <name>method</name>
- <required>false</required>
- <rtexprvalue>false</rtexprvalue>
- <description>
- Can optionally be used to narrow down the HTTP method (typically GET or POST) to which the URL
- applies to. Only has any meaning when used in combination with the "url" attribute.
- </description>
- </attribute>
-
-
- <attribute>
- <name>ifNotGranted</name>
- <required>false</required>
- <rtexprvalue>true</rtexprvalue>
- <description>
- A comma separated list of roles which the user must not have
- for the body to be output. Deprecated in favour of the access expression.
- </description>
- </attribute>
-
- <attribute>
- <name>ifAllGranted</name>
- <required>false</required>
- <rtexprvalue>true</rtexprvalue>
- <description>
- A comma separated list of roles which the user must all
- possess for the body to be output. Deprecated in favour of the access expression.
- </description>
- </attribute>
-
- <attribute>
- <name>ifAnyGranted</name>
- <required>false</required>
- <rtexprvalue>true</rtexprvalue>
- <description>
- A comma separated list of roles, one of which the user must
- possess for the body to be output. Deprecated in favour of the access expression.
- </description>
- </attribute>
- </tag>
-
- <tag>
- <name>authentication</name>
- <tag-class>org.springframework.security.taglibs.authz.AuthenticationTag</tag-class>
- <description>
- Allows access to the current Authentication object.
- </description>
-
- <attribute>
- <name>property</name>
- <required>true</required>
- <rtexprvalue>true</rtexprvalue>
- <description>
- Property of the Authentication object which should be output. Supports nested
- properties. For example if the principal object is an instance of UserDetails,
- the property "principal.username" will return the username. Alternatively, using
- "name" will call getName method on the Authentication object directly.
- </description>
- </attribute>
- <attribute>
- <name>var</name>
- <required>false</required>
- <rtexprvalue>false</rtexprvalue>
- <description>
- Name of the exported scoped variable which will contain the
- evaluated property of the Authentication object.
- </description>
- </attribute>
- <attribute>
- <name>htmlEscape</name>
- <required>false</required>
- <rtexprvalue>true</rtexprvalue>
- <description>Set HTML escaping for this tag, as a boolean value.</description>
- </attribute>
- <attribute>
- <name>scope</name>
- <required>false</required>
- <rtexprvalue>false</rtexprvalue>
- <description>
- Scope for var.
- </description>
- </attribute>
- </tag>
-
- <tag>
- <name>accesscontrollist</name>
- <tag-class>org.springframework.security.taglibs.authz.AccessControlListTag</tag-class>
- <description>
- Allows inclusion of a tag body if the current Authentication
- has one of the specified permissions to the presented
- domain object instance.
- </description>
-
- <attribute>
- <name>hasPermission</name>
- <required>true</required>
- <rtexprvalue>true</rtexprvalue>
- <description>
- A comma separated list of permissions, which will be converted to
- Permission instances by the configured PermissionFactory.
- </description>
- </attribute>
- <attribute>
- <name>domainObject</name>
- <required>true</required>
- <rtexprvalue>true</rtexprvalue>
- <description>
- The actual domain object instance for which permissions
- are being evaluated.
- </description>
- </attribute>
- </tag>
-
-</taglib>
diff --git a/dist/spring-security-taglibs/org/springframework/security/taglibs/authz/AccessControlListTag.java b/dist/spring-security-taglibs/org/springframework/security/taglibs/authz/AccessControlListTag.java
index 613ff10..955ffb0 100644
--- a/dist/spring-security-taglibs/org/springframework/security/taglibs/authz/AccessControlListTag.java
+++ b/dist/spring-security-taglibs/org/springframework/security/taglibs/authz/AccessControlListTag.java
@@ -14,58 +14,35 @@
*/
package org.springframework.security.taglibs.authz;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.StringTokenizer;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.security.access.PermissionEvaluator;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.taglibs.TagLibConfig;
+import org.springframework.web.context.support.WebApplicationContextUtils;
import javax.servlet.ServletContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.Tag;
import javax.servlet.jsp.tagext.TagSupport;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.context.ApplicationContext;
-import org.springframework.security.acls.domain.DefaultPermissionFactory;
-import org.springframework.security.acls.domain.ObjectIdentityRetrievalStrategyImpl;
-import org.springframework.security.acls.domain.PermissionFactory;
-import org.springframework.security.acls.domain.SidRetrievalStrategyImpl;
-import org.springframework.security.acls.model.Acl;
-import org.springframework.security.acls.model.AclService;
-import org.springframework.security.acls.model.NotFoundException;
-import org.springframework.security.acls.model.ObjectIdentity;
-import org.springframework.security.acls.model.ObjectIdentityRetrievalStrategy;
-import org.springframework.security.acls.model.Permission;
-import org.springframework.security.acls.model.Sid;
-import org.springframework.security.acls.model.SidRetrievalStrategy;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.web.context.support.WebApplicationContextUtils;
-import org.springframework.web.util.ExpressionEvaluationUtils;
+import java.util.*;
/**
* An implementation of {@link Tag} that allows its body through if some authorizations are granted to the request's
* principal.
* <p>
- * One or more comma separate numeric are specified via the <tt>hasPermission</tt> attribute.
- * These permissions are then converted into {@link Permission} instances using the {@link PermissionFactory}
- * instance obtained from the application context, or a {@link DefaultPermissionFactory} if one isn't found.
- * The <tt>Permission</tt> instances are then presented as a list
- * array to the {@link Acl#isGranted(List, List, boolean)} method.
- * The {@link Sid} presented is determined by the {@link SidRetrievalStrategy}.
+ * One or more comma separate numeric are specified via the {@code hasPermission} attribute. The tag delegates
+ * to the configured {@link PermissionEvaluator} which it obtains from the {@code ApplicationContext}.
* <p>
* For this class to operate it must be able to access the application context via the
- * <code>WebApplicationContextUtils</code> and attempt to locate an {@link AclService},
- * {@link ObjectIdentityRetrievalStrategy} and {@link SidRetrievalStrategy}.
- * There cannot be more than one of these present. The <tt>AclService</tt> must be provided, but a
- * {@link SidRetrievalStrategyImpl} and/or an {@link ObjectIdentityRetrievalStrategyImpl} will be created if no
- * implementations are found in the application context.
+ * {@code WebApplicationContextUtils} and attempt to locate the {@code PermissionEvaluator} instance.
+ * There cannot be more than one of these present for the tag to function.
*
* @author Ben Alex
+ * @author Luke Taylor
*/
public class AccessControlListTag extends TagSupport {
//~ Static fields/initializers =====================================================================================
@@ -74,44 +51,28 @@ public class AccessControlListTag extends TagSupport {
//~ Instance fields ================================================================================================
- private AclService aclService;
private ApplicationContext applicationContext;
private Object domainObject;
- private ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy;
- private SidRetrievalStrategy sidRetrievalStrategy;
- private PermissionFactory permissionFactory;
+ private PermissionEvaluator permissionEvaluator;
private String hasPermission = "";
+ private String var;
//~ Methods ========================================================================================================
public int doStartTag() throws JspException {
if ((null == hasPermission) || "".equals(hasPermission)) {
- return Tag.SKIP_BODY;
+ return skipBody();
}
initializeIfRequired();
- final String evaledPermissionsString = ExpressionEvaluationUtils.evaluateString("hasPermission", hasPermission,
- pageContext);
-
- List<Permission> requiredPermissions = parsePermissionsString(evaledPermissionsString);
-
- Object resolvedDomainObject = null;
-
- if (domainObject instanceof String) {
- resolvedDomainObject = ExpressionEvaluationUtils.evaluate("domainObject", (String) domainObject,
- Object.class, pageContext);
- } else {
- resolvedDomainObject = domainObject;
- }
-
- if (resolvedDomainObject == null) {
+ if (domainObject == null) {
if (logger.isDebugEnabled()) {
logger.debug("domainObject resolved to null, so including tag body");
}
// Of course they have access to a null object!
- return Tag.EVAL_BODY_INCLUDE;
+ return evalBody();
}
if (SecurityContextHolder.getContext().getAuthentication() == null) {
@@ -120,26 +81,32 @@ public class AccessControlListTag extends TagSupport {
"SecurityContextHolder did not return a non-null Authentication object, so skipping tag body");
}
- return Tag.SKIP_BODY;
+ return skipBody();
}
- List<Sid> sids = sidRetrievalStrategy.getSids(SecurityContextHolder.getContext().getAuthentication());
- ObjectIdentity oid = objectIdentityRetrievalStrategy.getObjectIdentity(resolvedDomainObject);
+ if (permissionEvaluator.hasPermission(SecurityContextHolder.getContext().getAuthentication(),
+ domainObject, hasPermission)) {
+ return evalBody();
+ }
- // Obtain aclEntrys applying to the current Authentication object
- try {
- Acl acl = aclService.readAclById(oid, sids);
+ return skipBody();
+ }
- if (acl.isGranted(requiredPermissions, sids, false)) {
- return Tag.EVAL_BODY_INCLUDE;
- } else {
- return Tag.SKIP_BODY;
- }
- } catch (NotFoundException nfe) {
- return Tag.SKIP_BODY;
+ private int skipBody() {
+ if (var != null) {
+ pageContext.setAttribute(var, Boolean.FALSE, PageContext.PAGE_SCOPE);
}
+ return TagLibConfig.evalOrSkip(false);
}
+ private int evalBody() {
+ if (var != null) {
+ pageContext.setAttribute(var, Boolean.TRUE, PageContext.PAGE_SCOPE);
+ }
+ return TagLibConfig.evalOrSkip(true);
+ }
+
+
/**
* Allows test cases to override where application context obtained from.
*
@@ -169,25 +136,7 @@ public class AccessControlListTag extends TagSupport {
this.applicationContext = getContext(pageContext);
- aclService = getBeanOfType(AclService.class);
-
- sidRetrievalStrategy = getBeanOfType(SidRetrievalStrategy.class);
-
- if (sidRetrievalStrategy == null) {
- sidRetrievalStrategy = new SidRetrievalStrategyImpl();
- }
-
- objectIdentityRetrievalStrategy = getBeanOfType(ObjectIdentityRetrievalStrategy.class);
-
- if (objectIdentityRetrievalStrategy == null) {
- objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl();
- }
-
- permissionFactory = getBeanOfType(PermissionFactory.class);
-
- if (permissionFactory == null) {
- permissionFactory = new DefaultPermissionFactory();
- }
+ permissionEvaluator = getBeanOfType(PermissionEvaluator.class);
}
private <T> T getBeanOfType(Class<T> type) throws JspException {
@@ -208,24 +157,6 @@ public class AccessControlListTag extends TagSupport {
+ "application context - you must have only have one!");
}
- private List<Permission> parsePermissionsString(String permissionsString) throws NumberFormatException {
- final Set<Permission> permissions = new HashSet<Permission>();
- final StringTokenizer tokenizer;
- tokenizer = new StringTokenizer(permissionsString, ",", false);
-
- while (tokenizer.hasMoreTokens()) {
- String permission = tokenizer.nextToken();
- try {
- permissions.add(permissionFactory.buildFromMask(Integer.valueOf(permission)));
- } catch (NumberFormatException nfe) {
- // Not an integer mask. Try using a name
- permissions.add(permissionFactory.buildFromName(permission));
- }
- }
-
- return new ArrayList<Permission>(permissions);
- }
-
public void setDomainObject(Object domainObject) {
this.domainObject = domainObject;
}
@@ -233,4 +164,8 @@ public class AccessControlListTag extends TagSupport {
public void setHasPermission(String hasPermission) {
this.hasPermission = hasPermission;
}
+
+ public void setVar(String var) {
+ this.var = var;
+ }
}
diff --git a/dist/spring-security-taglibs/org/springframework/security/taglibs/authz/AuthenticationTag.java b/dist/spring-security-taglibs/org/springframework/security/taglibs/authz/AuthenticationTag.java
index 04a286b..f79cfe0 100644
--- a/dist/spring-security-taglibs/org/springframework/security/taglibs/authz/AuthenticationTag.java
+++ b/dist/spring-security-taglibs/org/springframework/security/taglibs/authz/AuthenticationTag.java
@@ -23,7 +23,6 @@ import org.springframework.security.web.util.TextEscapeUtils;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.BeansException;
-import org.springframework.web.util.ExpressionEvaluationUtils;
import org.springframework.web.util.TagUtils;
import java.io.IOException;
@@ -144,13 +143,12 @@ public class AuthenticationTag extends TagSupport {
* Set HTML escaping for this tag, as boolean value.
*/
public void setHtmlEscape(String htmlEscape) throws JspException {
- this.htmlEscape = ExpressionEvaluationUtils.evaluateBoolean("htmlEscape", htmlEscape, pageContext);
+ this.htmlEscape = Boolean.valueOf(htmlEscape);
}
/**
* Return the HTML escaping setting for this tag,
* or the default setting if not overridden.
- * @see #isDefaultHtmlEscape()
*/
protected boolean isHtmlEscape() {
return htmlEscape;
diff --git a/dist/spring-security-taglibs/org/springframework/security/taglibs/authz/AuthorizeTag.java b/dist/spring-security-taglibs/org/springframework/security/taglibs/authz/AuthorizeTag.java
deleted file mode 100644
index af28090..0000000
--- a/dist/spring-security-taglibs/org/springframework/security/taglibs/authz/AuthorizeTag.java
+++ /dev/null
@@ -1,125 +0,0 @@
-package org.springframework.security.taglibs.authz;
-
-import java.io.IOException;
-import java.util.Map;
-
-import javax.servlet.FilterChain;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.jsp.JspException;
-
-import org.springframework.context.ApplicationContext;
-import org.springframework.expression.Expression;
-import org.springframework.expression.ParseException;
-import org.springframework.security.access.expression.ExpressionUtils;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.web.FilterInvocation;
-import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator;
-import org.springframework.security.web.access.expression.WebSecurityExpressionHandler;
-import org.springframework.web.context.support.WebApplicationContextUtils;
-
-/**
- * Access control tag which evaluates its body based either on
- * <ul>
- * <li>an access expression (the "access" attribute), or</li>
- * <li>by evaluating the current user's right to access a particular URL (set using the "url" attribute).</li>
- * </ul>
- * @author Luke Taylor
- * @since 3.0
- */
-public class AuthorizeTag extends LegacyAuthorizeTag {
- private String access;
- private String url;
- private String method;
-
- // If access expression evaluates to "true" return
- public int doStartTag() throws JspException {
- Authentication currentUser = SecurityContextHolder.getContext().getAuthentication();
-
- if (currentUser == null) {
- return SKIP_BODY;
- }
-
- if (access != null && access.length() > 0) {
- return authorizeUsingAccessExpression(currentUser);
- } else if (url != null && url.length() > 0) {
- return authorizeUsingUrlCheck(currentUser);
- }
-
- return super.doStartTag();
- }
-
- private int authorizeUsingAccessExpression(Authentication currentUser) throws JspException {
- // Get web expression
- WebSecurityExpressionHandler handler = getExpressionHandler();
-
- Expression accessExpression;
- try {
- accessExpression = handler.getExpressionParser().parseExpression(access);
-
- } catch (ParseException e) {
- throw new JspException(e);
- }
-
- FilterInvocation f = new FilterInvocation(pageContext.getRequest(), pageContext.getResponse(), DUMMY_CHAIN);
-
- if (ExpressionUtils.evaluateAsBoolean(accessExpression, handler.createEvaluationContext(currentUser, f))) {
- return EVAL_BODY_INCLUDE;
- }
-
- return SKIP_BODY;
- }
-
- private int authorizeUsingUrlCheck(Authentication currentUser) throws JspException {
- return getPrivilegeEvaluator().isAllowed(((HttpServletRequest)pageContext.getRequest()).getContextPath(),
- url, method, currentUser) ? EVAL_BODY_INCLUDE : SKIP_BODY;
- }
-
- public void setAccess(String access) {
- this.access = access;
- }
-
- public void setUrl(String url) {
- this.url = url;
- }
-
- public void setMethod(String method) {
- this.method = method;
- }
-
- WebSecurityExpressionHandler getExpressionHandler() throws JspException {
- ServletContext servletContext = pageContext.getServletContext();
- ApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
- Map<String, WebSecurityExpressionHandler> expressionHdlrs = ctx.getBeansOfType(WebSecurityExpressionHandler.class);
-
- if (expressionHdlrs.size() == 0) {
- throw new JspException("No visible WebSecurityExpressionHandler instance could be found in the application " +
- "context. There must be at least one in order to support expressions in JSP 'authorize' tags.");
- }
-
- return (WebSecurityExpressionHandler) expressionHdlrs.values().toArray()[0];
- }
-
- WebInvocationPrivilegeEvaluator getPrivilegeEvaluator() throws JspException {
- ServletContext servletContext = pageContext.getServletContext();
- ApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
- Map<String, WebInvocationPrivilegeEvaluator> wipes = ctx.getBeansOfType(WebInvocationPrivilegeEvaluator.class);
-
- if (wipes.size() == 0) {
- throw new JspException("No visible WebInvocationPrivilegeEvaluator instance could be found in the application " +
- "context. There must be at least one in order to support the use of URL access checks in 'authorize' tags.");
- }
-
- return (WebInvocationPrivilegeEvaluator) wipes.values().toArray()[0];
- }
-
- private static final FilterChain DUMMY_CHAIN = new FilterChain() {
- public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
- throw new UnsupportedOperationException();
- }
- };
-}
diff --git a/dist/spring-security-taglibs/org/springframework/security/taglibs/authz/LegacyAuthorizeTag.java b/dist/spring-security-taglibs/org/springframework/security/taglibs/authz/LegacyAuthorizeTag.java
deleted file mode 100644
index 4f120c9..0000000
--- a/dist/spring-security-taglibs/org/springframework/security/taglibs/authz/LegacyAuthorizeTag.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/* Copyright 2004, 2005, 2006 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.taglibs.authz;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-import javax.servlet.jsp.JspException;
-import javax.servlet.jsp.tagext.Tag;
-import javax.servlet.jsp.tagext.TagSupport;
-
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.authority.AuthorityUtils;
-import org.springframework.security.core.authority.GrantedAuthorityImpl;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.web.util.ExpressionEvaluationUtils;
-
-
-/**
- * An implementation of {@link javax.servlet.jsp.tagext.Tag} that allows it's body through if some authorizations
- * are granted to the request's principal.
- *
- * @author Francois Beausoleil
- */
-public class LegacyAuthorizeTag extends TagSupport {
- //~ Instance fields ================================================================================================
-
- private String ifAllGranted = "";
- private String ifAnyGranted = "";
- private String ifNotGranted = "";
-
- //~ Methods ========================================================================================================
-
- private Set<String> authoritiesToRoles(Collection<GrantedAuthority> c) {
- Set<String> target = new HashSet<String>();
-
- for (GrantedAuthority authority : c) {
- if (null == authority.getAuthority()) {
- throw new IllegalArgumentException(
- "Cannot process GrantedAuthority objects which return null from getAuthority() - attempting to process "
- + authority.toString());
- }
-
- target.add(authority.getAuthority());
- }
-
- return target;
- }
-
- public int doStartTag() throws JspException {
- if (((null == ifAllGranted) || "".equals(ifAllGranted)) && ((null == ifAnyGranted) || "".equals(ifAnyGranted))
- && ((null == ifNotGranted) || "".equals(ifNotGranted))) {
- return Tag.SKIP_BODY;
- }
-
- final Collection<GrantedAuthority> granted = getPrincipalAuthorities();
-
- final String evaledIfNotGranted = ExpressionEvaluationUtils.evaluateString("ifNotGranted", ifNotGranted,
- pageContext);
-
- if ((null != evaledIfNotGranted) && !"".equals(evaledIfNotGranted)) {
- Set<GrantedAuthority> grantedCopy = retainAll(granted, parseAuthoritiesString(evaledIfNotGranted));
-
- if (!grantedCopy.isEmpty()) {
- return Tag.SKIP_BODY;
- }
- }
-
- final String evaledIfAllGranted = ExpressionEvaluationUtils.evaluateString("ifAllGranted", ifAllGranted,
- pageContext);
-
- if ((null != evaledIfAllGranted) && !"".equals(evaledIfAllGranted)) {
- if (!granted.containsAll(parseAuthoritiesString(evaledIfAllGranted))) {
- return Tag.SKIP_BODY;
- }
- }
-
- final String evaledIfAnyGranted = ExpressionEvaluationUtils.evaluateString("ifAnyGranted", ifAnyGranted,
- pageContext);
-
- if ((null != evaledIfAnyGranted) && !"".equals(evaledIfAnyGranted)) {
- Set<GrantedAuthority> grantedCopy = retainAll(granted, parseAuthoritiesString(evaledIfAnyGranted));
-
- if (grantedCopy.isEmpty()) {
- return Tag.SKIP_BODY;
- }
- }
-
- return Tag.EVAL_BODY_INCLUDE;
- }
-
- public String getIfAllGranted() {
- return ifAllGranted;
- }
-
- public String getIfAnyGranted() {
- return ifAnyGranted;
- }
-
- public String getIfNotGranted() {
- return ifNotGranted;
- }
-
- private Collection<GrantedAuthority> getPrincipalAuthorities() {
- Authentication currentUser = SecurityContextHolder.getContext().getAuthentication();
-
- if (null == currentUser) {
- return Collections.emptyList();
- }
-
- return currentUser.getAuthorities();
- }
-
- private Set<GrantedAuthority> parseAuthoritiesString(String authorizationsString) {
- final Set<GrantedAuthority> requiredAuthorities = new HashSet<GrantedAuthority>();
- requiredAuthorities.addAll(AuthorityUtils.commaSeparatedStringToAuthorityList(authorizationsString));
-
- return requiredAuthorities;
- }
-
- /**
- * Find the common authorities between the current authentication's {@link GrantedAuthority} and the ones
- * that have been specified in the tag's ifAny, ifNot or ifAllGranted attributes.<p>We need to manually
- * iterate over both collections, because the granted authorities might not implement {@link
- * Object#equals(Object)} and {@link Object#hashCode()} in the same way as {@link GrantedAuthorityImpl}, thereby
- * invalidating {@link Collection#retainAll(java.util.Collection)} results.</p>
- * <p>
- * <strong>CAVEAT</strong>: This method <strong>will not</strong> work if the granted authorities
- * returns a <code>null</code> string as the return value of {@link GrantedAuthority#getAuthority()}.
- * </p>
- *
- * @param granted The authorities granted by the authentication. May be any implementation of {@link
- * GrantedAuthority} that does <strong>not</strong> return <code>null</code> from {@link
- * GrantedAuthority#getAuthority()}.
- * @param required A {@link Set} of {@link GrantedAuthorityImpl}s that have been built using ifAny, ifAll or
- * ifNotGranted.
- *
- * @return A set containing only the common authorities between <var>granted</var> and <var>required</var>.
- *
- */
- private Set<GrantedAuthority> retainAll(final Collection<GrantedAuthority> granted, final Set<GrantedAuthority> required) {
- Set<String> grantedRoles = authoritiesToRoles(granted);
- Set<String> requiredRoles = authoritiesToRoles(required);
- grantedRoles.retainAll(requiredRoles);
-
- return rolesToAuthorities(grantedRoles, granted);
- }
-
- private Set<GrantedAuthority> rolesToAuthorities(Set<String> grantedRoles, Collection<GrantedAuthority> granted) {
- Set<GrantedAuthority> target = new HashSet<GrantedAuthority>();
-
- for (String role : grantedRoles) {
- for (GrantedAuthority authority : granted) {
- if (authority.getAuthority().equals(role)) {
- target.add(authority);
-
- break;
- }
- }
- }
-
- return target;
- }
-
- public void setIfAllGranted(String ifAllGranted) throws JspException {
- this.ifAllGranted = ifAllGranted;
- }
-
- public void setIfAnyGranted(String ifAnyGranted) throws JspException {
- this.ifAnyGranted = ifAnyGranted;
- }
-
- public void setIfNotGranted(String ifNotGranted) throws JspException {
- this.ifNotGranted = ifNotGranted;
- }
-}
diff --git a/dist/spring-security-taglibs/org/springframework/security/taglibs/velocity/AuthzImpl.java b/dist/spring-security-taglibs/org/springframework/security/taglibs/velocity/AuthzImpl.java
index 403c153..56fa3b1 100644
--- a/dist/spring-security-taglibs/org/springframework/security/taglibs/velocity/AuthzImpl.java
+++ b/dist/spring-security-taglibs/org/springframework/security/taglibs/velocity/AuthzImpl.java
@@ -20,7 +20,7 @@ import javax.servlet.jsp.tagext.Tag;
import org.springframework.context.ApplicationContext;
import org.springframework.security.taglibs.authz.AuthenticationTag;
-import org.springframework.security.taglibs.authz.LegacyAuthorizeTag;
+import org.springframework.security.taglibs.authz.JspAuthorizeTag;
/**
@@ -72,12 +72,12 @@ public class AuthzImpl implements Authz {
}
/**
- * implementation of LegacyAuthorizeTag
+ * implementation of JspAuthorizeTag
*/
private boolean ifGranted(String roles, int grantType) {
- LegacyAuthorizeTag authorizeTag = new LegacyAuthorizeTag();
+ JspAuthorizeTag authorizeTag = new JspAuthorizeTag();
- int result = -1;
+ int result;
try {
switch (grantType) {
@@ -105,11 +105,7 @@ public class AuthzImpl implements Authz {
throw new IllegalArgumentException(je.getMessage());
}
- if (Tag.EVAL_BODY_INCLUDE == result) {
- return true;
- } else {
- return false;
- }
+ return Tag.EVAL_BODY_INCLUDE == result;
}
public boolean noneGranted(String roles) {
diff --git a/dist/spring-security-web/META-INF/MANIFEST.MF b/dist/spring-security-web/META-INF/MANIFEST.MF
index 351fd34..58630c0 100644
--- a/dist/spring-security-web/META-INF/MANIFEST.MF
+++ b/dist/spring-security-web/META-INF/MANIFEST.MF
@@ -1,4 +1,2 @@
Manifest-Version: 1.0
-Archiver-Version: Plexus Archiver
-Created-By: 17.1-b03-307 (Apple Inc.)
diff --git a/dist/spring-security-web/org/springframework/security/web/FilterChainProxy.java b/dist/spring-security-web/org/springframework/security/web/FilterChainProxy.java
index 8f4e564..bd163f1 100644
--- a/dist/spring-security-web/org/springframework/security/web/FilterChainProxy.java
+++ b/dist/spring-security-web/org/springframework/security/web/FilterChainProxy.java
@@ -17,23 +17,18 @@ package org.springframework.security.web;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.firewall.DefaultHttpFirewall;
import org.springframework.security.web.firewall.FirewalledRequest;
import org.springframework.security.web.firewall.HttpFirewall;
-import org.springframework.security.web.util.AntUrlPathMatcher;
-import org.springframework.security.web.util.UrlMatcher;
+import org.springframework.security.web.util.RequestMatcher;
import org.springframework.security.web.util.UrlUtils;
-import org.springframework.util.Assert;
import org.springframework.web.filter.DelegatingFilterProxy;
import org.springframework.web.filter.GenericFilterBean;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
-import javax.servlet.ServletRequestWrapper;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -45,46 +40,46 @@ import java.util.*;
* Delegates {@code Filter} requests to a list of Spring-managed filter beans.
* As of version 2.0, you shouldn't need to explicitly configure a {@code FilterChainProxy} bean in your application
* context unless you need very fine control over the filter chain contents. Most cases should be adequately covered
- * by the default <tt><security:http /></tt> namespace configuration options.
- *
- * <p>The <code>FilterChainProxy</code> is loaded via a standard Spring {@link DelegatingFilterProxy} declaration in
- * <code>web.xml</code>. <code>FilterChainProxy</code> will then pass {@link #init(FilterConfig)}, {@link #destroy()}
- * and {@link #doFilter(ServletRequest, ServletResponse, FilterChain)} invocations through to each <code>Filter</code>
- * defined against <code>FilterChainProxy</code>.
+ * by the default {@code <security:http />} namespace configuration options.
+ * <p>
+ * The {@code FilterChainProxy} is linked into the servlet container filter chain by adding a standard
+ * Spring {@link DelegatingFilterProxy} declaration in the application {@code web.xml} file.
*
- * <p>As of version 2.0, <tt>FilterChainProxy</tt> is configured using an ordered Map of path patterns to <tt>List</tt>s
- * of <tt>Filter</tt> objects. In previous
- * versions, a {@link FilterInvocationSecurityMetadataSource} was used. This is now deprecated in favour of namespace-based
- * configuration which provides a more robust and simplfied syntax. The Map instance will normally be
- * created while parsing the namespace configuration, so doesn't have to be set explicitly.
- * Instead the <filter-chain-map> element should be used within the FilterChainProxy bean declaration.
- * This in turn should have a list of child <filter-chain> elements which each define a URI pattern and the list
- * of filters (as comma-separated bean names) which should be applied to requests which match the pattern.
- * An example configuration might look like this:
+ * <h2>Configuration</h2>
+ * <p>
+ * As of version 3.1, {@code FilterChainProxy} is configured using a list of {@link SecurityFilterChain} instances,
+ * each of which contains a {@link RequestMatcher} and a list of filters which should be applied to matching requests.
+ * Most applications will only contain a single filter chain, and if you are using the namespace, you don't have to
+ * set the chains explicitly. If you require finer-grained control, you can make use of the {@code <filter-chain>}
+ * namespace element. This defines a URI pattern and the list of filters (as comma-separated bean names) which should be
+ * applied to requests which match the pattern. An example configuration might look like this:
*
* <pre>
<bean id="myfilterChainProxy" class="org.springframework.security.util.FilterChainProxy">
- <security:filter-chain-map pathType="ant">
- <security:filter-chain pattern="/do/not/filter" filters="none"/>
- <security:filter-chain pattern="/**" filters="filter1,filter2,filter3"/>
- </security:filter-chain-map>
+ <constructor-arg>
+ <util:list>
+ <security:filter-chain pattern="/do/not/filter*" filters="none"/>
+ <security:filter-chain pattern="/**" filters="filter1,filter2,filter3"/>
+ </util:list>
+ </constructor-arg>
</bean>
* </pre>
*
* The names "filter1", "filter2", "filter3" should be the bean names of {@code Filter} instances defined in the
* application context. The order of the names defines the order in which the filters will be applied. As shown above,
- * use of the value "none" for the "filters" can be used to exclude
- * Please consult the security namespace schema file for a full list of available configuration options.
+ * use of the value "none" for the "filters" can be used to exclude a request pattern from the security filter chain
+ * entirely. Please consult the security namespace schema file for a full list of available configuration options.
*
+ * <h2>Request Handling</h2>
* <p>
- * Each possible URI pattern that <code>FilterChainProxy</code> should service must be entered.
- * The first matching URI pattern for a given request will be used to define all of the
- * <code>Filter</code>s that apply to that request. NB: This means you must put most specific URI patterns at the top
- * of the list, and ensure all <code>Filter</code>s that should apply for a given URI pattern are entered against the
- * respective entry. The <code>FilterChainProxy</code> will not iterate the remainder of the URI patterns to locate
- * additional <code>Filter</code>s.
- *
- * <p><code>FilterChainProxy</code> respects normal handling of <code>Filter</code>s that elect not to call {@link
+ * Each possible pattern that the {@code FilterChainProxy} should service must be entered.
+ * The first match for a given request will be used to define all of the {@code Filter}s that apply to that
+ * request. This means you must put most specific matches at the top of the list, and ensure all {@code Filter}s
+ * that should apply for a given matcher are entered against the respective entry.
+ * The {@code FilterChainProxy} will not iterate through the remainder of the map entries to locate additional
+ * {@code Filter}s.
+ * <p>
+ * {@code FilterChainProxy} respects normal handling of {@code Filter}s that elect not to call {@link
* javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse,
* javax.servlet.FilterChain)}, in that the remainder of the original or {@code FilterChainProxy}-declared filter
* chain will not be called.
@@ -105,6 +100,10 @@ import java.util.*;
* response. When the request has passed through the security filter chain, the {@code reset} method will be called.
* With the default implementation this means that the original values of {@code servletPath} and {@code pathInfo} will
* be returned thereafter, instead of the modified ones used for security pattern matching.
+ * <p>
+ * Since this additional wrapping functionality is performed by the {@code FilterChainProxy}, we don't recommend that
+ * you use multiple instances in the same filter chain. It shouldn't be considered purely as a utility for wrapping
+ * filter beans in a single {@code Filter} instance.
*
* <h2>Filter Lifecycle</h2>
* <p>
@@ -116,31 +115,36 @@ import java.util.*;
* @author Carlos Sanchez
* @author Ben Alex
* @author Luke Taylor
- *
+ * @author Rob Winch
*/
public class FilterChainProxy extends GenericFilterBean {
//~ Static fields/initializers =====================================================================================
private static final Log logger = LogFactory.getLog(FilterChainProxy.class);
- public static final String TOKEN_NONE = "#NONE#";
//~ Instance fields ================================================================================================
-// private ApplicationContext applicationContext;
- /** Map of the original pattern Strings to filter chains */
- private Map<String, List<Filter>> uncompiledFilterChainMap;
- /** Compiled pattern version of the filter chain map */
- private Map<Object, List<Filter>> filterChainMap;
- private UrlMatcher matcher = new AntUrlPathMatcher();
- private boolean stripQueryStringFromUrls = true;
- private HttpFirewall firewall = new DefaultHttpFirewall();
+ private List<SecurityFilterChain> filterChains;
+
private FilterChainValidator filterChainValidator = new NullFilterChainValidator();
+ private HttpFirewall firewall = new DefaultHttpFirewall();
+
//~ Methods ========================================================================================================
+ public FilterChainProxy() {
+ }
+
+ public FilterChainProxy(SecurityFilterChain chain) {
+ this(Arrays.asList(chain));
+ }
+
+ public FilterChainProxy(List<SecurityFilterChain> filterChains) {
+ this.filterChains = filterChains;
+ }
+
@Override
public void afterPropertiesSet() {
- Assert.notNull(uncompiledFilterChainMap, "filterChainMap must be set");
filterChainValidator.validate(this);
}
@@ -149,13 +153,13 @@ public class FilterChainProxy extends GenericFilterBean {
FirewalledRequest fwRequest = firewall.getFirewalledRequest((HttpServletRequest) request);
HttpServletResponse fwResponse = firewall.getFirewalledResponse((HttpServletResponse) response);
- String url = UrlUtils.buildRequestUrl(fwRequest);
- List<Filter> filters = getFilters(url);
+ List<Filter> filters = getFilters(fwRequest);
if (filters == null || filters.size() == 0) {
if (logger.isDebugEnabled()) {
- logger.debug(url + (filters == null ? " has no matching filters" : " has an empty filter list"));
+ logger.debug(UrlUtils.buildRequestUrl(fwRequest) +
+ (filters == null ? " has no matching filters" : " has an empty filter list"));
}
fwRequest.reset();
@@ -165,45 +169,20 @@ public class FilterChainProxy extends GenericFilterBean {
return;
}
- VirtualFilterChain vfc = new VirtualFilterChain(url, chain, filters);
+ VirtualFilterChain vfc = new VirtualFilterChain(fwRequest, chain, filters);
vfc.doFilter(fwRequest, fwResponse);
}
/**
* Returns the first filter chain matching the supplied URL.
*
- * @param url the request URL
+ * @param request the request to match
* @return an ordered array of Filters defining the filter chain
*/
- public List<Filter> getFilters(String url) {
- if (stripQueryStringFromUrls) {
- // String query string - see SEC-953
- int firstQuestionMarkIndex = url.indexOf("?");
-
- if (firstQuestionMarkIndex != -1) {
- url = url.substring(0, firstQuestionMarkIndex);
- }
- }
-
- for (Map.Entry<Object, List<Filter>> entry : filterChainMap.entrySet()) {
- Object path = entry.getKey();
-
- if (matcher.requiresLowerCaseUrl()) {
- url = url.toLowerCase();
-
- if (logger.isDebugEnabled()) {
- logger.debug("Converted URL to lowercase, from: '" + url + "'; to: '" + url + "'");
- }
- }
-
- boolean matched = matcher.pathMatchesUrl(path, url);
-
- if (logger.isDebugEnabled()) {
- logger.debug("Candidate is: '" + url + "'; pattern is " + path + "; matched=" + matched);
- }
-
- if (matched) {
- return entry.getValue();
+ private List<Filter> getFilters(HttpServletRequest request) {
+ for (SecurityFilterChain chain : filterChains) {
+ if (chain.matches(request)) {
+ return chain.getFilters();
}
}
@@ -211,23 +190,13 @@ public class FilterChainProxy extends GenericFilterBean {
}
/**
- * Obtains all of the <b>unique</b><code>Filter</code> instances registered in the map of
- * filter chains.
- * <p>This is useful in ensuring a <code>Filter</code> is not initialized or destroyed twice.</p>
+ * Convenience method, mainly for testing.
*
- * @return all of the <code>Filter</code> instances in the application context which have an entry
- * in the map (only one entry is included in the array for
- * each <code>Filter</code> that actually exists in application context, even if a given
- * <code>Filter</code> is defined multiples times in the filter chain map)
+ * @param url the URL
+ * @return matching filter list
*/
- protected Collection<Filter> obtainAllDefinedFilters() {
- Set<Filter> allFilters = new LinkedHashSet<Filter>();
-
- for (List<Filter> filters : filterChainMap.values()) {
- allFilters.addAll(filters);
- }
-
- return allFilters;
+ public List<Filter> getFilters(String url) {
+ return getFilters(firewall.getFirewalledRequest((new FilterInvocation(url, null).getRequest())));
}
/**
@@ -241,98 +210,69 @@ public class FilterChainProxy extends GenericFilterBean {
* example.
*
* @param filterChainMap the map of path Strings to {@code List<Filter>}s.
+ * @deprecated Use the constructor which takes a {@code List<SecurityFilterChain>} instead.
*/
- @SuppressWarnings("unchecked")
- public void setFilterChainMap(Map filterChainMap) {
- checkContents(filterChainMap);
- uncompiledFilterChainMap = new LinkedHashMap<String, List<Filter>>(filterChainMap);
- checkPathOrder();
- createCompiledMap();
- }
-
- @SuppressWarnings("unchecked")
- private void checkContents(Map filterChainMap) {
- for (Object key : filterChainMap.keySet()) {
- Assert.isInstanceOf(String.class, key, "Path key must be a String but found " + key);
- Object filters = filterChainMap.get(key);
- Assert.isInstanceOf(List.class, filters, "Value must be a filter list");
- // Check the contents
- Iterator filterIterator = ((List)filters).iterator();
-
- while (filterIterator.hasNext()) {
- Object filter = filterIterator.next();
- Assert.isInstanceOf(Filter.class, filter, "Objects in filter chain must be of type Filter. ");
- }
- }
- }
-
- private void checkPathOrder() {
- // Check that the universal pattern is listed at the end, if at all
- String[] paths = (String[]) uncompiledFilterChainMap.keySet().toArray(new String[0]);
- String universalMatch = matcher.getUniversalMatchPattern();
+ @Deprecated
+ public void setFilterChainMap(Map<RequestMatcher, List<Filter>> filterChainMap) {
+ filterChains = new ArrayList<SecurityFilterChain>(filterChainMap.size());
- for (int i=0; i < paths.length-1; i++) {
- if (paths[i].equals(universalMatch)) {
- throw new IllegalArgumentException("A universal match pattern " + universalMatch + " is defined " +
- " before other patterns in the filter chain, causing them to be ignored. Please check the " +
- "ordering in your <security:http> namespace or FilterChainProxy bean configuration");
- }
- }
- }
-
- private void createCompiledMap() {
- filterChainMap = new LinkedHashMap<Object, List<Filter>>(uncompiledFilterChainMap.size());
-
- for (String path : uncompiledFilterChainMap.keySet()) {
- filterChainMap.put(matcher.compile(path), uncompiledFilterChainMap.get(path));
+ for (Map.Entry<RequestMatcher,List<Filter>> entry : filterChainMap.entrySet()) {
+ filterChains.add(new DefaultSecurityFilterChain(entry.getKey(), entry.getValue()));
}
}
/**
* Returns a copy of the underlying filter chain map. Modifications to the map contents
- * will not affect the FilterChainProxy state - to change the map call {@code setFilterChainMap}.
+ * will not affect the FilterChainProxy state.
*
* @return the map of path pattern Strings to filter chain lists (with ordering guaranteed).
+ *
+ * @deprecated use the list of {@link SecurityFilterChain}s instead
*/
- public Map<String, List<Filter>> getFilterChainMap() {
- return new LinkedHashMap<String, List<Filter>>(uncompiledFilterChainMap);
- }
-
- public void setMatcher(UrlMatcher matcher) {
- this.matcher = matcher;
- }
+ @Deprecated
+ public Map<RequestMatcher, List<Filter>> getFilterChainMap() {
+ LinkedHashMap<RequestMatcher, List<Filter>> map = new LinkedHashMap<RequestMatcher, List<Filter>>();
- public UrlMatcher getMatcher() {
- return matcher;
- }
+ for (SecurityFilterChain chain : filterChains) {
+ map.put(((DefaultSecurityFilterChain)chain).getRequestMatcher(), chain.getFilters());
+ }
- public void setFirewall(HttpFirewall firewall) {
- this.firewall = firewall;
+ return map;
}
/**
- * If set to 'true', the query string will be stripped from the request URL before
- * attempting to find a matching filter chain. This is the default value.
+ * @return the list of {@code SecurityFilterChain}s which will be matched against and
+ * applied to incoming requests.
*/
- public void setStripQueryStringFromUrls(boolean stripQueryStringFromUrls) {
- this.stripQueryStringFromUrls = stripQueryStringFromUrls;
+ public List<SecurityFilterChain> getFilterChains() {
+ return Collections.unmodifiableList(filterChains);
}
/**
* Used (internally) to specify a validation strategy for the filters in each configured chain.
*
- * @param filterChainValidator
+ * @param filterChainValidator the validator instance which will be invoked on during initialization
+ * to check the {@code FilterChainProxy} instance.
*/
public void setFilterChainValidator(FilterChainValidator filterChainValidator) {
this.filterChainValidator = filterChainValidator;
}
+ /**
+ * Sets the "firewall" implementation which will be used to validate and wrap (or potentially reject) the
+ * incoming requests. The default implementation should be satisfactory for most requirements.
+ *
+ * @param firewall
+ */
+ public void setFirewall(HttpFirewall firewall) {
+ this.firewall = firewall;
+ }
+
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("FilterChainProxy[");
- sb.append(" UrlMatcher = ").append(matcher);
- sb.append("; Filter Chains: ");
- sb.append(uncompiledFilterChainMap);
+ sb.append("Filter Chains: ");
+ sb.append(filterChains);
sb.append("]");
return sb.toString();
@@ -347,23 +287,26 @@ public class FilterChainProxy extends GenericFilterBean {
private static class VirtualFilterChain implements FilterChain {
private final FilterChain originalChain;
private final List<Filter> additionalFilters;
- private final String url;
+ private final FirewalledRequest firewalledRequest;
+ private final int size;
private int currentPosition = 0;
- private VirtualFilterChain(String url, FilterChain chain, List<Filter> additionalFilters) {
+ private VirtualFilterChain(FirewalledRequest firewalledRequest, FilterChain chain, List<Filter> additionalFilters) {
this.originalChain = chain;
- this.url = url;
this.additionalFilters = additionalFilters;
+ this.size = additionalFilters.size();
+ this.firewalledRequest = firewalledRequest;
}
- public void doFilter(final ServletRequest request, final ServletResponse response) throws IOException, ServletException {
- if (currentPosition == additionalFilters.size()) {
+ public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
+ if (currentPosition == size) {
if (logger.isDebugEnabled()) {
- logger.debug(url + " reached end of additional filter chain; proceeding with original chain");
+ logger.debug(UrlUtils.buildRequestUrl(firewalledRequest)
+ + " reached end of additional filter chain; proceeding with original chain");
}
// Deactivate path stripping as we exit the security filter chain
- resetWrapper(request);
+ this.firewalledRequest.reset();
originalChain.doFilter(request, response);
} else {
@@ -372,24 +315,14 @@ public class FilterChainProxy extends GenericFilterBean {
Filter nextFilter = additionalFilters.get(currentPosition - 1);
if (logger.isDebugEnabled()) {
- logger.debug(url + " at position " + currentPosition + " of "
- + additionalFilters.size() + " in additional filter chain; firing Filter: '"
+ logger.debug(UrlUtils.buildRequestUrl(firewalledRequest) + " at position " + currentPosition + " of "
+ + size + " in additional filter chain; firing Filter: '"
+ nextFilter.getClass().getSimpleName() + "'");
}
nextFilter.doFilter(request, response, this);
}
}
-
- private void resetWrapper(ServletRequest request) {
- while (request instanceof ServletRequestWrapper) {
- if (request instanceof FirewalledRequest) {
- ((FirewalledRequest)request).reset();
- break;
- }
- request = ((ServletRequestWrapper)request).getRequest();
- }
- }
}
public interface FilterChainValidator {
diff --git a/dist/spring-security-web/org/springframework/security/web/FilterInvocation.java b/dist/spring-security-web/org/springframework/security/web/FilterInvocation.java
index 49cb8ed..f7006d5 100644
--- a/dist/spring-security-web/org/springframework/security/web/FilterInvocation.java
+++ b/dist/spring-security-web/org/springframework/security/web/FilterInvocation.java
@@ -15,13 +15,28 @@
package org.springframework.security.web;
-import org.springframework.security.web.util.UrlUtils;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.security.Principal;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Map;
import javax.servlet.FilterChain;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
+import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import org.springframework.security.web.util.UrlUtils;
/**
@@ -34,8 +49,16 @@ import javax.servlet.http.HttpServletResponse;
*
* @author Ben Alex
* @author colin sampaleanu
+ * @author Luke Taylor
*/
public class FilterInvocation {
+ //~ Static fields ==================================================================================================
+ static final FilterChain DUMMY_CHAIN = new FilterChain() {
+ public void doFilter(ServletRequest req, ServletResponse res) throws IOException, ServletException {
+ throw new UnsupportedOperationException("Dummy filter chain");
+ }
+ };
+
//~ Instance fields ================================================================================================
private FilterChain chain;
@@ -54,6 +77,28 @@ public class FilterInvocation {
this.chain = chain;
}
+ public FilterInvocation(String servletPath, String method) {
+ this(null, servletPath, method);
+ }
+
+ public FilterInvocation(String contextPath, String servletPath, String method) {
+ this(contextPath, servletPath, null, null, method);
+ }
+
+ public FilterInvocation(String contextPath, String servletPath, String pathInfo, String query, String method) {
+ DummyRequest request = new DummyRequest();
+ if (contextPath == null) {
+ contextPath = "/cp";
+ }
+ request.setContextPath(contextPath);
+ request.setServletPath(servletPath);
+ request.setRequestURI(contextPath + servletPath + (pathInfo == null ? "" : pathInfo));
+ request.setPathInfo(pathInfo);
+ request.setQueryString(query);
+ request.setMethod(method);
+ this.request = request;
+ }
+
//~ Methods ========================================================================================================
public FilterChain getChain() {
@@ -101,3 +146,387 @@ public class FilterInvocation {
return "FilterInvocation: URL: " + getRequestUrl();
}
}
+
+ at SuppressWarnings({"unchecked", "deprecation"})
+class DummyRequest implements HttpServletRequest {
+ private String requestURI;
+ private String contextPath = "";
+ private String servletPath;
+ private String pathInfo;
+ private String queryString;
+ private String method;
+
+ public void setRequestURI(String requestURI) {
+ this.requestURI = requestURI;
+ }
+
+ public void setPathInfo(String pathInfo) {
+ this.pathInfo = pathInfo;
+ }
+
+ public String getRequestURI() {
+ return requestURI;
+ }
+
+ public void setContextPath(String contextPath) {
+ this.contextPath = contextPath;
+ }
+
+ public String getContextPath() {
+ return contextPath;
+ }
+
+ public void setServletPath(String servletPath) {
+ this.servletPath = servletPath;
+ }
+
+ public String getServletPath() {
+ return servletPath;
+ }
+
+ public void setMethod(String method) {
+ this.method = method;
+ }
+
+ public String getMethod() {
+ return method;
+ }
+
+ public String getPathInfo() {
+ return pathInfo;
+ }
+
+ public String getQueryString() {
+ return queryString;
+ }
+
+ public void setQueryString(String queryString) {
+ this.queryString = queryString;
+ }
+
+
+ public String getAuthType() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Cookie[] getCookies() {
+ throw new UnsupportedOperationException();
+ }
+
+ public long getDateHeader(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getHeader(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Enumeration getHeaderNames() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Enumeration getHeaders(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ public int getIntHeader(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getPathTranslated() {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getRemoteUser() {
+ throw new UnsupportedOperationException();
+ }
+
+ public StringBuffer getRequestURL() {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getRequestedSessionId() {
+ throw new UnsupportedOperationException();
+ }
+
+ public HttpSession getSession() {
+ throw new UnsupportedOperationException();
+ }
+
+ public HttpSession getSession(boolean create) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Principal getUserPrincipal() {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean isRequestedSessionIdFromCookie() {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean isRequestedSessionIdFromURL() {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean isRequestedSessionIdFromUrl() {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean isRequestedSessionIdValid() {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean isUserInRole(String role) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Object getAttribute(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Enumeration getAttributeNames() {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getCharacterEncoding() {
+ throw new UnsupportedOperationException();
+ }
+
+ public int getContentLength() {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getContentType() {
+ throw new UnsupportedOperationException();
+ }
+
+ public ServletInputStream getInputStream() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getLocalAddr() {
+ throw new UnsupportedOperationException();
+
+ }
+
+ public String getLocalName() {
+ throw new UnsupportedOperationException();
+ }
+
+ public int getLocalPort() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Locale getLocale() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Enumeration getLocales() {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getParameter(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Map getParameterMap() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Enumeration getParameterNames() {
+ throw new UnsupportedOperationException();
+ }
+
+ public String[] getParameterValues(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getProtocol() {
+ throw new UnsupportedOperationException();
+ }
+
+ public BufferedReader getReader() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getRealPath(String path) {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getRemoteAddr() {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getRemoteHost() {
+ throw new UnsupportedOperationException();
+ }
+
+ public int getRemotePort() {
+ throw new UnsupportedOperationException();
+ }
+
+ public RequestDispatcher getRequestDispatcher(String path) {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getScheme() {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getServerName() {
+ throw new UnsupportedOperationException();
+ }
+
+ public int getServerPort() {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean isSecure() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void removeAttribute(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setAttribute(String name, Object o) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setCharacterEncoding(String env) throws UnsupportedEncodingException {
+ throw new UnsupportedOperationException();
+ }
+}
+
+ at SuppressWarnings({"deprecation"})
+class DummyResponse implements HttpServletResponse {
+ public void addCookie(Cookie cookie) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void addDateHeader(String name, long date) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void addHeader(String name, String value) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void addIntHeader(String name, int value) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean containsHeader(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ public String encodeRedirectURL(String url) {
+ throw new UnsupportedOperationException();
+ }
+
+ public String encodeRedirectUrl(String url) {
+ throw new UnsupportedOperationException();
+ }
+
+ public String encodeURL(String url) {
+ throw new UnsupportedOperationException();
+ }
+
+ public String encodeUrl(String url) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void sendError(int sc) throws IOException {
+ throw new UnsupportedOperationException();
+
+ }
+
+ public void sendError(int sc, String msg) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void sendRedirect(String location) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setDateHeader(String name, long date) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setHeader(String name, String value) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setIntHeader(String name, int value) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setStatus(int sc) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setStatus(int sc, String sm) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void flushBuffer() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public int getBufferSize() {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getCharacterEncoding() {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getContentType() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Locale getLocale() {
+ throw new UnsupportedOperationException();
+ }
+
+ public ServletOutputStream getOutputStream() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public PrintWriter getWriter() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean isCommitted() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void reset() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void resetBuffer() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setBufferSize(int size) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setCharacterEncoding(String charset) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setContentLength(int len) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setContentType(String type) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setLocale(Locale loc) {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/dist/spring-security-web/org/springframework/security/web/PortMapperImpl.java b/dist/spring-security-web/org/springframework/security/web/PortMapperImpl.java
index 5dd3a6c..31f79e0 100644
--- a/dist/spring-security-web/org/springframework/security/web/PortMapperImpl.java
+++ b/dist/spring-security-web/org/springframework/security/web/PortMapperImpl.java
@@ -34,14 +34,14 @@ import java.util.Map;
public class PortMapperImpl implements PortMapper {
//~ Instance fields ================================================================================================
- private Map<Integer, Integer> httpsPortMappings;
+ private final Map<Integer, Integer> httpsPortMappings;
//~ Constructors ===================================================================================================
public PortMapperImpl() {
httpsPortMappings = new HashMap<Integer, Integer>();
- httpsPortMappings.put(new Integer(80), new Integer(443));
- httpsPortMappings.put(new Integer(8080), new Integer(8443));
+ httpsPortMappings.put(Integer.valueOf(80), Integer.valueOf(443));
+ httpsPortMappings.put(Integer.valueOf(8080), Integer.valueOf(8443));
}
//~ Methods ========================================================================================================
@@ -55,11 +55,7 @@ public class PortMapperImpl implements PortMapper {
}
public Integer lookupHttpPort(Integer httpsPort) {
- Iterator<Integer> iter = httpsPortMappings.keySet().iterator();
-
- while (iter.hasNext()) {
- Integer httpPort = iter.next();
-
+ for (Integer httpPort : httpsPortMappings.keySet()) {
if (httpsPortMappings.get(httpPort).equals(httpsPort)) {
return httpPort;
}
@@ -96,8 +92,8 @@ public class PortMapperImpl implements PortMapper {
httpsPortMappings.clear();
for (Map.Entry<String,String> entry : newMappings.entrySet()) {
- Integer httpPort = new Integer(entry.getKey());
- Integer httpsPort = new Integer(entry.getValue());
+ Integer httpPort = Integer.valueOf(entry.getKey());
+ Integer httpsPort = Integer.valueOf(entry.getValue());
if ((httpPort.intValue() < 1) || (httpPort.intValue() > 65535) || (httpsPort.intValue() < 1)
|| (httpsPort.intValue() > 65535)) {
diff --git a/dist/spring-security-web/org/springframework/security/web/PortResolverImpl.java b/dist/spring-security-web/org/springframework/security/web/PortResolverImpl.java
index 15da2bc..5ab5a31 100644
--- a/dist/spring-security-web/org/springframework/security/web/PortResolverImpl.java
+++ b/dist/spring-security-web/org/springframework/security/web/PortResolverImpl.java
@@ -50,10 +50,10 @@ public class PortResolverImpl implements PortResolver {
String scheme = request.getScheme().toLowerCase();
if ("http".equals(scheme)) {
- portLookup = portMapper.lookupHttpPort(new Integer(serverPort));
+ portLookup = portMapper.lookupHttpPort(Integer.valueOf(serverPort));
} else if ("https".equals(scheme)) {
- portLookup = portMapper.lookupHttpsPort(new Integer(serverPort));
+ portLookup = portMapper.lookupHttpsPort(Integer.valueOf(serverPort));
}
if (portLookup != null) {
diff --git a/dist/spring-security-web/org/springframework/security/web/WebAttributes.java b/dist/spring-security-web/org/springframework/security/web/WebAttributes.java
index 3072e7b..4b4ff38 100644
--- a/dist/spring-security-web/org/springframework/security/web/WebAttributes.java
+++ b/dist/spring-security-web/org/springframework/security/web/WebAttributes.java
@@ -7,8 +7,17 @@ package org.springframework.security.web;
* @since 3.0.3
*/
public final class WebAttributes {
+ /**
+ * Used to cache an {@code AccessDeniedException} in the request for rendering.
+ *
+ * @see org.springframework.security.web.access.AccessDeniedHandlerImpl
+ */
public static final String ACCESS_DENIED_403 = "SPRING_SECURITY_403_EXCEPTION";
+
+ /**
+ * Used to cache an authentication-failure exception in the session.
+ *
+ * @see org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler
+ */
public static final String AUTHENTICATION_EXCEPTION = "SPRING_SECURITY_LAST_EXCEPTION";
- public static final String LAST_USERNAME = "SPRING_SECURITY_LAST_USERNAME";
- public static final String SAVED_REQUEST = "SPRING_SECURITY_SAVED_REQUEST_KEY";
}
diff --git a/dist/spring-security-web/org/springframework/security/web/access/AccessDeniedHandlerImpl.java b/dist/spring-security-web/org/springframework/security/web/access/AccessDeniedHandlerImpl.java
index 43cd1c0..7395a68 100644
--- a/dist/spring-security-web/org/springframework/security/web/access/AccessDeniedHandlerImpl.java
+++ b/dist/spring-security-web/org/springframework/security/web/access/AccessDeniedHandlerImpl.java
@@ -36,17 +36,13 @@ import org.springframework.security.web.WebAttributes;
* Being a "forward", the <code>SecurityContextHolder</code> will remain
* populated. This is of benefit if the view (or a tag library or macro) wishes to access the
* <code>SecurityContextHolder</code>. The request scope will also be populated with the exception itself, available
- * from the key {@link WebAttributes.ACCESS_DENIED_403}.
+ * from the key {@link WebAttributes#ACCESS_DENIED_403}.
*
* @author Ben Alex
*/
public class AccessDeniedHandlerImpl implements AccessDeniedHandler {
//~ Static fields/initializers =====================================================================================
- /**
- * @deprecated Use the value in {@link WebAttributes} directly.
- */
- @Deprecated
- public static final String SPRING_SECURITY_ACCESS_DENIED_EXCEPTION_KEY = WebAttributes.ACCESS_DENIED_403;
+
protected static final Log logger = LogFactory.getLog(AccessDeniedHandlerImpl.class);
//~ Instance fields ================================================================================================
diff --git a/dist/spring-security-web/org/springframework/security/web/access/DefaultWebInvocationPrivilegeEvaluator.java b/dist/spring-security-web/org/springframework/security/web/access/DefaultWebInvocationPrivilegeEvaluator.java
index d60d3bd..1700ed2 100644
--- a/dist/spring-security-web/org/springframework/security/web/access/DefaultWebInvocationPrivilegeEvaluator.java
+++ b/dist/spring-security-web/org/springframework/security/web/access/DefaultWebInvocationPrivilegeEvaluator.java
@@ -15,27 +15,7 @@
package org.springframework.security.web.access;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.UnsupportedEncodingException;
-import java.security.Principal;
import java.util.Collection;
-import java.util.Enumeration;
-import java.util.Locale;
-import java.util.Map;
-
-import javax.servlet.FilterChain;
-import javax.servlet.RequestDispatcher;
-import javax.servlet.ServletException;
-import javax.servlet.ServletInputStream;
-import javax.servlet.ServletOutputStream;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -59,17 +39,9 @@ public class DefaultWebInvocationPrivilegeEvaluator implements WebInvocationPriv
protected static final Log logger = LogFactory.getLog(DefaultWebInvocationPrivilegeEvaluator.class);
- static final FilterChain DUMMY_CHAIN = new FilterChain() {
- public void doFilter(ServletRequest req, ServletResponse res) throws IOException, ServletException {
- throw new UnsupportedOperationException("DefaultWebInvocationPrivilegeEvaluator does not support filter chains");
- }
- };
-
- static final HttpServletResponse DUMMY_RESPONSE = new DummyResponse();
-
//~ Instance fields ================================================================================================
- private AbstractSecurityInterceptor securityInterceptor;
+ private final AbstractSecurityInterceptor securityInterceptor;
//~ Constructors ===================================================================================================
@@ -114,11 +86,7 @@ public class DefaultWebInvocationPrivilegeEvaluator implements WebInvocationPriv
public boolean isAllowed(String contextPath, String uri, String method, Authentication authentication) {
Assert.notNull(uri, "uri parameter is required");
- if (contextPath == null) {
- contextPath = "/ctxpath";
- }
-
- FilterInvocation fi = createFilterInvocation(contextPath, uri, method);
+ FilterInvocation fi = new FilterInvocation(contextPath, uri, method);
Collection<ConfigAttribute> attrs = securityInterceptor.obtainSecurityMetadataSource().getAttributes(fi);
if (attrs == null) {
@@ -145,389 +113,6 @@ public class DefaultWebInvocationPrivilegeEvaluator implements WebInvocationPriv
return true;
}
-
- private FilterInvocation createFilterInvocation(String contextPath, String uri, String method) {
- Assert.hasText(uri, "URI required");
-
- DummyRequest req = new DummyRequest();
- req.setRequestURI(contextPath + uri);
- req.setContextPath(contextPath);
- req.setServletPath(null);
- req.setMethod(method);
-
- return new FilterInvocation(req, DUMMY_RESPONSE, DUMMY_CHAIN);
- }
-}
-
- at SuppressWarnings("unchecked")
-class DummyRequest implements HttpServletRequest {
- private String requestURI;
- private String contextPath = "";
- private String servletPath;
- private String method;
-
- public void setRequestURI(String requestURI) {
- this.requestURI = requestURI;
- }
-
- public String getRequestURI() {
- return requestURI;
- }
-
- public void setContextPath(String contextPath) {
- this.contextPath = contextPath;
- }
-
- public String getContextPath() {
- return contextPath;
- }
-
- public void setServletPath(String servletPath) {
- this.servletPath = servletPath;
- }
-
- public String getServletPath() {
- return servletPath;
- }
-
- public void setMethod(String method) {
- this.method = method;
- }
-
- public String getMethod() {
- return method;
- }
-
- public String getPathInfo() {
- return null;
- }
-
- public String getQueryString() {
- return null;
- }
-
- public String getAuthType() {
- throw new UnsupportedOperationException();
- }
-
- public Cookie[] getCookies() {
- throw new UnsupportedOperationException();
- }
-
- public long getDateHeader(String name) {
- throw new UnsupportedOperationException();
- }
-
- public String getHeader(String name) {
- throw new UnsupportedOperationException();
- }
-
- public Enumeration getHeaderNames() {
- throw new UnsupportedOperationException();
- }
-
- public Enumeration getHeaders(String name) {
- throw new UnsupportedOperationException();
- }
-
- public int getIntHeader(String name) {
- throw new UnsupportedOperationException();
- }
-
- public String getPathTranslated() {
- throw new UnsupportedOperationException();
- }
-
- public String getRemoteUser() {
- throw new UnsupportedOperationException();
- }
-
- public StringBuffer getRequestURL() {
- throw new UnsupportedOperationException();
- }
-
- public String getRequestedSessionId() {
- throw new UnsupportedOperationException();
- }
-
- public HttpSession getSession() {
- throw new UnsupportedOperationException();
- }
-
- public HttpSession getSession(boolean create) {
- throw new UnsupportedOperationException();
- }
-
- public Principal getUserPrincipal() {
- throw new UnsupportedOperationException();
- }
-
- public boolean isRequestedSessionIdFromCookie() {
- throw new UnsupportedOperationException();
- }
-
- public boolean isRequestedSessionIdFromURL() {
- throw new UnsupportedOperationException();
- }
-
- public boolean isRequestedSessionIdFromUrl() {
- throw new UnsupportedOperationException();
- }
-
- public boolean isRequestedSessionIdValid() {
- throw new UnsupportedOperationException();
- }
-
- public boolean isUserInRole(String role) {
- throw new UnsupportedOperationException();
- }
-
- public Object getAttribute(String name) {
- throw new UnsupportedOperationException();
- }
-
- public Enumeration getAttributeNames() {
- throw new UnsupportedOperationException();
- }
-
- public String getCharacterEncoding() {
- throw new UnsupportedOperationException();
- }
-
- public int getContentLength() {
- throw new UnsupportedOperationException();
- }
-
- public String getContentType() {
- throw new UnsupportedOperationException();
- }
-
- public ServletInputStream getInputStream() throws IOException {
- throw new UnsupportedOperationException();
- }
-
- public String getLocalAddr() {
- throw new UnsupportedOperationException();
-
- }
-
- public String getLocalName() {
- throw new UnsupportedOperationException();
- }
-
- public int getLocalPort() {
- throw new UnsupportedOperationException();
- }
-
- public Locale getLocale() {
- throw new UnsupportedOperationException();
- }
-
- public Enumeration getLocales() {
- throw new UnsupportedOperationException();
- }
-
- public String getParameter(String name) {
- throw new UnsupportedOperationException();
- }
-
- public Map getParameterMap() {
- throw new UnsupportedOperationException();
- }
-
- public Enumeration getParameterNames() {
- throw new UnsupportedOperationException();
- }
-
- public String[] getParameterValues(String name) {
- throw new UnsupportedOperationException();
- }
-
- public String getProtocol() {
- throw new UnsupportedOperationException();
- }
-
- public BufferedReader getReader() throws IOException {
- throw new UnsupportedOperationException();
- }
-
- public String getRealPath(String path) {
- throw new UnsupportedOperationException();
- }
-
- public String getRemoteAddr() {
- throw new UnsupportedOperationException();
- }
-
- public String getRemoteHost() {
- throw new UnsupportedOperationException();
- }
-
- public int getRemotePort() {
- throw new UnsupportedOperationException();
- }
-
- public RequestDispatcher getRequestDispatcher(String path) {
- throw new UnsupportedOperationException();
- }
-
- public String getScheme() {
- throw new UnsupportedOperationException();
- }
-
- public String getServerName() {
- throw new UnsupportedOperationException();
- }
-
- public int getServerPort() {
- throw new UnsupportedOperationException();
- }
-
- public boolean isSecure() {
- throw new UnsupportedOperationException();
- }
-
- public void removeAttribute(String name) {
- throw new UnsupportedOperationException();
- }
-
- public void setAttribute(String name, Object o) {
- throw new UnsupportedOperationException();
- }
-
- public void setCharacterEncoding(String env) throws UnsupportedEncodingException {
- throw new UnsupportedOperationException();
- }
}
-class DummyResponse implements HttpServletResponse {
- public void addCookie(Cookie cookie) {
- throw new UnsupportedOperationException();
- }
-
- public void addDateHeader(String name, long date) {
- throw new UnsupportedOperationException();
- }
-
- public void addHeader(String name, String value) {
- throw new UnsupportedOperationException();
- }
-
- public void addIntHeader(String name, int value) {
- throw new UnsupportedOperationException();
- }
-
- public boolean containsHeader(String name) {
- throw new UnsupportedOperationException();
- }
-
- public String encodeRedirectURL(String url) {
- throw new UnsupportedOperationException();
- }
-
- public String encodeRedirectUrl(String url) {
- throw new UnsupportedOperationException();
- }
-
- public String encodeURL(String url) {
- throw new UnsupportedOperationException();
- }
-
- public String encodeUrl(String url) {
- throw new UnsupportedOperationException();
- }
-
- public void sendError(int sc) throws IOException {
- throw new UnsupportedOperationException();
-
- }
-
- public void sendError(int sc, String msg) throws IOException {
- throw new UnsupportedOperationException();
- }
-
- public void sendRedirect(String location) throws IOException {
- throw new UnsupportedOperationException();
- }
-
- public void setDateHeader(String name, long date) {
- throw new UnsupportedOperationException();
- }
-
- public void setHeader(String name, String value) {
- throw new UnsupportedOperationException();
- }
-
- public void setIntHeader(String name, int value) {
- throw new UnsupportedOperationException();
- }
-
- public void setStatus(int sc) {
- throw new UnsupportedOperationException();
- }
-
- public void setStatus(int sc, String sm) {
- throw new UnsupportedOperationException();
- }
-
- public void flushBuffer() throws IOException {
- throw new UnsupportedOperationException();
- }
-
- public int getBufferSize() {
- throw new UnsupportedOperationException();
- }
-
- public String getCharacterEncoding() {
- throw new UnsupportedOperationException();
- }
-
- public String getContentType() {
- throw new UnsupportedOperationException();
- }
-
- public Locale getLocale() {
- throw new UnsupportedOperationException();
- }
-
- public ServletOutputStream getOutputStream() throws IOException {
- throw new UnsupportedOperationException();
- }
-
- public PrintWriter getWriter() throws IOException {
- throw new UnsupportedOperationException();
- }
-
- public boolean isCommitted() {
- throw new UnsupportedOperationException();
- }
-
- public void reset() {
- throw new UnsupportedOperationException();
- }
-
- public void resetBuffer() {
- throw new UnsupportedOperationException();
- }
-
- public void setBufferSize(int size) {
- throw new UnsupportedOperationException();
- }
-
- public void setCharacterEncoding(String charset) {
- throw new UnsupportedOperationException();
- }
-
- public void setContentLength(int len) {
- throw new UnsupportedOperationException();
- }
-
- public void setContentType(String type) {
- throw new UnsupportedOperationException();
- }
-
- public void setLocale(Locale loc) {
- throw new UnsupportedOperationException();
- }
-}
diff --git a/dist/spring-security-web/org/springframework/security/web/access/ExceptionTranslationFilter.java b/dist/spring-security-web/org/springframework/security/web/access/ExceptionTranslationFilter.java
index 11f0c1f..436731f 100644
--- a/dist/spring-security-web/org/springframework/security/web/access/ExceptionTranslationFilter.java
+++ b/dist/spring-security-web/org/springframework/security/web/access/ExceptionTranslationFilter.java
@@ -75,17 +75,33 @@ public class ExceptionTranslationFilter extends GenericFilterBean {
private AccessDeniedHandler accessDeniedHandler = new AccessDeniedHandlerImpl();
private AuthenticationEntryPoint authenticationEntryPoint;
private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl();
-// private PortResolver portResolver = new PortResolverImpl();
private ThrowableAnalyzer throwableAnalyzer = new DefaultThrowableAnalyzer();
private RequestCache requestCache = new HttpSessionRequestCache();
+ /**
+ * @deprecated Use constructor injection
+ */
+ @Deprecated
+ public ExceptionTranslationFilter() {
+ }
+
+ public ExceptionTranslationFilter(AuthenticationEntryPoint authenticationEntryPoint) {
+ this(authenticationEntryPoint, new HttpSessionRequestCache());
+ }
+
+ public ExceptionTranslationFilter(AuthenticationEntryPoint authenticationEntryPoint, RequestCache requestCache) {
+ Assert.notNull(authenticationEntryPoint, "authenticationEntryPoint cannot be null");
+ Assert.notNull(requestCache, "requestCache cannot be null");
+ this.authenticationEntryPoint = authenticationEntryPoint;
+ this.requestCache = requestCache;
+ }
+
//~ Methods ========================================================================================================
@Override
public void afterPropertiesSet() {
Assert.notNull(authenticationEntryPoint, "authenticationEntryPoint must be specified");
-// Assert.notNull(portResolver, "portResolver must be specified");
}
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
@@ -96,9 +112,7 @@ public class ExceptionTranslationFilter extends GenericFilterBean {
try {
chain.doFilter(request, response);
- if (logger.isDebugEnabled()) {
- logger.debug("Chain processed normally");
- }
+ logger.debug("Chain processed normally");
}
catch (IOException ex) {
throw ex;
@@ -114,7 +128,7 @@ public class ExceptionTranslationFilter extends GenericFilterBean {
}
if (ase != null) {
- handleException(request, response, chain, ase);
+ handleSpringSecurityException(request, response, chain, ase);
} else {
// Rethrow ServletExceptions and RuntimeExceptions as-is
if (ex instanceof ServletException) {
@@ -124,7 +138,8 @@ public class ExceptionTranslationFilter extends GenericFilterBean {
throw (RuntimeException) ex;
}
- // Wrap other Exceptions. These are not expected to happen
+ // Wrap other Exceptions. This shouldn't actually happen
+ // as we've already covered all the possibilities for doFilter
throw new RuntimeException(ex);
}
}
@@ -138,30 +153,23 @@ public class ExceptionTranslationFilter extends GenericFilterBean {
return authenticationTrustResolver;
}
- private void handleException(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
+ private void handleSpringSecurityException(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
RuntimeException exception) throws IOException, ServletException {
if (exception instanceof AuthenticationException) {
- if (logger.isDebugEnabled()) {
- logger.debug("Authentication exception occurred; redirecting to authentication entry point", exception);
- }
+ logger.debug("Authentication exception occurred; redirecting to authentication entry point", exception);
sendStartAuthentication(request, response, chain, (AuthenticationException) exception);
}
else if (exception instanceof AccessDeniedException) {
if (authenticationTrustResolver.isAnonymous(SecurityContextHolder.getContext().getAuthentication())) {
- if (logger.isDebugEnabled()) {
- logger.debug("Access is denied (user is anonymous); redirecting to authentication entry point",
+ logger.debug("Access is denied (user is anonymous); redirecting to authentication entry point",
exception);
- }
sendStartAuthentication(request, response, chain, new InsufficientAuthenticationException(
"Full authentication is required to access this resource"));
}
else {
- if (logger.isDebugEnabled()) {
- logger.debug("Access is denied (user is not anonymous); delegating to AccessDeniedHandler",
- exception);
- }
+ logger.debug("Access is denied (user is not anonymous); delegating to AccessDeniedHandler", exception);
accessDeniedHandler.handle(request, response, (AccessDeniedException) exception);
}
@@ -183,6 +191,10 @@ public class ExceptionTranslationFilter extends GenericFilterBean {
this.accessDeniedHandler = accessDeniedHandler;
}
+ /**
+ * @deprecated Use constructor
+ */
+ @Deprecated
public void setAuthenticationEntryPoint(AuthenticationEntryPoint authenticationEntryPoint) {
this.authenticationEntryPoint = authenticationEntryPoint;
}
@@ -192,14 +204,6 @@ public class ExceptionTranslationFilter extends GenericFilterBean {
this.authenticationTrustResolver = authenticationTrustResolver;
}
-// public void setCreateSessionAllowed(boolean createSessionAllowed) {
-// this.createSessionAllowed = createSessionAllowed;
-// }
-
-// public void setPortResolver(PortResolver portResolver) {
-// this.portResolver = portResolver;
-// }
-
public void setThrowableAnalyzer(ThrowableAnalyzer throwableAnalyzer) {
Assert.notNull(throwableAnalyzer, "throwableAnalyzer must not be null");
this.throwableAnalyzer = throwableAnalyzer;
@@ -208,7 +212,10 @@ public class ExceptionTranslationFilter extends GenericFilterBean {
/**
* The RequestCache implementation used to store the current request before starting authentication.
* Defaults to an {@link HttpSessionRequestCache}.
+ *
+ * @deprecated Use constructor
*/
+ @Deprecated
public void setRequestCache(RequestCache requestCache) {
Assert.notNull(requestCache, "requestCache cannot be null");
this.requestCache = requestCache;
diff --git a/dist/spring-security-web/org/springframework/security/web/access/channel/AbstractRetryEntryPoint.java b/dist/spring-security-web/org/springframework/security/web/access/channel/AbstractRetryEntryPoint.java
index de34ad4..e38bc2b 100644
--- a/dist/spring-security-web/org/springframework/security/web/access/channel/AbstractRetryEntryPoint.java
+++ b/dist/spring-security-web/org/springframework/security/web/access/channel/AbstractRetryEntryPoint.java
@@ -1,9 +1,6 @@
package org.springframework.security.web.access.channel;
-import org.springframework.security.web.PortMapper;
-import org.springframework.security.web.PortMapperImpl;
-import org.springframework.security.web.PortResolver;
-import org.springframework.security.web.PortResolverImpl;
+import org.springframework.security.web.*;
import org.springframework.util.Assert;
import org.apache.commons.logging.Log;
@@ -30,6 +27,8 @@ public abstract class AbstractRetryEntryPoint implements ChannelEntryPoint {
/** The standard port for the scheme (80 for http, 443 for https) */
private final int standardPort;
+ private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
+
//~ Constructors ===================================================================================================
public AbstractRetryEntryPoint(String scheme, int standardPort) {
@@ -39,11 +38,11 @@ public abstract class AbstractRetryEntryPoint implements ChannelEntryPoint {
//~ Methods ========================================================================================================
- public void commence(HttpServletRequest request, HttpServletResponse res) throws IOException, ServletException {
+ public void commence(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
String queryString = request.getQueryString();
String redirectUrl = request.getRequestURI() + ((queryString == null) ? "" : ("?" + queryString));
- Integer currentPort = new Integer(portResolver.getServerPort(request));
+ Integer currentPort = Integer.valueOf(portResolver.getServerPort(request));
Integer redirectPort = getMappedPort(currentPort);
if (redirectPort != null) {
@@ -56,7 +55,7 @@ public abstract class AbstractRetryEntryPoint implements ChannelEntryPoint {
logger.debug("Redirecting to: " + redirectUrl);
}
- res.sendRedirect(res.encodeRedirectURL(redirectUrl));
+ redirectStrategy.sendRedirect(request, response, redirectUrl);
}
protected abstract Integer getMappedPort(Integer mapFromPort);
@@ -65,10 +64,6 @@ public abstract class AbstractRetryEntryPoint implements ChannelEntryPoint {
return portMapper;
}
- protected final PortResolver getPortResolver() {
- return portResolver;
- }
-
public void setPortMapper(PortMapper portMapper) {
Assert.notNull(portMapper, "portMapper cannot be null");
this.portMapper = portMapper;
@@ -78,4 +73,23 @@ public abstract class AbstractRetryEntryPoint implements ChannelEntryPoint {
Assert.notNull(portResolver, "portResolver cannot be null");
this.portResolver = portResolver;
}
+
+ protected final PortResolver getPortResolver() {
+ return portResolver;
+ }
+
+ /**
+ * Sets the strategy to be used for redirecting to the required channel URL. A {@code DefaultRedirectStrategy}
+ * instance will be used if not set.
+ *
+ * @param redirectStrategy the strategy instance to which the URL will be passed.
+ */
+ public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
+ Assert.notNull(redirectStrategy, "redirectStrategy cannot be null");
+ this.redirectStrategy = redirectStrategy;
+ }
+
+ protected final RedirectStrategy getRedirectStrategy() {
+ return redirectStrategy;
+ }
}
diff --git a/dist/spring-security-web/org/springframework/security/web/access/channel/ChannelDecisionManagerImpl.java b/dist/spring-security-web/org/springframework/security/web/access/channel/ChannelDecisionManagerImpl.java
index 5652587..91705d4 100644
--- a/dist/spring-security-web/org/springframework/security/web/access/channel/ChannelDecisionManagerImpl.java
+++ b/dist/spring-security-web/org/springframework/security/web/access/channel/ChannelDecisionManagerImpl.java
@@ -62,11 +62,7 @@ public class ChannelDecisionManagerImpl implements ChannelDecisionManager, Initi
}
public void decide(FilterInvocation invocation, Collection<ConfigAttribute> config) throws IOException, ServletException {
-
- Iterator<ConfigAttribute> attrs = config.iterator();
-
- while (attrs.hasNext()) {
- ConfigAttribute attribute = attrs.next();
+ for (ConfigAttribute attribute : config) {
if (ANY_CHANNEL.equals(attribute.getAttribute())) {
return;
}
diff --git a/dist/spring-security-web/org/springframework/security/web/access/channel/ChannelProcessingFilter.java b/dist/spring-security-web/org/springframework/security/web/access/channel/ChannelProcessingFilter.java
index 98330c2..983ce37 100644
--- a/dist/spring-security-web/org/springframework/security/web/access/channel/ChannelProcessingFilter.java
+++ b/dist/spring-security-web/org/springframework/security/web/access/channel/ChannelProcessingFilter.java
@@ -36,11 +36,46 @@ import org.springframework.web.filter.GenericFilterBean;
/**
* Ensures a web request is delivered over the required channel.
- * <p>Internally uses a {@link FilterInvocation} to represent the request, so that the
- * <code>FilterInvocation</code>-related property editors and lookup classes can be used.</p>
- * <p>Delegates the actual channel security decisions and necessary actions to the configured
- * {@link ChannelDecisionManager}. If a response is committed by the <code>ChannelDecisionManager</code>,
- * the filter chain will not proceed.</p>
+ * <p>
+ * Internally uses a {@link FilterInvocation} to represent the request, allowing a
+ * {@code FilterInvocationSecurityMetadataSource} to be used to lookup the attributes which apply.
+ * <p>
+ * Delegates the actual channel security decisions and necessary actions to the configured
+ * {@link ChannelDecisionManager}. If a response is committed by the {@code ChannelDecisionManager},
+ * the filter chain will not proceed.
+ * <p>
+ * The most common usage is to ensure that a request takes place over HTTPS, where the
+ * {@link ChannelDecisionManagerImpl} is configured with a {@link SecureChannelProcessor} and an
+ * {@link InsecureChannelProcessor}. A typical configuration would be
+ * <pre>
+ *
+<bean id="channelProcessingFilter" class="org.springframework.security.web.access.channel.ChannelProcessingFilter">
+ <property name="channelDecisionManager" ref="channelDecisionManager"/>
+ <property name="securityMetadataSource">
+ <security:filter-security-metadata-source path-type="regex">
+ <security:intercept-url pattern="\A/secure/.*\Z" access="REQUIRES_SECURE_CHANNEL"/>
+ <security:intercept-url pattern="\A/login.jsp.*\Z" access="REQUIRES_SECURE_CHANNEL"/>
+ <security:intercept-url pattern="\A/.*\Z" access="ANY_CHANNEL"/>
+ </security:filter-security-metadata-source>
+ </property>
+</bean>
+
+<bean id="channelDecisionManager" class="org.springframework.security.web.access.channel.ChannelDecisionManagerImpl">
+ <property name="channelProcessors">
+ <list>
+ <ref bean="secureChannelProcessor"/>
+ <ref bean="insecureChannelProcessor"/>
+ </list>
+ </property>
+</bean>
+
+<bean id="secureChannelProcessor"
+ class="org.springframework.security.web.access.channel.SecureChannelProcessor"/>
+<bean id="insecureChannelProcessor"
+ class="org.springframework.security.web.access.channel.InsecureChannelProcessor"/>
+
+ * </pre>
+ * which would force the login form and any access to the {@code /secure} path to be made over HTTPS.
*
* @author Ben Alex
*/
diff --git a/dist/spring-security-web/org/springframework/security/web/access/channel/InsecureChannelProcessor.java b/dist/spring-security-web/org/springframework/security/web/access/channel/InsecureChannelProcessor.java
index 32da4bf..1128e07 100644
--- a/dist/spring-security-web/org/springframework/security/web/access/channel/InsecureChannelProcessor.java
+++ b/dist/spring-security-web/org/springframework/security/web/access/channel/InsecureChannelProcessor.java
@@ -82,11 +82,7 @@ public class InsecureChannelProcessor implements InitializingBean, ChannelProces
}
public boolean supports(ConfigAttribute attribute) {
- if ((attribute != null) && (attribute.getAttribute() != null)
- && attribute.getAttribute().equals(getInsecureKeyword())) {
- return true;
- } else {
- return false;
- }
+ return (attribute != null) && (attribute.getAttribute() != null)
+ && attribute.getAttribute().equals(getInsecureKeyword());
}
}
diff --git a/dist/spring-security-web/org/springframework/security/web/access/channel/SecureChannelProcessor.java b/dist/spring-security-web/org/springframework/security/web/access/channel/SecureChannelProcessor.java
index fe284b3..62a7b60 100644
--- a/dist/spring-security-web/org/springframework/security/web/access/channel/SecureChannelProcessor.java
+++ b/dist/spring-security-web/org/springframework/security/web/access/channel/SecureChannelProcessor.java
@@ -80,11 +80,7 @@ public class SecureChannelProcessor implements InitializingBean, ChannelProcesso
}
public boolean supports(ConfigAttribute attribute) {
- if ((attribute != null) && (attribute.getAttribute() != null)
- && attribute.getAttribute().equals(getSecureKeyword())) {
- return true;
- } else {
- return false;
- }
+ return (attribute != null) && (attribute.getAttribute() != null)
+ && attribute.getAttribute().equals(getSecureKeyword());
}
}
diff --git a/dist/spring-security-web/org/springframework/security/web/access/expression/DefaultWebSecurityExpressionHandler.java b/dist/spring-security-web/org/springframework/security/web/access/expression/DefaultWebSecurityExpressionHandler.java
index 11236a9..d42599d 100644
--- a/dist/spring-security-web/org/springframework/security/web/access/expression/DefaultWebSecurityExpressionHandler.java
+++ b/dist/spring-security-web/org/springframework/security/web/access/expression/DefaultWebSecurityExpressionHandler.java
@@ -1,44 +1,21 @@
package org.springframework.security.web.access.expression;
-import org.springframework.expression.EvaluationContext;
-import org.springframework.expression.ExpressionParser;
-import org.springframework.expression.spel.standard.SpelExpressionParser;
-import org.springframework.expression.spel.support.StandardEvaluationContext;
+import org.springframework.security.access.expression.AbstractSecurityExpressionHandler;
import org.springframework.security.access.expression.SecurityExpressionRoot;
-import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
-import org.springframework.security.authentication.AuthenticationTrustResolver;
-import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.FilterInvocation;
/**
- * Facade which isolates Spring Security's requirements for evaluating web-security expressions
- * from the implementation of the underlying expression objects.
*
* @author Luke Taylor
* @since 3.0
*/
-public class DefaultWebSecurityExpressionHandler implements WebSecurityExpressionHandler {
+public class DefaultWebSecurityExpressionHandler extends AbstractSecurityExpressionHandler<FilterInvocation> {
- private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
- private ExpressionParser expressionParser = new SpelExpressionParser();
- private RoleHierarchy roleHierarchy;
-
- public ExpressionParser getExpressionParser() {
- return expressionParser;
- }
-
- public EvaluationContext createEvaluationContext(Authentication authentication, FilterInvocation fi) {
- StandardEvaluationContext ctx = new StandardEvaluationContext();
- SecurityExpressionRoot root = new WebSecurityExpressionRoot(authentication, fi);
- root.setTrustResolver(trustResolver);
- root.setRoleHierarchy(roleHierarchy);
- ctx.setRootObject(root);
-
- return ctx;
- }
-
- public void setRoleHierarchy(RoleHierarchy roleHierarchy) {
- this.roleHierarchy = roleHierarchy;
+ @Override
+ protected SecurityExpressionRoot createSecurityExpressionRoot(Authentication authentication, FilterInvocation fi) {
+ WebSecurityExpressionRoot root = new WebSecurityExpressionRoot(authentication, fi);
+ root.setPermissionEvaluator(getPermissionEvaluator());
+ return root;
}
}
diff --git a/dist/spring-security-web/org/springframework/security/web/access/expression/ExpressionBasedFilterInvocationSecurityMetadataSource.java b/dist/spring-security-web/org/springframework/security/web/access/expression/ExpressionBasedFilterInvocationSecurityMetadataSource.java
index 6686c89..d2bbc69 100644
--- a/dist/spring-security-web/org/springframework/security/web/access/expression/ExpressionBasedFilterInvocationSecurityMetadataSource.java
+++ b/dist/spring-security-web/org/springframework/security/web/access/expression/ExpressionBasedFilterInvocationSecurityMetadataSource.java
@@ -10,13 +10,14 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.ParseException;
import org.springframework.security.access.ConfigAttribute;
+import org.springframework.security.access.expression.SecurityExpressionHandler;
+import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource;
-import org.springframework.security.web.access.intercept.RequestKey;
-import org.springframework.security.web.util.UrlMatcher;
+import org.springframework.security.web.util.RequestMatcher;
import org.springframework.util.Assert;
/**
- * Expression-based <tt>FilterInvocationSecurityMetadataSource</tt>.
+ * Expression-based {@code FilterInvocationSecurityMetadataSource}.
*
* @author Luke Taylor
* @since 3.0
@@ -24,21 +25,22 @@ import org.springframework.util.Assert;
public final class ExpressionBasedFilterInvocationSecurityMetadataSource extends DefaultFilterInvocationSecurityMetadataSource {
private final static Log logger = LogFactory.getLog(ExpressionBasedFilterInvocationSecurityMetadataSource.class);
- public ExpressionBasedFilterInvocationSecurityMetadataSource(UrlMatcher urlMatcher,
- LinkedHashMap<RequestKey, Collection<ConfigAttribute>> requestMap, WebSecurityExpressionHandler expressionHandler) {
- super(urlMatcher, processMap(requestMap, expressionHandler.getExpressionParser()));
+ public ExpressionBasedFilterInvocationSecurityMetadataSource(
+ LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap,
+ SecurityExpressionHandler<FilterInvocation> expressionHandler) {
+ super(processMap(requestMap, expressionHandler.getExpressionParser()));
Assert.notNull(expressionHandler, "A non-null SecurityExpressionHandler is required");
}
- private static LinkedHashMap<RequestKey, Collection<ConfigAttribute>> processMap(
- LinkedHashMap<RequestKey,Collection<ConfigAttribute>> requestMap, ExpressionParser parser) {
+ private static LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> processMap(
+ LinkedHashMap<RequestMatcher,Collection<ConfigAttribute>> requestMap, ExpressionParser parser) {
Assert.notNull(parser, "SecurityExpressionHandler returned a null parser object");
- LinkedHashMap<RequestKey, Collection<ConfigAttribute>> requestToExpressionAttributesMap =
- new LinkedHashMap<RequestKey, Collection<ConfigAttribute>>(requestMap);
+ LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestToExpressionAttributesMap =
+ new LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>>(requestMap);
- for (Map.Entry<RequestKey, Collection<ConfigAttribute>> entry : requestMap.entrySet()) {
- RequestKey request = entry.getKey();
+ for (Map.Entry<RequestMatcher, Collection<ConfigAttribute>> entry : requestMap.entrySet()) {
+ RequestMatcher request = entry.getKey();
Assert.isTrue(entry.getValue().size() == 1, "Expected a single expression attribute for " + request);
ArrayList<ConfigAttribute> attributes = new ArrayList<ConfigAttribute>(1);
String expression = entry.getValue().toArray(new ConfigAttribute[1])[0].getAttribute();
diff --git a/dist/spring-security-web/org/springframework/security/web/access/expression/WebExpressionVoter.java b/dist/spring-security-web/org/springframework/security/web/access/expression/WebExpressionVoter.java
index 439c1fc..916a234 100644
--- a/dist/spring-security-web/org/springframework/security/web/access/expression/WebExpressionVoter.java
+++ b/dist/spring-security-web/org/springframework/security/web/access/expression/WebExpressionVoter.java
@@ -6,6 +6,7 @@ import org.springframework.expression.EvaluationContext;
import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.expression.ExpressionUtils;
+import org.springframework.security.access.expression.SecurityExpressionHandler;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.FilterInvocation;
@@ -14,12 +15,12 @@ import org.springframework.security.web.FilterInvocation;
* @author Luke Taylor
* @since 3.0
*/
-public class WebExpressionVoter implements AccessDecisionVoter {
- private WebSecurityExpressionHandler expressionHandler = new DefaultWebSecurityExpressionHandler();
+public class WebExpressionVoter implements AccessDecisionVoter<FilterInvocation> {
+ private SecurityExpressionHandler<FilterInvocation> expressionHandler = new DefaultWebSecurityExpressionHandler();
- public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) {
+ public int vote(Authentication authentication, FilterInvocation fi, Collection<ConfigAttribute> attributes) {
assert authentication != null;
- assert object != null;
+ assert fi != null;
assert attributes != null;
WebExpressionConfigAttribute weca = findConfigAttribute(attributes);
@@ -28,7 +29,6 @@ public class WebExpressionVoter implements AccessDecisionVoter {
return ACCESS_ABSTAIN;
}
- FilterInvocation fi = (FilterInvocation)object;
EvaluationContext ctx = expressionHandler.createEvaluationContext(authentication, fi);
return ExpressionUtils.evaluateAsBoolean(weca.getAuthorizeExpression(), ctx) ?
@@ -52,7 +52,7 @@ public class WebExpressionVoter implements AccessDecisionVoter {
return clazz.isAssignableFrom(FilterInvocation.class);
}
- public void setExpressionHandler(WebSecurityExpressionHandler expressionHandler) {
+ public void setExpressionHandler(SecurityExpressionHandler<FilterInvocation> expressionHandler) {
this.expressionHandler = expressionHandler;
}
}
diff --git a/dist/spring-security-web/org/springframework/security/web/access/expression/WebSecurityExpressionHandler.java b/dist/spring-security-web/org/springframework/security/web/access/expression/WebSecurityExpressionHandler.java
index c06a656..70bb5e8 100644
--- a/dist/spring-security-web/org/springframework/security/web/access/expression/WebSecurityExpressionHandler.java
+++ b/dist/spring-security-web/org/springframework/security/web/access/expression/WebSecurityExpressionHandler.java
@@ -1,19 +1,8 @@
package org.springframework.security.web.access.expression;
-import org.springframework.expression.EvaluationContext;
-import org.springframework.expression.ExpressionParser;
-import org.springframework.security.core.Authentication;
+import org.springframework.security.access.expression.SecurityExpressionHandler;
import org.springframework.security.web.FilterInvocation;
-public interface WebSecurityExpressionHandler {
- /**
- * @return an expression parser for the expressions used by the implementation.
- */
- ExpressionParser getExpressionParser();
-
- /**
- * Provides an evaluation context in which to evaluate security expressions for a web invocation.
- */
- EvaluationContext createEvaluationContext(Authentication authentication, FilterInvocation fi);
-
+ at Deprecated
+public interface WebSecurityExpressionHandler extends SecurityExpressionHandler<FilterInvocation> {
}
diff --git a/dist/spring-security-web/org/springframework/security/web/access/intercept/DefaultFilterInvocationSecurityMetadataSource.java b/dist/spring-security-web/org/springframework/security/web/access/intercept/DefaultFilterInvocationSecurityMetadataSource.java
index f6cf0bf..9854cc2 100644
--- a/dist/spring-security-web/org/springframework/security/web/access/intercept/DefaultFilterInvocationSecurityMetadataSource.java
+++ b/dist/spring-security-web/org/springframework/security/web/access/intercept/DefaultFilterInvocationSecurityMetadataSource.java
@@ -15,192 +15,75 @@
package org.springframework.security.web.access.intercept;
-import java.util.Arrays;
import java.util.Collection;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
+import javax.servlet.http.HttpServletRequest;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.web.FilterInvocation;
-import org.springframework.security.web.util.UrlMatcher;
+import org.springframework.security.web.util.RequestMatcher;
/**
* Default implementation of <tt>FilterInvocationDefinitionSource</tt>.
* <p>
- * Stores an ordered map of compiled URL paths to <tt>ConfigAttribute</tt> lists and provides URL matching
- * against the items stored in this map using the configured <tt>UrlMatcher</tt>.
+ * Stores an ordered map of {@link RequestMatcher}s to <tt>ConfigAttribute</tt> collections and provides matching
+ * of {@code FilterInvocation}s against the items stored in the map.
* <p>
- * The order of the URL paths in the map is very important.
- * The system will identify the <b>first</b> matching path for a given HTTP URL. It will not proceed to evaluate
- * later paths if a match has already been found. Accordingly, the most specific matches should be
- * registered first, with the most general matches registered last.
+ * The order of the {@link RequestMatcher}s in the map is very important. The <b>first</b> one which matches the
+ * request will be used. Later matchers in the map will not be invoked if a match has already been found.
+ * Accordingly, the most specific matchers should be registered first, with the most general matches registered last.
* <p>
- * If URL paths are registered for a particular HTTP method using, then the method-specific matches will take
- * precedence over any URLs which are registered without an HTTP method.
+ * The most common method creating an instance is using the Spring Security namespace. For example, the {@code pattern}
+ * and {@code access} attributes of the {@code <intercept-url>} elements defined as children of the
+ * {@code <http>} element are combined to build the instance used by the {@code FilterSecurityInterceptor}.
*
* @author Ben Alex
* @author Luke Taylor
*/
public class DefaultFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
- private static final Set<String> HTTP_METHODS = new HashSet<String>(Arrays.asList("DELETE", "GET", "HEAD", "OPTIONS", "POST", "PUT", "TRACE"));
-
protected final Log logger = LogFactory.getLog(getClass());
- //private Map<Object, List<ConfigAttribute>> requestMap = new LinkedHashMap<Object, List<ConfigAttribute>>();
- /** Stores request maps keyed by specific HTTP methods. A null key matches any method */
- private Map<String, Map<Object, Collection<ConfigAttribute>>> httpMethodMap =
- new HashMap<String, Map<Object, Collection<ConfigAttribute>>>();
-
- private UrlMatcher urlMatcher;
-
- private boolean stripQueryStringFromUrls;
+ private final Map<RequestMatcher, Collection<ConfigAttribute>> requestMap;
//~ Constructors ===================================================================================================
/**
- * Builds the internal request map from the supplied map. The key elements should be of type {@link RequestKey},
- * which contains a URL path and an optional HTTP method (may be null). The path stored in the key will depend on
+ * Sets the internal request map from the supplied map. The key elements should be of type {@link RequestMatcher},
+ * which. The path stored in the key will depend on
* the type of the supplied UrlMatcher.
*
- * @param urlMatcher typically an ant or regular expression matcher.
* @param requestMap order-preserving map of request definitions to attribute lists
*/
- public DefaultFilterInvocationSecurityMetadataSource(UrlMatcher urlMatcher,
- LinkedHashMap<RequestKey, Collection<ConfigAttribute>> requestMap) {
- this.urlMatcher = urlMatcher;
+ public DefaultFilterInvocationSecurityMetadataSource(
+ LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap) {
- for (Map.Entry<RequestKey, Collection<ConfigAttribute>> entry : requestMap.entrySet()) {
- addSecureUrl(entry.getKey().getUrl(), entry.getKey().getMethod(), entry.getValue());
- }
+ this.requestMap = requestMap;
}
//~ Methods ========================================================================================================
- /**
- * Adds a URL,attribute-list pair to the request map, first allowing the <tt>UrlMatcher</tt> to
- * process the pattern if required, using its <tt>compile</tt> method. The returned object will be used as the key
- * to the request map and will be passed back to the <tt>UrlMatcher</tt> when iterating through the map to find
- * a match for a particular URL.
- */
- private void addSecureUrl(String pattern, String method, Collection<ConfigAttribute> attrs) {
- Map<Object, Collection<ConfigAttribute>> mapToUse = getRequestMapForHttpMethod(method);
-
- mapToUse.put(urlMatcher.compile(pattern), attrs);
-
- if (logger.isDebugEnabled()) {
- logger.debug("Added URL pattern: " + pattern + "; attributes: " + attrs +
- (method == null ? "" : " for HTTP method '" + method + "'"));
- }
- }
-
- /**
- * Return the HTTP method specific request map, creating it if it doesn't already exist.
- * @param method GET, POST etc
- * @return map of URL patterns to <tt>ConfigAttribute</tt>s for this method.
- */
- private Map<Object, Collection<ConfigAttribute>> getRequestMapForHttpMethod(String method) {
- if (method != null && !HTTP_METHODS.contains(method)) {
- throw new IllegalArgumentException("Unrecognised HTTP method: '" + method + "'");
- }
-
- Map<Object, Collection<ConfigAttribute>> methodRequestMap = httpMethodMap.get(method);
-
- if (methodRequestMap == null) {
- methodRequestMap = new LinkedHashMap<Object, Collection<ConfigAttribute>>();
- httpMethodMap.put(method, methodRequestMap);
- }
-
- return methodRequestMap;
- }
-
public Collection<ConfigAttribute> getAllConfigAttributes() {
Set<ConfigAttribute> allAttributes = new HashSet<ConfigAttribute>();
- for (Map.Entry<String, Map<Object, Collection<ConfigAttribute>>> entry : httpMethodMap.entrySet()) {
- for (Collection<ConfigAttribute> attrs : entry.getValue().values()) {
- allAttributes.addAll(attrs);
- }
+ for (Map.Entry<RequestMatcher, Collection<ConfigAttribute>> entry : requestMap.entrySet()) {
+ allAttributes.addAll(entry.getValue());
}
return allAttributes;
}
-
public Collection<ConfigAttribute> getAttributes(Object object) {
- if ((object == null) || !this.supports(object.getClass())) {
- throw new IllegalArgumentException("Object must be a FilterInvocation");
- }
-
- String url = ((FilterInvocation) object).getRequestUrl();
- String method = ((FilterInvocation) object).getHttpRequest().getMethod();
-
- return lookupAttributes(url, method);
- }
-
- /**
- * Performs the actual lookup of the relevant <tt>ConfigAttribute</tt>s for the given <code>FilterInvocation</code>.
- * <p>
- * By default, iterates through the stored URL map and calls the
- * {@link UrlMatcher#pathMatchesUrl(Object path, String url)} method until a match is found.
- *
- * @param url the URI to retrieve configuration attributes for
- * @param method the HTTP method (GET, POST, DELETE...), or null for any method.
- *
- * @return the <code>ConfigAttribute</code>s that apply to the specified <code>FilterInvocation</code>
- * or null if no match is found
- */
- public final Collection<ConfigAttribute> lookupAttributes(String url, String method) {
- if (stripQueryStringFromUrls) {
- // Strip anything after a question mark symbol, as per SEC-161. See also SEC-321
- int firstQuestionMarkIndex = url.indexOf("?");
-
- if (firstQuestionMarkIndex != -1) {
- url = url.substring(0, firstQuestionMarkIndex);
- }
- }
-
- if (urlMatcher.requiresLowerCaseUrl()) {
- url = url.toLowerCase();
-
- if (logger.isDebugEnabled()) {
- logger.debug("Converted URL to lowercase, from: '" + url + "'; to: '" + url + "'");
- }
- }
-
- // Obtain the map of request patterns to attributes for this method and lookup the url.
- Collection<ConfigAttribute> attributes = extractMatchingAttributes(url, httpMethodMap.get(method));
-
- // If no attributes found in method-specific map, use the general one stored under the null key
- if (attributes == null) {
- attributes = extractMatchingAttributes(url, httpMethodMap.get(null));
- }
-
- return attributes;
- }
-
- private Collection<ConfigAttribute> extractMatchingAttributes(String url, Map<Object, Collection<ConfigAttribute>> map) {
- if (map == null) {
- return null;
- }
-
- final boolean debug = logger.isDebugEnabled();
-
- for (Map.Entry<Object, Collection<ConfigAttribute>> entry : map.entrySet()) {
- Object p = entry.getKey();
- boolean matched = urlMatcher.pathMatchesUrl(entry.getKey(), url);
-
- if (debug) {
- logger.debug("Candidate is: '" + url + "'; pattern is " + p + "; matched=" + matched);
- }
-
- if (matched) {
+ final HttpServletRequest request = ((FilterInvocation) object).getRequest();
+ for (Map.Entry<RequestMatcher, Collection<ConfigAttribute>> entry : requestMap.entrySet()) {
+ if (entry.getKey().matches(request)) {
return entry.getValue();
}
}
@@ -210,16 +93,4 @@ public class DefaultFilterInvocationSecurityMetadataSource implements FilterInvo
public boolean supports(Class<?> clazz) {
return FilterInvocation.class.isAssignableFrom(clazz);
}
-
- protected UrlMatcher getUrlMatcher() {
- return urlMatcher;
- }
-
- public boolean isConvertUrlToLowercaseBeforeComparison() {
- return urlMatcher.requiresLowerCaseUrl();
- }
-
- public void setStripQueryStringFromUrls(boolean stripQueryStringFromUrls) {
- this.stripQueryStringFromUrls = stripQueryStringFromUrls;
- }
}
diff --git a/dist/spring-security-web/org/springframework/security/web/access/intercept/FilterSecurityInterceptor.java b/dist/spring-security-web/org/springframework/security/web/access/intercept/FilterSecurityInterceptor.java
index 139549e..55dd0ce 100644
--- a/dist/spring-security-web/org/springframework/security/web/access/intercept/FilterSecurityInterceptor.java
+++ b/dist/spring-security-web/org/springframework/security/web/access/intercept/FilterSecurityInterceptor.java
@@ -87,7 +87,15 @@ public class FilterSecurityInterceptor extends AbstractSecurityInterceptor imple
return this.securityMetadataSource;
}
- public Class<? extends Object> getSecureObjectClass() {
+ public SecurityMetadataSource obtainSecurityMetadataSource() {
+ return this.securityMetadataSource;
+ }
+
+ public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource newSource) {
+ this.securityMetadataSource = newSource;
+ }
+
+ public Class<?> getSecureObjectClass() {
return FilterInvocation.class;
}
@@ -105,11 +113,9 @@ public class FilterSecurityInterceptor extends AbstractSecurityInterceptor imple
InterceptorStatusToken token = super.beforeInvocation(fi);
- try {
- fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
- } finally {
- super.afterInvocation(token, null);
- }
+ fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
+
+ super.afterInvocation(token, null);
}
}
@@ -127,22 +133,6 @@ public class FilterSecurityInterceptor extends AbstractSecurityInterceptor imple
return observeOncePerRequest;
}
- public SecurityMetadataSource obtainSecurityMetadataSource() {
- return this.securityMetadataSource;
- }
-
- /**
- * @deprecated use setSecurityMetadataSource instead
- */
- public void setObjectDefinitionSource(FilterInvocationSecurityMetadataSource newSource) {
- logger.warn("The property 'objectDefinitionSource' is deprecated. Please use 'securityMetadataSource' instead");
- this.securityMetadataSource = newSource;
- }
-
- public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource newSource) {
- this.securityMetadataSource = newSource;
- }
-
public void setObserveOncePerRequest(boolean observeOncePerRequest) {
this.observeOncePerRequest = observeOncePerRequest;
}
diff --git a/dist/spring-security-web/org/springframework/security/web/access/intercept/RequestKey.java b/dist/spring-security-web/org/springframework/security/web/access/intercept/RequestKey.java
index 3c699f4..21b13a7 100644
--- a/dist/spring-security-web/org/springframework/security/web/access/intercept/RequestKey.java
+++ b/dist/spring-security-web/org/springframework/security/web/access/intercept/RequestKey.java
@@ -5,8 +5,8 @@ package org.springframework.security.web.access.intercept;
* @since 2.0
*/
public class RequestKey {
- private String url;
- private String method;
+ private final String url;
+ private final String method;
public RequestKey(String url) {
this(url, null);
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/AbstractAuthenticationProcessingFilter.java b/dist/spring-security-web/org/springframework/security/web/authentication/AbstractAuthenticationProcessingFilter.java
index 8539aef..c79dd5e 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/AbstractAuthenticationProcessingFilter.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/AbstractAuthenticationProcessingFilter.java
@@ -110,15 +110,10 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
//~ Instance fields ================================================================================================
protected ApplicationEventPublisher eventPublisher;
- protected AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource();
+ protected AuthenticationDetailsSource<HttpServletRequest,?> authenticationDetailsSource = new WebAuthenticationDetailsSource();
private AuthenticationManager authenticationManager;
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
-
- /*
- * Delay use of NullRememberMeServices until initialization so that namespace has a chance to inject
- * the RememberMeServices implementation into custom implementations.
- */
- private RememberMeServices rememberMeServices = null;
+ private RememberMeServices rememberMeServices = new NullRememberMeServices();
/**
* The URL destination that this filter intercepts and processes (usually
@@ -215,7 +210,7 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
chain.doFilter(request, response);
}
- successfulAuthentication(request, response, authResult);
+ successfulAuthentication(request, response, chain, authResult);
}
/**
@@ -280,8 +275,35 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
* <li>Delegates additional behaviour to the {@link AuthenticationSuccessHandler}.</li>
* </ol>
*
+ * Subclasses can override this method to continue the {@link FilterChain} after successful authentication.
+ * @param request
+ * @param response
+ * @param chain
* @param authResult the object returned from the <tt>attemptAuthentication</tt> method.
+ * @throws IOException
+ * @throws ServletException
*/
+ protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
+ Authentication authResult) throws IOException, ServletException{
+ successfulAuthentication(request, response, authResult);
+ }
+
+ /**
+ * Default behaviour for successful authentication.
+ * <ol>
+ * <li>Sets the successful <tt>Authentication</tt> object on the {@link SecurityContextHolder}</li>
+ * <li>Invokes the configured {@link SessionAuthenticationStrategy} to handle any session-related behaviour
+ * (such as creating a new session to protect against session-fixation attacks).</li>
+ * <li>Informs the configured <tt>RememberMeServices</tt> of the successful login</li>
+ * <li>Fires an {@link InteractiveAuthenticationSuccessEvent} via the configured
+ * <tt>ApplicationEventPublisher</tt></li>
+ * <li>Delegates additional behaviour to the {@link AuthenticationSuccessHandler}.</li>
+ * </ol>
+ *
+ * @param authResult the object returned from the <tt>attemptAuthentication</tt> method.
+ * @deprecated since 3.1. Use {@link #successfulAuthentication(HttpServletRequest, HttpServletResponse, FilterChain, Authentication)} instead.
+ */
+ @Deprecated
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
Authentication authResult) throws IOException, ServletException {
@@ -346,6 +368,7 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
}
public void setRememberMeServices(RememberMeServices rememberMeServices) {
+ Assert.notNull("rememberMeServices cannot be null");
this.rememberMeServices = rememberMeServices;
}
@@ -363,7 +386,7 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
this.eventPublisher = eventPublisher;
}
- public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) {
+ public void setAuthenticationDetailsSource(AuthenticationDetailsSource<HttpServletRequest,?> authenticationDetailsSource) {
Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required");
this.authenticationDetailsSource = authenticationDetailsSource;
}
@@ -372,11 +395,6 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
this.messages = new MessageSourceAccessor(messageSource);
}
- public AuthenticationDetailsSource getAuthenticationDetailsSource() {
- // Required due to SEC-310
- return authenticationDetailsSource;
- }
-
protected boolean getAllowSessionCreation() {
return allowSessionCreation;
}
@@ -410,4 +428,12 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
Assert.notNull(failureHandler, "failureHandler cannot be null");
this.failureHandler = failureHandler;
}
+
+ protected AuthenticationSuccessHandler getSuccessHandler() {
+ return successHandler;
+ }
+
+ protected AuthenticationFailureHandler getFailureHandler() {
+ return failureHandler;
+ }
}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/AbstractAuthenticationTargetUrlRequestHandler.java b/dist/spring-security-web/org/springframework/security/web/authentication/AbstractAuthenticationTargetUrlRequestHandler.java
index c30f2fb..a5e5c4e 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/AbstractAuthenticationTargetUrlRequestHandler.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/AbstractAuthenticationTargetUrlRequestHandler.java
@@ -19,25 +19,28 @@ import org.springframework.util.StringUtils;
/**
* Base class containing the logic used by strategies which handle redirection to a URL and
- * are passed an <tt>Authentication</tt> object as part of the contract.
+ * are passed an {@code Authentication} object as part of the contract.
* See {@link AuthenticationSuccessHandler} and
* {@link org.springframework.security.web.authentication.logout.LogoutSuccessHandler LogoutSuccessHandler}, for example.
* <p>
* Uses the following logic sequence to determine how it should handle the forward/redirect
* <ul>
* <li>
- * If the <tt>alwaysUseDefaultTargetUrl</tt> property is set to true, the <tt>defaultTargetUrl</tt> property
+ * If the {@code alwaysUseDefaultTargetUrl} property is set to true, the {@code defaultTargetUrl} property
* will be used for the destination.
* </li>
* <li>
- * If a parameter matching the <tt>targetUrlParameter</tt> has been set on the request, the value will be used as
- * the destination.
+ * If a parameter matching the value of {@code targetUrlParameter} has been set on the request, the value will be used
+ * as the destination. If you are enabling this functionality, then you should ensure that the parameter
+ * cannot be used by an attacker to redirect the user to a malicious site (by clicking on a URL with the parameter
+ * included, for example). Typically it would be used when the parameter is included in the login form and submitted with
+ * the username and password.
* </li>
* <li>
- * If the <tt>useReferer</tt> property is set, the "Referer" HTTP header value will be used, if present.
+ * If the {@code useReferer} property is set, the "Referer" HTTP header value will be used, if present.
* </li>
* <li>
- * As a fallback option, the <tt>defaultTargetUrl</tt> value will be used.
+ * As a fallback option, the {@code defaultTargetUrl} value will be used.
* </li>
* </ul>
*
@@ -46,9 +49,8 @@ import org.springframework.util.StringUtils;
*/
public abstract class AbstractAuthenticationTargetUrlRequestHandler {
- public static String DEFAULT_TARGET_PARAMETER = "spring-security-redirect";
protected final Log logger = LogFactory.getLog(this.getClass());
- private String targetUrlParameter = DEFAULT_TARGET_PARAMETER;
+ private String targetUrlParameter = null;
private String defaultTargetUrl = "/";
private boolean alwaysUseDefaultTargetUrl = false;
private boolean useReferer = false;
@@ -83,18 +85,16 @@ public abstract class AbstractAuthenticationTargetUrlRequestHandler {
}
// Check for the parameter and use that if available
- String targetUrl = request.getParameter(targetUrlParameter);
+ String targetUrl = null;
- if (StringUtils.hasText(targetUrl)) {
- try {
- targetUrl = URLDecoder.decode(targetUrl, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- throw new IllegalStateException("UTF-8 not supported. Shouldn't be possible");
- }
+ if (targetUrlParameter != null ) {
+ targetUrl = request.getParameter(targetUrlParameter);
- logger.debug("Found targetUrlParameter in request: " + targetUrl);
+ if (StringUtils.hasText(targetUrl)) {
+ logger.debug("Found targetUrlParameter in request: " + targetUrl);
- return targetUrl;
+ return targetUrl;
+ }
}
if (useReferer && !StringUtils.hasLength(targetUrl)) {
@@ -112,7 +112,7 @@ public abstract class AbstractAuthenticationTargetUrlRequestHandler {
/**
* Supplies the default target Url that will be used if no saved request is found or the
- * <tt>alwaysUseDefaultTargetUrl</tt> property is set to true. If not set, defaults to <tt>/</tt>.
+ * {@code alwaysUseDefaultTargetUrl} property is set to true. If not set, defaults to {@code /}.
*
* @return the defaultTargetUrl property
*/
@@ -122,7 +122,7 @@ public abstract class AbstractAuthenticationTargetUrlRequestHandler {
/**
* Supplies the default target Url that will be used if no saved request is found in the session, or the
- * <tt>alwaysUseDefaultTargetUrl</tt> property is set to true. If not set, defaults to <tt>/</tt>. It
+ * {@code alwaysUseDefaultTargetUrl} property is set to true. If not set, defaults to {@code /}. It
* will be treated as relative to the web-app's context path, and should include the leading <code>/</code>.
* Alternatively, inclusion of a scheme name (such as "http://" or "https://") as the prefix will denote a
* fully-qualified URL and this is also supported.
@@ -136,7 +136,7 @@ public abstract class AbstractAuthenticationTargetUrlRequestHandler {
}
/**
- * If <code>true</code>, will always redirect to the value of <tt>defaultTargetUrl</tt>
+ * If <code>true</code>, will always redirect to the value of {@code defaultTargetUrl}
* (defaults to <code>false</code>).
*/
public void setAlwaysUseDefaultTargetUrl(boolean alwaysUseDefaultTargetUrl) {
@@ -148,13 +148,16 @@ public abstract class AbstractAuthenticationTargetUrlRequestHandler {
}
/**
- * The current request will be checked for this parameter before and the value used as the target URL if present.
+ * If this property is set, the current request will be checked for this a parameter with this name
+ * and the value used as the target URL if present.
*
- * @param targetUrlParameter the name of the parameter containing the encoded target URL. Defaults
- * to "spring-security-redirect".
+ * @param targetUrlParameter the name of the parameter containing the encoded target URL. Defaults
+ * to null.
*/
public void setTargetUrlParameter(String targetUrlParameter) {
- Assert.hasText("targetUrlParameter canot be null or empty");
+ if(targetUrlParameter != null) {
+ Assert.hasText(targetUrlParameter,"targetUrlParameter cannot be empty");
+ }
this.targetUrlParameter = targetUrlParameter;
}
@@ -174,9 +177,10 @@ public abstract class AbstractAuthenticationTargetUrlRequestHandler {
}
/**
- * If set to <tt>true</tt> the <tt>Referer</tt> header will be used (if available). Defaults to <tt>false</tt>.
+ * If set to {@code true} the {@code Referer} header will be used (if available). Defaults to {@code false}.
*/
public void setUseReferer(boolean useReferer) {
this.useReferer = useReferer;
}
+
}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/AbstractProcessingFilter.java b/dist/spring-security-web/org/springframework/security/web/authentication/AbstractProcessingFilter.java
deleted file mode 100644
index b75cb7a..0000000
--- a/dist/spring-security-web/org/springframework/security/web/authentication/AbstractProcessingFilter.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.springframework.security.web.authentication;
-
-/**
- * Renamed class, retained for backwards compatibility.
- * <p>
- * See {@link AbstractAuthenticationProcessingFilter}.
- *
- * @author Luke Taylor
- * @deprecated Use AbstractAuthenticationProcessingFilter instead.
- */
- at Deprecated
-public abstract class AbstractProcessingFilter extends AbstractAuthenticationProcessingFilter {
-
- protected AbstractProcessingFilter(String defaultFilterProcessesUrl) {
- super(defaultFilterProcessesUrl);
- }
-}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/AnonymousAuthenticationFilter.java b/dist/spring-security-web/org/springframework/security/web/authentication/AnonymousAuthenticationFilter.java
index d5cfd1d..24dc9eb 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/AnonymousAuthenticationFilter.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/AnonymousAuthenticationFilter.java
@@ -17,6 +17,7 @@ package org.springframework.security.web.authentication;
import java.io.IOException;
+import java.util.*;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
@@ -28,6 +29,8 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.memory.UserAttribute;
import org.springframework.util.Assert;
@@ -39,21 +42,53 @@ import org.springframework.web.filter.GenericFilterBean;
* populates it with one if needed.
*
* @author Ben Alex
+ * @author Luke Taylor
*/
public class AnonymousAuthenticationFilter extends GenericFilterBean implements InitializingBean {
//~ Instance fields ================================================================================================
- private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource();
+ private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource
+ = new WebAuthenticationDetailsSource();
private String key;
- private UserAttribute userAttribute;
+ private Object principal;
+ private List<GrantedAuthority> authorities;
+
+ /**
+ * @deprecated Use constructor injection version
+ */
+ @Deprecated
+ public AnonymousAuthenticationFilter() {
+ }
+
+ /**
+ * Creates a filter with a principal named "anonymousUser" and the single authority "ROLE_ANONYMOUS".
+ *
+ * @param key the key to identify tokens created by this filter
+ */
+ public AnonymousAuthenticationFilter(String key) {
+ this(key, "anonymousUser", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"));
+ }
+
+ /**
+ *
+ * @param key key the key to identify tokens created by this filter
+ * @param principal the principal which will be used to represent anonymous users
+ * @param authorities the authority list for anonymous users
+ */
+ public AnonymousAuthenticationFilter(String key, Object principal, List<GrantedAuthority> authorities) {
+ this.key = key;
+ this.principal = principal;
+ this.authorities = authorities;
+ }
//~ Methods ========================================================================================================
@Override
public void afterPropertiesSet() {
- Assert.notNull(userAttribute);
Assert.hasLength(key);
+ Assert.notNull(principal, "Anonymous authentication principal must be set");
+ Assert.notNull(authorities, "Anonymous authorities must be set");
}
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
@@ -88,37 +123,49 @@ public class AnonymousAuthenticationFilter extends GenericFilterBean implements
* @return <code>true</code> if the anonymous token should be setup for this request (provided that the request
* doesn't already have some other <code>Authentication</code> inside it), or <code>false</code> if no
* anonymous token should be setup for this request
+ * @deprecated no obvious use case and can easily be achieved by other means
*/
+ @Deprecated
protected boolean applyAnonymousForThisRequest(HttpServletRequest request) {
return true;
}
protected Authentication createAuthentication(HttpServletRequest request) {
- AnonymousAuthenticationToken auth = new AnonymousAuthenticationToken(key, userAttribute.getPassword(),
- userAttribute.getAuthorities());
+ AnonymousAuthenticationToken auth = new AnonymousAuthenticationToken(key, principal, authorities);
auth.setDetails(authenticationDetailsSource.buildDetails(request));
return auth;
}
- public String getKey() {
- return key;
+ public void setAuthenticationDetailsSource(AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource) {
+ Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required");
+ this.authenticationDetailsSource = authenticationDetailsSource;
}
- public UserAttribute getUserAttribute() {
- return userAttribute;
+ public Object getPrincipal() {
+ return principal;
}
- public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) {
- Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required");
- this.authenticationDetailsSource = authenticationDetailsSource;
+ public List<GrantedAuthority> getAuthorities() {
+ return authorities;
}
+ /**
+ *
+ * @deprecated use constructor injection instead
+ */
+ @Deprecated
public void setKey(String key) {
this.key = key;
}
+ /**
+ *
+ * @deprecated use constructor injection instead
+ */
+ @Deprecated
public void setUserAttribute(UserAttribute userAttributeDefinition) {
- this.userAttribute = userAttributeDefinition;
+ this.principal = userAttributeDefinition.getPassword();
+ this.authorities = userAttributeDefinition.getAuthorities();
}
}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/AuthenticationProcessingFilter.java b/dist/spring-security-web/org/springframework/security/web/authentication/AuthenticationProcessingFilter.java
deleted file mode 100644
index 06dcd8b..0000000
--- a/dist/spring-security-web/org/springframework/security/web/authentication/AuthenticationProcessingFilter.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.springframework.security.web.authentication;
-
-/**
- * Renamed class, retained for backwards compatibility.
- * <p>
- * See {@link UsernamePasswordAuthenticationFilter}.
- *
- * @author Luke Taylor
- * @deprecated Use UsernamePasswordAuthenticationFilter instead.
- */
-
-public class AuthenticationProcessingFilter extends UsernamePasswordAuthenticationFilter {
-
-}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/AuthenticationProcessingFilterEntryPoint.java b/dist/spring-security-web/org/springframework/security/web/authentication/AuthenticationProcessingFilterEntryPoint.java
deleted file mode 100644
index 02bc133..0000000
--- a/dist/spring-security-web/org/springframework/security/web/authentication/AuthenticationProcessingFilterEntryPoint.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.springframework.security.web.authentication;
-
-/**
- * Renamed class, retained for backwards compatibility.
- * <p>
- * See {@link LoginUrlAuthenticationEntryPoint}.
- *
- * @author Luke Taylor
- * @deprecated Use LoginUrlAuthenticationEntryPoint instead.
- */
-public class AuthenticationProcessingFilterEntryPoint extends LoginUrlAuthenticationEntryPoint{
-
-}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/DelegatingAuthenticationEntryPoint.java b/dist/spring-security-web/org/springframework/security/web/authentication/DelegatingAuthenticationEntryPoint.java
index d8ab2e1..933714e 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/DelegatingAuthenticationEntryPoint.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/DelegatingAuthenticationEntryPoint.java
@@ -31,8 +31,8 @@ import org.springframework.security.web.util.RequestMatcherEditor;
import org.springframework.util.Assert;
/**
- * An AuthenticationEntryPoint which selects a concrete EntryPoint based on a
- * RequestMatcher evaluation.
+ * An {@code AuthenticationEntryPoint} which selects a concrete {@code AuthenticationEntryPoint} based on a
+ * {@link RequestMatcher} evaluation.
*
* <p>A configuration might look like this:</p>
*
@@ -48,37 +48,27 @@ import org.springframework.util.Assert;
* </bean>
* </pre>
*
- * This example uses the {@link RequestMatcherEditor} which creates {@link ELRequestMatcher} instances for the map keys.
+ * This example uses the {@link RequestMatcherEditor} which creates a {@link ELRequestMatcher} instances for the map
+ * keys.
*
* @author Mike Wiesner
* @since 3.0.2
*/
-public class DelegatingAuthenticationEntryPoint implements
- AuthenticationEntryPoint, InitializingBean {
+public class DelegatingAuthenticationEntryPoint implements AuthenticationEntryPoint, InitializingBean {
- private LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints;
+ private final LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints;
private AuthenticationEntryPoint defaultEntryPoint;
- public DelegatingAuthenticationEntryPoint(
- LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints) {
+ public DelegatingAuthenticationEntryPoint(LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints) {
this.entryPoints = entryPoints;
}
- /**
- * EntryPoint which is used when no RequestMatcher returned true
- */
- public void setDefaultEntryPoint(AuthenticationEntryPoint defaultEntryPoint) {
- this.defaultEntryPoint = defaultEntryPoint;
- }
-
-
public void commence(HttpServletRequest request,
HttpServletResponse response, AuthenticationException authException)
throws IOException, ServletException {
for (RequestMatcher requestMatcher : entryPoints.keySet()) {
- if (requestMatcher.matches(request))
- {
+ if (requestMatcher.matches(request)) {
entryPoints.get(requestMatcher).commence(request, response, authException);
return;
}
@@ -88,10 +78,16 @@ public class DelegatingAuthenticationEntryPoint implements
defaultEntryPoint.commence(request, response, authException);
}
+ /**
+ * EntryPoint which is used when no RequestMatcher returned true
+ */
+ public void setDefaultEntryPoint(AuthenticationEntryPoint defaultEntryPoint) {
+ this.defaultEntryPoint = defaultEntryPoint;
+ }
+
public void afterPropertiesSet() throws Exception {
Assert.notEmpty(entryPoints, "entryPoints must be specified");
Assert.notNull(defaultEntryPoint, "defaultEntryPoint must be specified");
}
-
-
}
+
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/ExceptionMappingAuthenticationFailureHandler.java b/dist/spring-security-web/org/springframework/security/web/authentication/ExceptionMappingAuthenticationFailureHandler.java
index 7d3ece9..778ca0e 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/ExceptionMappingAuthenticationFailureHandler.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/ExceptionMappingAuthenticationFailureHandler.java
@@ -25,7 +25,7 @@ import org.springframework.util.Assert;
* @since 3.0
*/
public class ExceptionMappingAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
- private Map<String, String> failureUrlMap = new HashMap<String, String>();
+ private final Map<String, String> failureUrlMap = new HashMap<String, String>();
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/LoginUrlAuthenticationEntryPoint.java b/dist/spring-security-web/org/springframework/security/web/authentication/LoginUrlAuthenticationEntryPoint.java
index f8c4b03..36687ab 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/LoginUrlAuthenticationEntryPoint.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/LoginUrlAuthenticationEntryPoint.java
@@ -15,8 +15,6 @@
package org.springframework.security.web.authentication;
-
-
import java.io.IOException;
import javax.servlet.RequestDispatcher;
@@ -43,17 +41,20 @@ import org.springframework.util.StringUtils;
/**
* Used by the {@link ExceptionTranslationFilter} to commence a form login
- * authentication via the {@link UsernamePasswordAuthenticationFilter}. This object
- * holds the location of the login form, relative to the web app context path,
- * and is used to commence a redirect to that form.
+ * authentication via the {@link UsernamePasswordAuthenticationFilter}.
+ * <p>
+ * Holds the location of the login form in the {@code loginFormUrl} property, and
+ * uses that to build a redirect URL to the login page. Alternatively, an absolute URL
+ * can be set in this property and that will be used exclusively.
* <p>
- * By setting the <em>forceHttps</em> property to true, you may configure the
- * class to force the protocol used for the login form to be <code>HTTPS</code>,
+ * When using a relative URL, you can set the {@code forceHttps} property to true,
+ * to force the protocol used for the login form to be {@code HTTPS},
* even if the original intercepted request for a resource used the
- * <code>HTTP</code> protocol. When this happens, after a successful login
+ * {@code HTTP} protocol. When this happens, after a successful login
* (via HTTPS), the original resource will still be accessed as HTTP, via the
* original request URL. For the forced HTTPS feature to work, the {@link
- * PortMapper} is consulted to determine the HTTP:HTTPS pairs.
+ * PortMapper} is consulted to determine the HTTP:HTTPS pairs. The value of
+ * {@code forceHttps} will have no effect if an absolute URL is used.
*
* @author Ben Alex
* @author colin sampaleanu
@@ -78,13 +79,32 @@ public class LoginUrlAuthenticationEntryPoint implements AuthenticationEntryPoin
private boolean useForward = false;
- private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
+ private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
+
+ /**
+ * @deprecated Use constructor injection
+ */
+ @Deprecated
+ public LoginUrlAuthenticationEntryPoint() {
+ }
+
+ /**
+ *
+ * @param loginFormUrl URL where the login page can be found. Should either be relative to the web-app context path
+ * (include a leading {@code /}) or an absolute URL.
+ */
+ public LoginUrlAuthenticationEntryPoint(String loginFormUrl) {
+ this.loginFormUrl = loginFormUrl;
+ }
//~ Methods ========================================================================================================
public void afterPropertiesSet() throws Exception {
Assert.isTrue(StringUtils.hasText(loginFormUrl) && UrlUtils.isValidRedirectUrl(loginFormUrl),
"loginFormUrl must be specified and must be a valid redirect URL");
+ if (useForward && UrlUtils.isAbsoluteUrl(loginFormUrl)) {
+ throw new IllegalArgumentException("useForward must be false if using an absolute loginFormURL");
+ }
Assert.notNull(portMapper, "portMapper must be specified");
Assert.notNull(portResolver, "portResolver must be specified");
}
@@ -109,9 +129,6 @@ public class LoginUrlAuthenticationEntryPoint implements AuthenticationEntryPoin
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)
throws IOException, ServletException {
- HttpServletRequest httpRequest = (HttpServletRequest) request;
- HttpServletResponse httpResponse = (HttpServletResponse) response;
-
String redirectUrl = null;
if (useForward) {
@@ -119,17 +136,17 @@ public class LoginUrlAuthenticationEntryPoint implements AuthenticationEntryPoin
if (forceHttps && "http".equals(request.getScheme())) {
// First redirect the current request to HTTPS.
// When that request is received, the forward to the login page will be used.
- redirectUrl = buildHttpsRedirectUrlForRequest(httpRequest);
+ redirectUrl = buildHttpsRedirectUrlForRequest(request);
}
if (redirectUrl == null) {
- String loginForm = determineUrlToUseForThisRequest(httpRequest, httpResponse, authException);
+ String loginForm = determineUrlToUseForThisRequest(request, response, authException);
if (logger.isDebugEnabled()) {
logger.debug("Server side forward to: " + loginForm);
}
- RequestDispatcher dispatcher = httpRequest.getRequestDispatcher(loginForm);
+ RequestDispatcher dispatcher = request.getRequestDispatcher(loginForm);
dispatcher.forward(request, response);
@@ -138,17 +155,22 @@ public class LoginUrlAuthenticationEntryPoint implements AuthenticationEntryPoin
} else {
// redirect to login page. Use https if forceHttps true
- redirectUrl = buildRedirectUrlToLoginPage(httpRequest, httpResponse, authException);
+ redirectUrl = buildRedirectUrlToLoginPage(request, response, authException);
}
- redirectStrategy.sendRedirect(httpRequest, httpResponse, redirectUrl);
+ redirectStrategy.sendRedirect(request, response, redirectUrl);
}
protected String buildRedirectUrlToLoginPage(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) {
String loginForm = determineUrlToUseForThisRequest(request, response, authException);
+
+ if (UrlUtils.isAbsoluteUrl(loginForm)) {
+ return loginForm;
+ }
+
int serverPort = portResolver.getServerPort(request);
String scheme = request.getScheme();
@@ -161,7 +183,7 @@ public class LoginUrlAuthenticationEntryPoint implements AuthenticationEntryPoin
urlBuilder.setPathInfo(loginForm);
if (forceHttps && "http".equals(scheme)) {
- Integer httpsPort = portMapper.lookupHttpsPort(new Integer(serverPort));
+ Integer httpsPort = portMapper.lookupHttpsPort(Integer.valueOf(serverPort));
if (httpsPort != null) {
// Overwrite scheme and port in the redirect URL
@@ -183,7 +205,7 @@ public class LoginUrlAuthenticationEntryPoint implements AuthenticationEntryPoin
throws IOException, ServletException {
int serverPort = portResolver.getServerPort(request);
- Integer httpsPort = portMapper.lookupHttpsPort(new Integer(serverPort));
+ Integer httpsPort = portMapper.lookupHttpsPort(Integer.valueOf(serverPort));
if (httpsPort != null) {
RedirectUrlBuilder urlBuilder = new RedirectUrlBuilder();
@@ -220,9 +242,12 @@ public class LoginUrlAuthenticationEntryPoint implements AuthenticationEntryPoin
/**
* The URL where the <code>UsernamePasswordAuthenticationFilter</code> login
- * page can be found. Should be relative to the web-app context path, and
- * include a leading <code>/</code>
+ * page can be found. Should either be relative to the web-app context path
+ * (include a leading {@code /}) or an absolute URL.
+ *
+ * @deprecated use constructor injection
*/
+ @Deprecated
public void setLoginFormUrl(String loginFormUrl) {
this.loginFormUrl = loginFormUrl;
}
@@ -248,10 +273,11 @@ public class LoginUrlAuthenticationEntryPoint implements AuthenticationEntryPoin
}
/**
- * Tells if we are to do a forward to the <code>loginFormUrl</code> using the <tt>RequestDispatcher</tt>,
+ * Tells if we are to do a forward to the {@code loginFormUrl} using the {@code RequestDispatcher},
* instead of a 302 redirect.
*
- * @param useForward
+ * @param useForward true if a forward to the login page should be used. Must be false (the default) if
+ * {@code loginFormUrl} is set to an absolute value.
*/
public void setUseForward(boolean useForward) {
this.useForward = useForward;
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/SavedRequestAwareAuthenticationSuccessHandler.java b/dist/spring-security-web/org/springframework/security/web/authentication/SavedRequestAwareAuthenticationSuccessHandler.java
index a68f6f1..14af536 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/SavedRequestAwareAuthenticationSuccessHandler.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/SavedRequestAwareAuthenticationSuccessHandler.java
@@ -26,23 +26,23 @@ import org.springframework.util.StringUtils;
* Following a successful authentication, it decides on the redirect destination, based on the following scenarios:
* <ul>
* <li>
- * If the <tt>alwaysUseDefaultTargetUrl</tt> property is set to true, the <tt>defaultTargetUrl</tt>
- * will be used for the destination. Any <tt>DefaultSavedRequest</tt> stored in the session will be
+ * If the {@code alwaysUseDefaultTargetUrl} property is set to true, the {@code defaultTargetUrl}
+ * will be used for the destination. Any {@code DefaultSavedRequest} stored in the session will be
* removed.
* </li>
* <li>
- * If the <tt>targetUrlParameter</tt> has been set on the request, the value will be used as the destination.
- * Any <tt>DefaultSavedRequest</tt> will again be removed.
+ * If the {@code targetUrlParameter} has been set on the request, the value will be used as the destination.
+ * Any {@code DefaultSavedRequest} will again be removed.
* </li>
* <li>
- * If a {@link DefaultSavedRequest} is found in the <tt>RequestCache</tt> (as set by the {@link ExceptionTranslationFilter} to
+ * If a {@link SavedRequest} is found in the {@code RequestCache} (as set by the {@link ExceptionTranslationFilter} to
* record the original destination before the authentication process commenced), a redirect will be performed to the
- * Url of that original destination. The <tt>DefaultSavedRequest</tt> object will remain cached and be picked up
+ * Url of that original destination. The {@code SavedRequest} object will remain cached and be picked up
* when the redirected request is received
* (See {@link org.springframework.security.web.savedrequest.SavedRequestAwareWrapper SavedRequestAwareWrapper}).
* </li>
* <li>
- * If no <tt>DefaultSavedRequest</tt> is found, it will delegate to the base class.
+ * If no {@code SavedRequest} is found, it will delegate to the base class.
* </li>
* </ul>
*
@@ -64,8 +64,8 @@ public class SavedRequestAwareAuthenticationSuccessHandler extends SimpleUrlAuth
return;
}
-
- if (isAlwaysUseDefaultTargetUrl() || StringUtils.hasText(request.getParameter(getTargetUrlParameter()))) {
+ String targetUrlParameter = getTargetUrlParameter();
+ if (isAlwaysUseDefaultTargetUrl() || (targetUrlParameter != null && StringUtils.hasText(request.getParameter(targetUrlParameter)))) {
requestCache.removeRequest(request, response);
super.onAuthenticationSuccess(request, response, authentication);
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/SimpleUrlAuthenticationFailureHandler.java b/dist/spring-security-web/org/springframework/security/web/authentication/SimpleUrlAuthenticationFailureHandler.java
index 4ad1a2b..e6c7a6b 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/SimpleUrlAuthenticationFailureHandler.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/SimpleUrlAuthenticationFailureHandler.java
@@ -22,7 +22,7 @@ import org.springframework.util.Assert;
* If the property has not been set it will send a 401 response to the client, with the error message from the
* <tt>AuthenticationException</tt> which caused the failure.
* <p>
- * If the <tt>forwardToDestination</tt> parameter is set, a <tt>RequestDispatcher.forward</tt> call will be made to
+ * If the {@code useForward} property is set, a {@code RequestDispatcher.forward} call will be made to
* the destination instead of a redirect.
*
* @author Luke Taylor
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/SimpleUrlAuthenticationSuccessHandler.java b/dist/spring-security-web/org/springframework/security/web/authentication/SimpleUrlAuthenticationSuccessHandler.java
index 7770b8d..7de2430 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/SimpleUrlAuthenticationSuccessHandler.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/SimpleUrlAuthenticationSuccessHandler.java
@@ -55,6 +55,5 @@ public class SimpleUrlAuthenticationSuccessHandler extends AbstractAuthenticatio
}
session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
- session.removeAttribute(WebAttributes.LAST_USERNAME);
}
}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/UsernamePasswordAuthenticationFilter.java b/dist/spring-security-web/org/springframework/security/web/authentication/UsernamePasswordAuthenticationFilter.java
index 6a78758..84542ec 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/UsernamePasswordAuthenticationFilter.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/UsernamePasswordAuthenticationFilter.java
@@ -50,6 +50,10 @@ public class UsernamePasswordAuthenticationFilter extends AbstractAuthentication
public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "j_username";
public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "j_password";
+ /**
+ * @deprecated If you want to retain the username, cache it in a customized {@code AuthenticationFailureHandler}
+ */
+ @Deprecated
public static final String SPRING_SECURITY_LAST_USERNAME_KEY = "SPRING_SECURITY_LAST_USERNAME";
private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
@@ -84,13 +88,6 @@ public class UsernamePasswordAuthenticationFilter extends AbstractAuthentication
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
- // Place the last username attempted into HttpSession for views
- HttpSession session = request.getSession(false);
-
- if (session != null || getAllowSessionCreation()) {
- request.getSession().setAttribute(SPRING_SECURITY_LAST_USERNAME_KEY, TextEscapeUtils.escapeEntities(username));
- }
-
// Allow subclasses to set the "details" property
setDetails(request, authRequest);
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/WebAuthenticationDetails.java b/dist/spring-security-web/org/springframework/security/web/authentication/WebAuthenticationDetails.java
index 7572e65..7c39533 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/WebAuthenticationDetails.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/WebAuthenticationDetails.java
@@ -15,10 +15,9 @@
package org.springframework.security.web.authentication;
-import org.springframework.security.core.session.SessionIdentifierAware;
+import org.springframework.security.core.SpringSecurityCoreVersion;
import java.io.Serializable;
-
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
@@ -27,12 +26,16 @@ import javax.servlet.http.HttpSession;
* A holder of selected HTTP details related to a web authentication request.
*
* @author Ben Alex
+ * @author Luke Taylor
*/
-public class WebAuthenticationDetails implements SessionIdentifierAware, Serializable {
+public class WebAuthenticationDetails implements Serializable {
+
+ private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
+
//~ Instance fields ================================================================================================
- private String remoteAddress;
- private String sessionId;
+ private final String remoteAddress;
+ private final String sessionId;
//~ Constructors ===================================================================================================
@@ -47,19 +50,10 @@ public class WebAuthenticationDetails implements SessionIdentifierAware, Seriali
HttpSession session = request.getSession(false);
this.sessionId = (session != null) ? session.getId() : null;
-
- doPopulateAdditionalInformation(request);
}
//~ Methods ========================================================================================================
- /**
- * Provided so that subclasses can populate additional information.
- *
- * @param request that the authentication request was received from
- */
- protected void doPopulateAdditionalInformation(HttpServletRequest request) {}
-
public boolean equals(Object obj) {
if (obj instanceof WebAuthenticationDetails) {
WebAuthenticationDetails rhs = (WebAuthenticationDetails) obj;
@@ -132,9 +126,9 @@ public class WebAuthenticationDetails implements SessionIdentifierAware, Seriali
public String toString() {
StringBuilder sb = new StringBuilder();
- sb.append(super.toString() + ": ");
- sb.append("RemoteIpAddress: " + this.getRemoteAddress() + "; ");
- sb.append("SessionId: " + this.getSessionId());
+ sb.append(super.toString()).append(": ");
+ sb.append("RemoteIpAddress: ").append(this.getRemoteAddress()).append("; ");
+ sb.append("SessionId: ").append(this.getSessionId());
return sb.toString();
}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/WebAuthenticationDetailsSource.java b/dist/spring-security-web/org/springframework/security/web/authentication/WebAuthenticationDetailsSource.java
index a538a51..7c3b1ad 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/WebAuthenticationDetailsSource.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/WebAuthenticationDetailsSource.java
@@ -27,44 +27,19 @@ import javax.servlet.http.HttpServletRequest;
/**
* Implementation of {@link AuthenticationDetailsSource} which builds the details object from
- * an <tt>HttpServletRequest</tt> object.
- * <p>
- * By default will create an instance of <code>WebAuthenticationDetails</code>. Any object that accepts a
- * <code>HttpServletRequest</code> as its sole constructor can be used instead of this default.
+ * an <tt>HttpServletRequest</tt> object, creating a {@code WebAuthenticationDetails}.
*
* @author Ben Alex
*/
-public class WebAuthenticationDetailsSource implements AuthenticationDetailsSource {
- //~ Instance fields ================================================================================================
-
- private Class<?> clazz = WebAuthenticationDetails.class;
+public class WebAuthenticationDetailsSource implements AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> {
//~ Methods ========================================================================================================
/**
- * @param context the <tt>HttpServletRequest</tt> object.
+ * @param context the {@code HttpServletRequest} object.
+ * @return the {@code WebAuthenticationDetails} containing information about the current request
*/
- public Object buildDetails(Object context) {
- Assert.isInstanceOf(HttpServletRequest.class, context);
- try {
- Constructor<?> constructor = clazz.getConstructor(HttpServletRequest.class);
-
- return constructor.newInstance(context);
- } catch (NoSuchMethodException ex) {
- ReflectionUtils.handleReflectionException(ex);
- } catch (InvocationTargetException ex) {
- ReflectionUtils.handleReflectionException(ex);
- } catch (InstantiationException ex) {
- ReflectionUtils.handleReflectionException(ex);
- } catch (IllegalAccessException ex) {
- ReflectionUtils.handleReflectionException(ex);
- }
-
- return null;
- }
-
- public void setClazz(Class<?> clazz) {
- Assert.notNull(clazz, "Class required");
- this.clazz = clazz;
+ public WebAuthenticationDetails buildDetails(HttpServletRequest context) {
+ return new WebAuthenticationDetails(context);
}
}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/logout/LogoutFilter.java b/dist/spring-security-web/org/springframework/security/web/authentication/logout/LogoutFilter.java
index 1ca9093..2854c46 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/logout/LogoutFilter.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/logout/LogoutFilter.java
@@ -50,8 +50,8 @@ public class LogoutFilter extends GenericFilterBean {
//~ Instance fields ================================================================================================
private String filterProcessesUrl = "/j_spring_security_logout";
- private List<LogoutHandler> handlers;
- private LogoutSuccessHandler logoutSuccessHandler;
+ private final List<LogoutHandler> handlers;
+ private final LogoutSuccessHandler logoutSuccessHandler;
//~ Constructors ===================================================================================================
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/logout/SecurityContextLogoutHandler.java b/dist/spring-security-web/org/springframework/security/web/authentication/logout/SecurityContextLogoutHandler.java
index 512a65f..a211024 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/logout/SecurityContextLogoutHandler.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/logout/SecurityContextLogoutHandler.java
@@ -16,6 +16,8 @@
package org.springframework.security.web.authentication.logout;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.Assert;
@@ -27,12 +29,14 @@ import javax.servlet.http.HttpSession;
/**
* Performs a logout by modifying the {@link org.springframework.security.core.context.SecurityContextHolder}.
* <p>
- * Will also invalidate the {@link HttpSession} if {@link #isInvalidateHttpSession()} is <code>true</code> and the
- * session is not <code>null</code>.
+ * Will also invalidate the {@link HttpSession} if {@link #isInvalidateHttpSession()} is {@code true} and the
+ * session is not {@code null}.
*
* @author Ben Alex
*/
public class SecurityContextLogoutHandler implements LogoutHandler {
+ protected final Log logger = LogFactory.getLog(this.getClass());
+
private boolean invalidateHttpSession = true;
//~ Methods ========================================================================================================
@@ -49,6 +53,7 @@ public class SecurityContextLogoutHandler implements LogoutHandler {
if (invalidateHttpSession) {
HttpSession session = request.getSession(false);
if (session != null) {
+ logger.debug("Invalidating session: " + session.getId());
session.invalidate();
}
}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilter.java b/dist/spring-security-web/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilter.java
index 8ab40a2..0a77d57 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilter.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilter.java
@@ -1,7 +1,6 @@
package org.springframework.security.web.authentication.preauth;
import java.io.IOException;
-
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
@@ -10,7 +9,6 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
-import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.security.authentication.AuthenticationDetailsSource;
@@ -55,10 +53,11 @@ import org.springframework.web.filter.GenericFilterBean;
* @since 2.0
*/
public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFilterBean implements
- InitializingBean, ApplicationEventPublisherAware {
+ ApplicationEventPublisherAware {
private ApplicationEventPublisher eventPublisher = null;
- private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource();
+ private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource
+ = new WebAuthenticationDetailsSource();
private AuthenticationManager authenticationManager = null;
private boolean continueFilterChainOnUnsuccessfulAuthentication = true;
private boolean checkForPrincipalChanges;
@@ -93,7 +92,7 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
* Do the actual authentication for a pre-authenticated user.
*/
private void doAuthenticate(HttpServletRequest request, HttpServletResponse response) {
- Authentication authResult = null;
+ Authentication authResult;
Object principal = getPreAuthenticatedPrincipal(request);
Object credentials = getPreAuthenticatedCredentials(request);
@@ -131,24 +130,29 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
return true;
}
+ if (!checkForPrincipalChanges) {
+ return false;
+ }
+
Object principal = getPreAuthenticatedPrincipal(request);
- if (checkForPrincipalChanges &&
- !currentUser.getName().equals(principal)) {
- logger.debug("Pre-authenticated principal has changed to " + principal + " and will be reauthenticated");
- if (invalidateSessionOnPrincipalChange) {
- HttpSession session = request.getSession(false);
+ if (currentUser.getName().equals(principal)) {
+ return false;
+ }
- if (session != null) {
- logger.debug("Invalidating existing session");
- session.invalidate();
- }
- }
+ logger.debug("Pre-authenticated principal has changed to " + principal + " and will be reauthenticated");
- return true;
+ if (invalidateSessionOnPrincipalChange) {
+ HttpSession session = request.getSession(false);
+
+ if (session != null) {
+ logger.debug("Invalidating existing session");
+ session.invalidate();
+ request.getSession();
+ }
}
- return false;
+ return true;
}
/**
@@ -167,8 +171,9 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
}
/**
- * Ensures the authentication object in the secure context is set to null
- * when authentication fails.
+ * Ensures the authentication object in the secure context is set to null when authentication fails.
+ * <p>
+ * Caches the failure exception as a request attribute
*/
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) {
SecurityContextHolder.clearContext();
@@ -176,7 +181,7 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
if (logger.isDebugEnabled()) {
logger.debug("Cleared security context due to exception", failed);
}
- request.getSession().setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, failed);
+ request.setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, failed);
}
/**
@@ -191,11 +196,15 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
* @param authenticationDetailsSource
* The AuthenticationDetailsSource to use
*/
- public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) {
+ public void setAuthenticationDetailsSource(AuthenticationDetailsSource<HttpServletRequest,?> authenticationDetailsSource) {
Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required");
this.authenticationDetailsSource = authenticationDetailsSource;
}
+ protected AuthenticationDetailsSource<HttpServletRequest, ?> getAuthenticationDetailsSource() {
+ return authenticationDetailsSource;
+ }
+
/**
* @param authenticationManager
* The AuthenticationManager to use
@@ -204,6 +213,13 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
this.authenticationManager = authenticationManager;
}
+ /**
+ * If set to {@code true}, any {@code AuthenticationException} raised by the {@code AuthenticationManager} will be
+ * swallowed, and the request will be allowed to proceed, potentially using alternative authentication mechanisms.
+ * If {@code false} (the default), authentication failure will result in an immediate exception.
+ *
+ * @param shouldContinue set to {@code true} to allow the request to proceed after a failed authentication.
+ */
public void setContinueFilterChainOnUnsuccessfulAuthentication(boolean shouldContinue) {
continueFilterChainOnUnsuccessfulAuthentication = shouldContinue;
}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/PreAuthenticatedAuthenticationProvider.java b/dist/spring-security-web/org/springframework/security/web/authentication/preauth/PreAuthenticatedAuthenticationProvider.java
index 46a1096..4d0f98a 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/PreAuthenticatedAuthenticationProvider.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/preauth/PreAuthenticatedAuthenticationProvider.java
@@ -31,7 +31,7 @@ import org.springframework.util.Assert;
public class PreAuthenticatedAuthenticationProvider implements AuthenticationProvider, InitializingBean, Ordered {
private static final Log logger = LogFactory.getLog(PreAuthenticatedAuthenticationProvider.class);
- private AuthenticationUserDetailsService preAuthenticatedUserDetailsService = null;
+ private AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> preAuthenticatedUserDetailsService = null;
private UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker();
private boolean throwExceptionWhenTokenRejected = false;
@@ -77,7 +77,7 @@ public class PreAuthenticatedAuthenticationProvider implements AuthenticationPro
return null;
}
- UserDetails ud = preAuthenticatedUserDetailsService.loadUserDetails(authentication);
+ UserDetails ud = preAuthenticatedUserDetailsService.loadUserDetails((PreAuthenticatedAuthenticationToken)authentication);
userDetailsChecker.check(ud);
@@ -91,25 +91,17 @@ public class PreAuthenticatedAuthenticationProvider implements AuthenticationPro
/**
* Indicate that this provider only supports PreAuthenticatedAuthenticationToken (sub)classes.
*/
- public boolean supports(Class<? extends Object> authentication) {
+ public final boolean supports(Class<?> authentication) {
return PreAuthenticatedAuthenticationToken.class.isAssignableFrom(authentication);
}
/**
- * Set the AuthenticatedUserDetailsServices to be used.
+ * Set the AuthenticatedUserDetailsService to be used to load the {@code UserDetails} for the authenticated user.
*
- * @param aPreAuthenticatedUserDetailsService
+ * @param uds
*/
- public void setPreAuthenticatedUserDetailsService(AuthenticationUserDetailsService aPreAuthenticatedUserDetailsService) {
- this.preAuthenticatedUserDetailsService = aPreAuthenticatedUserDetailsService;
- }
-
- public int getOrder() {
- return order;
- }
-
- public void setOrder(int i) {
- order = i;
+ public void setPreAuthenticatedUserDetailsService(AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> uds) {
+ this.preAuthenticatedUserDetailsService = uds;
}
/**
@@ -130,4 +122,12 @@ public class PreAuthenticatedAuthenticationProvider implements AuthenticationPro
Assert.notNull(userDetailsChecker, "userDetailsChacker cannot be null");
this.userDetailsChecker = userDetailsChecker;
}
+
+ public int getOrder() {
+ return order;
+ }
+
+ public void setOrder(int i) {
+ order = i;
+ }
}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/PreAuthenticatedAuthenticationToken.java b/dist/spring-security-web/org/springframework/security/web/authentication/preauth/PreAuthenticatedAuthenticationToken.java
index b6854d6..417a38e 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/PreAuthenticatedAuthenticationToken.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/preauth/PreAuthenticatedAuthenticationToken.java
@@ -4,6 +4,7 @@ import java.util.Collection;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.SpringSecurityCoreVersion;
/**
@@ -14,6 +15,9 @@ import org.springframework.security.core.GrantedAuthority;
* @since 2.0
*/
public class PreAuthenticatedAuthenticationToken extends AbstractAuthenticationToken {
+
+ private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
+
private final Object principal;
private final Object credentials;
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/PreAuthenticatedGrantedAuthoritiesAuthenticationDetails.java b/dist/spring-security-web/org/springframework/security/web/authentication/preauth/PreAuthenticatedGrantedAuthoritiesAuthenticationDetails.java
index 204e9b2..dee974e 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/PreAuthenticatedGrantedAuthoritiesAuthenticationDetails.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/preauth/PreAuthenticatedGrantedAuthoritiesAuthenticationDetails.java
@@ -1,7 +1,6 @@
package org.springframework.security.web.authentication.preauth;
-import java.util.Collections;
-import java.util.List;
+import java.util.*;
import org.springframework.security.authentication.AuthenticationDetails;
import org.springframework.security.core.GrantedAuthority;
@@ -15,6 +14,7 @@ import org.springframework.util.Assert;
* @author Ruud Senden
* @since 2.0
*/
+ at Deprecated
public class PreAuthenticatedGrantedAuthoritiesAuthenticationDetails extends AuthenticationDetails implements
MutableGrantedAuthoritiesContainer {
public static final long serialVersionUID = 1L;
@@ -36,10 +36,12 @@ public class PreAuthenticatedGrantedAuthoritiesAuthenticationDetails extends Aut
}
/**
- * @see MutableGrantedAuthoritiesContainer#setGrantedAuthorities(List)
+ * @see MutableGrantedAuthoritiesContainer#setGrantedAuthorities(Collection)
*/
- public void setGrantedAuthorities(List<GrantedAuthority> aJ2eeBasedGrantedAuthorities) {
- this.preAuthenticatedGrantedAuthorities = Collections.unmodifiableList(aJ2eeBasedGrantedAuthorities);
+ public void setGrantedAuthorities(Collection<? extends GrantedAuthority> aJ2eeBasedGrantedAuthorities) {
+ List<GrantedAuthority> temp = new ArrayList<GrantedAuthority>(aJ2eeBasedGrantedAuthorities.size());
+ temp.addAll(aJ2eeBasedGrantedAuthorities);
+ this.preAuthenticatedGrantedAuthorities = Collections.unmodifiableList(temp);
}
/**
@@ -47,8 +49,8 @@ public class PreAuthenticatedGrantedAuthoritiesAuthenticationDetails extends Aut
*/
public String toString() {
StringBuilder sb = new StringBuilder();
- sb.append(super.toString() + "; ");
- sb.append("preAuthenticatedGrantedAuthorities: " + preAuthenticatedGrantedAuthorities);
+ sb.append(super.toString()).append("; ");
+ sb.append("preAuthenticatedGrantedAuthorities: ").append(preAuthenticatedGrantedAuthorities);
return sb.toString();
}
}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/PreAuthenticatedGrantedAuthoritiesUserDetailsService.java b/dist/spring-security-web/org/springframework/security/web/authentication/preauth/PreAuthenticatedGrantedAuthoritiesUserDetailsService.java
index b4e66ad..5651f09 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/PreAuthenticatedGrantedAuthoritiesUserDetailsService.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/preauth/PreAuthenticatedGrantedAuthoritiesUserDetailsService.java
@@ -1,6 +1,6 @@
package org.springframework.security.web.authentication.preauth;
-import java.util.List;
+import java.util.*;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
@@ -30,19 +30,19 @@ import org.springframework.util.Assert;
* @author Ruud Senden
* @since 2.0
*/
-public class PreAuthenticatedGrantedAuthoritiesUserDetailsService implements AuthenticationUserDetailsService {
+public class PreAuthenticatedGrantedAuthoritiesUserDetailsService
+ implements AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> {
/**
* Get a UserDetails object based on the user name contained in the given
* token, and the GrantedAuthorities as returned by the
* GrantedAuthoritiesContainer implementation as returned by
* the token.getDetails() method.
*/
- public final UserDetails loadUserDetails(Authentication token) throws AuthenticationException {
+ public final UserDetails loadUserDetails(PreAuthenticatedAuthenticationToken token) throws AuthenticationException {
Assert.notNull(token.getDetails());
Assert.isInstanceOf(GrantedAuthoritiesContainer.class, token.getDetails());
- List<GrantedAuthority> authorities = ((GrantedAuthoritiesContainer) token.getDetails()).getGrantedAuthorities();
- UserDetails ud = createuserDetails(token, authorities);
- return ud;
+ Collection<? extends GrantedAuthority> authorities = ((GrantedAuthoritiesContainer) token.getDetails()).getGrantedAuthorities();
+ return createuserDetails(token, authorities);
}
/**
@@ -51,7 +51,7 @@ public class PreAuthenticatedGrantedAuthoritiesUserDetailsService implements Aut
* @param token the authentication request token
* @param authorities the pre-authenticated authorities.
*/
- protected UserDetails createuserDetails(Authentication token, List<GrantedAuthority> authorities) {
+ protected UserDetails createuserDetails(Authentication token, Collection<? extends GrantedAuthority> authorities) {
return new User(token.getName(), "N/A", true, true, true, true, authorities);
}
}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails.java b/dist/spring-security-web/org/springframework/security/web/authentication/preauth/PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails.java
index 818eb99..33f1211 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/preauth/PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails.java
@@ -1,14 +1,13 @@
package org.springframework.security.web.authentication.preauth;
-import java.util.List;
-
-import javax.servlet.http.HttpServletRequest;
-
import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.authority.GrantedAuthoritiesContainerImpl;
-import org.springframework.security.core.authority.MutableGrantedAuthoritiesContainer;
+import org.springframework.security.core.SpringSecurityCoreVersion;
+import org.springframework.security.core.authority.GrantedAuthoritiesContainer;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
+import javax.servlet.http.HttpServletRequest;
+import java.util.*;
+
/**
* This WebAuthenticationDetails implementation allows for storing a list of
* pre-authenticated Granted Authorities.
@@ -18,27 +17,29 @@ import org.springframework.security.web.authentication.WebAuthenticationDetails;
* @since 2.0
*/
public class PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails extends WebAuthenticationDetails implements
- MutableGrantedAuthoritiesContainer {
- public static final long serialVersionUID = 1L;
+ GrantedAuthoritiesContainer {
- private MutableGrantedAuthoritiesContainer authoritiesContainer = new GrantedAuthoritiesContainerImpl();
+ private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
- public PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails(HttpServletRequest request) {
+ private final List<GrantedAuthority> authorities;
+
+ public PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails(HttpServletRequest request,
+ Collection<? extends GrantedAuthority> authorities) {
super(request);
- }
- public List<GrantedAuthority> getGrantedAuthorities() {
- return authoritiesContainer.getGrantedAuthorities();
+ List<GrantedAuthority> temp = new ArrayList<GrantedAuthority>(authorities.size());
+ temp.addAll(authorities);
+ this.authorities = Collections.unmodifiableList(temp);
}
- public void setGrantedAuthorities(List<GrantedAuthority> authorities) {
- this.authoritiesContainer.setGrantedAuthorities(authorities);
+ public List<GrantedAuthority> getGrantedAuthorities() {
+ return authorities;
}
public String toString() {
StringBuilder sb = new StringBuilder();
- sb.append(super.toString() + "; ");
- sb.append(authoritiesContainer);
+ sb.append(super.toString()).append("; ");
+ sb.append(authorities);
return sb.toString();
}
}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/PreAuthenticatedProcessingFilterEntryPoint.java b/dist/spring-security-web/org/springframework/security/web/authentication/preauth/PreAuthenticatedProcessingFilterEntryPoint.java
deleted file mode 100644
index 7ff5014..0000000
--- a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/PreAuthenticatedProcessingFilterEntryPoint.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.springframework.security.web.authentication.preauth;
-
-import org.springframework.security.web.authentication.Http403ForbiddenEntryPoint;
-
-/**
- * Renamed class, retained for backwards compatibility.
- * <p>
- * See {@link Http403ForbiddenEntryPoint}.
- *
- * @author Luke Taylor
- * @deprecated Use Http403ForbiddenEntryPoint instead.
- */
-public class PreAuthenticatedProcessingFilterEntryPoint extends Http403ForbiddenEntryPoint {
-
-}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/RequestHeaderAuthenticationFilter.java b/dist/spring-security-web/org/springframework/security/web/authentication/preauth/RequestHeaderAuthenticationFilter.java
index ec656c3..1320134 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/RequestHeaderAuthenticationFilter.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/preauth/RequestHeaderAuthenticationFilter.java
@@ -15,11 +15,11 @@ import org.springframework.util.Assert;
* in combination with other Spring Security authentication mechanisms such as form login, as this would imply there
* was a means of bypassing the external system which would be risky.
* <p>
- * The property <tt>principalRequestHeader</tt> is the name of the request header that contains the username. It
+ * The property {@code principalRequestHeader} is the name of the request header that contains the username. It
* defaults to "SM_USER" for compatibility with Siteminder.
* <p>
- * If the header is missing from the request, <tt>getPreAuthenticatedPrincipal</tt> will throw an exception. You
- * can override this behaviour by setting the <tt>exceptionIfMissingHeader</tt> property.
+ * If the header is missing from the request, {@code getPreAuthenticatedPrincipal} will throw an exception. You
+ * can override this behaviour by setting the {@code exceptionIfHeaderMissing} property.
*
*
* @author Luke Taylor
@@ -31,10 +31,10 @@ public class RequestHeaderAuthenticationFilter extends AbstractPreAuthenticatedP
private boolean exceptionIfHeaderMissing = true;
/**
- * Read and returns the header named by <tt>principalRequestHeader</tt> from the request.
+ * Read and returns the header named by {@code principalRequestHeader} from the request.
*
- * @throws PreAuthenticatedCredentialsNotFoundException if the header is missing and <tt>exceptionIfHeaderMissing</tt>
- * is set to <tt>true</tt>.
+ * @throws PreAuthenticatedCredentialsNotFoundException if the header is missing and {@code exceptionIfHeaderMissing}
+ * is set to {@code true}.
*/
protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
String principal = request.getHeader(principalRequestHeader);
@@ -48,14 +48,12 @@ public class RequestHeaderAuthenticationFilter extends AbstractPreAuthenticatedP
}
/**
- * Credentials aren't usually applicable, but if a <tt>credentialsRequestHeader</tt> is set, this
+ * Credentials aren't usually applicable, but if a {@code credentialsRequestHeader} is set, this
* will be read and used as the credentials value. Otherwise a dummy value will be used.
*/
protected Object getPreAuthenticatedCredentials(HttpServletRequest request) {
if (credentialsRequestHeader != null) {
- String credentials = request.getHeader(credentialsRequestHeader);
-
- return credentials;
+ return request.getHeader(credentialsRequestHeader);
}
return "N/A";
@@ -72,9 +70,9 @@ public class RequestHeaderAuthenticationFilter extends AbstractPreAuthenticatedP
}
/**
- * Defines whether an exception should be raised if the principal header is missing. Defaults to <tt>true</tt>.
+ * Defines whether an exception should be raised if the principal header is missing. Defaults to {@code true}.
*
- * @param exceptionIfHeaderMissing set to <tt>false</tt> to override the default behaviour and allow
+ * @param exceptionIfHeaderMissing set to {@code false} to override the default behaviour and allow
* the request to proceed if no header is found.
*/
public void setExceptionIfHeaderMissing(boolean exceptionIfHeaderMissing) {
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/j2ee/AbstractPreAuthenticatedAuthenticationDetailsSource.java b/dist/spring-security-web/org/springframework/security/web/authentication/preauth/j2ee/AbstractPreAuthenticatedAuthenticationDetailsSource.java
deleted file mode 100644
index b217f9e..0000000
--- a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/j2ee/AbstractPreAuthenticatedAuthenticationDetailsSource.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package org.springframework.security.web.authentication.preauth.j2ee;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.security.authentication.AuthenticationDetailsSourceImpl;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.authority.MutableGrantedAuthoritiesContainer;
-import org.springframework.security.core.authority.mapping.Attributes2GrantedAuthoritiesMapper;
-import org.springframework.security.core.authority.mapping.MappableAttributesRetriever;
-import org.springframework.security.core.authority.mapping.SimpleAttributes2GrantedAuthoritiesMapper;
-import org.springframework.util.Assert;
-
-/**
- * Base implementation for classes scenarios where the authentication details object is used
- * to store a list of authorities obtained from the context object (such as an HttpServletRequest)
- * passed to {@link #buildDetails(Object)}.
- * <p>
- *
- *
- * @author Luke Taylor
- * @since 2.0
- */
-public abstract class AbstractPreAuthenticatedAuthenticationDetailsSource extends AuthenticationDetailsSourceImpl {
- protected final Log logger = LogFactory.getLog(getClass());
- protected Set<String> j2eeMappableRoles;
- protected Attributes2GrantedAuthoritiesMapper j2eeUserRoles2GrantedAuthoritiesMapper =
- new SimpleAttributes2GrantedAuthoritiesMapper();
-
- public AbstractPreAuthenticatedAuthenticationDetailsSource() {
- }
-
- /**
- * Check that all required properties have been set.
- */
- public void afterPropertiesSet() throws Exception {
- Assert.notNull(j2eeMappableRoles, "No mappable roles available");
- Assert.notNull(j2eeUserRoles2GrantedAuthoritiesMapper, "Roles to granted authorities mapper not set");
- }
-
- /**
- * Build the authentication details object. If the specified authentication
- * details class implements {@link MutableGrantedAuthoritiesContainer}, a
- * list of pre-authenticated Granted Authorities will be set based on the
- * roles for the current user.
- *
- * @see org.springframework.security.authentication.AuthenticationDetailsSource#buildDetails(Object)
- */
- public Object buildDetails(Object context) {
- Object result = super.buildDetails(context);
-
- if (result instanceof MutableGrantedAuthoritiesContainer) {
- Collection<String> j2eeUserRoles = getUserRoles(context, j2eeMappableRoles);
- List<GrantedAuthority> userGas = j2eeUserRoles2GrantedAuthoritiesMapper.getGrantedAuthorities(j2eeUserRoles);
-
- if (logger.isDebugEnabled()) {
- logger.debug("J2EE roles [" + j2eeUserRoles + "] mapped to Granted Authorities: [" + userGas + "]");
- }
-
- ((MutableGrantedAuthoritiesContainer) result).setGrantedAuthorities(userGas);
- }
- return result;
- }
-
- /**
- * Allows the roles of the current user to be determined from the context object
- *
- * @param context the context object (an HttpRequest, PortletRequest etc)
- * @param mappableRoles the possible roles as determined by the MappableAttributesRetriever
- * @return the subset of mappable roles which the current user has.
- */
- protected abstract Collection<String> getUserRoles(Object context, Set<String> mappableRoles);
-
- /**
- * @param aJ2eeMappableRolesRetriever
- * The MappableAttributesRetriever to use
- */
- public void setMappableRolesRetriever(MappableAttributesRetriever aJ2eeMappableRolesRetriever) {
- this.j2eeMappableRoles = aJ2eeMappableRolesRetriever.getMappableAttributes();
- }
-
- /**
- * @param mapper
- * The Attributes2GrantedAuthoritiesMapper to use
- */
- public void setUserRoles2GrantedAuthoritiesMapper(Attributes2GrantedAuthoritiesMapper mapper) {
- j2eeUserRoles2GrantedAuthoritiesMapper = mapper;
- }
-}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/j2ee/J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource.java b/dist/spring-security-web/org/springframework/security/web/authentication/preauth/j2ee/J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource.java
index 9fffbc6..3358bd7 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/j2ee/J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/preauth/j2ee/J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource.java
@@ -1,13 +1,18 @@
package org.springframework.security.web.authentication.preauth.j2ee;
-import org.springframework.security.web.authentication.preauth.PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.security.authentication.AuthenticationDetailsSource;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.mapping.Attributes2GrantedAuthoritiesMapper;
+import org.springframework.security.core.authority.mapping.MappableAttributesRetriever;
import org.springframework.security.core.authority.mapping.SimpleAttributes2GrantedAuthoritiesMapper;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Set;
+import org.springframework.security.web.authentication.preauth.PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails;
+import org.springframework.util.Assert;
import javax.servlet.http.HttpServletRequest;
+import java.util.*;
/**
* Implementation of AuthenticationDetailsSource which converts the user's J2EE roles (as obtained by calling
@@ -17,29 +22,77 @@ import javax.servlet.http.HttpServletRequest;
* @author Ruud Senden
* @since 2.0
*/
-public class J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource extends AbstractPreAuthenticatedAuthenticationDetailsSource {
+public class J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource
+ implements AuthenticationDetailsSource<HttpServletRequest, PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails>,
+ InitializingBean {
+
+ protected final Log logger = LogFactory.getLog(getClass());
+ /** The role attributes returned by the configured {@code MappableAttributesRetriever} */
+ protected Set<String> j2eeMappableRoles;
+ protected Attributes2GrantedAuthoritiesMapper j2eeUserRoles2GrantedAuthoritiesMapper =
+ new SimpleAttributes2GrantedAuthoritiesMapper();
+
/**
- * Public constructor which overrides the default {@code WebAuthenticationDetails}
- * class to be used.
+ * Check that all required properties have been set.
*/
- public J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource() {
- super.setClazz(PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails.class);
-
- j2eeUserRoles2GrantedAuthoritiesMapper = new SimpleAttributes2GrantedAuthoritiesMapper();
+ public void afterPropertiesSet() throws Exception {
+ Assert.notNull(j2eeMappableRoles, "No mappable roles available");
+ Assert.notNull(j2eeUserRoles2GrantedAuthoritiesMapper, "Roles to granted authorities mapper not set");
}
/**
- * Obtains the list of user roles based on the current user's J2EE roles.
+ * Obtains the list of user roles based on the current user's JEE roles. The
+ * {@link javax.servlet.http.HttpServletRequest#isUserInRole(String)} method is called for each of the values
+ * in the {@code j2eeMappableRoles} set to determine if that role should be assigned to the user.
+ *
+ * @param request the request which should be used to extract the user's roles.
+ * @return The subset of {@code j2eeMappableRoles} which applies to the current user making the request.
*/
- protected Collection<String> getUserRoles(Object context, Set<String> mappableRoles) {
+ protected Collection<String> getUserRoles(HttpServletRequest request) {
ArrayList<String> j2eeUserRolesList = new ArrayList<String>();
- for (String role : mappableRoles) {
- if (((HttpServletRequest)context).isUserInRole(role)) {
+ for (String role : j2eeMappableRoles) {
+ if (request.isUserInRole(role)) {
j2eeUserRolesList.add(role);
}
}
return j2eeUserRolesList;
}
+
+ /**
+ * Builds the authentication details object.
+ *
+ * @see org.springframework.security.authentication.AuthenticationDetailsSource#buildDetails(Object)
+ */
+ public PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails buildDetails(HttpServletRequest context) {
+
+ Collection<String> j2eeUserRoles = getUserRoles(context);
+ Collection<? extends GrantedAuthority> userGas = j2eeUserRoles2GrantedAuthoritiesMapper.getGrantedAuthorities(j2eeUserRoles);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("J2EE roles [" + j2eeUserRoles + "] mapped to Granted Authorities: [" + userGas + "]");
+ }
+
+ PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails result =
+ new PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails(context, userGas);
+
+ return result;
+ }
+
+ /**
+ * @param aJ2eeMappableRolesRetriever
+ * The MappableAttributesRetriever to use
+ */
+ public void setMappableRolesRetriever(MappableAttributesRetriever aJ2eeMappableRolesRetriever) {
+ this.j2eeMappableRoles = Collections.unmodifiableSet(aJ2eeMappableRolesRetriever.getMappableAttributes());
+ }
+
+ /**
+ * @param mapper
+ * The Attributes2GrantedAuthoritiesMapper to use
+ */
+ public void setUserRoles2GrantedAuthoritiesMapper(Attributes2GrantedAuthoritiesMapper mapper) {
+ j2eeUserRoles2GrantedAuthoritiesMapper = mapper;
+ }
}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/websphere/DefaultWASUsernameAndGroupsExtractor.java b/dist/spring-security-web/org/springframework/security/web/authentication/preauth/websphere/DefaultWASUsernameAndGroupsExtractor.java
index aeced5c..1e3c8f4 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/websphere/DefaultWASUsernameAndGroupsExtractor.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/preauth/websphere/DefaultWASUsernameAndGroupsExtractor.java
@@ -54,7 +54,7 @@ final class DefaultWASUsernameAndGroupsExtractor implements WASUsernameAndGroups
* The subject for which to retrieve the security name
* @return String the security name for the given subject
*/
- private static final String getSecurityName(final Subject subject) {
+ private static String getSecurityName(final Subject subject) {
if (logger.isDebugEnabled()) {
logger.debug("Determining Websphere security name for subject " + subject);
}
@@ -77,7 +77,7 @@ final class DefaultWASUsernameAndGroupsExtractor implements WASUsernameAndGroups
*
* @return Subject the current RunAs subject
*/
- private static final Subject getRunAsSubject() {
+ private static Subject getRunAsSubject() {
logger.debug("Retrieving WebSphere RunAs subject");
// get Subject: WSSubject.getCallerSubject ();
return (Subject) invokeMethod(getRunAsSubjectMethod(), null, new Object[] {});
@@ -90,7 +90,7 @@ final class DefaultWASUsernameAndGroupsExtractor implements WASUsernameAndGroups
* The subject for which to retrieve the WebSphere group names
* @return the WebSphere group names for the given subject
*/
- private static final List<String> getWebSphereGroups(final Subject subject) {
+ private static List<String> getWebSphereGroups(final Subject subject) {
return getWebSphereGroups(getSecurityName(subject));
}
@@ -102,7 +102,7 @@ final class DefaultWASUsernameAndGroupsExtractor implements WASUsernameAndGroups
* @return the WebSphere group names for the given security name
*/
@SuppressWarnings("unchecked")
- private static final List<String> getWebSphereGroups(final String securityName) {
+ private static List<String> getWebSphereGroups(final String securityName) {
Context ic = null;
try {
// TODO: Cache UserRegistry object
@@ -123,14 +123,16 @@ final class DefaultWASUsernameAndGroupsExtractor implements WASUsernameAndGroups
throw new RuntimeException("Exception occured while looking up groups for user", e);
} finally {
try {
- ic.close();
+ if (ic != null) {
+ ic.close();
+ }
} catch (NamingException e) {
logger.debug("Exception occured while closing context", e);
}
}
}
- private static final Object invokeMethod(Method method, Object instance, Object[] args)
+ private static Object invokeMethod(Method method, Object instance, Object[] args)
{
try {
return method.invoke(instance,args);
@@ -146,7 +148,7 @@ final class DefaultWASUsernameAndGroupsExtractor implements WASUsernameAndGroups
}
}
- private static final Method getMethod(String className, String methodName, String[] parameterTypeNames) {
+ private static Method getMethod(String className, String methodName, String[] parameterTypeNames) {
try {
Class<?> c = Class.forName(className);
final int len = parameterTypeNames.length;
@@ -164,21 +166,21 @@ final class DefaultWASUsernameAndGroupsExtractor implements WASUsernameAndGroups
}
}
- private static final Method getRunAsSubjectMethod() {
+ private static Method getRunAsSubjectMethod() {
if (getRunAsSubject == null) {
getRunAsSubject = getMethod("com.ibm.websphere.security.auth.WSSubject", "getRunAsSubject", new String[] {});
}
return getRunAsSubject;
}
- private static final Method getGroupsForUserMethod() {
+ private static Method getGroupsForUserMethod() {
if (getGroupsForUser == null) {
getGroupsForUser = getMethod("com.ibm.websphere.security.UserRegistry", "getGroupsForUser", new String[] { "java.lang.String" });
}
return getGroupsForUser;
}
- private static final Method getSecurityNameMethod() {
+ private static Method getSecurityNameMethod() {
if (getSecurityName == null) {
getSecurityName = getMethod("com.ibm.websphere.security.cred.WSCredential", "getSecurityName", new String[] {});
}
@@ -186,14 +188,14 @@ final class DefaultWASUsernameAndGroupsExtractor implements WASUsernameAndGroups
}
// SEC-803
- private static final Class<?> getWSCredentialClass() {
+ private static Class<?> getWSCredentialClass() {
if (wsCredentialClass == null) {
wsCredentialClass = getClass("com.ibm.websphere.security.cred.WSCredential");
}
return wsCredentialClass;
}
- private static final Class<?> getClass(String className) {
+ private static Class<?> getClass(String className) {
try {
return Class.forName(className);
} catch (ClassNotFoundException e) {
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/websphere/WebSphere2SpringSecurityPropagationInterceptor.java b/dist/spring-security-web/org/springframework/security/web/authentication/preauth/websphere/WebSphere2SpringSecurityPropagationInterceptor.java
index 7d72085..a94cddd 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/websphere/WebSphere2SpringSecurityPropagationInterceptor.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/preauth/websphere/WebSphere2SpringSecurityPropagationInterceptor.java
@@ -18,10 +18,11 @@ import org.springframework.util.Assert;
* @author Ruud Senden
* @since 1.0
*/
+ at Deprecated
public class WebSphere2SpringSecurityPropagationInterceptor implements MethodInterceptor {
private static final Log logger = LogFactory.getLog(WebSphere2SpringSecurityPropagationInterceptor.class);
private AuthenticationManager authenticationManager = null;
- private AuthenticationDetailsSource authenticationDetailsSource = new WebSpherePreAuthenticatedAuthenticationDetailsSource();
+ private AuthenticationDetailsSource<?,?> authenticationDetailsSource = new WebSpherePreAuthenticatedAuthenticationDetailsSource();
private final WASUsernameAndGroupsExtractor wasHelper;
public WebSphere2SpringSecurityPropagationInterceptor() {
@@ -40,7 +41,7 @@ public class WebSphere2SpringSecurityPropagationInterceptor implements MethodInt
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
try {
logger.debug("Performing Spring Security authentication with WebSphere credentials");
- authenticateSpringSecurityWithWASCredentials(this);
+ authenticateSpringSecurityWithWASCredentials();
logger.debug("Proceeding with method invocation");
return methodInvocation.proceed();
} finally {
@@ -52,9 +53,8 @@ public class WebSphere2SpringSecurityPropagationInterceptor implements MethodInt
/**
* Retrieve the current WebSphere credentials and authenticate them with Spring Security
* using the pre-authenticated authentication provider.
- * @param aContext The context to use for building the authentication details.
*/
- private final void authenticateSpringSecurityWithWASCredentials(Object aContext) {
+ private void authenticateSpringSecurityWithWASCredentials() {
Assert.notNull(authenticationManager);
Assert.notNull(authenticationDetailsSource);
@@ -78,7 +78,7 @@ public class WebSphere2SpringSecurityPropagationInterceptor implements MethodInt
/**
* @param authenticationDetailsSource The authenticationDetailsSource to set.
*/
- public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) {
+ public void setAuthenticationDetailsSource(AuthenticationDetailsSource<?,?> authenticationDetailsSource) {
this.authenticationDetailsSource = authenticationDetailsSource;
}
}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/websphere/WebSpherePreAuthenticatedAuthenticationDetailsSource.java b/dist/spring-security-web/org/springframework/security/web/authentication/preauth/websphere/WebSpherePreAuthenticatedAuthenticationDetailsSource.java
index 56bc633..579ad04 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/websphere/WebSpherePreAuthenticatedAuthenticationDetailsSource.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/preauth/websphere/WebSpherePreAuthenticatedAuthenticationDetailsSource.java
@@ -1,6 +1,6 @@
package org.springframework.security.web.authentication.preauth.websphere;
-import java.util.List;
+import java.util.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -23,6 +23,7 @@ import org.springframework.util.Assert;
*
* @author Ruud Senden
*/
+ at Deprecated
public class WebSpherePreAuthenticatedAuthenticationDetailsSource extends AuthenticationDetailsSourceImpl implements InitializingBean {
private final Log logger = LogFactory.getLog(getClass());
@@ -72,9 +73,9 @@ public class WebSpherePreAuthenticatedAuthenticationDetailsSource extends Authen
*
* @return authorities mapped from the user's WebSphere groups.
*/
- private List<GrantedAuthority> getWebSphereGroupsBasedGrantedAuthorities() {
+ private Collection<? extends GrantedAuthority> getWebSphereGroupsBasedGrantedAuthorities() {
List<String> webSphereGroups = wasHelper.getGroupsForCurrentUser();
- List<GrantedAuthority> userGas = webSphereGroups2GrantedAuthoritiesMapper.getGrantedAuthorities(webSphereGroups);
+ Collection<? extends GrantedAuthority> userGas = webSphereGroups2GrantedAuthoritiesMapper.getGrantedAuthorities(webSphereGroups);
if (logger.isDebugEnabled()) {
logger.debug("WebSphere groups: " + webSphereGroups + " mapped to Granted Authorities: " + userGas);
}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/websphere/WebSpherePreAuthenticatedProcessingFilter.java b/dist/spring-security-web/org/springframework/security/web/authentication/preauth/websphere/WebSpherePreAuthenticatedProcessingFilter.java
index 46ee077..31da5cc 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/websphere/WebSpherePreAuthenticatedProcessingFilter.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/preauth/websphere/WebSpherePreAuthenticatedProcessingFilter.java
@@ -25,6 +25,7 @@ public class WebSpherePreAuthenticatedProcessingFilter extends AbstractPreAuthen
WebSpherePreAuthenticatedProcessingFilter(WASUsernameAndGroupsExtractor wasHelper) {
this.wasHelper = wasHelper;
+ setAuthenticationDetailsSource(new WebSpherePreAuthenticatedWebAuthenticationDetailsSource());
}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/websphere/WebSpherePreAuthenticatedWebAuthenticationDetailsSource.java b/dist/spring-security-web/org/springframework/security/web/authentication/preauth/websphere/WebSpherePreAuthenticatedWebAuthenticationDetailsSource.java
index ed3b668..3156944 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/websphere/WebSpherePreAuthenticatedWebAuthenticationDetailsSource.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/preauth/websphere/WebSpherePreAuthenticatedWebAuthenticationDetailsSource.java
@@ -1,24 +1,62 @@
package org.springframework.security.web.authentication.preauth.websphere;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.security.authentication.AuthenticationDetailsSource;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.mapping.Attributes2GrantedAuthoritiesMapper;
+import org.springframework.security.core.authority.mapping.SimpleAttributes2GrantedAuthoritiesMapper;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails;
+import javax.servlet.http.HttpServletRequest;
+import java.util.*;
+
/**
- * This AuthenticationDetailsSource implementation, when configured with a MutableGrantedAuthoritiesContainer,
- * will set the pre-authenticated granted authorities based on the WebSphere groups for the current WebSphere
- * user, mapped using the configured Attributes2GrantedAuthoritiesMapper.
- *
- * By default, this class is configured to build instances of the
- * PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails class.
+ * This AuthenticationDetailsSource implementation will set the pre-authenticated granted
+ * authorities based on the WebSphere groups for the current WebSphere user, mapped using the
+ * configured Attributes2GrantedAuthoritiesMapper.
*
* @author Ruud Senden
*/
-public class WebSpherePreAuthenticatedWebAuthenticationDetailsSource extends WebSpherePreAuthenticatedAuthenticationDetailsSource {
+public class WebSpherePreAuthenticatedWebAuthenticationDetailsSource implements
+ AuthenticationDetailsSource<HttpServletRequest, PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails> {
+ private final Log logger = LogFactory.getLog(getClass());
+
+ private Attributes2GrantedAuthoritiesMapper webSphereGroups2GrantedAuthoritiesMapper = new SimpleAttributes2GrantedAuthoritiesMapper();
+
+ private final WASUsernameAndGroupsExtractor wasHelper;
+
+ public WebSpherePreAuthenticatedWebAuthenticationDetailsSource() {
+ this(new DefaultWASUsernameAndGroupsExtractor());
+ }
+
+ public WebSpherePreAuthenticatedWebAuthenticationDetailsSource(WASUsernameAndGroupsExtractor wasHelper) {
+ this.wasHelper = wasHelper;
+ }
+
+ public PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails buildDetails(HttpServletRequest context) {
+ return new PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails(context, getWebSphereGroupsBasedGrantedAuthorities());
+ }
+
/**
- * Public constructor which overrides the default AuthenticationDetails
- * class to be used.
+ * Get a list of Granted Authorities based on the current user's WebSphere groups.
+ *
+ * @return authorities mapped from the user's WebSphere groups.
*/
- public WebSpherePreAuthenticatedWebAuthenticationDetailsSource() {
- super();
- super.setClazz(PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails.class);
+ private Collection<? extends GrantedAuthority> getWebSphereGroupsBasedGrantedAuthorities() {
+ List<String> webSphereGroups = wasHelper.getGroupsForCurrentUser();
+ Collection<? extends GrantedAuthority> userGas = webSphereGroups2GrantedAuthoritiesMapper.getGrantedAuthorities(webSphereGroups);
+ if (logger.isDebugEnabled()) {
+ logger.debug("WebSphere groups: " + webSphereGroups + " mapped to Granted Authorities: " + userGas);
+ }
+ return userGas;
}
+
+ /**
+ * @param mapper The Attributes2GrantedAuthoritiesMapper to use for converting the WAS groups to authorities
+ */
+ public void setWebSphereGroups2GrantedAuthoritiesMapper(Attributes2GrantedAuthoritiesMapper mapper) {
+ webSphereGroups2GrantedAuthoritiesMapper = mapper;
+ }
+
}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/x509/SubjectDnX509PrincipalExtractor.java b/dist/spring-security-web/org/springframework/security/web/authentication/preauth/x509/SubjectDnX509PrincipalExtractor.java
index c944323..0bb097c 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/preauth/x509/SubjectDnX509PrincipalExtractor.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/preauth/x509/SubjectDnX509PrincipalExtractor.java
@@ -45,7 +45,7 @@ public class SubjectDnX509PrincipalExtractor implements X509PrincipalExtractor {
Matcher matcher = subjectDnPattern.matcher(subjectDN);
if (!matcher.find()) {
- throw new BadCredentialsException(messages.getMessage("DaoX509AuthoritiesPopulator.noMatching",
+ throw new BadCredentialsException(messages.getMessage("SubjectDnX509PrincipalExtractor.noMatching",
new Object[] {subjectDN}, "No matching pattern was found in subject DN: {0}"));
}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/rememberme/AbstractRememberMeServices.java b/dist/spring-security-web/org/springframework/security/web/authentication/rememberme/AbstractRememberMeServices.java
index 4a4bce5..1de12f4 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/rememberme/AbstractRememberMeServices.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/rememberme/AbstractRememberMeServices.java
@@ -1,5 +1,7 @@
package org.springframework.security.web.authentication.rememberme;
+import java.lang.reflect.Method;
+
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -14,7 +16,9 @@ import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.authentication.RememberMeAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.SpringSecurityMessageSource;
-import org.springframework.security.core.codec.Base64;
+import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
+import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper;
+import org.springframework.security.crypto.codec.Base64;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsChecker;
import org.springframework.security.core.userdetails.UserDetailsService;
@@ -23,12 +27,14 @@ import org.springframework.security.web.authentication.RememberMeServices;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.util.Assert;
+import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
/**
* Base class for RememberMeServices implementations.
*
* @author Luke Taylor
+ * @author Rob Winch
* @since 2.0
*/
public abstract class AbstractRememberMeServices implements RememberMeServices, InitializingBean, LogoutHandler {
@@ -43,18 +49,36 @@ public abstract class AbstractRememberMeServices implements RememberMeServices,
//~ Instance fields ================================================================================================
protected final Log logger = LogFactory.getLog(getClass());
- protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
+ protected final MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
private UserDetailsService userDetailsService;
private UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker();
- private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource();
+ private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = new WebAuthenticationDetailsSource();
private String cookieName = SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY;
private String parameter = DEFAULT_PARAMETER;
private boolean alwaysRemember;
private String key;
private int tokenValiditySeconds = TWO_WEEKS_S;
- private boolean useSecureCookie = false;
+ private Boolean useSecureCookie = null;
+ private Method setHttpOnlyMethod;
+ private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper();
+
+ /**
+ * @deprecated Use constructor injection
+ */
+ @Deprecated
+ protected AbstractRememberMeServices() {
+ this.setHttpOnlyMethod = ReflectionUtils.findMethod(Cookie.class,"setHttpOnly", boolean.class);
+ }
+
+ protected AbstractRememberMeServices(String key, UserDetailsService userDetailsService) {
+ Assert.hasLength(key, "key cannot be empty or null");
+ Assert.notNull(userDetailsService, "UserDetailsService cannot be null");
+ this.key = key;
+ this.userDetailsService = userDetailsService;
+ this.setHttpOnlyMethod = ReflectionUtils.findMethod(Cookie.class,"setHttpOnly", boolean.class);
+ }
public void afterPropertiesSet() throws Exception {
Assert.hasLength(key);
@@ -125,9 +149,9 @@ public abstract class AbstractRememberMeServices implements RememberMeServices,
return null;
}
- for (int i = 0; i < cookies.length; i++) {
- if (cookieName.equals(cookies[i].getName())) {
- return cookies[i].getValue();
+ for (Cookie cookie : cookies) {
+ if (cookieName.equals(cookie.getName())) {
+ return cookie.getValue();
}
}
@@ -147,7 +171,8 @@ public abstract class AbstractRememberMeServices implements RememberMeServices,
* @return the <tt>Authentication</tt> for the remember-me authenticated user
*/
protected Authentication createSuccessfulAuthentication(HttpServletRequest request, UserDetails user) {
- RememberMeAuthenticationToken auth = new RememberMeAuthenticationToken(key, user, user.getAuthorities());
+ RememberMeAuthenticationToken auth = new RememberMeAuthenticationToken(key, user,
+ authoritiesMapper.mapAuthorities(user.getAuthorities()));
auth.setDetails(authenticationDetailsSource.buildDetails(request));
return auth;
}
@@ -292,9 +317,6 @@ public abstract class AbstractRememberMeServices implements RememberMeServices,
/**
* Sets a "cancel cookie" (with maxAge = 0) on the response to disable persistent logins.
- *
- * @param request
- * @param response
*/
protected void cancelCookie(HttpServletRequest request, HttpServletResponse response) {
logger.debug("Cancelling cookie");
@@ -306,7 +328,11 @@ public abstract class AbstractRememberMeServices implements RememberMeServices,
}
/**
- * Sets the cookie on the response
+ * Sets the cookie on the response.
+ *
+ * By default a secure cookie will be used if the connection is secure. You can set the {@code useSecureCookie}
+ * property to {@code false} to override this. If you set it to {@code true}, the cookie will always be flagged
+ * as secure. If Servlet 3.0 is used, the cookie will be marked as HttpOnly.
*
* @param tokens the tokens which will be encoded to make the cookie value.
* @param maxAge the value passed to {@link Cookie#setMaxAge(int)}
@@ -318,7 +344,19 @@ public abstract class AbstractRememberMeServices implements RememberMeServices,
Cookie cookie = new Cookie(cookieName, cookieValue);
cookie.setMaxAge(maxAge);
cookie.setPath(getCookiePath(request));
- cookie.setSecure(useSecureCookie);
+
+ if (useSecureCookie == null) {
+ cookie.setSecure(request.isSecure());
+ } else {
+ cookie.setSecure(useSecureCookie);
+ }
+
+ if(setHttpOnlyMethod != null) {
+ ReflectionUtils.invokeMethod(setHttpOnlyMethod, cookie, Boolean.TRUE);
+ } else if (logger.isDebugEnabled()) {
+ logger.debug("Note: Cookie will not be marked as HttpOnly because you are not using Servlet 3.0 (Cookie#setHttpOnly(boolean) was not found).");
+ }
+
response.addCookie(cookie);
}
@@ -328,7 +366,7 @@ public abstract class AbstractRememberMeServices implements RememberMeServices,
}
/**
- * Implementation of <tt>LogoutHandler</tt>. Default behaviour is to call <tt>cancelCookie()</tt>.
+ * Implementation of {@code LogoutHandler}. Default behaviour is to call {@code cancelCookie()}.
*/
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
if (logger.isDebugEnabled()) {
@@ -370,11 +408,21 @@ public abstract class AbstractRememberMeServices implements RememberMeServices,
return userDetailsService;
}
+ /**
+ *
+ * @deprecated Use constructor injection
+ */
+ @Deprecated
public void setUserDetailsService(UserDetailsService userDetailsService) {
Assert.notNull(userDetailsService, "UserDetailsService canot be null");
this.userDetailsService = userDetailsService;
}
+ /**
+ *
+ * @deprecated Use constructor injection
+ */
+ @Deprecated
public void setKey(String key) {
this.key = key;
}
@@ -391,16 +439,43 @@ public abstract class AbstractRememberMeServices implements RememberMeServices,
return tokenValiditySeconds;
}
+ /**
+ * Whether the cookie should be flagged as secure or not. Secure cookies can only be sent over an HTTPS connection
+ * and this cannot be accidentally submitted over HTTP where they could be intercepted.
+ * <p>
+ * By default the cookie will be secure if the request is secure. If you only want to use remember-me over
+ * HTTPS (recommended) you should set this property to {@code true}.
+ *
+ * @param useSecureCookie set to {@code true} to always user secure cookies, {@code false} to disable their use.
+ */
public void setUseSecureCookie(boolean useSecureCookie) {
this.useSecureCookie = useSecureCookie;
}
- protected AuthenticationDetailsSource getAuthenticationDetailsSource() {
+ protected AuthenticationDetailsSource<HttpServletRequest,?> getAuthenticationDetailsSource() {
return authenticationDetailsSource;
}
- public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) {
+ public void setAuthenticationDetailsSource(AuthenticationDetailsSource<HttpServletRequest,?> authenticationDetailsSource) {
Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource cannot be null");
this.authenticationDetailsSource = authenticationDetailsSource;
}
+
+ /**
+ * Sets the strategy to be used to validate the {@code UserDetails} object obtained for
+ * the user when processing a remember-me cookie to automatically log in a user.
+ *
+ * @param userDetailsChecker
+ * the strategy which will be passed the user object to allow it to be rejected if account should not
+ * be allowed to authenticate (if it is locked, for example). Defaults to a
+ * {@code AccountStatusUserDetailsChecker} instance.
+ *
+ */
+ public void setUserDetailsChecker(UserDetailsChecker userDetailsChecker) {
+ this.userDetailsChecker = userDetailsChecker;
+ }
+
+ public void setAuthoritiesMapper(GrantedAuthoritiesMapper authoritiesMapper) {
+ this.authoritiesMapper = authoritiesMapper;
+ }
}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/rememberme/InMemoryTokenRepositoryImpl.java b/dist/spring-security-web/org/springframework/security/web/authentication/rememberme/InMemoryTokenRepositoryImpl.java
index 2961caf..6078887 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/rememberme/InMemoryTokenRepositoryImpl.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/rememberme/InMemoryTokenRepositoryImpl.java
@@ -13,7 +13,7 @@ import java.util.Map;
* @author Luke Taylor
*/
public class InMemoryTokenRepositoryImpl implements PersistentTokenRepository {
- private Map<String, PersistentRememberMeToken> seriesTokens = new HashMap<String, PersistentRememberMeToken>();
+ private final Map<String, PersistentRememberMeToken> seriesTokens = new HashMap<String, PersistentRememberMeToken>();
public synchronized void createNewToken(PersistentRememberMeToken token) {
PersistentRememberMeToken current = seriesTokens.get(token.getSeries());
@@ -36,16 +36,16 @@ public class InMemoryTokenRepositoryImpl implements PersistentTokenRepository {
}
public synchronized PersistentRememberMeToken getTokenForSeries(String seriesId) {
- return (PersistentRememberMeToken) seriesTokens.get(seriesId);
+ return seriesTokens.get(seriesId);
}
public synchronized void removeUserTokens(String username) {
Iterator<String> series = seriesTokens.keySet().iterator();
while (series.hasNext()) {
- Object seriesId = series.next();
+ String seriesId = series.next();
- PersistentRememberMeToken token = (PersistentRememberMeToken) seriesTokens.get(seriesId);
+ PersistentRememberMeToken token = seriesTokens.get(seriesId);
if (username.equals(token.getUsername())) {
series.remove();
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/rememberme/JdbcTokenRepositoryImpl.java b/dist/spring-security-web/org/springframework/security/web/authentication/rememberme/JdbcTokenRepositoryImpl.java
index 7012b30..238aaf3 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/rememberme/JdbcTokenRepositoryImpl.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/rememberme/JdbcTokenRepositoryImpl.java
@@ -2,6 +2,7 @@ package org.springframework.security.web.authentication.rememberme;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
+import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.jdbc.object.MappingSqlQuery;
@@ -11,7 +12,7 @@ import javax.sql.DataSource;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
-import java.util.Date;
+import java.util.*;
/**
* JDBC based persistent login token repository implementation.
@@ -47,29 +48,19 @@ public class JdbcTokenRepositoryImpl extends JdbcDaoSupport implements Persisten
private String removeUserTokensSql = DEF_REMOVE_USER_TOKENS_SQL;
private boolean createTableOnStartup;
- private MappingSqlQuery<PersistentRememberMeToken> tokensBySeriesMapping;
- private SqlUpdate insertToken;
- private SqlUpdate updateToken;
- private SqlUpdate removeUserTokens;
-
protected void initDao() {
- tokensBySeriesMapping = new TokensBySeriesMapping(getDataSource());
- insertToken = new InsertToken(getDataSource());
- updateToken = new UpdateToken(getDataSource());
- removeUserTokens = new RemoveUserTokens(getDataSource());
-
if (createTableOnStartup) {
getJdbcTemplate().execute(CREATE_TABLE_SQL);
}
}
public void createNewToken(PersistentRememberMeToken token) {
- insertToken.update(
- new Object[] {token.getUsername(), token.getSeries(), token.getTokenValue(), token.getDate()});
+ getJdbcTemplate().update(insertTokenSql, token.getUsername(), token.getSeries(),
+ token.getTokenValue(), token.getDate());
}
public void updateToken(String series, String tokenValue, Date lastUsed) {
- updateToken.update(new Object[] {tokenValue, new Date(), series});
+ getJdbcTemplate().update(updateTokenSql, tokenValue, new Date(), series);
}
/**
@@ -83,7 +74,11 @@ public class JdbcTokenRepositoryImpl extends JdbcDaoSupport implements Persisten
*/
public PersistentRememberMeToken getTokenForSeries(String seriesId) {
try {
- return (PersistentRememberMeToken) tokensBySeriesMapping.findObject(seriesId);
+ return getJdbcTemplate().queryForObject(tokensBySeriesSql, new RowMapper<PersistentRememberMeToken>() {
+ public PersistentRememberMeToken mapRow(ResultSet rs, int rowNum) throws SQLException {
+ return new PersistentRememberMeToken(rs.getString(1), rs.getString(2), rs.getString(3), rs.getTimestamp(4));
+ }
+ }, seriesId);
} catch(IncorrectResultSizeDataAccessException moreThanOne) {
logger.error("Querying token for series '" + seriesId + "' returned more than one value. Series" +
" should be unique");
@@ -95,7 +90,7 @@ public class JdbcTokenRepositoryImpl extends JdbcDaoSupport implements Persisten
}
public void removeUserTokens(String username) {
- removeUserTokens.update(username);
+ getJdbcTemplate().update(removeUserTokensSql, username);
}
/**
@@ -107,53 +102,4 @@ public class JdbcTokenRepositoryImpl extends JdbcDaoSupport implements Persisten
public void setCreateTableOnStartup(boolean createTableOnStartup) {
this.createTableOnStartup = createTableOnStartup;
}
-
- //~ Inner Classes ==================================================================================================
-
- private class TokensBySeriesMapping extends MappingSqlQuery<PersistentRememberMeToken> {
- protected TokensBySeriesMapping(DataSource ds) {
- super(ds, tokensBySeriesSql);
- declareParameter(new SqlParameter(Types.VARCHAR));
- compile();
- }
-
- protected PersistentRememberMeToken mapRow(ResultSet rs, int rowNum) throws SQLException {
- PersistentRememberMeToken token =
- new PersistentRememberMeToken(rs.getString(1), rs.getString(2), rs.getString(3), rs.getTimestamp(4));
-
- return token;
- }
- }
-
- private class UpdateToken extends SqlUpdate {
-
- public UpdateToken(DataSource ds) {
- super(ds, updateTokenSql);
- setMaxRowsAffected(1);
- declareParameter(new SqlParameter(Types.VARCHAR));
- declareParameter(new SqlParameter(Types.TIMESTAMP));
- declareParameter(new SqlParameter(Types.VARCHAR));
- compile();
- }
- }
-
- private class InsertToken extends SqlUpdate {
-
- public InsertToken(DataSource ds) {
- super(ds, insertTokenSql);
- declareParameter(new SqlParameter(Types.VARCHAR));
- declareParameter(new SqlParameter(Types.VARCHAR));
- declareParameter(new SqlParameter(Types.VARCHAR));
- declareParameter(new SqlParameter(Types.TIMESTAMP));
- compile();
- }
- }
-
- private class RemoveUserTokens extends SqlUpdate {
- public RemoveUserTokens(DataSource ds) {
- super(ds, removeUserTokensSql);
- declareParameter(new SqlParameter(Types.VARCHAR));
- compile();
- }
- }
}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/rememberme/PersistentRememberMeToken.java b/dist/spring-security-web/org/springframework/security/web/authentication/rememberme/PersistentRememberMeToken.java
index ebab6da..7bf0556 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/rememberme/PersistentRememberMeToken.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/rememberme/PersistentRememberMeToken.java
@@ -6,10 +6,10 @@ import java.util.Date;
* @author Luke Taylor
*/
public class PersistentRememberMeToken {
- private String username;
- private String series;
- private String tokenValue;
- private Date date;
+ private final String username;
+ private final String series;
+ private final String tokenValue;
+ private final Date date;
public PersistentRememberMeToken(String username, String series, String tokenValue, Date date) {
this.username = username;
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/rememberme/PersistentTokenBasedRememberMeServices.java b/dist/spring-security-web/org/springframework/security/web/authentication/rememberme/PersistentTokenBasedRememberMeServices.java
index 0442294..c06d720 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/rememberme/PersistentTokenBasedRememberMeServices.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/rememberme/PersistentTokenBasedRememberMeServices.java
@@ -9,7 +9,8 @@ import javax.servlet.http.HttpServletResponse;
import org.springframework.dao.DataAccessException;
import org.springframework.security.core.Authentication;
-import org.springframework.security.core.codec.Base64;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.crypto.codec.Base64;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.RememberMeServices;
import org.springframework.util.Assert;
@@ -48,8 +49,19 @@ public class PersistentTokenBasedRememberMeServices extends AbstractRememberMeSe
private int seriesLength = DEFAULT_SERIES_LENGTH;
private int tokenLength = DEFAULT_TOKEN_LENGTH;
- public PersistentTokenBasedRememberMeServices() throws Exception {
- random = SecureRandom.getInstance("SHA1PRNG");
+ /**
+ * @deprecated Use constructor injection
+ */
+ @Deprecated
+ public PersistentTokenBasedRememberMeServices() {
+ random = new SecureRandom();
+ }
+
+ public PersistentTokenBasedRememberMeServices(String key, UserDetailsService userDetailsService,
+ PersistentTokenRepository tokenRepository) {
+ super(key, userDetailsService);
+ random = new SecureRandom();
+ this.tokenRepository = tokenRepository;
}
/**
@@ -112,9 +124,7 @@ public class PersistentTokenBasedRememberMeServices extends AbstractRememberMeSe
throw new RememberMeAuthenticationException("Autologin failed due to data access problem");
}
- UserDetails user = getUserDetailsService().loadUserByUsername(token.getUsername());
-
- return user;
+ return getUserDetailsService().loadUserByUsername(token.getUsername());
}
/**
@@ -134,7 +144,6 @@ public class PersistentTokenBasedRememberMeServices extends AbstractRememberMeSe
addCookie(persistentToken, request, response);
} catch (DataAccessException e) {
logger.error("Failed to save persistent token ", e);
-
}
}
@@ -163,6 +172,10 @@ public class PersistentTokenBasedRememberMeServices extends AbstractRememberMeSe
setCookie(new String[] {token.getSeries(), token.getTokenValue()}, getTokenValiditySeconds(), request, response);
}
+ /**
+ * @deprecated Use constructor injection
+ */
+ @Deprecated
public void setTokenRepository(PersistentTokenRepository tokenRepository) {
this.tokenRepository = tokenRepository;
}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/rememberme/RememberMeAuthenticationFilter.java b/dist/spring-security-web/org/springframework/security/web/authentication/rememberme/RememberMeAuthenticationFilter.java
index 31d74e4..bfba4e7 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/rememberme/RememberMeAuthenticationFilter.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/rememberme/RememberMeAuthenticationFilter.java
@@ -31,35 +31,55 @@ import org.springframework.security.authentication.event.InteractiveAuthenticati
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.RememberMeServices;
import org.springframework.util.Assert;
import org.springframework.web.filter.GenericFilterBean;
/**
- * Detects if there is no <code>Authentication</code> object in the <code>SecurityContext</code>, and populates it
- * with a remember-me authentication token if a {@link org.springframework.security.web.authentication.RememberMeServices}
- * implementation so requests.<p>Concrete <code>RememberMeServices</code> implementations will have their {@link
- * org.springframework.security.web.authentication.RememberMeServices#autoLogin(HttpServletRequest, HttpServletResponse)} method
- * called by this filter. The <code>Authentication</code> or <code>null</code> returned by that method will be placed
- * into the <code>SecurityContext</code>. The <code>AuthenticationManager</code> will be used, so that any concurrent
- * session management or other authentication-specific behaviour can be achieved. This is the same pattern as with
- * other authentication mechanisms, which call the <code>AuthenticationManager</code> as part of their contract.</p>
- * <p>If authentication is successful, an {@link
- * org.springframework.security.authentication.event.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>
+ * Detects if there is no {@code Authentication} object in the {@code SecurityContext}, and populates the context with
+ * a remember-me authentication token if a {@link RememberMeServices} implementation so requests.
+ * <p>
+ * Concrete {@code RememberMeServices} implementations will have their
+ * {@link RememberMeServices#autoLogin(HttpServletRequest, HttpServletResponse)}
+ * method called by this filter. If this method returns a non-null {@code Authentication} object, it will be passed
+ * to the {@code AuthenticationManager}, so that any authentication-specific behaviour can be achieved.
+ * The resulting {@code Authentication} (if successful) will be placed into the {@code SecurityContext}.
+ * <p>
+ * If authentication is successful, an {@link 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}-specific application event.
+ * <p>
+ * Normally the request will be allowed to proceed regardless of whether authentication succeeds or fails. If
+ * some control over the destination for authenticated users is required, an {@link AuthenticationSuccessHandler}
+ * can be injected
*
* @author Ben Alex
+ * @author Luke Taylor
*/
public class RememberMeAuthenticationFilter extends GenericFilterBean implements ApplicationEventPublisherAware {
//~ Instance fields ================================================================================================
private ApplicationEventPublisher eventPublisher;
+ private AuthenticationSuccessHandler successHandler;
private AuthenticationManager authenticationManager;
private RememberMeServices rememberMeServices;
+ /**
+ * @deprecated Use constructor injection
+ */
+ @Deprecated
+ public RememberMeAuthenticationFilter() {
+ }
+
+ public RememberMeAuthenticationFilter(AuthenticationManager authenticationManager,
+ RememberMeServices rememberMeServices) {
+ this.authenticationManager = authenticationManager;
+ this.rememberMeServices = rememberMeServices;
+ }
+
//~ Methods ========================================================================================================
@Override
@@ -96,6 +116,13 @@ public class RememberMeAuthenticationFilter extends GenericFilterBean implements
eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(
SecurityContextHolder.getContext().getAuthentication(), this.getClass()));
}
+
+ if (successHandler != null) {
+ successHandler.onAuthenticationSuccess(request, response, rememberMeAuth);
+
+ return;
+ }
+
} catch (AuthenticationException authenticationException) {
if (logger.isDebugEnabled()) {
logger.debug("SecurityContextHolder not populated with remember-me token, as "
@@ -121,17 +148,17 @@ public class RememberMeAuthenticationFilter extends GenericFilterBean implements
}
/**
- * Called if a remember-me token is presented and successfully authenticated by the <tt>RememberMeServices</tt>
- * <tt>autoLogin</tt> method and the <tt>AuthenticationManager</tt>.
+ * Called if a remember-me token is presented and successfully authenticated by the {@code RememberMeServices}
+ * {@code autoLogin} method and the {@code AuthenticationManager}.
*/
protected void onSuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
Authentication authResult) {
}
/**
- * Called if the <tt>AuthenticationManager</tt> rejects the authentication object returned from the
- * <tt>RememberMeServices</tt> <tt>autoLogin</tt> method. This method will not be called when no remember-me
- * token is present in the request and <tt>autoLogin</tt> returns null.
+ * Called if the {@code AuthenticationManager} rejects the authentication object returned from the
+ * {@code RememberMeServices} {@code autoLogin} method. This method will not be called when no remember-me
+ * token is present in the request and {@code autoLogin} reurns null.
*/
protected void onUnsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
AuthenticationException failed) {
@@ -145,11 +172,34 @@ public class RememberMeAuthenticationFilter extends GenericFilterBean implements
this.eventPublisher = eventPublisher;
}
+ /**
+ * @deprecated Use constructor injection
+ */
+ @Deprecated
public void setAuthenticationManager(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
+ /**
+ * @deprecated Use constructor injection
+ */
+ @Deprecated
public void setRememberMeServices(RememberMeServices rememberMeServices) {
this.rememberMeServices = rememberMeServices;
}
+
+ /**
+ * Allows control over the destination a remembered user is sent to when they are successfully authenticated.
+ * By default, the filter will just allow the current request to proceed, but if an
+ * {@code AuthenticationSuccessHandler} is set, it will be invoked and the {@code doFilter()} method will return
+ * immediately, thus allowing the application to redirect the user to a specific URL, regardless of whatthe original
+ * request was for.
+ *
+ * @param successHandler the strategy to invoke immediately before returning from {@code doFilter()}.
+ */
+ public void setAuthenticationSuccessHandler(AuthenticationSuccessHandler successHandler) {
+ Assert.notNull(successHandler, "successHandler cannot be null");
+ this.successHandler = successHandler;
+ }
+
}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/rememberme/TokenBasedRememberMeServices.java b/dist/spring-security-web/org/springframework/security/web/authentication/rememberme/TokenBasedRememberMeServices.java
index aa59a37..60708dd 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/rememberme/TokenBasedRememberMeServices.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/rememberme/TokenBasedRememberMeServices.java
@@ -16,13 +16,16 @@
package org.springframework.security.web.authentication.rememberme;
import org.springframework.security.core.Authentication;
-import org.springframework.security.core.codec.Hex;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.crypto.codec.Hex;
import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.crypto.codec.Utf8;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
@@ -79,8 +82,20 @@ import java.util.Date;
*/
public class TokenBasedRememberMeServices extends AbstractRememberMeServices {
+ /**
+ * @deprecated Use with-args constructor
+ */
+ @Deprecated
+ public TokenBasedRememberMeServices() {
+ }
+
+ public TokenBasedRememberMeServices(String key, UserDetailsService userDetailsService) {
+ super(key, userDetailsService);
+ }
+
//~ Methods ========================================================================================================
+ @Override
protected UserDetails processAutoLoginCookie(String[] cookieTokens, HttpServletRequest request,
HttpServletResponse response) {
@@ -117,9 +132,9 @@ public class TokenBasedRememberMeServices extends AbstractRememberMeServices {
String expectedTokenSignature = makeTokenSignature(tokenExpiryTime, userDetails.getUsername(),
userDetails.getPassword());
- if (!expectedTokenSignature.equals(cookieTokens[2])) {
+ if (!equals(expectedTokenSignature,cookieTokens[2])) {
throw new InvalidCookieException("Cookie token[2] contained signature '" + cookieTokens[2]
- + "' but expected '" + expectedTokenSignature + "'");
+ + "' but expected '" + expectedTokenSignature + "'");
}
return userDetails;
@@ -145,6 +160,7 @@ public class TokenBasedRememberMeServices extends AbstractRememberMeServices {
return tokenExpiryTime < System.currentTimeMillis();
}
+ @Override
public void onLoginSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication successfulAuthentication) {
@@ -153,10 +169,21 @@ public class TokenBasedRememberMeServices extends AbstractRememberMeServices {
// If unable to find a username and password, just abort as TokenBasedRememberMeServices is
// unable to construct a valid token in this case.
- if (!StringUtils.hasLength(username) || !StringUtils.hasLength(password)) {
+ if (!StringUtils.hasLength(username)) {
+ logger.debug("Unable to retrieve username");
return;
}
+ if (!StringUtils.hasLength(password)) {
+ UserDetails user = getUserDetailsService().loadUserByUsername(username);
+ password = user.getPassword();
+
+ if (!StringUtils.hasLength(password)) {
+ logger.debug("Unable to obtain password for user: " + username);
+ return;
+ }
+ }
+
int tokenLifetime = calculateLoginLifetime(request, successfulAuthentication);
long expiryTime = System.currentTimeMillis();
// SEC-949
@@ -216,4 +243,28 @@ public class TokenBasedRememberMeServices extends AbstractRememberMeServices {
private boolean isInstanceOfUserDetails(Authentication authentication) {
return authentication.getPrincipal() instanceof UserDetails;
}
+
+ /**
+ * Constant time comparison to prevent against timing attacks.
+ */
+ private static boolean equals(String expected, String actual) {
+ byte[] expectedBytes = bytesUtf8(expected);
+ byte[] actualBytes = bytesUtf8(actual);
+ if (expectedBytes.length != actualBytes.length) {
+ return false;
+ }
+
+ int result = 0;
+ for (int i = 0; i < expectedBytes.length; i++) {
+ result |= expectedBytes[i] ^ actualBytes[i];
+ }
+ return result == 0;
+ }
+
+ private static byte[] bytesUtf8(String s) {
+ if (s == null) {
+ return null;
+ }
+ return Utf8.encode(s);
+ }
}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/session/ConcurrentSessionControlStrategy.java b/dist/spring-security-web/org/springframework/security/web/authentication/session/ConcurrentSessionControlStrategy.java
index ae9f14c..75e2685 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/session/ConcurrentSessionControlStrategy.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/session/ConcurrentSessionControlStrategy.java
@@ -123,18 +123,18 @@ public class ConcurrentSessionControlStrategy extends SessionFixationProtectionS
protected void allowableSessionsExceeded(List<SessionInformation> sessions, int allowableSessions,
SessionRegistry registry) throws SessionAuthenticationException {
if (exceptionIfMaximumExceeded || (sessions == null)) {
- throw new SessionAuthenticationException(messages.getMessage("ConcurrentSessionControllerImpl.exceededAllowed",
- new Object[] {new Integer(allowableSessions)},
+ throw new SessionAuthenticationException(messages.getMessage("ConcurrentSessionControlStrategy.exceededAllowed",
+ new Object[] {Integer.valueOf(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.size(); i++) {
+ for (SessionInformation session : sessions) {
if ((leastRecentlyUsed == null)
- || sessions.get(i).getLastRequest().before(leastRecentlyUsed.getLastRequest())) {
- leastRecentlyUsed = sessions.get(i);
+ || session.getLastRequest().before(leastRecentlyUsed.getLastRequest())) {
+ leastRecentlyUsed = session;
}
}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/session/SessionFixationProtectionStrategy.java b/dist/spring-security-web/org/springframework/security/web/authentication/session/SessionFixationProtectionStrategy.java
index 1d84114..ffea758 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/session/SessionFixationProtectionStrategy.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/session/SessionFixationProtectionStrategy.java
@@ -1,32 +1,39 @@
package org.springframework.security.web.authentication.session;
-import java.util.Arrays;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.security.core.Authentication;
+import org.springframework.util.Assert;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.web.WebAttributes;
+import java.util.*;
/**
* The default implementation of {@link SessionAuthenticationStrategy}.
* <p>
* Creates a new session for the newly authenticated user if they already have a session (as a defence against
- * session-fixation protection attacks), and copies their
- * session attributes across to the new session (can be disabled by setting <tt>migrateSessionAttributes</tt> to
- * <tt>false</tt>).
+ * session-fixation protection attacks), and copies their session attributes across to the new session.
+ * The copying of the attributes can be disabled by setting {@code migrateSessionAttributes} to {@code false}
+ * (note that even in this case, internal Spring Security attributes will still be migrated to the new session).
* <p>
* This approach will only be effective if your servlet container always assigns a new session Id when a session is
* invalidated and a new session created by calling {@link HttpServletRequest#getSession()}.
* <p>
- * If concurrent session control is in use, then a <tt>SessionRegistry</tt> must be injected.
+ * If concurrent session control is in use, then a {@code SessionRegistry} must be injected.
+ * <p>
+ * <h3>Issues with {@code HttpSessionBindingListener}</h3>
+ * <p>
+ * The migration of existing attributes to the newly-created session may cause problems if any of the objects
+ * implement the {@code HttpSessionBindingListener} interface in a way which makes assumptions about the life-cycle of
+ * the object. An example is the use of Spring session-scoped beans, where the initial removal of the bean from the
+ * session will cause the {@code DisposableBean} interface to be invoked, in the assumption that the bean is no longer
+ * required.
+ * <p>
+ * We'd recommend that you take account of this when designing your application and do not store attributes which
+ * may not function correctly when they are removed and then placed back in the session. Alternatively, you should
+ * customize the {@code SessionAuthenticationStrategy} to deal with the issue in an application-specific way.
*
* @author Luke Taylor
* @since 3.0
@@ -44,11 +51,11 @@ public class SessionFixationProtectionStrategy implements SessionAuthenticationS
* In the case where the attributes will not be migrated, this field allows a list of named attributes
* which should <em>not</em> be discarded.
*/
- private List<String> retainedAttributes = Arrays.asList(WebAttributes.SAVED_REQUEST);
+ private List<String> retainedAttributes = null;
/**
- * If set to <tt>true</tt>, a session will always be created, even if one didn't exist at the start of the request.
- * Defaults to <tt>false</tt>.
+ * If set to {@code true}, a session will always be created, even if one didn't exist at the start of the request.
+ * Defaults to {@code false}.
*/
private boolean alwaysCreateSession;
@@ -56,12 +63,12 @@ public class SessionFixationProtectionStrategy implements SessionAuthenticationS
* Called when a user is newly authenticated.
* <p>
* If a session already exists, and matches the session Id from the client, a new session will be created, and the
- * session attributes copied to it (if <tt>migrateSessionAttributes</tt> is set).
+ * session attributes copied to it (if {@code migrateSessionAttributes} is set).
* The sessionRegistry will be updated with the new session information. If the client's requested session Id is
* invalid, nothing will be done, since there is no need to change the session Id if it doesn't match the current
* session.
* <p>
- * If there is no session, no action is taken unless the <tt>alwaysCreateSession</tt> property is set, in which
+ * If there is no session, no action is taken unless the {@code alwaysCreateSession} property is set, in which
* case a session will be created if one doesn't already exist.
*/
public void onAuthentication(Authentication authentication, HttpServletRequest request, HttpServletResponse response) {
@@ -85,7 +92,7 @@ public class SessionFixationProtectionStrategy implements SessionAuthenticationS
"and" : "without") + " migrating attributes.");
}
- HashMap<String, Object> attributesToMigrate = createMigratedAttributeMap(session);
+ Map<String, Object> attributesToMigrate = extractAttributes(session);
session.invalidate();
session = request.getSession(true); // we now have a new session
@@ -99,12 +106,9 @@ public class SessionFixationProtectionStrategy implements SessionAuthenticationS
" not be adequately protected against session-fixation attacks");
}
- // Copy attributes to new session
- if (attributesToMigrate != null) {
- for (Map.Entry<String, Object> entry : attributesToMigrate.entrySet()) {
- session.setAttribute(entry.getKey(), entry.getValue());
- }
- }
+ transferAttributes(attributesToMigrate, session);
+
+ onSessionChange(originalSessionId, session, authentication);
}
}
@@ -119,17 +123,47 @@ public class SessionFixationProtectionStrategy implements SessionAuthenticationS
protected void onSessionChange(String originalSessionId, HttpSession newSession, Authentication auth) {
}
+ /**
+ * Called to extract the existing attributes from the session, prior to invalidating it. If
+ * {@code migrateAttributes} is set to {@code false}, only Spring Security attributes will be retained.
+ * All application attributes will be discarded.
+ * <p>
+ * You can override this method to control exactly what is transferred to the new session.
+ *
+ * @param session the session from which the attributes should be extracted
+ * @return the map of session attributes which should be transferred to the new session
+ */
+ protected Map<String, Object> extractAttributes(HttpSession session) {
+ return createMigratedAttributeMap(session);
+ }
+
+ /**
+ * @param attributes the attributes which were extracted from the original session by {@code extractAttributes}
+ * @param newSession the newly created session
+ */
+ private void transferAttributes(Map<String, Object> attributes, HttpSession newSession) {
+ if (attributes != null) {
+ for (Map.Entry<String, Object> entry : attributes.entrySet()) {
+ newSession.setAttribute(entry.getKey(), entry.getValue());
+ }
+ }
+ }
+
@SuppressWarnings("unchecked")
private HashMap<String, Object> createMigratedAttributeMap(HttpSession session) {
HashMap<String, Object> attributesToMigrate = null;
- if (migrateSessionAttributes) {
+ if (migrateSessionAttributes || retainedAttributes == null) {
attributesToMigrate = new HashMap<String, Object>();
Enumeration enumer = session.getAttributeNames();
while (enumer.hasMoreElements()) {
String key = (String) enumer.nextElement();
+ if (!migrateSessionAttributes && !key.startsWith("SPRING_SECURITY_")) {
+ // Only retain Spring Security attributes
+ continue;
+ }
attributesToMigrate.put(key, session.getAttribute(key));
}
} else {
@@ -148,11 +182,27 @@ public class SessionFixationProtectionStrategy implements SessionAuthenticationS
return attributesToMigrate;
}
+ /**
+ * Defines whether attributes should be migrated to a new session or not. Has no effect if you
+ * override the {@code extractAttributes} method.
+ * <p>
+ * Attributes used by Spring Security (to store cached requests, for example) will still be retained by default,
+ * even if you set this value to {@code false}.
+ *
+ * @param migrateSessionAttributes whether the attributes from the session should be transferred to the new,
+ * authenticated session.
+ */
public void setMigrateSessionAttributes(boolean migrateSessionAttributes) {
this.migrateSessionAttributes = migrateSessionAttributes;
}
+ /**
+ * @deprecated Override the {@code extractAttributes} method instead
+ */
+ @Deprecated
public void setRetainedAttributes(List<String> retainedAttributes) {
+ logger.warn("Retained attributes is deprecated. Override the extractAttributes() method instead.");
+ Assert.notNull(retainedAttributes);
this.retainedAttributes = retainedAttributes;
}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/switchuser/AuthenticationSwitchUserEvent.java b/dist/spring-security-web/org/springframework/security/web/authentication/switchuser/AuthenticationSwitchUserEvent.java
index b4361a9..ab68b45 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/switchuser/AuthenticationSwitchUserEvent.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/switchuser/AuthenticationSwitchUserEvent.java
@@ -29,7 +29,7 @@ import org.springframework.security.core.userdetails.UserDetails;
public class AuthenticationSwitchUserEvent extends AbstractAuthenticationEvent {
//~ Instance fields ================================================================================================
- private UserDetails targetUser;
+ private final UserDetails targetUser;
//~ Constructors ===================================================================================================
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/switchuser/SwitchUserAuthorityChanger.java b/dist/spring-security-web/org/springframework/security/web/authentication/switchuser/SwitchUserAuthorityChanger.java
index 41ed21a..699a4de 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/switchuser/SwitchUserAuthorityChanger.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/switchuser/SwitchUserAuthorityChanger.java
@@ -22,10 +22,10 @@ public interface SwitchUserAuthorityChanger {
*
* @param targetUser the UserDetails representing the identity being switched to
* @param currentAuthentication the current Authentication of the principal performing the switching
- * @param authoritiesToBeGranted all {@link GrantedAuthority} instances to be granted to the user,
+ * @param authoritiesToBeGranted all {@link org.springframework.security.core.GrantedAuthority} instances to be granted to the user,
* excluding the special "switch user" authority that is used internally (guaranteed never null)
*
* @return the modified list of granted authorities.
*/
- Collection<GrantedAuthority> modifyGrantedAuthorities(UserDetails targetUser, Authentication currentAuthentication, Collection<GrantedAuthority> authoritiesToBeGranted);
+ Collection<? extends GrantedAuthority> modifyGrantedAuthorities(UserDetails targetUser, Authentication currentAuthentication, Collection<? extends GrantedAuthority> authoritiesToBeGranted);
}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/switchuser/SwitchUserFilter.java b/dist/spring-security-web/org/springframework/security/web/authentication/switchuser/SwitchUserFilter.java
index e140e49..9cdf90e 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/switchuser/SwitchUserFilter.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/switchuser/SwitchUserFilter.java
@@ -75,11 +75,13 @@ import org.springframework.web.filter.GenericFilterBean;
* <b>Note: This URL will be required to have appropriate security constraints configured so that only users of that
* role can access it (e.g. ROLE_ADMIN).</b>
* <p>
- * On a successful switch, the user's <code>SecurityContextHolder</code> will be updated to reflect the
+ * On a successful switch, the user's <code>SecurityContext</code> will be updated to reflect the
* specified user and will also contain an additional
* {@link org.springframework.security.web.authentication.switchuser.SwitchUserGrantedAuthority} which contains the original user.
+ * Before switching, a check will be made on whether the user is already currently switched, and any current switch will
+ * be exited to prevent "nested" switches.
* <p>
- * To 'exit' from a user context, the user will then need to access a URL (see <code>exitUserUrl</code>) that
+ * To 'exit' from a user context, the user needs to access a URL (see <code>exitUserUrl</code>) that
* will switch back to the original user as identified by the <code>ROLE_PREVIOUS_ADMINISTRATOR</code>.
* <p>
* To configure the Switch User Processing Filter, create a bean definition for the Switch User processing
@@ -109,12 +111,13 @@ public class SwitchUserFilter extends GenericFilterBean implements ApplicationEv
//~ Instance fields ================================================================================================
private ApplicationEventPublisher eventPublisher;
- private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource();
+ private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = new WebAuthenticationDetailsSource();
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
private String exitUserUrl = "/j_spring_security_exit_user";
private String switchUserUrl = "/j_spring_security_switch_user";
private String targetUrl;
private String switchFailureUrl;
+ private String usernameParameter = SPRING_SECURITY_SWITCH_USERNAME_KEY;
private SwitchUserAuthorityChanger switchUserAuthorityChanger;
private UserDetailsService userDetailsService;
private UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker();
@@ -191,9 +194,9 @@ public class SwitchUserFilter extends GenericFilterBean implements ApplicationEv
* @throws CredentialsExpiredException If the target user credentials are expired.
*/
protected Authentication attemptSwitchUser(HttpServletRequest request) throws AuthenticationException {
- UsernamePasswordAuthenticationToken targetUserRequest = null;
+ UsernamePasswordAuthenticationToken targetUserRequest;
- String username = request.getParameter(SPRING_SECURITY_SWITCH_USERNAME_KEY);
+ String username = request.getParameter(usernameParameter);
if (username == null) {
username = "";
@@ -287,11 +290,20 @@ public class SwitchUserFilter extends GenericFilterBean implements ApplicationEv
// 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();
+
+ Authentication currentAuth;
+
+ try {
+ // SEC-1763. Check first if we are already switched.
+ currentAuth = attemptExitUser(request);
+ } catch (AuthenticationCredentialsNotFoundException e) {
+ currentAuth = SecurityContextHolder.getContext().getAuthentication();
+ }
+
GrantedAuthority switchAuthority = new SwitchUserGrantedAuthority(ROLE_PREVIOUS_ADMINISTRATOR, currentAuth);
// get the original authorities
- Collection<GrantedAuthority> orig = targetUser.getAuthorities();
+ Collection<? extends GrantedAuthority> orig = targetUser.getAuthorities();
// Allow subclasses to change the authorities to be granted
if (switchUserAuthorityChanger != null) {
@@ -324,7 +336,7 @@ public class SwitchUserFilter extends GenericFilterBean implements ApplicationEv
Authentication original = null;
// iterate over granted authorities and find the 'switch user' authority
- Collection<GrantedAuthority> authorities = current.getAuthorities();
+ Collection<? extends GrantedAuthority> authorities = current.getAuthorities();
for (GrantedAuthority auth : authorities) {
// check for switch user type of authority
@@ -372,7 +384,7 @@ public class SwitchUserFilter extends GenericFilterBean implements ApplicationEv
this.eventPublisher = eventPublisher;
}
- public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) {
+ public void setAuthenticationDetailsSource(AuthenticationDetailsSource<HttpServletRequest,?> authenticationDetailsSource) {
Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required");
this.authenticationDetailsSource = authenticationDetailsSource;
}
@@ -475,6 +487,15 @@ public class SwitchUserFilter extends GenericFilterBean implements ApplicationEv
}
/**
+ * Allows the parameter containing the username to be customized.
+ *
+ * @param usernameParameter the parameter name. Defaults to {@code j_username}
+ */
+ public void setUsernameParameter(String usernameParameter) {
+ this.usernameParameter = usernameParameter;
+ }
+
+ /**
* Strips any content after the ';' in the request URI
*
* @param request The http request
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/switchuser/SwitchUserGrantedAuthority.java b/dist/spring-security-web/org/springframework/security/web/authentication/switchuser/SwitchUserGrantedAuthority.java
index a8d2a85..2ade561 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/switchuser/SwitchUserGrantedAuthority.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/switchuser/SwitchUserGrantedAuthority.java
@@ -16,27 +16,32 @@
package org.springframework.security.web.authentication.switchuser;
import org.springframework.security.core.Authentication;
-import org.springframework.security.core.authority.GrantedAuthorityImpl;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.SpringSecurityCoreVersion;
/**
- * Custom <code>GrantedAuthority</code> used by {@link org.springframework.security.web.authentication.switchuser.SwitchUserFilter}<p>Stores
- * the <code>Authentication</code> object of the original user to be used later when 'exiting' from a user switch.</p>
+ * Custom {@code GrantedAuthority} used by
+ * {@link org.springframework.security.web.authentication.switchuser.SwitchUserFilter}
+ * <p>
+ * Stores the {@code Authentication} object of the original user to be used later when 'exiting' from a user switch.
*
* @author Mark St.Godard
*
* @see org.springframework.security.web.authentication.switchuser.SwitchUserFilter
*/
-public class SwitchUserGrantedAuthority extends GrantedAuthorityImpl {
- //~ Instance fields ================================================================================================
+public final class SwitchUserGrantedAuthority implements GrantedAuthority {
+
+ private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
- private static final long serialVersionUID = 1L;
- private Authentication source;
+ //~ Instance fields ================================================================================================
+ private final String role;
+ private final Authentication source;
//~ Constructors ===================================================================================================
public SwitchUserGrantedAuthority(String role, Authentication source) {
- super(role);
+ this.role = role;
this.source = source;
}
@@ -50,4 +55,29 @@ public class SwitchUserGrantedAuthority extends GrantedAuthorityImpl {
public Authentication getSource() {
return source;
}
+
+ public String getAuthority() {
+ return role;
+ }
+
+ public int hashCode() {
+ return 31 ^ source.hashCode() ^ role.hashCode();
+ }
+
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj instanceof SwitchUserGrantedAuthority) {
+ SwitchUserGrantedAuthority swa = (SwitchUserGrantedAuthority) obj;
+ return this.role.equals(swa.role) && this.source.equals(swa.source);
+ }
+
+ return false;
+ }
+
+ public String toString() {
+ return "Switch User Authority [" + role + "," + source + "]" ;
+ }
}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/ui/DefaultLoginPageGeneratingFilter.java b/dist/spring-security-web/org/springframework/security/web/authentication/ui/DefaultLoginPageGeneratingFilter.java
index bd00973..ff9d065 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/ui/DefaultLoginPageGeneratingFilter.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/ui/DefaultLoginPageGeneratingFilter.java
@@ -94,18 +94,13 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
private String generateLoginPageHtml(HttpServletRequest request) {
boolean loginError = request.getParameter(ERROR_PARAMETER_NAME) != null;
String errorMsg = "none";
- String lastUser = "";
if (loginError) {
HttpSession session = request.getSession(false);
if(session != null) {
- lastUser = (String) session.getAttribute(UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_USERNAME_KEY);
AuthenticationException ex = (AuthenticationException) session.getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
errorMsg = ex != null ? ex.getMessage() : "none";
- if (lastUser == null) {
- lastUser = "";
- }
}
}
@@ -128,15 +123,14 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
sb.append("<form name='f' action='").append(request.getContextPath()).append(authenticationUrl).append("' method='POST'>\n");
sb.append(" <table>\n");
sb.append(" <tr><td>User:</td><td><input type='text' name='");
- sb.append(usernameParameter).append("' value='").append(lastUser).append("'></td></tr>\n");
+ sb.append(usernameParameter).append("' value='").append("'></td></tr>\n");
sb.append(" <tr><td>Password:</td><td><input type='password' name='").append(passwordParameter).append("'/></td></tr>\n");
if (rememberMeParameter != null) {
sb.append(" <tr><td><input type='checkbox' name='").append(rememberMeParameter).append("'/></td><td>Remember me on this computer.</td></tr>\n");
}
- sb.append(" <tr><td colspan='2'><input name=\"submit\" type=\"submit\"/></td></tr>\n");
- sb.append(" <tr><td colspan='2'><input name=\"reset\" type=\"reset\"/></td></tr>\n");
+ sb.append(" <tr><td colspan='2'><input name=\"submit\" type=\"submit\" value=\"Login\"/></td></tr>\n");
sb.append(" </table>\n");
sb.append("</form>");
}
@@ -145,15 +139,14 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
sb.append("<h3>Login with OpenID Identity</h3>");
sb.append("<form name='oidf' action='").append(request.getContextPath()).append(openIDauthenticationUrl).append("' method='POST'>\n");
sb.append(" <table>\n");
- sb.append(" <tr><td>Identity:</td><td><input type='text' name='");
+ sb.append(" <tr><td>Identity:</td><td><input type='text' size='30' name='");
sb.append(openIDusernameParameter).append("'/></td></tr>\n");
if (openIDrememberMeParameter != null) {
sb.append(" <tr><td><input type='checkbox' name='").append(openIDrememberMeParameter).append("'></td><td>Remember me on this computer.</td></tr>\n");
}
- sb.append(" <tr><td colspan='2'><input name=\"submit\" type=\"submit\"/></td></tr>\n");
- sb.append(" <tr><td colspan='2'><input name=\"reset\" type=\"reset\"/></td></tr>\n");
+ sb.append(" <tr><td colspan='2'><input name=\"submit\" type=\"submit\" value=\"Login\"/></td></tr>\n");
sb.append(" </table>\n");
sb.append("</form>");
}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/www/BasicAuthenticationEntryPoint.java b/dist/spring-security-web/org/springframework/security/web/authentication/www/BasicAuthenticationEntryPoint.java
index 9b7e59f..35c2645 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/www/BasicAuthenticationEntryPoint.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/www/BasicAuthenticationEntryPoint.java
@@ -49,10 +49,9 @@ public class BasicAuthenticationEntryPoint implements AuthenticationEntryPoint,
}
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)
- throws IOException, ServletException {
- HttpServletResponse httpResponse = (HttpServletResponse) response;
- httpResponse.addHeader("WWW-Authenticate", "Basic realm=\"" + realmName + "\"");
- httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage());
+ throws IOException, ServletException {
+ response.addHeader("WWW-Authenticate", "Basic realm=\"" + realmName + "\"");
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage());
}
public String getRealmName() {
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/www/BasicAuthenticationFilter.java b/dist/spring-security-web/org/springframework/security/web/authentication/www/BasicAuthenticationFilter.java
index 6418564..ab1db4c 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/www/BasicAuthenticationFilter.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/www/BasicAuthenticationFilter.java
@@ -27,10 +27,11 @@ import javax.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
-import org.springframework.security.core.codec.Base64;
+import org.springframework.security.crypto.codec.Base64;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.NullRememberMeServices;
@@ -88,13 +89,44 @@ public class BasicAuthenticationFilter extends GenericFilterBean {
//~ Instance fields ================================================================================================
- private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource();
+ private AuthenticationDetailsSource<HttpServletRequest,?> authenticationDetailsSource = new WebAuthenticationDetailsSource();
private AuthenticationEntryPoint authenticationEntryPoint;
private AuthenticationManager authenticationManager;
private RememberMeServices rememberMeServices = new NullRememberMeServices();
private boolean ignoreFailure = false;
private String credentialsCharset = "UTF-8";
+ /**
+ * @deprecated Use constructor injection
+ */
+ public BasicAuthenticationFilter() {
+ }
+
+ /**
+ * Creates an instance which will authenticate against the supplied {@code AuthenticationManager}
+ * and which will ignore failed authentication attempts, allowing the request to proceed down the filter chain.
+ *
+ * @param authenticationManager the bean to submit authentication requests to
+ */
+ public BasicAuthenticationFilter(AuthenticationManager authenticationManager) {
+ this.authenticationManager = authenticationManager;
+ ignoreFailure = true;
+ }
+
+ /**
+ * Creates an instance which will authenticate against the supplied {@code AuthenticationManager} and
+ * use the supplied {@code AuthenticationEntryPoint} to handle authentication failures.
+ *
+ * @param authenticationManager the bean to submit authentication requests to
+ * @param authenticationEntryPoint will be invoked when authentication fails. Typically an instance of
+ * {@link BasicAuthenticationEntryPoint}.
+ */
+ public BasicAuthenticationFilter(AuthenticationManager authenticationManager,
+ AuthenticationEntryPoint authenticationEntryPoint) {
+ this.authenticationManager = authenticationManager;
+ this.authenticationEntryPoint = authenticationEntryPoint;
+ }
+
//~ Methods ========================================================================================================
@Override
@@ -114,18 +146,16 @@ public class BasicAuthenticationFilter extends GenericFilterBean {
String header = request.getHeader("Authorization");
- if ((header != null) && header.startsWith("Basic ")) {
- byte[] base64Token = header.substring(6).getBytes("UTF-8");
- String token = new String(Base64.decode(base64Token), getCredentialsCharset(request));
+ if (header == null || !header.startsWith("Basic ")) {
+ chain.doFilter(request, response);
+ return;
+ }
- String username = "";
- String password = "";
- int delim = token.indexOf(":");
+ try {
+ String[] tokens = extractAndDecodeHeader(header, request);
+ assert tokens.length == 2;
- if (delim != -1) {
- username = token.substring(0, delim);
- password = token.substring(delim + 1);
- }
+ String username = tokens[0];
if (debug) {
logger.debug("Basic Authentication Authorization header found for user '" + username + "'");
@@ -133,37 +163,12 @@ public class BasicAuthenticationFilter extends GenericFilterBean {
if (authenticationIsRequired(username)) {
UsernamePasswordAuthenticationToken authRequest =
- new UsernamePasswordAuthenticationToken(username, password);
+ new UsernamePasswordAuthenticationToken(username, tokens[1]);
authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
+ Authentication authResult = authenticationManager.authenticate(authRequest);
- Authentication authResult;
-
- try {
- authResult = authenticationManager.authenticate(authRequest);
- } catch (AuthenticationException failed) {
- // Authentication failed
- if (debug) {
- logger.debug("Authentication request for user: " + username + " failed: " + failed.toString());
- }
-
- SecurityContextHolder.getContext().setAuthentication(null);
-
- rememberMeServices.loginFail(request, response);
-
- onUnsuccessfulAuthentication(request, response, failed);
-
- if (ignoreFailure) {
- chain.doFilter(request, response);
- } else {
- authenticationEntryPoint.commence(request, response, failed);
- }
-
- return;
- }
-
- // Authentication success
if (debug) {
- logger.debug("Authentication success: " + authResult.toString());
+ logger.debug("Authentication success: " + authResult);
}
SecurityContextHolder.getContext().setAuthentication(authResult);
@@ -172,11 +177,55 @@ public class BasicAuthenticationFilter extends GenericFilterBean {
onSuccessfulAuthentication(request, response, authResult);
}
+
+ } catch (AuthenticationException failed) {
+ SecurityContextHolder.clearContext();
+
+ if (debug) {
+ logger.debug("Authentication request for failed: " + failed);
+ }
+
+ rememberMeServices.loginFail(request, response);
+
+ onUnsuccessfulAuthentication(request, response, failed);
+
+ if (ignoreFailure) {
+ chain.doFilter(request, response);
+ } else {
+ authenticationEntryPoint.commence(request, response, failed);
+ }
+
+ return;
}
chain.doFilter(request, response);
}
+ /**
+ * Decodes the header into a username and password.
+ *
+ * @throws BadCredentialsException if the Basic header is not present or is not valid Base64
+ */
+ private String[] extractAndDecodeHeader(String header, HttpServletRequest request) throws IOException {
+
+ byte[] base64Token = header.substring(6).getBytes("UTF-8");
+ byte[] decoded;
+ try {
+ decoded = Base64.decode(base64Token);
+ } catch (IllegalArgumentException e) {
+ throw new BadCredentialsException("Failed to decode basic authentication token");
+ }
+
+ String token = new String(decoded, getCredentialsCharset(request));
+
+ int delim = token.indexOf(":");
+
+ if (delim == -1) {
+ throw new BadCredentialsException("Invalid basic authentication token");
+ }
+ return new String[] {token.substring(0, delim), token.substring(delim + 1)};
+ }
+
private boolean authenticationIsRequired(String username) {
// Only reauthenticate if username doesn't match SecurityContextHolder and user isn't authenticated
// (see SEC-53)
@@ -219,6 +268,10 @@ public class BasicAuthenticationFilter extends GenericFilterBean {
return authenticationEntryPoint;
}
+ /**
+ * @deprecated Use constructor injection
+ */
+ @Deprecated
public void setAuthenticationEntryPoint(AuthenticationEntryPoint authenticationEntryPoint) {
this.authenticationEntryPoint = authenticationEntryPoint;
}
@@ -227,6 +280,10 @@ public class BasicAuthenticationFilter extends GenericFilterBean {
return authenticationManager;
}
+ /**
+ * @deprecated Use constructor injection
+ */
+ @Deprecated
public void setAuthenticationManager(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
@@ -235,11 +292,16 @@ public class BasicAuthenticationFilter extends GenericFilterBean {
return ignoreFailure;
}
+ /**
+ *
+ * @deprecated Use the constructor which takes a single AuthenticationManager parameter
+ */
+ @Deprecated
public void setIgnoreFailure(boolean ignoreFailure) {
this.ignoreFailure = ignoreFailure;
}
- public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) {
+ public void setAuthenticationDetailsSource(AuthenticationDetailsSource<HttpServletRequest,?> authenticationDetailsSource) {
Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required");
this.authenticationDetailsSource = authenticationDetailsSource;
}
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/www/DigestAuthUtils.java b/dist/spring-security-web/org/springframework/security/web/authentication/www/DigestAuthUtils.java
index 9bb5edf..1c6cac5 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/www/DigestAuthUtils.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/www/DigestAuthUtils.java
@@ -7,7 +7,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import org.springframework.security.core.codec.Hex;
+import org.springframework.security.crypto.codec.Hex;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -17,9 +17,8 @@ final class DigestAuthUtils {
static String encodePasswordInA1Format(String username, String realm, String password) {
String a1 = username + ":" + realm + ":" + password;
- String a1Md5 = md5Hex(a1);
- return a1Md5;
+ return md5Hex(a1);
}
static String[] splitIgnoringQuotes(String str, char separatorChar) {
@@ -91,7 +90,7 @@ final class DigestAuthUtils {
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 a1Md5;
String a2 = httpMethod + ":" + uri;
String a2Md5 = md5Hex(a2);
@@ -113,9 +112,7 @@ final class DigestAuthUtils {
throw new IllegalArgumentException("This method does not support a qop: '" + qop + "'");
}
- String digestMd5 = new String(md5Hex(digest));
-
- return digestMd5;
+ return md5Hex(digest);
}
/**
@@ -138,13 +135,13 @@ final class DigestAuthUtils {
Map<String, String> map = new HashMap<String, String>();
- for (int i = 0; i < array.length; i++) {
+ for (String s : array) {
String postRemove;
if (removeCharacters == null) {
- postRemove = array[i];
+ postRemove = s;
} else {
- postRemove = StringUtils.replace(array[i], removeCharacters, "");
+ postRemove = StringUtils.replace(s, removeCharacters, "");
}
String[] splitThisArrayElement = split(postRemove, delimiter);
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/www/DigestAuthenticationEntryPoint.java b/dist/spring-security-web/org/springframework/security/web/authentication/www/DigestAuthenticationEntryPoint.java
index 7729b4a..c6c8417 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/www/DigestAuthenticationEntryPoint.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/www/DigestAuthenticationEntryPoint.java
@@ -26,17 +26,19 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.Ordered;
import org.springframework.security.core.AuthenticationException;
-import org.springframework.security.core.codec.Base64;
+import org.springframework.security.crypto.codec.Base64;
import org.springframework.security.web.AuthenticationEntryPoint;
/**
* Used by the <code>SecurityEnforcementFilter</code> to commence authentication via the {@link
- * DigestAuthenticationFilter}.<p>The nonce sent back to the user agent will be valid for the period indicated by
+ * DigestAuthenticationFilter}.
+ * <p>
+ * The nonce sent back to the user agent will be valid for the period indicated by
* {@link #setNonceValiditySeconds(int)}. By default this is 300 seconds. Shorter times should be used if replay
* attacks are a major concern. Larger values can be used if performance is a greater concern. This class correctly
- * presents the <code>stale=true</code> header when the nonce has expierd, so properly implemented user agents will
- * automatically renegotiate with a new nonce value (ie without presenting a new password dialog box to the user).</p>
+ * presents the <code>stale=true</code> header when the nonce has expired, so properly implemented user agents will
+ * automatically renegotiate with a new nonce value (i.e. without presenting a new password dialog box to the user).
*
* @author Ben Alex
*/
@@ -80,7 +82,7 @@ public class DigestAuthenticationEntryPoint implements AuthenticationEntryPoint,
// format of nonce is:
// base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key))
long expiryTime = System.currentTimeMillis() + (nonceValiditySeconds * 1000);
- String signatureValue = new String(DigestAuthUtils.md5Hex(expiryTime + ":" + key));
+ String signatureValue = DigestAuthUtils.md5Hex(expiryTime + ":" + key);
String nonceValue = expiryTime + ":" + signatureValue;
String nonceValueBase64 = new String(Base64.encode(nonceValue.getBytes()));
diff --git a/dist/spring-security-web/org/springframework/security/web/authentication/www/DigestAuthenticationFilter.java b/dist/spring-security-web/org/springframework/security/web/authentication/www/DigestAuthenticationFilter.java
index 8c226c7..ced3790 100644
--- a/dist/spring-security-web/org/springframework/security/web/authentication/www/DigestAuthenticationFilter.java
+++ b/dist/spring-security-web/org/springframework/security/web/authentication/www/DigestAuthenticationFilter.java
@@ -34,9 +34,10 @@ import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.SpringSecurityMessageSource;
-import org.springframework.security.core.codec.Base64;
+import org.springframework.security.crypto.codec.Base64;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserCache;
import org.springframework.security.core.userdetails.UserDetails;
@@ -74,6 +75,10 @@ import org.springframework.web.filter.GenericFilterBean;
* Note there are limitations to Digest authentication, although it is a more comprehensive and secure solution
* than Basic authentication. Please see RFC 2617 section 4 for a full discussion on the advantages of Digest
* authentication over Basic authentication, including commentary on the limitations that it still imposes.
+ *
+ * @author Ben Alex
+ * @author Luke Taylor
+ * @since 1.0.0
*/
public class DigestAuthenticationFilter extends GenericFilterBean implements MessageSourceAware {
//~ Static fields/initializers =====================================================================================
@@ -83,7 +88,7 @@ public class DigestAuthenticationFilter extends GenericFilterBean implements Mes
//~ Instance fields ================================================================================================
- private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource();
+ private AuthenticationDetailsSource<HttpServletRequest,?> authenticationDetailsSource = new WebAuthenticationDetailsSource();
private DigestAuthenticationEntryPoint authenticationEntryPoint;
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
private UserCache userCache = new NullUserCache();
@@ -93,8 +98,6 @@ public class DigestAuthenticationFilter extends GenericFilterBean implements Mes
//~ Methods ========================================================================================================
-
-
@Override
public void afterPropertiesSet() {
Assert.notNull(userDetailsService, "A UserDetailsService is required");
@@ -108,131 +111,37 @@ public class DigestAuthenticationFilter extends GenericFilterBean implements Mes
String header = request.getHeader("Authorization");
- if (logger.isDebugEnabled()) {
- logger.debug("Authorization header received from user agent: " + header);
- }
-
- if ((header != null) && header.startsWith("Digest ")) {
- String section212response = header.substring(7);
-
- String[] headerEntries = DigestAuthUtils.splitIgnoringQuotes(section212response, ',');
- Map<String,String> headerMap = DigestAuthUtils.splitEachArrayElementAndCreateMap(headerEntries, "=", "\"");
-
- String username = headerMap.get("username");
- String realm = headerMap.get("realm");
- String nonce = headerMap.get("nonce");
- String uri = headerMap.get("uri");
- String responseDigest = headerMap.get("response");
- String qop = headerMap.get("qop"); // RFC 2617 extension
- String nc = headerMap.get("nc"); // RFC 2617 extension
- String cnonce = headerMap.get("cnonce"); // RFC 2617 extension
-
- // Check all required parameters were supplied (ie RFC 2069)
- if ((username == null) || (realm == null) || (nonce == null) || (uri == null) || (response == null)) {
- if (logger.isDebugEnabled()) {
- logger.debug("extracted username: '" + username + "'; realm: '" + username + "'; nonce: '"
- + username + "'; uri: '" + username + "'; response: '" + username + "'");
- }
-
- fail(request, response,
- new BadCredentialsException(messages.getMessage("DigestAuthenticationFilter.missingMandatory",
- new Object[]{section212response}, "Missing mandatory digest value; received header {0}")));
-
- return;
- }
-
- // Check all required parameters for an "auth" qop were supplied (ie RFC 2617)
- if ("auth".equals(qop)) {
- if ((nc == null) || (cnonce == null)) {
- if (logger.isDebugEnabled()) {
- logger.debug("extracted nc: '" + nc + "'; cnonce: '" + cnonce + "'");
- }
-
- fail(request, response,
- new BadCredentialsException(messages.getMessage("DigestAuthenticationFilter.missingAuth",
- new Object[]{section212response}, "Missing mandatory digest value; received header {0}")));
-
- return;
- }
- }
+ if (header == null || !header.startsWith("Digest ")) {
+ chain.doFilter(request, response);
- // Check realm name equals what we expected
- if (!this.getAuthenticationEntryPoint().getRealmName().equals(realm)) {
- fail(request, response,
- new BadCredentialsException(messages.getMessage("DigestAuthenticationFilter.incorrectRealm",
- new Object[]{realm, this.getAuthenticationEntryPoint().getRealmName()},
- "Response realm name '{0}' does not match system realm name of '{1}'")));
-
- return;
- }
-
- // Check nonce was a Base64 encoded (as sent by DigestAuthenticationEntryPoint)
- if (!Base64.isBase64(nonce.getBytes())) {
- fail(request, response,
- new BadCredentialsException(messages.getMessage("DigestAuthenticationFilter.nonceEncoding",
- new Object[]{nonce}, "Nonce is not encoded in Base64; received nonce {0}")));
-
- return;
- }
-
- // Decode nonce from Base64
- // format of nonce is:
- // base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key))
- String nonceAsPlainText = new String(Base64.decode(nonce.getBytes()));
- String[] nonceTokens = StringUtils.delimitedListToStringArray(nonceAsPlainText, ":");
-
- if (nonceTokens.length != 2) {
- fail(request, response,
- new BadCredentialsException(messages.getMessage("DigestAuthenticationFilter.nonceNotTwoTokens",
- new Object[]{nonceAsPlainText}, "Nonce should have yielded two tokens but was {0}")));
-
- return;
- }
-
- // Extract expiry time from nonce
- long nonceExpiryTime;
+ return;
+ }
- try {
- nonceExpiryTime = new Long(nonceTokens[0]).longValue();
- } catch (NumberFormatException nfe) {
- fail(request, response,
- new BadCredentialsException(messages.getMessage("DigestAuthenticationFilter.nonceNotNumeric",
- new Object[]{nonceAsPlainText},
- "Nonce token should have yielded a numeric first token, but was {0}")));
+ if (logger.isDebugEnabled()) {
+ logger.debug("Digest Authorization header received from user agent: " + header);
+ }
- return;
- }
+ DigestData digestAuth = new DigestData(header);
- // Check signature of nonce matches this expiry time
- String expectedNonceSignature = DigestAuthUtils.md5Hex(nonceExpiryTime + ":"
- + this.getAuthenticationEntryPoint().getKey());
+ try {
+ digestAuth.validateAndDecode(authenticationEntryPoint.getKey(), authenticationEntryPoint.getRealmName());
+ } catch (BadCredentialsException e) {
+ fail(request, response, e);
- if (!expectedNonceSignature.equals(nonceTokens[1])) {
- fail(request, response,
- new BadCredentialsException(messages.getMessage("DigestAuthenticationFilter.nonceCompromised",
- new Object[]{nonceAsPlainText}, "Nonce token compromised {0}")));
-
- return;
- }
+ 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);
+ // 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 cacheWasUsed = true;
+ UserDetails user = userCache.getUserFromCache(digestAuth.getUsername());
+ String serverDigestMd5;
+ try {
if (user == null) {
- loadedFromDao = true;
-
- try {
- user = userDetailsService.loadUserByUsername(username);
- } catch (UsernameNotFoundException notFound) {
- fail(request, response,
- new BadCredentialsException(messages.getMessage("DigestAuthenticationFilter.usernameNotFound",
- new Object[]{username}, "Username {0} not found")));
-
- return;
- }
+ cacheWasUsed = false;
+ user = userDetailsService.loadUserByUsername(digestAuth.getUsername());
if (user == null) {
throw new AuthenticationServiceException(
@@ -242,83 +151,78 @@ public class DigestAuthenticationFilter extends GenericFilterBean implements Mes
userCache.putUserInCache(user);
}
- // Compute the expected response-digest (will be in hex form)
- String serverDigestMd5;
-
- // Don't catch IllegalArgumentException (already checked validity)
- serverDigestMd5 = DigestAuthUtils.generateDigest(passwordAlreadyEncoded, username, realm, user.getPassword(),
- request.getMethod(), uri, qop, nonce, nc, cnonce);
+ serverDigestMd5 = digestAuth.calculateServerDigest(user.getPassword(), request.getMethod());
// If digest is incorrect, try refreshing from backend and recomputing
- if (!serverDigestMd5.equals(responseDigest) && !loadedFromDao) {
+ if (!serverDigestMd5.equals(digestAuth.getResponse()) && cacheWasUsed) {
if (logger.isDebugEnabled()) {
logger.debug(
"Digest comparison failure; trying to refresh user from DAO in case password had changed");
}
- try {
- user = userDetailsService.loadUserByUsername(username);
- } catch (UsernameNotFoundException notFound) {
- // Would very rarely happen, as user existed earlier
- fail(request, response,
- new BadCredentialsException(messages.getMessage("DigestAuthenticationFilter.usernameNotFound",
- new Object[]{username}, "Username {0} not found")));
- }
-
+ user = userDetailsService.loadUserByUsername(digestAuth.getUsername());
userCache.putUserInCache(user);
-
- // Don't catch IllegalArgumentException (already checked validity)
- serverDigestMd5 = DigestAuthUtils.generateDigest(passwordAlreadyEncoded, username, realm, user.getPassword(),
- request.getMethod(), uri, qop, nonce, nc, cnonce);
+ serverDigestMd5 = digestAuth.calculateServerDigest(user.getPassword(), request.getMethod());
}
- // If digest is still incorrect, definitely reject authentication attempt
- if (!serverDigestMd5.equals(responseDigest)) {
- if (logger.isDebugEnabled()) {
- logger.debug("Expected response: '" + serverDigestMd5 + "' but received: '" + responseDigest
- + "'; is AuthenticationDao returning clear text passwords?");
- }
+ } catch (UsernameNotFoundException notFound) {
+ fail(request, response,
+ new BadCredentialsException(messages.getMessage("DigestAuthenticationFilter.usernameNotFound",
+ new Object[]{digestAuth.getUsername()}, "Username {0} not found")));
- fail(request, response,
- new BadCredentialsException(messages.getMessage("DigestAuthenticationFilter.incorrectResponse",
- "Incorrect response")));
- return;
- }
-
- // To get this far, the digest must have been valid
- // Check the nonce has not expired
- // We do this last so we can direct the user agent its nonce is stale
- // but the request was otherwise appearing to be valid
- if (nonceExpiryTime < System.currentTimeMillis()) {
- fail(request, response,
- new NonceExpiredException(messages.getMessage("DigestAuthenticationFilter.nonceExpired",
- "Nonce has expired/timed out")));
+ return;
+ }
- return;
- }
+ // If digest is still incorrect, definitely reject authentication attempt
+ if (!serverDigestMd5.equals(digestAuth.getResponse())) {
if (logger.isDebugEnabled()) {
- logger.debug("Authentication success for user: '" + username + "' with response: '" + responseDigest
- + "'");
+ logger.debug("Expected response: '" + serverDigestMd5 + "' but received: '" + digestAuth.getResponse()
+ + "'; is AuthenticationDao returning clear text passwords?");
}
- UsernamePasswordAuthenticationToken authRequest;
- if (createAuthenticatedToken) {
- authRequest = new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities());
- }
- else
- {
- authRequest = new UsernamePasswordAuthenticationToken(user, user.getPassword());
- }
+ fail(request, response,
+ new BadCredentialsException(messages.getMessage("DigestAuthenticationFilter.incorrectResponse",
+ "Incorrect response")));
+ return;
+ }
- authRequest.setDetails(authenticationDetailsSource.buildDetails((HttpServletRequest) request));
+ // To get this far, the digest must have been valid
+ // Check the nonce has not expired
+ // We do this last so we can direct the user agent its nonce is stale
+ // but the request was otherwise appearing to be valid
+ if (digestAuth.isNonceExpired()) {
+ fail(request, response,
+ new NonceExpiredException(messages.getMessage("DigestAuthenticationFilter.nonceExpired",
+ "Nonce has expired/timed out")));
+
+ return;
+ }
- SecurityContextHolder.getContext().setAuthentication(authRequest);
+ if (logger.isDebugEnabled()) {
+ logger.debug("Authentication success for user: '" + digestAuth.getUsername()
+ + "' with response: '" + digestAuth.getResponse() + "'");
}
+ SecurityContextHolder.getContext().setAuthentication(createSuccessfulAuthentication(request, user));
+
chain.doFilter(request, response);
}
+ private Authentication createSuccessfulAuthentication(HttpServletRequest request, UserDetails user) {
+ UsernamePasswordAuthenticationToken authRequest;
+ if (createAuthenticatedToken) {
+ authRequest = new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities());
+ }
+ else {
+ authRequest = new UsernamePasswordAuthenticationToken(user, user.getPassword());
+ }
+
+ authRequest.setDetails(authenticationDetailsSource.buildDetails((HttpServletRequest) request));
+
+ return authRequest;
+ }
+
private void fail(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed)
throws IOException, ServletException {
SecurityContextHolder.getContext().setAuthentication(null);
@@ -330,7 +234,7 @@ public class DigestAuthenticationFilter extends GenericFilterBean implements Mes
authenticationEntryPoint.commence(request, response, failed);
}
- public DigestAuthenticationEntryPoint getAuthenticationEntryPoint() {
+ protected final DigestAuthenticationEntryPoint getAuthenticationEntryPoint() {
return authenticationEntryPoint;
}
@@ -342,7 +246,7 @@ public class DigestAuthenticationFilter extends GenericFilterBean implements Mes
return userDetailsService;
}
- public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) {
+ public void setAuthenticationDetailsSource(AuthenticationDetailsSource<HttpServletRequest,?> authenticationDetailsSource) {
Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required");
this.authenticationDetailsSource = authenticationDetailsSource;
}
@@ -385,4 +289,119 @@ public class DigestAuthenticationFilter extends GenericFilterBean implements Mes
public void setCreateAuthenticatedToken(boolean createAuthenticatedToken) {
this.createAuthenticatedToken = createAuthenticatedToken;
}
+
+ private class DigestData {
+ private final String username;
+ private final String realm;
+ private final String nonce;
+ private final String uri;
+ private final String response;
+ private final String qop;
+ private final String nc;
+ private final String cnonce;
+ private final String section212response;
+ private long nonceExpiryTime;
+
+ DigestData(String header) {
+ section212response = header.substring(7);
+ String[] headerEntries = DigestAuthUtils.splitIgnoringQuotes(section212response, ',');
+ Map<String,String> headerMap = DigestAuthUtils.splitEachArrayElementAndCreateMap(headerEntries, "=", "\"");
+
+ username = headerMap.get("username");
+ realm = headerMap.get("realm");
+ nonce = headerMap.get("nonce");
+ uri = headerMap.get("uri");
+ response = headerMap.get("response");
+ qop = headerMap.get("qop"); // RFC 2617 extension
+ nc = headerMap.get("nc"); // RFC 2617 extension
+ cnonce = headerMap.get("cnonce"); // RFC 2617 extension
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Extracted username: '" + username + "'; realm: '" + realm + "'; nonce: '"
+ + nonce + "'; uri: '" + uri + "'; response: '" + response + "'");
+ }
+ }
+
+ void validateAndDecode(String entryPointKey, String expectedRealm) throws BadCredentialsException {
+ // Check all required parameters were supplied (ie RFC 2069)
+ if ((username == null) || (realm == null) || (nonce == null) || (uri == null) || (response == null)) {
+ throw new BadCredentialsException(messages.getMessage("DigestAuthenticationFilter.missingMandatory",
+ new Object[]{section212response}, "Missing mandatory digest value; received header {0}"));
+ }
+ // Check all required parameters for an "auth" qop were supplied (ie RFC 2617)
+ if ("auth".equals(qop)) {
+ if ((nc == null) || (cnonce == null)) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("extracted nc: '" + nc + "'; cnonce: '" + cnonce + "'");
+ }
+
+ throw new BadCredentialsException(messages.getMessage("DigestAuthenticationFilter.missingAuth",
+ new Object[]{section212response}, "Missing mandatory digest value; received header {0}"));
+ }
+ }
+
+ // Check realm name equals what we expected
+ if (!expectedRealm.equals(realm)) {
+ throw new BadCredentialsException(messages.getMessage("DigestAuthenticationFilter.incorrectRealm",
+ new Object[]{realm, expectedRealm},
+ "Response realm name '{0}' does not match system realm name of '{1}'"));
+ }
+
+ // Check nonce was Base64 encoded (as sent by DigestAuthenticationEntryPoint)
+ if (!Base64.isBase64(nonce.getBytes())) {
+ throw new BadCredentialsException(messages.getMessage("DigestAuthenticationFilter.nonceEncoding",
+ new Object[]{nonce}, "Nonce is not encoded in Base64; received nonce {0}"));
+ }
+
+ // Decode nonce from Base64
+ // format of nonce is:
+ // base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key))
+ String nonceAsPlainText = new String(Base64.decode(nonce.getBytes()));
+ String[] nonceTokens = StringUtils.delimitedListToStringArray(nonceAsPlainText, ":");
+
+ if (nonceTokens.length != 2) {
+ throw new BadCredentialsException(messages.getMessage("DigestAuthenticationFilter.nonceNotTwoTokens",
+ new Object[]{nonceAsPlainText}, "Nonce should have yielded two tokens but was {0}"));
+ }
+
+ // Extract expiry time from nonce
+
+ try {
+ nonceExpiryTime = new Long(nonceTokens[0]).longValue();
+ } catch (NumberFormatException nfe) {
+ throw new BadCredentialsException(messages.getMessage("DigestAuthenticationFilter.nonceNotNumeric",
+ new Object[]{nonceAsPlainText},
+ "Nonce token should have yielded a numeric first token, but was {0}"));
+ }
+
+ // Check signature of nonce matches this expiry time
+ String expectedNonceSignature = DigestAuthUtils.md5Hex(nonceExpiryTime + ":" + entryPointKey);
+
+ if (!expectedNonceSignature.equals(nonceTokens[1])) {
+ new BadCredentialsException(messages.getMessage("DigestAuthenticationFilter.nonceCompromised",
+ new Object[]{nonceAsPlainText}, "Nonce token compromised {0}"));
+ }
+ }
+
+ String calculateServerDigest(String password, String httpMethod) {
+ // Compute the expected response-digest (will be in hex form)
+
+ // Don't catch IllegalArgumentException (already checked validity)
+ return DigestAuthUtils.generateDigest(passwordAlreadyEncoded, username, realm, password,
+ httpMethod, uri, qop, nonce, nc, cnonce);
+ }
+
+ boolean isNonceExpired() {
+ long now = System.currentTimeMillis();
+ return nonceExpiryTime < now;
+ }
+
+ String getUsername() {
+ return username;
+ }
+
+ String getResponse() {
+ return response;
+ }
+ }
}
diff --git a/dist/spring-security-web/org/springframework/security/web/context/HttpSessionContextIntegrationFilter.java b/dist/spring-security-web/org/springframework/security/web/context/HttpSessionContextIntegrationFilter.java
deleted file mode 100644
index 6b807e5..0000000
--- a/dist/spring-security-web/org/springframework/security/web/context/HttpSessionContextIntegrationFilter.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/* Copyright 2004, 2005, 2006 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.web.context;
-
-import javax.servlet.ServletException;
-
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.security.core.context.SecurityContext;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.core.context.SecurityContextImpl;
-
-/**
- * Populates the {@link SecurityContextHolder} with information obtained from
- * the <code>HttpSession</code>.
- * <p/>
- * <p/>
- * The <code>HttpSession</code> will be queried to retrieve the
- * <code>SecurityContext</code> that should be stored against the
- * <code>SecurityContextHolder</code> for the duration of the web request. At
- * the end of the web request, any updates made to the
- * <code>SecurityContextHolder</code> will be persisted back to the
- * <code>HttpSession</code> by this filter.
- * </p>
- * <p/>
- * If a valid <code>SecurityContext</code> cannot be obtained from the
- * <code>HttpSession</code> for whatever reason, a fresh
- * <code>SecurityContext</code> will be created and used instead. The created
- * object will be of the instance defined by the {@link #setContextClass(Class)}
- * method (which defaults to {@link org.springframework.security.core.context.SecurityContextImpl}.
- * </p>
- * <p/>
- * No <code>HttpSession</code> will be created by this filter if one does not
- * already exist. If at the end of the web request the <code>HttpSession</code>
- * does not exist, a <code>HttpSession</code> will <b>only</b> be created if
- * the current contents of the <code>SecurityContextHolder</code> are not
- * {@link java.lang.Object#equals(java.lang.Object)} to a <code>new</code>
- * instance of {@link #setContextClass(Class)}. This avoids needless
- * <code>HttpSession</code> creation, but automates the storage of changes
- * made to the <code>SecurityContextHolder</code>. There is one exception to
- * this rule, that is if the {@link #forceEagerSessionCreation} property is
- * <code>true</code>, in which case sessions will always be created
- * irrespective of normal session-minimisation logic (the default is
- * <code>false</code>, as this is resource intensive and not recommended).
- * </p>
- * <p/>
- * This filter will only execute once per request, to resolve servlet container
- * (specifically Weblogic) incompatibilities.
- * </p>
- * <p/>
- * If for whatever reason no <code>HttpSession</code> should <b>ever</b> be
- * created (eg this filter is only being used with Basic authentication or
- * similar clients that will never present the same <code>jsessionid</code>
- * etc), the {@link #setAllowSessionCreation(boolean)} should be set to
- * <code>false</code>. Only do this if you really need to conserve server
- * memory and ensure all classes using the <code>SecurityContextHolder</code>
- * are designed to have no persistence of the <code>SecurityContext</code>
- * between web requests. Please note that if {@link #forceEagerSessionCreation}
- * is <code>true</code>, the <code>allowSessionCreation</code> must also be
- * <code>true</code> (setting it to <code>false</code> will cause a startup
- * time error).
- * </p>
- * <p/>
- * This filter MUST be executed BEFORE any authentication processing mechanisms.
- * Authentication processing mechanisms (eg BASIC, CAS processing filters etc)
- * expect the <code>SecurityContextHolder</code> to contain a valid
- * <code>SecurityContext</code> by the time they execute.
- * </p>
- *
- * @author Ben Alex
- * @author Patrick Burleson
- * @author Luke Taylor
- * @author Martin Algesten
- *
- * @deprecated Use SecurityContextPersistenceFilter instead.
- *
- */
-public class HttpSessionContextIntegrationFilter extends SecurityContextPersistenceFilter implements InitializingBean {
- //~ Static fields/initializers =====================================================================================
- public static final String SPRING_SECURITY_CONTEXT_KEY = HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY;
-
- //~ Instance fields ================================================================================================
-
- private Class<? extends SecurityContext> contextClass = SecurityContextImpl.class;
-
- /**
- * Indicates if this filter can create a <code>HttpSession</code> if
- * needed (sessions are always created sparingly, but setting this value to
- * <code>false</code> will prohibit sessions from ever being created).
- * Defaults to <code>true</code>. Do not set to <code>false</code> if
- * you are have set {@link #forceEagerSessionCreation} to <code>true</code>,
- * as the properties would be in conflict.
- */
- private boolean allowSessionCreation = true;
-
- /**
- * Indicates if this filter is required to create a <code>HttpSession</code>
- * for every request before proceeding through the filter chain, even if the
- * <code>HttpSession</code> would not ordinarily have been created. By
- * default this is <code>false</code>, which is entirely appropriate for
- * most circumstances as you do not want a <code>HttpSession</code>
- * created unless the filter actually needs one. It is envisaged the main
- * situation in which this property would be set to <code>true</code> is
- * if using other filters that depend on a <code>HttpSession</code>
- * already existing, such as those which need to obtain a session ID. This
- * is only required in specialised cases, so leave it set to
- * <code>false</code> unless you have an actual requirement and are
- * conscious of the session creation overhead.
- */
- private boolean forceEagerSessionCreation = false;
-
- /**
- * Indicates whether the <code>SecurityContext</code> will be cloned from
- * the <code>HttpSession</code>. The default is to simply reference (ie
- * the default is <code>false</code>). The default may cause issues if
- * concurrent threads need to have a different security identity from other
- * threads being concurrently processed that share the same
- * <code>HttpSession</code>. In most normal environments this does not
- * represent an issue, as changes to the security identity in one thread is
- * allowed to affect the security identitiy in other threads associated with
- * the same <code>HttpSession</code>. For unusual cases where this is not
- * permitted, change this value to <code>true</code> and ensure the
- * {@link #contextClass} is set to a <code>SecurityContext</code> that
- * implements {@link Cloneable} and overrides the <code>clone()</code>
- * method.
- */
- private boolean cloneFromHttpSession = false;
-
- // private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl();
-
- private HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
-
- public HttpSessionContextIntegrationFilter() throws ServletException {
- super.setSecurityContextRepository(repo);
- }
-
- public boolean isCloneFromHttpSession() {
- return cloneFromHttpSession;
- }
-
- public void setCloneFromHttpSession(boolean cloneFromHttpSession) {
- this.cloneFromHttpSession = cloneFromHttpSession;
- repo.setCloneFromHttpSession(cloneFromHttpSession);
- }
-
- public boolean isAllowSessionCreation() {
- return allowSessionCreation;
- }
-
- public void setAllowSessionCreation(boolean allowSessionCreation) {
- this.allowSessionCreation = allowSessionCreation;
- repo.setAllowSessionCreation(allowSessionCreation);
- }
-
- protected Class<? extends SecurityContext> getContextClass() {
- return contextClass;
- }
-
- @SuppressWarnings("unchecked")
- public void setContextClass(Class secureContext) {
- this.contextClass = secureContext;
- repo.setSecurityContextClass(secureContext);
- }
-
- public boolean isForceEagerSessionCreation() {
- return forceEagerSessionCreation;
- }
-
- public void setForceEagerSessionCreation(boolean forceEagerSessionCreation) {
- this.forceEagerSessionCreation = forceEagerSessionCreation;
- super.setForceEagerSessionCreation(forceEagerSessionCreation);
- }
-
- //~ Methods ========================================================================================================
-
- public void afterPropertiesSet() {
- if (forceEagerSessionCreation && !allowSessionCreation) {
- throw new IllegalArgumentException(
- "If using forceEagerSessionCreation, you must set allowSessionCreation to also be true");
- }
- }
-}
diff --git a/dist/spring-security-web/org/springframework/security/web/context/HttpSessionSecurityContextRepository.java b/dist/spring-security-web/org/springframework/security/web/context/HttpSessionSecurityContextRepository.java
index e0cbee4..a22f7cc 100644
--- a/dist/spring-security-web/org/springframework/security/web/context/HttpSessionSecurityContextRepository.java
+++ b/dist/spring-security-web/org/springframework/security/web/context/HttpSessionSecurityContextRepository.java
@@ -1,11 +1,5 @@
package org.springframework.security.web.context;
-import java.lang.reflect.Method;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.authentication.AuthenticationTrustResolver;
@@ -17,12 +11,16 @@ import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
/**
* A {@code SecurityContextRepository} implementation which stores the security context in the {@code HttpSession}
* between requests.
* <p>
* The {@code HttpSession} will be queried to retrieve the {@code SecurityContext} in the <tt>loadContext</tt>
- * method (using the key {@link #SPRING_SECURITY_CONTEXT_KEY}). If a valid {@code SecurityContext} cannot be
+ * method (using the key {@link #SPRING_SECURITY_CONTEXT_KEY} by default). If a valid {@code SecurityContext} cannot be
* obtained from the {@code HttpSession} for whatever reason, a fresh {@code SecurityContext} will be created
* by calling by {@link SecurityContextHolder#createEmptyContext()} and this instance will be returned instead.
* <p>
@@ -53,28 +51,27 @@ import org.springframework.util.ReflectionUtils;
* @since 3.0
*/
public class HttpSessionSecurityContextRepository implements SecurityContextRepository {
+ /**
+ * The default key under which the security context will be stored in the session.
+ */
public static final String SPRING_SECURITY_CONTEXT_KEY = "SPRING_SECURITY_CONTEXT";
protected final Log logger = LogFactory.getLog(this.getClass());
- private Class<? extends SecurityContext> securityContextClass = null;
/** SecurityContext instance used to check for equality with default (unauthenticated) content */
- private Object contextObject = SecurityContextHolder.createEmptyContext();
- private boolean cloneFromHttpSession = false;
+ private final Object contextObject = SecurityContextHolder.createEmptyContext();
private boolean allowSessionCreation = true;
private boolean disableUrlRewriting = false;
+ private String springSecurityContextKey = SPRING_SECURITY_CONTEXT_KEY;
- private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl();
+ private final AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl();
/**
* Gets the security context for the current request (if available) and returns it.
* <p>
* If the session is null, the context object is null or the context object stored in the session
- * is not an instance of <tt>SecurityContext</tt>, a new context object will be generated and
+ * is not an instance of {@code SecurityContext}, a new context object will be generated and
* returned.
- * <p>
- * If <tt>cloneFromHttpSession</tt> is set to true, it will attempt to clone the context object first
- * and return the cloned instance.
*/
public SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder) {
HttpServletRequest request = requestResponseHolder.getRequest();
@@ -92,8 +89,8 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo
}
- requestResponseHolder.setResponse(new SaveToSessionResponseWrapper(response, request,
- httpSession != null, context.hashCode()));
+ requestResponseHolder.setResponse(
+ new SaveToSessionResponseWrapper(response, request, httpSession != null, context));
return context;
}
@@ -115,7 +112,7 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo
return false;
}
- return session.getAttribute(SPRING_SECURITY_CONTEXT_KEY) != null;
+ return session.getAttribute(springSecurityContextKey) != null;
}
/**
@@ -135,7 +132,7 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo
// Session exists, so try to obtain a context from it.
- Object contextFromSession = httpSession.getAttribute(SPRING_SECURITY_CONTEXT_KEY);
+ Object contextFromSession = httpSession.getAttribute(springSecurityContextKey);
if (contextFromSession == null) {
if (debug) {
@@ -148,7 +145,7 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo
// We now have the security context object from the session.
if (!(contextFromSession instanceof SecurityContext)) {
if (logger.isWarnEnabled()) {
- logger.warn("SPRING_SECURITY_CONTEXT did not contain a SecurityContext but contained: '"
+ logger.warn(springSecurityContextKey + " did not contain a SecurityContext but contained: '"
+ contextFromSession + "'; are you improperly modifying the HttpSession directly "
+ "(you should always use SecurityContextHolder) or using the HttpSession attribute "
+ "reserved for this class?");
@@ -157,13 +154,8 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo
return null;
}
- // Clone if required (see SEC-356)
- if (cloneFromHttpSession) {
- contextFromSession = cloneContext(contextFromSession);
- }
-
if (debug) {
- logger.debug("Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT: '" + contextFromSession + "'");
+ logger.debug("Obtained a valid SecurityContext from " + springSecurityContextKey + ": '" + contextFromSession + "'");
}
// Everything OK. The only non-null return from this method.
@@ -172,88 +164,15 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo
}
/**
- *
- * @param context the object which was stored under the security context key in the HttpSession.
- * @return the cloned SecurityContext object. Never null.
- */
- private Object cloneContext(Object context) {
- Object clonedContext = null;
- Assert.isInstanceOf(Cloneable.class, context,
- "Context must implement Cloneable and provide a Object.clone() method");
- try {
- Method m = context.getClass().getMethod("clone", new Class[]{});
- if (!m.isAccessible()) {
- m.setAccessible(true);
- }
- clonedContext = m.invoke(context, new Object[]{});
- } catch (Exception ex) {
- ReflectionUtils.handleReflectionException(ex);
- }
-
- return clonedContext;
- }
-
- /**
* By default, calls {@link SecurityContextHolder#createEmptyContext()} to obtain a new context (there should be
* no context present in the holder when this method is called). Using this approach the context creation
* strategy is decided by the {@link SecurityContextHolderStrategy} in use. The default implementations
* will return a new <tt>SecurityContextImpl</tt>.
- * <p>
- * An alternative way of customizing the <tt>SecurityContext</tt> implementation is by setting the
- * <tt>securityContextClass</tt> property. In this case, the method will attempt to invoke the no-args
- * constructor on the supplied class instead and return the created instance.
*
* @return a new SecurityContext instance. Never null.
*/
- SecurityContext generateNewContext() {
- SecurityContext context = null;
-
- if (securityContextClass == null) {
- context = SecurityContextHolder.createEmptyContext();
-
- return context;
- }
-
- try {
- context = securityContextClass.newInstance();
- } catch (Exception e) {
- ReflectionUtils.handleReflectionException(e);
- }
- return context;
- }
-
- @SuppressWarnings("unchecked")
- @Deprecated
- /**
- * Sets the {@code SecurityContext} implementation class.
- *
- * @deprecated use a custom {@code SecurityContextHolderStrategy} where the {@code createEmptyContext} method
- * returns the correct implementation.
- */
- public void setSecurityContextClass(Class contextClass) {
- if (contextClass == null || (!SecurityContext.class.isAssignableFrom(contextClass))) {
- throw new IllegalArgumentException("securityContextClass must implement SecurityContext "
- + "(typically use org.springframework.security.core.context.SecurityContextImpl; existing class is "
- + contextClass + ")");
- }
-
- this.securityContextClass = contextClass;
- contextObject = generateNewContext();
- }
-
- /**
- * Normally, the {@code SecurityContext} retrieved from the session is stored directly in the
- * {@code SecurityContextHolder}, meaning that it is shared between concurrent threads.
- * In this case, if one thread modifies the contents of the context, all threads will see the same
- * change.
- *
- * @param cloneFromHttpSession set to true to clone the security context retrieved from the session.
- * Defaults to false.
- * @deprecated Override the {@code loadContext} method and copy the created context instead.
- */
- @Deprecated
- public void setCloneFromHttpSession(boolean cloneFromHttpSession) {
- this.cloneFromHttpSession = cloneFromHttpSession;
+ protected SecurityContext generateNewContext() {
+ return SecurityContextHolder.createEmptyContext();
}
/**
@@ -280,6 +199,17 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo
this.disableUrlRewriting = disableUrlRewriting;
}
+ /**
+ * Allows the session attribute name to be customized for this repository instance.
+ *
+ * @param springSecurityContextKey the key under which the security context will be stored. Defaults to
+ * {@link #SPRING_SECURITY_CONTEXT_KEY}.
+ */
+ public void setSpringSecurityContextKey(String springSecurityContextKey) {
+ Assert.hasText(springSecurityContextKey, "springSecurityContextKey cannot be empty");
+ this.springSecurityContextKey = springSecurityContextKey;
+ }
+
//~ Inner Classes ==================================================================================================
/**
@@ -292,9 +222,10 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo
*/
final class SaveToSessionResponseWrapper extends SaveContextOnUpdateOrErrorResponseWrapper {
- private HttpServletRequest request;
- private boolean httpSessionExistedAtStartOfRequest;
- private int contextHashBeforeChainExecution;
+ private final HttpServletRequest request;
+ private final boolean httpSessionExistedAtStartOfRequest;
+ private final SecurityContext contextBeforeExecution;
+ private final Authentication authBeforeExecution;
/**
* Takes the parameters required to call <code>saveContext()</code> successfully in
@@ -304,17 +235,17 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo
* @param httpSessionExistedAtStartOfRequest indicates whether there was a session in place before the
* filter chain executed. If this is true, and the session is found to be null, this indicates that it was
* invalidated during the request and a new session will now be created.
- * @param contextHashBeforeChainExecution the hashcode of the context before the filter chain executed.
- * The context will only be stored if it has a different hashcode, indicating that the context changed
- * during the request.
+ * @param context the context before the filter chain executed.
+ * The context will only be stored if it or its contents changed during the request.
*/
SaveToSessionResponseWrapper(HttpServletResponse response, HttpServletRequest request,
boolean httpSessionExistedAtStartOfRequest,
- int contextHashBeforeChainExecution) {
+ SecurityContext context) {
super(response, disableUrlRewriting);
this.request = request;
this.httpSessionExistedAtStartOfRequest = httpSessionExistedAtStartOfRequest;
- this.contextHashBeforeChainExecution = contextHashBeforeChainExecution;
+ this.contextBeforeExecution = context;
+ this.authBeforeExecution = context.getAuthentication();
}
/**
@@ -335,12 +266,12 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo
// See SEC-776
if (authentication == null || authenticationTrustResolver.isAnonymous(authentication)) {
if (logger.isDebugEnabled()) {
- logger.debug("SecurityContext is empty or anonymous - context will not be stored in HttpSession. ");
+ logger.debug("SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.");
}
if (httpSession != null) {
// SEC-1587 A non-anonymous context may still be in the session
- httpSession.removeAttribute(SPRING_SECURITY_CONTEXT_KEY);
+ httpSession.removeAttribute(springSecurityContextKey);
}
return;
}
@@ -349,19 +280,24 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo
httpSession = createNewSessionIfAllowed(context);
}
- // If HttpSession exists, store current SecurityContextHolder contents but only if
- // the SecurityContext has actually changed (see JIRA SEC-37)
- // We also check that the session contains the context, in case a new session has been created (SEC-1561)
- if (httpSession != null && (context.hashCode() != contextHashBeforeChainExecution ||
- httpSession.getAttribute(SPRING_SECURITY_CONTEXT_KEY) == null)) {
- httpSession.setAttribute(SPRING_SECURITY_CONTEXT_KEY, context);
+ // If HttpSession exists, store current SecurityContext but only if it has
+ // actually changed in this thread (see SEC-37, SEC-1307, SEC-1528)
+ if (httpSession != null) {
+ // We may have a new session, so check also whether the context attribute is set SEC-1561
+ if (contextChanged(context) || httpSession.getAttribute(springSecurityContextKey) == null) {
+ httpSession.setAttribute(springSecurityContextKey, context);
- if (logger.isDebugEnabled()) {
- logger.debug("SecurityContext stored to HttpSession: '" + context + "'");
+ if (logger.isDebugEnabled()) {
+ logger.debug("SecurityContext stored to HttpSession: '" + context + "'");
+ }
}
}
}
+ private boolean contextChanged(SecurityContext context) {
+ return context != contextBeforeExecution || context.getAuthentication() != authBeforeExecution;
+ }
+
private HttpSession createNewSessionIfAllowed(SecurityContext context) {
if (httpSessionExistedAtStartOfRequest) {
if (logger.isDebugEnabled()) {
@@ -375,7 +311,8 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo
if (!allowSessionCreation) {
if (logger.isDebugEnabled()) {
logger.debug("The HttpSession is currently null, and the "
- + "HttpSessionContextIntegrationFilter is prohibited from creating an HttpSession "
+ + HttpSessionSecurityContextRepository.class.getSimpleName()
+ + " is prohibited from creating an HttpSession "
+ "(because the allowSessionCreation property is false) - SecurityContext thus not "
+ "stored for next request");
}
diff --git a/dist/spring-security-web/org/springframework/security/web/context/SaveContextOnUpdateOrErrorResponseWrapper.java b/dist/spring-security-web/org/springframework/security/web/context/SaveContextOnUpdateOrErrorResponseWrapper.java
index c5c1670..cd38e7d 100644
--- a/dist/spring-security-web/org/springframework/security/web/context/SaveContextOnUpdateOrErrorResponseWrapper.java
+++ b/dist/spring-security-web/org/springframework/security/web/context/SaveContextOnUpdateOrErrorResponseWrapper.java
@@ -25,7 +25,7 @@ public abstract class SaveContextOnUpdateOrErrorResponseWrapper extends HttpServ
private boolean contextSaved = false;
/* See SEC-1052 */
- private boolean disableUrlRewriting;
+ private final boolean disableUrlRewriting;
/**
* @param response the response to be wrapped
diff --git a/dist/spring-security-web/org/springframework/security/web/context/SecurityContextPersistenceFilter.java b/dist/spring-security-web/org/springframework/security/web/context/SecurityContextPersistenceFilter.java
index 8ecc542..db033ec 100644
--- a/dist/spring-security-web/org/springframework/security/web/context/SecurityContextPersistenceFilter.java
+++ b/dist/spring-security-web/org/springframework/security/web/context/SecurityContextPersistenceFilter.java
@@ -12,6 +12,7 @@ import javax.servlet.http.HttpSession;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.util.Assert;
import org.springframework.web.filter.GenericFilterBean;
/**
@@ -42,10 +43,17 @@ public class SecurityContextPersistenceFilter extends GenericFilterBean {
static final String FILTER_APPLIED = "__spring_security_scpf_applied";
- private SecurityContextRepository repo = new HttpSessionSecurityContextRepository();
+ private SecurityContextRepository repo;
private boolean forceEagerSessionCreation = false;
+ public SecurityContextPersistenceFilter() {
+ this(new HttpSessionSecurityContextRepository());
+ }
+
+ public SecurityContextPersistenceFilter(SecurityContextRepository repo) {
+ this.repo = repo;
+ }
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
@@ -91,7 +99,12 @@ public class SecurityContextPersistenceFilter extends GenericFilterBean {
}
}
+ /**
+ * @deprecated Use constructor injection
+ */
+ @Deprecated
public void setSecurityContextRepository(SecurityContextRepository repo) {
+ Assert.notNull(repo, "SecurityContextRepository cannot be null");
this.repo = repo;
}
diff --git a/dist/spring-security-web/org/springframework/security/web/firewall/DefaultHttpFirewall.java b/dist/spring-security-web/org/springframework/security/web/firewall/DefaultHttpFirewall.java
index a40fa43..5592e9d 100644
--- a/dist/spring-security-web/org/springframework/security/web/firewall/DefaultHttpFirewall.java
+++ b/dist/spring-security-web/org/springframework/security/web/firewall/DefaultHttpFirewall.java
@@ -33,7 +33,7 @@ public class DefaultHttpFirewall implements HttpFirewall {
}
public HttpServletResponse getFirewalledResponse(HttpServletResponse response) {
- return response;
+ return new FirewalledResponse(response);
}
/**
diff --git a/dist/spring-security-web/org/springframework/security/web/firewall/FirewalledRequest.java b/dist/spring-security-web/org/springframework/security/web/firewall/FirewalledRequest.java
index 48cf40a..2363fdb 100644
--- a/dist/spring-security-web/org/springframework/security/web/firewall/FirewalledRequest.java
+++ b/dist/spring-security-web/org/springframework/security/web/firewall/FirewalledRequest.java
@@ -31,4 +31,9 @@ public abstract class FirewalledRequest extends HttpServletRequestWrapper {
* for the security infrastructure, while still maintaining the
*/
public abstract void reset();
+
+ @Override
+ public String toString() {
+ return "FirewalledRequest[ " + getRequest() + "]";
+ }
}
diff --git a/dist/spring-security-web/org/springframework/security/web/firewall/RequestWrapper.java b/dist/spring-security-web/org/springframework/security/web/firewall/RequestWrapper.java
index df2f0b6..1b2bb37 100644
--- a/dist/spring-security-web/org/springframework/security/web/firewall/RequestWrapper.java
+++ b/dist/spring-security-web/org/springframework/security/web/firewall/RequestWrapper.java
@@ -140,4 +140,4 @@ final class RequestWrapper extends FirewalledRequest {
return RequestWrapper.super.getRequestDispatcher(path);
}
}
-}
\ No newline at end of file
+}
diff --git a/dist/spring-security-web/org/springframework/security/web/savedrequest/DefaultSavedRequest.java b/dist/spring-security-web/org/springframework/security/web/savedrequest/DefaultSavedRequest.java
index b759aaf..9dfd2f2 100644
--- a/dist/spring-security-web/org/springframework/security/web/savedrequest/DefaultSavedRequest.java
+++ b/dist/spring-security-web/org/springframework/security/web/savedrequest/DefaultSavedRequest.java
@@ -18,7 +18,6 @@ package org.springframework.security.web.savedrequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.web.PortResolver;
-import org.springframework.security.web.WebAttributes;
import org.springframework.security.web.util.UrlUtils;
import org.springframework.util.Assert;
@@ -26,8 +25,9 @@ import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
+
/**
- * Represents central information from a <code>HttpServletRequest</code>.
+ * Represents central information from a {@code HttpServletRequest}.
* <p>
* This class is used by {@link org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter}
* and {@link org.springframework.security.web.savedrequest.SavedRequestAwareWrapper} to
@@ -48,11 +48,6 @@ public class DefaultSavedRequest implements SavedRequest {
//~ Static fields/initializers =====================================================================================
protected static final Log logger = LogFactory.getLog(DefaultSavedRequest.class);
- /**
- * @deprecated Use the value in {@link WebAttributes} directly.
- */
- @Deprecated
- public static final String SPRING_SECURITY_SAVED_REQUEST_KEY = WebAttributes.SAVED_REQUEST;
private static final String HEADER_IF_NONE_MATCH = "If-None-Match";
private static final String HEADER_IF_MODIFIED_SINCE = "If-Modified-Since";
@@ -85,8 +80,8 @@ public class DefaultSavedRequest implements SavedRequest {
Cookie[] cookies = request.getCookies();
if (cookies != null) {
- for (int i = 0; i < cookies.length; i++) {
- this.addCookie(cookies[i]);
+ for (Cookie cookie : cookies) {
+ this.addCookie(cookie);
}
}
@@ -170,7 +165,10 @@ public class DefaultSavedRequest implements SavedRequest {
* Determines if the current request matches the <code>DefaultSavedRequest</code>.
* <p>
* All URL arguments are considered but not cookies, locales, headers or parameters.
- * <p>
+ *
+ * @param request the actual request to be matched against this one
+ * @param portResolver used to obtain the server port of the request
+ * @return true if the request is deemed to match this one.
*
*/
public boolean doesRequestMatch(HttpServletRequest request, PortResolver portResolver) {
@@ -192,7 +190,7 @@ public class DefaultSavedRequest implements SavedRequest {
return false;
}
- if (!propertyEquals("serverPort", new Integer(this.serverPort), new Integer(portResolver.getServerPort(request)))) {
+ if (!propertyEquals("serverPort", Integer.valueOf(this.serverPort), Integer.valueOf(portResolver.getServerPort(request)))) {
return false;
}
@@ -212,11 +210,8 @@ public class DefaultSavedRequest implements SavedRequest {
return false;
}
- if (!propertyEquals("servletPath", this.servletPath, request.getServletPath())) {
- return false;
- }
+ return propertyEquals("servletPath", this.servletPath, request.getServletPath());
- return true;
}
public String getContextPath() {
@@ -273,7 +268,7 @@ public class DefaultSavedRequest implements SavedRequest {
}
public String[] getParameterValues(String name) {
- return ((String[]) parameters.get(name));
+ return parameters.get(name);
}
public String getPathInfo() {
@@ -317,7 +312,7 @@ public class DefaultSavedRequest implements SavedRequest {
return true;
}
- if (((arg1 == null) && (arg2 != null)) || ((arg1 != null) && (arg2 == null))) {
+ if (arg1 == null || arg2 == null) {
if (logger.isDebugEnabled()) {
logger.debug(log + ": arg1=" + arg1 + "; arg2=" + arg2 + " (property not equals)");
}
diff --git a/dist/spring-security-web/org/springframework/security/web/savedrequest/FastHttpDateFormat.java b/dist/spring-security-web/org/springframework/security/web/savedrequest/FastHttpDateFormat.java
index 136d2a8..50b2c49 100644
--- a/dist/spring-security-web/org/springframework/security/web/savedrequest/FastHttpDateFormat.java
+++ b/dist/spring-security-web/org/springframework/security/web/savedrequest/FastHttpDateFormat.java
@@ -79,19 +79,19 @@ public class FastHttpDateFormat {
*
* @return Formatted date
*/
- public static final String formatDate(long value, DateFormat threadLocalformat) {
+ public static String formatDate(long value, DateFormat threadLocalformat) {
String cachedDate = null;
- Long longValue = new Long(value);
+ Long longValue = Long.valueOf(value);
try {
cachedDate = formatCache.get(longValue);
- } catch (Exception e) {}
+ } catch (Exception ignored) {}
if (cachedDate != null) {
return cachedDate;
}
- String newDate = null;
+ String newDate;
Date dateValue = new Date(value);
if (threadLocalformat != null) {
@@ -115,7 +115,7 @@ public class FastHttpDateFormat {
*
* @return Current date in HTTP format
*/
- public static final String getCurrentDate() {
+ public static String getCurrentDate() {
long now = System.currentTimeMillis();
if ((now - currentDateGenerated) > 1000) {
@@ -144,8 +144,7 @@ public class FastHttpDateFormat {
for (int i = 0; (date == null) && (i < formats.length); i++) {
try {
date = formats[i].parse(value);
- } catch (ParseException e) {
- ;
+ } catch (ParseException ignored) {
}
}
@@ -165,18 +164,18 @@ public class FastHttpDateFormat {
*
* @return Parsed date (or -1 if error occurred)
*/
- public static final long parseDate(String value, DateFormat[] threadLocalformats) {
+ public static long parseDate(String value, DateFormat[] threadLocalformats) {
Long cachedDate = null;
try {
cachedDate = (Long) parseCache.get(value);
- } catch (Exception e) {}
+ } catch (Exception ignored) {}
if (cachedDate != null) {
return cachedDate.longValue();
}
- Long date = null;
+ Long date;
if (threadLocalformats != null) {
date = internalParseDate(value, threadLocalformats);
diff --git a/dist/spring-security-web/org/springframework/security/web/savedrequest/HttpSessionRequestCache.java b/dist/spring-security-web/org/springframework/security/web/savedrequest/HttpSessionRequestCache.java
index 2a6387a..1a2b15d 100644
--- a/dist/spring-security-web/org/springframework/security/web/savedrequest/HttpSessionRequestCache.java
+++ b/dist/spring-security-web/org/springframework/security/web/savedrequest/HttpSessionRequestCache.java
@@ -8,10 +8,11 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.web.PortResolver;
import org.springframework.security.web.PortResolverImpl;
-import org.springframework.security.web.WebAttributes;
+import org.springframework.security.web.util.AnyRequestMatcher;
+import org.springframework.security.web.util.RequestMatcher;
/**
- * <tt>RequestCache</tt> which stores the <tt>SavedRequest</tt> in the HttpSession.
+ * {@code RequestCache} which stores the {@code SavedRequest} in the HttpSession.
*
* The {@link DefaultSavedRequest} class is used as the implementation.
*
@@ -19,34 +20,36 @@ import org.springframework.security.web.WebAttributes;
* @since 3.0
*/
public class HttpSessionRequestCache implements RequestCache {
+ static final String SAVED_REQUEST = "SPRING_SECURITY_SAVED_REQUEST";
protected final Log logger = LogFactory.getLog(this.getClass());
private PortResolver portResolver = new PortResolverImpl();
private boolean createSessionAllowed = true;
- private boolean justUseSavedRequestOnGet;
+ private RequestMatcher requestMatcher = new AnyRequestMatcher();
/**
* Stores the current request, provided the configuration properties allow it.
*/
public void saveRequest(HttpServletRequest request, HttpServletResponse response) {
- if (!justUseSavedRequestOnGet || "GET".equals(request.getMethod())) {
+ if (requestMatcher.matches(request)) {
DefaultSavedRequest savedRequest = new DefaultSavedRequest(request, portResolver);
if (createSessionAllowed || request.getSession(false) != null) {
// Store the HTTP request itself. Used by AbstractAuthenticationProcessingFilter
// for redirection after successful authentication (SEC-29)
- request.getSession().setAttribute(WebAttributes.SAVED_REQUEST, savedRequest);
+ request.getSession().setAttribute(SAVED_REQUEST, savedRequest);
logger.debug("DefaultSavedRequest added to Session: " + savedRequest);
}
+ } else {
+ logger.debug("Request not saved as configured RequestMatcher did not match");
}
-
}
public SavedRequest getRequest(HttpServletRequest currentRequest, HttpServletResponse response) {
HttpSession session = currentRequest.getSession(false);
if (session != null) {
- return (DefaultSavedRequest) session.getAttribute(WebAttributes.SAVED_REQUEST);
+ return (DefaultSavedRequest) session.getAttribute(SAVED_REQUEST);
}
return null;
@@ -57,7 +60,7 @@ public class HttpSessionRequestCache implements RequestCache {
if (session != null) {
logger.debug("Removing DefaultSavedRequest from session if present");
- session.removeAttribute(WebAttributes.SAVED_REQUEST);
+ session.removeAttribute(SAVED_REQUEST);
}
}
@@ -79,11 +82,15 @@ public class HttpSessionRequestCache implements RequestCache {
}
/**
- * If <code>true</code>, will only use <code>DefaultSavedRequest</code> to determine the target URL on successful
- * authentication if the request that caused the authentication request was a GET. Defaults to false.
+ * Allows selective use of saved requests for a subset of requests. By default any request will be cached
+ * by the {@code saveRequest} method.
+ * <p>
+ * If set, only matching requests will be cached.
+ *
+ * @param requestMatcher a request matching strategy which defines which requests should be cached.
*/
- public void setJustUseSavedRequestOnGet(boolean justUseSavedRequestOnGet) {
- this.justUseSavedRequestOnGet = justUseSavedRequestOnGet;
+ public void setRequestMatcher(RequestMatcher requestMatcher) {
+ this.requestMatcher = requestMatcher;
}
/**
diff --git a/dist/spring-security-web/org/springframework/security/web/savedrequest/RequestCacheAwareFilter.java b/dist/spring-security-web/org/springframework/security/web/savedrequest/RequestCacheAwareFilter.java
index 909208d..6087c87 100644
--- a/dist/spring-security-web/org/springframework/security/web/savedrequest/RequestCacheAwareFilter.java
+++ b/dist/spring-security-web/org/springframework/security/web/savedrequest/RequestCacheAwareFilter.java
@@ -9,6 +9,7 @@ import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.springframework.util.Assert;
import org.springframework.web.filter.GenericFilterBean;
/**
@@ -24,7 +25,16 @@ import org.springframework.web.filter.GenericFilterBean;
*/
public class RequestCacheAwareFilter extends GenericFilterBean {
- private RequestCache requestCache = new HttpSessionRequestCache();
+ private RequestCache requestCache;
+
+ public RequestCacheAwareFilter() {
+ this(new HttpSessionRequestCache());
+ }
+
+ public RequestCacheAwareFilter(RequestCache requestCache) {
+ Assert.notNull(requestCache, "requestCache cannot be null");
+ this.requestCache = requestCache;
+ }
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
@@ -35,6 +45,10 @@ public class RequestCacheAwareFilter extends GenericFilterBean {
chain.doFilter(wrappedSavedRequest == null ? request : wrappedSavedRequest, response);
}
+ /**
+ * @deprecated Use constructor injection
+ */
+ @Deprecated
public void setRequestCache(RequestCache requestCache) {
this.requestCache = requestCache;
}
diff --git a/dist/spring-security-web/org/springframework/security/web/savedrequest/SavedCookie.java b/dist/spring-security-web/org/springframework/security/web/savedrequest/SavedCookie.java
index 6730c67..61edc16 100644
--- a/dist/spring-security-web/org/springframework/security/web/savedrequest/SavedCookie.java
+++ b/dist/spring-security-web/org/springframework/security/web/savedrequest/SavedCookie.java
@@ -9,14 +9,14 @@ import java.io.Serializable;
* @author Ray Krueger
*/
public class SavedCookie implements Serializable {
- private java.lang.String name;
- private java.lang.String value;
- private java.lang.String comment;
- private java.lang.String domain;
- private int maxAge;
- private java.lang.String path;
- private boolean secure;
- private int version;
+ private final java.lang.String name;
+ private final java.lang.String value;
+ private final java.lang.String comment;
+ private final java.lang.String domain;
+ private final int maxAge;
+ private final java.lang.String path;
+ private final boolean secure;
+ private final int version;
public SavedCookie(String name, String value, String comment, String domain, int maxAge, String path, boolean secure, int version) {
this.name = name;
diff --git a/dist/spring-security-web/org/springframework/security/web/savedrequest/SavedRequestAwareWrapper.java b/dist/spring-security-web/org/springframework/security/web/savedrequest/SavedRequestAwareWrapper.java
index 180f766..32826a6 100644
--- a/dist/spring-security-web/org/springframework/security/web/savedrequest/SavedRequestAwareWrapper.java
+++ b/dist/spring-security-web/org/springframework/security/web/savedrequest/SavedRequestAwareWrapper.java
@@ -66,7 +66,7 @@ class SavedRequestAwareWrapper extends HttpServletRequestWrapper {
* The set of SimpleDateFormat formats to use in getDateHeader(). Notice that because SimpleDateFormat is
* not thread-safe, we can't declare formats[] as a static variable.
*/
- protected SimpleDateFormat[] formats = new SimpleDateFormat[3];
+ protected final SimpleDateFormat[] formats = new SimpleDateFormat[3];
//~ Constructors ===================================================================================================
@@ -238,9 +238,9 @@ class SavedRequestAwareWrapper extends HttpServletRequestWrapper {
List<String> combinedParams = new ArrayList<String>(wrappedParamsList);
// We want to add all parameters of the saved request *apart from* duplicates of those already added
- for (int i = 0; i < savedRequestParams.length; i++) {
- if (!wrappedParamsList.contains(savedRequestParams[i])) {
- combinedParams.add(savedRequestParams[i]);
+ for (String savedRequestParam : savedRequestParams) {
+ if (!wrappedParamsList.contains(savedRequestParam)) {
+ combinedParams.add(savedRequestParam);
}
}
diff --git a/dist/spring-security-web/org/springframework/security/web/servletapi/SecurityContextHolderAwareRequestWrapper.java b/dist/spring-security-web/org/springframework/security/web/servletapi/SecurityContextHolderAwareRequestWrapper.java
index baf4276..8095433 100644
--- a/dist/spring-security-web/org/springframework/security/web/servletapi/SecurityContextHolderAwareRequestWrapper.java
+++ b/dist/spring-security-web/org/springframework/security/web/servletapi/SecurityContextHolderAwareRequestWrapper.java
@@ -45,13 +45,13 @@ import org.springframework.security.core.userdetails.UserDetails;
public class SecurityContextHolderAwareRequestWrapper extends HttpServletRequestWrapper {
//~ Instance fields ================================================================================================
- private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl();
+ private final AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl();
/**
* The prefix passed by the filter. It will be prepended to any supplied role values before
* comparing it with the roles obtained from the security context.
*/
- private String rolePrefix;
+ private final String rolePrefix;
//~ Constructors ===================================================================================================
@@ -127,7 +127,7 @@ public class SecurityContextHolderAwareRequestWrapper extends HttpServletRequest
return false;
}
- Collection<GrantedAuthority> authorities = auth.getAuthorities();
+ Collection<? extends GrantedAuthority> authorities = auth.getAuthorities();
if (authorities == null) {
return false;
@@ -159,4 +159,9 @@ public class SecurityContextHolderAwareRequestWrapper extends HttpServletRequest
public boolean isUserInRole(String role) {
return isGranted(role);
}
+
+ @Override
+ public String toString() {
+ return "SecurityContextHolderAwareRequestWrapper[ " + getRequest() + "]";
+ }
}
diff --git a/dist/spring-security-web/org/springframework/security/web/session/ConcurrentSessionFilter.java b/dist/spring-security-web/org/springframework/security/web/session/ConcurrentSessionFilter.java
index e907ff2..462d271 100644
--- a/dist/spring-security-web/org/springframework/security/web/session/ConcurrentSessionFilter.java
+++ b/dist/spring-security-web/org/springframework/security/web/session/ConcurrentSessionFilter.java
@@ -64,6 +64,22 @@ public class ConcurrentSessionFilter extends GenericFilterBean {
//~ Methods ========================================================================================================
+
+ /**
+ * @deprecated Use constructor which injects the <tt>SessionRegistry</tt>.
+ */
+ public ConcurrentSessionFilter() {
+ }
+
+ public ConcurrentSessionFilter(SessionRegistry sessionRegistry) {
+ this(sessionRegistry, null);
+ }
+
+ public ConcurrentSessionFilter(SessionRegistry sessionRegistry, String expiredUrl) {
+ this.sessionRegistry = sessionRegistry;
+ this.expiredUrl = expiredUrl;
+ }
+
@Override
public void afterPropertiesSet() {
Assert.notNull(sessionRegistry, "SessionRegistry required");
@@ -101,7 +117,7 @@ public class ConcurrentSessionFilter extends GenericFilterBean {
return;
} else {
// Non-expired - update last request date/time
- info.refreshLastRequest();
+ sessionRegistry.refreshLastRequest(info.getSessionId());
}
}
}
@@ -116,15 +132,23 @@ public class ConcurrentSessionFilter extends GenericFilterBean {
private void doLogout(HttpServletRequest request, HttpServletResponse response) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
- for (int i = 0; i < handlers.length; i++) {
- handlers[i].logout(request, response, auth);
+ for (LogoutHandler handler : handlers) {
+ handler.logout(request, response, auth);
}
}
+ /**
+ * @deprecated use constructor injection instead
+ */
+ @Deprecated
public void setExpiredUrl(String expiredUrl) {
this.expiredUrl = expiredUrl;
}
+ /**
+ * @deprecated use constructor injection instead
+ */
+ @Deprecated
public void setSessionRegistry(SessionRegistry sessionRegistry) {
this.sessionRegistry = sessionRegistry;
}
diff --git a/dist/spring-security-web/org/springframework/security/web/session/HttpSessionCreatedEvent.java b/dist/spring-security-web/org/springframework/security/web/session/HttpSessionCreatedEvent.java
index 8c67702..bc1cc71 100644
--- a/dist/spring-security-web/org/springframework/security/web/session/HttpSessionCreatedEvent.java
+++ b/dist/spring-security-web/org/springframework/security/web/session/HttpSessionCreatedEvent.java
@@ -20,7 +20,7 @@ import javax.servlet.http.HttpSession;
import org.springframework.security.core.session.SessionCreationEvent;
/**
- * Published by the {@link HttpSessionEventPublisher} when a HttpSession is destroyed by the container
+ * Published by the {@link HttpSessionEventPublisher} when an {@code HttpSession} is created by the container
*
* @author Ray Krueger
* @author Luke Taylor
diff --git a/dist/spring-security-web/org/springframework/security/web/session/HttpSessionDestroyedEvent.java b/dist/spring-security-web/org/springframework/security/web/session/HttpSessionDestroyedEvent.java
index cb7f219..805259b 100644
--- a/dist/spring-security-web/org/springframework/security/web/session/HttpSessionDestroyedEvent.java
+++ b/dist/spring-security-web/org/springframework/security/web/session/HttpSessionDestroyedEvent.java
@@ -19,8 +19,8 @@ import javax.servlet.http.HttpSession;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.session.SessionDestroyedEvent;
-import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
+import java.util.*;
/**
* Published by the {@link HttpSessionEventPublisher} when a HttpSession is created in the container
@@ -39,9 +39,23 @@ public class HttpSessionDestroyedEvent extends SessionDestroyedEvent {
return (HttpSession) getSource();
}
+ @SuppressWarnings("unchecked")
@Override
- public SecurityContext getSecurityContext() {
- return (SecurityContext) ((HttpSession)getSource()).getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
+ public List<SecurityContext> getSecurityContexts() {
+ HttpSession session = (HttpSession)getSource();
+
+ Enumeration<String> attributes = session.getAttributeNames();
+
+ ArrayList<SecurityContext> contexts = new ArrayList<SecurityContext>();
+
+ while(attributes.hasMoreElements()) {
+ Object attribute = attributes.nextElement();
+ if (attribute instanceof SecurityContext) {
+ contexts.add((SecurityContext) attribute);
+ }
+ }
+
+ return contexts;
}
@Override
diff --git a/dist/spring-security-web/org/springframework/security/web/session/SessionManagementFilter.java b/dist/spring-security-web/org/springframework/security/web/session/SessionManagementFilter.java
index e30830e..8d2e6d0 100644
--- a/dist/spring-security-web/org/springframework/security/web/session/SessionManagementFilter.java
+++ b/dist/spring-security-web/org/springframework/security/web/session/SessionManagementFilter.java
@@ -13,8 +13,6 @@ import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.web.DefaultRedirectStrategy;
-import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.web.authentication.session.SessionAuthenticationException;
@@ -41,14 +39,20 @@ public class SessionManagementFilter extends GenericFilterBean {
//~ Instance fields ================================================================================================
private final SecurityContextRepository securityContextRepository;
- private SessionAuthenticationStrategy sessionStrategy = new SessionFixationProtectionStrategy();
- private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl();
- private String invalidSessionUrl;
+ private SessionAuthenticationStrategy sessionAuthenticationStrategy;
+ private final AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl();
+ private InvalidSessionStrategy invalidSessionStrategy = null;
private AuthenticationFailureHandler failureHandler = new SimpleUrlAuthenticationFailureHandler();
- private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
public SessionManagementFilter(SecurityContextRepository securityContextRepository) {
+ this(securityContextRepository, new SessionFixationProtectionStrategy());
+ }
+
+ public SessionManagementFilter(SecurityContextRepository securityContextRepository, SessionAuthenticationStrategy sessionStrategy) {
+ Assert.notNull(securityContextRepository, "SecurityContextRepository cannot be null");
+ Assert.notNull(sessionStrategy, "SessionAuthenticationStrategy cannot be null");
this.securityContextRepository = securityContextRepository;
+ this.sessionAuthenticationStrategy = sessionStrategy;
}
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
@@ -69,7 +73,7 @@ public class SessionManagementFilter extends GenericFilterBean {
if (authentication != null && !authenticationTrustResolver.isAnonymous(authentication)) {
// The user has been authenticated during the current request, so call the session strategy
try {
- sessionStrategy.onAuthentication(authentication, request, response);
+ sessionAuthenticationStrategy.onAuthentication(authentication, request, response);
} catch (SessionAuthenticationException e) {
// The session strategy can reject the authentication
logger.debug("SessionAuthenticationStrategy rejected the authentication object", e);
@@ -86,11 +90,8 @@ public class SessionManagementFilter extends GenericFilterBean {
if (request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid()) {
logger.debug("Requested session ID" + request.getRequestedSessionId() + " is invalid.");
- if (invalidSessionUrl != null) {
- logger.debug("Starting new session (if required) and redirecting to '" + invalidSessionUrl + "'");
- request.getSession();
- redirectStrategy.sendRedirect(request, response, invalidSessionUrl);
-
+ if (invalidSessionStrategy != null) {
+ invalidSessionStrategy.onInvalidSessionDetected(request, response);
return;
}
}
@@ -104,21 +105,23 @@ public class SessionManagementFilter extends GenericFilterBean {
* Sets the strategy object which handles the session management behaviour when a
* user has been authenticated during the current request.
*
- * @param sessionStrategy the strategy object. If not set, a {@link SessionFixationProtectionStrategy} is used.
+ * @param sessionAuthenticationStrategy the strategy object. If not set, a {@link SessionFixationProtectionStrategy} is used.
+ * @deprecated Use constructor injection
*/
- public void setSessionAuthenticationStrategy(SessionAuthenticationStrategy sessionStrategy) {
- Assert.notNull(sessionStrategy, "authenticatedSessionStratedy must not be null");
- this.sessionStrategy = sessionStrategy;
+ @Deprecated
+ public void setSessionAuthenticationStrategy(SessionAuthenticationStrategy sessionAuthenticationStrategy) {
+ Assert.notNull(sessionAuthenticationStrategy, "authenticatedSessionStrategy must not be null");
+ this.sessionAuthenticationStrategy = sessionAuthenticationStrategy;
}
/**
- * Sets the URL to which the response should be redirected if the user agent requests an invalid session Id.
- * If the property is not set, no action will be taken.
+ * Sets the strategy which will be invoked instead of allowing the filter chain to prceed, if the user agent
+ * requests an invalid session Id. If the property is not set, no action will be taken.
*
- * @param invalidSessionUrl
+ * @param invalidSessionStrategy the strategy to invoke. Typically a {@link SimpleRedirectInvalidSessionStrategy}.
*/
- public void setInvalidSessionUrl(String invalidSessionUrl) {
- this.invalidSessionUrl = invalidSessionUrl;
+ public void setInvalidSessionStrategy(InvalidSessionStrategy invalidSessionStrategy) {
+ this.invalidSessionStrategy = invalidSessionStrategy;
}
/**
@@ -131,8 +134,4 @@ public class SessionManagementFilter extends GenericFilterBean {
Assert.notNull(failureHandler, "failureHandler cannot be null");
this.failureHandler = failureHandler;
}
-
- public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
- this.redirectStrategy = redirectStrategy;
- }
}
diff --git a/dist/spring-security-web/org/springframework/security/web/util/AntUrlPathMatcher.java b/dist/spring-security-web/org/springframework/security/web/util/AntUrlPathMatcher.java
deleted file mode 100644
index f0fbadf..0000000
--- a/dist/spring-security-web/org/springframework/security/web/util/AntUrlPathMatcher.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package org.springframework.security.web.util;
-
-import org.springframework.util.PathMatcher;
-import org.springframework.util.AntPathMatcher;
-
-/**
- * Ant path strategy for URL matching.
- *
- * @author Luke Taylor
- */
-public class AntUrlPathMatcher implements UrlMatcher {
- private boolean requiresLowerCaseUrl = true;
- private PathMatcher pathMatcher = new AntPathMatcher();
-
- public AntUrlPathMatcher() {
- this(true);
- }
-
- public AntUrlPathMatcher(boolean requiresLowerCaseUrl) {
- this.requiresLowerCaseUrl = requiresLowerCaseUrl;
- }
-
- public Object compile(String path) {
- if (requiresLowerCaseUrl) {
- return path.toLowerCase();
- }
-
- return path;
- }
-
- public void setRequiresLowerCaseUrl(boolean requiresLowerCaseUrl) {
- this.requiresLowerCaseUrl = requiresLowerCaseUrl;
- }
-
- public boolean pathMatchesUrl(Object path, String url) {
- return pathMatcher.match((String)path, url);
- }
-
- public String getUniversalMatchPattern() {
- return "/**";
- }
-
- public boolean requiresLowerCaseUrl() {
- return requiresLowerCaseUrl;
- }
-
- public String toString() {
- return getClass().getName() + "[requiresLowerCase='" + requiresLowerCaseUrl + "']";
- }
-}
diff --git a/dist/spring-security-web/org/springframework/security/web/util/ELRequestMatcher.java b/dist/spring-security-web/org/springframework/security/web/util/ELRequestMatcher.java
index 9a2f751..e188444 100644
--- a/dist/spring-security-web/org/springframework/security/web/util/ELRequestMatcher.java
+++ b/dist/spring-security-web/org/springframework/security/web/util/ELRequestMatcher.java
@@ -19,7 +19,6 @@ package org.springframework.security.web.util;
import javax.servlet.http.HttpServletRequest;
import org.springframework.expression.EvaluationContext;
-import org.springframework.expression.EvaluationException;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
@@ -28,10 +27,10 @@ import org.springframework.security.web.authentication.DelegatingAuthenticationE
/**
* A RequestMatcher implementation which uses a SpEL expression
*
- * <p>With the default EvalutationContext ({@link ELRequestMatcherContext}) you can use
+ * <p>With the default EvaluationContext ({@link ELRequestMatcherContext}) you can use
* <code>hasIpAdress()</code> and <code>hasHeader()</code></p>
*
- * <p>See {@link DelegatingAuthenticationEntryPoint} for a example configuration.</p>
+ * <p>See {@link DelegatingAuthenticationEntryPoint} for an example configuration.</p>
*
*
* @author Mike Wiesner
@@ -39,7 +38,7 @@ import org.springframework.security.web.authentication.DelegatingAuthenticationE
*/
public class ELRequestMatcher implements RequestMatcher {
- private Expression expression;
+ private final Expression expression;
public ELRequestMatcher(String el) {
SpelExpressionParser parser = new SpelExpressionParser();
@@ -48,7 +47,7 @@ public class ELRequestMatcher implements RequestMatcher {
public boolean matches(HttpServletRequest request) {
EvaluationContext context = createELContext(request);
- return evaluateAsBoolean(expression, context);
+ return expression.getValue(context, Boolean.class).booleanValue();
}
/**
@@ -60,11 +59,4 @@ public class ELRequestMatcher implements RequestMatcher {
return new StandardEvaluationContext(new ELRequestMatcherContext(request));
}
- private boolean evaluateAsBoolean(Expression expr, EvaluationContext ctx) {
- try {
- return ((Boolean) expr.getValue(ctx, Boolean.class)).booleanValue();
- } catch (EvaluationException e) {
- throw new IllegalArgumentException("Failed to evaluate expression '" + expr.getExpressionString() + "'", e);
- }
- }
}
diff --git a/dist/spring-security-web/org/springframework/security/web/util/ELRequestMatcherContext.java b/dist/spring-security-web/org/springframework/security/web/util/ELRequestMatcherContext.java
index b675e30..ab6fa70 100644
--- a/dist/spring-security-web/org/springframework/security/web/util/ELRequestMatcherContext.java
+++ b/dist/spring-security-web/org/springframework/security/web/util/ELRequestMatcherContext.java
@@ -22,7 +22,7 @@ import org.springframework.util.StringUtils;
class ELRequestMatcherContext {
- private HttpServletRequest request;
+ private final HttpServletRequest request;
public ELRequestMatcherContext(HttpServletRequest request) {
this.request = request;
@@ -34,7 +34,7 @@ class ELRequestMatcherContext {
public boolean hasHeader(String headerName, String value) {
String header = request.getHeader(headerName);
- if (StringUtils.hasText(header) == false) {
+ if (!StringUtils.hasText(header)) {
return false;
}
diff --git a/dist/spring-security-web/org/springframework/security/web/util/IpAddressMatcher.java b/dist/spring-security-web/org/springframework/security/web/util/IpAddressMatcher.java
index cb966c8..57611e1 100644
--- a/dist/spring-security-web/org/springframework/security/web/util/IpAddressMatcher.java
+++ b/dist/spring-security-web/org/springframework/security/web/util/IpAddressMatcher.java
@@ -17,7 +17,7 @@ import org.springframework.util.StringUtils;
* @author Luke Taylor
* @since 3.0.2
*/
-public class IpAddressMatcher implements RequestMatcher {
+public final class IpAddressMatcher implements RequestMatcher {
private final int nMaskBits;
private final InetAddress requiredAddress;
@@ -34,19 +34,23 @@ public class IpAddressMatcher implements RequestMatcher {
ipAddress = addressAndMask[0];
nMaskBits = Integer.parseInt(addressAndMask[1]);
} else {
- nMaskBits = 0;
+ nMaskBits = -1;
}
requiredAddress = parseAddress(ipAddress);
}
public boolean matches(HttpServletRequest request) {
- InetAddress remoteAddress = parseAddress(request.getRemoteAddr());
+ return matches(request.getRemoteAddr());
+ }
+
+ public boolean matches(String address) {
+ InetAddress remoteAddress = parseAddress(address);
if (!requiredAddress.getClass().equals(remoteAddress.getClass())) {
return false;
}
- if (nMaskBits == 0) {
+ if (nMaskBits < 0) {
return remoteAddress.equals(requiredAddress);
}
diff --git a/dist/spring-security-web/org/springframework/security/web/util/RegexUrlPathMatcher.java b/dist/spring-security-web/org/springframework/security/web/util/RegexUrlPathMatcher.java
deleted file mode 100644
index 5445d07..0000000
--- a/dist/spring-security-web/org/springframework/security/web/util/RegexUrlPathMatcher.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.springframework.security.web.util;
-
-import java.util.regex.Pattern;
-
-/**
- * @author Luke Taylor
- */
-public class RegexUrlPathMatcher implements UrlMatcher {
- private boolean requiresLowerCaseUrl = false;
-
- public Object compile(String path) {
- return Pattern.compile(path);
- }
-
- public void setRequiresLowerCaseUrl(boolean requiresLowerCaseUrl) {
- this.requiresLowerCaseUrl = requiresLowerCaseUrl;
- }
-
- public boolean pathMatchesUrl(Object compiledPath, String url) {
- Pattern pattern = (Pattern)compiledPath;
-
- return pattern.matcher(url).matches();
- }
-
- public String getUniversalMatchPattern() {
- return "/.*";
- }
-
- public boolean requiresLowerCaseUrl() {
- return requiresLowerCaseUrl;
- }
-}
diff --git a/dist/spring-security-web/org/springframework/security/web/util/TextEscapeUtils.java b/dist/spring-security-web/org/springframework/security/web/util/TextEscapeUtils.java
index b339c4a..fdd9943 100644
--- a/dist/spring-security-web/org/springframework/security/web/util/TextEscapeUtils.java
+++ b/dist/spring-security-web/org/springframework/security/web/util/TextEscapeUtils.java
@@ -9,7 +9,7 @@ package org.springframework.security.web.util;
*/
public abstract class TextEscapeUtils {
- public final static String escapeEntities(String s) {
+ public static String escapeEntities(String s) {
if (s == null || s.length() == 0) {
return s;
}
diff --git a/dist/spring-security-web/org/springframework/security/web/util/ThrowableAnalyzer.java b/dist/spring-security-web/org/springframework/security/web/util/ThrowableAnalyzer.java
index f201d29..1ac4a25 100644
--- a/dist/spring-security-web/org/springframework/security/web/util/ThrowableAnalyzer.java
+++ b/dist/spring-security-web/org/springframework/security/web/util/ThrowableAnalyzer.java
@@ -175,7 +175,7 @@ public class ThrowableAnalyzer {
for (Map.Entry<Class<? extends Throwable>, ThrowableCauseExtractor> entry : extractorMap.entrySet()) {
Class<? extends Throwable> throwableType = entry.getKey();
if (throwableType.isInstance(throwable)) {
- ThrowableCauseExtractor extractor = (ThrowableCauseExtractor) entry.getValue();
+ ThrowableCauseExtractor extractor = entry.getValue();
return extractor.extractCause(throwable);
}
}
@@ -198,9 +198,7 @@ public class ThrowableAnalyzer {
*/
public final Throwable getFirstThrowableOfType(Class<? extends Throwable> throwableType, Throwable[] chain) {
if (chain != null) {
- for (int i = 0; i < chain.length; ++i) {
- Throwable t = chain[i];
-
+ for (Throwable t : chain) {
if ((t != null) && throwableType.isInstance(t)) {
return t;
}
@@ -223,7 +221,7 @@ public class ThrowableAnalyzer {
* @throws IllegalArgumentException if <code>throwable</code> is either <code>null</code>
* or its type is not assignable to <code>expectedBaseType</code>
*/
- public static final void verifyThrowableHierarchy(Throwable throwable, Class<? extends Throwable> expectedBaseType) {
+ public static void verifyThrowableHierarchy(Throwable throwable, Class<? extends Throwable> expectedBaseType) {
if (expectedBaseType == null) {
return;
}
diff --git a/dist/spring-security-web/org/springframework/security/web/util/UrlMatcher.java b/dist/spring-security-web/org/springframework/security/web/util/UrlMatcher.java
deleted file mode 100644
index 5367267..0000000
--- a/dist/spring-security-web/org/springframework/security/web/util/UrlMatcher.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.springframework.security.web.util;
-
-/**
- * Strategy for deciding whether configured path matches a submitted candidate URL.
- *
- * @author Luke Taylor
- * @since 2.0
- */
-public interface UrlMatcher {
-
- Object compile(String urlPattern);
-
- boolean pathMatchesUrl(Object compiledUrlPattern, String url);
-
- /** Returns the path which matches every URL */
- String getUniversalMatchPattern();
-
- /**
- * Returns true if the matcher expects the URL to be converted to lower case before
- * calling {@link #pathMatchesUrl(Object, String)}.
- */
- boolean requiresLowerCaseUrl();
-}
diff --git a/dist/spring-security-web/org/springframework/security/web/util/UrlUtils.java b/dist/spring-security-web/org/springframework/security/web/util/UrlUtils.java
index fb679e0..c4f40cf 100644
--- a/dist/spring-security-web/org/springframework/security/web/util/UrlUtils.java
+++ b/dist/spring-security-web/org/springframework/security/web/util/UrlUtils.java
@@ -129,7 +129,7 @@ public final class UrlUtils {
* Decides if a URL is absolute based on whether it contains a valid scheme name, as defined in RFC 1738.
*/
public static boolean isAbsoluteUrl(String url) {
- final Pattern ABSOLUTE_URL = Pattern.compile("\\A[a-z.+-]+://.*", Pattern.CASE_INSENSITIVE);
+ final Pattern ABSOLUTE_URL = Pattern.compile("\\A[a-z0-9.+-]+://.*", Pattern.CASE_INSENSITIVE);
return ABSOLUTE_URL.matcher(url).matches();
}
diff --git a/docs/reference/advanced-topics.html b/docs/reference/advanced-topics.html
index 264690a..40bf26b 100644
--- a/docs/reference/advanced-topics.html
+++ b/docs/reference/advanced-topics.html
@@ -1,6 +1,6 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>Part V. Additional Topics</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="springsecurity.html" title="Spring Security"><link rel="prev" href="el-access.html" title="15. Expression-Based Access Control"><link rel="next" href="domain-acls.html" title="16. Domain Object Security (ACLs)"><!--Begin Google Analytics code--><script type="text/javascript">
+ <title>Part V. Additional Topics</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="springsecurity.html" title="Spring Security"><link rel="prev" href="el-access.html" title="16. Expression-Based Access Control"><link rel="next" href="domain-acls.html" title="17. Domain Object Security (ACLs)"><!--Begin Google Analytics code--><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
@@ -8,8 +8,9 @@
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
- </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Part V. Additional Topics</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="el-access.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="domain-acls.html">Next</a></td></tr></table><hr></div><div class="part" title="Part V. Additional Topics"><div class="titlepage"><div><div><h1 class="title"><a name="advanced-topics"></a>Part V. Additional Topics</h1></div></div></div><div class="partintro" title="Additional Topics"><div></div><p> In this part we cover features which require a knowledge of previous chapters as well
- as some of the more advanced and less-commonly used features of the framework.</p></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
+ </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Part V. Additional Topics</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="el-access.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="domain-acls.html">Next</a></td></tr></table><hr></div><div class="part" title="Part V. Additional Topics"><div class="titlepage"><div><div><h1 class="title"><a name="advanced-topics"></a>Part V. Additional Topics</h1></div></div></div><div class="partintro" title="Additional Topics"><div></div><p> In this part we cover features which require a knowledge of previous chapters as
+ well as some of the more advanced and less-commonly used features of the
+ framework.</p></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
- </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="el-access.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="domain-acls.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">15. Expression-Based Access Control </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 16. Domain Object Security (ACLs)</td></tr></table></div></body></html>
\ No newline at end of file
+ </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="el-access.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="domain-acls.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">16. Expression-Based Access Control </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 17. Domain Object Security (ACLs)</td></tr></table></div></body></html>
\ No newline at end of file
diff --git a/docs/reference/anonymous.html b/docs/reference/anonymous.html
index 3dcec27..52172b3 100644
--- a/docs/reference/anonymous.html
+++ b/docs/reference/anonymous.html
@@ -1,6 +1,6 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>12. Anonymous Authentication</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="web-app-security.html" title="Part III. Web Application Security"><link rel="prev" href="session-mgmt.html" title="11. Session Management"><link rel="next" href="authorization.html" title="Part IV. Authorization"><!--Begin Google Analytics code--><script type="text/javascript">
+ <title>13. Anonymous Authentication</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="web-app-security.html" title="Part III. Web Application Security"><link rel="prev" href="session-mgmt.html" title="12. Session Management"><link rel="next" href="authorization.html" title="Part IV. Authorization"><!--Begin Google Analytics code--><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
@@ -8,89 +8,84 @@
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
- </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">12. Anonymous Authentication</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="session-mgmt.html">Prev</a> </td><th width="60%" align="center">Part III. Web Application Security</th><td width="20%" align="right"> <a accesskey="n" href="authorization.html">Next</a></td></tr></table><hr></div><div class="chapter" title="12. Anonymous Authentication"><div class="titlepage"><div><div><h1 class="title"><a name="anonymous"></a>Anonymous Authentication</h1></div></div></div><div class="section" title="12.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="anonymous-overview"></a>12.1 Overview</h2></div></div></div><p>It's generally considered good security practice to adopt a
- <span class="quote">“<span class="quote">deny-by-default</span>”</span> where you explicitly specify what is allowed and
- disallow everything else. Defining what is accessible to unauthenticated users is a
- similar situation, particularly for web applications. Many sites require that users must
- be authenticated for anything other than a few URLs (for example the home and login
- pages). In this case it is easiest to define access configuration attributes for these
- specific URLs rather than have for every secured resource. Put differently, sometimes it
- is nice to say <code class="literal">ROLE_SOMETHING</code> is required by default and only allow
- certain exceptions to this rule, such as for login, logout and home pages of an
- application. You could also omit these pages from the filter chain entirely, thus
- bypassing the access control checks, but this may be undesirable for other reasons,
- particularly if the pages behave differently for authenticated users.</p><p>This is what we mean by anonymous authentication. Note that there is no real
+ </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">13. Anonymous Authentication</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="session-mgmt.html">Prev</a> </td><th width="60%" align="center">Part III. Web Application Security</th><td width="20%" align="right"> <a accesskey="n" href="authorization.html">Next</a></td></tr></table><hr></div><div class="chapter" title="13. Anonymous Authentication"><div class="titlepage"><div><div><h1 class="title"><a name="anonymous"></a>Anonymous Authentication</h1></div></div></div><div class="section" title="13.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="anonymous-overview"></a>13.1 Overview</h2></div></div></div><p>It's generally considered good security practice to adopt a
+ <span class="quote">“<span class="quote">deny-by-default</span>”</span> where you explicitly specify what is allowed and disallow
+ everything else. Defining what is accessible to unauthenticated users is a similar
+ situation, particularly for web applications. Many sites require that users must be
+ authenticated for anything other than a few URLs (for example the home and login pages).
+ In this case it is easiest to define access configuration attributes for these specific
+ URLs rather than have for every secured resource. Put differently, sometimes it is nice
+ to say <code class="literal">ROLE_SOMETHING</code> is required by default and only allow certain
+ exceptions to this rule, such as for login, logout and home pages of an application. You
+ could also omit these pages from the filter chain entirely, thus bypassing the access
+ control checks, but this may be undesirable for other reasons, particularly if the pages
+ behave differently for authenticated users.</p><p>This is what we mean by anonymous authentication. Note that there is no real
conceptual difference between a user who is <span class="quote">“<span class="quote">anonymously authenticated</span>”</span> and
an unauthenticated user. Spring Security's anonymous authentication just gives you a
more convenient way to configure your access-control attributes. Calls to servlet API
calls such as <code class="methodname">getCallerPrincipal</code>, for example, will still
return null even though there is actually an anonymous authentication object in the
- <code class="classname">SecurityContextHolder</code>.</p><p>There are other situations where anonymous authentication is useful, such as when an
+ <code class="classname">SecurityContextHolder</code>.</p><p>There are other situations where anonymous authentication is useful, such as when an
auditing interceptor queries the <code class="classname">SecurityContextHolder</code> to
identify which principal was responsible for a given operation. Classes can be authored
more robustly if they know the <code class="classname">SecurityContextHolder</code> always
contains an <code class="interfacename">Authentication</code> object, and never
- <code class="literal">null</code>.</p></div><div class="section" title="12.2 Configuration"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="anonymous-config"></a>12.2 Configuration</h2></div></div></div><p>Anonymous authentication support is provided automatically when using the HTTP
+ <code class="literal">null</code>.</p></div><div class="section" title="13.2 Configuration"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="anonymous-config"></a>13.2 Configuration</h2></div></div></div><p>Anonymous authentication support is provided automatically when using the HTTP
configuration Spring Security 3.0 and can be customized (or disabled) using the
- <code class="literal"><anonymous></code> element. You don't need to configure the beans
+ <code class="literal"><anonymous></code> element. You don't need to configure the beans
described here unless you are using traditional bean configuration.</p><p>Three classes that together provide the anonymous authentication feature.
- <code class="literal">AnonymousAuthenticationToken</code> is an implementation of
- <code class="interfacename">Authentication</code>, and stores the
- <code class="interfacename">GrantedAuthority</code>s which apply to the anonymous
- principal. There is a corresponding <code class="literal">AnonymousAuthenticationProvider</code>,
- which is chained into the <code class="literal">ProviderManager</code> so that
- <code class="literal">AnonymousAuthenticationToken</code>s are accepted. Finally, there is an
- <code class="classname">AnonymousAuthenticationFilter</code>, which is chained after the
- normal authentication mechanisms and automatically adds an
- <code class="literal">AnonymousAuthenticationToken</code> to the
- <code class="classname">SecurityContextHolder</code> if there is no existing
- <code class="interfacename">Authentication</code> held there. The definition of the
- filter and authentication provider appears as follows:</p><p>
- </p><pre class="programlisting">
+ <code class="literal">AnonymousAuthenticationToken</code> is an implementation of
+ <code class="interfacename">Authentication</code>, and stores the
+ <code class="interfacename">GrantedAuthority</code>s which apply to the anonymous principal.
+ There is a corresponding <code class="literal">AnonymousAuthenticationProvider</code>, which is
+ chained into the <code class="literal">ProviderManager</code> so that
+ <code class="literal">AnonymousAuthenticationToken</code>s are accepted. Finally, there is an
+ <code class="classname">AnonymousAuthenticationFilter</code>, which is chained after the normal
+ authentication mechanisms and automatically adds an
+ <code class="literal">AnonymousAuthenticationToken</code> to the
+ <code class="classname">SecurityContextHolder</code> if there is no existing
+ <code class="interfacename">Authentication</code> held there. The definition of the filter
+ and authentication provider appears as follows:</p><p> </p><pre class="programlisting">
-<bean id="anonymousAuthFilter"
- class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter">
- <property name="key" value="foobar"/>
- <property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS"/>
-</bean>
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"anonymousAuthFilter"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.authentication.AnonymousAuthenticationFilter"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"key"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"foobar"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"userAttribute"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"anonymousUser,ROLE_ANONYMOUS"</span><span class="hl-tag">/></span>
+<span class="hl-tag"></bean></span>
-<bean id="anonymousAuthenticationProvider"
- class="org.springframework.security.authentication.AnonymousAuthenticationProvider">
- <property name="key" value="foobar"/>
-</bean>
- </pre><p>
- </p><p>The <code class="literal">key</code> is shared between the filter and authentication provider,
- so that tokens created by the former are accepted by the latter<sup>[<a name="d0e4035" href="#ftn.d0e4035" class="footnote">14</a>]</sup>. The
- <code class="literal">userAttribute</code> is expressed in the form of
- <code class="literal">usernameInTheAuthenticationToken,grantedAuthority[,grantedAuthority]</code>.
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"anonymousAuthenticationProvider"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.authentication.AnonymousAuthenticationProvider"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"key"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"foobar"</span><span class="hl-tag">/></span>
+<span class="hl-tag"></bean></span>
+ </pre><p> </p><p>The <code class="literal">key</code> is shared between the filter and authentication provider,
+ so that tokens created by the former are accepted by the latter<sup>[<a name="d0e4644" href="#ftn.d0e4644" class="footnote">21</a>]</sup>. The <code class="literal">userAttribute</code> is expressed in the form of
+ <code class="literal">usernameInTheAuthenticationToken,grantedAuthority[,grantedAuthority]</code>.
This is the same syntax as used after the equals sign for
- <code class="literal">InMemoryDaoImpl</code>'s <code class="literal">userMap</code> property.</p><p>As explained earlier, the benefit of anonymous authentication is that all URI patterns
- can have security applied to them. For example:</p><p>
- </p><pre class="programlisting">
+ <code class="literal">InMemoryDaoImpl</code>'s <code class="literal">userMap</code> property.</p><p>As explained earlier, the benefit of anonymous authentication is that all URI patterns
+ can have security applied to them. For example:</p><p> </p><pre class="programlisting">
-<bean id="filterSecurityInterceptor"
- class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
- <property name="authenticationManager" ref="authenticationManager"/>
- <property name="accessDecisionManager" ref="httpRequestAccessDecisionManager"/>
- <property name="securityMetadata">
- <security:filter-security-metadata-source>
- <security:intercept-url pattern='/index.jsp' access='ROLE_ANONYMOUS,ROLE_USER'/>
- <security:intercept-url pattern='/hello.htm' access='ROLE_ANONYMOUS,ROLE_USER'/>
- <security:intercept-url pattern='/logoff.jsp' access='ROLE_ANONYMOUS,ROLE_USER'/>
- <security:intercept-url pattern='/login.jsp' access='ROLE_ANONYMOUS,ROLE_USER'/>
- <security:intercept-url pattern='/**' access='ROLE_USER'/>
- </security:filter-security-metadata-source>" +
- </property>
-</bean>
- </pre><p>
- </p></div><div class="section" title="12.3 AuthenticationTrustResolver"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="anonymous-auth-trust-resolver"></a>12.3 <code class="interfacename">AuthenticationTrustResolver</code></h2></div></div></div><p> Rounding out the anonymous authentication discussion is the
- <code class="interfacename">AuthenticationTrustResolver</code> interface, with its
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"filterSecurityInterceptor"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.access.intercept.FilterSecurityInterceptor"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"authenticationManager"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"accessDecisionManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"httpRequestAccessDecisionManager"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"securityMetadata"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><security:filter-security-metadata-source></span>
+ <span class="hl-tag"><security:intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">'/index.jsp'</span> <span class="hl-attribute">access</span>=<span class="hl-value">'ROLE_ANONYMOUS,ROLE_USER'</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><security:intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">'/hello.htm'</span> <span class="hl-attribute">access</span>=<span class="hl-value">'ROLE_ANONYMOUS,ROLE_USER'</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><security:intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">'/logoff.jsp'</span> <span class="hl-attribute">access</span>=<span class="hl-value">'ROLE_ANONYMOUS,ROLE_USER'</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><security:intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">'/login.jsp'</span> <span class="hl-attribute">access</span>=<span class="hl-value">'ROLE_ANONYMOUS,ROLE_USER'</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><security:intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">'/**'</span> <span class="hl-attribute">access</span>=<span class="hl-value">'ROLE_USER'</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></security:filter-security-metadata-source></span>" +
+ <span class="hl-tag"></property></span>
+<span class="hl-tag"></bean></span>
+ </pre><p> </p></div><div class="section" title="13.3 AuthenticationTrustResolver"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="anonymous-auth-trust-resolver"></a>13.3 <code class="interfacename">AuthenticationTrustResolver</code></h2></div></div></div><p> Rounding out the anonymous authentication discussion is the
+ <code class="interfacename">AuthenticationTrustResolver</code> interface, with its
corresponding <code class="literal">AuthenticationTrustResolverImpl</code> implementation. This
interface provides an <code class="literal">isAnonymous(Authentication)</code> method, which
allows interested classes to take into account this special type of authentication
status. The <code class="classname">ExceptionTranslationFilter</code> uses this interface in
processing <code class="literal">AccessDeniedException</code>s. If an
- <code class="literal">AccessDeniedException</code> is thrown, and the authentication is of an
+ <code class="literal">AccessDeniedException</code> is thrown, and the authentication is of an
anonymous type, instead of throwing a 403 (forbidden) response, the filter will instead
commence the <code class="interfacename">AuthenticationEntryPoint</code> so the principal
can authenticate properly. This is a necessary distinction, otherwise principals would
@@ -99,27 +94,26 @@
interceptor configuration replaced with <code class="literal">IS_AUTHENTICATED_ANONYMOUSLY</code>,
which is effectively the same thing when defining access controls. This is an example of
the use of the <code class="classname">AuthenticatedVoter</code> which we will see in the <a class="link" href="authz-arch.html#authz-authenticated-voter" title="AuthenticatedVoter">authorization chapter</a>. It uses an
- <code class="interfacename">AuthenticationTrustResolver</code> to process this
- particular configuration attribute and grant access to anonymous users. The
- <code class="classname">AuthenticatedVoter</code> approach is more powerful, since it allows
- you to differentiate between anonymous, remember-me and fully-authenticated users. If
- you don't need this functionality though, then you can stick with
- <code class="literal">ROLE_ANONYMOUS</code>, which will be processed by Spring Security's
- standard <code class="classname">RoleVoter</code>. </p></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e4035" href="#d0e4035" class="para">14</a>] </sup>The use
- of the <code class="literal">key</code> property should not be regarded as providing any
- real security here. It is merely a book-keeping exercise. If you are sharing a
- <code class="classname">ProviderManager</code> which contains an
- <code class="classname">AnonymousAuthenticationProvider</code> in a scenario where
- it is possible for an authenticating client to construct the
- <code class="interfacename">Authentication</code> object (such as with RMI
- invocations), then a malicious client could submit an
- <code class="classname">AnonymousAuthenticationToken</code> which it had created
- itself (with chosen username and authority list). If the <code class="literal">key</code>
- is guessable or can be found out, then the token would be accepted by the
- anonymous provider. This isn't a problem with normal usage but if you are using
- RMI you would be best to use a customized <code class="classname">ProviderManager</code>
- which omits the anonymous provider rather than sharing the one you use for your
- HTTP authentication mechanisms.</p></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
+ <code class="interfacename">AuthenticationTrustResolver</code> to process this particular
+ configuration attribute and grant access to anonymous users. The
+ <code class="classname">AuthenticatedVoter</code> approach is more powerful, since it allows you
+ to differentiate between anonymous, remember-me and fully-authenticated users. If you
+ don't need this functionality though, then you can stick with
+ <code class="literal">ROLE_ANONYMOUS</code>, which will be processed by Spring Security's standard
+ <code class="classname">RoleVoter</code>. </p></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e4644" href="#d0e4644" class="para">21</a>] </sup>The use of the <code class="literal">key</code> property should not be regarded as providing
+ any real security here. It is merely a book-keeping exercise. If you are sharing a
+ <code class="classname">ProviderManager</code> which contains an
+ <code class="classname">AnonymousAuthenticationProvider</code> in a scenario where it is
+ possible for an authenticating client to construct the
+ <code class="interfacename">Authentication</code> object (such as with RMI invocations),
+ then a malicious client could submit an
+ <code class="classname">AnonymousAuthenticationToken</code> which it had created itself
+ (with chosen username and authority list). If the <code class="literal">key</code> is
+ guessable or can be found out, then the token would be accepted by the anonymous
+ provider. This isn't a problem with normal usage but if you are using RMI you would
+ be best to use a customized <code class="classname">ProviderManager</code> which omits the
+ anonymous provider rather than sharing the one you use for your HTTP authentication
+ mechanisms.</p></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
- </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="session-mgmt.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="web-app-security.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="authorization.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">11. Session Management </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> Part IV. Authorization</td></tr></table></div></body></html>
\ No newline at end of file
+ </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="session-mgmt.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="web-app-security.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="authorization.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">12. Session Management </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> Part IV. Authorization</td></tr></table></div></body></html>
\ No newline at end of file
diff --git a/docs/reference/appendix-namespace.html b/docs/reference/appendix-namespace.html
index 12a3dad..b36c44b 100644
--- a/docs/reference/appendix-namespace.html
+++ b/docs/reference/appendix-namespace.html
@@ -1,6 +1,6 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>Appendix B. The Security Namespace</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="springsecurity.html" title="Spring Security"><link rel="prev" href="appendix-schema.html" title="Appendix A. Security Database Schema"><!--Begin Google Analytics code--><script type="text/javascript">
+ <title>Appendix B. The Security Namespace</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="springsecurity.html" title="Spring Security"><link rel="prev" href="appendix-schema.html" title="Appendix A. Security Database Schema"><link rel="next" href="appendix-dependencies.html" title="Appendix C. Spring Security Dependencies"><!--Begin Google Analytics code--><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
@@ -8,94 +8,172 @@
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
- </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Appendix B. The Security Namespace</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="appendix-schema.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> </td></tr></table><hr></div><div class="appendix" title="Appendix B. The Security Namespace"><div class="titlepage"><div><div><h1 class="title"><a name="appendix-namespace"></a>The Security Namespace</h1></div></div></div><p> This appendix provides a reference to the elements available in the security namespace
+ </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Appendix B. The Security Namespace</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="appendix-schema.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="appendix-dependencies.html">Next</a></td></tr></table><hr></div><div class="appendix" title="Appendix B. The Security Namespace"><div class="titlepage"><div><div><h1 class="title"><a name="appendix-namespace"></a>The Security Namespace</h1></div></div></div><p> This appendix provides a reference to the elements available in the security namespace
and information on the underlying beans they create (a knowledge of the individual classes
and how they work together is assumed - you can find more information in the project Javadoc
and elsewhere in this document). If you haven't used the namespace before, please read the
- <a class="link" href="ns-config.html" title="2. Security Namespace Configuration">introductory chapter</a> on namespace configuration, as
+ <a class="link" href="ns-config.html" title="3. Security Namespace Configuration">introductory chapter</a> on namespace configuration, as
this is intended as a supplement to the information there. Using a good quality XML editor
while editing a configuration based on the schema is recommended as this will provide
contextual information on which elements and attributes are available as well as comments
explaining their purpose. The namespace is written in <a class="link" href="http://www.relaxng.org/" target="_top">RELAX NG</a> Compact format and later converted into
- an XSD schema. If you are familiar with this format, you may wish to examine the <a class="link" href="https://fisheye.springsource.org/browse/spring-security/config/src/main/resources/org/springframework/security/config/spring-security-3.1.rnc" target="_top">schema file</a> directly.</p><div class="section" title="B.1 Web Application Security - the <http> Element"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="nsa-http"></a>B.1 Web Application Security - the <code class="literal"><http></code> Element</h2></div></div></div><p> If you use an <code class="literal"><http></code> element within your application, a
- <code class="classname">FilterChainProxy</code> bean named "springSecurityFilterChain" is
- created and the configuration within the element is used to build a filter chain within
- <code class="classname">FilterChainProxy</code>. As of Spring Security 3.1, additional
- <code class="literal">http</code> elements can be used to add extra filter chains <sup>[<a name="d0e6997" href="#ftn.d0e6997" class="footnote">16</a>]</sup>. Some core filters are always created in a filter chain and others will be
- added to the stack depending on the attributes and child elements which are present. The
- positions of the standard filters are fixed (see <a class="link" href="ns-config.html#filter-stack" title="Table 2.1. Standard Filter Aliases and Ordering">the
- filter order table</a> in the namespace introduction), removing a common source of
- errors with previous versions of the framework when users had to configure the filter
- chain explicitly in the<code class="classname">FilterChainProxy</code> bean. You can, of course,
- still do this if you need full control of the configuration. </p><p> All filters which require a reference to the
- <code class="interfacename">AuthenticationManager</code> will be automatically injected with
- the internal instance created by the namespace configuration (see the <a class="link" href="ns-config.html#ns-auth-manager" title="2.6 The Authentication Manager and the Namespace"> introductory chapter</a> for more on the
- <code class="interfacename">AuthenticationManager</code>). </p><p> Each <code class="literal"><http></code> namespace block always creates an
- <code class="classname">SecurityContextPersistenceFilter</code>, an
- <code class="classname">ExceptionTranslationFilter</code> and a
- <code class="classname">FilterSecurityInterceptor</code>. These are fixed and cannot be replaced
- with alternatives. </p><div class="section" title="B.1.1 <http> Attributes"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-http-attributes"></a>B.1.1 <code class="literal"><http></code> Attributes</h3></div></div></div><p> The attributes on the <code class="literal"><http></code> element control some of the
- properties on the core filters. </p><div class="section" title="pattern"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-http-pattern"></a><code class="literal">pattern</code></h4></div></div></div><p>Defining a pattern for the <code class="literal">http</code> element controls the
- requests which will be filtered through the list of filters which it defines.
- The interpretation is dependent on the configured <a class="link" href="appendix-namespace.html#nsa-path-type" title="request-matcher">request-matcher</a>. If no pattern is defined,
- all requests will be matched, so the most specific patterns should be declared
- first. </p></div><div class="section" title="security"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-http-secured"></a><code class="literal">security</code></h4></div></div></div><p>A request pattern can be mapped to an empty filter chain, by setting this
- attribute to <code class="literal">none</code>. No security will be applied and none of
- Spring Security's features will be available. </p></div><div class="section" title="servlet-api-provision"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-servlet-api-provision"></a><code class="literal">servlet-api-provision</code></h4></div></div></div><p> Provides versions of <code class="literal">HttpServletRequest</code> security methods
- such as <code class="literal">isUserInRole()</code> and <code class="literal">getPrincipal()</code>
- which are implemented by adding a
- <code class="classname">SecurityContextHolderAwareRequestFilter</code> bean to the
- stack. Defaults to "true".</p></div><div class="section" title="jaas-api-provision"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-jaas-api-provision"></a><code class="literal">jaas-api-provision</code></h4></div></div></div><p>If available, runs the request as the <code class="literal">Subject</code> acquired from
- the <code class="classname">JaasAuthenticationToken</code> which is implemented by
- adding a <code class="classname">JaasApiIntegrationFilter</code> bean to the stack.
- Defaults to "false".</p></div><div class="section" title="request-matcher"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-path-type"></a><code class="literal">request-matcher</code></h4></div></div></div><p> Defines the <code class="interfacename">RequestMatcher</code> strategy used in
- the <code class="classname">FilterChainProxy</code> and the beans created by the
- <code class="literal">intercept-url</code> to match incoming requests. Options are
- currently <code class="literal">ant</code>, <code class="literal">regex</code> and
- <code class="literal">ciRegex</code>, for ant, regular-expression and case-insensitive
- regular-expression repsectively. A separate instance is created for each
- <code class="literal">intercept-url</code> element using its <code class="literal">pattern</code>
- and <code class="literal">method</code> attributes (see below). Ant paths are matched
- using an <code class="classname">AntPathRequestMatcher</code> and regular expressions
- are matched using a <code class="classname">RegexRequestMatcher</code>. See the Javadoc
- for these classes for more details on exactly how the matching is preformed. Ant
- paths are the default strategy.</p></div><div class="section" title="realm"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-realm"></a><code class="literal">realm</code></h4></div></div></div><p> Sets the realm name used for basic authentication (if enabled). Corresponds
- to the <code class="literal">realmName</code> property on
- <code class="classname">BasicAuthenticationEntryPoint</code>. </p></div><div class="section" title="entry-point-ref"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-entry-point-ref"></a><code class="literal">entry-point-ref</code></h4></div></div></div><p> Normally the <code class="interfacename">AuthenticationEntryPoint</code> used
- will be set depending on which authentication mechanisms have been configured.
- This attribute allows this behaviour to be overridden by defining a customized
- <code class="interfacename">AuthenticationEntryPoint</code> bean which will start
- the authentication process. </p></div><div class="section" title="security-context-repository-ref"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-security-context-repo-ref"></a><code class="literal">security-context-repository-ref</code></h4></div></div></div><p> Allows injection of a custom
- <code class="interfacename">SecurityContextRepository</code> into the
- <code class="classname">SecurityContextPersistenceFilter</code>. </p></div><div class="section" title="access-decision-manager-ref"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-access-decision-manager-ref"></a><code class="literal">access-decision-manager-ref</code></h4></div></div></div><p> Optional attribute specifying the ID of the
- <code class="interfacename">AccessDecisionManager</code> implementation which should
- be used for authorizing HTTP requests. By default an
- <code class="classname">AffirmativeBased</code> implementation is used for with a
- <code class="classname">RoleVoter</code> and an
- <code class="classname">AuthenticatedVoter</code>. </p></div><div class="section" title="access-denied-page"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-access-denied-page"></a><code class="literal">access-denied-page</code></h4></div></div></div><p> Deprecated in favour of the <code class="literal">access-denied-handler</code> child
- element. </p></div><div class="section" title="once-per-request"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-once-per-request"></a><code class="literal">once-per-request</code></h4></div></div></div><p> Corresponds to the <code class="literal">observeOncePerRequest</code> property of
- <code class="classname">FilterSecurityInterceptor</code>. Defaults to "true". </p></div><div class="section" title="create-session"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-create-session"></a><code class="literal">create-session</code></h4></div></div></div><p> Controls the eagerness with which an HTTP session is created. If not set,
- defaults to "ifRequired". Other options are "always" and "never". The setting of
- this attribute affect the <code class="literal">allowSessionCreation</code> and
- <code class="literal">forceEagerSessionCreation</code> properties of
- <code class="classname">HttpSessionContextIntegrationFilter</code>.
- <code class="literal">allowSessionCreation</code> will always be true unless this
- attribute is set to "never". <code class="literal">forceEagerSessionCreation</code> is
- "false" unless it is set to "always". So the default configuration allows
- session creation but does not force it. The exception is if concurrent session
- control is enabled, when <code class="literal">forceEagerSessionCreation</code> will be
- set to true, regardless of what the setting is here. Using "never" would then
- cause an exception during the initialization of
- <code class="classname">HttpSessionContextIntegrationFilter</code>. </p></div><div class="section" title="use-expressions"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-use-expressions"></a><code class="literal">use-expressions</code></h4></div></div></div><p>Enables EL-expressions in the <code class="literal">access</code> attribute, as
- described in the chapter on <a class="link" href="el-access.html#el-access-web" title="15.2 Web Security Expressions">expression-based
- access-control</a>. </p></div><div class="section" title="disable-url-rewriting"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-disable-url-rewriting"></a><code class="literal">disable-url-rewriting</code></h4></div></div></div><p>Prevents session IDs from being appended to URLs in the application. Clients
- must use cookies if this attribute is set to <code class="literal">true</code>. </p></div></div><div class="section" title="B.1.2 <access-denied-handler>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-access-denied-handler"></a>B.1.2 <code class="literal"><access-denied-handler></code></h3></div></div></div><p> This element allows you to set the <code class="literal">errorPage</code> property for the
+ an XSD schema. If you are familiar with this format, you may wish to examine the <a class="link" href="https://fisheye.springsource.org/browse/spring-security/config/src/main/resources/org/springframework/security/config/spring-security-3.1.rnc" target="_top">schema file</a> directly.</p><div class="section" title="B.1 Web Application Security"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="nsa-web"></a>B.1 Web Application Security</h2></div></div></div><div class="section" title="B.1.1 <debug>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-debug"></a>B.1.1 <code class="literal"><debug></code></h3></div></div></div><p>Enables Spring Security debugging infrastructure. This will provide human-readable (multi-line)
+ debugging information to monitor requests coming into the security filters. This may include sensitive
+ information, such as request parameters or headers, and should only be used in a development
+ environment.</p></div><div class="section" title="B.1.2 <http>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-http"></a>B.1.2 <code class="literal"><http></code></h3></div></div></div><p> If you use an <code class="literal"><http></code> element within your application, a
+ <code class="classname">FilterChainProxy</code> bean named "springSecurityFilterChain" is
+ created and the configuration within the element is used to build a filter chain within
+ <code class="classname">FilterChainProxy</code>. As of Spring Security 3.1, additional
+ <code class="literal">http</code> elements can be used to add extra filter chains <sup>[<a name="d0e8540" href="#ftn.d0e8540" class="footnote">24</a>]</sup>. Some core filters are always created in a filter chain and others will be
+ added to the stack depending on the attributes and child elements which are present. The
+ positions of the standard filters are fixed (see <a class="link" href="ns-config.html#filter-stack" title="Table 3.1. Standard Filter Aliases and Ordering">the
+ filter order table</a> in the namespace introduction), removing a common source of
+ errors with previous versions of the framework when users had to configure the filter
+ chain explicitly in the <code class="classname">FilterChainProxy</code> bean. You can, of course,
+ still do this if you need full control of the configuration. </p><p> All filters which require a reference to the
+ <code class="interfacename">AuthenticationManager</code> will be automatically injected with
+ the internal instance created by the namespace configuration (see the <a class="link" href="ns-config.html#ns-auth-manager" title="3.6 The Authentication Manager and the Namespace">introductory chapter</a> for more on the
+ <code class="interfacename">AuthenticationManager</code>). </p><p> Each <code class="literal"><http></code> namespace block always creates an
+ <code class="classname">SecurityContextPersistenceFilter</code>, an
+ <code class="classname">ExceptionTranslationFilter</code> and a
+ <code class="classname">FilterSecurityInterceptor</code>. These are fixed and cannot be replaced
+ with alternatives. </p><div class="section" title="<http> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-http-attributes"></a><code class="literal"><http></code> Attributes</h4></div></div></div><p> The attributes on the <code class="literal"><http></code> element control some of the
+ properties on the core filters. </p><div class="section" title="access-decision-manager-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-access-decision-manager-ref"></a><code class="literal">access-decision-manager-ref</code></h5></div></div></div><p> Optional attribute specifying the ID of the
+ <code class="interfacename">AccessDecisionManager</code> implementation which should
+ be used for authorizing HTTP requests. By default an
+ <code class="classname">AffirmativeBased</code> implementation is used for with a
+ <code class="classname">RoleVoter</code> and an
+ <code class="classname">AuthenticatedVoter</code>. </p></div><div class="section" title="access-denied-page"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-access-denied-page"></a><code class="literal">access-denied-page</code></h5></div></div></div><p> Deprecated in favour of the <a class="link" href="appendix-namespace.html#nsa-access-denied-handler" title="B.1.3 <access-denied-handler>">access-denied-handler</a>
+ child element.</p></div><div class="section" title="authentication-manager-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-authentication-manager-ref"></a><code class="literal">authentication-manager-ref</code></h5></div></div></div><p>A reference to the <code class="interfacename">AuthenticationManager</code> used for the
+ <code class="classname">FilterChain</code> created by this http element.</p></div><div class="section" title="auto-config"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-auto-config"></a><code class="literal">auto-config</code></h5></div></div></div><p>Automatically registers a login form, BASIC authentication, anonymous authentication, logout
+ services, remember-me and servlet-api-integration. If set to "true", all of these capabilities are added
+ (although you can still customize the configuration of each by providing the respective element). If
+ unspecified, defaults to "false".</p></div><div class="section" title="create-session"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-create-session"></a><code class="literal">create-session</code></h5></div></div></div><p>Controls the eagerness with which an HTTP session is created by Spring Security classes.
+ Options include:
+ </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><code class="literal">always</code> - Spring Security will proactively create a session if one
+ does not exist.
+ </li><li class="listitem"><code class="literal">ifRequired</code> - Spring Security will only create a session only if one
+ is required (default value).
+ </li><li class="listitem"><code class="literal">never</code> - Spring Security will never create a session, but will
+ make use of one if the application does.</li><li class="listitem"><code class="literal">stateless</code> - Spring Security will not create a session and ignore the
+ session for obtaining a Spring <code class="interfacename">Authentication</code>.
+ </li></ul></div><p>
+ </p></div><div class="section" title="disable-url-rewriting"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-disable-url-rewriting"></a><code class="literal">disable-url-rewriting</code></h5></div></div></div><p>Prevents session IDs from being appended to URLs in the application. Clients
+ must use cookies if this attribute is set to <code class="literal">true</code>. The default is
+ <code class="literal">false</code>.</p></div><div class="section" title="entry-point-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-entry-point-ref"></a><code class="literal">entry-point-ref</code></h5></div></div></div><p> Normally the <code class="interfacename">AuthenticationEntryPoint</code> used
+ will be set depending on which authentication mechanisms have been configured.
+ This attribute allows this behaviour to be overridden by defining a customized
+ <code class="interfacename">AuthenticationEntryPoint</code> bean which will start
+ the authentication process.</p></div><div class="section" title="jaas-api-provision"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-jaas-api-provision"></a><code class="literal">jaas-api-provision</code></h5></div></div></div><p>If available, runs the request as the <code class="literal">Subject</code> acquired from
+ the <code class="classname">JaasAuthenticationToken</code> which is implemented by
+ adding a <code class="classname">JaasApiIntegrationFilter</code> bean to the stack.
+ Defaults to <code class="literal">false</code>.</p></div><div class="section" title="name"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-name"></a><code class="literal">name</code></h5></div></div></div><p>A bean identifier, used for referring to the bean elsewhere in the context.</p></div><div class="section" title="once-per-request"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-once-per-request"></a><code class="literal">once-per-request</code></h5></div></div></div><p>Corresponds to the <code class="literal">observeOncePerRequest</code> property of
+ <code class="classname">FilterSecurityInterceptor</code>. Defaults to <code class="literal">true</code>.</p></div><div class="section" title="path-type"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-path-type"></a><code class="literal">path-type</code></h5></div></div></div><p>Deprecated in favor of <a class="link" href="appendix-namespace.html#nsa-http-request-matcher" title="request-matcher">request-matcher</a>.
+ </p></div><div class="section" title="pattern"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-pattern"></a><code class="literal">pattern</code></h5></div></div></div><p>Defining a pattern for the <a class="link" href="appendix-namespace.html#nsa-http" title="B.1.2 <http>">http</a> element controls the
+ requests which will be filtered through the list of filters which it defines.
+ The interpretation is dependent on the configured <a class="link" href="appendix-namespace.html#nsa-http-request-matcher" title="request-matcher">request-matcher</a>. If no pattern is defined,
+ all requests will be matched, so the most specific patterns should be declared
+ first.</p></div><div class="section" title="realm"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-realm"></a><code class="literal">realm</code></h5></div></div></div><p>Sets the realm name used for basic authentication (if enabled). Corresponds
+ to the <code class="literal">realmName</code> property on
+ <code class="classname">BasicAuthenticationEntryPoint</code>.</p></div><div class="section" title="request-matcher"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-request-matcher"></a><code class="literal">request-matcher</code></h5></div></div></div><p>Defines the <code class="interfacename">RequestMatcher</code> strategy used in
+ the <code class="classname">FilterChainProxy</code> and the beans created by the
+ <code class="literal">intercept-url</code> to match incoming requests. Options are
+ currently <code class="literal">ant</code>, <code class="literal">regex</code> and
+ <code class="literal">ciRegex</code>, for ant, regular-expression and case-insensitive
+ regular-expression repsectively. A separate instance is created for each
+ <a class="link" href="appendix-namespace.html#nsa-intercept-url" title="B.1.10 <intercept-url>">intercept-url</a> element using its
+ <a class="link" href="appendix-namespace.html#nsa-intercept-url-pattern" title="pattern">pattern</a> and
+ <a class="link" href="appendix-namespace.html#nsa-intercept-url-method" title="method">method</a> attributes. Ant paths
+ are matched using an <code class="classname">AntPathRequestMatcher</code> and regular expressions
+ are matched using a <code class="classname">RegexRequestMatcher</code>. See the Javadoc
+ for these classes for more details on exactly how the matching is preformed. Ant
+ paths are the default strategy.</p></div><div class="section" title="request-matcher-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-request-matcher-ref"></a><code class="literal">request-matcher-ref</code></h5></div></div></div><p>A referenece to a bean that implements <code class="interfacename">RequestMatcher</code> that
+ will determine if this <code class="classname">FilterChain</code> should be used. This is a more
+ powerful alternative to <a class="link" href="appendix-namespace.html#nsa-http-pattern" title="pattern">pattern</a>.</p></div><div class="section" title="security"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-security"></a><code class="literal">security</code></h5></div></div></div><p>A request pattern can be mapped to an empty filter chain, by setting this
+ attribute to <code class="literal">none</code>. No security will be applied and none of
+ Spring Security's features will be available.</p></div><div class="section" title="security-context-repository-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-security-context-repository-ref"></a><code class="literal">security-context-repository-ref</code></h5></div></div></div><p>Allows injection of a custom
+ <code class="interfacename">SecurityContextRepository</code> into the
+ <code class="classname">SecurityContextPersistenceFilter</code>.</p></div><div class="section" title="servlet-api-provision"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-servlet-api-provision"></a><code class="literal">servlet-api-provision</code></h5></div></div></div><p>Provides versions of <code class="literal">HttpServletRequest</code> security methods
+ such as <code class="literal">isUserInRole()</code> and <code class="literal">getPrincipal()</code>
+ which are implemented by adding a
+ <code class="classname">SecurityContextHolderAwareRequestFilter</code> bean to the
+ stack. Defaults to <code class="literal">true</code>.</p></div><div class="section" title="use-expressions"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-use-expressions"></a><code class="literal">use-expressions</code></h5></div></div></div><p>Enables EL-expressions in the <code class="literal">access</code> attribute, as
+ described in the chapter on <a class="link" href="el-access.html#el-access-web" title="16.2 Web Security Expressions">expression-based
+ access-control</a>.</p></div></div><div class="section" title="Child Elements of <http>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-http-children"></a>Child Elements of <http></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-access-denied-handler" title="B.1.3 <access-denied-handler>">access-denied-handler</a></li><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-anonymous" title="B.1.4 <anonymous>">anonymous</a></li><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-custom-filter" title="B.1.5 <custom-filter>">custom-filter</a></li><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-expression-handler" title="B.1.6 <expression-handler>">expression-handler</a></li><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-form-login" title="B.1.7 <form-login>">form-login</a></li><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-http-basic" title="B.1.8 <http-basic>">http-basic</a></li><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-intercept-url" title="B.1.10 <intercept-url>">intercept-url</a></li><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-jee" title="B.1.11 <jee>">jee</a></li><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-logout" title="B.1.12 <logout>">logout</a></li><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-openid-login" title="B.1.13 <openid-login>">openid-login</a></li><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-port-mappings" title="B.1.16 <port-mappings>">port-mappings</a></li><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-remember-me" title="B.1.18 <remember-me>">remember-me</a></li><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-request-cache" title="B.1.19 <request-cache> Element">request-cache</a></li><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-session-management" title="B.1.20 <session-management>">session-management</a></li><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-x509" title="B.1.22 <x509>">x509</a></li></ul></div></div></div><div class="section" title="B.1.3 <access-denied-handler>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-access-denied-handler"></a>B.1.3 <code class="literal"><access-denied-handler></code></h3></div></div></div><p>This element allows you to set the <code class="literal">errorPage</code> property for the
default <code class="interfacename">AccessDeniedHandler</code> used by the
- <code class="classname">ExceptionTranslationFilter</code>, (using the
- <code class="literal">error-page</code> attribute, or to supply your own implementation using
- the <code class="literal">ref</code> attribute. This is discussed in more detail in the
- section on <a class="link" href="core-web-filters.html#access-denied-handler" title="8.2.2 AccessDeniedHandler">the
- <code class="classname">ExceptionTranslationFilter</code></a>.</p></div><div class="section" title="B.1.3 The <intercept-url> Element"><div class="titlepage"><div><div><h3 class="title"><a name="d0e7289"></a>B.1.3 The <code class="literal"><intercept-url></code> Element</h3></div></div></div><p> This element is used to define the set of URL patterns that the application is
+ <code class="classname">ExceptionTranslationFilter</code>, using the
+ <a class="link" href="appendix-namespace.html#nsa-access-denied-handler-error-page" title="error-page">error-page</a> attribute, or
+ to supply your own implementation using the
+ <a class="link" href="appendix-namespace.html#nsa-access-denied-handler-ref" title="ref">ref</a> attribute. This is discussed
+ in more detail in the section on the <a class="link" href="core-web-filters.html#access-denied-handler" title="9.2.2 AccessDeniedHandler">
+ <code class="classname">ExceptionTranslationFilter</code></a>.</p><div class="section" title="Parent Elements of <access-denied-handler>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-access-denied-handler-parents"></a>Parent Elements of <code class="literal"><access-denied-handler></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-http" title="B.1.2 <http>">http</a></li></ul></div></div><div class="section" title="<access-denied-handler> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-access-denied-handler-attributes"></a><code class="literal"><access-denied-handler></code> Attributes</h4></div></div></div><div class="section" title="error-page"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-access-denied-handler-error-page"></a><code class="literal">error-page</code></h5></div></div></div><p>The access denied page that an authenticated user will be redirected to if they request a
+ page which they don't have the authority to access.</p></div><div class="section" title="ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-access-denied-handler-ref"></a><code class="literal">ref</code></h5></div></div></div><p>Defines a reference to a Spring bean of type <code class="interfacename">AccessDeniedHandler
+ </code>.</p></div></div></div><div class="section" title="B.1.4 <anonymous>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-anonymous"></a>B.1.4 <code class="literal"><anonymous></code></h3></div></div></div><p>Adds an <code class="classname">AnonymousAuthenticationFilter</code> to the stack and an
+ <code class="classname">AnonymousAuthenticationProvider</code>. Required if you are using
+ the <code class="literal">IS_AUTHENTICATED_ANONYMOUSLY</code> attribute.</p><div class="section" title="Parent Elements of <anonymous>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-anonymous-parents"></a>Parent Elements of <code class="literal"><anonymous></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-http" title="B.1.2 <http>">http</a></li></ul></div></div><div class="section" title="<anonymous> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-anonymous-attributes"></a><code class="literal"><anonymous></code> Attributes</h4></div></div></div><div class="section" title="enabled"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-anonymous-enabled"></a><code class="literal">enabled</code></h5></div></div></div><p>With the default namespace setup, the anonymous "authentication" facility is automatically
+ enabled. You can disable it using this property.</p></div><div class="section" title="granted-authority"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-anonymous-granted-authority"></a><code class="literal">granted-authority</code></h5></div></div></div><p>The granted authority that should be assigned to the anonymous request. Commonly this is used
+ to assign the anonymous request particular roles, which can subsequently be used in authorization
+ decisions. If unset, defaults to <code class="literal">ROLE_ANONYMOUS</code>.</p></div><div class="section" title="key"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-anonymous-key"></a><code class="literal">key</code></h5></div></div></div><p>The key shared between the provider and filter. This generally does not need to be set. If
+ unset, it will default to a secure randomly generated value. This means setting this value can
+ improve startup time when using the anonymous functionality since secure random values can take
+ a while to be generated.</p></div><div class="section" title="username"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-anonymous-username"></a><code class="literal">username</code></h5></div></div></div><p>The username that should be assigned to the anonymous request. This allows the principal to
+ be identified, which may be important for logging and auditing. if unset, defaults to
+ <code class="literal">anonymousUser</code>.</p></div></div></div><div class="section" title="B.1.5 <custom-filter>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-custom-filter"></a>B.1.5 <code class="literal"><custom-filter></code></h3></div></div></div><p>This element is used to add a filter to the filter chain. It doesn't create any
+ additional beans but is used to select a bean of type
+ <code class="interfacename">javax.servlet.Filter</code> which is already defined in the
+ application context and add that at a particular position in the filter chain
+ maintained by Spring Security. Full details can be found in the <a class="link" href="ns-config.html#ns-custom-filters" title="3.3.5 Adding in Your Own Filters">
+ namespace chapter</a>.</p><div class="section" title="Parent Elements of <custom-filter>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-custom-filter-parents"></a>Parent Elements of <code class="literal"><custom-filter></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-http" title="B.1.2 <http>">http</a></li></ul></div></div><div class="section" title="<custom-filter> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-custom-filter-attributes"></a><code class="literal"><custom-filter></code> Attributes</h4></div></div></div><div class="section" title="after"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-custom-filter-after"></a><code class="literal">after</code></h5></div></div></div><p>The filter immediately after which the custom-filter should be placed in the chain. This
+ feature will only be needed by advanced users who wish to mix their own filters into the
+ security filter chain and have some knowledge of the standard Spring Security filters. The
+ filter names map to specific Spring Security implementation filters.</p></div><div class="section" title="before"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-custom-filter-before"></a><code class="literal">before</code></h5></div></div></div><p>The filter immediately before which the custom-filter should be placed in the chain</p></div><div class="section" title="position"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-custom-filter-position"></a><code class="literal">position</code></h5></div></div></div><p>The explicit position at which the custom-filter should be placed in the chain. Use if you
+ are replacing a standard filter.</p></div><div class="section" title="ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-custom-filter-ref"></a><code class="literal">ref</code></h5></div></div></div><p>Defines a reference to a Spring bean that implements <code class="interfacename">Filter</code>.</p></div></div></div><div class="section" title="B.1.6 <expression-handler>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-expression-handler"></a>B.1.6 <code class="literal"><expression-handler></code></h3></div></div></div><p>Defines the <code class="interfacename">SecurityExpressionHandler</code> instance which will be used if
+ expression-based access-control is enabled. A default implementation (with no ACL support) will be used
+ if not supplied.</p><div class="section" title="Parent Elements of <expression-handler>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-expression-handler-parents"></a>Parent Elements of <code class="literal"><expression-handler></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-global-method-security" title="B.3.1 <global-method-security>">global-method-security</a></li><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-http" title="B.1.2 <http>">http</a></li></ul></div></div><div class="section" title="<expression-handler> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-expression-handler-attributes"></a><code class="literal"><expression-handler></code> Attributes</h4></div></div></div><div class="section" title="ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-expression-handler-ref"></a><code class="literal">ref</code></h5></div></div></div><p>Defines a reference to a Spring bean that implements <code class="interfacename">SecurityExpressionHandler</code>.</p></div></div></div><div class="section" title="B.1.7 <form-login>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-form-login"></a>B.1.7 <code class="literal"><form-login></code></h3></div></div></div><p>Used to add an <code class="classname">UsernamePasswordAuthenticationFilter</code> to the
+ filter stack and an <code class="classname">LoginUrlAuthenticationEntryPoint</code> to the
+ application context to provide authentication on demand. This will always take
+ precedence over other namespace-created entry points. If no attributes are supplied,
+ a login page will be generated automatically at the URL "/spring_security_login" <sup>[<a name="d0e9129" href="#ftn.d0e9129" class="footnote">25</a>]</sup> The behaviour can be customized using the <a class="link" href="appendix-namespace.html#nsa-form-login-attributes" title="<form-login> Attributes">
+ <code class="literal"><form-login></code> Attributes</a>.</p><div class="section" title="Parent Elements of <form-login>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-form-login-parents"></a>Parent Elements of <code class="literal"><form-login></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-http" title="B.1.2 <http>">http</a></li></ul></div></div><div class="section" title="<form-login> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-form-login-attributes"></a><code class="literal"><form-login></code> Attributes</h4></div></div></div><div class="section" title="always-use-default-target"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-form-login-always-use-default-target"></a><code class="literal">always-use-default-target</code></h5></div></div></div><p>If set to <code class="literal">true</code>, the user will always start at the value given by
+ <a class="link" href="appendix-namespace.html#nsa-form-login-default-target-url" title="default-target-url">default-target-url</a>, regardless
+ of how they arrived at the login page. Maps to the <code class="literal">alwaysUseDefaultTargetUrl</code>
+ property of <code class="classname">UsernamePasswordAuthenticationFilter</code>. Default value is
+ <code class="literal">false</code>.</p></div><div class="section" title="authentication-details-source-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-form-login-authentication-details-source-ref"></a><code class="literal">authentication-details-source-ref</code></h5></div></div></div><p>Reference to an <code class="interfacename">AuthenticationDetailsSource</code> which will be used
+ by the authentication filter</p></div><div class="section" title="authentication-failure-handler-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-form-login-authentication-failure-handler-ref"></a><code class="literal">authentication-failure-handler-ref</code></h5></div></div></div><p>Can be used as an alternative to
+ <a class="link" href="appendix-namespace.html#nsa-form-login-authentication-failure-url" title="authentication-failure-url">authentication-failure-url</a>,
+ giving you full control over the navigation flow after an authentication failure. The value
+ should be he name of an <code class="interfacename">AuthenticationFailureHandler</code> bean in the
+ application context.</p></div><div class="section" title="authentication-failure-url"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-form-login-authentication-failure-url"></a><code class="literal">authentication-failure-url</code></h5></div></div></div><p>Maps to the <code class="literal">authenticationFailureUrl</code> property of
+ <code class="classname">UsernamePasswordAuthenticationFilter</code>. Defines the URL the
+ browser will be redirected to on login failure. Defaults to
+ <code class="literal">/spring_security_login?login_error</code>, which will be automatically handled by
+ the automatic login page generator, re-rendering the login page with an error message.</p></div><div class="section" title="authentication-success-handler-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-form-login-authentication-success-handler-ref"></a><code class="literal">authentication-success-handler-ref</code></h5></div></div></div><p>This can be used as an alternative to
+ <a class="link" href="appendix-namespace.html#nsa-form-login-default-target-url" title="default-target-url">default-target-url</a>
+ and <a class="link" href="appendix-namespace.html#nsa-form-login-always-use-default-target" title="always-use-default-target">always-use-default-target</a>,
+ giving you full control over the navigation flow after a successful authentication. The value
+ should be the name of an <code class="interfacename">AuthenticationSuccessHandler</code> bean in
+ the application context. By default, an implementation of
+ <code class="classname">SavedRequestAwareAuthenticationSuccessHandler</code> is used and
+ injected with the <a class="link" href="appendix-namespace.html#nsa-form-login-default-target-url" title="default-target-url">default-target-url
+ </a>.</p></div><div class="section" title="default-target-url"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-form-login-default-target-url"></a><code class="literal">default-target-url</code></h5></div></div></div><p>Maps to the <code class="literal">defaultTargetUrl</code> property of
+ <code class="classname">UsernamePasswordAuthenticationFilter</code>. If not set, the
+ default value is "/" (the application root). A user will be taken to this URL
+ after logging in, provided they were not asked to login while attempting to
+ access a secured resource, when they will be taken to the originally requested
+ URL.</p></div><div class="section" title="login-page"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-form-login-login-page"></a><code class="literal">login-page</code></h5></div></div></div><p> The URL that should be used to render the login page. Maps to the
+ <code class="literal">loginFormUrl</code> property of the
+ <code class="classname">LoginUrlAuthenticationEntryPoint</code>. Defaults to
+ "/spring_security_login".</p></div><div class="section" title="login-processing-url"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-form-login-login-processing-url"></a><code class="literal">login-processing-url</code></h5></div></div></div><p> Maps to the <code class="literal">filterProcessesUrl</code> property of
+ <code class="classname">UsernamePasswordAuthenticationFilter</code>. The default value
+ is "/j_spring_security_check".</p></div><div class="section" title="password-parameter"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-form-login-password-parameter"></a><code class="literal">password-parameter</code></h5></div></div></div><p>The name of the request parameter which contains the password. Defaults to "j_password".</p></div><div class="section" title="username-parameter"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-form-login-username-parameter"></a><code class="literal">username-parameter</code></h5></div></div></div><p>The name of the request parameter which contains the username. Defaults to "j_username".</p></div></div></div><div class="section" title="B.1.8 <http-basic>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-http-basic"></a>B.1.8 <code class="literal"><http-basic></code></h3></div></div></div><p>Adds a <code class="classname">BasicAuthenticationFilter</code> and
+ <code class="classname">BasicAuthenticationEntryPoint</code> to the configuration. The
+ latter will only be used as the configuration entry point if form-based login is not
+ enabled.</p><div class="section" title="Parent Elements of <http-basic>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-http-basic-parents"></a>Parent Elements of <code class="literal"><http-basic></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-http" title="B.1.2 <http>">http</a></li></ul></div></div><div class="section" title="<http-basic> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-http-basic-attributes"></a><code class="literal"><http-basic></code> Attributes</h4></div></div></div><div class="section" title="authentication-details-source-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-basic-authentication-details-source-ref"></a><code class="literal">authentication-details-source-ref</code></h5></div></div></div><p>Reference to an <code class="interfacename">AuthenticationDetailsSource</code> which will be used
+ by the authentication filter</p></div><div class="section" title="entry-point-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-basic-entry-point-ref"></a><code class="literal">entry-point-ref</code></h5></div></div></div><p>Sets the <code class="interfacename">AuthenticationEntryPoint</code> which is used by the
+ <code class="classname">BasicAuthenticationFilter</code>.</p></div></div></div><div class="section" title="B.1.9 <http-firewall> Element"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-http-firewall"></a>B.1.9 <code class="literal"><http-firewall></code> Element</h3></div></div></div><p>This is a top-level element which can be used to inject a custom implementation of
+ <code class="interfacename">HttpFirewall</code> into the
+ <code class="classname">FilterChainProxy</code> created by the namespace. The default
+ implementation should be suitable for most applications.</p><div class="section" title="<http-firewall> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-http-firewall-attributes"></a><code class="literal"><http-firewall></code> Attributes</h4></div></div></div><div class="section" title="ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-firewall-ref"></a><code class="literal">ref</code></h5></div></div></div><p>Defines a reference to a Spring bean that implements <code class="interfacename">HttpFirewall</code>.</p></div></div></div><div class="section" title="B.1.10 <intercept-url>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-intercept-url"></a>B.1.10 <code class="literal"><intercept-url></code></h3></div></div></div><p>This element is used to define the set of URL patterns that the application is
interested in and to configure how they should be handled. It is used to construct
the <code class="interfacename">FilterInvocationSecurityMetadataSource</code> used by
the <code class="classname">FilterSecurityInterceptor</code>. It is also responsible for
@@ -103,101 +181,133 @@
need to be accessed by HTTPS, for example. When matching the specified patterns
against an incoming request, the matching is done in the order in which the elements
are declared. So the most specific matches patterns should come first and the most
- general should come last.</p><div class="section" title="pattern"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-pattern"></a><code class="literal">pattern</code></h4></div></div></div><p> The pattern which defines the URL path. The content will depend on the
- <code class="literal">request-matcher</code> attribute from the containing http element,
- so will default to ant path syntax. </p></div><div class="section" title="method"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-method"></a><code class="literal">method</code></h4></div></div></div><p> The HTTP Method which will be used in combination with the pattern to match
- an incoming request. If omitted, any method will match. If an identical pattern
- is specified with and without a method, the method-specific match will take
- precedence.</p></div><div class="section" title="access"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-access"></a><code class="literal">access</code></h4></div></div></div><p> Lists the access attributes which will be stored in the
- <code class="interfacename">FilterInvocationSecurityMetadataSource</code> for the
- defined URL pattern/method combination. This should be a comma-separated list of
- the security configuration attributes (such as role names). </p></div><div class="section" title="requires-channel"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-requires-channel"></a><code class="literal">requires-channel</code></h4></div></div></div><p> Can be <span class="quote">“<span class="quote">http</span>”</span> or <span class="quote">“<span class="quote">https</span>”</span> depending on whether a
- particular URL pattern should be accessed over HTTP or HTTPS respectively.
- Alternatively the value <span class="quote">“<span class="quote">any</span>”</span> can be used when there is no
- preference. If this attribute is present on any
- <code class="literal"><intercept-url></code> element, then a
- <code class="classname">ChannelAuthenticationFilter</code> will be added to the filter
- stack and its additional dependencies added to the application
- context.</p><p> If a <code class="literal"><port-mappings></code> configuration is added, this
- will be used to by the <code class="classname">SecureChannelProcessor</code> and
- <code class="classname">InsecureChannelProcessor</code> beans to determine the ports
- used for redirecting to HTTP/HTTPS. </p></div><div class="section" title="filters"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7363"></a><code class="literal">filters</code></h4></div></div></div><p>Can only take the value <span class="quote">“<span class="quote">none</span>”</span>. This will cause any matching
- request to bypass the Spring Security filter chain entirely. None of the rest of
- the <code class="literal"><http></code> configuration will have any effect on the
- request and there will be no security context available for its duration. Access
- to secured methods during the request will fail.</p></div></div><div class="section" title="B.1.4 The <port-mappings> Element"><div class="titlepage"><div><div><h3 class="title"><a name="d0e7375"></a>B.1.4 The <code class="literal"><port-mappings></code> Element</h3></div></div></div><p> By default, an instance of <code class="classname">PortMapperImpl</code> will be added to
+ general should come last.</p><div class="section" title="Parent Elements of <intercept-url>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-intercept-url-parents"></a>Parent Elements of <code class="literal"><intercept-url></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-filter-invocation-definition-source" title="B.1.25 <filter-invocation-definition-source>">filter-invocation-definition-source</a></li><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-filter-security-metadata-source" title="B.1.26 <filter-security-metadata-source>">filter-security-metadata-source</a></li><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-http" title="B.1.2 <http>">http</a></li></ul></div></div><div class="section" title="<intercept-url> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-intercept-url-attributes"></a><code class="literal"><intercept-url></code> Attributes</h4></div></div></div><div class="section" title="access"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-intercept-url-access"></a><code class="literal">access</code></h5></div></div></div><p>Lists the access attributes which will be stored in the
+ <code class="interfacename">FilterInvocationSecurityMetadataSource</code> for the
+ defined URL pattern/method combination. This should be a comma-separated list of
+ the security configuration attributes (such as role names).</p></div><div class="section" title="filters"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-intercept-url-filters"></a><code class="literal">filters</code></h5></div></div></div><p>Can only take the value <span class="quote">“<span class="quote">none</span>”</span>. This will cause any matching
+ request to bypass the Spring Security filter chain entirely. None of the rest of
+ the <code class="literal"><http></code> configuration will have any effect on the
+ request and there will be no security context available for its duration. Access
+ to secured methods during the request will fail.</p></div><div class="section" title="method"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-intercept-url-method"></a><code class="literal">method</code></h5></div></div></div><p>The HTTP Method which will be used in combination with the pattern to match
+ an incoming request. If omitted, any method will match. If an identical pattern
+ is specified with and without a method, the method-specific match will take
+ precedence.</p></div><div class="section" title="pattern"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-intercept-url-pattern"></a><code class="literal">pattern</code></h5></div></div></div><p>The pattern which defines the URL path. The content will depend on the
+ <code class="literal">request-matcher</code> attribute from the containing http element,
+ so will default to ant path syntax.</p></div><div class="section" title="requires-channel"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-intercept-url-requires-channel"></a><code class="literal">requires-channel</code></h5></div></div></div><p>Can be <span class="quote">“<span class="quote">http</span>”</span> or <span class="quote">“<span class="quote">https</span>”</span> depending on whether a
+ particular URL pattern should be accessed over HTTP or HTTPS respectively.
+ Alternatively the value <span class="quote">“<span class="quote">any</span>”</span> can be used when there is no
+ preference. If this attribute is present on any
+ <code class="literal"><intercept-url></code> element, then a
+ <code class="classname">ChannelAuthenticationFilter</code> will be added to the filter
+ stack and its additional dependencies added to the application
+ context.</p><p>If a <code class="literal"><port-mappings></code> configuration is added, this
+ will be used to by the <code class="classname">SecureChannelProcessor</code> and
+ <code class="classname">InsecureChannelProcessor</code> beans to determine the ports
+ used for redirecting to HTTP/HTTPS. </p></div></div></div><div class="section" title="B.1.11 <jee>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-jee"></a>B.1.11 <code class="literal"><jee></code></h3></div></div></div><p>Adds a J2eePreAuthenticatedProcessingFilter to the filter chain to provide integration with container
+ authentication.</p><div class="section" title="Parent Elements of <jee>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-jee-parents"></a>Parent Elements of <code class="literal"><jee></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-http" title="B.1.2 <http>">http</a></li></ul></div></div><div class="section" title="<jee> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-jee-attributes"></a><code class="literal"><jee></code> Attributes</h4></div></div></div><div class="section" title="mappable-roles"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-jee-mappable-roles"></a><code class="literal">mappable-roles</code></h5></div></div></div><p>A comma-separate list of roles to look for in the incoming HttpServletRequest.</p></div><div class="section" title="user-service-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-jee-user-service-ref"></a><code class="literal">user-service-ref</code></h5></div></div></div><p>A reference to a user-service (or UserDetailsService bean) Id</p></div></div></div><div class="section" title="B.1.12 <logout>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-logout"></a>B.1.12 <code class="literal"><logout></code></h3></div></div></div><p>Adds a <code class="classname">LogoutFilter</code> to the filter stack. This is
+ configured with a <code class="classname">SecurityContextLogoutHandler</code>.</p><div class="section" title="Parent Elements of <logout>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-logout-parents"></a>Parent Elements of <code class="literal"><logout></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-http" title="B.1.2 <http>">http</a></li></ul></div></div><div class="section" title="<logout> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-logout-attributes"></a><code class="literal"><logout></code> Attributes</h4></div></div></div><div class="section" title="The delete-cookies attribute"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-logout-delete-cookies"></a>The <code class="literal">delete-cookies</code> attribute</h5></div></div></div><p>A comma-separated list of the names of cookies which should be deleted when the user logs out.
+ </p></div><div class="section" title="The invalidate-session attribute"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-logout-invalidate-session"></a>The <code class="literal">invalidate-session</code> attribute</h5></div></div></div><p> Maps to the <code class="literal">invalidateHttpSession</code> of the
+ <code class="classname">SecurityContextLogoutHandler</code>. Defaults to "true", so the
+ session will be invalidated on logout.</p></div><div class="section" title="The logout-success-url attribute"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-logout-logout-success-url"></a>The <code class="literal">logout-success-url</code> attribute</h5></div></div></div><p>The destination URL which the user will be taken to after logging out.
+ Defaults to "/". </p><p>Setting this attribute will inject the <code class="classname">SessionManagementFilter</code>
+ with a <code class="classname">SimpleRedirectInvalidSessionStrategy</code> configured with
+ the attribute value. When an invalid session ID is submitted, the strategy will be invoked,
+ redirecting to the configured URL.</p></div><div class="section" title="The logout-url attribute"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-logout-logout-url"></a>The <code class="literal">logout-url</code> attribute</h5></div></div></div><p> The URL which will cause a logout (i.e. which will be processed by the
+ filter). Defaults to "/j_spring_security_logout". </p></div><div class="section" title="The success-handler-ref attribute"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-logout-success-handler-ref"></a>The <code class="literal">success-handler-ref</code> attribute</h5></div></div></div><p>May be used to supply an instance of <code class="interfacename">LogoutSuccessHandler</code>
+ which will be invoked to control the navigation after logging out.
+ </p></div></div></div><div class="section" title="B.1.13 <openid-login>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-openid-login"></a>B.1.13 <code class="literal"><openid-login></code></h3></div></div></div><p> Similar to <code class="literal"><form-login></code> and has the same attributes. The
+ default value for <code class="literal">login-processing-url</code> is
+ "/j_spring_openid_security_check". An
+ <code class="classname">OpenIDAuthenticationFilter</code> and
+ <code class="classname">OpenIDAuthenticationProvider</code> will be registered. The latter
+ requires a reference to a <code class="interfacename">UserDetailsService</code>. Again,
+ this can be specified by <code class="literal">id</code>, using the <code class="literal">user-service-ref</code>
+ attribute, or will be located automatically in the application context. </p><div class="section" title="Parent Elements of <openid-login>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-openid-login-parents"></a>Parent Elements of <code class="literal"><openid-login></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-http" title="B.1.2 <http>">http</a></li></ul></div></div><div class="section" title="<openid-login> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-openid-login-attributes"></a><code class="literal"><openid-login></code> Attributes</h4></div></div></div><div class="section" title="always-use-default-target"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-openid-login-always-use-default-target"></a><code class="literal">always-use-default-target</code></h5></div></div></div><p>Whether the user should always be redirected to the default-target-url after login.</p></div><div class="section" title="authentication-details-source-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-openid-login-authentication-details-source-ref"></a><code class="literal">authentication-details-source-ref</code></h5></div></div></div><p>Reference to an AuthenticationDetailsSource which will be used by the authentication filter</p></div><div class="section" title="authentication-failure-handler-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-openid-login-authentication-failure-handler-ref"></a><code class="literal">authentication-failure-handler-ref</code></h5></div></div></div><p>Reference to an AuthenticationFailureHandler bean which should be used to handle a failed
+ authentication request. Should not be used in combination with authentication-failure-url as the
+ implementation should always deal with navigation to the subsequent destination</p></div><div class="section" title="authentication-failure-url"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-openid-login-authentication-failure-url"></a><code class="literal">authentication-failure-url</code></h5></div></div></div><p>The URL for the login failure page. If no login failure URL is specified, Spring Security will
+ automatically create a failure login URL at /spring_security_login?login_error and a corresponding
+ filter to render that login failure URL when requested.</p></div><div class="section" title="authentication-success-handler-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-openid-login-authentication-success-handler-ref"></a><code class="literal">authentication-success-handler-ref</code></h5></div></div></div><p>Reference to an AuthenticationSuccessHandler bean which should be used to handle a successful
+ authentication request. Should not be used in combination with
+ <a class="link" href="appendix-namespace.html#nsa-openid-login-default-target-url" title="default-target-url">default-target-url</a> (or
+ <a class="link" href="appendix-namespace.html#nsa-openid-login-always-use-default-target" title="always-use-default-target">
+ always-use-default-target</a>) as the implementation should always deal with navigation
+ to the subsequent destination</p></div><div class="section" title="default-target-url"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-openid-login-default-target-url"></a><code class="literal">default-target-url</code></h5></div></div></div><p>The URL that will be redirected to after successful authentication, if the user's previous action
+ could not be resumed. This generally happens if the user visits a login page without having first requested a
+ secured operation that triggers authentication. If unspecified, defaults to the root of the application.</p></div><div class="section" title="login-page"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-openid-login-login-page"></a><code class="literal">login-page</code></h5></div></div></div><p>The URL for the login page. If no login URL is specified, Spring Security will automatically
+ create a login URL at /spring_security_login and a corresponding filter to render that login URL when requested.
+ </p></div><div class="section" title="login-processing-url"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-openid-login-login-processing-url"></a><code class="literal">login-processing-url</code></h5></div></div></div><p>The URL that the login form is posted to. If unspecified, it defaults to /j_spring_security_check.</p></div><div class="section" title="password-parameter"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-openid-login-password-parameter"></a><code class="literal">password-parameter</code></h5></div></div></div><p>The name of the request parameter which contains the password. Defaults to "j_password".</p></div><div class="section" title="user-service-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-openid-login-user-service-ref"></a><code class="literal">user-service-ref</code></h5></div></div></div><p>A reference to a user-service (or UserDetailsService bean) Id</p></div><div class="section" title="username-parameter"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-openid-login-username-parameter"></a><code class="literal">username-parameter</code></h5></div></div></div><p>The name of the request parameter which contains the username. Defaults to "j_username".</p></div></div><div class="section" title="Child Elements of <openid-login>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-openid-login-children"></a>Child Elements of <openid-login></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-attribute-exchange" title="B.1.14 <attribute-exchange>">attribute-exchange</a></li></ul></div></div></div><div class="section" title="B.1.14 <attribute-exchange>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-attribute-exchange"></a>B.1.14 <code class="literal"><attribute-exchange></code></h3></div></div></div><p>The <code class="literal">attribute-exchange</code> element defines the list of
+ attributes which should be requested from the identity provider. An example can be found
+ in the <a class="link" href="ns-config.html#ns-openid" title="3.3.4 OpenID Support">OpenID Support</a> section of the namespace configuration
+ chapter. More than one can be used, in which case each must have an <code class="literal">identifier-match</code>
+ attribute, containing a regular expression which is matched against the supplied
+ OpenID identifier. This allows different attribute lists to be fetched from
+ different providers (Google, Yahoo etc).</p><div class="section" title="Parent Elements of <attribute-exchange>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-attribute-exchange-parents"></a>Parent Elements of <code class="literal"><attribute-exchange></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-openid-login" title="B.1.13 <openid-login>">openid-login</a></li></ul></div></div><div class="section" title="<attribute-exchange> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-attribute-exchange-attributes"></a><code class="literal"><attribute-exchange></code> Attributes</h4></div></div></div><div class="section" title="identifier-match"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-attribute-exchange-identifier-match"></a><code class="literal">identifier-match</code></h5></div></div></div><p>A regular expression which will be compared against the claimed identity, when deciding which
+ attribute-exchange configuration to use during authentication.</p></div></div><div class="section" title="Child Elements of <attribute-exchange>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-attribute-exchange-children"></a>Child Elements of <code class="literal"><attribute-exchange></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-openid-attribute" title="B.1.15 <openid-attribute>">openid-attribute</a></li></ul></div></div></div><div class="section" title="B.1.15 <openid-attribute>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-openid-attribute"></a>B.1.15 <code class="literal"><openid-attribute></code></h3></div></div></div><p>Attributes used when making an OpenID AX
+ <a class="link" href="http://openid.net/specs/openid-attribute-exchange-1_0.html#fetch_request" target="_top">
+ Fetch Request</a></p><div class="section" title="Parent Elements of <openid-attribute>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-openid-attribute-parents"></a>Parent Elements of <code class="literal"><openid-attribute></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-attribute-exchange" title="B.1.14 <attribute-exchange>">attribute-exchange</a></li></ul></div></div><div class="section" title="<openid-attribute> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-openid-attribute-attributes"></a><code class="literal"><openid-attribute></code> Attributes</h4></div></div></div><div class="section" title="count"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-openid-attribute-count"></a><code class="literal">count</code></h5></div></div></div><p>Specifies the number of attributes that you wish to get back. For example, return 3 emails.
+ The default value is 1.</p></div><div class="section" title="name"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-openid-attribute-name"></a><code class="literal">name</code></h5></div></div></div><p>Specifies the name of the attribute that you wish to get back. For example, email.</p></div><div class="section" title="required"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-openid-attribute-required"></a><code class="literal">required</code></h5></div></div></div><p>Specifies if this attribute is required to the OP, but does not error out if the OP does not
+ return the attribute. Default is false.</p></div><div class="section" title="type"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-openid-attribute-type"></a><code class="literal">type</code></h5></div></div></div><p>Specifies the attribute type. For example, http://axschema.org/contact/email. See your OP's
+ documentation for valid attribute types.</p></div></div></div><div class="section" title="B.1.16 <port-mappings>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-port-mappings"></a>B.1.16 <code class="literal"><port-mappings></code></h3></div></div></div><p> By default, an instance of <code class="classname">PortMapperImpl</code> will be added to
the configuration for use in redirecting to secure and insecure URLs. This element
can optionally be used to override the default mappings which that class defines.
Each child <code class="literal"><port-mapping></code> element defines a pair of
HTTP:HTTPS ports. The default mappings are 80:443 and 8080:8443. An example of
- overriding these can be found in the <a class="link" href="ns-config.html#ns-requires-channel" title="2.3.2 Adding HTTP/HTTPS Channel Security">namespace introduction</a>. </p></div><div class="section" title="B.1.5 The <form-login> Element"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-form-login"></a>B.1.5 The <code class="literal"><form-login></code> Element</h3></div></div></div><p> Used to add an <code class="classname">UsernamePasswordAuthenticationFilter</code> to the
- filter stack and an <code class="classname">LoginUrlAuthenticationEntryPoint</code> to the
- application context to provide authentication on demand. This will always take
- precedence over other namespace-created entry points. If no attributes are supplied,
- a login page will be generated automatically at the URL "/spring_security_login" <sup>[<a name="d0e7406" href="#ftn.d0e7406" class="footnote">17</a>]</sup> The behaviour can be customized using the following attributes. </p><div class="section" title="login-page"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7413"></a><code class="literal">login-page</code></h4></div></div></div><p> The URL that should be used to render the login page. Maps to the
- <code class="literal">loginFormUrl</code> property of the
- <code class="classname">LoginUrlAuthenticationEntryPoint</code>. Defaults to
- "/spring_security_login". </p></div><div class="section" title="login-processing-url"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7425"></a><code class="literal">login-processing-url</code></h4></div></div></div><p> Maps to the <code class="literal">filterProcessesUrl</code> property of
- <code class="classname">UsernamePasswordAuthenticationFilter</code>. The default value
- is "/j_spring_security_check". </p></div><div class="section" title="default-target-url"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7437"></a><code class="literal">default-target-url</code></h4></div></div></div><p>Maps to the <code class="literal">defaultTargetUrl</code> property of
- <code class="classname">UsernamePasswordAuthenticationFilter</code>. If not set, the
- default value is "/" (the application root). A user will be taken to this URL
- after logging in, provided they were not asked to login while attempting to
- access a secured resource, when they will be taken to the originally requested
- URL. </p></div><div class="section" title="always-use-default-target"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7449"></a><code class="literal">always-use-default-target</code></h4></div></div></div><p> If set to "true", the user will always start at the value given by
- <code class="literal">default-target-url</code>, regardless of how they arrived at the
- login page. Maps to the <code class="literal">alwaysUseDefaultTargetUrl</code> property of
- <code class="classname">UsernamePasswordAuthenticationFilter</code>. Default value is
- "false". </p></div><div class="section" title="authentication-failure-url"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7464"></a><code class="literal">authentication-failure-url</code></h4></div></div></div><p> Maps to the <code class="literal">authenticationFailureUrl</code> property of
- <code class="classname">UsernamePasswordAuthenticationFilter</code>. Defines the URL the
- browser will be redirected to on login failure. Defaults to
- "/spring_security_login?login_error", which will be automatically handled by the
- automatic login page generator, re-rendering the login page with an error
- message. </p></div><div class="section" title="authentication-success-handler-ref"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7476"></a><code class="literal">authentication-success-handler-ref</code></h4></div></div></div><p>This can be used as an alternative to <code class="literal">default-target-url</code>
- and <code class="literal">always-use-default-target</code>, giving you full control over
- the navigation flow after a successful authentication. The value should be the
- name of an <code class="interfacename">AuthenticationSuccessHandler</code> bean in
- the application context. By default, an imlementation of
- <code class="classname">SavedRequestAwareAuthenticationSuccessHandler</code> is used and
- injected with the <code class="literal">default-target-url</code>.</p></div><div class="section" title="authentication-failure-handler-ref"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7497"></a><code class="literal">authentication-failure-handler-ref</code></h4></div></div></div><p>Can be used as an alternative to
- <code class="literal">authentication-failure-url</code>, giving you full control over the
- navigation flow after an authentication failure. The value should be he name of
- an <code class="interfacename">AuthenticationFailureHandler</code> bean in the
- application context. </p></div></div><div class="section" title="B.1.6 The <http-basic> Element"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-http-basic"></a>B.1.6 The <code class="literal"><http-basic></code> Element</h3></div></div></div><p> Adds a <code class="classname">BasicAuthenticationFilter</code> and
- <code class="classname">BasicAuthenticationEntryPoint</code> to the configuration. The
- latter will only be used as the configuration entry point if form-based login is not
- enabled. </p></div><div class="section" title="B.1.7 The <remember-me> Element"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-remember-me"></a>B.1.7 The <code class="literal"><remember-me></code> Element</h3></div></div></div><p> Adds the <code class="classname">RememberMeAuthenticationFilter</code> to the stack. This
+ overriding these can be found in the <a class="link" href="ns-config.html#ns-requires-channel" title="3.3.2 Adding HTTP/HTTPS Channel Security">namespace introduction</a>. </p><div class="section" title="Parent Elements of <port-mappings>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-port-mappings-parents"></a>Parent Elements of <code class="literal"><port-mappings></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-http" title="B.1.2 <http>">http</a></li></ul></div></div><div class="section" title="Child Elements of <port-mappings>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-port-mappings-children"></a>Child Elements of <code class="literal"><port-mappings></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-port-mapping" title="B.1.17 <port-mapping>">port-mapping</a></li></ul></div></div></div><div class="section" title="B.1.17 <port-mapping>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-port-mapping"></a>B.1.17 <code class="literal"><port-mapping></code></h3></div></div></div><p>Provides a method to map http ports to https ports when forcing a redirect.</p><div class="section" title="Parent Elements of <port-mapping>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-port-mapping-parents"></a>Parent Elements of <code class="literal"><port-mapping></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-port-mappings" title="B.1.16 <port-mappings>">port-mappings</a></li></ul></div></div><div class="section" title="<port-mapping> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-port-mapping-attributes"></a><code class="literal"><port-mapping></code> Attributes</h4></div></div></div><div class="section" title="http"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-port-mapping-http"></a><code class="literal">http</code></h5></div></div></div><p>The http port to use.</p></div><div class="section" title="https"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-port-mapping-https"></a><code class="literal">https</code></h5></div></div></div><p>The https port to use.</p></div></div></div><div class="section" title="B.1.18 <remember-me>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-remember-me"></a>B.1.18 <code class="literal"><remember-me></code></h3></div></div></div><p> Adds the <code class="classname">RememberMeAuthenticationFilter</code> to the stack. This
in turn will be configured with either a
<code class="classname">TokenBasedRememberMeServices</code>, a
<code class="classname">PersistentTokenBasedRememberMeServices</code> or a user-specified
bean implementing <code class="interfacename">RememberMeServices</code> depending on the
- attribute settings. </p><div class="section" title="data-source-ref"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7543"></a><code class="literal">data-source-ref</code></h4></div></div></div><p> If this is set, <code class="classname">PersistentTokenBasedRememberMeServices</code>
- will be used and configured with a
- <code class="classname">JdbcTokenRepositoryImpl</code> instance. </p></div><div class="section" title="services-ref"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7555"></a><code class="literal">services-ref</code></h4></div></div></div><p> Allows complete control of the
- <code class="interfacename">RememberMeServices</code> implementation that will be
- used by the filter. The value should be the <code class="literal">id</code> of a bean in the application
- context which implements this interface. Should also implement
- <code class="interfacename">LogoutHandler</code> if a logout filter is in use.</p></div><div class="section" title="token-repository-ref"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7570"></a><code class="literal">token-repository-ref</code></h4></div></div></div><p> Configures a <code class="classname">PersistentTokenBasedRememberMeServices</code>
- but allows the use of a custom
- <code class="interfacename">PersistentTokenRepository</code> bean. </p></div><div class="section" title="The key Attribute"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7582"></a>The <code class="literal">key</code> Attribute</h4></div></div></div><p>Maps to the "key" property of
- <code class="classname">AbstractRememberMeServices</code>. Should be set to a unique
- value to ensure that remember-me cookies are only valid within the one
- application <sup>[<a name="d0e7593" href="#ftn.d0e7593" class="footnote">18</a>]</sup>. </p></div><div class="section" title="token-validity-seconds"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7600"></a><code class="literal">token-validity-seconds</code></h4></div></div></div><p> Maps to the <code class="literal">tokenValiditySeconds</code> property of
- <code class="classname">AbstractRememberMeServices</code>. Specifies the period in
- seconds for which the remember-me cookie should be valid. By default it will be
- valid for 14 days. </p></div><div class="section" title="user-service-ref"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7612"></a><code class="literal">user-service-ref</code></h4></div></div></div><p> The remember-me services implementations require access to a
- <code class="interfacename">UserDetailsService</code>, so there has to be one
- defined in the application context. If there is only one, it will be selected
- and used automatically by the namespace configuration. If there are multiple
- instances, you can specify a bean <code class="literal">id</code> explicitly using this attribute. </p></div></div><div class="section" title="B.1.8 The <session-management> Element"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-session-mgmt"></a>B.1.8 The <code class="literal"><session-management></code> Element</h3></div></div></div><p>Session-management related functionality is implemented by the addition of a
- <code class="classname">SessionManagementFilter</code> to the filter stack.</p><div class="section" title="session-fixation-protection"><div class="titlepage"><div><div><h4 class="title"><a name="session-fixation-protection"></a><code class="literal">session-fixation-protection</code></h4></div></div></div><p> Indicates whether an existing session should be invalidated when a user
- authenticates and a new session started. If set to "none" no change will be
- made. "newSession" will create a new empty session. "migrateSession" will create
- a new session and copy the session attributes to the new session. Defaults to
- "migrateSession".</p><p> If session fixation protection is enabled, the
- <code class="classname">SessionManagementFilter</code> is inected with a appropriately
- configured <code class="classname">DefaultSessionAuthenticationStrategy</code>. See the
- Javadoc for this class for more details. </p></div></div><div class="section" title="B.1.9 The <concurrency-control> Element"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-concurrent-session-control"></a>B.1.9 The <code class="literal"><concurrency-control></code> Element</h3></div></div></div><p> Adds support for concurrent session control, allowing limits to be placed on the
+ attribute settings. </p><div class="section" title="Parent Elements of <remember-me>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-remember-me-parents"></a>Parent Elements of <code class="literal"><remember-me></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-http" title="B.1.2 <http>">http</a></li></ul></div></div><div class="section" title="<remember-me> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-remember-me-attributes"></a><code class="literal"><remember-me></code> Attributes</h4></div></div></div><div class="section" title="authentication-success-handler-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-remember-me-authentication-success-handler-ref"></a><code class="literal">authentication-success-handler-ref</code></h5></div></div></div><p>Sets the <code class="code">authenticationSuccessHandler</code> property on the
+ <code class="classname">RememberMeAuthenticationFilter</code> if custom navigation is required.
+ The value should be the name of a <code class="interfacename">AuthenticationSuccessHandler</code>
+ bean in the application context. </p></div><div class="section" title="data-source-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-remember-me-data-source-ref"></a><code class="literal">data-source-ref</code></h5></div></div></div><p>A reference to a <code class="interfacename">DataSource</code> bean. If this is set,
+ <code class="classname">PersistentTokenBasedRememberMeServices</code> will be used and configured with a
+ <code class="classname">JdbcTokenRepositoryImpl</code> instance. </p></div><div class="section" title="key"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-remember-me-key"></a><code class="literal">key</code></h5></div></div></div><p>Maps to the "key" property of
+ <code class="classname">AbstractRememberMeServices</code>. Should be set to a unique
+ value to ensure that remember-me cookies are only valid within the one
+ application <sup>[<a name="d0e9921" href="#ftn.d0e9921" class="footnote">26</a>]</sup>. If this is not set a secure random value will be generated. Since generating secure
+ random values can take a while, setting this value explicitly can help improve startup times when
+ using the remember me functionality.</p></div><div class="section" title="services-alias"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-remember-me-services-alias"></a><code class="literal">services-alias</code></h5></div></div></div><p>Exports the internally defined <code class="interfacename">RememberMeServices</code> as a bean alias,
+ allowing it to be used by other beans in the application context.</p></div><div class="section" title="services-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-remember-me-services-ref"></a><code class="literal">services-ref</code></h5></div></div></div><p> Allows complete control of the
+ <code class="interfacename">RememberMeServices</code> implementation that will be
+ used by the filter. The value should be the <code class="literal">id</code> of a bean in the application
+ context which implements this interface. Should also implement
+ <code class="interfacename">LogoutHandler</code> if a logout filter is in use.</p></div><div class="section" title="token-repository-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-remember-me-token-repository-ref"></a><code class="literal">token-repository-ref</code></h5></div></div></div><p> Configures a <code class="classname">PersistentTokenBasedRememberMeServices</code>
+ but allows the use of a custom
+ <code class="interfacename">PersistentTokenRepository</code> bean. </p></div><div class="section" title="token-validity-seconds"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-remember-me-token-validity-seconds"></a><code class="literal">token-validity-seconds</code></h5></div></div></div><p> Maps to the <code class="literal">tokenValiditySeconds</code> property of
+ <code class="classname">AbstractRememberMeServices</code>. Specifies the period in
+ seconds for which the remember-me cookie should be valid. By default it will be
+ valid for 14 days. </p></div><div class="section" title="use-secure-cookie"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-remember-me-use-secure-cookie"></a><code class="literal">use-secure-cookie</code></h5></div></div></div><p>It is recommended that remember-me cookies are only submitted over HTTPS and thus should
+ be flagged as <span class="quote">“<span class="quote">secure</span>”</span>. By default, a secure cookie will be used if the
+ connection over which the login request is made is secure (as it should be).
+ If you set this property to <code class="literal">false</code>, secure cookies will not be used.
+ Setting it to <code class="literal">true</code> will always set the secure flag on the cookie.
+ This attribute maps to the <code class="literal">useSecureCookie</code> property of
+ <code class="classname">AbstractRememberMeServices</code>.
+ </p></div><div class="section" title="user-service-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-remember-me-user-service-ref"></a><code class="literal">user-service-ref</code></h5></div></div></div><p> The remember-me services implementations require access to a
+ <code class="interfacename">UserDetailsService</code>, so there has to be one
+ defined in the application context. If there is only one, it will be selected
+ and used automatically by the namespace configuration. If there are multiple
+ instances, you can specify a bean <code class="literal">id</code> explicitly using this attribute. </p></div></div></div><div class="section" title="B.1.19 <request-cache> Element"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-request-cache"></a>B.1.19 <code class="literal"><request-cache></code> Element</h3></div></div></div><p>Sets the <code class="interfacename">RequestCache</code> instance which will be used
+ by the <code class="classname">ExceptionTranslationFilter</code> to store request
+ information before invoking an
+ <code class="interfacename">AuthenticationEntryPoint</code>. </p><div class="section" title="Parent Elements of <request-cache>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-request-cache-parents"></a>Parent Elements of <code class="literal"><request-cache></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-http" title="B.1.2 <http>">http</a></li></ul></div></div><div class="section" title="<request-cache> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-request-cache-attributes"></a><code class="literal"><request-cache></code> Attributes</h4></div></div></div><div class="section" title="ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-request-cache-ref"></a><code class="literal">ref</code></h5></div></div></div><p>Defines a reference to a Spring bean that is a <code class="interfacename">RequestCache</code>.</p></div></div></div><div class="section" title="B.1.20 <session-management>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-session-management"></a>B.1.20 <code class="literal"><session-management></code></h3></div></div></div><p> Session-management related functionality is implemented by the addition of a
+ <code class="classname">SessionManagementFilter</code> to the filter stack.</p><div class="section" title="Parent Elements of <session-management>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-session-management-parents"></a>Parent Elements of <code class="literal"><session-management></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-http" title="B.1.2 <http>">http</a></li></ul></div></div><div class="section" title="<session-management> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-session-management-attributes"></a><code class="literal"><session-management></code> Attributes</h4></div></div></div><div class="section" title="invalid-session-url"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-session-management-invalid-session-url"></a><code class="literal">invalid-session-url</code></h5></div></div></div><p>Setting this attribute will inject the <code class="classname">SessionManagementFilter</code>
+ with a <code class="classname">SimpleRedirectInvalidSessionStrategy</code> configured with
+ the attribute value. When an invalid session ID is submitted, the strategy will be invoked,
+ redirecting to the configured URL.
+ </p></div><div class="section" title="session-authentication-error-url"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-session-management-session-authentication-error-url"></a><code class="literal">session-authentication-error-url</code></h5></div></div></div><p>Defines the URL of the error page which should be shown when the SessionAuthenticationStrategy
+ raises an exception. If not set, an unauthorized (402) error code will be returned to the client.
+ Note that this attribute doesn't apply if the error occurs during a form-based login, where the URL
+ for authentication failure will take precedence.</p></div><div class="section" title="session-authentication-strategy-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-session-management-session-authentication-strategy-ref"></a><code class="literal">session-authentication-strategy-ref</code></h5></div></div></div><p>Allows injection of the SessionAuthenticationStrategy instance used by the
+ SessionManagementFilter</p></div><div class="section" title="session-fixation-protection"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-session-management-session-fixation-protection"></a><code class="literal">session-fixation-protection</code></h5></div></div></div><p> Indicates whether an existing session should be invalidated when a user
+ authenticates and a new session started. If set to "none" no change will be
+ made. "newSession" will create a new empty session. "migrateSession" will create
+ a new session and copy the session attributes to the new session. Defaults to
+ "migrateSession".</p><p> If session fixation protection is enabled, the
+ <code class="classname">SessionManagementFilter</code> is injected with an appropriately
+ configured <code class="classname">DefaultSessionAuthenticationStrategy</code>. See the
+ Javadoc for this class for more details. </p></div></div><div class="section" title="Child elements of <session-management>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-session-management-children"></a>Child elements of <code class="literal"><session-management></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-concurrency-control" title="B.1.21 <concurrency-control>">concurrency-control</a></li></ul></div></div></div><div class="section" title="B.1.21 <concurrency-control>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-concurrency-control"></a>B.1.21 <code class="literal"><concurrency-control></code></h3></div></div></div><p> Adds support for concurrent session control, allowing limits to be placed on the
number of active sessions a user can have. A
<code class="classname">ConcurrentSessionFilter</code> will be created, and a
<code class="classname">ConcurrentSessionControlStrategy</code> will be used with the
@@ -206,67 +316,59 @@
created authentication filter. An instance of
<code class="interfacename">SessionRegistry</code> (a
<code class="classname">SessionRegistryImpl</code> instance unless the user wishes to use a
- custom bean) will be created for use by the strategy.</p><div class="section" title="The max-sessions attribute"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7675"></a>The <code class="literal">max-sessions</code> attribute</h4></div></div></div><p>Maps to the <code class="literal">maximumSessions</code> property of
- <code class="classname">ConcurrentSessionControlStrategy</code>.</p></div><div class="section" title="The expired-url attribute"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7689"></a>The <code class="literal">expired-url</code> attribute</h4></div></div></div><p> The URL a user will be redirected to if they attempt to use a session which
- has been "expired" by the concurrent session controller because the user has
- exceeded the number of allowed sessions and has logged in again elsewhere.
- Should be set unless <code class="literal">exception-if-maximum-exceeded</code> is set. If
- no value is supplied, an expiry message will just be written directly back to
- the response. </p></div><div class="section" title="The error-if-maximum-exceeded attribute"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7700"></a>The <code class="literal">error-if-maximum-exceeded</code> attribute</h4></div></div></div><p>If set to "true" a
- <code class="exceptionname">SessionAuthenticationException</code> will be raised
- when a user attempts to exceed the maximum allowed number of sessions. The
- default behaviour is to expire the original session. </p></div><div class="section" title="The session-registry-alias and session-registry-ref attributes"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7711"></a>The <code class="literal">session-registry-alias</code> and
- <code class="literal">session-registry-ref</code> attributes</h4></div></div></div><p> The user can supply their own <code class="interfacename">SessionRegistry</code>
- implementation using the <code class="literal">session-registry-ref</code> attribute. The
- other concurrent session control beans will be wired up to use it. </p><p> It can also be useful to have a reference to the internal session registry
- for use in your own beans or an admin interface. You can expose the interal bean
- using the <code class="literal">session-registry-alias</code> attribute, giving it a name
- that you can use elsewhere in your configuration. </p></div></div><div class="section" title="B.1.10 The <anonymous> Element"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-anonymous"></a>B.1.10 The <code class="literal"><anonymous></code> Element</h3></div></div></div><p> Adds an <code class="classname">AnonymousAuthenticationFilter</code> to the stack and an
- <code class="classname">AnonymousAuthenticationProvider</code>. Required if you are using
- the <code class="literal">IS_AUTHENTICATED_ANONYMOUSLY</code> attribute. </p></div><div class="section" title="B.1.11 The <x509> Element"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-x509"></a>B.1.11 The <code class="literal"><x509></code> Element</h3></div></div></div><p> Adds support for X.509 authentication. An
+ custom bean) will be created for use by the strategy.</p><div class="section" title="Parent Elements of <concurrency-control>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-concurrency-control-parents"></a>Parent Elements of <code class="literal"><concurrency-control></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-session-management" title="B.1.20 <session-management>">session-management</a></li></ul></div></div><div class="section" title="<concurrency-control> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-concurrency-control-attributes"></a><code class="literal"><concurrency-control></code> Attributes</h4></div></div></div><div class="section" title="error-if-maximum-exceeded"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-concurrency-control-error-if-maximum-exceeded"></a><code class="literal">error-if-maximum-exceeded</code></h5></div></div></div><p>If set to "true" a
+ <code class="exceptionname">SessionAuthenticationException</code> will be raised
+ when a user attempts to exceed the maximum allowed number of sessions. The
+ default behaviour is to expire the original session. </p></div><div class="section" title="expired-url"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-concurrency-control-expired-url"></a><code class="literal">expired-url</code></h5></div></div></div><p> The URL a user will be redirected to if they attempt to use a session which
+ has been "expired" by the concurrent session controller because the user has
+ exceeded the number of allowed sessions and has logged in again elsewhere.
+ Should be set unless <code class="literal">exception-if-maximum-exceeded</code> is set. If
+ no value is supplied, an expiry message will just be written directly back to
+ the response. </p></div><div class="section" title="max-sessions"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-concurrency-control-max-sessions"></a><code class="literal">max-sessions</code></h5></div></div></div><p>Maps to the <code class="literal">maximumSessions</code> property of
+ <code class="classname">ConcurrentSessionControlStrategy</code>.</p></div><div class="section" title="session-registry-alias"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-concurrency-control-session-registry-alias"></a><code class="literal">session-registry-alias</code></h5></div></div></div><p> It can also be useful to have a reference to the internal session registry
+ for use in your own beans or an admin interface. You can expose the internal bean
+ using the <code class="literal">session-registry-alias</code> attribute, giving it a name
+ that you can use elsewhere in your configuration. </p></div><div class="section" title="session-registry-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-concurrency-control-session-registry-ref"></a><code class="literal">session-registry-ref</code></h5></div></div></div><p> The user can supply their own <code class="interfacename">SessionRegistry</code>
+ implementation using the <code class="literal">session-registry-ref</code> attribute. The
+ other concurrent session control beans will be wired up to use it. </p></div></div></div><div class="section" title="B.1.22 <x509>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-x509"></a>B.1.22 <code class="literal"><x509></code></h3></div></div></div><p> Adds support for X.509 authentication. An
<code class="classname">X509AuthenticationFilter</code> will be added to the stack and an
<code class="classname">Http403ForbiddenEntryPoint</code> bean will be created. The latter
- will only be used if no other authentication mechanisms are in use (it's only
+ will only be used if no other authentication mechanisms are in use (its only
functionality is to return an HTTP 403 error code). A
<code class="classname">PreAuthenticatedAuthenticationProvider</code> will also be created
which delegates the loading of user authorities to a
- <code class="interfacename">UserDetailsService</code>. </p><div class="section" title="The subject-principal-regex attribute"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7770"></a>The <code class="literal">subject-principal-regex</code> attribute</h4></div></div></div><p> Defines a regular expression which will be used to extract the username from
- the certificate (for use with the
- <code class="interfacename">UserDetailsService</code>). </p></div><div class="section" title="The user-service-ref attribute"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7781"></a>The <code class="literal">user-service-ref</code> attribute</h4></div></div></div><p> Allows a specific <code class="interfacename">UserDetailsService</code> to be
- used with X.509 in the case where multiple instances are configured. If not set,
- an attempt will be made to locate a suitable instance automatically and use
- that. </p></div></div><div class="section" title="B.1.12 The <openid-login> Element"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-openid-login"></a>B.1.12 The <code class="literal"><openid-login></code> Element</h3></div></div></div><p> Similar to <code class="literal"><form-login></code> and has the same attributes. The
- default value for <code class="literal">login-processing-url</code> is
- "/j_spring_openid_security_check". An
- <code class="classname">OpenIDAuthenticationFilter</code> and
- <code class="classname">OpenIDAuthenticationProvider</code> will be registered. The latter
- requires a reference to a <code class="interfacename">UserDetailsService</code>. Again,
- this can be specified by <code class="literal">id</code>, using the <code class="literal">user-service-ref</code>
- attribute, or will be located automatically in the application context. </p><div class="section" title="The <attribute-exchange> Element"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7821"></a>The <code class="literal"><attribute-exchange></code> Element</h4></div></div></div><p>The <code class="literal">attribute-exchange</code> element defines the list of
- attributes which should be requested from the identity provider. More than one
- can be used, in which case each must have an <code class="literal">identifier-match</code>
- attribute, containing a regular expression which is matched against the supplied
- OpenID identifer. This allows different attribute lists to be fetched from
- different providers (Google, Yahoo etc).</p></div></div><div class="section" title="B.1.13 The <logout> Element"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-logout"></a>B.1.13 The <code class="literal"><logout></code> Element</h3></div></div></div><p> Adds a <code class="classname">LogoutFilter</code> to the filter stack. This is
- configured with a <code class="classname">SecurityContextLogoutHandler</code>. </p><div class="section" title="The logout-url attribute"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7849"></a>The <code class="literal">logout-url</code> attribute</h4></div></div></div><p> The URL which will cause a logout (i.e. which will be processed by the
- filter). Defaults to "/j_spring_security_logout". </p></div><div class="section" title="The logout-success-url attribute"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7857"></a>The <code class="literal">logout-success-url</code> attribute</h4></div></div></div><p> The destination URL which the user will be taken to after logging out.
- Defaults to "/". </p></div><div class="section" title="The success-handler-ref attribute"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7865"></a>The <code class="literal">success-handler-ref</code> attribute</h4></div></div></div><p>May be used to supply an instance of <code class="interfacename">LogoutSuccessHandler</code>
- which will be invoked to control the navigation after logging out.
- </p></div><div class="section" title="The invalidate-session attribute"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7876"></a>The <code class="literal">invalidate-session</code> attribute</h4></div></div></div><p> Maps to the <code class="literal">invalidateHttpSession</code> of the
- <code class="classname">SecurityContextLogoutHandler</code>. Defaults to "true", so the
- session will be invalidated on logout.</p></div><div class="section" title="The delete-cookies attribute"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7890"></a>The <code class="literal">delete-cookies</code> attribute</h4></div></div></div><p>A comma-separated list of the names of cookies which should be deleted when the user logs out.
- </p></div></div><div class="section" title="B.1.14 The <custom-filter> Element"><div class="titlepage"><div><div><h3 class="title"><a name="d0e7898"></a>B.1.14 The <code class="literal"><custom-filter></code> Element</h3></div></div></div><p>This element is used to add a filter to the filter chain. It doesn't create any
- additional beans but is used to select a bean of type
- <code class="interfacename">javax.servlet.Filter</code> which is already defined in the
- appllication context and add that at a particular position in the filter chain
- maintained by Spring Security. Full details can be found in the namespace
- chapter.</p></div><div class="section" title="B.1.15 The request-cache Element"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-request-cache"></a>B.1.15 The <code class="literal">request-cache</code> Element</h3></div></div></div><p>Sets the <code class="interfacename">RequestCache</code> instance which will be used
- by the <code class="classname">ExceptionTranslationFilter</code> to store request
- information before invoking an
- <code class="interfacename">AuthenticationEntryPoint</code>. </p></div><div class="section" title="B.1.16 The <http-firewall> Element"><div class="titlepage"><div><div><h3 class="title"><a name="d0e7926"></a>B.1.16 The <code class="literal"><http-firewall></code> Element</h3></div></div></div><p>This is a top-level element which can be used to inject a custom implementation of
- <code class="interfacename">HttpFirewall</code> into the
- <code class="classname">FilterChainProxy</code> created by the namespace. The default
- implementation should be suitable for most applications.</p></div></div><div class="section" title="B.2 Authentication Services"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="nsa-authentication"></a>B.2 Authentication Services</h2></div></div></div><p> Before Spring Security 3.0, an <code class="interfacename">AuthenticationManager</code>
+ <code class="interfacename">UserDetailsService</code>. </p><div class="section" title="Parent Elements of <x509>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-x509-parents"></a>Parent Elements of <code class="literal"><x509></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-http" title="B.1.2 <http>">http</a></li></ul></div></div><div class="section" title="<x509> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-x509-attributes"></a><code class="literal"><x509></code> Attributes</h4></div></div></div><div class="section" title="authentication-details-source-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-x509-authentication-details-source-ref"></a><code class="literal">authentication-details-source-ref</code></h5></div></div></div><p>A reference to an <code class="interfacename">AuthenticationDetailsSource</code></p></div><div class="section" title="subject-principal-regex"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-x509-subject-principal-regex"></a><code class="literal">subject-principal-regex</code></h5></div></div></div><p> Defines a regular expression which will be used to extract the username from
+ the certificate (for use with the
+ <code class="interfacename">UserDetailsService</code>). </p></div><div class="section" title="user-service-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-x509-user-service-ref"></a><code class="literal">user-service-ref</code></h5></div></div></div><p> Allows a specific <code class="interfacename">UserDetailsService</code> to be
+ used with X.509 in the case where multiple instances are configured. If not set,
+ an attempt will be made to locate a suitable instance automatically and use
+ that. </p></div></div></div><div class="section" title="B.1.23 <filter-chain-map>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-filter-chain-map"></a>B.1.23 <code class="literal"><filter-chain-map></code></h3></div></div></div><p>Used to explicitly configure a FilterChainProxy instance with a FilterChainMap</p><div class="section" title="<filter-chain-map> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-filter-chain-map-attributes"></a><code class="literal"><filter-chain-map></code> Attributes</h4></div></div></div><div class="section" title="path-type"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-filter-chain-map-path-type"></a><code class="literal">path-type</code></h5></div></div></div><p>Superseded by the
+ <a class="link" href="appendix-namespace.html#nsa-filter-chain-map-request-matcher" title="request-matcher">request-matcher</a> attribute</p></div><div class="section" title="request-matcher"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-filter-chain-map-request-matcher"></a><code class="literal">request-matcher</code></h5></div></div></div><p>Supersedes the 'path-type' attribute. Defines the strategy use for matching incoming requests.
+ Currently the options are 'ant' (for ant path patterns), 'regex' for regular expressions and 'ciRegex' for
+ case-insensitive regular expressions.</p></div></div><div class="section" title="Child Elements of <filter-chain-map>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-filter-chain-map-children"></a>Child Elements of <code class="literal"><filter-chain-map></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-filter-chain" title="B.1.24 <filter-chain>">filter-chain</a></li></ul></div></div></div><div class="section" title="B.1.24 <filter-chain>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-filter-chain"></a>B.1.24 <code class="literal"><filter-chain></code></h3></div></div></div><p>Used within to define a specific URL pattern and the list of filters which apply to the URLs matching
+ that pattern. When multiple filter-chain elements are assembled in a list in order to configure a FilterChainProxy,
+ the most specific patterns must be placed at the top of the list, with most general ones at the bottom.</p><div class="section" title="Parent Elements of <filter-chain>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-filter-chain-parents"></a>Parent Elements of <code class="literal"><filter-chain></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-filter-chain-map" title="B.1.23 <filter-chain-map>">filter-chain-map</a></li></ul></div></div><div class="section" title="<filter-chain> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-filter-chain-attributes"></a><code class="literal"><filter-chain></code> Attributes</h4></div></div></div><div class="section" title="filters"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-filter-chain-filters"></a><code class="literal">filters</code></h5></div></div></div><p>A comma separated list of references to Spring beans that implement
+ <code class="interfacename">Filter</code>. The value "none" means that no
+ <code class="interfacename">Filter</code>'s should be used for this
+ <code class="classname">FilterChain</code>.</p></div><div class="section" title="pattern"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-filter-chain-pattern"></a><code class="literal">pattern</code></h5></div></div></div><p>A-pattern that creates RequestMatcher in combination with the
+ <a class="link" href="appendix-namespace.html#nsa-filter-chain-map-request-matcher" title="request-matcher">request-matcher</a></p></div><div class="section" title="request-matcher-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-filter-chain-request-matcher-ref"></a><code class="literal">request-matcher-ref</code></h5></div></div></div><p>A reference to a <code class="interfacename">RequestMatcher</code> that will be used to determine if the
+ <code class="interfacename">Filter</code>'s from the <code class="literal">filters</code> attribute should be invoked.</p></div></div></div><div class="section" title="B.1.25 <filter-invocation-definition-source>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-filter-invocation-definition-source"></a>B.1.25 <code class="literal"><filter-invocation-definition-source></code></h3></div></div></div><p>Deprecated synonym for filter-security-metadata-source</p><div class="section" title="<filter-invocation-definition-source> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-filter-invocation-definition-source-attributes"></a><code class="literal"><filter-invocation-definition-source></code> Attributes</h4></div></div></div><div class="section" title="id"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-filter-invocation-definition-source-id"></a><code class="literal">id</code></h5></div></div></div><p>A bean identifier, used for referring to the bean elsewhere in the context.</p></div><div class="section" title="lowercase-comparisons"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-filter-invocation-definition-source-lowercase-comparisons"></a><code class="literal">lowercase-comparisons</code></h5></div></div></div><p>Compare after forcing to lowercase</p></div><div class="section" title="path-type"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-filter-invocation-definition-source-path-type"></a><code class="literal">path-type</code></h5></div></div></div><p>Superseded by
+ <a class="link" href="appendix-namespace.html#nsa-filter-invocation-definition-source-request-matcher" title="request-matcher">request-matcher</a></p></div><div class="section" title="request-matcher"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-filter-invocation-definition-source-request-matcher"></a><code class="literal">request-matcher</code></h5></div></div></div><p>Supersedes the 'path-type' attribute. Defines the strategy use for matching incoming requests.
+ Currently the options are 'ant' (for ant path patterns), 'regex' for regular expressions and 'ciRegex' for
+ case-insensitive regular expressions.</p></div><div class="section" title="use-expressions"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-filter-invocation-definition-source-use-expressions"></a><code class="literal">use-expressions</code></h5></div></div></div><p>Enables the use of expressions in the 'access' attributes in <intercept-url> elements
+ rather than the traditional list of configuration attributes. Defaults to 'false'. If
+ enabled, each attribute should contain a single boolean expression. If the expression evaluates to 'true', access will be
+ granted.</p></div></div><div class="section" title="Child Elements of <filter-invocation-definition-source>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-filter-invocation-definition-source-children"></a>Child Elements of <code class="literal"><filter-invocation-definition-source></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-intercept-url" title="B.1.10 <intercept-url>">intercept-url</a></li></ul></div></div></div><div class="section" title="B.1.26 <filter-security-metadata-source>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-filter-security-metadata-source"></a>B.1.26 <code class="literal"><filter-security-metadata-source></code></h3></div></div></div><p>Used to explicitly configure a FilterSecurityMetadataSource bean for use with a FilterSecurityInterceptor. Usually
+ only needed if you are configuring a FilterChainProxy explicitly, rather than using the
+ <http> element. The intercept-url elements used should only contain pattern, method and access attributes. Any
+ others will result in a configuration error.</p><div class="section" title="<filter-security-metadata-source> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-filter-security-metadata-source-attributes"></a><code class="literal"><filter-security-metadata-source></code> Attributes</h4></div></div></div><div class="section" title="id"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-filter-security-metadata-source-id"></a><code class="literal">id</code></h5></div></div></div><p>A bean identifier, used for referring to the bean elsewhere in the context.</p></div><div class="section" title="lowercase-comparisons"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-filter-security-metadata-source-lowercase-comparisons"></a><code class="literal">lowercase-comparisons</code></h5></div></div></div><p>Compare after forcing to lower case</p></div><div class="section" title="path-type"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-filter-security-metadata-source-path-type"></a><code class="literal">path-type</code></h5></div></div></div><p>Superseded by
+ <a class="link" href="appendix-namespace.html#nsa-filter-security-metadata-source-request-matcher" title="request-matcher">request-matcher</a>
+ </p></div><div class="section" title="request-matcher"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-filter-security-metadata-source-request-matcher"></a><code class="literal">request-matcher</code></h5></div></div></div><p>Supersedes the 'path-type' attribute. Defines the strategy use for matching incoming requests.
+ Currently the options are 'ant' (for ant path patterns), 'regex' for regular expressions and 'ciRegex' for
+ case-insensitive regular expressions.</p></div><div class="section" title="use-expressions"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-filter-security-metadata-source-use-expressions"></a><code class="literal">use-expressions</code></h5></div></div></div><p>Enables the use of expressions in the 'access' attributes in
+ <intercept-url> elements rather than the traditional list of configuration attributes. Defaults to 'false'. If
+ enabled, each attribute should contain a single boolean expression. If the expression evaluates to 'true',
+ access will be granted.</p></div></div><div class="section" title="Child Elements of <filter-security-metadata-source>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-filter-security-metadata-source-children"></a>Child Elements of <code class="literal"><filter-security-metadata-source></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-intercept-url" title="B.1.10 <intercept-url>">intercept-url</a></li></ul></div></div></div></div><div class="section" title="B.2 Authentication Services"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="nsa-authentication"></a>B.2 Authentication Services</h2></div></div></div><p> Before Spring Security 3.0, an <code class="interfacename">AuthenticationManager</code>
was automatically registered internally. Now you must register one explicitly using the
<code class="literal"><authentication-manager></code> element. This creates an instance of
Spring Security's <code class="classname">ProviderManager</code> class, which needs to be
@@ -274,97 +376,172 @@
<code class="interfacename">AuthenticationProvider</code> instances. These can either be
created using syntax elements provided by the namespace, or they can be standard bean
definitions, marked for addition to the list using the
- <code class="literal">authentication-provider</code> element. </p><div class="section" title="B.2.1 The <authentication-manager> Element"><div class="titlepage"><div><div><h3 class="title"><a name="d0e7960"></a>B.2.1 The <code class="literal"><authentication-manager></code> Element</h3></div></div></div><p> Every Spring Security application which uses the namespace must have include this
+ <code class="literal">authentication-provider</code> element. </p><div class="section" title="B.2.1 <authentication-manager>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-authentication-manager"></a>B.2.1 <code class="literal"><authentication-manager></code></h3></div></div></div><p> Every Spring Security application which uses the namespace must have include this
element somewhere. It is responsible for registering the
<code class="interfacename">AuthenticationManager</code> which provides authentication
- services to the application. It also allows you to define an alias name for the
- internal instance for use in your own configuration. Its use is described in the
- <a class="link" href="ns-config.html#ns-auth-manager" title="2.6 The Authentication Manager and the Namespace">namespace introduction</a>. All elements
+ services to the application. All elements
which create <code class="interfacename">AuthenticationProvider</code> instances should
- be children of this element.</p><p> The element also exposes an <code class="literal">erase-credentials</code> attribute which
- maps to the <code class="literal">eraseCredentialsAfterAuthentication</code> property of the
- <code class="classname">ProviderManager</code>. This is discussed in the <a class="link" href="core-services.html#core-services-erasing-credentials" title="6.1.2 Erasing Credentials on Successful Authentication">Core Services</a> chapter.</p><div class="section" title="The <authentication-provider> Element"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7991"></a>The <code class="literal"><authentication-provider></code> Element</h4></div></div></div><p> Unless used with a <code class="literal">ref</code> attribute, this element is
- shorthand for configuring a <a class="link" href="core-services.html#core-services-dao-provider" title="6.1.1 DaoAuthenticationProvider"><code class="classname">DaoAuthenticationProvider</code></a>.
- <code class="classname">DaoAuthenticationProvider</code> loads user information from a
- <code class="interfacename">UserDetailsService</code> and compares the
- username/password combination with the values supplied at login. The
- <code class="interfacename">UserDetailsService</code> instance can be defined either
- by using an available namespace element (<code class="literal">jdbc-user-service</code> or
- by using the <code class="literal">user-service-ref</code> attribute to point to a bean
- defined elsewhere in the application context). You can find examples of these
- variations in the <a class="link" href="ns-config.html#ns-auth-providers" title="2.2.3 Using other Authentication Providers">namespace
- introduction</a>. </p><div class="section" title="The <password-encoder> Element"><div class="titlepage"><div><div><h5 class="title"><a name="d0e8024"></a>The <code class="literal"><password-encoder></code> Element</h5></div></div></div><p>Authentication providers can optionally be configured to use a password
- encoder as described in the <a class="link" href="ns-config.html#ns-password-encoder" title="Adding a Password Encoder">namespace introduction</a>. This will result in the bean being injected
- with the appropriate <code class="interfacename">PasswordEncoder</code>
- instance, potentially with an accompanying
- <code class="interfacename">SaltSource</code> bean to provide salt values for
- hashing. </p></div></div><div class="section" title="Using <authentication-provider> to refer to an AuthenticationProvider Bean"><div class="titlepage"><div><div><h4 class="title"><a name="d0e8041"></a>Using <code class="literal"><authentication-provider></code> to refer to an
- <code class="interfacename">AuthenticationProvider</code> Bean</h4></div></div></div><p> If you have written your own
- <code class="interfacename">AuthenticationProvider</code> implementation (or want to
- configure one of Spring Security's own implementations as a traditional bean for
- some reason, then you can use the following syntax to add it to the internal
- <code class="classname">ProviderManager</code>'s list: </p><pre class="programlisting">
- <security:authentication-manager>
- <security:authentication-provider ref="myAuthenticationProvider" />
- </security:authentication-manager>
- <bean id="myAuthenticationProvider" class="com.something.MyAuthenticationProvider"/>
- </pre></div></div></div><div class="section" title="B.3 Method Security"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="nsa-method-security"></a>B.3 Method Security</h2></div></div></div><div class="section" title="B.3.1 The <global-method-security> Element"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-gms"></a>B.3.1 The <code class="literal"><global-method-security></code> Element</h3></div></div></div><p> This element is the primary means of adding support for securing methods on
+ be children of this element.</p><div class="section" title="<authentication-manager> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-authentication-manager-attributes"></a><code class="literal"><authentication-manager></code> Attributes</h4></div></div></div><div class="section" title="alias"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-authentication-manager-alias"></a><code class="literal">alias</code></h5></div></div></div><p>This attribute allows you to define an alias name for the
+ internal instance for use in your own configuration. Its use is described in the
+ <a class="link" href="ns-config.html#ns-auth-manager" title="3.6 The Authentication Manager and the Namespace">namespace introduction</a>.</p></div><div class="section" title="erase-credentials"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-authentication-manager-erase-credentials"></a><code class="literal">erase-credentials</code></h5></div></div></div><p>If set to true, the AuthenticationManger will attempt to clear any credentials data in the
+ returned Authentication object, once the user has been authenticated. Literally it maps to
+ the <code class="literal">eraseCredentialsAfterAuthentication</code> property of the
+ <code class="classname">ProviderManager</code>. This is discussed in the <a class="link" href="core-services.html#core-services-erasing-credentials" title="7.1.1 Erasing Credentials on Successful Authentication">Core Services</a> chapter.</p></div><div class="section" title="id"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-authentication-manager-id"></a><code class="literal">id</code></h5></div></div></div><p>This attribute allows you to define an id for the internal instance for use in your own
+ configuration. It is the same a the alias element, but provides a more consistent experience
+ with elements that use the id attribute.</p></div></div><div class="section" title="Child Elements of <authentication-manager>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-authentication-manager-children"></a>Child Elements of <code class="literal"><authentication-manager></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-authentication-provider" title="B.2.2 <authentication-provider>">authentication-provider</a></li><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-ldap-authentication-provider" title="B.4.2 <ldap-authentication-provider>">ldap-authentication-provider</a></li></ul></div></div></div><div class="section" title="B.2.2 <authentication-provider>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-authentication-provider"></a>B.2.2 <code class="literal"><authentication-provider></code></h3></div></div></div><p> Unless used with a <code class="literal">ref</code> attribute, this element is
+ shorthand for configuring a <a class="link" href="core-services.html#core-services-dao-provider" title="7.1.2 DaoAuthenticationProvider"><code class="classname">DaoAuthenticationProvider</code></a>.
+ <code class="classname">DaoAuthenticationProvider</code> loads user information from a
+ <code class="interfacename">UserDetailsService</code> and compares the
+ username/password combination with the values supplied at login. The
+ <code class="interfacename">UserDetailsService</code> instance can be defined either
+ by using an available namespace element (<code class="literal">jdbc-user-service</code> or
+ by using the <code class="literal">user-service-ref</code> attribute to point to a bean
+ defined elsewhere in the application context). You can find examples of these
+ variations in the <a class="link" href="ns-config.html#ns-auth-providers" title="3.2.5 Using other Authentication Providers">namespace
+ introduction</a>. </p><div class="section" title="Parent Elements of <authentication-provider>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-authentication-provider-parents"></a>Parent Elements of <code class="literal"><authentication-provider></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-authentication-manager" title="B.2.1 <authentication-manager>">authentication-manager</a></li></ul></div></div><div class="section" title="<authentication-provider> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-authentication-provider-attributes"></a><code class="literal"><authentication-provider></code> Attributes</h4></div></div></div><div class="section" title="ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-authentication-provider-ref"></a><code class="literal">ref</code></h5></div></div></div><p>Defines a reference to a Spring bean that implements <code class="interfacename">AuthenticationProvider
+ </code>.</p><p> If you have written your own
+ <code class="interfacename">AuthenticationProvider</code> implementation (or want to
+ configure one of Spring Security's own implementations as a traditional bean for
+ some reason, then you can use the following syntax to add it to the internal
+ <code class="classname">ProviderManager</code>'s list: </p><pre class="programlisting">
+<span class="hl-tag"><security:authentication-manager></span>
+ <span class="hl-tag"><security:authentication-provider</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"myAuthenticationProvider"</span><span class="hl-tag"> /></span>
+<span class="hl-tag"></security:authentication-manager></span>
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"myAuthenticationProvider"</span> <span class="hl-attribute">class</span>=<span class="hl-value">"com.something.MyAuthenticationProvider"</span><span class="hl-tag">/></span>
+ </pre></div><div class="section" title="user-service-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-authentication-provider-user-service-ref"></a><code class="literal">user-service-ref</code></h5></div></div></div><p>A reference to a bean that implements UserDetailsService that may be created using the standard bean
+ element or the custom user-service element.</p></div></div><div class="section" title="Child Elements of <authentication-provider>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-authentication-provider-children"></a>Child Elements of <code class="literal"><authentication-provider></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-jdbc-user-service" title="B.2.3 <jdbc-user-service>">jdbc-user-service</a></li><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-ldap-user-service" title="B.4.4 <ldap-user-service>">ldap-user-service</a></li><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-password-encoder" title="B.2.4 <password-encoder>">password-encoder</a></li><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-user-service" title="B.2.6 <user-service>">user-service</a></li></ul></div></div></div><div class="section" title="B.2.3 <jdbc-user-service>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-jdbc-user-service"></a>B.2.3 <code class="literal"><jdbc-user-service></code></h3></div></div></div><p>Causes creation of a JDBC-based UserDetailsService.</p><div class="section" title="<jdbc-user-service> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-jdbc-user-service-attributes"></a><code class="literal"><jdbc-user-service></code> Attributes</h4></div></div></div><div class="section" title="authorities-by-username-query"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-jdbc-user-service-authorities-by-username-query"></a><code class="literal">authorities-by-username-query</code></h5></div></div></div><p>An SQL statement to query for a user's granted authorities given a username.</p><p>The default is
+ </p><pre class="programlisting">select username, authority from authorities where username = ?</pre></div><div class="section" title="cache-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-jdbc-user-service-cache-ref"></a><code class="literal">cache-ref</code></h5></div></div></div><p>Defines a reference to a cache for use with a UserDetailsService.</p></div><div class="section" title="data-source-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-jdbc-user-service-data-source-ref"></a><code class="literal">data-source-ref</code></h5></div></div></div><p>The bean ID of the DataSource which provides the required tables.</p></div><div class="section" title="group-authorities-by-username-query"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-jdbc-user-service-group-authorities-by-username-query"></a><code class="literal">group-authorities-by-username-query</code></h5></div></div></div><p>An SQL statement to query user's group authorities given a username.</p><p>The default is
+ </p><pre class="programlisting">select
+ g.id, g.group_name, ga.authority
+from
+ groups g, group_members gm, group_authorities ga
+where
+ gm.username = ? and g.id = ga.group_id and g.id = gm.group_id</pre></div><div class="section" title="id"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-jdbc-user-service-id"></a><code class="literal">id</code></h5></div></div></div><p>A bean identifier, used for referring to the bean elsewhere in the context.</p></div><div class="section" title="role-prefix"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-jdbc-user-service-role-prefix"></a><code class="literal">role-prefix</code></h5></div></div></div><p>A non-empty string prefix that will be added to role strings loaded from persistent
+ storage (default is "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty.</p></div><div class="section" title="users-by-username-query"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-jdbc-user-service-users-by-username-query"></a><code class="literal">users-by-username-query</code></h5></div></div></div><p>An SQL statement to query a username, password, and enabled status given a username.</p><p>The default is
+ </p><pre class="programlisting">select username, password, enabled from users where username = ?</pre></div></div></div><div class="section" title="B.2.4 <password-encoder>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-password-encoder"></a>B.2.4 <code class="literal"><password-encoder></code></h3></div></div></div><p>Authentication providers can optionally be configured to use a password
+ encoder as described in the <a class="link" href="ns-config.html#ns-password-encoder" title="Adding a Password Encoder">namespace introduction</a>. This will result in the bean being injected
+ with the appropriate <code class="interfacename">PasswordEncoder</code>
+ instance, potentially with an accompanying
+ <code class="interfacename">SaltSource</code> bean to provide salt values for
+ hashing. </p><div class="section" title="Parent Elements of <password-encoder>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-password-encoder-parents"></a>Parent Elements of <code class="literal"><password-encoder></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-authentication-provider" title="B.2.2 <authentication-provider>">authentication-provider</a></li><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-password-compare" title="B.4.3 <password-compare>">password-compare</a></li></ul></div></div><div class="section" title="<password-encoder> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-password-encoder-attributes"></a><code class="literal"><password-encoder></code> Attributes</h4></div></div></div><div class="section" title="base64"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-password-encoder-base64"></a><code class="literal">base64</code></h5></div></div></div><p>Whether a string should be base64 encoded</p></div><div class="section" title="hash"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-password-encoder-hash"></a><code class="literal">hash</code></h5></div></div></div><p>Defines the hashing algorithm used on user passwords. We recommend strongly against using
+ MD4, as it is a very weak hashing algorithm.</p></div><div class="section" title="ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-password-encoder-ref"></a><code class="literal">ref</code></h5></div></div></div><p>Defines a reference to a Spring bean that implements <code class="interfacename">PasswordEncoder
+ </code>.</p></div></div><div class="section" title="Child Elements of <password-encoder>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-password-encoder-children"></a>Child Elements of <code class="literal"><password-encoder></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-salt-source" title="B.2.5 <salt-source>">salt-source</a></li></ul></div></div></div><div class="section" title="B.2.5 <salt-source>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-salt-source"></a>B.2.5 <code class="literal"><salt-source></code></h3></div></div></div><p>Password salting strategy. A system-wide constant or a property from the UserDetails object
+ can be used.</p><div class="section" title="Parent Elements of <salt-source>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-salt-source-parents"></a>Parent Elements of <code class="literal"><salt-source></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-password-encoder" title="B.2.4 <password-encoder>">password-encoder</a></li></ul></div></div><div class="section" title="<salt-source> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-salt-source-attributes"></a><code class="literal"><salt-source></code> Attributes</h4></div></div></div><div class="section" title="ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-salt-source-ref"></a><code class="literal">ref</code></h5></div></div></div><p>Defines a reference to a Spring bean Id.</p></div><div class="section" title="system-wide"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-salt-source-system-wide"></a><code class="literal">system-wide</code></h5></div></div></div><p>A single value that will be used as the salt for a password encoder.</p></div><div class="section" title="user-property"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-salt-source-user-property"></a><code class="literal">user-property</code></h5></div></div></div><p>A property of the UserDetails object which will be used as salt by a password encoder.
+ Typically something like "username" might be used.</p></div></div></div><div class="section" title="B.2.6 <user-service>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-user-service"></a>B.2.6 <code class="literal"><user-service></code></h3></div></div></div><p>Creates an in-memory UserDetailsService from a properties file or a list of "user" child
+ elements. Usernames are converted to lower-case internally to allow for case-insensitive lookups, so
+ this should not be used if case-sensitivity is required.</p><div class="section" title="<user-service> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-user-service-attributes"></a><code class="literal"><user-service></code> Attributes</h4></div></div></div><div class="section" title="id"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-user-service-id"></a><code class="literal">id</code></h5></div></div></div><p>A bean identifier, used for referring to the bean elsewhere in the context.</p></div><div class="section" title="properties"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-user-service-properties"></a><code class="literal">properties</code></h5></div></div></div><p>The location of a Properties file where each line is in the format of
+ </p><pre class="programlisting">username=password,grantedAuthority[,grantedAuthority][,enabled|disabled]</pre></div></div><div class="section" title="Child Elements of <user-service>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-user-service-children"></a>Child Elements of <code class="literal"><user-service></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-user" title="B.2.7 <user>">user</a></li></ul></div></div></div><div class="section" title="B.2.7 <user>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-user"></a>B.2.7 <code class="literal"><user></code></h3></div></div></div><p>Represents a user in the application.</p><div class="section" title="Parent Elements of <user>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-user-parents"></a>Parent Elements of <code class="literal"><user></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-user-service" title="B.2.6 <user-service>">user-service</a></li></ul></div></div><div class="section" title="<user> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-user-attributes"></a><code class="literal"><user></code> Attributes</h4></div></div></div><div class="section" title="authorities"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-user-authorities"></a><code class="literal">authorities</code></h5></div></div></div><p>One of more authorities granted to the user. Separate authorities with a comma
+ (but no space). For example, "ROLE_USER,ROLE_ADMINISTRATOR"</p></div><div class="section" title="disabled"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-user-disabled"></a><code class="literal">disabled</code></h5></div></div></div><p>Can be set to "true" to mark an account as disabled and unusable.</p></div><div class="section" title="locked"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-user-locked"></a><code class="literal">locked</code></h5></div></div></div><p>Can be set to "true" to mark an account as locked and unusable.</p></div><div class="section" title="name"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-user-name"></a><code class="literal">name</code></h5></div></div></div><p>The username assigned to the user.</p></div><div class="section" title="password"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-user-password"></a><code class="literal">password</code></h5></div></div></div><p>The password assigned to the user. This may be hashed if the corresponding
+ authentication provider supports hashing (remember to set the "hash" attribute of the
+ "user-service" element). This attribute be omitted in the case where the data will
+ not be used for authentication, but only for accessing authorities. If omitted, the
+ namespace will generate a random value, preventing its accidental use for
+ authentication. Cannot be empty.</p></div></div></div></div><div class="section" title="B.3 Method Security"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="nsa-method-security"></a>B.3 Method Security</h2></div></div></div><div class="section" title="B.3.1 <global-method-security>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-global-method-security"></a>B.3.1 <code class="literal"><global-method-security></code></h3></div></div></div><p> This element is the primary means of adding support for securing methods on
Spring Security beans. Methods can be secured by the use of annotations (defined at
the interface or class level) or by defining a set of pointcuts as child elements,
- using AspectJ syntax. </p><p> Method security uses the same
- <code class="interfacename">AccessDecisionManager</code> configuration as web security,
- but this can be overridden as explained above <a class="xref" href="appendix-namespace.html#nsa-access-decision-manager-ref" title="access-decision-manager-ref">the section called “<code class="literal">access-decision-manager-ref</code>”</a>, using the same attribute. </p><div class="section" title="The secured-annotations and jsr250-annotations Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="d0e8078"></a>The <code class="literal">secured-annotations</code> and
- <code class="literal">jsr250-annotations</code> Attributes</h4></div></div></div><p> Setting these to "true" will enable support for Spring Security's own
- <code class="literal">@Secured</code> annotations and JSR-250 annotations, respectively.
- They are both disabled by default. Use of JSR-250 annotations also adds a
- <code class="classname">Jsr250Voter</code> to the
- <code class="interfacename">AccessDecisionManager</code>, so you need to make sure
- you do this if you are using a custom implementation and want to use these
- annotations. </p></div><div class="section" title="The mode Attribute"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-gms-mode"></a>The <code class="literal">mode</code> Attribute</h4></div></div></div><p>This attribute can be set to <span class="quote">“<span class="quote">aspectj</span>”</span> to specify that AspectJ
- should be used instead of the default Spring AOP. Secured methods must be woven
- with the <code class="classname">AnnotationSecurityAspect</code> from the
- <code class="literal">spring-security-aspects</code> module. </p></div><div class="section" title="Securing Methods using <protect-pointcut>"><div class="titlepage"><div><div><h4 class="title"><a name="d0e8115"></a>Securing Methods using <code class="literal"><protect-pointcut></code></h4></div></div></div><p> Rather than defining security attributes on an individual method or class
- basis using the <code class="literal">@Secured</code> annotation, you can define
- cross-cutting security constraints across whole sets of methods and interfaces
- in your service layer using the <code class="literal"><protect-pointcut></code>
- element. This has two attributes: </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p><code class="literal">expression</code> - the pointcut expression</p></li><li class="listitem"><p><code class="literal">access</code> - the security attributes which apply</p></li></ul></div><p> You can find an example in the <a class="link" href="ns-config.html#ns-protect-pointcut" title="Adding Security Pointcuts using protect-pointcut">namespace introduction</a>. </p></div><div class="section" title="The <after-invocation-provider> Element"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-custom-after-invocation"></a>The <code class="literal"><after-invocation-provider></code> Element</h4></div></div></div><p> This element can be used to decorate an
- <code class="interfacename">AfterInvocationProvider</code> for use by the security
- interceptor maintained by the <code class="literal"><global-method-security></code>
- namespace. You can define zero or more of these within the
- <code class="literal">global-method-security</code> element, each with a
- <code class="literal">ref</code> attribute pointing to an
- <code class="interfacename">AfterInvocationProvider</code> bean instance within your
- application context. </p></div></div><div class="section" title="B.3.2 LDAP Namespace Options"><div class="titlepage"><div><div><h3 class="title"><a name="d0e8166"></a>B.3.2 LDAP Namespace Options</h3></div></div></div><p> LDAP is covered in some details in <a class="link" href="ldap.html" title="18. LDAP Authentication">its own
- chapter</a>. We will expand on that here with some explanation of how the
- namespace options map to Spring beans. The LDAP implementation uses Spring LDAP
- extensively, so some familiarity with that project's API may be useful. </p><div class="section" title="Defining the LDAP Server using the <ldap-server> Element"><div class="titlepage"><div><div><h4 class="title"><a name="d0e8174"></a>Defining the LDAP Server using the <code class="literal"><ldap-server></code>
- Element</h4></div></div></div><p> This element sets up a Spring LDAP
- <code class="interfacename">ContextSource</code> for use by the other LDAP beans,
- defining the location of the LDAP server and other information (such as a
- username and password, if it doesn't allow anonymous access) for connecting to
- it. It can also be used to create an embedded server for testing. Details of the
- syntax for both options are covered in the <a class="link" href="ldap.html#ldap-server" title="18.3 Configuring an LDAP Server">LDAP
- chapter</a>. The actual <code class="interfacename">ContextSource</code>
- implementation is <code class="classname">DefaultSpringSecurityContextSource</code>
- which extends Spring LDAP's <code class="classname">LdapContextSource</code> class. The
- <code class="literal">manager-dn</code> and <code class="literal">manager-password</code> attributes
- map to the latter's <code class="literal">userDn</code> and <code class="literal">password</code>
- properties respectively. </p><p> If you only have one server defined in your application context, the other
- LDAP namespace-defined beans will use it automatically. Otherwise, you can give
- the element an "id" attribute and refer to it from other namespace beans using
- the <code class="literal">server-ref</code> attribute. This is actually the bean <code class="literal">id</code> of the
- <code class="literal">ContextSource</code> instance, if you want to use it in other
- traditional Spring beans. </p></div><div class="section" title="The <ldap-provider> Element"><div class="titlepage"><div><div><h4 class="title"><a name="d0e8220"></a>The <code class="literal"><ldap-provider></code> Element</h4></div></div></div><p> This element is shorthand for the creation of an
- <code class="classname">LdapAuthenticationProvider</code> instance. By default this will
- be configured with a <code class="classname">BindAuthenticator</code> instance and a
- <code class="classname">DefaultAuthoritiesPopulator</code>. As with all namespace
- authentication providers, it must be included as a child of the
- <code class="literal">authentication-provider</code> element.</p><div class="section" title="The user-dn-pattern Attribute"><div class="titlepage"><div><div><h5 class="title"><a name="d0e8240"></a>The <code class="literal">user-dn-pattern</code> Attribute</h5></div></div></div><p> If your users are at a fixed location in the directory (i.e. you can work
+ using AspectJ syntax. </p><div class="section" title="<global-method-security> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-global-method-security-attributes"></a><code class="literal"><global-method-security></code> Attributes</h4></div></div></div><div class="section" title="access-decision-manager-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-global-method-security-access-decision-manager-ref"></a><code class="literal">access-decision-manager-ref</code></h5></div></div></div><p>Method security uses the same <code class="interfacename">AccessDecisionManager</code>
+ configuration as web security, but this can be overridden using this attribute. By default
+ an AffirmativeBased implementation is used for with a RoleVoter and an AuthenticatedVoter. </p></div><div class="section" title="authentication-manager-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-global-method-security-authentication-manager-ref"></a><code class="literal">authentication-manager-ref</code></h5></div></div></div><p>A reference to an <code class="interfacename">AuthenticationManager</code>
+ that should be used for method security.</p></div><div class="section" title="jsr250-annotations"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-global-method-security-jsr250-annotations"></a><code class="literal">jsr250-annotations</code></h5></div></div></div><p>Specifies whether JSR-250 style attributes are to be used (for example "RolesAllowed"). This
+ will require the javax.annotation.security classes on the classpath. Setting this to true also
+ adds a <code class="classname">Jsr250Voter</code> to the
+ <code class="interfacename">AccessDecisionManager</code>, so you need to make sure you do this if
+ you are using a custom implementation and want to use these annotations.</p></div><div class="section" title="<metadata-source-ref> Attribute"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-global-method-security-metadata-source-ref"></a><code class="literal"><metadata-source-ref></code> Attribute</h5></div></div></div><p> An external <code class="interfacename">MethodSecurityMetadataSource</code>
+ instance can be supplied which will take priority over other sources
+ (such as the default annotations).
+ </p></div><div class="section" title="The mode Attribute"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-global-method-security-mode"></a>The <code class="literal">mode</code> Attribute</h5></div></div></div><p>This attribute can be set to <span class="quote">“<span class="quote">aspectj</span>”</span> to specify that AspectJ
+ should be used instead of the default Spring AOP. Secured methods must be woven
+ with the <code class="classname">AnnotationSecurityAspect</code> from the
+ <code class="literal">spring-security-aspects</code> module. </p></div><div class="section" title="order"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-global-method-security-order"></a><code class="literal">order</code></h5></div></div></div><p>Allows the advice "order" to be set for the method security interceptor.</p></div><div class="section" title="pre-post-annotations"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-global-method-security-pre-post-annotations"></a><code class="literal">pre-post-annotations</code></h5></div></div></div><p>Specifies whether the use of Spring Security's pre and post invocation annotations (@PreFilter,
+ @PreAuthorize, @PostFilter, @PostAuthorize) should be enabled for this application context.
+ Defaults to "disabled".</p></div><div class="section" title="proxy-target-class"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-global-method-security-proxy-target-class"></a><code class="literal">proxy-target-class</code></h5></div></div></div><p>If true, class based proxying will be used instead of interface based proxying.</p></div><div class="section" title="run-as-manager-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-global-method-security-run-as-manager-ref"></a><code class="literal">run-as-manager-ref</code></h5></div></div></div><p>A reference to an optional <code class="interfacename">RunAsManager</code> implementation which
+ will be used by the configured <code class="classname">MethodSecurityInterceptor</code></p></div><div class="section" title="secured-annotations"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-global-method-security-secured-annotations"></a><code class="literal">secured-annotations</code></h5></div></div></div><p>Specifies whether the use of Spring Security's @Secured annotations should be enabled for this
+ application context. Defaults to "disabled".</p></div></div><div class="section" title="Child Elements of <global-method-security>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-global-method-security-children"></a>Child Elements of <code class="literal"><global-method-security></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-after-invocation-provider" title="B.3.2 <after-invocation-provider>">after-invocation-provider</a></li><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-expression-handler" title="B.1.6 <expression-handler>">expression-handler</a></li><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-pre-post-annotation-handling" title="B.3.3 <pre-post-annotation-handling>">pre-post-annotation-handling</a></li><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-protect-pointcut" title="B.3.7 Securing Methods using <protect-pointcut>">protect-pointcut</a></li></ul></div></div></div><div class="section" title="B.3.2 <after-invocation-provider>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-after-invocation-provider"></a>B.3.2 <code class="literal"><after-invocation-provider></code></h3></div></div></div><p> This element can be used to decorate an
+ <code class="interfacename">AfterInvocationProvider</code> for use by the security
+ interceptor maintained by the <code class="literal"><global-method-security></code>
+ namespace. You can define zero or more of these within the
+ <code class="literal">global-method-security</code> element, each with a
+ <code class="literal">ref</code> attribute pointing to an
+ <code class="interfacename">AfterInvocationProvider</code> bean instance within your
+ application context. </p><div class="section" title="Parent Elements of <after-invocation-provider>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-after-invocation-provider-parents"></a>Parent Elements of <code class="literal"><after-invocation-provider></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-global-method-security" title="B.3.1 <global-method-security>">global-method-security</a></li></ul></div></div><div class="section" title="<after-invocation-provider> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-after-invocation-provider-attributes"></a><code class="literal"><after-invocation-provider></code> Attributes</h4></div></div></div><div class="section" title="ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-after-invocation-provider-ref"></a><code class="literal">ref</code></h5></div></div></div><p>Defines a reference to a Spring bean that implements <code class="interfacename">
+ AfterInvocationProvider</code>.</p></div></div></div><div class="section" title="B.3.3 <pre-post-annotation-handling>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-pre-post-annotation-handling"></a>B.3.3 <code class="literal"><pre-post-annotation-handling></code></h3></div></div></div><p>Allows the default expression-based mechanism for handling Spring Security's pre and post invocation
+ annotations (@PreFilter, @PreAuthorize, @PostFilter, @PostAuthorize) to be replace entirely. Only
+ applies if these annotations are enabled.</p><div class="section" title="Parent Elements of <pre-post-annotation-handling>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-pre-post-annotation-handling-parents"></a>Parent Elements of <code class="literal"><pre-post-annotation-handling></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-global-method-security" title="B.3.1 <global-method-security>">global-method-security</a></li></ul></div></div><div class="section" title="Child Elements of <pre-post-annotation-handling>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-pre-post-annotation-handling-children"></a>Child Elements of <code class="literal"><pre-post-annotation-handling></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-invocation-attribute-factory" title="B.3.4 <invocation-attribute-factory>">invocation-attribute-factory</a></li><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-post-invocation-advice" title="B.3.5 <post-invocation-advice>">post-invocation-advice</a></li><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-pre-invocation-advice" title="B.3.6 <pre-invocation-advice>">pre-invocation-advice</a></li></ul></div></div></div><div class="section" title="B.3.4 <invocation-attribute-factory>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-invocation-attribute-factory"></a>B.3.4 <code class="literal"><invocation-attribute-factory></code></h3></div></div></div><p>Defines the PrePostInvocationAttributeFactory instance which is used to generate pre and post
+ invocation metadata from the annotated methods.</p><div class="section" title="Parent Elements of <invocation-attribute-factory>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-invocation-attribute-factory-parents"></a>Parent Elements of <code class="literal"><invocation-attribute-factory></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-pre-post-annotation-handling" title="B.3.3 <pre-post-annotation-handling>">pre-post-annotation-handling</a></li></ul></div></div><div class="section" title="<invocation-attribute-factory> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-invocation-attribute-factory-attributes"></a><code class="literal"><invocation-attribute-factory></code> Attributes</h4></div></div></div><div class="section" title="ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-invocation-attribute-factory-ref"></a><code class="literal">ref</code></h5></div></div></div><p>Defines a reference to a Spring bean Id.</p></div></div></div><div class="section" title="B.3.5 <post-invocation-advice>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-post-invocation-advice"></a>B.3.5 <code class="literal"><post-invocation-advice></code></h3></div></div></div><p>Customizes the <code class="classname">PostInvocationAdviceProvider</code> with the ref as the
+ <code class="classname">PostInvocationAuthorizationAdvice</code> for the <pre-post-annotation-handling>
+ element.</p><div class="section" title="Parent Elements of <post-invocation-advice>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-post-invocation-advice-parents"></a>Parent Elements of <code class="literal"><post-invocation-advice></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-pre-post-annotation-handling" title="B.3.3 <pre-post-annotation-handling>">pre-post-annotation-handling</a></li></ul></div></div><div class="section" title="<post-invocation-advice> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-post-invocation-advice-attributes"></a><code class="literal"><post-invocation-advice></code> Attributes</h4></div></div></div><div class="section" title="ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-post-invocation-advice-ref"></a><code class="literal">ref</code></h5></div></div></div><p>Defines a reference to a Spring bean Id.</p></div></div></div><div class="section" title="B.3.6 <pre-invocation-advice>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-pre-invocation-advice"></a>B.3.6 <code class="literal"><pre-invocation-advice></code></h3></div></div></div><p>Customizes the <code class="classname">PreInvocationAuthorizationAdviceVoter</code> with the ref as the
+ <code class="classname">PreInvocationAuthorizationAdviceVoter</code> for the
+ <pre-post-annotation-handling> element.</p><div class="section" title="Parent Elements of <pre-invocation-advice>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-pre-invocation-advice-parents"></a>Parent Elements of <code class="literal"><pre-invocation-advice></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-pre-post-annotation-handling" title="B.3.3 <pre-post-annotation-handling>">pre-post-annotation-handling</a></li></ul></div></div><div class="section" title="<pre-invocation-advice> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-pre-invocation-advice-attributes"></a><code class="literal"><pre-invocation-advice></code> Attributes</h4></div></div></div><div class="section" title="ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-pre-invocation-advice-ref"></a><code class="literal">ref</code></h5></div></div></div><p>Defines a reference to a Spring bean Id.</p></div></div></div><div class="section" title="B.3.7 Securing Methods using <protect-pointcut>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-protect-pointcut"></a>B.3.7 Securing Methods using <code class="literal"><protect-pointcut></code></h3></div></div></div><p> Rather than defining security attributes on an individual method or class
+ basis using the <code class="literal">@Secured</code> annotation, you can define
+ cross-cutting security constraints across whole sets of methods and interfaces
+ in your service layer using the <code class="literal"><protect-pointcut></code>
+ element. You can find an example in the <a class="link" href="ns-config.html#ns-protect-pointcut" title="Adding Security Pointcuts using protect-pointcut">namespace introduction</a>.</p><div class="section" title="Parent Elements of <protect-pointcut>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-protect-pointcut-parents"></a>Parent Elements of <code class="literal"><protect-pointcut></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-global-method-security" title="B.3.1 <global-method-security>">global-method-security</a></li></ul></div></div><div class="section" title="<protect-pointcut> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-protect-pointcut-attributes"></a><code class="literal"><protect-pointcut></code> Attributes</h4></div></div></div><div class="section" title="access"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-protect-pointcut-access"></a><code class="literal">access</code></h5></div></div></div><p>Access configuration attributes list that applies to all methods matching the pointcut,
+ e.g. "ROLE_A,ROLE_B"</p></div><div class="section" title="expression"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-protect-pointcut-expression"></a><code class="literal">expression</code></h5></div></div></div><p>An AspectJ expression, including the 'execution' keyword. For example, 'execution(int
+ com.foo.TargetObject.countLength(String))' (without the quotes).</p></div></div></div><div class="section" title="B.3.8 <intercept-methods>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-intercept-methods"></a>B.3.8 <code class="literal"><intercept-methods></code></h3></div></div></div><p>Can be used inside a bean definition to add a security interceptor to the bean and set up access
+ configuration attributes for the bean's methods</p><div class="section" title="<intercept-methods> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-intercept-methods-attributes"></a><code class="literal"><intercept-methods></code> Attributes</h4></div></div></div><div class="section" title="access-decision-manager-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-intercept-methods-access-decision-manager-ref"></a><code class="literal">access-decision-manager-ref</code></h5></div></div></div><p>Optional AccessDecisionManager bean ID to be used by the created method security interceptor.</p></div></div><div class="section" title="Child Elements of <intercept-methods>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-intercept-methods-children"></a>Child Elements of <code class="literal"><intercept-methods></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-protect" title="B.3.10 <protect>">protect</a></li></ul></div></div></div><div class="section" title="B.3.9 <method-security-metadata-source>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-method-security-metadata-source"></a>B.3.9 <code class="literal"><method-security-metadata-source></code></h3></div></div></div><p>Creates a MethodSecurityMetadataSource instance</p><div class="section" title="<method-security-metadata-source> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-method-security-metadata-source-attributes"></a><code class="literal"><method-security-metadata-source></code> Attributes</h4></div></div></div><div class="section" title="id"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-method-security-metadata-source-id"></a><code class="literal">id</code></h5></div></div></div><p>A bean identifier, used for referring to the bean elsewhere in the context.</p></div><div class="section" title="use-expressions"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-method-security-metadata-source-use-expressions"></a><code class="literal">use-expressions</code></h5></div></div></div><p>Enables the use of expressions in the 'access' attributes in
+ <intercept-url> elements rather than the traditional list of configuration attributes.
+ Defaults to 'false'. If enabled, each attribute should contain a single boolean expression.
+ If the expression evaluates to 'true', access will be granted.</p></div></div><div class="section" title="Child Elements of <method-security-metadata-source>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-method-security-metadata-source-children"></a>Child Elements of <code class="literal"><method-security-metadata-source></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-protect" title="B.3.10 <protect>">protect</a></li></ul></div></div></div><div class="section" title="B.3.10 <protect>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-protect"></a>B.3.10 <code class="literal"><protect></code></h3></div></div></div><p>Defines a protected method and the access control configuration attributes that apply to it. We
+ strongly advise you NOT to mix "protect" declarations with any services provided "global-method-security".</p><div class="section" title="Parent Elements of <protect>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-protect-parents"></a>Parent Elements of <code class="literal"><protect></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-intercept-methods" title="B.3.8 <intercept-methods>">intercept-methods</a></li><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-method-security-metadata-source" title="B.3.9 <method-security-metadata-source>">method-security-metadata-source</a></li></ul></div></div><div class="section" title="<protect> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-protect-attributes"></a><code class="literal"><protect></code> Attributes</h4></div></div></div><div class="section" title="access"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-protect-access"></a><code class="literal">access</code></h5></div></div></div><p>Access configuration attributes list that applies to the method, e.g. "ROLE_A,ROLE_B".</p></div><div class="section" title="method"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-protect-method"></a><code class="literal">method</code></h5></div></div></div><p>A method name</p></div></div></div></div><div class="section" title="B.4 LDAP Namespace Options"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="nsa-ldap"></a>B.4 LDAP Namespace Options</h2></div></div></div><p> LDAP is covered in some details in <a class="link" href="ldap.html" title="19. LDAP Authentication">its own
+ chapter</a>. We will expand on that here with some explanation of how the
+ namespace options map to Spring beans. The LDAP implementation uses Spring LDAP
+ extensively, so some familiarity with that project's API may be useful. </p><div class="section" title="B.4.1 Defining the LDAP Server using the <ldap-server> Element"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-ldap-server"></a>B.4.1 Defining the LDAP Server using the <code class="literal"><ldap-server></code>
+ Element</h3></div></div></div><p> This element sets up a Spring LDAP
+ <code class="interfacename">ContextSource</code> for use by the other LDAP beans,
+ defining the location of the LDAP server and other information (such as a
+ username and password, if it doesn't allow anonymous access) for connecting to
+ it. It can also be used to create an embedded server for testing. Details of the
+ syntax for both options are covered in the <a class="link" href="ldap.html#ldap-server" title="19.3 Configuring an LDAP Server">LDAP
+ chapter</a>. The actual <code class="interfacename">ContextSource</code>
+ implementation is <code class="classname">DefaultSpringSecurityContextSource</code>
+ which extends Spring LDAP's <code class="classname">LdapContextSource</code> class. The
+ <code class="literal">manager-dn</code> and <code class="literal">manager-password</code> attributes
+ map to the latter's <code class="literal">userDn</code> and <code class="literal">password</code>
+ properties respectively. </p><p> If you only have one server defined in your application context, the other
+ LDAP namespace-defined beans will use it automatically. Otherwise, you can give
+ the element an "id" attribute and refer to it from other namespace beans using
+ the <code class="literal">server-ref</code> attribute. This is actually the bean <code class="literal">id</code> of the
+ <code class="literal">ContextSource</code> instance, if you want to use it in other
+ traditional Spring beans. </p><div class="section" title="<ldap-server> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-ldap-server-attributes"></a><code class="literal"><ldap-server></code> Attributes</h4></div></div></div><div class="section" title="id"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-server-id"></a><code class="literal">id</code></h5></div></div></div><p>A bean identifier, used for referring to the bean elsewhere in the context.</p></div><div class="section" title="ldif"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-server-ldif"></a><code class="literal">ldif</code></h5></div></div></div><p>Explicitly specifies an ldif file resource to load into an embedded LDAP server. The ldiff
+ is should be a Spring resource pattern (i.e. classpath:init.ldiff). The default is
+ classpath*:*.ldiff</p></div><div class="section" title="manager-dn"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-server-manager-dn"></a><code class="literal">manager-dn</code></h5></div></div></div><p>Username (DN) of the "manager" user identity which will be used to authenticate to a
+ (non-embedded) LDAP server. If omitted, anonymous access will be used.</p></div><div class="section" title="manager-password"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-server-manager-password"></a><code class="literal">manager-password</code></h5></div></div></div><p>The password for the manager DN. This is required if the manager-dn is specified.</p></div><div class="section" title="port"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-server-port"></a><code class="literal">port</code></h5></div></div></div><p>Specifies an IP port number. Used to configure an embedded LDAP server, for example. The
+ default value is 33389.</p></div><div class="section" title="root"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-server-root"></a><code class="literal">root</code></h5></div></div></div><p>Optional root suffix for the embedded LDAP server. Default is "dc=springframework,dc=org"
+ </p></div><div class="section" title="url"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-server-url"></a><code class="literal">url</code></h5></div></div></div><p>Specifies the ldap server URL when not using the embedded LDAP server.</p></div></div></div><div class="section" title="B.4.2 <ldap-authentication-provider>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-ldap-authentication-provider"></a>B.4.2 <code class="literal"><ldap-authentication-provider></code></h3></div></div></div><p> This element is shorthand for the creation of an
+ <code class="classname">LdapAuthenticationProvider</code> instance. By default this will
+ be configured with a <code class="classname">BindAuthenticator</code> instance and a
+ <code class="classname">DefaultAuthoritiesPopulator</code>. As with all namespace
+ authentication providers, it must be included as a child of the
+ <code class="literal">authentication-provider</code> element.</p><div class="section" title="Parent Elements of <ldap-authentication-provider>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-ldap-authentication-provider-parents"></a>Parent Elements of <code class="literal"><ldap-authentication-provider></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-authentication-manager" title="B.2.1 <authentication-manager>">authentication-manager</a></li></ul></div></div><div class="section" title="<ldap-authentication-provider> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-ldap-authentication-provider-attributes"></a><code class="literal"><ldap-authentication-provider></code> Attributes</h4></div></div></div><div class="section" title="group-role-attribute"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-authentication-provider-group-role-attribute"></a><code class="literal">group-role-attribute</code></h5></div></div></div><p>The LDAP attribute name which contains the role name which will be used within Spring
+ Security. Maps to the <code class="classname">DefaultLdapAuthoritiesPopulator</code>'s
+ <code class="literal">groupRoleAttribute</code> property. Defaults to "cn".</p></div><div class="section" title="group-search-base"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-authentication-provider-group-search-base"></a><code class="literal">group-search-base</code></h5></div></div></div><p>Search base for group membership searches. Maps to the
+ <code class="classname">DefaultLdapAuthoritiesPopulator</code>'s <code class="literal">groupSearchBase</code>
+ constructor argument. Defaults to "" (searching from the root).</p></div><div class="section" title="group-search-filter"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-authentication-provider-group-search-filter"></a><code class="literal">group-search-filter</code></h5></div></div></div><p>Group search filter. Maps to the <code class="classname">DefaultLdapAuthoritiesPopulator</code>'s
+ <code class="literal">groupSearchFilter</code> property. Defaults to (uniqueMember={0}).
+ The substituted parameter is the DN of the user.</p></div><div class="section" title="role-prefix"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-authentication-provider-role-prefix"></a><code class="literal">role-prefix</code></h5></div></div></div><p>A non-empty string prefix that will be added to role strings loaded from persistent.
+ Maps to the <code class="classname">DefaultLdapAuthoritiesPopulator</code>'s
+ <code class="literal">rolePrefix</code> property. Defaults to "ROLE_". Use the value "none" for
+ no prefix in cases where the default is non-empty.</p></div><div class="section" title="server-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-authentication-provider-server-ref"></a><code class="literal">server-ref</code></h5></div></div></div><p>The optional server to use. If omitted, and a default LDAP server is registered (using
+ <ldap-server> with no Id), that server will be used.</p></div><div class="section" title="user-context-mapper-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-authentication-provider-user-context-mapper-ref"></a><code class="literal">user-context-mapper-ref</code></h5></div></div></div><p>Allows explicit customization of the loaded user object by specifying a
+ UserDetailsContextMapper bean which will be called with the context information
+ from the user's directory entry</p></div><div class="section" title="user-details-class"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-authentication-provider-user-details-class"></a><code class="literal">user-details-class</code></h5></div></div></div><p>Allows the objectClass of the user entry to be specified. If set, the framework will
+ attempt to load standard attributes for the defined class into the returned UserDetails
+ object</p></div><div class="section" title="user-dn-pattern"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-authentication-provider-user-dn-pattern"></a><code class="literal">user-dn-pattern</code></h5></div></div></div><p>If your users are at a fixed location in the directory (i.e. you can work
out the DN directly from the username without doing a directory search), you
can use this attribute to map directly to the DN. It maps directly to the
<code class="literal">userDnPatterns</code> property of
- <code class="classname">AbstractLdapAuthenticator</code>. </p></div><div class="section" title="The user-search-base and user-search-filter Attributes"><div class="titlepage"><div><div><h5 class="title"><a name="d0e8254"></a>The <code class="literal">user-search-base</code> and
- <code class="literal">user-search-filter</code> Attributes</h5></div></div></div><p> If you need to perform a search to locate the user in the directory, then
+ <code class="classname">AbstractLdapAuthenticator</code>. The value is a specific pattern
+ used to build the user's DN, for example "uid={0},ou=people". The key
+ "{0}" must be present and will be substituted with the username.</p></div><div class="section" title="user-search-base"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-authentication-provider-user-search-base"></a><code class="literal">user-search-base</code></h5></div></div></div><p>Search base for user searches. Defaults to "". Only used with a 'user-search-filter'.</p><p>If you need to perform a search to locate the user in the directory, then
+ you can set these attributes to control the search. The
+ <code class="classname">BindAuthenticator</code> will be configured with a
+ <code class="classname">FilterBasedLdapUserSearch</code> and the attribute values
+ map directly to the first two arguments of that bean's constructor. If these
+ attributes aren't set and no <code class="literal">user-dn-pattern</code> has been
+ supplied as an alternative, then the default search values of
+ <code class="literal">user-search-filter="(uid={0})"</code> and
+ <code class="literal">user-search-base=""</code> will be used. </p></div><div class="section" title="user-search-filter"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-authentication-provider-user-search-filter"></a><code class="literal">user-search-filter</code></h5></div></div></div><p>The LDAP filter used to search for users (optional). For example "(uid={0})". The
+ substituted parameter is the user's login name.</p><p>If you need to perform a search to locate the user in the directory, then
you can set these attributes to control the search. The
<code class="classname">BindAuthenticator</code> will be configured with a
<code class="classname">FilterBasedLdapUserSearch</code> and the attribute values
@@ -372,37 +549,35 @@
attributes aren't set and no <code class="literal">user-dn-pattern</code> has been
supplied as an alternative, then the default search values of
<code class="literal">user-search-filter="(uid={0})"</code> and
- <code class="literal">user-search-base=""</code> will be used. </p></div><div class="section" title="group-search-filter, group-search-base, group-role-attribute and role-prefix Attributes"><div class="titlepage"><div><div><h5 class="title"><a name="d0e8280"></a><code class="literal">group-search-filter</code>,
- <code class="literal">group-search-base</code>,
- <code class="literal">group-role-attribute</code> and <code class="literal">role-prefix</code>
- Attributes</h5></div></div></div><p> The value of <code class="literal">group-search-base</code> is mapped to the
- <code class="literal">groupSearchBase</code> constructor argument of
- <code class="classname">DefaultAuthoritiesPopulator</code> and defaults to
- "ou=groups". The default filter value is "(uniqueMember={0})", which assumes
- that the entry is of type "groupOfUniqueNames".
- <code class="literal">group-role-attribute</code> maps to the
- <code class="literal">groupRoleAttribute</code> attribute and defaults to "cn".
- Similarly <code class="literal">role-prefix</code> maps to
- <code class="literal">rolePrefix</code> and defaults to "ROLE_". </p></div><div class="section" title="The <password-compare> Element"><div class="titlepage"><div><div><h5 class="title"><a name="d0e8317"></a>The <code class="literal"><password-compare></code> Element</h5></div></div></div><p> This is used as child element to <code class="literal"><ldap-provider></code>
- and switches the authentication strategy from
- <code class="classname">BindAuthenticator</code> to
- <code class="classname">PasswordComparisonAuthenticator</code>. This can optionally
- be supplied with a <code class="literal">hash</code> attribute or with a child
- <code class="literal"><password-encoder></code> element to hash the password
- before submitting it to the directory for comparison. </p></div></div><div class="section" title="The <ldap-user-service> Element"><div class="titlepage"><div><div><h4 class="title"><a name="d0e8340"></a>The <code class="literal"><ldap-user-service></code> Element</h4></div></div></div><p> This element configures an LDAP
- <code class="interfacename">UserDetailsService</code>. The class used is
- <code class="classname">LdapUserDetailsService</code> which is a combination of a
- <code class="classname">FilterBasedLdapUserSearch</code> and a
- <code class="classname">DefaultAuthoritiesPopulator</code>. The attributes it supports
- have the same usage as in <code class="literal"><ldap-provider></code>. </p></div></div></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e6997" href="#d0e6997" class="para">16</a>] </sup>See the <a class="link" href="ns-config.html#ns-web-xml" title="2.2.1 web.xml Configuration"> introductory chapter</a> for how to set
- up the mapping from your <code class="literal">web.xml</code></p></div><div class="footnote"><p><sup>[<a name="ftn.d0e7406" href="#d0e7406" class="para">17</a>] </sup>This feature is really just provided for convenience and is not intended for
+ <code class="literal">user-search-base=""</code> will be used. </p></div></div><div class="section" title="Child Elements of <ldap-authentication-provider>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-ldap-authentication-provider-children"></a>Child Elements of <code class="literal"><ldap-authentication-provider></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-password-compare" title="B.4.3 <password-compare>">password-compare</a></li></ul></div></div></div><div class="section" title="B.4.3 <password-compare>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-password-compare"></a>B.4.3 <code class="literal"><password-compare></code></h3></div></div></div><p> This is used as child element to <code class="literal"><ldap-provider></code>
+ and switches the authentication strategy from
+ <code class="classname">BindAuthenticator</code> to
+ <code class="classname">PasswordComparisonAuthenticator</code>.</p><div class="section" title="Parent Elements of <password-compare>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-password-compare-parents"></a>Parent Elements of <code class="literal"><password-compare></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-ldap-authentication-provider" title="B.4.2 <ldap-authentication-provider>">ldap-authentication-provider</a></li></ul></div></div><div class="section" title="<password-compare> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-password-compare-attributes"></a><code class="literal"><password-compare></code> Attributes</h4></div></div></div><div class="section" title="hash"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-password-compare-hash"></a><code class="literal">hash</code></h5></div></div></div><p>Defines the hashing algorithm used on user passwords. We recommend strongly against
+ using MD4, as it is a very weak hashing algorithm.</p></div><div class="section" title="password-attribute"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-password-compare-password-attribute"></a><code class="literal">password-attribute</code></h5></div></div></div><p>The attribute in the directory which contains the user password. Defaults to "userPassword".
+ </p></div></div><div class="section" title="Child Elements of <password-compare>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-password-compare-children"></a>Child Elements of <code class="literal"><password-compare></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="appendix-namespace.html#nsa-password-encoder" title="B.2.4 <password-encoder>">password-encoder</a></li></ul></div></div></div><div class="section" title="B.4.4 <ldap-user-service>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-ldap-user-service"></a>B.4.4 <code class="literal"><ldap-user-service></code></h3></div></div></div><p> This element configures an LDAP
+ <code class="interfacename">UserDetailsService</code>. The class used is
+ <code class="classname">LdapUserDetailsService</code> which is a combination of a
+ <code class="classname">FilterBasedLdapUserSearch</code> and a
+ <code class="classname">DefaultLdapAuthoritiesPopulator</code>. The attributes it supports
+ have the same usage as in <code class="literal"><ldap-provider></code>. </p><div class="section" title="<ldap-user-service> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-ldap-user-service-attributes"></a><code class="literal"><ldap-user-service></code> Attributes</h4></div></div></div><div class="section" title="cache-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-user-service-cache-ref"></a><code class="literal">cache-ref</code></h5></div></div></div><p>Defines a reference to a cache for use with a UserDetailsService.</p></div><div class="section" title="group-role-attribute"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-user-service-group-role-attribute"></a><code class="literal">group-role-attribute</code></h5></div></div></div><p>The LDAP attribute name which contains the role name which will be used within Spring
+ Security. Defaults to "cn".</p></div><div class="section" title="group-search-base"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-user-service-group-search-base"></a><code class="literal">group-search-base</code></h5></div></div></div><p>Search base for group membership searches. Defaults to "" (searching from the root).</p></div><div class="section" title="group-search-filter"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-user-service-group-search-filter"></a><code class="literal">group-search-filter</code></h5></div></div></div><p>Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of
+ the user.</p></div><div class="section" title="id"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-user-service-id"></a><code class="literal">id</code></h5></div></div></div><p>A bean identifier, used for referring to the bean elsewhere in the context.</p></div><div class="section" title="role-prefix"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-user-service-role-prefix"></a><code class="literal">role-prefix</code></h5></div></div></div><p>A non-empty string prefix that will be added to role strings loaded from persistent
+ storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is
+ non-empty.</p></div><div class="section" title="server-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-user-service-server-ref"></a><code class="literal">server-ref</code></h5></div></div></div><p>The optional server to use. If omitted, and a default LDAP server is registered (using
+ <ldap-server> with no Id), that server will be used.</p></div><div class="section" title="user-context-mapper-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-user-service-user-context-mapper-ref"></a><code class="literal">user-context-mapper-ref</code></h5></div></div></div><p>Allows explicit customization of the loaded user object by specifying a
+ UserDetailsContextMapper bean which will be called with the context information from the
+ user's directory entry</p></div><div class="section" title="user-details-class"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-user-service-user-details-class"></a><code class="literal">user-details-class</code></h5></div></div></div><p>Allows the objectClass of the user entry to be specified. If set, the framework will
+ attempt to load standard attributes for the defined class into the returned UserDetails object
+ </p></div><div class="section" title="user-search-base"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-user-service-user-search-base"></a><code class="literal">user-search-base</code></h5></div></div></div><p>Search base for user searches. Defaults to "". Only used with a 'user-search-filter'.</p></div><div class="section" title="user-search-filter"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-user-service-user-search-filter"></a><code class="literal">user-search-filter</code></h5></div></div></div><p>The LDAP filter used to search for users (optional). For example "(uid={0})". The
+ substituted parameter is the user's login name.</p></div></div></div></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e8540" href="#d0e8540" class="para">24</a>] </sup>See the <a class="link" href="ns-config.html#ns-web-xml" title="3.2.1 web.xml Configuration">introductory chapter</a> for how to set
+ up the mapping from your <code class="literal">web.xml</code></p></div><div class="footnote"><p><sup>[<a name="ftn.d0e9129" href="#d0e9129" class="para">25</a>] </sup>This feature is really just provided for convenience and is not intended for
production (where a view technology will have been chosen and can be used to
render a customized login page). The class
<code class="classname">DefaultLoginPageGeneratingFilter</code> is responsible for
rendering the login page and will provide login forms for both normal form login
- and/or OpenID if required.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e7593" href="#d0e7593" class="para">18</a>] </sup>This doesn't affect the use of
- <code class="classname">PersistentTokenBasedRememberMeServices</code>, where the
- tokens are stored on the server side.</p></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
+ and/or OpenID if required.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e9921" href="#d0e9921" class="para">26</a>] </sup>This doesn't affect the use of
+ <code class="classname">PersistentTokenBasedRememberMeServices</code>, where the
+ tokens are stored on the server side.</p></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
- </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="appendix-schema.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> </td></tr><tr><td width="40%" align="left" valign="top">Appendix A. Security Database Schema </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> </td></tr></table></div></body></html>
\ No newline at end of file
+ </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="appendix-schema.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="appendix-dependencies.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Appendix A. Security Database Schema </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> Appendix C. Spring Security Dependencies</td></tr></table></div></body></html>
\ No newline at end of file
diff --git a/docs/reference/appendix-schema.html b/docs/reference/appendix-schema.html
index 5d9ed55..086f004 100644
--- a/docs/reference/appendix-schema.html
+++ b/docs/reference/appendix-schema.html
@@ -1,6 +1,6 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>Appendix A. Security Database Schema</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="springsecurity.html" title="Spring Security"><link rel="prev" href="runas.html" title="23. Run-As Authentication Replacement"><link rel="next" href="appendix-namespace.html" title="Appendix B. The Security Namespace"><!--Begin Google Analytics code--><script type="text/javascript">
+ <title>Appendix A. Security Database Schema</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="springsecurity.html" title="Spring Security"><link rel="prev" href="crypto.html" title="25. Spring Security Crypto Module"><link rel="next" href="appendix-namespace.html" title="Appendix B. The Security Namespace"><!--Begin Google Analytics code--><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
@@ -8,13 +8,14 @@
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
- </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Appendix A. Security Database Schema</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="runas.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="appendix-namespace.html">Next</a></td></tr></table><hr></div><div class="appendix" title="Appendix A. Security Database Schema"><div class="titlepage"><div><div><h1 class="title"><a name="appendix-schema"></a>Security Database Schema</h1></div></div></div><p> There are various database schema used by the framework and this appendix provides a single
- reference point to them all. You only need to provide the tables for the areas of functonality
- you require. </p><p> DDL statements are given for the HSQLDB database. You can use these as a guideline for
- defining the schema for the database you are using. </p><div class="section" title="A.1 User Schema"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e6840"></a>A.1 User Schema</h2></div></div></div><p> The standard JDBC implementation of the <code class="interfacename">UserDetailsService</code>
- (<code class="classname">JdbcDaoImpl</code>) requires tables to load the password, account status
- (enabled or disabled) and a list of authorities (roles) for the user.
- <a name="db_schema_users_authorities"></a></p><pre class="programlisting">
+ </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Appendix A. Security Database Schema</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="crypto.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="appendix-namespace.html">Next</a></td></tr></table><hr></div><div class="appendix" title="Appendix A. Security Database Schema"><div class="titlepage"><div><div><h1 class="title"><a name="appendix-schema"></a>Security Database Schema</h1></div></div></div><p> There are various database schema used by the framework and this appendix provides a
+ single reference point to them all. You only need to provide the tables for the areas of
+ functonality you require. </p><p> DDL statements are given for the HSQLDB database. You can use these as a guideline for
+ defining the schema for the database you are using. </p><div class="section" title="A.1 User Schema"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e8365"></a>A.1 User Schema</h2></div></div></div><p> The standard JDBC implementation of the
+ <code class="interfacename">UserDetailsService</code> (<code class="classname">JdbcDaoImpl</code>)
+ requires tables to load the password, account status (enabled or disabled) and a list of
+ authorities (roles) for the
+ user.<a name="db_schema_users_authorities"></a></p><pre class="programlisting">
create table users(
username varchar_ignorecase(50) not null primary key,
password varchar_ignorecase(50) not null,
@@ -25,9 +26,9 @@
authority varchar_ignorecase(50) not null,
constraint fk_authorities_users foreign key(username) references users(username));
create unique index ix_auth_username on authorities (username,authority);
-</pre><div class="section" title="A.1.1 Group Authorities"><div class="titlepage"><div><div><h3 class="title"><a name="d0e6853"></a>A.1.1 Group Authorities</h3></div></div></div><p> Spring Security 2.0 introduced support for group authorities in
- <code class="classname">JdbcDaoImpl</code>. The table structure if groups are enabled is as
- follows:<a name="db-schema-groups"></a></p><pre class="programlisting">
+</pre><div class="section" title="A.1.1 Group Authorities"><div class="titlepage"><div><div><h3 class="title"><a name="d0e8378"></a>A.1.1 Group Authorities</h3></div></div></div><p> Spring Security 2.0 introduced support for group authorities in
+ <code class="classname">JdbcDaoImpl</code>. The table structure if groups are enabled is as
+ follows:<a name="db-schema-groups"></a></p><pre class="programlisting">
create table groups (
id bigint generated by default as identity(start with 0) primary key,
group_name varchar_ignorecase(50) not null);
@@ -42,28 +43,35 @@ create table group_members (
username varchar(50) not null,
group_id bigint not null,
constraint fk_group_members_group foreign key(group_id) references groups(id));
- </pre></div></div><div class="section" title="A.2 Persistent Login (Remember-Me) Schema"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e6863"></a>A.2 Persistent Login (Remember-Me) Schema</h2></div></div></div><p> This table is used to store data used by the more secure <a class="link" href="remember-me.html#remember-me-persistent-token" title="10.3 Persistent Token Approach">persistent token</a> remember-me
- implementation. If you are using <code class="classname">JdbcTokenRepositoryImpl</code> either
- directly or through the namespace, then you will need this table.
- <a name="db-schema-remeber-me"></a></p><pre class="programlisting">
+ </pre><p>Remember that these tables are only required if you are using the provided JDBC
+ <code class="interfacename">UserDetailsService</code> implementation. If you write your
+ own or choose to implement <code class="interfacename">AuthenticationProvider</code>
+ without a <code class="interfacename">UserDetailsService</code>, then you have complete
+ freedom over how you store the data, as long as the interface contract is
+ satisfied.</p></div></div><div class="section" title="A.2 Persistent Login (Remember-Me) Schema"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e8399"></a>A.2 Persistent Login (Remember-Me) Schema</h2></div></div></div><p> This table is used to store data used by the more secure <a class="link" href="remember-me.html#remember-me-persistent-token" title="11.3 Persistent Token Approach">persistent token</a> remember-me
+ implementation. If you are using <code class="classname">JdbcTokenRepositoryImpl</code> either
+ directly or through the namespace, then you will need this table.
+ <a name="db-schema-remeber-me"></a></p><pre class="programlisting">
create table persistent_logins (
username varchar(64) not null,
series varchar(64) primary key,
token varchar(64) not null,
last_used timestamp not null);
-</pre></div><div class="section" title="A.3 ACL Schema"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="dbschema-acl"></a>A.3 ACL Schema</h2></div></div></div><p>There are four tables used by the Spring Security <a class="link" href="domain-acls.html" title="16. Domain Object Security (ACLs)">ACL</a> implementation. </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p><code class="literal">acl_sid</code> stores the security identities recognised by the ACL
- system. These can be unique principals or authorities which may apply to multiple
- principals.</p></li><li class="listitem"><p><code class="literal">acl_class</code> defines the domain object types to which ACLs apply.
- The <code class="literal">class</code> column stores the Java class name of the object. </p></li><li class="listitem"><p><code class="literal">acl_object_identity</code> stores the object identity definitions of
- specific domai objects.</p></li><li class="listitem"><p><code class="literal">acl_entry</code> stores the ACL permissions which apply to a specific
- object identity and security identity.</p></li></ol></div><p>It is assumed that the database will auto-generate the primary keys for each of the
- identities. The <code class="literal">JdbcMutableAclService</code> has to be able to retrieve these when
- it has created a new row in the <code class="literal">acl_sid</code> or <code class="literal">acl_class</code>
- tables. It has two properties which define the SQL needed to retrieve these values
- <code class="literal">classIdentityQuery</code> and <code class="literal">sidIdentityQuery</code>. Both of these
- default to <code class="literal">call identity()</code></p><div class="section" title="A.3.1 Hypersonic SQL"><div class="titlepage"><div><div><h3 class="title"><a name="d0e6927"></a>A.3.1 Hypersonic SQL</h3></div></div></div><p>The default schema works with the embedded HSQLDB database that is used in unit tests
- within the
- framework.<a name="dbschema-acl-hsql"></a></p><pre class="programlisting">
+</pre></div><div class="section" title="A.3 ACL Schema"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="dbschema-acl"></a>A.3 ACL Schema</h2></div></div></div><p>There are four tables used by the Spring Security <a class="link" href="domain-acls.html" title="17. Domain Object Security (ACLs)">ACL</a> implementation. </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p><code class="literal">acl_sid</code> stores the security identities recognised by the
+ ACL system. These can be unique principals or authorities which may apply to
+ multiple principals.</p></li><li class="listitem"><p><code class="literal">acl_class</code> defines the domain object types to which ACLs
+ apply. The <code class="literal">class</code> column stores the Java class name of the
+ object. </p></li><li class="listitem"><p><code class="literal">acl_object_identity</code> stores the object identity definitions
+ of specific domai objects.</p></li><li class="listitem"><p><code class="literal">acl_entry</code> stores the ACL permissions which apply to a
+ specific object identity and security identity.</p></li></ol></div><p>It is assumed that the database will auto-generate the primary keys for each of the
+ identities. The <code class="literal">JdbcMutableAclService</code> has to be able to retrieve
+ these when it has created a new row in the <code class="literal">acl_sid</code> or
+ <code class="literal">acl_class</code> tables. It has two properties which define the SQL needed
+ to retrieve these values <code class="literal">classIdentityQuery</code> and
+ <code class="literal">sidIdentityQuery</code>. Both of these default to <code class="literal">call
+ identity()</code></p><div class="section" title="A.3.1 Hypersonic SQL"><div class="titlepage"><div><div><h3 class="title"><a name="d0e8463"></a>A.3.1 Hypersonic SQL</h3></div></div></div><p>The default schema works with the embedded HSQLDB database that is used in unit
+ tests within the
+ framework.<a name="dbschema-acl-hsql"></a></p><pre class="programlisting">
create table acl_sid (
id bigint generated by default as identity(start with 100) not null primary key,
principal boolean not null,
@@ -97,8 +105,8 @@ create table acl_entry (
references acl_object_identity(id),
constraint foreign_fk_5 foreign key(sid) references acl_sid(id) );
-</pre><div class="section" title="PostgreSQL"><div class="titlepage"><div><div><h4 class="title"><a name="d0e6934"></a>PostgreSQL</h4></div></div></div><p>
- </p><pre class="programlisting">create table acl_sid(
+ </pre></div><div class="section" title="A.3.2 PostgreSQL"><div class="titlepage"><div><div><h3 class="title"><a name="d0e8470"></a>A.3.2 PostgreSQL</h3></div></div></div><p>
+ </p><pre class="programlisting">create table acl_sid(
id bigserial not null primary key,
principal boolean not null,
sid varchar(100) not null,
@@ -134,12 +142,12 @@ create table acl_entry(
constraint foreign_fk_4 foreign key(acl_object_identity)
references acl_object_identity(id),
constraint foreign_fk_5 foreign key(sid) references acl_sid(id));
-</pre><p>
- </p><p>You will have to set the <code class="literal">classIdentityQuery</code> and
- <code class="literal">sidIdentityQuery</code> properties of
- <code class="classname">JdbcMutableAclService</code> to the following values, respectively: </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p><code class="literal">select currval(pg_get_serial_sequence('acl_class',
- 'id'))</code></p></li><li class="listitem"><p><code class="literal">select currval(pg_get_serial_sequence('acl_sid',
- 'id'))</code></p></li></ul></div></div></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
+</pre><p> </p><p>You will have to set the <code class="literal">classIdentityQuery</code> and
+ <code class="literal">sidIdentityQuery</code> properties of
+ <code class="classname">JdbcMutableAclService</code> to the following values,
+ respectively: </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p><code class="literal">select currval(pg_get_serial_sequence('acl_class',
+ 'id'))</code></p></li><li class="listitem"><p><code class="literal">select currval(pg_get_serial_sequence('acl_sid',
+ 'id'))</code></p></li></ul></div></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
- </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="runas.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="appendix-namespace.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">23. Run-As Authentication Replacement </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> Appendix B. The Security Namespace</td></tr></table></div></body></html>
\ No newline at end of file
+ </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="crypto.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="appendix-namespace.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">25. Spring Security Crypto Module </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> Appendix B. The Security Namespace</td></tr></table></div></body></html>
\ No newline at end of file
diff --git a/docs/reference/authorization.html b/docs/reference/authorization.html
index 881d1df..30774c4 100644
--- a/docs/reference/authorization.html
+++ b/docs/reference/authorization.html
@@ -1,6 +1,6 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>Part IV. Authorization</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="springsecurity.html" title="Spring Security"><link rel="prev" href="anonymous.html" title="12. Anonymous Authentication"><link rel="next" href="authz-arch.html" title="13. Authorization Architecture"><!--Begin Google Analytics code--><script type="text/javascript">
+ <title>Part IV. Authorization</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="springsecurity.html" title="Spring Security"><link rel="prev" href="anonymous.html" title="13. Anonymous Authentication"><link rel="next" href="authz-arch.html" title="14. Authorization Architecture"><!--Begin Google Analytics code--><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
@@ -8,15 +8,15 @@
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
- </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Part IV. Authorization</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="anonymous.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="authz-arch.html">Next</a></td></tr></table><hr></div><div class="part" title="Part IV. Authorization"><div class="titlepage"><div><div><h1 class="title"><a name="authorization"></a>Part IV. Authorization</h1></div></div></div><div class="partintro" title="Authorization"><div></div><p>The advanced authorization capabilities within Spring Security represent one of the most
- compelling reasons for its popularity. Irrespective of how you choose to authenticate -
- whether using a Spring Security-provided mechanism and provider, or integrating with a
- container or other non-Spring Security authentication authority - you will find the
- authorization services can be used within your application in a consistent and simple
- way.</p><p>In this part we'll explore the different
- <code class="classname">AbstractSecurityInterceptor</code> implementations, which were introduced
- in Part I. We then move on to explore how to fine-tune authorization through use of domain
- access control lists.</p></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
+ </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Part IV. Authorization</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="anonymous.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="authz-arch.html">Next</a></td></tr></table><hr></div><div class="part" title="Part IV. Authorization"><div class="titlepage"><div><div><h1 class="title"><a name="authorization"></a>Part IV. Authorization</h1></div></div></div><div class="partintro" title="Authorization"><div></div><p>The advanced authorization capabilities within Spring Security represent one of
+ the most compelling reasons for its popularity. Irrespective of how you choose to
+ authenticate - whether using a Spring Security-provided mechanism and provider, or
+ integrating with a container or other non-Spring Security authentication authority -
+ you will find the authorization services can be used within your application in a
+ consistent and simple way.</p><p>In this part we'll explore the different
+ <code class="classname">AbstractSecurityInterceptor</code> implementations, which were
+ introduced in Part I. We then move on to explore how to fine-tune authorization
+ through use of domain access control lists.</p></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
- </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="anonymous.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="authz-arch.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">12. Anonymous Authentication </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 13. Authorization Architecture</td></tr></table></div></body></html>
\ No newline at end of file
+ </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="anonymous.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="authz-arch.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">13. Anonymous Authentication </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 14. Authorization Architecture</td></tr></table></div></body></html>
\ No newline at end of file
diff --git a/docs/reference/authz-arch.html b/docs/reference/authz-arch.html
index ab42825..bbdd85c 100644
--- a/docs/reference/authz-arch.html
+++ b/docs/reference/authz-arch.html
@@ -1,6 +1,6 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>13. Authorization Architecture</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="authorization.html" title="Part IV. Authorization"><link rel="prev" href="authorization.html" title="Part IV. Authorization"><link rel="next" href="secure-object-impls.html" title="14. Secure Object Implementations"><!--Begin Google Analytics code--><script type="text/javascript">
+ <title>14. Authorization Architecture</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="authorization.html" title="Part IV. Authorization"><link rel="prev" href="authorization.html" title="Part IV. Authorization"><link rel="next" href="secure-object-impls.html" title="15. Secure Object Implementations"><!--Begin Google Analytics code--><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
@@ -8,162 +8,208 @@
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
- </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">13. Authorization Architecture</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="authorization.html">Prev</a> </td><th width="60%" align="center">Part IV. Authorization</th><td width="20%" align="right"> <a accesskey="n" href="secure-object-impls.html">Next</a></td></tr></table><hr></div><div class="chapter" title="13. Authorization Architecture"><div class="titlepage"><div><div><h1 class="title"><a name="authz-arch"></a>Authorization Architecture</h1></div></div></div><div class="section" title="13.1 Authorities"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="authz-authorities"></a>13.1 Authorities</h2></div></div></div><p>As we saw in the <a class="link" href="technical-overview.html#tech-granted-authority" title="5.2.3 GrantedAuthority">technical overview</a>, all
- <code class="interfacename">Authentication</code> implementations store a list of
- <code class="interfacename">GrantedAuthority</code> objects. These represent the authorities
- that have been granted to the principal. The <code class="interfacename">GrantedAuthority</code>
- objects are inserted into the <code class="interfacename">Authentication</code> object by the
- <code class="interfacename">AuthenticationManager</code> and are later read by
- <code class="interfacename">AccessDecisionManager</code>s when making authorization
- decisions.</p><p><code class="interfacename">GrantedAuthority</code> is an interface with only one method:
- </p><pre class="programlisting">
+ </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">14. Authorization Architecture</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="authorization.html">Prev</a> </td><th width="60%" align="center">Part IV. Authorization</th><td width="20%" align="right"> <a accesskey="n" href="secure-object-impls.html">Next</a></td></tr></table><hr></div><div class="chapter" title="14. Authorization Architecture"><div class="titlepage"><div><div><h1 class="title"><a name="authz-arch"></a>Authorization Architecture</h1></div></div></div><div class="section" title="14.1 Authorities"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="authz-authorities"></a>14.1 Authorities</h2></div></div></div><p>As we saw in the <a class="link" href="technical-overview.html#tech-granted-authority" title="6.2.3 GrantedAuthority">technical overview</a>,
+ all <code class="interfacename">Authentication</code> implementations store a list of
+ <code class="interfacename">GrantedAuthority</code> objects. These represent the authorities
+ that have been granted to the principal. The
+ <code class="interfacename">GrantedAuthority</code> objects are inserted into the
+ <code class="interfacename">Authentication</code> object by the
+ <code class="interfacename">AuthenticationManager</code> and are later read by
+ <code class="interfacename">AccessDecisionManager</code>s when making authorization
+ decisions.</p><p><code class="interfacename">GrantedAuthority</code> is an interface with only one method:
+ </p><pre class="programlisting">
String getAuthority();
</pre><p> This method allows
- <code class="interfacename">AccessDecisionManager</code>s to obtain a precise
- <code class="literal">String</code> representation of the
- <code class="interfacename">GrantedAuthority</code>. By returning a representation as a
- <code class="literal">String</code>, a <code class="interfacename">GrantedAuthority</code> can be easily
- <span class="quote">“<span class="quote">read</span>”</span> by most <code class="interfacename">AccessDecisionManager</code>s. If a
- <code class="interfacename">GrantedAuthority</code> cannot be precisely represented as a
- <code class="literal">String</code>, the <code class="interfacename">GrantedAuthority</code> is considered
- <span class="quote">“<span class="quote">complex</span>”</span> and <code class="literal">getAuthority()</code> must return
- <code class="literal">null</code>.</p><p>An example of a <span class="quote">“<span class="quote">complex</span>”</span>
- <code class="interfacename">GrantedAuthority</code> would be an implementation that stores a list
- of operations and authority thresholds that apply to different customer account numbers.
- Representing this complex <code class="interfacename">GrantedAuthority</code> as a
- <code class="literal">String</code> would be quite difficult, and as a result the
- <code class="literal">getAuthority()</code> method should return <code class="literal">null</code>. This will
- indicate to any <code class="interfacename">AccessDecisionManager</code> that it will need to
- specifically support the <code class="interfacename">GrantedAuthority</code> implementation in
- order to understand its contents.</p><p>Spring Security includes one concrete <code class="interfacename">GrantedAuthority</code>
- implementation, <code class="literal">GrantedAuthorityImpl</code>. This allows any user-specified
- <code class="literal">String</code> to be converted into a
- <code class="interfacename">GrantedAuthority</code>. All
- <code class="classname">AuthenticationProvider</code>s included with the security architecture use
- <code class="literal">GrantedAuthorityImpl</code> to populate the
- <code class="interfacename">Authentication</code> object.</p></div><div class="section" title="13.2 Pre-Invocation Handling"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="authz-pre-invocation"></a>13.2 Pre-Invocation Handling</h2></div></div></div><p> As we've also seen in the <a class="link" href="technical-overview.html#secure-objects" title="5.5.2 Secure Objects and the AbstractSecurityInterceptor">Technical Overview</a>
- chapter, Spring Security provides interceptors which control access to secure objects such as
- method invocations or web requests. A pre-invocation decision on whether the invocation is
- allowed to proceed is made by the <code class="interfacename">AccessDecisionManager</code>. </p><div class="section" title="13.2.1 The AccessDecisionManager"><div class="titlepage"><div><div><h3 class="title"><a name="authz-access-decision-manager"></a>13.2.1 The AccessDecisionManager</h3></div></div></div><p>The <code class="interfacename">AccessDecisionManager</code> is called by the
- <code class="classname">AbstractSecurityInterceptor</code> and is responsible for making final
- access control decisions. The <code class="interfacename">AccessDecisionManager</code> interface
- contains three methods:
- </p><pre class="programlisting">
- void decide(Authentication authentication, Object secureObject,
- List<ConfigAttribute> config) throws AccessDeniedException;
- boolean supports(ConfigAttribute attribute);
- boolean supports(Class clazz);
+ <code class="interfacename">AccessDecisionManager</code>s to obtain a precise
+ <code class="literal">String</code> representation of the
+ <code class="interfacename">GrantedAuthority</code>. By returning a representation as a
+ <code class="literal">String</code>, a <code class="interfacename">GrantedAuthority</code> can be
+ easily <span class="quote">“<span class="quote">read</span>”</span> by most
+ <code class="interfacename">AccessDecisionManager</code>s. If a
+ <code class="interfacename">GrantedAuthority</code> cannot be precisely represented as a
+ <code class="literal">String</code>, the <code class="interfacename">GrantedAuthority</code> is
+ considered <span class="quote">“<span class="quote">complex</span>”</span> and <code class="literal">getAuthority()</code> must return
+ <code class="literal">null</code>.</p><p>An example of a <span class="quote">“<span class="quote">complex</span>”</span> <code class="interfacename">GrantedAuthority</code>
+ would be an implementation that stores a list of operations and authority thresholds
+ that apply to different customer account numbers. Representing this complex
+ <code class="interfacename">GrantedAuthority</code> as a <code class="literal">String</code> would be
+ quite difficult, and as a result the <code class="literal">getAuthority()</code> method should
+ return <code class="literal">null</code>. This will indicate to any
+ <code class="interfacename">AccessDecisionManager</code> that it will need to specifically
+ support the <code class="interfacename">GrantedAuthority</code> implementation in order to
+ understand its contents.</p><p>Spring Security includes one concrete <code class="interfacename">GrantedAuthority</code>
+ implementation, <code class="literal">GrantedAuthorityImpl</code>. This allows any user-specified
+ <code class="literal">String</code> to be converted into a
+ <code class="interfacename">GrantedAuthority</code>. All
+ <code class="classname">AuthenticationProvider</code>s included with the security architecture
+ use <code class="literal">GrantedAuthorityImpl</code> to populate the
+ <code class="interfacename">Authentication</code> object.</p></div><div class="section" title="14.2 Pre-Invocation Handling"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="authz-pre-invocation"></a>14.2 Pre-Invocation Handling</h2></div></div></div><p> As we've also seen in the <a class="link" href="technical-overview.html#secure-objects" title="6.5.2 Secure Objects and the AbstractSecurityInterceptor">Technical
+ Overview</a> chapter, Spring Security provides interceptors which control access to
+ secure objects such as method invocations or web requests. A pre-invocation decision on
+ whether the invocation is allowed to proceed is made by the
+ <code class="interfacename">AccessDecisionManager</code>. </p><div class="section" title="14.2.1 The AccessDecisionManager"><div class="titlepage"><div><div><h3 class="title"><a name="authz-access-decision-manager"></a>14.2.1 The AccessDecisionManager</h3></div></div></div><p>The <code class="interfacename">AccessDecisionManager</code> is called by the
+ <code class="classname">AbstractSecurityInterceptor</code> and is responsible for making
+ final access control decisions. The
+ <code class="interfacename">AccessDecisionManager</code> interface contains three
+ methods:
+ </p><pre class="programlisting">
+ <span class="hl-keyword">void</span> decide(Authentication authentication, Object secureObject,
+ Collection<ConfigAttribute> attrs) <span class="hl-keyword">throws</span> AccessDeniedException;
+ <span class="hl-keyword">boolean</span> supports(ConfigAttribute attribute);
+ <span class="hl-keyword">boolean</span> supports(Class clazz);
</pre><p>
- The <code class="interfacename">AccessDecisionManager</code>'s <code class="methodname">decide</code>
- method is passed all the relevant information it needs in order to make an authorization
- decision. In particular, passing the secure <code class="literal">Object</code> enables those
- arguments contained in the actual secure object invocation to be inspected. For example,
- let's assume the secure object was a <code class="classname">MethodInvocation</code>. It would be
- easy to query the <code class="classname">MethodInvocation</code> for any
- <code class="literal">Customer</code> argument, and then implement some sort of security logic in
- the <code class="interfacename">AccessDecisionManager</code> to ensure the principal is
- permitted to operate on that customer. Implementations are expected to throw an
- <code class="literal">AccessDeniedException</code> if access is denied.</p><p>The <code class="literal">supports(ConfigAttribute)</code> method is called by the
- <code class="classname">AbstractSecurityInterceptor</code> at startup time to determine if the
- <code class="interfacename">AccessDecisionManager</code> can process the passed
- <code class="literal">ConfigAttribute</code>. The <code class="literal">supports(Class)</code> method is
- called by a security interceptor implementation to ensure the configured
- <code class="interfacename">AccessDecisionManager</code> supports the type of secure object
- that the security interceptor will present.</p></div><div class="section" title="13.2.2 Voting-Based AccessDecisionManager Implementations"><div class="titlepage"><div><div><h3 class="title"><a name="authz-voting-based"></a>13.2.2 Voting-Based AccessDecisionManager Implementations</h3></div></div></div><p>Whilst users can implement their own
- <code class="interfacename">AccessDecisionManager</code> to control all aspects of
- authorization, Spring Security includes several
- <code class="interfacename">AccessDecisionManager</code> implementations that are based on
- voting. <a class="xref" href="authz-arch.html#authz-access-voting" title="Figure 13.1. Voting Decision Manager">Figure 13.1, “Voting Decision Manager”</a> illustrates the relevant classes.</p><div class="figure"><a name="authz-access-voting"></a><p class="title"><b>Figure 13.1. Voting Decision Manager</b></p><div class="figure-contents"><div class="mediaobject" align="center"><img src="images/access-decision-voting.png" align="middle" alt="Voting Decision Manager"></div></div></div><br class="figure-break"><p>Using this approach, a series of <code class="interfacename">AccessDecisionVoter</code>
- implementations are polled on an authorization decision. The
- <code class="interfacename">AccessDecisionManager</code> then decides whether or not to throw
- an <code class="literal">AccessDeniedException</code> based on its assessment of the votes.</p><p>The <code class="interfacename">AccessDecisionVoter</code> interface has three methods:
- </p><pre class="programlisting">
-int vote(Authentication authentication, Object object, List<ConfigAttribute> config);
-boolean supports(ConfigAttribute attribute);
-boolean supports(Class clazz);
+ The <code class="interfacename">AccessDecisionManager</code>'s
+ <code class="methodname">decide</code> method is passed all the relevant information it
+ needs in order to make an authorization decision. In particular, passing the secure
+ <code class="literal">Object</code> enables those arguments contained in the actual secure
+ object invocation to be inspected. For example, let's assume the secure object was a
+ <code class="classname">MethodInvocation</code>. It would be easy to query the
+ <code class="classname">MethodInvocation</code> for any <code class="literal">Customer</code>
+ argument, and then implement some sort of security logic in the
+ <code class="interfacename">AccessDecisionManager</code> to ensure the principal is
+ permitted to operate on that customer. Implementations are expected to throw an
+ <code class="literal">AccessDeniedException</code> if access is denied.</p><p>The <code class="literal">supports(ConfigAttribute)</code> method is called by the
+ <code class="classname">AbstractSecurityInterceptor</code> at startup time to determine if
+ the <code class="interfacename">AccessDecisionManager</code> can process the passed
+ <code class="literal">ConfigAttribute</code>. The <code class="literal">supports(Class)</code> method is
+ called by a security interceptor implementation to ensure the configured
+ <code class="interfacename">AccessDecisionManager</code> supports the type of secure
+ object that the security interceptor will present.</p></div><div class="section" title="14.2.2 Voting-Based AccessDecisionManager Implementations"><div class="titlepage"><div><div><h3 class="title"><a name="authz-voting-based"></a>14.2.2 Voting-Based AccessDecisionManager Implementations</h3></div></div></div><p>Whilst users can implement their own
+ <code class="interfacename">AccessDecisionManager</code> to control all aspects of
+ authorization, Spring Security includes several
+ <code class="interfacename">AccessDecisionManager</code> implementations that are based
+ on voting. <a class="xref" href="authz-arch.html#authz-access-voting" title="Figure 14.1. Voting Decision Manager">Figure 14.1, “Voting Decision Manager”</a> illustrates the relevant
+ classes.</p><div class="figure"><a name="authz-access-voting"></a><p class="title"><b>Figure 14.1. Voting Decision Manager</b></p><div class="figure-contents"><div class="mediaobject" align="center"><img src="images/access-decision-voting.png" align="middle" alt="Voting Decision Manager"></div></div></div><br class="figure-break"><p>Using this approach, a series of
+ <code class="interfacename">AccessDecisionVoter</code> implementations are polled on an
+ authorization decision. The <code class="interfacename">AccessDecisionManager</code>
+ then decides whether or not to throw an <code class="literal">AccessDeniedException</code>
+ based on its assessment of the votes.</p><p>The <code class="interfacename">AccessDecisionVoter</code> interface has three
+ methods:
+ </p><pre class="programlisting">
+<span class="hl-keyword">int</span> vote(Authentication authentication, Object object, Collection<ConfigAttribute> attrs);
+<span class="hl-keyword">boolean</span> supports(ConfigAttribute attribute);
+<span class="hl-keyword">boolean</span> supports(Class clazz);
</pre><p>
- Concrete implementations return an <code class="literal">int</code>, with possible values being
- reflected in the <code class="interfacename">AccessDecisionVoter</code> static fields
- <code class="literal">ACCESS_ABSTAIN</code>, <code class="literal">ACCESS_DENIED</code> and
- <code class="literal">ACCESS_GRANTED</code>. A voting implementation will return
- <code class="literal">ACCESS_ABSTAIN</code> if it has no opinion on an authorization decision. If it
- does have an opinion, it must return either <code class="literal">ACCESS_DENIED</code> or
- <code class="literal">ACCESS_GRANTED</code>.</p><p>There are three concrete <code class="interfacename">AccessDecisionManager</code>s provided
- with Spring Security that tally the votes. The <code class="literal">ConsensusBased</code>
- implementation will grant or deny access based on the consensus of non-abstain votes.
- Properties are provided to control behavior in the event of an equality of votes or if all
- votes are abstain. The <code class="literal">AffirmativeBased</code> implementation will grant access
- if one or more <code class="literal">ACCESS_GRANTED</code> votes were received (i.e. a deny vote will
- be ignored, provided there was at least one grant vote). Like the
- <code class="literal">ConsensusBased</code> implementation, there is a parameter that controls the
- behavior if all voters abstain. The <code class="literal">UnanimousBased</code> provider expects
- unanimous <code class="literal">ACCESS_GRANTED</code> votes in order to grant access, ignoring
- abstains. It will deny access if there is any <code class="literal">ACCESS_DENIED</code> vote. Like
- the other implementations, there is a parameter that controls the behaviour if all voters
- abstain.</p><p>It is possible to implement a custom
- <code class="interfacename">AccessDecisionManager</code> that tallies votes differently. For
- example, votes from a particular <code class="interfacename">AccessDecisionVoter</code> might
- receive additional weighting, whilst a deny vote from a particular voter may have a veto
- effect.</p><div class="section" title="RoleVoter"><div class="titlepage"><div><div><h4 class="title"><a name="authz-role-voter"></a><code class="classname">RoleVoter</code></h4></div></div></div><p> The most commonly used <code class="interfacename">AccessDecisionVoter</code> provided
- with Spring Security is the simple <code class="classname">RoleVoter</code>, which treats
- configuration attributes as simple role names and votes to grant access if the user has
- been assigned that role.</p><p>It will vote if any <code class="interfacename">ConfigAttribute</code> begins with the
- prefix <code class="literal">ROLE_</code>. It will vote to grant access if there is a
- <code class="interfacename">GrantedAuthority</code> which returns a
- <code class="literal">String</code> representation (via the <code class="literal">getAuthority()</code>
- method) exactly equal to one or more <code class="literal">ConfigAttributes</code> starting with the
- prefix <code class="literal">ROLE_</code>. If there is no exact match of any
- <code class="literal">ConfigAttribute</code> starting with <code class="literal">ROLE_</code>, the
- <code class="literal">RoleVoter</code> will vote to deny access. If no
- <code class="literal">ConfigAttribute</code> begins with <code class="literal">ROLE_</code>, the voter will
- abstain.</p></div><div class="section" title="AuthenticatedVoter"><div class="titlepage"><div><div><h4 class="title"><a name="authz-authenticated-voter"></a><code class="classname">AuthenticatedVoter</code></h4></div></div></div><p> Another voter which we've implicitly seen is the
- <code class="classname">AuthenticatedVoter</code>, which can be used to differentiate between
- anonymous, fully-authenticated and remember-me authenticated users. Many sites allow
- certain limited access under remember-me authentication, but require a user to confirm
- their identity by logging in for full access.</p><p>When we've used the attribute <code class="literal">IS_AUTHENTICATED_ANONYMOUSLY</code> to grant
- anonymous access, this attribute was being processed by the
- <code class="classname">AuthenticatedVoter</code>. See the Javadoc for this class for more
- information. </p></div><div class="section" title="Custom Voters"><div class="titlepage"><div><div><h4 class="title"><a name="d0e4509"></a>Custom Voters</h4></div></div></div><p>It is also possible to implement a custom
- <code class="interfacename">AccessDecisionVoter</code>. Several examples are provided in
- Spring Security unit tests, including <code class="literal">ContactSecurityVoter</code> and
- <code class="literal">DenyVoter</code>. The <code class="literal">ContactSecurityVoter</code> abstains from
- voting decisions where a <code class="literal">CONTACT_OWNED_BY_CURRENT_USER</code>
- <code class="literal">ConfigAttribute</code> is not found. If voting, it queries the
- <code class="classname">MethodInvocation</code> to extract the owner of the
- <code class="literal">Contact</code> object that is subject of the method call. It votes to grant
- access if the <code class="literal">Contact</code> owner matches the principal presented in the
- <code class="interfacename">Authentication</code> object. It could have just as easily
- compared the <code class="literal">Contact</code> owner with some
- <code class="interfacename">GrantedAuthority</code> the
- <code class="interfacename">Authentication</code> object presented. All of this is achieved
- with relatively few lines of code and demonstrates the flexibility of the authorization
- model.</p></div></div></div><div class="section" title="13.3 After Invocation Handling"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="authz-after-invocation-handling"></a>13.3 After Invocation Handling</h2></div></div></div><p>Whilst the <code class="interfacename">AccessDecisionManager</code> is called by the
- <code class="classname">AbstractSecurityInterceptor</code> before proceeding with the secure object
- invocation, some applications need a way of modifying the object actually returned by the
- secure object invocation. Whilst you could easily implement your own AOP concern to achieve
- this, Spring Security provides a convenient hook that has several concrete implementations
- that integrate with its ACL capabilities.</p><p><a class="xref" href="authz-arch.html#authz-after-invocation" title="Figure 13.2. After Invocation Implementation">Figure 13.2, “After Invocation Implementation”</a> illustrates Spring Security's
- <code class="literal">AfterInvocationManager</code> and its concrete implementations. </p><div class="figure"><a name="authz-after-invocation"></a><p class="title"><b>Figure 13.2. After Invocation Implementation</b></p><div class="figure-contents"><div class="mediaobject" align="center"><img src="images/after-invocation.png" align="middle" alt="After Invocation Implementation"></div></div></div><p><br class="figure-break"></p><p>Like many other parts of Spring Security, <code class="literal">AfterInvocationManager</code> has a
- single concrete implementation, <code class="literal">AfterInvocationProviderManager</code>, which polls
- a list of <code class="literal">AfterInvocationProvider</code>s. Each
- <code class="literal">AfterInvocationProvider</code> is allowed to modify the return object or throw
- an <code class="literal">AccessDeniedException</code>. Indeed multiple providers can modify the object,
- as the result of the previous provider is passed to the next in the list.</p><p>Please be aware that if you're using <code class="literal">AfterInvocationManager</code>, you will
- still need configuration attributes that allow the
- <code class="classname">MethodSecurityInterceptor</code>'s
- <code class="interfacename">AccessDecisionManager</code> to allow an operation. If you're using
- the typical Spring Security included <code class="interfacename">AccessDecisionManager</code>
- implementations, having no configuration attributes defined for a particular secure method
- invocation will cause each <code class="interfacename">AccessDecisionVoter</code> to abstain from
- voting. In turn, if the <code class="interfacename">AccessDecisionManager</code> property
- "<code class="literal">allowIfAllAbstainDecisions</code>" is <code class="literal">false</code>, an
- <code class="literal">AccessDeniedException</code> will be thrown. You may avoid this potential issue
- by either (i) setting "<code class="literal">allowIfAllAbstainDecisions</code>" to
- <code class="literal">true</code> (although this is generally not recommended) or (ii) simply ensure
- that there is at least one configuration attribute that an
- <code class="interfacename">AccessDecisionVoter</code> will vote to grant access for. This
- latter (recommended) approach is usually achieved through a <code class="literal">ROLE_USER</code> or
- <code class="literal">ROLE_AUTHENTICATED</code> configuration attribute.</p></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
+ Concrete implementations return an <code class="literal">int</code>, with possible values
+ being reflected in the <code class="interfacename">AccessDecisionVoter</code> static
+ fields <code class="literal">ACCESS_ABSTAIN</code>, <code class="literal">ACCESS_DENIED</code> and
+ <code class="literal">ACCESS_GRANTED</code>. A voting implementation will return
+ <code class="literal">ACCESS_ABSTAIN</code> if it has no opinion on an authorization decision.
+ If it does have an opinion, it must return either <code class="literal">ACCESS_DENIED</code>
+ or <code class="literal">ACCESS_GRANTED</code>.</p><p>There are three concrete <code class="interfacename">AccessDecisionManager</code>s
+ provided with Spring Security that tally the votes. The
+ <code class="literal">ConsensusBased</code> implementation will grant or deny access based on
+ the consensus of non-abstain votes. Properties are provided to control behavior in
+ the event of an equality of votes or if all votes are abstain. The
+ <code class="literal">AffirmativeBased</code> implementation will grant access if one or more
+ <code class="literal">ACCESS_GRANTED</code> votes were received (i.e. a deny vote will be
+ ignored, provided there was at least one grant vote). Like the
+ <code class="literal">ConsensusBased</code> implementation, there is a parameter that controls
+ the behavior if all voters abstain. The <code class="literal">UnanimousBased</code> provider
+ expects unanimous <code class="literal">ACCESS_GRANTED</code> votes in order to grant access,
+ ignoring abstains. It will deny access if there is any
+ <code class="literal">ACCESS_DENIED</code> vote. Like the other implementations, there is a
+ parameter that controls the behaviour if all voters abstain.</p><p>It is possible to implement a custom
+ <code class="interfacename">AccessDecisionManager</code> that tallies votes differently.
+ For example, votes from a particular
+ <code class="interfacename">AccessDecisionVoter</code> might receive additional
+ weighting, whilst a deny vote from a particular voter may have a veto effect.</p><div class="section" title="RoleVoter"><div class="titlepage"><div><div><h4 class="title"><a name="authz-role-voter"></a><code class="classname">RoleVoter</code></h4></div></div></div><p> The most commonly used <code class="interfacename">AccessDecisionVoter</code>
+ provided with Spring Security is the simple <code class="classname">RoleVoter</code>,
+ which treats configuration attributes as simple role names and votes to grant
+ access if the user has been assigned that role.</p><p>It will vote if any <code class="interfacename">ConfigAttribute</code> begins with
+ the prefix <code class="literal">ROLE_</code>. It will vote to grant access if there is a
+ <code class="interfacename">GrantedAuthority</code> which returns a
+ <code class="literal">String</code> representation (via the
+ <code class="literal">getAuthority()</code> method) exactly equal to one or more
+ <code class="literal">ConfigAttributes</code> starting with the prefix
+ <code class="literal">ROLE_</code>. If there is no exact match of any
+ <code class="literal">ConfigAttribute</code> starting with <code class="literal">ROLE_</code>, the
+ <code class="literal">RoleVoter</code> will vote to deny access. If no
+ <code class="literal">ConfigAttribute</code> begins with <code class="literal">ROLE_</code>, the
+ voter will abstain.</p></div><div class="section" title="AuthenticatedVoter"><div class="titlepage"><div><div><h4 class="title"><a name="authz-authenticated-voter"></a><code class="classname">AuthenticatedVoter</code></h4></div></div></div><p> Another voter which we've implicitly seen is the
+ <code class="classname">AuthenticatedVoter</code>, which can be used to differentiate
+ between anonymous, fully-authenticated and remember-me authenticated users. Many
+ sites allow certain limited access under remember-me authentication, but require
+ a user to confirm their identity by logging in for full access.</p><p>When we've used the attribute <code class="literal">IS_AUTHENTICATED_ANONYMOUSLY</code>
+ to grant anonymous access, this attribute was being processed by the
+ <code class="classname">AuthenticatedVoter</code>. See the Javadoc for this class for
+ more information. </p></div><div class="section" title="Custom Voters"><div class="titlepage"><div><div><h4 class="title"><a name="authz-custom-voter"></a>Custom Voters</h4></div></div></div><p>Obviously, you can also implement a custom
+ <code class="interfacename">AccessDecisionVoter</code> and you can
+ put just about any access-control logic you want in it. It might
+ be specific to your application (business-logic related) or it
+ might implement some security administration logic. For example, you'll find
+ a <a class="link" href="http://blog.springsource.com/2009/01/02/spring-security-customization-part-2-adjusting-secured-session-in-real-time/" target="_top">
+ blog article</a> on the SpringSource web site which describes how to
+ use a voter to deny access in real-time to users whose accounts have
+ been suspended.
+ </p></div></div></div><div class="section" title="14.3 After Invocation Handling"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="authz-after-invocation-handling"></a>14.3 After Invocation Handling</h2></div></div></div><p>Whilst the <code class="interfacename">AccessDecisionManager</code> is called by the
+ <code class="classname">AbstractSecurityInterceptor</code> before proceeding with the secure
+ object invocation, some applications need a way of modifying the object actually
+ returned by the secure object invocation. Whilst you could easily implement your own AOP
+ concern to achieve this, Spring Security provides a convenient hook that has several
+ concrete implementations that integrate with its ACL capabilities.</p><p><a class="xref" href="authz-arch.html#authz-after-invocation" title="Figure 14.2. After Invocation Implementation">Figure 14.2, “After Invocation Implementation”</a> illustrates Spring Security's
+ <code class="literal">AfterInvocationManager</code> and its concrete implementations. </p><div class="figure"><a name="authz-after-invocation"></a><p class="title"><b>Figure 14.2. After Invocation Implementation</b></p><div class="figure-contents"><div class="mediaobject" align="center"><img src="images/after-invocation.png" align="middle" alt="After Invocation Implementation"></div></div></div><p><br class="figure-break"></p><p>Like many other parts of Spring Security, <code class="literal">AfterInvocationManager</code>
+ has a single concrete implementation, <code class="literal">AfterInvocationProviderManager</code>,
+ which polls a list of <code class="literal">AfterInvocationProvider</code>s. Each
+ <code class="literal">AfterInvocationProvider</code> is allowed to modify the return object or
+ throw an <code class="literal">AccessDeniedException</code>. Indeed multiple providers can modify
+ the object, as the result of the previous provider is passed to the next in the
+ list.</p><p>Please be aware that if you're using <code class="literal">AfterInvocationManager</code>, you
+ will still need configuration attributes that allow the
+ <code class="classname">MethodSecurityInterceptor</code>'s
+ <code class="interfacename">AccessDecisionManager</code> to allow an operation. If you're
+ using the typical Spring Security included
+ <code class="interfacename">AccessDecisionManager</code> implementations, having no
+ configuration attributes defined for a particular secure method invocation will cause
+ each <code class="interfacename">AccessDecisionVoter</code> to abstain from voting. In turn,
+ if the <code class="interfacename">AccessDecisionManager</code> property
+ "<code class="literal">allowIfAllAbstainDecisions</code>" is <code class="literal">false</code>, an
+ <code class="literal">AccessDeniedException</code> will be thrown. You may avoid this potential
+ issue by either (i) setting "<code class="literal">allowIfAllAbstainDecisions</code>" to
+ <code class="literal">true</code> (although this is generally not recommended) or (ii) simply
+ ensure that there is at least one configuration attribute that an
+ <code class="interfacename">AccessDecisionVoter</code> will vote to grant access for. This
+ latter (recommended) approach is usually achieved through a <code class="literal">ROLE_USER</code>
+ or <code class="literal">ROLE_AUTHENTICATED</code> configuration attribute.</p></div><div class="section" title="14.4 Hierarchical Roles"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="authz-hierarchical-roles"></a>14.4 Hierarchical Roles</h2></div></div></div><p>
+ It is a common requirement that a particular role in an application should automatically
+ <span class="quote">“<span class="quote">include</span>”</span> other roles. For example, in an application which has the concept of
+ an <span class="quote">“<span class="quote">admin</span>”</span> and a <span class="quote">“<span class="quote">user</span>”</span> role, you may want an admin to be able to
+ do everything a normal user can. To achieve this, you can either make sure that all admin users
+ are also assigned the <span class="quote">“<span class="quote">user</span>”</span> role. Alternatively, you can modify every access constraint
+ which requires the <span class="quote">“<span class="quote">user</span>”</span> role to also include the <span class="quote">“<span class="quote">admin</span>”</span> role.
+ This can get quite complicated if you have a lot of different roles in your application.
+ </p><p>
+ The use of a role-hierarchy allows you to configure which roles (or authorities) should include others.
+ An extended version of Spring Security's <a class="link" href="authz-arch.html#authz-role-voter" title="RoleVoter"><code class="classname">RoleVoter</code></a>,
+ <code class="classname">RoleHierarchyVoter</code>, is configured with a <code class="interfacename">RoleHierarchy</code>,
+ from which it obtains all the <span class="quote">“<span class="quote">reachable authorities</span>”</span> which the user is assigned.
+ A typical configuration might look like this:
+</p><pre class="programlisting">
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"roleVoter"</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.access.vote.RoleHierarchyVoter"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"roleHierarchy"</span><span class="hl-tag"> /></span>
+<span class="hl-tag"></class></span>
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"roleHierarchy"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"hierarchy"</span><span class="hl-tag">></span>
+ ROLE_ADMIN > ROLE_STAFF
+ ROLE_STAFF > ROLE_USER
+ ROLE_USER > ROLE_GUEST
+ <span class="hl-tag"></property></span>
+<span class="hl-tag"></bean></span>
+</pre><p>
+ Here we have four roles in a hierarchy <code class="literal">ROLE_ADMIN => ROLE_STAFF => ROLE_USER => ROLE_GUEST</code>.
+ A user who is authenticated with <code class="literal">ROLE_ADMIN</code>, will behave as if they have all four roles when
+ security contraints are evaluated against an <code class="interfacename">AccessDecisionManager</code> cconfigured
+ with the above <code class="classname">RoleHierarchyVoter</code>. The <code class="literal">></code> symbol can be thought of
+ as meaning <span class="quote">“<span class="quote">includes</span>”</span>.
+ </p><p>
+ Role hierarchies offer a convenient means of simplifying the access-control configuration data for your
+ application and/or reducing the number of authorities which you need to assign to a user. For more
+ complex requirements you may wish to define a logical mapping between the specific access-rights your
+ application requires and the roles that are assigned to users, translating between the two when loading
+ the user information.
+
+ </p></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
- </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="authorization.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="authorization.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="secure-object-impls.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Part IV. Authorization </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 14. Secure Object Implementations</td></tr></table></div></body></html>
\ No newline at end of file
+ </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="authorization.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="authorization.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="secure-object-impls.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Part IV. Authorization </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 15. Secure Object Implementations</td></tr></table></div></body></html>
\ No newline at end of file
diff --git a/docs/reference/basic.html b/docs/reference/basic.html
index 7f8edd9..b646c0e 100644
--- a/docs/reference/basic.html
+++ b/docs/reference/basic.html
@@ -1,6 +1,6 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>9. Basic and Digest Authentication</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="web-app-security.html" title="Part III. Web Application Security"><link rel="prev" href="core-web-filters.html" title="8. Core Security Filters"><link rel="next" href="remember-me.html" title="10. Remember-Me Authentication"><!--Begin Google Analytics code--><script type="text/javascript">
+ <title>10. Basic and Digest Authentication</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="web-app-security.html" title="Part III. Web Application Security"><link rel="prev" href="core-web-filters.html" title="9. Core Security Filters"><link rel="next" href="remember-me.html" title="11. Remember-Me Authentication"><!--Begin Google Analytics code--><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
@@ -8,25 +8,24 @@
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
- </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">9. Basic and Digest Authentication</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="core-web-filters.html">Prev</a> </td><th width="60%" align="center">Part III. Web Application Security</th><td width="20%" align="right"> <a accesskey="n" href="remember-me.html">Next</a></td></tr></table><hr></div><div class="chapter" title="9. Basic and Digest Authentication"><div class="titlepage"><div><div><h1 class="title"><a name="basic"></a>Basic and Digest Authentication</h1></div></div></div><p>Basic and digest authentiation are alternative authentication mechanisms which are popular
+ </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">10. Basic and Digest Authentication</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="core-web-filters.html">Prev</a> </td><th width="60%" align="center">Part III. Web Application Security</th><td width="20%" align="right"> <a accesskey="n" href="remember-me.html">Next</a></td></tr></table><hr></div><div class="chapter" title="10. Basic and Digest Authentication"><div class="titlepage"><div><div><h1 class="title"><a name="basic"></a>Basic and Digest Authentication</h1></div></div></div><p>Basic and digest authentiation are alternative authentication mechanisms which are popular
in web applications. Basic authentication is often used with stateless clients which pass
their credentials on each request. It's quite common to use it in combination with
form-based authentication where an application is used through both a browser-based user
interface and as a web-service. However, basic authentication transmits the password as
plain text so it should only really be used over an encrypted transport layer such as
- HTTPS.</p><div class="section" title="9.1 BasicAuthenticationFilter"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="basic-processing-filter"></a>9.1 <code class="classname">BasicAuthenticationFilter</code></h2></div></div></div><p><code class="literal">BasicAuthenticationFilter</code> is responsible for processing basic
+ HTTPS.</p><div class="section" title="10.1 BasicAuthenticationFilter"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="basic-processing-filter"></a>10.1 <code class="classname">BasicAuthenticationFilter</code></h2></div></div></div><p><code class="literal">BasicAuthenticationFilter</code> is responsible for processing basic
authentication credentials presented in HTTP headers. This can be used for
authenticating calls made by Spring remoting protocols (such as Hessian and Burlap), as
well as normal browser user agents (such as Firefox and Internet Explorer). The standard
governing HTTP Basic Authentication is defined by RFC 1945, Section 11, and
- <code class="literal">BasicAuthenticationFilter</code> conforms with this RFC. Basic
+ <code class="literal">BasicAuthenticationFilter</code> conforms with this RFC. Basic
Authentication is an attractive approach to authentication, because it is very widely
deployed in user agents and implementation is extremely simple (it's just a Base64
- encoding of the username:password, specified in an HTTP header).</p><div class="section" title="9.1.1 Configuration"><div class="titlepage"><div><div><h3 class="title"><a name="basic-config"></a>9.1.1 Configuration</h3></div></div></div><p>To implement HTTP Basic Authentication, you need to add a
- <code class="literal">BasicAuthenticationFilter</code> to your filter chain. The
- application context should contain <code class="literal">BasicAuthenticationFilter</code> and
- its required collaborator:</p><p>
- </p><pre class="programlisting">
+ encoding of the username:password, specified in an HTTP header).</p><div class="section" title="10.1.1 Configuration"><div class="titlepage"><div><div><h3 class="title"><a name="basic-config"></a>10.1.1 Configuration</h3></div></div></div><p>To implement HTTP Basic Authentication, you need to add a
+ <code class="literal">BasicAuthenticationFilter</code> to your filter chain. The application
+ context should contain <code class="literal">BasicAuthenticationFilter</code> and its required
+ collaborator:</p><p> </p><pre class="programlisting">
<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"basicAuthenticationFilter"</span>
<span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.authentication.www.BasicAuthenticationFilter"</span><span class="hl-tag">></span>
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"authenticationManager"</span><span class="hl-tag">/></span>
@@ -37,19 +36,18 @@
<span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint"</span><span class="hl-tag">></span>
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"realmName"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"Name Of Your Realm"</span><span class="hl-tag">/></span>
<span class="hl-tag"></bean></span>
- </pre><p>
- </p><p>The configured <code class="interfacename">AuthenticationManager</code> processes each
+ </pre><p> </p><p>The configured <code class="interfacename">AuthenticationManager</code> processes each
authentication request. If authentication fails, the configured
- <code class="interfacename">AuthenticationEntryPoint</code> will be used to retry
- the authentication process. Usually you will use the filter in combination with a
- <code class="literal">BasicAuthenticationEntryPoint</code>, which returns a 401 response
- with a suitable header to retry HTTP Basic authentication. If authentication is
+ <code class="interfacename">AuthenticationEntryPoint</code> will be used to retry the
+ authentication process. Usually you will use the filter in combination with a
+ <code class="literal">BasicAuthenticationEntryPoint</code>, which returns a 401 response with
+ a suitable header to retry HTTP Basic authentication. If authentication is
successful, the resulting <code class="interfacename">Authentication</code> object will
be placed into the <code class="classname">SecurityContextHolder</code> as usual.</p><p>If the authentication event was successful, or authentication was not attempted
because the HTTP header did not contain a supported authentication request, the
filter chain will continue as normal. The only time the filter chain will be
interrupted is if authentication fails and the
- <code class="interfacename">AuthenticationEntryPoint</code> is called.</p></div></div><div class="section" title="9.2 DigestAuthenticationFilter"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="digest-processing-filter"></a>9.2 <code class="classname">DigestAuthenticationFilter</code></h2></div></div></div><p><code class="classname">DigestAuthenticationFilter</code> is capable of processing digest
+ <code class="interfacename">AuthenticationEntryPoint</code> is called.</p></div></div><div class="section" title="10.2 DigestAuthenticationFilter"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="digest-processing-filter"></a>10.2 <code class="classname">DigestAuthenticationFilter</code></h2></div></div></div><p><code class="classname">DigestAuthenticationFilter</code> is capable of processing digest
authentication credentials presented in HTTP headers. Digest Authentication attempts to
solve many of the weaknesses of Basic authentication, specifically by ensuring
credentials are never sent in clear text across the wire. Many user agents support
@@ -58,7 +56,7 @@
the Digest Authentication standard prescribed by RFC 2069. Most user agents implement
RFC 2617. Spring Security's <code class="classname">DigestAuthenticationFilter</code> is
compatible with the "<code class="literal">auth</code>" quality of protection
- (<code class="literal">qop</code>) prescribed by RFC 2617, which also provides backward
+ (<code class="literal">qop</code>) prescribed by RFC 2617, which also provides backward
compatibility with RFC 2069. Digest Authentication is a more attractive option if you
need to use unencrypted HTTP (i.e. no TLS/HTTPS) and wish to maximise security of the
authentication process. Indeed Digest Authentication is a mandatory requirement for the
@@ -68,14 +66,13 @@
a "nonce". This is a value the server generates. Spring Security's nonce adopts the
following format:</p><p>
</p><pre class="programlisting">
- base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key))
+ base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key))
- expirationTime: The date and time when the nonce expires, expressed in milliseconds
- key: A private key to prevent modification of the nonce token
- </pre><p>
- </p><p>The <code class="classname">DigestAuthenticatonEntryPoint</code> has a property specifying the
- <code class="literal">key</code> used for generating the nonce tokens, along with a
- <code class="literal">nonceValiditySeconds</code> property for determining the expiration time
+ expirationTime: The date and time when the nonce expires, expressed in milliseconds
+ key: A private key to prevent modification of the nonce token
+ </pre><p> </p><p>The <code class="classname">DigestAuthenticatonEntryPoint</code> has a property specifying the
+ <code class="literal">key</code> used for generating the nonce tokens, along with a
+ <code class="literal">nonceValiditySeconds</code> property for determining the expiration time
(default 300, which equals five minutes). Whist ever the nonce is valid, the digest is
computed by concatenating various strings including the username, password, nonce, URI
being requested, a client-generated nonce (merely a random value which the user agent
@@ -84,51 +81,48 @@
if they disagree on an included value (eg password). In Spring Security implementation,
if the server-generated nonce has merely expired (but the digest was otherwise valid),
the <code class="classname">DigestAuthenticationEntryPoint</code> will send a
- <code class="literal">"stale=true"</code> header. This tells the user agent there is no need
- to disturb the user (as the password and username etc is correct), but simply to try
- again using a new nonce.</p><p>An appropriate value for <code class="classname">DigestAuthenticationEntryPoint</code>'s
- <code class="literal">nonceValiditySeconds</code> parameter will depend on your application.
+ <code class="literal">"stale=true"</code> header. This tells the user agent there is no need to
+ disturb the user (as the password and username etc is correct), but simply to try again
+ using a new nonce.</p><p>An appropriate value for <code class="classname">DigestAuthenticationEntryPoint</code>'s
+ <code class="literal">nonceValiditySeconds</code> parameter will depend on your application.
Extremely secure applications should note that an intercepted authentication header can
be used to impersonate the principal until the <code class="literal">expirationTime</code>
contained in the nonce is reached. This is the key principle when selecting an
appropriate setting, but it would be unusual for immensely secure applications to not be
running over TLS/HTTPS in the first instance.</p><p>Because of the more complex implementation of Digest Authentication, there are often
user agent issues. For example, Internet Explorer fails to present an
- "<code class="literal">opaque</code>" token on subsequent requests in the same session. Spring
+ "<code class="literal">opaque</code>" token on subsequent requests in the same session. Spring
Security filters therefore encapsulate all state information into the
- "<code class="literal">nonce</code>" token instead. In our testing, Spring Security's
+ "<code class="literal">nonce</code>" token instead. In our testing, Spring Security's
implementation works reliably with FireFox and Internet Explorer, correctly handling
- nonce timeouts etc.</p><div class="section" title="9.2.1 Configuration"><div class="titlepage"><div><div><h3 class="title"><a name="digest-config"></a>9.2.1 Configuration</h3></div></div></div><p>Now that we've reviewed the theory, let's see how to use it. To implement HTTP
+ nonce timeouts etc.</p><div class="section" title="10.2.1 Configuration"><div class="titlepage"><div><div><h3 class="title"><a name="digest-config"></a>10.2.1 Configuration</h3></div></div></div><p>Now that we've reviewed the theory, let's see how to use it. To implement HTTP
Digest Authentication, it is necessary to define
- <code class="literal">DigestAuthenticationFilter</code> in the filter chain. The
- application context will need to define the
- <code class="literal">DigestAuthenticationFilter</code> and its required
- collaborators:</p><p>
- </p><pre class="programlisting">
-<bean id="digestFilter" class=
- "org.springframework.security.web.authentication.www.DigestAuthenticationFilter">
- <property name="userDetailsService" ref="jdbcDaoImpl"/>
- <property name="authenticationEntryPoint" ref="digestEntryPoint"/>
- <property name="userCache" ref="userCache"/>
-</bean>
+ <code class="literal">DigestAuthenticationFilter</code> in the filter chain. The application
+ context will need to define the <code class="literal">DigestAuthenticationFilter</code> and
+ its required collaborators:</p><p> </p><pre class="programlisting">
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"digestFilter"</span> <span class="hl-attribute">class</span>=
+ <span class="hl-value">"org.springframework.security.web.authentication.www.DigestAuthenticationFilter"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"userDetailsService"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"jdbcDaoImpl"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationEntryPoint"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"digestEntryPoint"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"userCache"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"userCache"</span><span class="hl-tag">/></span>
+<span class="hl-tag"></bean></span>
-<bean id="digestEntryPoint" class=
- "org.springframework.security.web.authentication.www.DigestAuthenticationEntryPoint">
- <property name="realmName" value="Contacts Realm via Digest Authentication"/>
- <property name="key" value="acegi"/>
- <property name="nonceValiditySeconds" value="10"/>
-</bean>
- </pre><p>
- </p><p>The configured <code class="interfacename">UserDetailsService</code> is needed because
- <code class="literal">DigestAuthenticationFilter</code> must have direct access to the
- clear text password of a user. Digest Authentication will NOT work if you are using
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"digestEntryPoint"</span> <span class="hl-attribute">class</span>=
+ <span class="hl-value">"org.springframework.security.web.authentication.www.DigestAuthenticationEntryPoint"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"realmName"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"Contacts Realm via Digest Authentication"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"key"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"acegi"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"nonceValiditySeconds"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"10"</span><span class="hl-tag">/></span>
+<span class="hl-tag"></bean></span>
+ </pre><p> </p><p>The configured <code class="interfacename">UserDetailsService</code> is needed because
+ <code class="literal">DigestAuthenticationFilter</code> must have direct access to the clear
+ text password of a user. Digest Authentication will NOT work if you are using
encoded passwords in your DAO. The DAO collaborator, along with the
- <code class="literal">UserCache</code>, are typically shared directly with a
- <code class="classname">DaoAuthenticationProvider</code>. The
- <code class="literal">authenticationEntryPoint</code> property must be
- <code class="classname">DigestAuthenticationEntryPoint</code>, so that
- <code class="classname">DigestAuthenticationFilter</code> can obtain the correct
- <code class="literal">realmName</code> and <code class="literal">key</code> for digest
+ <code class="literal">UserCache</code>, are typically shared directly with a
+ <code class="classname">DaoAuthenticationProvider</code>. The
+ <code class="literal">authenticationEntryPoint</code> property must be
+ <code class="classname">DigestAuthenticationEntryPoint</code>, so that
+ <code class="classname">DigestAuthenticationFilter</code> can obtain the correct
+ <code class="literal">realmName</code> and <code class="literal">key</code> for digest
calculations.</p><p>Like <code class="literal">BasicAuthenticationFilter</code>, if authentication is successful
an <code class="interfacename">Authentication</code> request token will be placed into
the <code class="classname">SecurityContextHolder</code>. If the authentication event was
@@ -145,4 +139,4 @@
Security's implementation does comply with the minimum standards of this RFC.</p></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
- </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="core-web-filters.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="web-app-security.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="remember-me.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">8. Core Security Filters </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 10. Remember-Me Authentication</td></tr></table></div></body></html>
\ No newline at end of file
+ </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="core-web-filters.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="web-app-security.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="remember-me.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">9. Core Security Filters </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 11. Remember-Me Authentication</td></tr></table></div></body></html>
\ No newline at end of file
diff --git a/docs/reference/cas.html b/docs/reference/cas.html
index 2112401..4e41d61 100644
--- a/docs/reference/cas.html
+++ b/docs/reference/cas.html
@@ -1,6 +1,6 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>21. CAS Authentication</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="advanced-topics.html" title="Part V. Additional Topics"><link rel="prev" href="jaas.html" title="20. Java Authentication and Authorization Service (JAAS) Provider"><link rel="next" href="x509.html" title="22. X.509 Authentication"><!--Begin Google Analytics code--><script type="text/javascript">
+ <title>22. CAS Authentication</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="advanced-topics.html" title="Part V. Additional Topics"><link rel="prev" href="jaas.html" title="21. Java Authentication and Authorization Service (JAAS) Provider"><link rel="next" href="x509.html" title="23. X.509 Authentication"><!--Begin Google Analytics code--><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
@@ -8,18 +8,18 @@
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
- </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">21. CAS Authentication</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="jaas.html">Prev</a> </td><th width="60%" align="center">Part V. Additional Topics</th><td width="20%" align="right"> <a accesskey="n" href="x509.html">Next</a></td></tr></table><hr></div><div class="chapter" title="21. CAS Authentication"><div class="titlepage"><div><div><h2 class="title"><a name="cas"></a>21. CAS Authentication</h2></div></div></div><div class="section" title="21.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="cas-overview"></a>21.1 Overview</h2></div></div></div><p>JA-SIG produces an enterprise-wide single sign on system known as CAS. Unlike other
- initiatives, JA-SIG's Central Authentication Service is open source, widely used, simple to
- understand, platform independent, and supports proxy capabilities. Spring Security fully
- supports CAS, and provides an easy migration path from single-application deployments of
- Spring Security through to multiple-application deployments secured by an enterprise-wide CAS
- server.</p><p>You can learn more about CAS at <code class="literal">http://www.ja-sig.org/cas</code>. You will
- also need to visit this site to download the CAS Server files.</p></div><div class="section" title="21.2 How CAS Works"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="cas-how-it-works"></a>21.2 How CAS Works</h2></div></div></div><p>Whilst the CAS web site contains documents that detail the architecture of CAS, we present
- the general overview again here within the context of Spring Security. Spring Security 3.0
- supports CAS 3. At the time of writing, the CAS server was at version 3.3.</p><p>Somewhere in your enterprise you will need to setup a CAS server. The CAS server is simply
- a standard WAR file, so there isn't anything difficult about setting up your server. Inside
- the WAR file you will customise the login and other single sign on pages displayed to
- users.</p><p>When deploying a CAS 3.3 server, you will also need to specify an
+ </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">22. CAS Authentication</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="jaas.html">Prev</a> </td><th width="60%" align="center">Part V. Additional Topics</th><td width="20%" align="right"> <a accesskey="n" href="x509.html">Next</a></td></tr></table><hr></div><div class="chapter" title="22. CAS Authentication"><div class="titlepage"><div><div><h2 class="title"><a name="cas"></a>22. CAS Authentication</h2></div></div></div><div class="section" title="22.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="cas-overview"></a>22.1 Overview</h2></div></div></div><p>JA-SIG produces an enterprise-wide single sign on system known as CAS. Unlike other
+ initiatives, JA-SIG's Central Authentication Service is open source, widely used, simple
+ to understand, platform independent, and supports proxy capabilities. Spring Security
+ fully supports CAS, and provides an easy migration path from single-application
+ deployments of Spring Security through to multiple-application deployments secured by an
+ enterprise-wide CAS server.</p><p>You can learn more about CAS at <code class="literal">http://www.ja-sig.org/cas</code>. You will
+ also need to visit this site to download the CAS Server files.</p></div><div class="section" title="22.2 How CAS Works"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="cas-how-it-works"></a>22.2 How CAS Works</h2></div></div></div><p>Whilst the CAS web site contains documents that detail the architecture of CAS, we
+ present the general overview again here within the context of Spring Security. Spring Security
+ 3.x supports CAS 3. At the time of writing, the CAS server was at version 3.4.</p><p>Somewhere in your enterprise you will need to setup a CAS server. The CAS server is
+ simply a standard WAR file, so there isn't anything difficult about setting up your
+ server. Inside the WAR file you will customise the login and other single sign on pages
+ displayed to users.</p><p>When deploying a CAS 3.4 server, you will also need to specify an
<code class="literal">AuthenticationHandler</code> in the
<code class="filename">deployerConfigContext.xml</code> included with CAS. The
<code class="literal">AuthenticationHandler</code> has a simple method that returns a boolean as to
@@ -30,78 +30,388 @@
download and deploy the server war file, it is set up to successfully authenticate users who
enter a password matching their username, which is useful for testing.</p><p>Apart from the CAS server itself, the other key players are of course the secure web
applications deployed throughout your enterprise. These web applications are known as
- "services". There are two types of services: standard services and proxy services. A proxy
- service is able to request resources from other services on behalf of the user. This will be
- explained more fully later.</p></div><div class="section" title="21.3 Configuration of CAS Client"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="cas-client"></a>21.3 Configuration of CAS Client</h2></div></div></div><p>The web application side of CAS is made easy due to Spring Security. It is assumed you
- already know the basics of using Spring Security, so these are not covered again below. We'll
- assume a namespace based configuration is being used and add in the CAS beans as required. </p><p>You will need to add a <code class="classname">ServiceProperties</code> bean to your application
- context. This represents your CAS service:</p><p>
- </p><pre class="programlisting">
- <bean id="serviceProperties"
- class="org.springframework.security.cas.ServiceProperties">
- <property name="service"
- value="https://localhost:8443/cas-sample/j_spring_cas_security_check"/>
- <property name="sendRenew" value="false"/>
- </bean>
- </pre><p>
- </p><p>The <code class="literal">service</code> must equal a URL that will be monitored by the
- <code class="literal">CasAuthenticationFilter</code>. The <code class="literal">sendRenew</code> defaults to
- false, but should be set to true if your application is particularly sensitive. What this
- parameter does is tell the CAS login service that a single sign on login is unacceptable.
- Instead, the user will need to re-enter their username and password in order to gain access to
- the service.</p><p>The following beans should be configured to commence the CAS authentication process
- (assuming you're using a namespace configuration):</p><p>
- </p><pre class="programlisting">
-<security:http entry-point-ref="casEntryPoint">
+ "services". There are three types of services. Those that authenticate service tickets, those that
+ can obtain proxy tickets, and those that authenticate proxy tickets. Authenticating a proxy ticket
+ differs because the list of proxies must be validated and often times a proxy ticket can be reused.</p><div class="section" title="22.2.1 Spring Security and CAS Interaction Sequence"><div class="titlepage"><div><div><h3 class="title"><a name="cas-sequence"></a>22.2.1 Spring Security and CAS Interaction Sequence</h3></div></div></div><p>The basic interaction between a web browser, CAS server and a
+ Spring Security-secured service is as follows:</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>The web user is browsing the service's public pages. CAS or
+ Spring Security is not involved.</p></li><li class="listitem"><p>The user eventually requests a page that is either secure or
+ one of the beans it uses is secure. Spring Security's
+ <code class="classname">ExceptionTranslationFilter</code> will detect the
+ <code class="classname">AccessDeniedException</code> or <code class="classname">AuthenticationException</code>.</p></li><li class="listitem"><p>Because the user's <code class="interfacename">Authentication</code> object (or lack
+ thereof) caused an <code class="classname">AuthenticationException</code>, the
+ <code class="classname">ExceptionTranslationFilter</code> will call the configured
+ <code class="interfacename">AuthenticationEntryPoint</code>. If using CAS, this will be
+ the <code class="classname">CasAuthenticationEntryPoint</code> class.</p></li><li class="listitem"><p>The <code class="classname">CasAuthenticationEntryPoint</code> will redirect the user's browser
+ to the CAS server. It will also indicate a <code class="literal">service</code> parameter, which
+ is the callback URL for the Spring Security service (your application). For example, the
+ URL to which the browser is redirected might be
+ <code class="literal">https://my.company.com/cas/login?service=https%3A%2F%2Fserver3.company.com%2Fwebapp%2Fj_spring_cas_security_check</code>.</p></li><li class="listitem"><p>After the user's browser redirects to CAS, they will be
+ prompted for their username and password. If the user presents a
+ session cookie which indicates they've previously logged on, they
+ will not be prompted to login again (there is an exception to this
+ procedure, which we'll cover later). CAS will use the
+ <code class="interfacename">PasswordHandler</code> (or
+ <code class="interfacename">AuthenticationHandler</code> if using CAS 3.0)
+ discussed above to decide whether the username and password is
+ valid.</p></li><li class="listitem"><p>Upon successful login, CAS will redirect the user's browser
+ back to the original service. It will also include a
+ <code class="literal">ticket</code> parameter, which is an opaque string
+ representing the "service ticket". Continuing our earlier example,
+ the URL the browser is redirected to might be
+ <code class="literal">https://server3.company.com/webapp/j_spring_cas_security_check?ticket=ST-0-ER94xMJmn6pha35CQRoZ</code>.</p></li><li class="listitem"><p>Back in the service web application, the <code class="classname">CasAuthenticationFilter</code> is
+ always listening for requests to <code class="literal">/j_spring_cas_security_check</code> (this
+ is configurable, but we'll use the defaults in this introduction). The processing filter
+ will construct a <code class="classname">UsernamePasswordAuthenticationToken</code> representing the
+ service ticket. The principal will be equal to
+ <code class="literal">CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER</code>, whilst the credentials
+ will be the service ticket opaque value. This authentication request will then be handed
+ to the configured <code class="interfacename">AuthenticationManager</code>.</p></li><li class="listitem"><p>The <code class="interfacename">AuthenticationManager</code> implementation
+ will be the <code class="classname">ProviderManager</code>, which is in turn
+ configured with the <code class="classname">CasAuthenticationProvider</code>.
+ The <code class="classname">CasAuthenticationProvider</code> only responds to
+ <code class="classname">UsernamePasswordAuthenticationToken</code>s containing
+ the CAS-specific principal (such as
+ <code class="literal">CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER</code>)
+ and <code class="classname">CasAuthenticationToken</code>s (discussed
+ later).</p></li><li class="listitem"><p><code class="classname">CasAuthenticationProvider</code> will validate the service ticket using a
+ <code class="interfacename">TicketValidator</code> implementation. This will typically be a
+ <code class="classname">Cas20ServiceTicketValidator</code> which is one of the classes
+ included in the CAS client library. In the event the application needs to validate proxy tickets, the
+ <code class="classname">Cas20ProxyTicketValidator</code> is used. The
+ <code class="interfacename">TicketValidator</code> makes an HTTPS request to the CAS server in order to
+ validate the service ticket. It may also include a proxy callback URL, which is included in this example:
+ <code class="literal">https://my.company.com/cas/proxyValidate?service=https%3A%2F%2Fserver3.company.com%2Fwebapp%2Fj_spring_cas_security_check&ticket=ST-0-ER94xMJmn6pha35CQRoZ&pgtUrl=https://server3.company.com/webapp/j_spring_cas_security_proxyreceptor</code>.
+ </p></li><li class="listitem"><p>Back on the CAS server, the validation request will be
+ received. If the presented service ticket matches the service URL
+ the ticket was issued to, CAS will provide an affirmative response
+ in XML indicating the username. If any proxy was involved in the
+ authentication (discussed below), the list of proxies is also
+ included in the XML response.</p></li><li class="listitem"><p>[OPTIONAL] If the request to the CAS validation service included the proxy callback
+ URL (in the <code class="literal">pgtUrl</code> parameter), CAS will include a
+ <code class="literal">pgtIou</code> string in the XML response. This <code class="literal">pgtIou</code>
+ represents a proxy-granting ticket IOU. The CAS server will then create its own HTTPS
+ connection back to the <code class="literal">pgtUrl</code>. This is to mutually authenticate the
+ CAS server and the claimed service URL. The HTTPS connection will be used to send a
+ proxy granting ticket to the original web application. For example,
+ <code class="literal">https://server3.company.com/webapp/j_spring_cas_security_proxyreceptor?pgtIou=PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt&pgtId=PGT-1-si9YkkHLrtACBo64rmsi3v2nf7cpCResXg5MpESZFArbaZiOKH</code>.</p></li><li class="listitem"><p>The <code class="classname">Cas20TicketValidator</code> will parse the XML received from the
+ CAS server. It will return to the <code class="classname">CasAuthenticationProvider</code> a
+ <code class="literal">TicketResponse</code>, which includes the username (mandatory), proxy list
+ (if any were involved), and proxy-granting ticket IOU (if the proxy callback was
+ requested).</p></li><li class="listitem"><p>Next <code class="literal">CasAuthenticationProvider</code> will call
+ a configured <code class="literal">CasProxyDecider</code>. The
+ <code class="literal">CasProxyDecider</code> indicates whether the proxy
+ list in the <code class="literal">TicketResponse</code> is acceptable to the
+ service. Several implementations are provided with Spring
+ Security: <code class="literal">RejectProxyTickets</code>,
+ <code class="literal">AcceptAnyCasProxy</code> and
+ <code class="literal">NamedCasProxyDecider</code>. These names are largely
+ self-explanatory, except <code class="literal">NamedCasProxyDecider</code>
+ which allows a <code class="literal">List</code> of trusted proxies to be
+ provided.</p></li><li class="listitem"><p><code class="classname">CasAuthenticationProvider</code> will next
+ request a <code class="interfacename">AuthenticationUserDetailsService</code> to load the
+ <code class="interfacename">GrantedAuthority</code> objects that apply to the user
+ contained in the <code class="interfacename">Assertion</code>.</p></li><li class="listitem"><p>If there were no problems,
+ <code class="classname">CasAuthenticationProvider</code> constructs a
+ <code class="classname">CasAuthenticationToken</code> including the details
+ contained in the <code class="interfacename">TicketResponse</code> and the
+ <code class="interfacename">GrantedAuthority</code>s.</p></li><li class="listitem"><p>Control then returns to
+ <code class="classname">CasAuthenticationFilter</code>, which places the created
+ <code class="classname">CasAuthenticationToken</code> in the security context.</p></li><li class="listitem"><p>The user's browser is redirected to the original page that
+ caused the <code class="classname">AuthenticationException</code> (or a
+ <a class="link" href="core-web-filters.html#form-login-flow-handling" title="9.4.1 Application Flow on Authentication Success and Failure">custom destination</a> depending on
+ the configuration).</p></li></ol></div><p>It's good that you're still here! Let's now look at how this is configured</p></div></div><div class="section" title="22.3 Configuration of CAS Client"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="cas-client"></a>22.3 Configuration of CAS Client</h2></div></div></div><p>The web application side of CAS is made easy due to Spring Security. It is assumed you
+ already know the basics of using Spring Security, so these are not covered again below.
+ We'll assume a namespace based configuration is being used and add in the CAS beans as
+ required. Each section builds upon the previous section. A full
+ <a class="link" href="sample-apps.html#cas-sample" title="4.5 CAS Sample">CAS sample application</a> can be found in the Spring
+ Security Samples.</p><div class="section" title="22.3.1 Service Ticket Authentication"><div class="titlepage"><div><div><h3 class="title"><a name="cas-st"></a>22.3.1 Service Ticket Authentication</h3></div></div></div><p>This section describes how to setup Spring Security to authenticate Service Tickets. Often times
+ this is all a web application requires. You will need to add a <code class="classname">ServiceProperties</code>
+ bean to your application context. This represents your CAS service:</p><p> </p><pre class="programlisting">
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"serviceProperties"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.cas.ServiceProperties"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"service"</span>
+ <span class="hl-attribute">value</span>=<span class="hl-value">"https://localhost:8443/cas-sample/j_spring_cas_security_check"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"sendRenew"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"false"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></bean></span>
+ </pre><p> </p><p>The <code class="literal">service</code> must equal a URL that will be monitored by the
+ <code class="literal">CasAuthenticationFilter</code>. The <code class="literal">sendRenew</code> defaults to
+ false, but should be set to true if your application is particularly sensitive. What
+ this parameter does is tell the CAS login service that a single sign on login is
+ unacceptable. Instead, the user will need to re-enter their username and password in
+ order to gain access to the service.</p><p>The following beans should be configured to commence the CAS authentication process
+ (assuming you're using a namespace configuration):</p><p> </p><pre class="programlisting">
+ <span class="hl-tag"><security:http</span> <span class="hl-attribute">entry-point-ref</span>=<span class="hl-value">"casEntryPoint"</span><span class="hl-tag">></span>
...
- <custom-filter position="FORM_LOGIN_FILTER" ref="myFilter" />
-</security:http>
+ <span class="hl-tag"><security:custom-filter</span> <span class="hl-attribute">position</span>=<span class="hl-value">"CAS_FILTER"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"casFilter"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"></security:http></span>
-<bean id="casFilter"
- class="org.springframework.security.cas.web.CasAuthenticationFilter">
- <property name="authenticationManager" ref="authenticationManager"/>
-</bean>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"casFilter"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.cas.web.CasAuthenticationFilter"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"authenticationManager"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></bean></span>
-<bean id="casEntryPoint"
- class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
- <property name="loginUrl" value="https://localhost:9443/cas/login"/>
- <property name="serviceProperties" ref="serviceProperties"/>
-</bean>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"casEntryPoint"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.cas.web.CasAuthenticationEntryPoint"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"loginUrl"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"https://localhost:9443/cas/login"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"serviceProperties"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"serviceProperties"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></bean></span>
- </pre><p>
- </p><p> The <code class="classname">CasAuthenticationEntryPoint</code> should be selected to drive
- authentication using <a class="link" href="ns-config.html#ns-entry-point-ref" title="Setting a Custom AuthenticationEntryPoint"><code class="literal">entry-point-ref</code></a>. </p><p>The <code class="classname">CasAuthenticationFilter</code> has very similar properties to the
- <code class="classname">UsernamePasswordAuthenticationFilter</code> (used for form-based logins).
- </p><p>For CAS to operate, the <code class="classname">ExceptionTranslationFilter</code> must have its
- <code class="literal">authenticationEntryPoint</code> property set to the
- <code class="classname">CasAuthenticationEntryPoint</code> bean.</p><p>The <code class="classname">CasAuthenticationEntryPoint</code> must refer to the
- <code class="classname">ServiceProperties</code> bean (discussed above), which provides the URL to the
- enterprise's CAS login server. This is where the user's browser will be redirected.</p><p>Next you need to add a <code class="literal">CasAuthenticationProvider</code> and its collaborators: </p><pre class="programlisting">
- <security:authentication-manager alias="authenticationManager">
- <security:authentication-provider ref="casAuthenticationProvider" />
- </security:authentication-manager>
+ </pre><p> </p><p>For CAS to operate, the <code class="classname">ExceptionTranslationFilter</code> must have
+ its <code class="literal">authenticationEntryPoint</code> property set to the
+ <code class="classname">CasAuthenticationEntryPoint</code> bean. This can easily be done using
+ <a class="link" href="ns-config.html#ns-entry-point-ref" title="Setting a Custom AuthenticationEntryPoint"><code class="literal">entry-point-ref</code></a> as is
+ done in the example above. The <code class="classname">CasAuthenticationEntryPoint</code> must refer to the
+ <code class="classname">ServiceProperties</code> bean (discussed above), which provides the URL
+ to the enterprise's CAS login server. This is where the user's browser will be
+ redirected.</p><p>The <code class="classname">CasAuthenticationFilter</code> has very similar properties to the
+ <code class="classname">UsernamePasswordAuthenticationFilter</code> (used for form-based
+ logins). You can use these properties to customize things like behavior for authentication
+ success and failure.</p><p>Next you need to add a <code class="classname">CasAuthenticationProvider</code> and its
+ collaborators: </p><pre class="programlisting">
+ <span class="hl-tag"><security:authentication-manager</span> <span class="hl-attribute">alias</span>=<span class="hl-value">"authenticationManager"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><security:authentication-provider</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"casAuthenticationProvider"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"></security:authentication-manager></span>
- <bean id="casAuthenticationProvider"
- class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
- <property name="userDetailsService" ref="userService"/>
- <property name="serviceProperties" ref="serviceProperties" />
- <property name="ticketValidator">
- <bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
- <constructor-arg index="0" value="https://localhost:9443/cas" />
- </bean>
- </property>
- <property name="key" value="an_id_for_this_auth_provider_only"/>
- </bean>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"casAuthenticationProvider"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.cas.authentication.CasAuthenticationProvider"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationUserDetailsService"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"userService"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"></bean></span>
+ <span class="hl-tag"></property></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"serviceProperties"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"serviceProperties"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"ticketValidator"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.jasig.cas.client.validation.Cas20ServiceTicketValidator"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">index</span>=<span class="hl-value">"0"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"https://localhost:9443/cas"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"></bean></span>
+ <span class="hl-tag"></property></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"key"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"an_id_for_this_auth_provider_only"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></bean></span>
- <security:user-service id="userService">
- <security:user name="joe" password="joe" authorities="ROLE_USER" />
+ <span class="hl-tag"><security:user-service</span> <span class="hl-attribute">id</span>=<span class="hl-value">"userService"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><security:user</span> <span class="hl-attribute">name</span>=<span class="hl-value">"joe"</span> <span class="hl-attribute">password</span>=<span class="hl-value">"joe"</span> <span class="hl-attribute">authorities</span>=<span class="hl-value">"ROLE_USER"</span><span class="hl-tag"> /></span>
...
- </security:user-service>
- </pre><p> The
- <code class="classname">CasAuthenticationProvider</code> uses a
- <code class="interfacename">UserDetailsService</code> instance to load the authorities for a
- user, once they have been authentiated by CAS. We've shown a simple in-memory setup here. </p><p>The beans are all reasonable self-explanatory if you refer back to the "How CAS Works"
- section.</p></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
+ <span class="hl-tag"></security:user-service></span>
+ </pre><p> The <code class="classname">CasAuthenticationProvider</code> uses a
+ <code class="interfacename">UserDetailsService</code> instance to load the authorities for a
+ user, once they have been authenticated by CAS. We've shown a simple in-memory setup
+ here. Note that the <code class="classname">CasAuthenticationProvider</code> does not actually use
+ the password for authentication, but it does use the authorities.</p><p>The beans are all reasonably self-explanatory if you refer back to the
+ <a class="link" href="cas.html#cas-how-it-works" title="22.2 How CAS Works">How CAS Works</a> section.</p><p>This completes the most basic configuration for CAS. If you haven't made any
+ mistakes, your web application should happily work within the
+ framework of CAS single sign on. No other parts of Spring Security
+ need to be concerned about the fact CAS handled authentication. In the following sections
+ we will discuss some (optional) more advanced configurations.</p></div><div class="section" title="22.3.2 Single Logout"><div class="titlepage"><div><div><h3 class="title"><a name="cas-singlelogout"></a>22.3.2 Single Logout</h3></div></div></div><p>The CAS protocol supports Single Logout and can be easily added to your Spring
+ Security configuration. Below are updates to the Spring Security configuration
+ that handle Single Logout </p><pre class="programlisting">
+ <span class="hl-tag"><security:http</span> <span class="hl-attribute">entry-point-ref</span>=<span class="hl-value">"casEntryPoint"</span><span class="hl-tag">></span>
+ ...
+ <span class="hl-tag"><security:logout</span> <span class="hl-attribute">logout-success-url</span>=<span class="hl-value">"/cas-logout.jsp"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><security:custom-filter</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"requestSingleLogoutFilter"</span> <span class="hl-attribute">before</span>=<span class="hl-value">"LOGOUT_FILTER"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><security:custom-filter</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"singleLogoutFilter"</span> <span class="hl-attribute">before</span>=<span class="hl-value">"CAS_FILTER"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></security:http></span>
+
+ <span class="hl-comment"><!-- This filter handles a Single Logout Request from the CAS Server --></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"singleLogoutFilter"</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.jasig.cas.client.session.SingleSignOutFilter"</span><span class="hl-tag">/></span>
+ <span class="hl-comment"><!-- This filter redirects to the CAS Server to signal Single Logout should be performed --></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"requestSingleLogoutFilter"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.authentication.logout.LogoutFilter"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">value</span>=<span class="hl-value">"https://localhost:9443/cas/logout"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><constructor-arg></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=
+ <span class="hl-value">"org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></constructor-arg></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"filterProcessesUrl"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"/j_spring_cas_security_logout"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></bean></span>
+ </pre><p> The <code class="literal">logout</code> element logs the user out of the local application, but
+ does not terminate the session with the CAS server or any other applications that have been logged
+ into. The <code class="literal">requestSingleLogoutFilter</code> filter will allow the url of
+ <code class="literal">/spring_security_cas_logout</code> to be requested to redirect the application to the
+ configured CAS Server logout url. Then the CAS Server will send a Single Logout request to all the
+ services that were signed into. The <code class="literal">singleLogoutFilter</code> handles the Single Logout
+ request by looking up the <code class="literal">HttpSession</code> in a static <code class="interfacename">Map</code>
+ and then invalidating it.</p><p>It might be confusing why both the <code class="literal">logout</code> element and the
+ <code class="literal">singleLogoutFilter</code> are needed. It is considered best practice to logout locally
+ first since the <code class="literal">SingleSignOutFilter</code> just stores the
+ <code class="interfacename">HttpSession</code> in a static <code class="interfacename">Map</code> in order to
+ call invalidate on it. With the configuration above, the flow of logout would be:
+ </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem">The user requests <code class="literal">/j_spring_security_logout</code> which would log the user
+ out of the local application and send the user to the logout success page.</li><li class="listitem">The logout success page, <code class="literal">/cas-logout.jsp</code>, should instruct the user
+ to click a link pointing to <code class="literal">/j_spring_cas_security_logout</code> in order to logout
+ out of all applications.</li><li class="listitem">When the user clicks the link, the user is redirected to the CAS single logout URL
+ (<code class="literal">https://localhost:9443/cas/logout</code>).</li><li class="listitem">On the CAS Server side, the CAS single logout URL then submits single logout requests to
+ all the CAS Services. On the CAS Service side, JASIG's
+ <code class="classname">SingleSignOutFilter</code> processes the logout request by invaliditing the
+ original session.</li></ol></div><p>
+ </p><p>The next step is to add the following to your web.xml
+ </p><pre class="programlisting">
+ <span class="hl-tag"><filter></span>
+ <span class="hl-tag"><filter-name></span>characterEncodingFilter<span class="hl-tag"></filter-name></span>
+ <span class="hl-tag"><filter-class></span>org.springframework.web.filter.CharacterEncodingFilter<span class="hl-tag"></filter-class></span>
+ <span class="hl-tag"><init-param></span>
+ <span class="hl-tag"><param-name></span>encoding<span class="hl-tag"></param-name></span>
+ <span class="hl-tag"><param-value></span>UTF-8<span class="hl-tag"></param-value></span>
+ <span class="hl-tag"></init-param></span>
+ <span class="hl-tag"></filter></span>
+ <span class="hl-tag"><filter-mapping></span>
+ <span class="hl-tag"><filter-name></span>characterEncodingFilter<span class="hl-tag"></filter-name></span>
+ <span class="hl-tag"><url-pattern></span>/*<span class="hl-tag"></url-pattern></span>
+ <span class="hl-tag"></filter-mapping></span>
+ <span class="hl-tag"><listener></span>
+ <span class="hl-tag"><listener-class></span>org.jasig.cas.client.session.SingleSignOutHttpSessionListener<span class="hl-tag"></listener-class></span>
+ <span class="hl-tag"></listener></span></pre><p>When using the SingleSignOutFilter you might encounter some encoding issues. Therefore it is
+ recommended to add the <code class="classname">CharacterEncodingFilter</code> to ensure that the character
+ encoding is correct when using the <code class="classname">SingleSignOutFilter</code>. Again, refer to JASIG's
+ documentation for details. The <code class="classname">SingleSignOutHttpSessionListener</code> ensures that
+ when an <code class="interfacename">HttpSession</code> expires, the mapping used for single logout is
+ removed.</p></div><div class="section" title="22.3.3 Authenticating to a Stateless Service with CAS"><div class="titlepage"><div><div><h3 class="title"><a name="cas-pt-client"></a>22.3.3 Authenticating to a Stateless Service with CAS</h3></div></div></div><p>This section describes how to authenticate to a service using CAS. In other words,
+ this section discusses how to setup a client that uses a service that authenticates with
+ CAS. The next section describes how to setup a stateless service to Authenticate
+ using CAS.</p><div class="section" title="Configuring CAS to Obtain Proxy Granting Tickets"><div class="titlepage"><div><div><h4 class="title"><a name="cas-pt-client-config"></a>Configuring CAS to Obtain Proxy Granting Tickets</h4></div></div></div><p>In order to authenticate to a stateless service, the application needs to obtain a proxy granting ticket
+ (PGT). This section describes how to configure Spring Security to obtain a PGT building upon then
+ <a class="link" href="cas-st" target="_top">Service Ticket Authentication</a> configuration.</p><p>The first step is to include a <code class="classname">ProxyGrantingTicketStorage</code> in your Spring Security
+ configuration. This is used to store PGT's that are obtained by the
+ <code class="classname">CasAuthenticationFilter</code> so that they can be used to obtain proxy tickets. An example
+ configuration is shown below </p><pre class="programlisting">
+ <span class="hl-comment"><!--
+ NOTE: In a real application you should not use an in memory implementation. You will also want
+ to ensure to clean up expired tickets by calling ProxyGrantingTicketStorage.cleanup()
+ --></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"pgtStorage"</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl"</span><span class="hl-tag">/></span>
+</pre><p>The next step is to update the <code class="classname">CasAuthenticationProvider</code> to be able to obtain proxy
+ tickets. To do this replace the <code class="classname">Cas20ServiceTicketValidator</code> with a
+ <code class="classname">Cas20ProxyTicketValidator</code>. The <code class="literal">proxyCallbackUrl</code> should be set to
+ a URL that the application will receive PGT's at. Last, the configuration should also reference the
+ <code class="classname">ProxyGrantingTicketStorage</code> so it can use a PGT to obtain proxy tickets.
+ You can find an example of the configuration changes that should be made below.
+</p><pre class="programlisting">
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"casAuthenticationProvider"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.cas.authentication.CasAuthenticationProvider"</span><span class="hl-tag">></span>
+ ...
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"ticketValidator"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.jasig.cas.client.validation.Cas20ProxyTicketValidator"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">value</span>=<span class="hl-value">"https://localhost:9443/cas"</span><span class="hl-tag">/></span>
+
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"proxyCallbackUrl"</span>
+ <span class="hl-attribute">value</span>=<span class="hl-value">"https://localhost:8443/cas-sample/j_spring_cas_security_proxyreceptor"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"proxyGrantingTicketStorage"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"pgtStorage"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></bean></span>
+ <span class="hl-tag"></property></span>
+ <span class="hl-tag"></bean></span>
+</pre><p>The last step is to update the <code class="classname">CasAuthenticationFilter</code> to accept PGT and to store them
+ in the <code class="classname">ProxyGrantingTicketStorage</code>. It is important the the <code class="literal">proxyReceptorUrl</code>
+ matches the <code class="literal">proxyCallbackUrl</code> of the <code class="classname">Cas20ProxyTicketValidator</code>. An example
+ configuration is shown below.
+</p><pre class="programlisting">
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"casFilter"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.cas.web.CasAuthenticationFilter"</span><span class="hl-tag">></span>
+ ...
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"proxyGrantingTicketStorage"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"pgtStorage"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"proxyReceptorUrl"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"/j_spring_cas_security_proxyreceptor"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></bean></span>
+</pre></div><div class="section" title="Calling a Stateless Service Using a Proxy Ticket"><div class="titlepage"><div><div><h4 class="title"><a name="cas-pt-client-sample"></a>Calling a Stateless Service Using a Proxy Ticket</h4></div></div></div><p>Now that Spring Security obtains PGTs, you can use them to create proxy tickets which can be used to authenticate
+ to a stateless service. The <a class="link" href="sample-apps.html#cas-sample" title="4.5 CAS Sample">CAS sample application</a> contains a working example in
+ the <code class="classname">ProxyTicketSampleServlet</code>. Example code can be found below:
+</p><pre class="programlisting">
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ // NOTE: The CasAuthenticationToken can also be obtained using
+ // SecurityContextHolder.getContext().getAuthentication()
+ final CasAuthenticationToken token = (CasAuthenticationToken) request.getUserPrincipal();
+ // proxyTicket could be reused to make calls to the CAS service even if the
+ // target url differs
+ final String proxyTicket = token.getAssertion().getPrincipal().getProxyTicketFor(targetUrl);
+
+ // Make a remote call using the proxy ticket
+ final String serviceUrl = targetUrl+"?ticket="+URLEncoder.encode(proxyTicket, "UTF-8");
+ String proxyResponse = CommonUtils.getResponseFromServer(serviceUrl, "UTF-8");
+ ...
+ }
+</pre></div></div><div class="section" title="22.3.4 Proxy Ticket Authentication"><div class="titlepage"><div><div><h3 class="title"><a name="cas-pt"></a>22.3.4 Proxy Ticket Authentication</h3></div></div></div><p>The <code class="classname">CasAuthenticationProvider</code> distinguishes
+ between stateful and stateless clients. A stateful client is
+ considered any that submits to the <code class="literal">filterProcessUrl</code> of the
+ <code class="classname">CasAuthenticationFilter</code>. A stateless client is any that
+ presents an authentication request to <code class="classname">CasAuthenticationFilter</code>
+ on a URL other than the <code class="literal">filterProcessUrl</code>.</p><p>Because remoting protocols have no way of presenting themselves
+ within the context of an <code class="classname">HttpSession</code>, it isn't
+ possible to rely on the default practice of storing the security context in the
+ session between requests. Furthermore, because the CAS server invalidates a
+ ticket after it has been validated by the <code class="literal">TicketValidator</code>,
+ presenting the same proxy ticket on subsequent requests will not
+ work.</p><p>One obvious option is to not use CAS at all for remoting
+ protocol clients. However, this would eliminate many of the desirable
+ features of CAS. As a middle-ground, the
+ <code class="literal">CasAuthenticationProvider</code> uses a
+ <code class="literal">StatelessTicketCache</code>. This is used solely for stateless clients
+ which use a principal equal to
+ <code class="literal">CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER</code>. What
+ happens is the <code class="literal">CasAuthenticationProvider</code> will store
+ the resulting <code class="literal">CasAuthenticationToken</code> in the
+ <code class="literal">StatelessTicketCache</code>, keyed on the proxy ticket.
+ Accordingly, remoting protocol clients can present the same proxy
+ ticket and the <code class="literal">CasAuthenticationProvider</code> will not
+ need to contact the CAS server for validation (aside from the first
+ request). Once authenticated, the proxy ticket could be used for URLs other than the
+ original target service.</p><p>This section builds upon the previous sections to accomodate proxy ticket authentication.
+ The first step is to specify to authenticate all artifacts as shown below.
+</p><pre class="programlisting">
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"serviceProperties"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.cas.ServiceProperties"</span><span class="hl-tag">></span>
+ ...
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticateAllArtifacts"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"true"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></bean></span>
+</pre><p>The next step is to specify <code class="literal">serviceProperties</code> and the
+ <code class="literal">authenticationDetailsSource</code> for the <code class="classname">CasAuthenticationFilter</code>.
+ The <code class="literal">serviceProperties</code> property instructs the
+ <code class="classname">CasAuthenticationFilter</code> to attempt to authenticate all artifacts instead of only
+ ones present on the <code class="literal">filterProcessUrl</code>. The
+ <code class="classname">ServiceAuthenticationDetailsSource</code> creates a
+ <code class="interfacename">ServiceAuthenticationDetails</code> that ensures the current URL, based
+ upon the <code class="literal">HttpServletRequest</code>, is used as the service URL when validating the ticket.
+ The method for generating the service URL can be customized by injecting a custom
+ <code class="literal">AuthenticationDetailsSource</code> that returns a custom
+ <code class="interfacename">ServiceAuthenticationDetails</code>.</p><pre class="programlisting">
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"casFilter"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.cas.web.CasAuthenticationFilter"</span><span class="hl-tag">></span>
+ ...
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"serviceProperties"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"serviceProperties"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationDetailsSource"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=
+ <span class="hl-value">"org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></property></span>
+ <span class="hl-tag"></bean></span>
+</pre><p>You will also need to update the <code class="classname">CasAuthenticationProvider</code> to handle proxy tickets.
+ To do this replace the <code class="classname">Cas20ServiceTicketValidator</code> with a
+ <code class="classname">Cas20ProxyTicketValidator</code>. You will need to configure the
+ <code class="literal">statelessTicketCache</code> and which proxies you want to accept. You can find an example of the updates
+ required to accept all proxies below.
+</p><pre class="programlisting">
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"casAuthenticationProvider"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.cas.authentication.CasAuthenticationProvider"</span><span class="hl-tag">></span>
+ ...
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"ticketValidator"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.jasig.cas.client.validation.Cas20ProxyTicketValidator"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">value</span>=<span class="hl-value">"https://localhost:9443/cas"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"acceptAnyProxy"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"true"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></bean></span>
+ <span class="hl-tag"></property></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"statelessTicketCache"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.cas.authentication.EhCacheBasedTicketCache"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"cache"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"net.sf.ehcache.Cache"</span>
+ <span class="hl-attribute">init-method</span>=<span class="hl-value">"initialise"</span> <span class="hl-attribute">destroy-method</span>=<span class="hl-value">"dispose"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">value</span>=<span class="hl-value">"casTickets"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">value</span>=<span class="hl-value">"50"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">value</span>=<span class="hl-value">"true"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">value</span>=<span class="hl-value">"false"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">value</span>=<span class="hl-value">"3600"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">value</span>=<span class="hl-value">"900"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></bean></span>
+ <span class="hl-tag"></property></span>
+ <span class="hl-tag"></bean></span>
+ <span class="hl-tag"></property></span>
+ <span class="hl-tag"></bean></span>
+</pre></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
- </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="jaas.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="advanced-topics.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="x509.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">20. Java Authentication and Authorization Service (JAAS) Provider </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 22. X.509 Authentication</td></tr></table></div></body></html>
\ No newline at end of file
+ </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="jaas.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="advanced-topics.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="x509.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">21. Java Authentication and Authorization Service (JAAS) Provider </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 23. X.509 Authentication</td></tr></table></div></body></html>
\ No newline at end of file
diff --git a/docs/reference/community.html b/docs/reference/community.html
index a824d23..55066b1 100644
--- a/docs/reference/community.html
+++ b/docs/reference/community.html
@@ -1,6 +1,6 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>4. Spring Security Community</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="getting-started.html" title="Part I. Getting Started"><link rel="prev" href="sample-apps.html" title="3. Sample Applications"><link rel="next" href="overall-architecture.html" title="Part II. Architecture and Implementation"><!--Begin Google Analytics code--><script type="text/javascript">
+ <title>5. Spring Security Community</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="getting-started.html" title="Part I. Getting Started"><link rel="prev" href="sample-apps.html" title="4. Sample Applications"><link rel="next" href="overall-architecture.html" title="Part II. Architecture and Implementation"><!--Begin Google Analytics code--><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
@@ -8,19 +8,19 @@
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
- </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">4. Spring Security Community</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="sample-apps.html">Prev</a> </td><th width="60%" align="center">Part I. Getting Started</th><td width="20%" align="right"> <a accesskey="n" href="overall-architecture.html">Next</a></td></tr></table><hr></div><div class="chapter" title="4. Spring Security Community"><div class="titlepage"><div><div><h1 class="title"><a name="community"></a>Spring Security Community</h1></div></div></div><div class="section" title="4.1 Issue Tracking"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="jira"></a>4.1 Issue Tracking</h2></div></div></div><p>Spring Security uses JIRA to manage bug reports and enhancement requests. If you find
+ </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">5. Spring Security Community</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="sample-apps.html">Prev</a> </td><th width="60%" align="center">Part I. Getting Started</th><td width="20%" align="right"> <a accesskey="n" href="overall-architecture.html">Next</a></td></tr></table><hr></div><div class="chapter" title="5. Spring Security Community"><div class="titlepage"><div><div><h1 class="title"><a name="community"></a>Spring Security Community</h1></div></div></div><div class="section" title="5.1 Issue Tracking"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="jira"></a>5.1 Issue Tracking</h2></div></div></div><p>Spring Security uses JIRA to manage bug reports and enhancement requests. If you find
a bug, please log a report using JIRA. Do not log it on the support forum, mailing list
or by emailing the project's developers. Such approaches are ad-hoc and we prefer to
manage bugs using a more formal process.</p><p>If possible, in your issue report please provide a JUnit test that demonstrates any
incorrect behaviour. Or, better yet, provide a patch that corrects the issue. Similarly,
enhancements are welcome to be logged in the issue tracker, although we only accept
enhancement requests if you include corresponding unit tests. This is necessary to
- ensure project test coverage is adequately maintained.</p><p>You can access the issue tracker at <a class="link" href="http://jira.springsource.org/browse/SEC" target="_top">http://jira.springsource.org/browse/SEC</a>. </p></div><div class="section" title="4.2 Becoming Involved"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="becoming-involved"></a>4.2 Becoming Involved</h2></div></div></div><p>We welcome your involvement in the Spring Security project. There are many ways of
+ ensure project test coverage is adequately maintained.</p><p>You can access the issue tracker at <a class="link" href="http://jira.springsource.org/browse/SEC" target="_top">http://jira.springsource.org/browse/SEC</a>. </p></div><div class="section" title="5.2 Becoming Involved"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="becoming-involved"></a>5.2 Becoming Involved</h2></div></div></div><p>We welcome your involvement in the Spring Security project. There are many ways of
contributing, including reading the forum and responding to questions from other people,
writing new code, improving existing code, assisting with documentation, developing
- samples or tutorials, or simply making suggestions.</p></div><div class="section" title="4.3 Further Information"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="further-info"></a>4.3 Further Information</h2></div></div></div><p>Questions and comments on Spring Security are welcome. You can use the Spring
- Community Forum web site at <code class="uri"><a class="uri" href="http://forum.springsource.org" target="_top">http://forum.springsource.org</a></code> to discuss Spring Security with other users of
- the framework. Remember to use JIRA for bug reports, as explained above.</p></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
+ samples or tutorials, or simply making suggestions.</p></div><div class="section" title="5.3 Further Information"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="further-info"></a>5.3 Further Information</h2></div></div></div><p>Questions and comments on Spring Security are welcome. You can use the Spring
+ Community Forum web site at <code class="uri"><a class="uri" href="http://forum.springsource.org" target="_top">http://forum.springsource.org</a></code> to discuss Spring Security with other users of the
+ framework. Remember to use JIRA for bug reports, as explained above.</p></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
- </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="sample-apps.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="getting-started.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="overall-architecture.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">3. Sample Applications </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> Part II. Architecture and Implementation</td></tr></table></div></body></html>
\ No newline at end of file
+ </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="sample-apps.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="getting-started.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="overall-architecture.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">4. Sample Applications </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> Part II. Architecture and Implementation</td></tr></table></div></body></html>
\ No newline at end of file
diff --git a/docs/reference/core-services.html b/docs/reference/core-services.html
index 38b562b..67a6bc5 100644
--- a/docs/reference/core-services.html
+++ b/docs/reference/core-services.html
@@ -1,6 +1,6 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>6. Core Services</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="overall-architecture.html" title="Part II. Architecture and Implementation"><link rel="prev" href="technical-overview.html" title="5. Technical Overview"><link rel="next" href="web-app-security.html" title="Part III. Web Application Security"><!--Begin Google Analytics code--><script type="text/javascript">
+ <title>7. Core Services</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="overall-architecture.html" title="Part II. Architecture and Implementation"><link rel="prev" href="technical-overview.html" title="6. Technical Overview"><link rel="next" href="web-app-security.html" title="Part III. Web Application Security"><!--Begin Google Analytics code--><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
@@ -8,40 +8,38 @@
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
- </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">6. Core Services</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="technical-overview.html">Prev</a> </td><th width="60%" align="center">Part II. Architecture and Implementation</th><td width="20%" align="right"> <a accesskey="n" href="web-app-security.html">Next</a></td></tr></table><hr></div><div class="chapter" title="6. Core Services"><div class="titlepage"><div><div><h2 class="title"><a name="core-services"></a>6. Core Services</h2></div></div></div><p> Now that we have a high-level overview of the Spring Security architecture and its core
+ </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">7. Core Services</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="technical-overview.html">Prev</a> </td><th width="60%" align="center">Part II. Architecture and Implementation</th><td width="20%" align="right"> <a accesskey="n" href="web-app-security.html">Next</a></td></tr></table><hr></div><div class="chapter" title="7. Core Services"><div class="titlepage"><div><div><h2 class="title"><a name="core-services"></a>7. Core Services</h2></div></div></div><p> Now that we have a high-level overview of the Spring Security architecture and its core
classes, let's take a closer look at one or two of the core interfaces and their
implementations, in particular the <code class="interfacename">AuthenticationManager</code>,
- <code class="interfacename">UserDetailsService</code> and the
- <code class="interfacename">AccessDecisionManager</code>. These crop up regularly throughout
- the remainder of this document so it's important you know how they are configured and how
- they operate. </p><div class="section" title="6.1 The AuthenticationManager, ProviderManager and AuthenticationProviders"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="core-services-authentication-manager"></a>6.1 The <code class="interfacename">AuthenticationManager</code>,
- <code class="classname">ProviderManager</code> and
- <code class="classname">AuthenticationProvider</code>s</h2></div></div></div><p>The <code class="interfacename">AuthenticationManager</code> is just an interface, so the
+ <code class="interfacename">UserDetailsService</code> and the
+ <code class="interfacename">AccessDecisionManager</code>. These crop up regularly throughout the
+ remainder of this document so it's important you know how they are configured and how they
+ operate. </p><div class="section" title="7.1 The AuthenticationManager, ProviderManager and AuthenticationProviders"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="core-services-authentication-manager"></a>7.1 The <code class="interfacename">AuthenticationManager</code>,
+ <code class="classname">ProviderManager</code> and
+ <code class="classname">AuthenticationProvider</code>s</h2></div></div></div><p>The <code class="interfacename">AuthenticationManager</code> is just an interface, so the
implementation can be anything we choose, but how does it work in practice? What if we
need to check multiple authentication databases or a combination of different
authentication services such as a database and an LDAP server?</p><p>The default implementation in Spring Security is called
- <code class="classname">ProviderManager</code> and rather than handling the authentication
+ <code class="classname">ProviderManager</code> and rather than handling the authentication
request itself, it delegates to a list of configured
- <code class="classname">AuthenticationProvider</code>s, each of which is queried in turn to
- see if it can perform the authentication. Each provider will either throw an exception
- or return a fully populated <code class="interfacename">Authentication</code> object.
- Remember our good friends, <code class="interfacename">UserDetails</code> and
- <code class="interfacename">UserDetailsService</code>? If not, head back to the previous
+ <code class="classname">AuthenticationProvider</code>s, each of which is queried in turn to see
+ if it can perform the authentication. Each provider will either throw an exception or
+ return a fully populated <code class="interfacename">Authentication</code> object. Remember
+ our good friends, <code class="interfacename">UserDetails</code> and
+ <code class="interfacename">UserDetailsService</code>? If not, head back to the previous
chapter and refresh your memory. The most common approach to verifying an authentication
request is to load the corresponding <code class="interfacename">UserDetails</code> and
check the loaded password against the one that has been entered by the user. This is the
approach used by the <code class="classname">DaoAuthenticationProvider</code> (see below). The
loaded <code class="interfacename">UserDetails</code> object - and particularly the
- <code class="literal">GrantedAuthority</code>s it contains - will be used when building the
- fully populated <code class="interfacename">Authentication</code> object which is returned
- from a successful authentication and stored in the
- <code class="classname">SecurityContext</code>. </p><p> If you are using the namespace, an instance of
- <code class="classname">ProviderManager</code> is created and maintained internally, and
- you add providers to it by using the namespace authentication provider elements
- (see <a class="link" href="ns-config.html#ns-auth-manager" title="2.6 The Authentication Manager and the Namespace">the namespace chapter</a>). In this
- case, you should not declare a <code class="classname">ProviderManager</code> bean in your
- application context. However, if you are not using the namespace then you would declare
- it like so: </p><pre class="programlisting">
+ <code class="literal">GrantedAuthority</code>s it contains - will be used when building the fully
+ populated <code class="interfacename">Authentication</code> object which is returned from a
+ successful authentication and stored in the <code class="classname">SecurityContext</code>. </p><p> If you are using the namespace, an instance of <code class="classname">ProviderManager</code>
+ is created and maintained internally, and you add providers to it by using the namespace
+ authentication provider elements (see <a class="link" href="ns-config.html#ns-auth-manager" title="3.6 The Authentication Manager and the Namespace">the namespace
+ chapter</a>). In this case, you should not declare a
+ <code class="classname">ProviderManager</code> bean in your application context. However, if you
+ are not using the namespace then you would declare it like so: </p><pre class="programlisting">
<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"authenticationManager"</span>
<span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.authentication.ProviderManager"</span><span class="hl-tag">></span>
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"providers"</span><span class="hl-tag">></span>
@@ -55,15 +53,15 @@
is implied by the use of a <code class="literal">List</code>), with each provider able to attempt
authentication, or skip authentication by simply returning <code class="literal">null</code>. If
all implementations return null, the <code class="literal">ProviderManager</code> will throw a
- <code class="exceptionname">ProviderNotFoundException</code>. If you're interested in
+ <code class="exceptionname">ProviderNotFoundException</code>. If you're interested in
learning more about chaining providers, please refer to the
- <code class="literal">ProviderManager</code> JavaDocs.</p><p> Authentication mechanisms such as a web form-login processing filter are injected
+ <code class="literal">ProviderManager</code> JavaDocs.</p><p> Authentication mechanisms such as a web form-login processing filter are injected
with a reference to the <code class="interfacename">ProviderManager</code> and will call it
to handle their authentication requests. The providers you require will sometimes be
interchangeable with the authentication mechanisms, while at other times they will
depend on a specific authentication mechanism. For example,
- <code class="classname">DaoAuthenticationProvider</code> and
- <code class="classname">LdapAuthenticationProvider</code> are compatible with any mechanism
+ <code class="classname">DaoAuthenticationProvider</code> and
+ <code class="classname">LdapAuthenticationProvider</code> are compatible with any mechanism
which submits a simple username/password authentication request and so will work with
form-based logins or HTTP Basic authentication. On the other hand, some authentication
mechanisms create an authentication request object which can only be interpreted by a
@@ -72,93 +70,87 @@
authenticated by a <code class="classname">CasAuthenticationProvider</code>. You needn't be too
concerned about this, because if you forget to register a suitable provider, you'll
simply receive a <code class="literal">ProviderNotFoundException</code> when an attempt to
- authenticate is made.</p><div class="section" title="6.1.1 DaoAuthenticationProvider"><div class="titlepage"><div><div><h3 class="title"><a name="core-services-dao-provider"></a>6.1.1 <code class="literal">DaoAuthenticationProvider</code></h3></div></div></div><p>The simplest <code class="interfacename">AuthenticationProvider</code> implemented by
+ authenticate is made.</p><div class="section" title="7.1.1 Erasing Credentials on Successful Authentication"><div class="titlepage"><div><div><h3 class="title"><a name="core-services-erasing-credentials"></a>7.1.1 Erasing Credentials on Successful Authentication</h3></div></div></div><p> By default (from Spring Security 3.1 onwards) the
+ <code class="classname">ProviderManager</code> will attempt to clear any sensitive
+ credentials information from the <code class="interfacename">Authentication</code>
+ object which is returned by a successful authentication request. This prevents
+ information like passwords being retained longer than necessary. </p><p> This may cause issues when you are using a cache of user objects, for example, to
+ improve performance in a stateless application. If the
+ <code class="interfacename">Authentication</code> contains a reference to an object in
+ the cache (such as a <code class="interfacename">UserDetails</code> instance) and this
+ has its credentials removed, then it will no longer be possible to authenticate
+ against the cached value. You need to take this into account if you are using a
+ cache. An obvious solution is to make a copy of the object first, either in the
+ cache implementation or in the <code class="interfacename">AuthenticationProvider</code>
+ which creates the returned <code class="interfacename">Authentication</code> object.
+ Alternatively, you can disable the
+ <code class="literal">eraseCredentialsAfterAuthentication</code> property on
+ <code class="classname">ProviderManager</code>. See the Javadoc for more information.
+ </p></div><div class="section" title="7.1.2 DaoAuthenticationProvider"><div class="titlepage"><div><div><h3 class="title"><a name="core-services-dao-provider"></a>7.1.2 <code class="literal">DaoAuthenticationProvider</code></h3></div></div></div><p>The simplest <code class="interfacename">AuthenticationProvider</code> implemented by
Spring Security is <code class="literal">DaoAuthenticationProvider</code>, which is also one
of the earliest supported by the framework. It leverages a
- <code class="interfacename">UserDetailsService</code> (as a DAO) in order to lookup
- the username, password and <code class="interfacename">GrantedAuthority</code>s. It
+ <code class="interfacename">UserDetailsService</code> (as a DAO) in order to lookup the
+ username, password and <code class="interfacename">GrantedAuthority</code>s. It
authenticates the user simply by comparing the password submitted in a
- <code class="classname">UsernamePasswordAuthenticationToken</code> against the one
- loaded by the <code class="interfacename">UserDetailsService</code>. Configuring the
- provider is quite simple: </p><pre class="programlisting">
+ <code class="classname">UsernamePasswordAuthenticationToken</code> against the one loaded by
+ the <code class="interfacename">UserDetailsService</code>. Configuring the provider is
+ quite simple: </p><pre class="programlisting">
<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"daoAuthenticationProvider"</span>
<span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.authentication.dao.DaoAuthenticationProvider"</span><span class="hl-tag">></span>
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"userDetailsService"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"inMemoryDaoImpl"</span><span class="hl-tag">/></span>
- <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"saltSource"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"saltSource"</span><span class="hl-tag">/></span>
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"passwordEncoder"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"passwordEncoder"</span><span class="hl-tag">/></span>
-<span class="hl-tag"></bean></span></pre><p> The <code class="interfacename">PasswordEncoder</code> and
- <code class="interfacename">SaltSource</code> are optional. A
- <code class="interfacename">PasswordEncoder</code> provides encoding and decoding of
+<span class="hl-tag"></bean></span></pre><p> The <code class="interfacename">PasswordEncoder</code> is optional. A
+ <code class="interfacename">PasswordEncoder</code> provides encoding and decoding of
passwords presented in the <code class="interfacename">UserDetails</code> object that is
- returned from the configured <code class="interfacename">UserDetailsService</code>. A
- <code class="interfacename">SaltSource</code> enables the passwords to be populated
- with a "salt", which enhances the security of the passwords in the authentication
- repository. These will be discussed in more detail <a class="link" href="core-services.html#core-services-password-encoding" title="6.3 Password Encoding">below</a>. </p></div><div class="section" title="6.1.2 Erasing Credentials on Successful Authentication"><div class="titlepage"><div><div><h3 class="title"><a name="core-services-erasing-credentials"></a>6.1.2 Erasing Credentials on Successful Authentication</h3></div></div></div><p>
- From Spring Security 3.0.3, you can configure the <code class="classname">ProviderManager</code>
- will attempt to clear any sensitive credentials information from the
- <code class="interfacename">Authentication</code> object which is returned by a successful
- authentication request, to prevent information like passwords being retained longer
- than necessary. This feature is controlled by the <code class="literal">eraseCredentialsAfterAuthentication</code>
- property on <code class="classname">ProviderManager</code>. It is off by default.
- See the Javadoc for more information.
- </p><p>
- This may cause issues when you are using a cache of user objects, for example, to
- improve performance in a stateless application. If the <code class="interfacename">Authentication</code>
- contains a reference to an object in the cache (such as a <code class="interfacename">UserDetails</code>
- instance) and this has its credentials removed, then it will no longer be possible to authenticate
- against the cached value. You need to take this into account if you are using a cache. An obvious
- solution is to make a copy of the object first, either in the cache implementation or in
- the <code class="interfacename">AuthenticationProvider</code> which creates the returned
- <code class="interfacename">Authentication</code> object.
- </p></div></div><div class="section" title="6.2 UserDetailsService Implementations"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e2530"></a>6.2 <code class="interfacename">UserDetailsService</code> Implementations</h2></div></div></div><p>As mentioned in the earlier in this reference guide, most authentication providers
+ returned from the configured <code class="interfacename">UserDetailsService</code>. This
+ will be discussed in more detail <a class="link" href="core-services.html#core-services-password-encoding" title="7.3 Password Encoding">below</a>. </p></div></div><div class="section" title="7.2 UserDetailsService Implementations"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e2871"></a>7.2 <code class="interfacename">UserDetailsService</code> Implementations</h2></div></div></div><p>As mentioned in the earlier in this reference guide, most authentication providers
take advantage of the <code class="interfacename">UserDetails</code> and
- <code class="interfacename">UserDetailsService</code> interfaces. Recall that the
- contract for <code class="interfacename">UserDetailsService</code> is a single
- method:</p><p>
+ <code class="interfacename">UserDetailsService</code> interfaces. Recall that the contract
+ for <code class="interfacename">UserDetailsService</code> is a single method:</p><p>
</p><pre class="programlisting">
- UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
+ UserDetails loadUserByUsername(String username) <span class="hl-keyword">throws</span> UsernameNotFoundException;
</pre><p>
</p><p>The returned <code class="interfacename">UserDetails</code> is an interface that provides
getters that guarantee non-null provision of authentication information such as the
username, password, granted authorities and whether the user account is enabled or
disabled. Most authentication providers will use a
- <code class="interfacename">UserDetailsService</code>, even if the username and password
- are not actually used as part of the authentication decision. They may use the returned
- <code class="interfacename">UserDetails</code> object just for its
- <code class="literal">GrantedAuthority</code> information, because some other system (like
- LDAP or X.509 or CAS etc) has undertaken the responsibility of actually validating the
+ <code class="interfacename">UserDetailsService</code>, even if the username and password are
+ not actually used as part of the authentication decision. They may use the returned
+ <code class="interfacename">UserDetails</code> object just for its
+ <code class="literal">GrantedAuthority</code> information, because some other system (like LDAP or
+ X.509 or CAS etc) has undertaken the responsibility of actually validating the
credentials.</p><p>Given <code class="interfacename">UserDetailsService</code> is so simple to implement, it
should be easy for users to retrieve authentication information using a persistence
strategy of their choice. Having said that, Spring Security does include a couple of
- useful base implementations, which we'll look at below.</p><div class="section" title="6.2.1 In-Memory Authentication"><div class="titlepage"><div><div><h3 class="title"><a name="core-services-in-memory-service"></a>6.2.1 In-Memory Authentication</h3></div></div></div><p>Is easy to use create a custom <code class="interfacename">UserDetailsService</code>
+ useful base implementations, which we'll look at below.</p><div class="section" title="7.2.1 In-Memory Authentication"><div class="titlepage"><div><div><h3 class="title"><a name="core-services-in-memory-service"></a>7.2.1 In-Memory Authentication</h3></div></div></div><p>Is easy to use create a custom <code class="interfacename">UserDetailsService</code>
implementation that extracts information from a persistence engine of choice, but
many applications do not require such complexity. This is particularly true if
you're building a prototype application or just starting integrating Spring
Security, when you don't really want to spend time configuring databases or writing
- <code class="interfacename">UserDetailsService</code> implementations. For this sort
- of situation, a simple option is to use the <code class="literal">user-service</code> element
- from the security <a class="link" href="ns-config.html#ns-minimal" title="2.2.2 A Minimal <http> Configuration">namespace</a>: </p><pre class="programlisting">
- <user-service id="userDetailsService">
- <user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
- <user name="bob" password="bobspassword" authorities="ROLE_USER" />
- </user-service>
+ <code class="interfacename">UserDetailsService</code> implementations. For this sort of
+ situation, a simple option is to use the <code class="literal">user-service</code> element
+ from the security <a class="link" href="ns-config.html#ns-minimal" title="3.2.2 A Minimal <http> Configuration">namespace</a>: </p><pre class="programlisting">
+ <span class="hl-tag"><user-service</span> <span class="hl-attribute">id</span>=<span class="hl-value">"userDetailsService"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><user</span> <span class="hl-attribute">name</span>=<span class="hl-value">"jimi"</span> <span class="hl-attribute">password</span>=<span class="hl-value">"jimispassword"</span> <span class="hl-attribute">authorities</span>=<span class="hl-value">"ROLE_USER, ROLE_ADMIN"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"><user</span> <span class="hl-attribute">name</span>=<span class="hl-value">"bob"</span> <span class="hl-attribute">password</span>=<span class="hl-value">"bobspassword"</span> <span class="hl-attribute">authorities</span>=<span class="hl-value">"ROLE_USER"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"></user-service></span>
</pre><p> This also supports the use of an external properties
file: </p><pre class="programlisting">
- <user-service id="userDetailsService" properties="users.properties"/>
+ <span class="hl-tag"><user-service</span> <span class="hl-attribute">id</span>=<span class="hl-value">"userDetailsService"</span> <span class="hl-attribute">properties</span>=<span class="hl-value">"users.properties"</span><span class="hl-tag">/></span>
</pre><p> The properties file should contain entries in the form
</p><pre class="programlisting">username=password,grantedAuthority[,grantedAuthority][,enabled|disabled]</pre><p>
For example
</p><pre class="programlisting">
jimi=jimispassword,ROLE_USER,ROLE_ADMIN,enabled
- bob=bobspassword,ROLE_USER,enabled</pre></div><div class="section" title="6.2.2 JdbcDaoImpl"><div class="titlepage"><div><div><h3 class="title"><a name="core-services-jdbc-user-service"></a>6.2.2 <code class="literal">JdbcDaoImpl</code></h3></div></div></div><p>Spring Security also includes a <code class="interfacename">UserDetailsService</code>
+ bob=bobspassword,ROLE_USER,enabled</pre></div><div class="section" title="7.2.2 JdbcDaoImpl"><div class="titlepage"><div><div><h3 class="title"><a name="core-services-jdbc-user-service"></a>7.2.2 <code class="literal">JdbcDaoImpl</code></h3></div></div></div><p>Spring Security also includes a <code class="interfacename">UserDetailsService</code>
that can obtain authentication information from a JDBC data source. Internally
Spring JDBC is used, so it avoids the complexity of a fully-featured object
relational mapper (ORM) just to store user details. If your application does use an
ORM tool, you might prefer to write a custom
- <code class="interfacename">UserDetailsService</code> to reuse the mapping files
- you've probably already created. Returning to <code class="literal">JdbcDaoImpl</code>, an
- example configuration is shown below:</p><p>
+ <code class="interfacename">UserDetailsService</code> to reuse the mapping files you've
+ probably already created. Returning to <code class="literal">JdbcDaoImpl</code>, an example
+ configuration is shown below:</p><p>
</p><pre class="programlisting">
<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"dataSource"</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.jdbc.datasource.DriverManagerDataSource"</span><span class="hl-tag">></span>
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"driverClassName"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"org.hsqldb.jdbcDriver"</span><span class="hl-tag">/></span>
@@ -167,78 +159,84 @@
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"password"</span> <span class="hl-attribute">value</span>=<span class="hl-value">""</span><span class="hl-tag">/></span>
<span class="hl-tag"></bean></span>
-<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"userDetailsService"</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl"</span><span class="hl-tag">></span>
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"userDetailsService"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl"</span><span class="hl-tag">></span>
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"dataSource"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"dataSource"</span><span class="hl-tag">/></span>
<span class="hl-tag"></bean></span> </pre><p>
</p><p>You can use different relational database management systems by modifying the
- <code class="literal">DriverManagerDataSource</code> shown above. You can also use a
- global data source obtained from JNDI, as with any other Spring
- configuration.</p><div class="section" title="Authority Groups"><div class="titlepage"><div><div><h4 class="title"><a name="d0e2623"></a>Authority Groups</h4></div></div></div><p>By default, <code class="classname">JdbcDaoImpl</code> loads the authorities for a
+ <code class="literal">DriverManagerDataSource</code> shown above. You can also use a global
+ data source obtained from JNDI, as with any other Spring configuration.</p><div class="section" title="Authority Groups"><div class="titlepage"><div><div><h4 class="title"><a name="d0e2964"></a>Authority Groups</h4></div></div></div><p>By default, <code class="classname">JdbcDaoImpl</code> loads the authorities for a
single user with the assumption that the authorities are mapped directly to
users (see the <a class="link" href="appendix-schema.html" title="Appendix A. Security Database Schema">database schema
- appendix</a>). An alternative approach is to partition the authorities
- into groups and assign groups to the user. Some people prefer this approach as a
+ appendix</a>). An alternative approach is to partition the authorities into
+ groups and assign groups to the user. Some people prefer this approach as a
means of administering user rights. See the <code class="classname">JdbcDaoImpl</code>
Javadoc for more information on how to enable the use of group authorities. The
- group schema is also included in the appendix.</p></div></div></div><div class="section" title="6.3 Password Encoding"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="core-services-password-encoding"></a>6.3 Password Encoding</h2></div></div></div><p>Spring Security's <code class="interfacename">PasswordEncoder</code> interface is used to
- support the use of passwords which are encoded in some way in persistent storage. This
- will normally mean that the passwords are <span class="quote">“<span class="quote">hashed</span>”</span> using a digest algorithm
- such as MD5 or SHA.</p><div class="section" title="6.3.1 What is a hash?"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2649"></a>6.3.1 What is a hash?</h3></div></div></div><p>Password hashing is not unique to Spring Security but is a common source of
+ group schema is also included in the appendix.</p></div></div></div><div class="section" title="7.3 Password Encoding"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="core-services-password-encoding"></a>7.3 Password Encoding</h2></div></div></div><p>Spring Security's
+ <code class="interfacename">PasswordEncoder</code> interface is used to support the use of
+ passwords which are encoded in some way in persistent storage. This will normally mean
+ that the passwords are <span class="quote">“<span class="quote">hashed</span>”</span> using a digest algorithm such as MD5 or
+ SHA. Spring Security 3.1's <a class="link" href="crypto.html#spring-security-crypto-passwordencoders" title="25.4 Password Encoding"><code class="literal">crypto</code></a> package introduces a simpler API which encourages
+ best-practice for password hashing. We would encourage you to use these APIs for new
+ development and regard the classes in package
+ <code class="literal">org.springframework.security.authentication.encoding</code> as legacy
+ implementations. The <code class="classname">DaoAuthenticationProvider</code> can be injected
+ with either the new or legacy <code class="interfacename">PasswordEncoder</code>
+ types.</p><div class="section" title="7.3.1 What is a hash?"><div class="titlepage"><div><div><h3 class="title"><a name="d0e3003"></a>7.3.1 What is a hash?</h3></div></div></div><p>Password hashing is not unique to Spring Security but is a common source of
confusion for users who are not familiar with the concept. A hash (or digest)
algorithm is a one-way function which produces a piece of fixed-length output data
(the hash) from some input data, such as a password. As an example, the MD5 hash of
the string <span class="quote">“<span class="quote">password</span>”</span> (in hexadecimal) is
</p><pre class="programlisting">
5f4dcc3b5aa765d61d8327deb882cf99
-</pre><p> A hash is
- <span class="quote">“<span class="quote">one-way</span>”</span> in the sense that it is very difficult (effectively
+</pre><p>
+ A hash is <span class="quote">“<span class="quote">one-way</span>”</span> in the sense that it is very difficult (effectively
impossible) to obtain the original input given the hash value, or indeed any
possible input which would produce that hash value. This property makes hash values
very useful for authentication purposes. They can be stored in your user database as
an alternative to plaintext passwords and even if the values are compromised they do
not immediately reveal a password which can be used to login. Note that this also
- means you have no way of recovering the password once it is encoded.</p></div><div class="section" title="6.3.2 Adding Salt to a Hash"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2663"></a>6.3.2 Adding Salt to a Hash</h3></div></div></div><p> One potential problem with the use of password hashes that it is relatively easy
+ means you have no way of recovering the password once it is encoded.</p></div><div class="section" title="7.3.2 Adding Salt to a Hash"><div class="titlepage"><div><div><h3 class="title"><a name="d0e3017"></a>7.3.2 Adding Salt to a Hash</h3></div></div></div><p> One potential problem with the use of password hashes that it is relatively easy
to get round the one-way property of the hash if a common word is used for the
input. For example, if you search for the hash value
- <code class="literal">5f4dcc3b5aa765d61d8327deb882cf99</code> using google, you will
- quickly find the original word <span class="quote">“<span class="quote">password</span>”</span>. In a similar way, an
- attacker can build a dictionary of hashes from a standard word list and use this to
- lookup the original password. One way to help prevent this is to have a suitably
- strong password policy to try to prevent common words from being used. Another is to
- use a <span class="quote">“<span class="quote">salt</span>”</span> when calculating the hashes. This is an additional string
- of known data for each user which is combined with the password before calculating
- the hash. Ideally the data should be as random as possible, but in practice any salt
- value is usually preferable to none. Spring Security has a
- <code class="interfacename">SaltSource</code> interface which can be used by an
- authentication provider to generate a salt value for a particular user. Using a salt
- means that an attacker has to build a separate dictionary of hashes for each salt
- value, making the attack more complicated (but not impossible).</p></div><div class="section" title="6.3.3 Hashing and Authentication"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2680"></a>6.3.3 Hashing and Authentication</h3></div></div></div><p>When an authentication provider (such as Spring Security's
- <code class="classname">DaoAuthenticationProvider</code> needs to check the password in
- a submitted authentication request against the known value for a user, and the
- stored password is encoded in some way, then the submitted value must be encoded
- using exactly the same algorithm. It's up to you to check that these are compatible
- as Spring Security has no control over the persistent values. If you add password
+ <code class="literal">5f4dcc3b5aa765d61d8327deb882cf99</code> using google, you will quickly
+ find the original word <span class="quote">“<span class="quote">password</span>”</span>. In a similar way, an attacker can
+ build a dictionary of hashes from a standard word list and use this to lookup the
+ original password. One way to help prevent this is to have a suitably strong
+ password policy to try to prevent common words from being used. Another is to use a
+ <span class="quote">“<span class="quote">salt</span>”</span> when calculating the hashes. This is an additional string of
+ known data for each user which is combined with the password before calculating the
+ hash. Ideally the data should be as random as possible, but in practice any salt
+ value is usually preferable to none. Using a salt means that an attacker has to
+ build a separate dictionary of hashes for each salt value, making the attack more
+ complicated (but not impossible).</p><p>The <code class="classname">StandardPasswordEncoder</code> in the <a class="link" href="crypto.html#spring-security-crypto-passwordencoders" title="25.4 Password Encoding"><code class="literal">crypto</code></a> package uses a random 8-byte salt, which is stored
+ in the same field as the password.</p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>The legacy approach to handling salt was to inject a
+ <code class="interfacename">SaltSource</code> into the
+ <code class="classname">DaoAuthenticationProvider</code>, which would obtain a salt
+ value for a particular user and pass it to the
+ <code class="interfacename">PasswordEncoder</code>. Using a random salt and
+ combining it with the password data field means you don't have to worry about
+ the details of salt handling (such as where the the value is stored), as it is
+ all done internally. So we'd strongly recommend you use this approach unless you
+ already have a system in place which stores the salt separately.</p></td></tr></table></div></div><div class="section" title="7.3.3 Hashing and Authentication"><div class="titlepage"><div><div><h3 class="title"><a name="d0e3052"></a>7.3.3 Hashing and Authentication</h3></div></div></div><p>When an authentication provider (such as Spring Security's
+ <code class="classname">DaoAuthenticationProvider</code>) needs to check the password in a
+ submitted authentication request against the known value for a user, and the stored
+ password is encoded in some way, then the submitted value must be encoded using
+ exactly the same algorithm. It's up to you to check that these are compatible as
+ Spring Security has no control over the persistent values. If you add password
hashing to your authentication configuration in Spring Security, and your database
contains plaintext passwords, then there is no way authentication can succeed. Even
if you are aware that your database is using MD5 to encode the passwords, for
example, and your application is configured to use Spring Security's
- <code class="classname">Md5PasswordEncoder</code>, there are still things that can go
- wrong. The database may have the passwords encoded in Base 64, for example while the
- enocoder is using hexadecimal strings (the default)<sup>[<a name="d0e2691" href="#ftn.d0e2691" class="footnote">6</a>]</sup>. Alternatively your database
- may be using upper-case while the output from the encoder is lower-case. Make sure
- you write a test to check the output from your configured password encoder with a
- known password and salt combination and check that it matches the database value
- before going further and attempting to authenticate through your application. For
- more information on the default method for merging salt and password, see the
- Javadoc for <code class="classname">BasePasswordEncoder</code>. If you want to generate
- encoded passwords directly in Java for storage in your user database, then you can
- use the <code class="methodname">encodePassword</code> method on the
- <code class="interfacename">PasswordEncoder</code>.</p></div></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e2691" href="#d0e2691" class="para">6</a>] </sup>You can configure
- the encoder to use Base 64 instead of hex by setting the
- <code class="literal">encodeHashAsBase64</code> property to
- <code class="literal">true</code>. Check the Javadoc for
- <code class="classname">MessageDigestPasswordEncoder</code> and its parent
- classes for more information.</p></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
+ <code class="classname">Md5PasswordEncoder</code>, there are still things that can go wrong.
+ The database may have the passwords encoded in Base 64, for example while the
+ encoder is using hexadecimal strings (the default). Alternatively your database may
+ be using upper-case while the output from the encoder is lower-case. Make sure you
+ write a test to check the output from your configured password encoder with a known
+ password and salt combination and check that it matches the database value before
+ going further and attempting to authenticate through your application.</p><p>If you want to generate encoded passwords directly in Java for storage in your
+ user database, then you can use the <code class="methodname">encode</code> method on the
+ <code class="interfacename">PasswordEncoder</code>.</p></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
- </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="technical-overview.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="overall-architecture.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="web-app-security.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">5. Technical Overview </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> Part III. Web Application Security</td></tr></table></div></body></html>
\ No newline at end of file
+ </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="technical-overview.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="overall-architecture.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="web-app-security.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">6. Technical Overview </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> Part III. Web Application Security</td></tr></table></div></body></html>
\ No newline at end of file
diff --git a/docs/reference/core-web-filters.html b/docs/reference/core-web-filters.html
index 952938f..60b608e 100644
--- a/docs/reference/core-web-filters.html
+++ b/docs/reference/core-web-filters.html
@@ -1,6 +1,6 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>8. Core Security Filters</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="web-app-security.html" title="Part III. Web Application Security"><link rel="prev" href="security-filter-chain.html" title="7. The Security Filter Chain"><link rel="next" href="basic.html" title="9. Basic and Digest Authentication"><!--Begin Google Analytics code--><script type="text/javascript">
+ <title>9. Core Security Filters</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="web-app-security.html" title="Part III. Web Application Security"><link rel="prev" href="security-filter-chain.html" title="8. The Security Filter Chain"><link rel="next" href="basic.html" title="10. Basic and Digest Authentication"><!--Begin Google Analytics code--><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
@@ -8,19 +8,19 @@
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
- </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">8. Core Security Filters</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="security-filter-chain.html">Prev</a> </td><th width="60%" align="center">Part III. Web Application Security</th><td width="20%" align="right"> <a accesskey="n" href="basic.html">Next</a></td></tr></table><hr></div><div class="chapter" title="8. Core Security Filters"><div class="titlepage"><div><div><h2 class="title"><a name="core-web-filters"></a>8. Core Security Filters</h2></div></div></div><p> There are some key filters which will always be used in a web application which uses
+ </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">9. Core Security Filters</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="security-filter-chain.html">Prev</a> </td><th width="60%" align="center">Part III. Web Application Security</th><td width="20%" align="right"> <a accesskey="n" href="basic.html">Next</a></td></tr></table><hr></div><div class="chapter" title="9. Core Security Filters"><div class="titlepage"><div><div><h2 class="title"><a name="core-web-filters"></a>9. Core Security Filters</h2></div></div></div><p> There are some key filters which will always be used in a web application which uses
Spring Security, so we'll look at these and their supporting classes and interfaces first.
We won't cover every feature, so be sure to look at the Javadoc for them if you want to get
- the complete picture.</p><div class="section" title="8.1 FilterSecurityInterceptor"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="filter-security-interceptor"></a>8.1 <code class="classname">FilterSecurityInterceptor</code></h2></div></div></div><p>We've already seen <code class="classname">FilterSecurityInterceptor</code> briefly when
- discussing <a class="link" href="technical-overview.html#tech-intro-access-control" title="5.5 Access-Control (Authorization) in Spring Security">access-control in
- general</a>, and we've already used it with the namespace where the
- <code class="literal"><intercept-url></code> elements are combined to configure it
- internally. Now we'll see how to explicitly configure it for use with a
- <code class="classname">FilterChainProxy</code>, along with its companion filter
- <code class="classname">ExceptionTranslationFilter</code>. A typical configuration example
- is shown below: </p><pre class="programlisting">
+ the complete picture.</p><div class="section" title="9.1 FilterSecurityInterceptor"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="filter-security-interceptor"></a>9.1 <code class="classname">FilterSecurityInterceptor</code></h2></div></div></div><p>We've already seen <code class="classname">FilterSecurityInterceptor</code> briefly when
+ discussing <a class="link" href="technical-overview.html#tech-intro-access-control" title="6.5 Access-Control (Authorization) in Spring Security">access-control in
+ general</a>, and we've already used it with the namespace where the
+ <code class="literal"><intercept-url></code> elements are combined to configure it internally.
+ Now we'll see how to explicitly configure it for use with a
+ <code class="classname">FilterChainProxy</code>, along with its companion filter
+ <code class="classname">ExceptionTranslationFilter</code>. A typical configuration example is
+ shown below: </p><pre class="programlisting">
<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"filterSecurityInterceptor"</span>
- <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.access.intercept.FilterSecurityInterceptor"</span><span class="hl-tag">></span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.access.intercept.FilterSecurityInterceptor"</span><span class="hl-tag">></span>
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"authenticationManager"</span><span class="hl-tag">/></span>
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"accessDecisionManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"accessDecisionManager"</span><span class="hl-tag">/></span>
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"securityMetadataSource"</span><span class="hl-tag">></span>
@@ -31,44 +31,42 @@
<span class="hl-tag"></property></span>
<span class="hl-tag"></bean></span></pre><p><code class="classname">FilterSecurityInterceptor</code> is responsible for handling the
security of HTTP resources. It requires a reference to an
- <code class="interfacename">AuthenticationManager</code> and an
- <code class="interfacename">AccessDecisionManager</code>. It is also supplied with
- configuration attributes that apply to different HTTP URL requests. Refer back to <a class="link" href="technical-overview.html#tech-intro-config-attributes" title="What are Configuration Attributes?">the original discussion on these</a>
- in the technical introduction.</p><p>The <code class="classname">FilterSecurityInterceptor</code> can be configured with
+ <code class="interfacename">AuthenticationManager</code> and an
+ <code class="interfacename">AccessDecisionManager</code>. It is also supplied with
+ configuration attributes that apply to different HTTP URL requests. Refer back to <a class="link" href="technical-overview.html#tech-intro-config-attributes" title="What are Configuration Attributes?">the original discussion on these</a> in
+ the technical introduction.</p><p>The <code class="classname">FilterSecurityInterceptor</code> can be configured with
configuration attributes in two ways. The first, which is shown above, is using the
- <code class="literal"><filter-security-metadata-source></code> namespace element. This
- is similar to the <code class="literal"><filter-chain-map></code> used to configure a
- <code class="classname">FilterChainProxy</code> but the
- <code class="literal"><intercept-url></code> child elements only use the
- <code class="literal">pattern</code> and <code class="literal">access</code> attributes. Commas are used
- to delimit the different configuration attributes that apply to each HTTP URL. The
- second option is to write your own
+ <code class="literal"><filter-security-metadata-source></code> namespace element. This is
+ similar to the <code class="literal"><http></code> element from the namespace chapter
+ but the <code class="literal"><intercept-url></code>
+ child elements only use the <code class="literal">pattern</code> and <code class="literal">access</code>
+ attributes. Commas are used to delimit the different configuration attributes that apply
+ to each HTTP URL. The second option is to write your own
<code class="interfacename">SecurityMetadataSource</code>, but this is beyond the scope of
this document. Irrespective of the approach used, the
- <code class="interfacename">SecurityMetadataSource</code> is responsible for returning a
- <code class="literal">List<ConfigAttribute></code> containing all of the configuration
+ <code class="interfacename">SecurityMetadataSource</code> is responsible for returning a
+ <code class="literal">List<ConfigAttribute></code> containing all of the configuration
attributes associated with a single secure HTTP URL.</p><p>It should be noted that the
- <code class="literal">FilterSecurityInterceptor.setSecurityMetadataSource()</code> method
- actually expects an instance of
- <code class="interfacename">FilterSecurityMetadataSource</code>. This is a marker
- interface which subclasses <code class="interfacename">SecurityMetadataSource</code>. It
- simply denotes the <code class="interfacename">SecurityMetadataSource</code> understands
- <code class="classname">FilterInvocation</code>s. In the interests of simplicity we'll
- continue to refer to the
- <code class="interfacename">FilterInvocationSecurityMetadataSource</code> as a
- <code class="interfacename">SecurityMetadataSource</code>, as the distinction is of
- little relevance to most users.</p><p>The <code class="interfacename">SecurityMetadataSource</code> created by the namespace
+ <code class="literal">FilterSecurityInterceptor.setSecurityMetadataSource()</code> method actually
+ expects an instance of <code class="interfacename">FilterSecurityMetadataSource</code>. This
+ is a marker interface which subclasses
+ <code class="interfacename">SecurityMetadataSource</code>. It simply denotes the
+ <code class="interfacename">SecurityMetadataSource</code> understands
+ <code class="classname">FilterInvocation</code>s. In the interests of simplicity we'll continue
+ to refer to the <code class="interfacename">FilterInvocationSecurityMetadataSource</code> as
+ a <code class="interfacename">SecurityMetadataSource</code>, as the distinction is of little
+ relevance to most users.</p><p>The <code class="interfacename">SecurityMetadataSource</code> created by the namespace
syntax obtains the configuration attributes for a particular
- <code class="classname">FilterInvocation</code> by matching the request URL against the
+ <code class="classname">FilterInvocation</code> by matching the request URL against the
configured <code class="literal">pattern</code> attributes. This behaves in the same way as it
does for namespace configuration. The default is to treat all expressions as Apache Ant
paths and regular expressions are also supported for more complex cases. The
- <code class="literal">path-type</code> attribute is used to specify the type of pattern being
+ <code class="literal">path-type</code> attribute is used to specify the type of pattern being
used. It is not possible to mix expression syntaxes within the same definition. As an
example, the previous configuration using regular expressions instead of Ant paths would
be written as follows:</p><pre class="programlisting">
<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"filterInvocationInterceptor"</span>
- <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.access.intercept.FilterSecurityInterceptor"</span><span class="hl-tag">></span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.access.intercept.FilterSecurityInterceptor"</span><span class="hl-tag">></span>
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"authenticationManager"</span><span class="hl-tag">/></span>
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"accessDecisionManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"accessDecisionManager"</span><span class="hl-tag">/></span>
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"runAsManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"runAsManager"</span><span class="hl-tag">/></span>
@@ -81,40 +79,39 @@
<span class="hl-tag"></bean></span> </pre><p>Patterns are always evaluated in the order they are defined. Thus it is important that
more specific patterns are defined higher in the list than less specific patterns. This
is reflected in our example above, where the more specific
- <code class="literal">/secure/super/</code> pattern appears higher than the less specific
- <code class="literal">/secure/</code> pattern. If they were reversed, the
- <code class="literal">/secure/</code> pattern would always match and the
- <code class="literal">/secure/super/</code> pattern would never be evaluated.</p></div><div class="section" title="8.2 ExceptionTranslationFilter"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="exception-translation-filter"></a>8.2
- <code class="classname">ExceptionTranslationFilter</code></h2></div></div></div><p>The <code class="classname">ExceptionTranslationFilter</code> sits above the
- <code class="classname">FilterSecurityInterceptor</code> in the security filter stack. It
+ <code class="literal">/secure/super/</code> pattern appears higher than the less specific
+ <code class="literal">/secure/</code> pattern. If they were reversed, the
+ <code class="literal">/secure/</code> pattern would always match and the
+ <code class="literal">/secure/super/</code> pattern would never be evaluated.</p></div><div class="section" title="9.2 ExceptionTranslationFilter"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="exception-translation-filter"></a>9.2 <code class="classname">ExceptionTranslationFilter</code></h2></div></div></div><p>The <code class="classname">ExceptionTranslationFilter</code> sits above the
+ <code class="classname">FilterSecurityInterceptor</code> in the security filter stack. It
doesn't do any actual security enforcement itself, but handles exceptions thrown by the
security interceptors and provides suitable and HTTP responses. </p><pre class="programlisting">
<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"exceptionTranslationFilter"</span>
- <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.access.ExceptionTranslationFilter"</span><span class="hl-tag">></span>
- <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationEntryPoint"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"authenticationEntryPoint"</span><span class="hl-tag">/></span>
- <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"accessDeniedHandler"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"accessDeniedHandler"</span><span class="hl-tag">/></span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.access.ExceptionTranslationFilter"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationEntryPoint"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"authenticationEntryPoint"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"accessDeniedHandler"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"accessDeniedHandler"</span><span class="hl-tag">/></span>
<span class="hl-tag"></bean></span>
<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"authenticationEntryPoint"</span>
- <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint"</span><span class="hl-tag">></span>
- <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"loginFormUrl"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"/login.jsp"</span><span class="hl-tag">/></span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"loginFormUrl"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"/login.jsp"</span><span class="hl-tag">/></span>
<span class="hl-tag"></bean></span>
<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"accessDeniedHandler"</span>
<span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.access.AccessDeniedHandlerImpl"</span><span class="hl-tag">></span>
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"errorPage"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"/accessDenied.htm"</span><span class="hl-tag">/></span>
<span class="hl-tag"></bean></span>
-</pre><div class="section" title="8.2.1 AuthenticationEntryPoint"><div class="titlepage"><div><div><h3 class="title"><a name="auth-entry-point"></a>8.2.1 <code class="interfacename">AuthenticationEntryPoint</code></h3></div></div></div><p> The <code class="interfacename">AuthenticationEntryPoint</code> will be called if the
+</pre><div class="section" title="9.2.1 AuthenticationEntryPoint"><div class="titlepage"><div><div><h3 class="title"><a name="auth-entry-point"></a>9.2.1 <code class="interfacename">AuthenticationEntryPoint</code></h3></div></div></div><p> The <code class="interfacename">AuthenticationEntryPoint</code> will be called if the
user requests a secure HTTP resource but they are not authenticated. An appropriate
- <code class="exceptionname">AuthenticationException</code> or
- <code class="exceptionname">AccessDeniedException</code> will be thrown by a
- security interceptor further down the call stack, triggering the
- <code class="methodname">commence</code> method on the entry point. This does the job
- of presenting the appropriate response to the user so that authentication can begin.
+ <code class="exceptionname">AuthenticationException</code> or
+ <code class="exceptionname">AccessDeniedException</code> will be thrown by a security
+ interceptor further down the call stack, triggering the
+ <code class="methodname">commence</code> method on the entry point. This does the job of
+ presenting the appropriate response to the user so that authentication can begin.
The one we've used here is <code class="classname">LoginUrlAuthenticationEntryPoint</code>,
which redirects the request to a different URL (typically a login page). The actual
implementation used will depend on the authentication mechanism you want to be used
- in your application. </p></div><div class="section" title="8.2.2 AccessDeniedHandler"><div class="titlepage"><div><div><h3 class="title"><a name="access-denied-handler"></a>8.2.2 <code class="interfacename">AccessDeniedHandler</code></h3></div></div></div><p>What happens if a user is already authenticated an they try to access a protected
+ in your application. </p></div><div class="section" title="9.2.2 AccessDeniedHandler"><div class="titlepage"><div><div><h3 class="title"><a name="access-denied-handler"></a>9.2.2 <code class="interfacename">AccessDeniedHandler</code></h3></div></div></div><p>What happens if a user is already authenticated and they try to access a protected
resource? In normal usage, this shouldn't happen because the application workflow
should be restricted to operations to which a user has access. For example, an HTML
link to an administration page might be hidden from users who do not have an admin
@@ -127,22 +124,39 @@
service layer interfaces to really nail down what is permissible.</p><p>If an <code class="exceptionname">AccessDeniedException</code> is thrown and a user
has already been authenticated, then this means that an operation has been attempted
for which they don't have enough permissions. In this case,
- <code class="classname">ExceptionTranslationFilter</code> will invoke a second strategy,
- the <code class="interfacename">AccessDeniedHandler</code>. By default, an
- <code class="classname">AccessDeniedHandlerImpl</code> is used, which just sends a 403
+ <code class="classname">ExceptionTranslationFilter</code> will invoke a second strategy, the
+ <code class="interfacename">AccessDeniedHandler</code>. By default, an
+ <code class="classname">AccessDeniedHandlerImpl</code> is used, which just sends a 403
(Forbidden) response to the client. Alternatively you can configure an instance
explicitly (as in the above example) and set an error page URL which it will
- forwards the request to <sup>[<a name="d0e3217" href="#ftn.d0e3217" class="footnote">8</a>]</sup>. This can be a simple <span class="quote">“<span class="quote">access denied</span>”</span> page, such as a JSP,
+ forwards the request to <sup>[<a name="d0e3725" href="#ftn.d0e3725" class="footnote">15</a>]</sup>. This can be a simple <span class="quote">“<span class="quote">access denied</span>”</span> page, such as a JSP,
or it could be a more complex handler such as an MVC controller. And of course, you
can implement the interface yourself and use your own implementation. </p><p>It's also possible to supply a custom
- <code class="interfacename">AccessDeniedHandler</code> when you're using the
- namespace to configure your application. See <a class="link" href="appendix-namespace.html#nsa-access-denied-handler" title="B.1.2 <access-denied-handler>">the namespace appendix</a> for more
- details.</p></div></div><div class="section" title="8.3 SecurityContextPersistenceFilter"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="security-context-persistence-filter"></a>8.3 <code class="classname">SecurityContextPersistenceFilter</code></h2></div></div></div><p> We covered the purpose of this all-important filter in the <a class="link" href="technical-overview.html#tech-intro-sec-context-persistence" title="5.4.4 Storing the SecurityContext between requests">Technical Overview</a> chapter
- so you might want to re-read that section at this point. Let's first take a look at how
- you would configure it for use with a <code class="classname">FilterChainProxy</code>. A basic
+ <code class="interfacename">AccessDeniedHandler</code> when you're using the namespace
+ to configure your application. See <a class="link" href="appendix-namespace.html#nsa-access-denied-handler" title="B.1.3 <access-denied-handler>">the
+ namespace appendix</a> for more details.</p></div><div class="section" title="9.2.3 SavedRequests and the RequestCache Interface"><div class="titlepage"><div><div><h3 class="title"><a name="request-caching"></a>9.2.3 <code class="interfacename">SavedRequest</code>s and the <code class="interfacename">RequestCache</code> Interface</h3></div></div></div><p>Another of <code class="classname">ExceptionTranslationFilter</code>'s responsibilities is
+ to save the current request before invoking the <code class="interfacename">AuthenticationEntryPoint</code>.
+ This allows the request to be restored after the use has authenticated (see previous overview
+ of <a class="link" href="technical-overview.html#tech-intro-web-authentication" title="6.4 Authentication in a Web Application">web authentication</a>).
+ A typical example would be where the user logs in with a form, and is then redirected to the
+ original URL by the default <code class="classname">SavedRequestAwareAuthenticationSuccessHandler</code>
+ (see <a class="link" href="core-web-filters.html#form-login-flow-handling" title="9.4.1 Application Flow on Authentication Success and Failure">below</a>).
+ </p><p>The <code class="interfacename">RequestCache</code> encapsulates the functionality required for storing
+ and retrieving <code class="interfacename">HttpServletRequest</code> instances. By default
+ the <code class="classname">HttpSessionRequestCache</code> is used, which stores the request
+ in the <code class="interfacename">HttpSession</code>. The <code class="classname">RequestCacheFilter</code>
+ has the job of actually restoring the saved request from the cache when the user is redirected to
+ the original URL.
+ </p><p>Under normal circumstances, you shouldn't need to modify any of this functionality, but the
+ saved-request handling is a <span class="quote">“<span class="quote">best-effort</span>”</span> approach and there may be situations which
+ the default configuration isn't able to handle. The use of these interfaces makes it fully pluggable
+ from Spring Security 3.0 onwards.
+ </p></div></div><div class="section" title="9.3 SecurityContextPersistenceFilter"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="security-context-persistence-filter"></a>9.3 <code class="classname">SecurityContextPersistenceFilter</code></h2></div></div></div><p> We covered the purpose of this all-important filter in the <a class="link" href="technical-overview.html#tech-intro-sec-context-persistence" title="6.4.4 Storing the SecurityContext between requests">Technical Overview</a> chapter so
+ you might want to re-read that section at this point. Let's first take a look at how you
+ would configure it for use with a <code class="classname">FilterChainProxy</code>. A basic
configuration only requires the bean itself </p><pre class="programlisting">
-<bean id="securityContextPersistenceFilter"
-class="org.springframework.security.web.context.SecurityContextPersistenceFilter"/>
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"securityContextPersistenceFilter"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.context.SecurityContextPersistenceFilter"</span><span class="hl-tag">/></span>
</pre><p> As we saw previously, this filter has two main tasks. It is responsible for
storage of the <code class="classname">SecurityContext</code> contents between HTTP requests and
for clearing the <code class="classname">SecurityContextHolder</code> when a request is
@@ -150,7 +164,7 @@ class="org.springframework.security.web.context.SecurityContextPersistenceFilter
stored is essential, as it might otherwise be possible for a thread to be replaced into
the servlet container's thread pool, with the security context for a particular user
still attached. This thread might then be used at a later stage, performing operations
- with the wrong credentials. </p><div class="section" title="8.3.1 SecurityContextRepository"><div class="titlepage"><div><div><h3 class="title"><a name="security-context-repository"></a>8.3.1 <code class="interfacename">SecurityContextRepository</code></h3></div></div></div><p>From Spring Security 3.0, the job of loading and storing the security context is
+ with the wrong credentials. </p><div class="section" title="9.3.1 SecurityContextRepository"><div class="titlepage"><div><div><h3 class="title"><a name="security-context-repository"></a>9.3.1 <code class="interfacename">SecurityContextRepository</code></h3></div></div></div><p>From Spring Security 3.0, the job of loading and storing the security context is
now delegated to a separate strategy interface:
</p><pre class="programlisting">
<span class="hl-keyword">public</span> <span class="hl-keyword">interface</span> SecurityContextRepository {
@@ -162,86 +176,87 @@ class="org.springframework.security.web.context.SecurityContextPersistenceFilter
The <code class="classname">HttpRequestResponseHolder</code> is simply a container for the
incoming request and response objects, allowing the implementation to replace these
with wrapper classes. The returned contents will be passed to the filter chain. </p><p> The default implementation is
- <code class="classname">HttpSessionSecurityContextRepository</code>, which stores the
- security context as an <code class="interfacename">HttpSession</code> attribute <sup>[<a name="d0e3276" href="#ftn.d0e3276" class="footnote">9</a>]</sup>. The most important configuration parameter for this implementation is
+ <code class="classname">HttpSessionSecurityContextRepository</code>, which stores the
+ security context as an <code class="interfacename">HttpSession</code> attribute <sup>[<a name="d0e3831" href="#ftn.d0e3831" class="footnote">16</a>]</sup>. The most important configuration parameter for this implementation is
the <code class="literal">allowSessionCreation</code> property, which defaults to
- <code class="literal">true</code>, thus allowing the class to create a session if it needs
- one to store the security context for an authenticated user (it won't create one
- unless authentication has taken place and the contents of the security context have
+ <code class="literal">true</code>, thus allowing the class to create a session if it needs one
+ to store the security context for an authenticated user (it won't create one unless
+ authentication has taken place and the contents of the security context have
changed). If you don't want a session to be created, then you can set this property
to <code class="literal">false</code>: </p><pre class="programlisting">
<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"securityContextPersistenceFilter"</span>
-<span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.context.SecurityContextPersistenceFilter"</span><span class="hl-tag">></span>
-<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">'securityContextRepository'</span><span class="hl-tag">></span>
-<span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">'org.springframework.security.web.context.HttpSessionSecurityContextRepository'</span><span class="hl-tag">></span>
- <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">'allowSessionCreation'</span> <span class="hl-attribute">value</span>=<span class="hl-value">'false'</span><span class="hl-tag"> /></span>
-<span class="hl-tag"></bean></span>
-<span class="hl-tag"></property></span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.context.SecurityContextPersistenceFilter"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">'securityContextRepository'</span><span class="hl-tag">></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">'org.springframework.security.web.context.HttpSessionSecurityContextRepository'</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">'allowSessionCreation'</span> <span class="hl-attribute">value</span>=<span class="hl-value">'false'</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"></bean></span>
+ <span class="hl-tag"></property></span>
<span class="hl-tag"></bean></span>
-</pre><p> Alternatively you could provide a null implementation of the
- <code class="interfacename">SecurityContextRepository</code> interface, which will
- prevent the security context from being stored, even if a session has already been
- created during the request. </p></div></div><div class="section" title="8.4 UsernamePasswordAuthenticationFilter"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="form-login-filter"></a>8.4 <code class="classname">UsernamePasswordAuthenticationFilter</code></h2></div></div></div><p>We've now seen the three main filters which are always present in a Spring Security
+</pre><p> Alternatively you could provide an instance of
+ <code class="classname">NullSecurityContextRepository</code>, a <span class="quote">“<span class="quote"><a class="link" href="http://en.wikipedia.org/wiki/Null_Object_pattern" target="_top">null object</a></span>”</span>
+ implementation, which will prevent the security context from being stored, even if a
+ session has already been created during the request. </p></div></div><div class="section" title="9.4 UsernamePasswordAuthenticationFilter"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="form-login-filter"></a>9.4 <code class="classname">UsernamePasswordAuthenticationFilter</code></h2></div></div></div><p>We've now seen the three main filters which are always present in a Spring Security
web configuration. These are also the three which are automatically created by the
namespace <code class="literal"><http></code> element and cannot be substituted with
alternatives. The only thing that's missing now is an actual authentication mechanism,
something that will allow a user to authenticate. This filter is the most commonly used
- authentication filter and the one that is most often customized <sup>[<a name="d0e3310" href="#ftn.d0e3310" class="footnote">10</a>]</sup>. It also provides the implementation used by the
- <code class="literal"><form-login></code> element from the namespace. There are three
- stages required to configure it. </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>Configure a <code class="classname">LoginUrlAuthenticationEntryPoint</code> with
- the URL of the login page, just as we did above, and set it on the
- <code class="classname">ExceptionTranslationFilter</code>. </p></li><li class="listitem"><p>Implement the login page (using a JSP or MVC controller).</p></li><li class="listitem"><p>Configure an instance of
- <code class="classname">UsernamePasswordAuthenticationFilter</code> in the
- application context</p></li><li class="listitem"><p>Add the filter bean to your filter chain proxy (making sure you pay
- attention to the order). </p></li></ol></div><p> The login form simply contains <code class="literal">j_username</code> and
- <code class="literal">j_password</code> input fields, and posts to the URL that is monitored
- by the filter (by default this is <code class="literal">/j_spring_security_check</code>). The
- basic filter configuration looks something like this: </p><pre class="programlisting">
-<bean id="authenticationFilter" class=
-"org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
- <property name="authenticationManager" ref="authenticationManager"/>
- <property name="filterProcessesUrl" value="/j_spring_security_check"/>
-</bean>
- </pre><div class="section" title="8.4.1 Application Flow on Authentication Success and Failure"><div class="titlepage"><div><div><h3 class="title"><a name="form-login-flow-handling"></a>8.4.1 Application Flow on Authentication Success and Failure</h3></div></div></div><p> The filter calls the configured
- <code class="interfacename">AuthenticationManager</code> to process each
- authentication request. The destination following a successful authentication or an
- authentication failure is controlled by the
- <code class="interfacename">AuthenticationSuccessHandler</code> and
- <code class="interfacename">AuthenticationFailureHandler</code> strategy interfaces,
+ authentication filter and the one that is most often customized <sup>[<a name="d0e3869" href="#ftn.d0e3869" class="footnote">17</a>]</sup>. It also provides the implementation used by the
+ <code class="literal"><form-login></code> element from the namespace. There are three stages
+ required to configure it. </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>Configure a <code class="classname">LoginUrlAuthenticationEntryPoint</code> with the
+ URL of the login page, just as we did above, and set it on the
+ <code class="classname">ExceptionTranslationFilter</code>. </p></li><li class="listitem"><p>Implement the login page (using a JSP or MVC controller).</p></li><li class="listitem"><p>Configure an instance of
+ <code class="classname">UsernamePasswordAuthenticationFilter</code> in the application
+ context</p></li><li class="listitem"><p>Add the filter bean to your filter chain proxy (making sure you pay attention
+ to the order). </p></li></ol></div><p> The login form simply contains <code class="literal">j_username</code> and
+ <code class="literal">j_password</code> input fields, and posts to the URL that is monitored by
+ the filter (by default this is <code class="literal">/j_spring_security_check</code>). The basic
+ filter configuration looks something like this: </p><pre class="programlisting">
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"authenticationFilter"</span> <span class="hl-attribute">class</span>=
+<span class="hl-value">"org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"authenticationManager"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"filterProcessesUrl"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"/j_spring_security_check"</span><span class="hl-tag">/></span>
+<span class="hl-tag"></bean></span>
+ </pre><div class="section" title="9.4.1 Application Flow on Authentication Success and Failure"><div class="titlepage"><div><div><h3 class="title"><a name="form-login-flow-handling"></a>9.4.1 Application Flow on Authentication Success and Failure</h3></div></div></div><p> The filter calls the configured
+ <code class="interfacename">AuthenticationManager</code> to process each authentication
+ request. The destination following a successful authentication or an authentication
+ failure is controlled by the
+ <code class="interfacename">AuthenticationSuccessHandler</code> and
+ <code class="interfacename">AuthenticationFailureHandler</code> strategy interfaces,
respectively. The filter has properties which allow you to set these so you can
- customize the behaviour completely <sup>[<a name="d0e3372" href="#ftn.d0e3372" class="footnote">11</a>]</sup>. Some standard implementations are supplied such as
- <code class="classname">SimpleUrlAuthenticationSuccessHandler</code>,
- <code class="classname">SavedRequestAwareAuthenticationSuccessHandler</code>,
- <code class="classname">SimpleUrlAuthenticationFailureHandler</code> and
- <code class="classname">ExceptionMappingAuthenticationFailureHandler</code>. Have a look
- at the Javadoc for these classes to see how they work. </p><p>If authentication is successful, the resulting
- <code class="interfacename">Authentication</code> object will be placed into the
- <code class="classname">SecurityContextHolder</code>. The configured
- <code class="interfacename">AuthenticationSuccessHandler</code> will then be called
- to either redirect or forward the user to the appropriate destination. By default a
- <code class="classname">SavedRequestAwareAuthenticationSuccessHandler</code> is used,
- which means that the user will be redirected to the original destination they
- requested before they were asked to login. </p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p> The <code class="classname">ExceptionTranslationFilter</code> caches the original
- request a user makes. When the user authenticates, the request handler makes
- use of this cached request to obtain the original URL and redirect to it.
- The original request is then rebuilt and used as an alternative. </p></td></tr></table></div><p> If authentication fails, the configured
- <code class="interfacename">AuthenticationFailureHandler</code> will be invoked.
- </p></div></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e3217" href="#d0e3217" class="para">8</a>] </sup>We use a forward so that the SecurityContextHolder still contains details
- of the principal, which may be useful for displaying to the user. In old
- releases of Spring Security we relied upon the servlet container to handle a
- 403 error message, which lacked this useful contextual information.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e3276" href="#d0e3276" class="para">9</a>] </sup>In Spring Security 2.0 and earlier, this filter was called
- <code class="classname">HttpSessionContextIntegrationFilter</code> and performed
- all the work of storing the context was performed by the filter itself. If
- you were familiar with this class, then most of the configuration options
- which were available can now be found on
- <code class="classname">HttpSessionSecurityContextRepository</code>. </p></div><div class="footnote"><p><sup>[<a name="ftn.d0e3310" href="#d0e3310" class="para">10</a>] </sup>For historical reasons, prior to Spring Security 3.0, this filter was called
- <code class="classname">AuthenticationProcessingFilter</code> and the entry point
- was called <code class="classname">AuthenticationProcessingFilterEntryPoint</code>.
- Since the framework now supports many different forms of authentication, they
- have both been given more specific names in 3.0.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e3372" href="#d0e3372" class="para">11</a>] </sup>In versions prior to 3.0, the application flow at this point had evolved
- to a stage was controlled by a mix of properties on this class and strategy
- plugins. The decision was made for 3.0 to refactor the code to make these
- two strategies entirely responsible. </p></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
+ customize the behaviour completely <sup>[<a name="d0e3931" href="#ftn.d0e3931" class="footnote">18</a>]</sup>. Some standard implementations are supplied such as
+ <code class="classname">SimpleUrlAuthenticationSuccessHandler</code>,
+ <code class="classname">SavedRequestAwareAuthenticationSuccessHandler</code>,
+ <code class="classname">SimpleUrlAuthenticationFailureHandler</code> and
+ <code class="classname">ExceptionMappingAuthenticationFailureHandler</code>. Have a look at
+ the Javadoc for these classes and also for <code class="classname">AbstractAuthenticationProcessingFilter</code>
+ to get an overview of how they work and the supported features.
+ </p><p>If authentication is successful, the resulting
+ <code class="interfacename">Authentication</code> object will be placed into the
+ <code class="classname">SecurityContextHolder</code>. The configured
+ <code class="interfacename">AuthenticationSuccessHandler</code> will then be called to
+ either redirect or forward the user to the appropriate destination. By default a
+ <code class="classname">SavedRequestAwareAuthenticationSuccessHandler</code> is used, which
+ means that the user will be redirected to the original destination they requested
+ before they were asked to login. </p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p> The <code class="classname">ExceptionTranslationFilter</code> caches the original
+ request a user makes. When the user authenticates, the request handler makes use
+ of this cached request to obtain the original URL and redirect to it. The
+ original request is then rebuilt and used as an alternative. </p></td></tr></table></div><p> If authentication fails, the configured
+ <code class="interfacename">AuthenticationFailureHandler</code> will be invoked. </p></div></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e3725" href="#d0e3725" class="para">15</a>] </sup>We use a forward so that the SecurityContextHolder still contains details of
+ the principal, which may be useful for displaying to the user. In old releases
+ of Spring Security we relied upon the servlet container to handle a 403 error
+ message, which lacked this useful contextual information.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e3831" href="#d0e3831" class="para">16</a>] </sup>In Spring Security 2.0 and earlier, this filter was called
+ <code class="classname">HttpSessionContextIntegrationFilter</code> and performed all the
+ work of storing the context was performed by the filter itself. If you were
+ familiar with this class, then most of the configuration options which were
+ available can now be found on
+ <code class="classname">HttpSessionSecurityContextRepository</code>. </p></div><div class="footnote"><p><sup>[<a name="ftn.d0e3869" href="#d0e3869" class="para">17</a>] </sup>For historical reasons, prior to Spring Security 3.0, this filter was called
+ <code class="classname">AuthenticationProcessingFilter</code> and the entry point was called
+ <code class="classname">AuthenticationProcessingFilterEntryPoint</code>. Since the framework
+ now supports many different forms of authentication, they have both been given more
+ specific names in 3.0.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e3931" href="#d0e3931" class="para">18</a>] </sup>In versions prior to 3.0, the application flow at this point had evolved to a
+ stage was controlled by a mix of properties on this class and strategy plugins.
+ The decision was made for 3.0 to refactor the code to make these two strategies
+ entirely responsible. </p></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
- </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="security-filter-chain.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="web-app-security.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="basic.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">7. The Security Filter Chain </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 9. Basic and Digest Authentication</td></tr></table></div></body></html>
\ No newline at end of file
+ </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="security-filter-chain.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="web-app-security.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="basic.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">8. The Security Filter Chain </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 10. Basic and Digest Authentication</td></tr></table></div></body></html>
\ No newline at end of file
diff --git a/docs/reference/domain-acls.html b/docs/reference/domain-acls.html
index 0bf00cb..7479f96 100644
--- a/docs/reference/domain-acls.html
+++ b/docs/reference/domain-acls.html
@@ -1,6 +1,6 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>16. Domain Object Security (ACLs)</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="advanced-topics.html" title="Part V. Additional Topics"><link rel="prev" href="advanced-topics.html" title="Part V. Additional Topics"><link rel="next" href="preauth.html" title="17. Pre-Authentication Scenarios"><!--Begin Google Analytics code--><script type="text/javascript">
+ <title>17. Domain Object Security (ACLs)</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="advanced-topics.html" title="Part V. Additional Topics"><link rel="prev" href="advanced-topics.html" title="Part V. Additional Topics"><link rel="next" href="preauth.html" title="18. Pre-Authentication Scenarios"><!--Begin Google Analytics code--><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
@@ -8,60 +8,60 @@
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
- </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">16. Domain Object Security (ACLs)</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="advanced-topics.html">Prev</a> </td><th width="60%" align="center">Part V. Additional Topics</th><td width="20%" align="right"> <a accesskey="n" href="preauth.html">Next</a></td></tr></table><hr></div><div class="chapter" title="16. Domain Object Security (ACLs)"><div class="titlepage"><div><div><h1 class="title"><a name="domain-acls"></a>Domain Object Security (ACLs)</h1></div></div></div><div class="section" title="16.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="domain-acls-overview"></a>16.1 Overview</h2></div></div></div><p>Complex applications often will find the need to define access permissions not simply
+ </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">17. Domain Object Security (ACLs)</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="advanced-topics.html">Prev</a> </td><th width="60%" align="center">Part V. Additional Topics</th><td width="20%" align="right"> <a accesskey="n" href="preauth.html">Next</a></td></tr></table><hr></div><div class="chapter" title="17. Domain Object Security (ACLs)"><div class="titlepage"><div><div><h1 class="title"><a name="domain-acls"></a>Domain Object Security (ACLs)</h1></div></div></div><div class="section" title="17.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="domain-acls-overview"></a>17.1 Overview</h2></div></div></div><p>Complex applications often will find the need to define access permissions not simply
at a web request or method invocation level. Instead, security decisions need to
comprise both who (<code class="interfacename">Authentication</code>), where
- (<code class="classname">MethodInvocation</code>) and what (<code class="literal">SomeDomainObject</code>). In
- other words, authorization decisions also need to consider the actual domain object
- instance subject of a method invocation.</p><p>Imagine you're designing an application for a pet clinic. There will be two main
+ (<code class="classname">MethodInvocation</code>) and what
+ (<code class="literal">SomeDomainObject</code>). In other words, authorization decisions also need
+ to consider the actual domain object instance subject of a method invocation.</p><p>Imagine you're designing an application for a pet clinic. There will be two main
groups of users of your Spring-based application: staff of the pet clinic, as well as
the pet clinic's customers. The staff will have access to all of the data, whilst your
customers will only be able to see their own customer records. To make it a little more
interesting, your customers can allow other users to see their customer records, such as
their "puppy preschool" mentor or president of their local "Pony Club". Using Spring
Security as the foundation, you have several approaches that can be used:</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>Write your business methods to enforce the security. You could consult a
- collection within the <code class="literal">Customer</code> domain object instance to
- determine which users have access. By using the
- <code class="literal">SecurityContextHolder.getContext().getAuthentication()</code>,
- you'll be able to access the <code class="interfacename">Authentication</code>
- object.</p></li><li class="listitem"><p>Write an <code class="interfacename">AccessDecisionVoter</code> to enforce the security
- from the <code class="literal">GrantedAuthority[]</code>s stored in the
- <code class="interfacename">Authentication</code> object. This would mean your
- <code class="interfacename">AuthenticationManager</code> would need to populate the
- <code class="interfacename">Authentication</code> with custom
- <code class="interfacename">GrantedAuthority</code>[]s representing each of the
- <code class="literal">Customer</code> domain object instances the principal has
- access to.</p></li><li class="listitem"><p>Write an <code class="interfacename">AccessDecisionVoter</code> to enforce the security
- and open the target <code class="literal">Customer</code> domain object directly. This
- would mean your voter needs access to a DAO that allows it to retrieve the
- <code class="literal">Customer</code> object. It would then access the
- <code class="literal">Customer</code> object's collection of approved users and
- make the appropriate decision.</p></li></ol></div><p>Each one of these approaches is perfectly legitimate. However, the first couples your
+ collection within the <code class="literal">Customer</code> domain object instance to
+ determine which users have access. By using the
+ <code class="literal">SecurityContextHolder.getContext().getAuthentication()</code>,
+ you'll be able to access the <code class="interfacename">Authentication</code>
+ object.</p></li><li class="listitem"><p>Write an <code class="interfacename">AccessDecisionVoter</code> to enforce the
+ security from the <code class="literal">GrantedAuthority[]</code>s stored in the
+ <code class="interfacename">Authentication</code> object. This would mean your
+ <code class="interfacename">AuthenticationManager</code> would need to populate the
+ <code class="interfacename">Authentication</code> with custom
+ <code class="interfacename">GrantedAuthority</code>[]s representing each of the
+ <code class="literal">Customer</code> domain object instances the principal has access
+ to.</p></li><li class="listitem"><p>Write an <code class="interfacename">AccessDecisionVoter</code> to enforce the
+ security and open the target <code class="literal">Customer</code> domain object directly.
+ This would mean your voter needs access to a DAO that allows it to retrieve the
+ <code class="literal">Customer</code> object. It would then access the
+ <code class="literal">Customer</code> object's collection of approved users and make the
+ appropriate decision.</p></li></ol></div><p>Each one of these approaches is perfectly legitimate. However, the first couples your
authorization checking to your business code. The main problems with this include the
enhanced difficulty of unit testing and the fact it would be more difficult to reuse the
- <code class="literal">Customer</code> authorization logic elsewhere. Obtaining the
- <code class="literal">GrantedAuthority[]</code>s from the <code class="interfacename">Authentication</code>
- object is also fine, but will not scale to large numbers of
- <code class="literal">Customer</code>s. If a user might be able to access 5,000
+ <code class="literal">Customer</code> authorization logic elsewhere. Obtaining the
+ <code class="literal">GrantedAuthority[]</code>s from the
+ <code class="interfacename">Authentication</code> object is also fine, but will not scale to
+ large numbers of <code class="literal">Customer</code>s. If a user might be able to access 5,000
<code class="literal">Customer</code>s (unlikely in this case, but imagine if it were a popular
vet for a large Pony Club!) the amount of memory consumed and time required to construct
- the <code class="interfacename">Authentication</code> object would be undesirable. The final method,
- opening the <code class="literal">Customer</code> directly from external code, is probably the
- best of the three. It achieves separation of concerns, and doesn't misuse memory or CPU
- cycles, but it is still inefficient in that both the
- <code class="interfacename">AccessDecisionVoter</code> and the eventual business method itself will
- perform a call to the DAO responsible for retrieving the <code class="literal">Customer</code>
- object. Two accesses per method invocation is clearly undesirable. In addition, with
- every approach listed you'll need to write your own access control list (ACL)
- persistence and business logic from scratch.</p><p>Fortunately, there is another alternative, which we'll talk about below.</p></div><div class="section" title="16.2 Key Concepts"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="domain-acls-key-concepts"></a>16.2 Key Concepts</h2></div></div></div><p>Spring Security's ACL services are shipped in the
+ the <code class="interfacename">Authentication</code> object would be undesirable. The final
+ method, opening the <code class="literal">Customer</code> directly from external code, is probably
+ the best of the three. It achieves separation of concerns, and doesn't misuse memory or
+ CPU cycles, but it is still inefficient in that both the
+ <code class="interfacename">AccessDecisionVoter</code> and the eventual business method
+ itself will perform a call to the DAO responsible for retrieving the
+ <code class="literal">Customer</code> object. Two accesses per method invocation is clearly
+ undesirable. In addition, with every approach listed you'll need to write your own
+ access control list (ACL) persistence and business logic from scratch.</p><p>Fortunately, there is another alternative, which we'll talk about below.</p></div><div class="section" title="17.2 Key Concepts"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="domain-acls-key-concepts"></a>17.2 Key Concepts</h2></div></div></div><p>Spring Security's ACL services are shipped in the
<code class="literal">spring-security-acl-xxx.jar</code>. You will need to add this JAR to your
classpath to use Spring Security's domain object instance security capabilities.</p><p>Spring Security's domain object instance security capabilities centre on the concept
of an access control list (ACL). Every domain object instance in your system has its own
ACL, and the ACL records details of who can and can't work with that domain object. With
this in mind, Spring Security delivers three main ACL-related capabilities to your application:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>A way of efficiently retrieving ACL entries for all of your domain objects
- (and modifying those ACLs)</p></li><li class="listitem"><p>A way of ensuring a given principal is permitted to work with your
- objects, before methods are called</p></li><li class="listitem"><p>A way of ensuring a given principal is permitted to work with your objects
- (or something they return), after methods are called</p></li></ul></div><p>As indicated by the first bullet point, one of the main capabilities of the Spring
+ (and modifying those ACLs)</p></li><li class="listitem"><p>A way of ensuring a given principal is permitted to work with your objects,
+ before methods are called</p></li><li class="listitem"><p>A way of ensuring a given principal is permitted to work with your objects (or
+ something they return), after methods are called</p></li></ul></div><p>As indicated by the first bullet point, one of the main capabilities of the Spring
Security ACL module is providing a high-performance way of retrieving ACLs. This ACL
repository capability is extremely important, because every domain object instance in
your system might have several access control entries, and each ACL might inherit from
@@ -73,35 +73,32 @@
updating.</p><p>Given databases are central to the operation of the ACL module, let's explore the four
main tables used by default in the implementation. The tables are presented below in
order of size in a typical Spring Security ACL deployment, with the table with the most
- rows listed last:</p><p>
- </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>ACL_SID allows us to uniquely identify any principal or authority in the
- system ("SID" stands for "security identity"). The only columns are the ID,
- a textual representation of the SID, and a flag to indicate whether the
- textual representation refers to a principal name or a
- <code class="interfacename">GrantedAuthority</code>. Thus, there is a single row for
- each unique principal or <code class="interfacename">GrantedAuthority</code>. When used in
- the context of receiving a permission, a SID is generally called a
- "recipient".</p></li><li class="listitem"><p>ACL_CLASS allows us to uniquely identify any domain object class in the
- system. The only columns are the ID and the Java class name. Thus, there is
- a single row for each unique Class we wish to store ACL permissions
- for.</p></li><li class="listitem"><p>ACL_OBJECT_IDENTITY stores information for each unique domain object
- instance in the system. Columns include the ID, a foreign key to the
- ACL_CLASS table, a unique identifier so we know which ACL_CLASS instance
- we're providing information for, the parent, a foreign key to the ACL_SID
- table to represent the owner of the domain object instance, and whether we
- allow ACL entries to inherit from any parent ACL. We have a single row for
- every domain object instance we're storing ACL permissions for.</p></li><li class="listitem"><p>Finally, ACL_ENTRY stores the individual permissions assigned to each
- recipient. Columns include a foreign key to the ACL_OBJECT_IDENTITY, the
- recipient (ie a foreign key to ACL_SID), whether we'll be auditing or not,
- and the integer bit mask that represents the actual permission being granted
- or denied. We have a single row for every recipient that receives a
- permission to work with a domain object.</p></li></ul></div><p>
- </p><p>As mentioned in the last paragraph, the ACL system uses integer bit masking. Don't
+ rows listed last:</p><p> </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>ACL_SID allows us to uniquely identify any principal or authority in the
+ system ("SID" stands for "security identity"). The only columns are the ID, a
+ textual representation of the SID, and a flag to indicate whether the textual
+ representation refers to a principal name or a
+ <code class="interfacename">GrantedAuthority</code>. Thus, there is a single row for
+ each unique principal or <code class="interfacename">GrantedAuthority</code>. When
+ used in the context of receiving a permission, a SID is generally called a
+ "recipient".</p></li><li class="listitem"><p>ACL_CLASS allows us to uniquely identify any domain object class in the
+ system. The only columns are the ID and the Java class name. Thus, there is a
+ single row for each unique Class we wish to store ACL permissions for.</p></li><li class="listitem"><p>ACL_OBJECT_IDENTITY stores information for each unique domain object instance
+ in the system. Columns include the ID, a foreign key to the ACL_CLASS table, a
+ unique identifier so we know which ACL_CLASS instance we're providing
+ information for, the parent, a foreign key to the ACL_SID table to represent the
+ owner of the domain object instance, and whether we allow ACL entries to inherit
+ from any parent ACL. We have a single row for every domain object instance we're
+ storing ACL permissions for.</p></li><li class="listitem"><p>Finally, ACL_ENTRY stores the individual permissions assigned to each
+ recipient. Columns include a foreign key to the ACL_OBJECT_IDENTITY, the
+ recipient (ie a foreign key to ACL_SID), whether we'll be auditing or not, and
+ the integer bit mask that represents the actual permission being granted or
+ denied. We have a single row for every recipient that receives a permission to
+ work with a domain object.</p></li></ul></div><p> </p><p>As mentioned in the last paragraph, the ACL system uses integer bit masking. Don't
worry, you need not be aware of the finer points of bit shifting to use the ACL system,
but suffice to say that we have 32 bits we can switch on or off. Each of these bits
represents a permission, and by default the permissions are read (bit 0), write (bit 1),
create (bit 2), delete (bit 3) and administer (bit 4). It's easy to implement your own
- <code class="literal">Permission</code> instance if you wish to use other permissions, and the
+ <code class="literal">Permission</code> instance if you wish to use other permissions, and the
remainder of the ACL framework will operate without knowledge of your extensions.</p><p>It is important to understand that the number of domain objects in your system has
absolutely no bearing on the fact we've chosen to use integer bit masking. Whilst you
have 32 bits available for permissions, you could have billions of domain object
@@ -111,29 +108,29 @@
looks like at a table structure, let's explore the key interfaces. The key interfaces
are:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc" compact><li class="listitem"><p><code class="literal">Acl</code>: Every domain object has one and only one
<code class="literal">Acl</code> object, which internally holds the
- <code class="literal">AccessControlEntry</code>s as well as knows the owner of the
- <code class="literal">Acl</code>. An Acl does not refer directly to the domain object,
- but instead to an <code class="literal">ObjectIdentity</code>. The <code class="literal">Acl</code>
- is stored in the ACL_OBJECT_IDENTITY table.</p></li><li class="listitem"><p><code class="literal">AccessControlEntry</code>: An <code class="literal">Acl</code> holds
+ <code class="literal">AccessControlEntry</code>s as well as knows the owner of the
+ <code class="literal">Acl</code>. An Acl does not refer directly to the domain object, but
+ instead to an <code class="literal">ObjectIdentity</code>. The <code class="literal">Acl</code> is
+ stored in the ACL_OBJECT_IDENTITY table.</p></li><li class="listitem"><p><code class="literal">AccessControlEntry</code>: An <code class="literal">Acl</code> holds
multiple <code class="literal">AccessControlEntry</code>s, which are often abbreviated as
ACEs in the framework. Each ACE refers to a specific tuple of
- <code class="literal">Permission</code>, <code class="literal">Sid</code> and
+ <code class="literal">Permission</code>, <code class="literal">Sid</code> and
<code class="literal">Acl</code>. An ACE can also be granting or non-granting and contain
audit settings. The ACE is stored in the ACL_ENTRY table.</p></li><li class="listitem"><p><code class="literal">Permission</code>: A permission represents a particular immutable
bit mask, and offers convenience functions for bit masking and outputting
information. The basic permissions presented above (bits 0 through 4) are
contained in the <code class="literal">BasePermission</code> class.</p></li><li class="listitem"><p><code class="literal">Sid</code>: The ACL module needs to refer to principals and
- <code class="literal">GrantedAuthority[]</code>s. A level of indirection is provided
- by the <code class="literal">Sid</code> interface, which is an abbreviation of "security
+ <code class="literal">GrantedAuthority[]</code>s. A level of indirection is provided by
+ the <code class="literal">Sid</code> interface, which is an abbreviation of "security
identity". Common classes include <code class="literal">PrincipalSid</code> (to represent
- the principal inside an <code class="interfacename">Authentication</code> object) and
- <code class="literal">GrantedAuthoritySid</code>. The security identity information is
+ the principal inside an <code class="interfacename">Authentication</code> object)
+ and <code class="literal">GrantedAuthoritySid</code>. The security identity information is
stored in the ACL_SID table.</p></li><li class="listitem"><p><code class="literal">ObjectIdentity</code>: Each domain object is represented
internally within the ACL module by an <code class="literal">ObjectIdentity</code>. The
default implementation is called <code class="literal">ObjectIdentityImpl</code>.</p></li><li class="listitem"><p><code class="literal">AclService</code>: Retrieves the <code class="literal">Acl</code> applicable
for a given <code class="literal">ObjectIdentity</code>. In the included implementation
- (<code class="literal">JdbcAclService</code>), retrieval operations are delegated to a
- <code class="literal">LookupStrategy</code>. The <code class="literal">LookupStrategy</code>
+ (<code class="literal">JdbcAclService</code>), retrieval operations are delegated to a
+ <code class="literal">LookupStrategy</code>. The <code class="literal">LookupStrategy</code>
provides a highly optimized strategy for retrieving ACL information, using
batched retrievals <code class="literal">(BasicLookupStrategy</code>) and supporting
custom implementations that leverage materialized views, hierarchical queries
@@ -144,19 +141,18 @@
the system had been successfully tested using Hypersonic SQL, PostgreSQL, Microsoft SQL
Server and Oracle.</p><p>Two samples ship with Spring Security that demonstrate the ACL module. The first is
the Contacts Sample, and the other is the Document Management System (DMS) Sample. We
- suggest taking a look over these for examples.</p></div><div class="section" title="16.3 Getting Started"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="domain-acls-getting-started"></a>16.3 Getting Started</h2></div></div></div><p>To get starting using Spring Security's ACL capability, you will need to store your
+ suggest taking a look over these for examples.</p></div><div class="section" title="17.3 Getting Started"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="domain-acls-getting-started"></a>17.3 Getting Started</h2></div></div></div><p>To get starting using Spring Security's ACL capability, you will need to store your
ACL information somewhere. This necessitates the instantiation of a
<code class="literal">DataSource</code> using Spring. The <code class="literal">DataSource</code> is then
injected into a <code class="literal">JdbcMutableAclService</code> and
- <code class="literal">BasicLookupStrategy</code> instance. The latter provides
- high-performance ACL retrieval capabilities, and the former provides mutator
- capabilities. Refer to one of the samples that ship with Spring Security for an example
- configuration. You'll also need to populate the database with the four ACL-specific
- tables listed in the last section (refer to the ACL samples for the appropriate SQL
- statements).</p><p>Once you've created the required schema and instantiated
- <code class="literal">JdbcMutableAclService</code>, you'll next need to ensure your domain
- model supports interoperability with the Spring Security ACL package. Hopefully
- <code class="literal">ObjectIdentityImpl</code> will prove sufficient, as it provides a large
+ <code class="literal">BasicLookupStrategy</code> instance. The latter provides high-performance
+ ACL retrieval capabilities, and the former provides mutator capabilities. Refer to one
+ of the samples that ship with Spring Security for an example configuration. You'll also
+ need to populate the database with the four ACL-specific tables listed in the last
+ section (refer to the ACL samples for the appropriate SQL statements).</p><p>Once you've created the required schema and instantiated
+ <code class="literal">JdbcMutableAclService</code>, you'll next need to ensure your domain model
+ supports interoperability with the Spring Security ACL package. Hopefully
+ <code class="literal">ObjectIdentityImpl</code> will prove sufficient, as it provides a large
number of ways in which it can be used. Most people will have domain objects that
contain a <code class="literal">public Serializable getId()</code> method. If the return type is
long, or compatible with long (eg an int), you will find you need not give further
@@ -167,20 +163,20 @@
compatible with all database sequences, the most common identifier data type, and are of
sufficient length to accommodate all common usage scenarios.</p><p>The following fragment of code shows how to create an <code class="literal">Acl</code>, or
modify an existing
- <code class="literal">Acl</code>:</p><pre class="programlisting">// Prepare the information we'd like in our access control entry (ACE)
-ObjectIdentity oi = new ObjectIdentityImpl(Foo.class, new Long(44));
-Sid sid = new PrincipalSid("Samantha");
+ <code class="literal">Acl</code>:</p><pre class="programlisting"><span class="hl-comment">// Prepare the information we'd like in our access control entry (ACE)</span>
+ObjectIdentity oi = <span class="hl-keyword">new</span> ObjectIdentityImpl(Foo.<span class="hl-keyword">class</span>, <span class="hl-keyword">new</span> Long(<span class="hl-number">44</span>));
+Sid sid = <span class="hl-keyword">new</span> PrincipalSid(<span class="hl-string">"Samantha"</span>);
Permission p = BasePermission.ADMINISTRATION;
-// Create or update the relevant ACL
+<span class="hl-comment">// Create or update the relevant ACL</span>
MutableAcl acl = null;
-try {
+<span class="hl-keyword">try</span> {
acl = (MutableAcl) aclService.readAclById(oi);
-} catch (NotFoundException nfe) {
+} <span class="hl-keyword">catch</span> (NotFoundException nfe) {
acl = aclService.createAcl(oi);
}
-// Now grant some permissions via an access control entry (ACE)
+<span class="hl-comment">// Now grant some permissions via an access control entry (ACE)</span>
acl.insertAce(acl.getEntries().length, p, sid, true);
aclService.updateAcl(acl);
</pre><p>In the example above, we're retrieving the ACL associated with the "Foo" domain object
@@ -190,7 +186,8 @@ aclService.updateAcl(acl);
position in the Acl the new entry will be inserted. In the example above, we're just
putting the new ACE at the end of the existing ACEs. The final argument is a boolean
indicating whether the ACE is granting or denying. Most of the time it will be granting
- (true), but if it is denying (false), the permissions are effectively being blocked.</p><p>Spring Security does not provide any special integration to automatically create,
+ (true), but if it is denying (false), the permissions are effectively being
+ blocked.</p><p>Spring Security does not provide any special integration to automatically create,
update or delete ACLs as part of your DAO or repository operations. Instead, you will
need to write code like shown above for your individual domain objects. It's worth
considering using AOP on your services layer to automatically integrate the ACL
@@ -198,17 +195,17 @@ aclService.updateAcl(acl);
approach in the past.</p><p>Once you've used the above techniques to store some ACL information in the database,
the next step is to actually use the ACL information as part of authorization decision
logic. You have a number of choices here. You could write your own
- <code class="interfacename">AccessDecisionVoter</code> or <code class="literal">AfterInvocationProvider</code>
- that respectively fires before or after a method invocation. Such classes would use
- <code class="literal">AclService</code> to retrieve the relevant ACL and then call
- <code class="literal">Acl.isGranted(Permission[] permission, Sid[] sids, boolean
- administrativeMode)</code> to decide whether permission is granted or denied.
+ <code class="interfacename">AccessDecisionVoter</code> or
+ <code class="literal">AfterInvocationProvider</code> that respectively fires before or after a
+ method invocation. Such classes would use <code class="literal">AclService</code> to retrieve the
+ relevant ACL and then call <code class="literal">Acl.isGranted(Permission[] permission, Sid[] sids,
+ boolean administrativeMode)</code> to decide whether permission is granted or denied.
Alternately, you could use our <code class="literal">AclEntryVoter</code>,
- <code class="literal">AclEntryAfterInvocationProvider</code> or
- <code class="literal">AclEntryAfterInvocationCollectionFilteringProvider</code> classes. All
- of these classes provide a declarative-based approach to evaluating ACL information at
+ <code class="literal">AclEntryAfterInvocationProvider</code> or
+ <code class="literal">AclEntryAfterInvocationCollectionFilteringProvider</code> classes. All of
+ these classes provide a declarative-based approach to evaluating ACL information at
runtime, freeing you from needing to write any code. Please refer to the sample
applications to learn how to use these classes.</p></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
- </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="advanced-topics.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="advanced-topics.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="preauth.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Part V. Additional Topics </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 17. Pre-Authentication Scenarios</td></tr></table></div></body></html>
\ No newline at end of file
+ </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="advanced-topics.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="advanced-topics.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="preauth.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Part V. Additional Topics </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 18. Pre-Authentication Scenarios</td></tr></table></div></body></html>
\ No newline at end of file
diff --git a/docs/reference/el-access.html b/docs/reference/el-access.html
index 63401c3..d6e544b 100644
--- a/docs/reference/el-access.html
+++ b/docs/reference/el-access.html
@@ -1,6 +1,6 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>15. Expression-Based Access Control</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="authorization.html" title="Part IV. Authorization"><link rel="prev" href="secure-object-impls.html" title="14. Secure Object Implementations"><link rel="next" href="advanced-topics.html" title="Part V. Additional Topics"><!--Begin Google Analytics code--><script type="text/javascript">
+ <title>16. Expression-Based Access Control</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="authorization.html" title="Part IV. Authorization"><link rel="prev" href="secure-object-impls.html" title="15. Secure Object Implementations"><link rel="next" href="advanced-topics.html" title="Part V. Additional Topics"><!--Begin Google Analytics code--><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
@@ -8,83 +8,85 @@
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
- </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">15. Expression-Based Access Control</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="secure-object-impls.html">Prev</a> </td><th width="60%" align="center">Part IV. Authorization</th><td width="20%" align="right"> <a accesskey="n" href="advanced-topics.html">Next</a></td></tr></table><hr></div><div class="chapter" title="15. Expression-Based Access Control"><div class="titlepage"><div><div><h2 class="title"><a name="el-access"></a>15. Expression-Based Access Control</h2></div></div></div><p> Spring Security 3.0 introduced the ability to use Spring EL expressions as an
+ </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">16. Expression-Based Access Control</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="secure-object-impls.html">Prev</a> </td><th width="60%" align="center">Part IV. Authorization</th><td width="20%" align="right"> <a accesskey="n" href="advanced-topics.html">Next</a></td></tr></table><hr></div><div class="chapter" title="16. Expression-Based Access Control"><div class="titlepage"><div><div><h2 class="title"><a name="el-access"></a>16. Expression-Based Access Control</h2></div></div></div><p> Spring Security 3.0 introduced the ability to use Spring EL expressions as an
authorization mechanism in addition to the simple use of configuration attributes and
access-decision voters which have seen before. Expression-based access control is built on
the same architecture but allows complicated boolean logic to be encapsulated in a single
- expression.</p><div class="section" title="15.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e4781"></a>15.1 Overview</h2></div></div></div><p>Spring Security uses Spring EL for expression support and you should look at how that
+ expression.</p><div class="section" title="16.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e5418"></a>16.1 Overview</h2></div></div></div><p>Spring Security uses Spring EL for expression support and you should look at how that
works if you are interested in understanding the topic in more depth. Expressions are
evaluated with a <span class="quote">“<span class="quote">root object</span>”</span> as part of the evaluation context. Spring
Security uses specific classes for web and method security as the root object, in order
to provide built-in expressions and access to values such as the current
- principal.</p><div class="section" title="15.1.1 Common Built-In Expressions"><div class="titlepage"><div><div><h3 class="title"><a name="el-common-built-in"></a>15.1.1 Common Built-In Expressions</h3></div></div></div><p>The base class for expression root objects is
- <code class="classname">SecurityExpressionRoot</code>. This provides some common
- expressions which are available in both web and method security.</p><div class="table"><a name="d0e4797"></a><p class="title"><b>Table 15.1. Common built-in expressions</b></p><div class="table-contents"><table summary="Common built-in expressions" style="border: none;"><colgroup><col><col></colgroup><thead><tr><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; ">Expression</th><th style="border-bottom: 0.5pt solid ; ">Description</th></tr></thead><tbody><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">hasRole([role])</code></td><td style="border-bottom: 0.5pt solid ; ">Returns <code class="literal">true</code> if the current principal has the
+ principal.</p><div class="section" title="16.1.1 Common Built-In Expressions"><div class="titlepage"><div><div><h3 class="title"><a name="el-common-built-in"></a>16.1.1 Common Built-In Expressions</h3></div></div></div><p>The base class for expression root objects is
+ <code class="classname">SecurityExpressionRoot</code>. This provides some common expressions
+ which are available in both web and method security.</p><div class="table"><a name="d0e5434"></a><p class="title"><b>Table 16.1. Common built-in expressions</b></p><div class="table-contents"><table summary="Common built-in expressions" style="border: none;"><colgroup><col><col></colgroup><thead><tr><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; ">Expression</th><th style="border-bottom: 0.5pt solid ; ">Description</th></tr></thead><tbody><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">hasRole([role])</code></td><td style="border-bottom: 0.5pt solid ; ">Returns <code class="literal">true</code> if the current principal has the
specified role.</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">hasAnyRole([role1,role2])</code></td><td style="border-bottom: 0.5pt solid ; ">Returns <code class="literal">true</code> if the current principal has any
of the supplied roles (given as a comma-separated list of
strings)</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">principal</code></td><td style="border-bottom: 0.5pt solid ; ">Allows direct access to the principal object representing the
current user</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">authentication</code></td><td style="border-bottom: 0.5pt solid ; ">Allows direct access to the current
- <code class="interfacename">Authentication</code> object obtained
- from the <code class="interfacename">SecurityContext</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">permitAll</code></td><td style="border-bottom: 0.5pt solid ; ">Always evaluates to <code class="literal">true</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">denyAll</code></td><td style="border-bottom: 0.5pt solid ; ">Always evaluates to <code class="literal">false</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">isAnonymous()</code></td><td style="border-bottom: 0.5pt solid ; ">Returns <code class="literal">true</code> if the current principal is an
+ <code class="interfacename">Authentication</code> object obtained from
+ the <code class="interfacename">SecurityContext</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">permitAll</code></td><td style="border-bottom: 0.5pt solid ; ">Always evaluates to <code class="literal">true</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">denyAll</code></td><td style="border-bottom: 0.5pt solid ; ">Always evaluates to <code class="literal">false</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">isAnonymous()</code></td><td style="border-bottom: 0.5pt solid ; ">Returns <code class="literal">true</code> if the current principal is an
anonymous user</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">isRememberMe()</code></td><td style="border-bottom: 0.5pt solid ; ">Returns <code class="literal">true</code> if the current principal is a
remember-me user</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">isAuthenticated()</code></td><td style="border-bottom: 0.5pt solid ; ">Returns <code class="literal">true</code> if the user is not
anonymous</td></tr><tr><td style="border-right: 0.5pt solid ; "><code class="literal">isFullyAuthenticated()</code></td><td style="">Returns <code class="literal">true</code> if the user is not an anonymous
- or a remember-me user</td></tr></tbody></table></div></div><br class="table-break"></div></div><div class="section" title="15.2 Web Security Expressions"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="el-access-web"></a>15.2 Web Security Expressions</h2></div></div></div><p> To use expressions to secure individual URLs, you would first need to set the
- <code class="literal">use-expressions</code> attribute in the <code class="literal"><http></code>
- element to <code class="literal">true</code>. Spring Security will then expect the
- <code class="literal">access</code> attributes of the <code class="literal"><intercept-url></code>
+ or a remember-me user</td></tr></tbody></table></div></div><br class="table-break"></div></div><div class="section" title="16.2 Web Security Expressions"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="el-access-web"></a>16.2 Web Security Expressions</h2></div></div></div><p> To use expressions to secure individual URLs, you would first need to set the
+ <code class="literal">use-expressions</code> attribute in the <code class="literal"><http></code> element
+ to <code class="literal">true</code>. Spring Security will then expect the
+ <code class="literal">access</code> attributes of the <code class="literal"><intercept-url></code>
elements to contain Spring EL expressions. The expressions should evaluate to a boolean,
defining whether access should be allowed or not. For example:</p><pre class="programlisting">
- <http use-expressions="true">
- <intercept-url pattern="/admin*"
- access="hasRole('admin') and hasIpAddress('192.168.1.0/24')"/>
+ <span class="hl-tag"><http</span> <span class="hl-attribute">use-expressions</span>=<span class="hl-value">"true"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/admin*"</span>
+ <span class="hl-attribute">access</span>=<span class="hl-value">"hasRole('admin') and hasIpAddress('192.168.1.0/24')"</span><span class="hl-tag">/></span>
...
- </http>
+ <span class="hl-tag"></http></span>
</pre><p>Here we have defined that the <span class="quote">“<span class="quote">admin</span>”</span> area of an application
(defined by the URL pattern) should only be available to users who have the granted
authority <span class="quote">“<span class="quote">admin</span>”</span> and whose IP address matches a local subnet. We've
already seen the built-in <code class="literal">hasRole</code> expression in the previous section.
The expression <code class="literal">hasIpAddress</code> is an additional built-in expression
which is specific to web security. It is defined by the
- <code class="classname">WebSecurityExpressionRoot</code> class, an instance of which is used
- as the expression root object when evaluation web-access expressions. This object also
+ <code class="classname">WebSecurityExpressionRoot</code> class, an instance of which is used as
+ the expression root object when evaluation web-access expressions. This object also
directly exposed the <code class="interfacename">HttpServletRequest</code> object under the
name <code class="literal">request</code> so you can invoke the request directly in an
expression.</p><p>If expressions are being used, a <code class="classname">WebExpressionVoter</code> will be
added to the <code class="interfacename">AccessDecisionManager</code> which is used by the
namespace. So if you aren't using the namespace and want to use expressions, you will
- have to add one of these to your configuration.</p></div><div class="section" title="15.3 Method Security Expressions"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e4949"></a>15.3 Method Security Expressions</h2></div></div></div><p>Method security is a bit more complicated than a simple allow or deny rule. Spring
+ have to add one of these to your configuration.</p></div><div class="section" title="16.3 Method Security Expressions"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e5586"></a>16.3 Method Security Expressions</h2></div></div></div><p>Method security is a bit more complicated than a simple allow or deny rule. Spring
Security 3.0 introduced some new annotations in order to allow comprehensive support for
- the use of expressions.</p><div class="section" title="15.3.1 @Pre and @Post Annotations"><div class="titlepage"><div><div><h3 class="title"><a name="el-pre-post-annotations"></a>15.3.1 <code class="literal">@Pre</code> and <code class="literal">@Post</code> Annotations</h3></div></div></div><p>There are four annotations which support expression attributes to allow pre and
+ the use of expressions.</p><div class="section" title="16.3.1 @Pre and @Post Annotations"><div class="titlepage"><div><div><h3 class="title"><a name="el-pre-post-annotations"></a>16.3.1 <code class="literal">@Pre</code> and <code class="literal">@Post</code> Annotations</h3></div></div></div><p>There are four annotations which support expression attributes to allow pre and
post-invocation authorization checks and also to support filtering of submitted
collection arguments or return values. They are <code class="literal">@PreAuthorize</code>,
- <code class="literal">@PreFilter</code>, <code class="literal">@PostAuthorize</code> and
- <code class="literal">@PostFilter</code>. Their use is enabled through the
- <code class="literal">global-method-security</code> namespace
- element:</p><pre class="programlisting"><global-method-security pre-post-annotations="enabled"/></pre><div class="section" title="Access Control using @PreAuthorize and @PostAuthorize"><div class="titlepage"><div><div><h4 class="title"><a name="d0e4981"></a>Access Control using <code class="literal">@PreAuthorize</code> and
- <code class="literal">@PostAuthorize</code></h4></div></div></div><p>The most obviously useful annotation is <code class="literal">@PreAuthorize</code> which
+ <code class="literal">@PreFilter</code>, <code class="literal">@PostAuthorize</code> and
+ <code class="literal">@PostFilter</code>. Their use is enabled through the
+ <code class="literal">global-method-security</code> namespace
+ element:</p><pre class="programlisting"><span class="hl-tag"><global-method-security</span> <span class="hl-attribute">pre-post-annotations</span>=<span class="hl-value">"enabled"</span><span class="hl-tag">/></span></pre><div class="section" title="Access Control using @PreAuthorize and @PostAuthorize"><div class="titlepage"><div><div><h4 class="title"><a name="d0e5618"></a>Access Control using <code class="literal">@PreAuthorize</code> and
+ <code class="literal">@PostAuthorize</code></h4></div></div></div><p>The most obviously useful annotation is <code class="literal">@PreAuthorize</code> which
decides whether a method can actually be invoked or not. For example (from the
- <span class="quote">“<span class="quote">Contacts</span>”</span> sample
- application)</p><pre class="programlisting"> @PreAuthorize("hasRole('ROLE_USER')")
- public void create(Contact contact);</pre><p>which
+ <span class="quote">“<span class="quote">Contacts</span>”</span> sample
+ application)</p><pre class="programlisting">
+ <i><span class="hl-annotation" style="color: gray">@PreAuthorize("hasRole('ROLE_USER')")</span></i>
+ <span class="hl-keyword">public</span> <span class="hl-keyword">void</span> create(Contact contact);</pre><p>which
means that access will only be allowed for users with the role "ROLE_USER".
Obviously the same thing could easily be achieved using a traditional
configuration and a simple configuration attribute for the required role. But
what
- about:</p><pre class="programlisting"> @PreAuthorize("hasPermission(#contact, 'admin')")
- public void deletePermission(Contact contact, Sid recipient, Permission permission);</pre><p>Here
+ about:</p><pre class="programlisting">
+ <i><span class="hl-annotation" style="color: gray">@PreAuthorize("hasPermission(#contact, 'admin')")</span></i>
+ <span class="hl-keyword">public</span> <span class="hl-keyword">void</span> deletePermission(Contact contact, Sid recipient, Permission permission);</pre><p>Here
we're actually using a method argument as part of the expression to decide
whether the current user has the <span class="quote">“<span class="quote">admin</span>”</span>permission for the given
contact. The built-in <code class="literal">hasPermission()</code> expression is linked
into the Spring Security ACL module through the application context, as we'll
- <a class="link" href="el-access.html#el-permission-evaluator" title="The PermissionEvaluator interface">see below</a>. You can access
- any of the method arguments by name as expression variables, provided your code
- has debug information compiled in. Any Spring-EL functionality is available
- within the expression, so you can also access properties on the arguments. For
- example, if you wanted a particular method to only allow access to a user whose
- username matched that of the contact, you could write</p><pre class="programlisting">
- @PreAuthorize("#contact.name == authentication.name")
- public void doSomething(Contact contact);</pre><p>Here we are accessing another built–in expression, <code class="literal">authentication</code>,
+ <a class="link" href="el-access.html#el-permission-evaluator" title="The PermissionEvaluator interface">see below</a>. You can access any
+ of the method arguments by name as expression variables, provided your code has
+ debug information compiled in. Any Spring-EL functionality is available within
+ the expression, so you can also access properties on the arguments. For example,
+ if you wanted a particular method to only allow access to a user whose username
+ matched that of the contact, you could write</p><pre class="programlisting">
+ <i><span class="hl-annotation" style="color: gray">@PreAuthorize("#contact.name == authentication.name")</span></i>
+ <span class="hl-keyword">public</span> <span class="hl-keyword">void</span> doSomething(Contact contact);</pre><p>Here we are accessing another built–in expression, <code class="literal">authentication</code>,
which is the <code class="interfacename">Authentication</code> stored in the
security context. You can also access its <span class="quote">“<span class="quote">principal</span>”</span> property
directly, using the expression <code class="literal">principal</code>. The value will
@@ -92,15 +94,15 @@
expression like <code class="literal">principal.username</code> or
<code class="literal">principal.enabled</code>.</p><p>Less commonly, you may wish to perform an access-control check after the
method has been invoked. This can be achieved using the
- <code class="literal">@PostAuthorize</code> annotation. To access the return value
- from a method, use the built–in name <code class="literal">returnObject</code> in the
- expression.</p></div><div class="section" title="Filtering using @PreFilter and @PostFilter"><div class="titlepage"><div><div><h4 class="title"><a name="d0e5045"></a>Filtering using <code class="literal">@PreFilter</code> and
- <code class="literal">@PostFilter</code></h4></div></div></div><p>As you may already be aware, Spring Security supports filtering of collections
+ <code class="literal">@PostAuthorize</code> annotation. To access the return value from a
+ method, use the built–in name <code class="literal">returnObject</code> in the
+ expression.</p></div><div class="section" title="Filtering using @PreFilter and @PostFilter"><div class="titlepage"><div><div><h4 class="title"><a name="d0e5682"></a>Filtering using <code class="literal">@PreFilter</code> and
+ <code class="literal">@PostFilter</code></h4></div></div></div><p>As you may already be aware, Spring Security supports filtering of collections
and arrays and this can now be achieved using expressions. This is most commonly
performed on the return value of a method. For
- example:</p><pre class="programlisting"> @PreAuthorize("hasRole('ROLE_USER')")
- @PostFilter("hasPermission(filterObject, 'read') or hasPermission(filterObject, 'admin')")
- public List<Contact> getAll();</pre><p>When
+ example:</p><pre class="programlisting"> <i><span class="hl-annotation" style="color: gray">@PreAuthorize("hasRole('ROLE_USER')")</span></i>
+ <i><span class="hl-annotation" style="color: gray">@PostFilter("hasPermission(filterObject, 'read') or hasPermission(filterObject, 'admin')")</span></i>
+ <span class="hl-keyword">public</span> List<Contact> getAll();</pre><p>When
using the <code class="literal">@PostFilter</code> annotation, Spring Security iterates
through the returned collection and removes any elements for which the supplied
expression is false. The name <code class="literal">filterObject</code> refers to the
@@ -108,21 +110,25 @@
using <code class="literal">@PreFilter</code>, though this is a less common requirement.
The syntax is just the same, but if there is more than one argument which is a
collection type then you have to select one by name using the
- <code class="literal">filterTarget</code> property of this annotation.</p><p>Note that filtering is obviously not a substitute for tuning your data
+ <code class="literal">filterTarget</code> property of this annotation.</p><p>Note that filtering is obviously not a substitute for tuning your data
retrieval queries. If you are filtering large collections and removing many of
- the entries then this is likely to be inefficient.</p></div></div><div class="section" title="15.3.2 Built-In Expressions"><div class="titlepage"><div><div><h3 class="title"><a name="el-method-built-in"></a>15.3.2 Built-In Expressions</h3></div></div></div><p>There are some built-in expressions which are specific to method security, which
+ the entries then this is likely to be inefficient.</p></div></div><div class="section" title="16.3.2 Built-In Expressions"><div class="titlepage"><div><div><h3 class="title"><a name="el-method-built-in"></a>16.3.2 Built-In Expressions</h3></div></div></div><p>There are some built-in expressions which are specific to method security, which
we have already seen in use above. The <code class="literal">filterTarget</code> and
- <code class="literal">returnValue</code> values are simple enough, but the use of the
- <code class="literal">hasPermission()</code> expression warrants a closer look.</p><div class="section" title="The PermissionEvaluator interface"><div class="titlepage"><div><div><h4 class="title"><a name="el-permission-evaluator"></a>The <code class="interfacename">PermissionEvaluator</code> interface</h4></div></div></div><p><code class="literal">hasPermission()</code> expressions are delegated to an instance of
- <code class="interfacename">PermissionEvaluator</code>. It is intended to bridge
+ <code class="literal">returnValue</code> values are simple enough, but the use of the
+ <code class="literal">hasPermission()</code> expression warrants a closer look.</p><div class="section" title="The PermissionEvaluator interface"><div class="titlepage"><div><div><h4 class="title"><a name="el-permission-evaluator"></a>The <code class="interfacename">PermissionEvaluator</code> interface</h4></div></div></div><p><code class="literal">hasPermission()</code> expressions are delegated to an instance of
+ <code class="interfacename">PermissionEvaluator</code>. It is intended to bridge
between the expression system and Spring Security's ACL system, allowing you to
specify authorization constraints on domain objects, based on abstract
permissions. It has no explicit dependencies on the ACL module, so you could
swap that out for an alternative implementation if required. The interface has
two methods:
- </p><pre class="programlisting"> <span class="hl-keyword">boolean</span> hasPermission(Authentication authentication, Object targetDomainObject, Object permission);
+ </p><pre class="programlisting">
+ <span class="hl-keyword">boolean</span> hasPermission(Authentication authentication, Object targetDomainObject,
+ Object permission);
- <span class="hl-keyword">boolean</span> hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission);</pre><p>which
+ <span class="hl-keyword">boolean</span> hasPermission(Authentication authentication, Serializable targetId,
+ String targetType, Object permission);
+</pre><p>which
map directly to the available versions of the expression, with the exception
that the first argument (the <code class="interfacename">Authentication</code>
object) is not supplied. The first is used in situations where the domain
@@ -134,19 +140,19 @@
has traditionally been the Java class of the object, but does not have to be as
long as it is consistent with how the permissions are loaded.</p><p>To use <code class="literal">hasPermission()</code> expressions, you have to explicitly
configure a <code class="interfacename">PermissionEvaluator</code> in your
- application context. This would look something like this:</p><pre class="programlisting"> <span class="hl-tag"><security:global-method-security</span> <span class="hl-attribute">pre-post-annotations</span>=<span class="hl-value">"enabled"</span><span class="hl-tag">></span>
- <span class="hl-tag"><security:expression-handler</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"expressionHandler"</span><span class="hl-tag">/></span>
- <span class="hl-tag"></security:global-method-security></span>
+ application context. This would look something like this: </p><pre class="programlisting">
+<span class="hl-tag"><security:global-method-security</span> <span class="hl-attribute">pre-post-annotations</span>=<span class="hl-value">"enabled"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><security:expression-handler</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"expressionHandler"</span><span class="hl-tag">/></span>
+<span class="hl-tag"></security:global-method-security></span>
- <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"expressionHandler"</span>
- <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler"</span><span class="hl-tag">></span>
- <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"permissionEvaluator"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"myPermissionEvaluator"</span><span class="hl-tag">/></span>
- <span class="hl-tag"></bean></span></pre><p>Where <code class="literal">myPermissionEvaluator</code> is the bean which
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"expressionHandler"</span> <span class="hl-attribute">class</span>=
+ <span class="hl-value">"org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"permissionEvaluator"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"myPermissionEvaluator"</span><span class="hl-tag">/></span>
+<span class="hl-tag"></bean></span></pre><p>Where <code class="literal">myPermissionEvaluator</code> is the bean which
implements <code class="interfacename">PermissionEvaluator</code>. Usually this will
be the implementation from the ACL module which is called
- <code class="classname">AclPermissionEvaluator</code>. See the
- <span class="quote">“<span class="quote">Contacts</span>”</span> sample application configuration for more
- details.</p></div></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
+ <code class="classname">AclPermissionEvaluator</code>. See the <span class="quote">“<span class="quote">Contacts</span>”</span>
+ sample application configuration for more details.</p></div></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
- </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="secure-object-impls.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="authorization.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="advanced-topics.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">14. Secure Object Implementations </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> Part V. Additional Topics</td></tr></table></div></body></html>
\ No newline at end of file
+ </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="secure-object-impls.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="authorization.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="advanced-topics.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">15. Secure Object Implementations </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> Part V. Additional Topics</td></tr></table></div></body></html>
\ No newline at end of file
diff --git a/docs/reference/getting-started.html b/docs/reference/getting-started.html
index 4fd3f5e..18353f2 100644
--- a/docs/reference/getting-started.html
+++ b/docs/reference/getting-started.html
@@ -9,16 +9,17 @@
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
</script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Part I. Getting Started</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="preface.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="introduction.html">Next</a></td></tr></table><hr></div><div class="part" title="Part I. Getting Started"><div class="titlepage"><div><div><h1 class="title"><a name="getting-started"></a>Part I. Getting Started</h1></div></div></div><div class="partintro" title="Getting Started"><div></div><p>The later parts of this guide provide an in-depth discussion of the framework
- architecture and implementation classes, which you need to understand if you want to do any
- serious customization. In this part, we'll introduce Spring Security 3.0, give a brief
- overview of the project's history and take a slightly gentler look at how to get started
- using the framework. In particular, we'll look at namespace configuration which provides a
- much simpler way of securing your application compared to the traditional Spring bean
- approach where you have to wire up all the implementation classes individually. </p><p> We'll also take a look at the sample applications that are available. It's worth trying
- to run these and experimenting with them a bit even before you read the later sections - you
- can dip back into them as your understanding of the framework increases. Please also check
- out the <a class="link" href="http://static.springsource.org/spring-security/site/index.html" target="_top">project website</a> as it has useful information on building the project, plus links
- to articles, videos and tutorials. </p></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
+ architecture and implementation classes, which you need to understand if you want to
+ do any serious customization. In this part, we'll introduce Spring Security 3.0,
+ give a brief overview of the project's history and take a slightly gentler look at
+ how to get started using the framework. In particular, we'll look at namespace
+ configuration which provides a much simpler way of securing your application
+ compared to the traditional Spring bean approach where you have to wire up all the
+ implementation classes individually. </p><p> We'll also take a look at the sample applications that are available. It's worth
+ trying to run these and experimenting with them a bit even before you read the later
+ sections - you can dip back into them as your understanding of the framework
+ increases. Please also check out the <a class="link" href="http://static.springsource.org/spring-security/site/index.html" target="_top">project website</a> as it has useful information on building the project,
+ plus links to articles, videos and tutorials. </p></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
</script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="preface.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="introduction.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Preface </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 1. Introduction</td></tr></table></div></body></html>
\ No newline at end of file
diff --git a/docs/reference/introduction.html b/docs/reference/introduction.html
index 86cec82..9e5abb7 100644
--- a/docs/reference/introduction.html
+++ b/docs/reference/introduction.html
@@ -1,6 +1,6 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>1. Introduction</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="getting-started.html" title="Part I. Getting Started"><link rel="prev" href="getting-started.html" title="Part I. Getting Started"><link rel="next" href="ns-config.html" title="2. Security Namespace Configuration"><!--Begin Google Analytics code--><script type="text/javascript">
+ <title>1. Introduction</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="getting-started.html" title="Part I. Getting Started"><link rel="prev" href="getting-started.html" title="Part I. Getting Started"><link rel="next" href="new-3.1.html" title="2. What's new in Spring Security 3.1"><!--Begin Google Analytics code--><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
@@ -8,7 +8,7 @@
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
- </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">1. Introduction</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="getting-started.html">Prev</a> </td><th width="60%" align="center">Part I. Getting Started</th><td width="20%" align="right"> <a accesskey="n" href="ns-config.html">Next</a></td></tr></table><hr></div><div class="chapter" title="1. Introduction"><div class="titlepage"><div><div><h2 class="title"><a name="introduction"></a>1. Introduction</h2></div></div></div><div class="section" title="1.1 What is Spring Security?"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="what-is-acegi-security"></a>1.1 What is Spring Security?</h2></div></div></div><p>Spring Security provides comprehensive security services for J2EE-based enterprise
+ </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">1. Introduction</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="getting-started.html">Prev</a> </td><th width="60%" align="center">Part I. Getting Started</th><td width="20%" align="right"> <a accesskey="n" href="new-3.1.html">Next</a></td></tr></table><hr></div><div class="chapter" title="1. Introduction"><div class="titlepage"><div><div><h2 class="title"><a name="introduction"></a>1. Introduction</h2></div></div></div><div class="section" title="1.1 What is Spring Security?"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="what-is-acegi-security"></a>1.1 What is Spring Security?</h2></div></div></div><p>Spring Security provides comprehensive security services for J2EE-based enterprise
software applications. There is a particular emphasis on supporting projects built using
The Spring Framework, which is the leading J2EE solution for enterprise software
development. If you're not using Spring for developing enterprise applications, we
@@ -22,13 +22,13 @@
reconfigure your application's security in the new target environment. Using Spring
Security overcomes these problems, and also brings you dozens of other useful,
customisable security features.</p><p>As you probably know two major areas of application security are
- <span class="quote">“<span class="quote">authentication</span>”</span> and <span class="quote">“<span class="quote">authorization</span>”</span> (or
- <span class="quote">“<span class="quote">access-control</span>”</span>). These are the two main areas that Spring Security
+ <span class="quote">“<span class="quote">authentication</span>”</span> and <span class="quote">“<span class="quote">authorization</span>”</span> (or
+ <span class="quote">“<span class="quote">access-control</span>”</span>). These are the two main areas that Spring Security
targets. <span class="quote">“<span class="quote">Authentication</span>”</span> is the process of establishing a principal is who
they claim to be (a <span class="quote">“<span class="quote">principal</span>”</span> generally means a user, device or some
other system which can perform an action in your application).
- <span class="quote">“<span class="quote">Authorization</span>”</span> refers to the process of deciding whether a principal
- is allowed to perform an action within your application. To arrive at the point where an
+ <span class="quote">“<span class="quote">Authorization</span>”</span> refers to the process of deciding whether a principal is
+ allowed to perform an action within your application. To arrive at the point where an
authorization decision is needed, the identity of the principal has already been
established by the authentication process. These concepts are common, and not at all
specific to Spring Security. </p><p>At an authentication level, Spring Security supports a wide range of authentication
@@ -36,16 +36,15 @@
developed by relevant standards bodies such as the Internet Engineering Task Force. In
addition, Spring Security provides its own set of authentication features. Specifically,
Spring Security currently supports authentication integration with all of these
- technologies:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc" compact><li class="listitem"><p>HTTP BASIC authentication headers (an IEFT RFC-based standard)</p></li><li class="listitem"><p>HTTP Digest authentication headers (an IEFT RFC-based standard)</p></li><li class="listitem"><p>HTTP X.509 client certificate exchange (an IEFT RFC-based standard)</p></li><li class="listitem"><p>LDAP (a very common approach to cross-platform authentication needs,
+ technologies:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc" compact><li class="listitem"><p>HTTP BASIC authentication headers (an IETF RFC-based standard)</p></li><li class="listitem"><p>HTTP Digest authentication headers (an IETF RFC-based standard)</p></li><li class="listitem"><p>HTTP X.509 client certificate exchange (an IETF RFC-based standard)</p></li><li class="listitem"><p>LDAP (a very common approach to cross-platform authentication needs,
especially in large environments)</p></li><li class="listitem"><p>Form-based authentication (for simple user interface needs)</p></li><li class="listitem"><p>OpenID authentication</p></li><li class="listitem"><p>Authentication based on pre-established request headers (such as Computer
Associates Siteminder)</p></li><li class="listitem"><p>JA-SIG Central Authentication Service (otherwise known as CAS, which is a
- popular open source single sign on system)</p></li><li class="listitem"><p>Transparent authentication context propagation for Remote Method Invocation
+ popular open source single sign-on system)</p></li><li class="listitem"><p>Transparent authentication context propagation for Remote Method Invocation
(RMI) and HttpInvoker (a Spring remoting protocol)</p></li><li class="listitem"><p>Automatic "remember-me" authentication (so you can tick a box to avoid
- re-authentication for a predetermined period of time)</p></li><li class="listitem"><p>Anonymous authentication (allowing every call to automatically assume a
+ re-authentication for a predetermined period of time)</p></li><li class="listitem"><p>Anonymous authentication (allowing every unauthenticated call to automatically assume a
particular security identity)</p></li><li class="listitem"><p>Run-as authentication (which is useful if one call should proceed with a
different security identity)</p></li><li class="listitem"><p>Java Authentication and Authorization Service (JAAS)</p></li><li class="listitem"><p>JEE container autentication (so you can still use Container Managed
- Authentication if desired)</p></li><li class="listitem"><p>Kerberos</p></li><li class="listitem"><p>Java Open Source Single Sign On (JOSSO) *</p></li><li class="listitem"><p>OpenNMS Network Management Platform *</p></li><li class="listitem"><p>AppFuse *</p></li><li class="listitem"><p>AndroMDA *</p></li><li class="listitem"><p>Mule ESB *</p></li><li class="listitem"><p>Direct Web Request (DWR) *</p></li><li class="listitem"><p>Grails *</p></li><li class="listitem"><p>Tapestry *</p></li><li class="listitem"><p>JTrac *</p></li><li class="listitem"><p>Jasypt *</p></li><li class="listitem"><p>Roller *</p></li><li class="listitem"><p>Elastic Path *</p></li><li class="listitem"><p>Atlassian Crowd *</p></li><li class="listitem"><p>Your own authentication systems (see below)</p></li></ul></div><p>(* Denotes provided by a third party; check our <a class="link" href="http://acegisecurity.org/powering.html" target="_top">integration page</a> for
- links to the latest details)</p><p>Many independent software vendors (ISVs) adopt Spring Security because of this
+ Authentication if desired)</p></li><li class="listitem"><p>Kerberos</p></li><li class="listitem"><p>Java Open Source Single Sign On (JOSSO) *</p></li><li class="listitem"><p>OpenNMS Network Management Platform *</p></li><li class="listitem"><p>AppFuse *</p></li><li class="listitem"><p>AndroMDA *</p></li><li class="listitem"><p>Mule ESB *</p></li><li class="listitem"><p>Direct Web Request (DWR) *</p></li><li class="listitem"><p>Grails *</p></li><li class="listitem"><p>Tapestry *</p></li><li class="listitem"><p>JTrac *</p></li><li class="listitem"><p>Jasypt *</p></li><li class="listitem"><p>Roller *</p></li><li class="listitem"><p>Elastic Path *</p></li><li class="listitem"><p>Atlassian Crowd *</p></li><li class="listitem"><p>Your own authentication systems (see below)</p></li></ul></div><p>(* Denotes provided by a third party</p><p>Many independent software vendors (ISVs) adopt Spring Security because of this
significant choice of flexible authentication models. Doing so allows them to quickly
integrate their solutions with whatever their end clients need, without undertaking a
lot of engineering or requiring the client to change their environment. If none of the
@@ -53,22 +52,15 @@
it is quite simple to write your own authentication mechanism. Many corporate users of
Spring Security need to integrate with "legacy" systems that don't follow any particular
security standards, and Spring Security is happy to "play nicely" with such
- systems.</p><p>Sometimes the mere process of authentication isn't enough. Sometimes you need to also
- differentiate security based on the way a principal is interacting with your
- application. For example, you might want to ensure requests only arrive over HTTPS, in
- order to protect passwords from eavesdropping or end users from man-in-the-middle
- attacks. This is especially helpful to protect password recovery processes from brute
- force attacks, or simply to make it harder for people to duplicate your application's
- key content. To help you achieve these goals, Spring Security fully supports automatic
- "channel security", together with JCaptcha integration for human user detection.</p><p>Irrespective of how authentication was undertaken, Spring Security provides a deep set
- of authorization capabilities. There are three main areas of interest in respect of
- authorization, these being authorizing web requests, authorizing whether methods can be
+ systems.</p><p>Irrespective of the authentication mechanism, Spring Security provides a deep set
+ of authorization capabilities. There are three main areas of interest
+ - authorizing web requests, authorizing whether methods can be
invoked, and authorizing access to individual domain object instances. To help you
understand the differences, consider the authorization capabilities found in the Servlet
Specification web pattern security, EJB Container Managed Security and file system
security respectively. Spring Security provides deep capabilities in all of these
important areas, which we'll explore later in this reference guide.</p></div><div class="section" title="1.2 History"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="history"></a>1.2 History</h2></div></div></div><p>Spring Security began in late 2003 as <span class="quote">“<span class="quote">The Acegi Security System for
- Spring</span>”</span>. A question was posed on the Spring Developers' mailing list asking
+ Spring</span>”</span>. A question was posed on the Spring Developers' mailing list asking
whether there had been any consideration given to a Spring-based security
implementation. At the time the Spring community was relatively small (especially
compared with the size today!), and indeed Spring itself had only existed as a
@@ -94,16 +86,17 @@
core of developers who work on the code itself and an active community which also
regularly share patches and support their peers.</p></div><div class="section" title="1.3 Release Numbering"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="release-numbering"></a>1.3 Release Numbering</h2></div></div></div><p>It is useful to understand how Spring Security release numbers work, as it will help
you identify the effort (or lack thereof) involved in migrating to future releases of
- the project. Officially, we use the Apache Portable Runtime Project versioning
- guidelines, which can be viewed at
- <code class="literal">http://apr.apache.org/versioning.html</code>. We quote the introduction
- contained on that page for your convenience:</p><p><span class="quote">“<span class="quote">Versions are denoted using a standard triplet of integers: MAJOR.MINOR.PATCH.
- The basic intent is that MAJOR versions are incompatible, large-scale upgrades of
- the API. MINOR versions retain source and binary compatibility with older minor
- versions, and changes in the PATCH level are perfectly compatible, forwards and
- backwards.</span>”</span></p></div><div class="section" title="1.4 Getting Spring Security"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="get-spring-security"></a>1.4 Getting Spring Security</h2></div></div></div><p>You can get hold of Spring Security in several ways. You can download a packaged
- distribution from the main Spring <a class="link" href="http://www.springsource.com/download/community?project=Spring%20Security" target="_top">download page</a>, download individual jars (and sample WAR files) from the
- Maven Central repository (or a SpringSource Maven repository for snapshot and milestone
+ the project. Each release uses a standard triplet of integers: MAJOR.MINOR.PATCH. The
+ intent is that MAJOR versions are incompatible, large-scale upgrades of the API. MINOR
+ versions should largely retain source and binary compatibility with older minor
+ versions, thought there may be some design changes and incompatible udates. PATCH level
+ should be perfectly compatible, forwards and backwards, with the possible exception of
+ changes which are to fix bugs and defects.</p><p>The extent to which you are affected by changes will depend on how tightly integrated
+ your code is. If you are doing a lot of customization you are more likely to be affected
+ than if you are using a simple namespace configuration.</p><p>You should always test your application thoroughly before rolling out a new
+ version.</p></div><div class="section" title="1.4 Getting Spring Security"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="get-spring-security"></a>1.4 Getting Spring Security</h2></div></div></div><p>You can get hold of Spring Security in several ways. You can download a packaged
+ distribution from the main Spring <a class="link" href="http://www.springsource.com/download/community?project=Spring%20Security" target="_top">download page</a>, download individual jars (and sample WAR files) from the Maven
+ Central repository (or a SpringSource Maven repository for snapshot and milestone
releases) or, alternatively, you can build the project from source yourself. See the
project web site for more details. </p><div class="section" title="1.4.1 Project Modules"><div class="titlepage"><div><div><h3 class="title"><a name="modules"></a>1.4.1 Project Modules</h3></div></div></div><p>In Spring Security 3.0, the codebase has been sub-divided into separate jars which
more clearly separate different functionaltiy areas and third-party dependencies. If
@@ -114,20 +107,21 @@
libraries that are included in the sample applications.</p><div class="section" title="Core - spring-security-core.jar"><div class="titlepage"><div><div><h4 class="title"><a name="spring-security-core"></a>Core - <code class="literal">spring-security-core.jar</code></h4></div></div></div><p>Contains core authentication and access-contol classes and interfaces,
remoting support and basic provisioning APIs. Required by any application which
uses Spring Security. Supports standalone applications, remote clients, method
- (service layer) security and JDBC user provisioning. Contains the top-level
- packages:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p><code class="literal">org.springframework.security.core</code></p></li><li class="listitem"><p><code class="literal">org.springframework.security.access</code></p></li><li class="listitem"><p><code class="literal">org.springframework.security.authentication</code></p></li><li class="listitem"><p><code class="literal">org.springframework.security.provisioning</code></p></li><li class="listitem"><p><code class="literal">org.springframework.security.remoting</code></p></li></ul></div></div><div class="section" title="Web - spring-security-web.jar"><div class="titlepage"><div><div><h4 class="title"><a name="spring-security-web"></a>Web - <code class="literal">spring-security-web.jar</code></h4></div></div></div><p>Contains filters and related web-security infrastructure code. Anything with a
+ (service layer) security and JDBC user provisioning. Contains the top-level packages:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p><code class="literal">org.springframework.security.core</code></p></li><li class="listitem"><p><code class="literal">org.springframework.security.access</code></p></li><li class="listitem"><p><code class="literal">org.springframework.security.authentication</code></p></li><li class="listitem"><p><code class="literal">org.springframework.security.provisioning</code></p></li></ul></div></div><div class="section" title="Remoting - spring-security-remoting.jar"><div class="titlepage"><div><div><h4 class="title"><a name="spring-security-remoting"></a>Remoting - <code class="literal">spring-security-remoting.jar</code></h4></div></div></div><p>Provides intergration with Spring Remoting. You don't need this unless you are
+ writing a remote client which uses Spring Remoting. The main package is
+ <code class="literal">org.springframework.security.remoting</code>.</p></div><div class="section" title="Web - spring-security-web.jar"><div class="titlepage"><div><div><h4 class="title"><a name="spring-security-web"></a>Web - <code class="literal">spring-security-web.jar</code></h4></div></div></div><p>Contains filters and related web-security infrastructure code. Anything with a
servlet API dependency. You'll need it if you require Spring Security web
authentication services and URL-based access-control. The main package is
- <code class="literal">org.springframework.security.web</code>.</p></div><div class="section" title="Config - spring-security-config.jar"><div class="titlepage"><div><div><h4 class="title"><a name="spring-security-config"></a>Config - <code class="literal">spring-security-config.jar</code></h4></div></div></div><p>Contains the security namespace parsing code (and hence nothing that you are
- likely yo use directly in your application). You need it if you are using the
+ <code class="literal">org.springframework.security.web</code>.</p></div><div class="section" title="Config - spring-security-config.jar"><div class="titlepage"><div><div><h4 class="title"><a name="spring-security-config"></a>Config - <code class="literal">spring-security-config.jar</code></h4></div></div></div><p>Contains the security namespace parsing code. You need it if you are using the
Spring Security XML namespace for configuration. The main package is
- <code class="literal">org.springframework.security.config</code>.</p></div><div class="section" title="LDAP - spring-security-ldap.jar"><div class="titlepage"><div><div><h4 class="title"><a name="spring-security-ldap"></a>LDAP - <code class="literal">spring-security-ldap.jar</code></h4></div></div></div><p>LDAP authentication and provisioning code. Required if you need to use LDAP
+ <code class="literal">org.springframework.security.config</code>. None of the
+ classes are intended for direct use in an application.</p></div><div class="section" title="LDAP - spring-security-ldap.jar"><div class="titlepage"><div><div><h4 class="title"><a name="spring-security-ldap"></a>LDAP - <code class="literal">spring-security-ldap.jar</code></h4></div></div></div><p>LDAP authentication and provisioning code. Required if you need to use LDAP
authentication or manage LDAP user entries. The top-level package is
- <code class="literal">org.springframework.security.ldap</code>.</p></div><div class="section" title="ACL - spring-security-acl.jar"><div class="titlepage"><div><div><h4 class="title"><a name="spring-security-acl"></a>ACL - <code class="literal">spring-security-acl.jar</code></h4></div></div></div><p>Specialized domain object ACL implementation. Used to apply security to
+ <code class="literal">org.springframework.security.ldap</code>.</p></div><div class="section" title="ACL - spring-security-acl.jar"><div class="titlepage"><div><div><h4 class="title"><a name="spring-security-acl"></a>ACL - <code class="literal">spring-security-acl.jar</code></h4></div></div></div><p>Specialized domain object ACL implementation. Used to apply security to
specific domain object instances within your application. The top-level package
- is <code class="literal">org.springframework.security.acls</code>.</p></div><div class="section" title="CAS - spring-security-cas-client.jar"><div class="titlepage"><div><div><h4 class="title"><a name="spring-security-cas"></a>CAS - <code class="literal">spring-security-cas-client.jar</code></h4></div></div></div><p>Spring Security's CAS client integration. If you want to use Spring Security
+ is <code class="literal">org.springframework.security.acls</code>.</p></div><div class="section" title="CAS - spring-security-cas.jar"><div class="titlepage"><div><div><h4 class="title"><a name="spring-security-cas"></a>CAS - <code class="literal">spring-security-cas.jar</code></h4></div></div></div><p>Spring Security's CAS client integration. If you want to use Spring Security
web authentication with a CAS single sign-on server. The top-level package is
- <code class="literal">org.springframework.security.cas</code>.</p></div><div class="section" title="OpenID - spring-security-openid.jar"><div class="titlepage"><div><div><h4 class="title"><a name="spring-security-openid"></a>OpenID - <code class="literal">spring-security-openid.jar</code></h4></div></div></div><p>OpenID web authentication support. Used to authenticate users against an
+ <code class="literal">org.springframework.security.cas</code>.</p></div><div class="section" title="OpenID - spring-security-openid.jar"><div class="titlepage"><div><div><h4 class="title"><a name="spring-security-openid"></a>OpenID - <code class="literal">spring-security-openid.jar</code></h4></div></div></div><p>OpenID web authentication support. Used to authenticate users against an
external OpenID server. <code class="literal">org.springframework.security.openid</code>.
Requires OpenID4Java.</p></div></div><div class="section" title="1.4.2 Checking out the Source"><div class="titlepage"><div><div><h3 class="title"><a name="get-source"></a>1.4.2 Checking out the Source</h3></div></div></div><p> Since Spring Security is an Open Source project, we'd strongly encourage you to
check out the source code using git. This will give you full access to all the
@@ -136,13 +130,12 @@
stack traces are no longer obscure black-box issues but you can get straight to the
line that's causing the problem and work out what's happening. The source is the
ultimate documentation for a project and often the simplest place to find out how
- something actually works. </p><p>To obtain the source for the project trunk, use the following git command:
+ something actually works. </p><p>To obtain the source for the project, use the following git command:
</p><pre class="programlisting">
git clone git://git.springsource.org/spring-security/spring-security.git
</pre><p>
- You can checkout specific versions from
- <code class="literal">https://src.springframework.org/svn/spring-security/tags/</code>.
- </p></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
+ </p><p>This will give you access to the entire project history (including all releases
+ and branches) on your local machine.</p></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
- </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="getting-started.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="getting-started.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="ns-config.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Part I. Getting Started </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 2. Security Namespace Configuration</td></tr></table></div></body></html>
\ No newline at end of file
+ </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="getting-started.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="getting-started.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="new-3.1.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Part I. Getting Started </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 2. What's new in Spring Security 3.1</td></tr></table></div></body></html>
\ No newline at end of file
diff --git a/docs/reference/jaas.html b/docs/reference/jaas.html
index 527c2f2..10e95da 100644
--- a/docs/reference/jaas.html
+++ b/docs/reference/jaas.html
@@ -1,6 +1,6 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>20. Java Authentication and Authorization Service (JAAS) Provider</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="advanced-topics.html" title="Part V. Additional Topics"><link rel="prev" href="taglibs.html" title="19. JSP Tag Libraries"><link rel="next" href="cas.html" title="21. CAS Authentication"><!--Begin Google Analytics code--><script type="text/javascript">
+ <title>21. Java Authentication and Authorization Service (JAAS) Provider</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="advanced-topics.html" title="Part V. Additional Topics"><link rel="prev" href="taglibs.html" title="20. JSP Tag Libraries"><link rel="next" href="cas.html" title="22. CAS Authentication"><!--Begin Google Analytics code--><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
@@ -8,101 +8,156 @@
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
- </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">20. Java Authentication and Authorization Service (JAAS) Provider</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="taglibs.html">Prev</a> </td><th width="60%" align="center">Part V. Additional Topics</th><td width="20%" align="right"> <a accesskey="n" href="cas.html">Next</a></td></tr></table><hr></div><div class="chapter" title="20. Java Authentication and Authorization Service (JAAS) Provider"><div class="titlepage"><div><div><h1 class="title"><a name="jaas"></a>Java Authentication and Authorization Service (JAAS) Provider</h1></div></div></div><div class="section" title="20.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="jaas-overview"></a>20.1 Overview</h2></div></div></div><p>Spring Security provides a package able to delegate
- authentication requests to the Java Authentication and Authorization
- Service (JAAS). This package is discussed in detail below.</p><p>Central to JAAS operation are login configuration files. To
- learn more about JAAS login configuration files, consult the JAAS
- reference documentation available from Sun Microsystems. We expect you
- to have a basic understanding of JAAS and its login configuration file
- syntax in order to understand this section.</p></div><div class="section" title="20.2 Configuration"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="jaas-config"></a>20.2 Configuration</h2></div></div></div><p>The <code class="literal">JaasAuthenticationProvider</code> attempts to
- authenticate a user’s principal and credentials through JAAS.</p><p>Let’s assume we have a JAAS login configuration file,
- <code class="literal">/WEB-INF/login.conf</code>, with the following
- contents:
-</p><pre class="programlisting">
-JAASTest {
- sample.SampleLoginModule required;
-};</pre><p>Like all Spring Security beans, the
- <code class="classname">JaasAuthenticationProvider</code> is configured via the
- application context. The following definitions would correspond to the
- above JAAS login configuration file:
-</p><pre class="programlisting">
-<bean id="jaasAuthenticationProvider"
- class="org.springframework.security.authentication.jaas.JaasAuthenticationProvider">
- <property name="loginConfig" value="/WEB-INF/login.conf"/>
- <property name="loginContextName" value="JAASTest"/>
- <property name="callbackHandlers">
- <list>
- <bean
- class="org.springframework.security.authentication.jaas.JaasNameCallbackHandler"/>
- <bean
- class="org.springframework.security.authentication.jaas.JaasPasswordCallbackHandler"/>
- </list>
- </property>
- <property name="authorityGranters">
- <list>
- <bean class="org.springframework.security.authentication.jaas.TestAuthorityGranter"/>
- </list>
- </property>
-</bean>
-</pre><p>The <code class="literal">CallbackHandler</code>s and
- <code class="interfacename">AuthorityGranter</code>s are discussed below.</p><div class="section" title="20.2.1 JAAS CallbackHandler"><div class="titlepage"><div><div><h3 class="title"><a name="jaas-callbackhandler"></a>20.2.1 JAAS CallbackHandler</h3></div></div></div><p>Most JAAS <code class="literal">LoginModule</code>s require a callback
- of some sort. These callbacks are usually used to obtain the
- username and password from the user.</p><p>In a Spring Security deployment, Spring Security is
- responsible for this user interaction (via the authentication
- mechanism). Thus, by the time the authentication request is
- delegated through to JAAS, Spring Security's authentication
- mechanism will already have fully-populated an
- <code class="interfacename">Authentication</code> object containing all the
- information required by the JAAS
- <code class="literal">LoginModule</code>.</p><p>Therefore, the JAAS package for Spring Security provides two
- default callback handlers,
- <code class="literal">JaasNameCallbackHandler</code> and
- <code class="literal">JaasPasswordCallbackHandler</code>. Each of these
- callback handlers implement
- <code class="literal">JaasAuthenticationCallbackHandler</code>. In most cases
- these callback handlers can simply be used without understanding the
- internal mechanics.</p><p>For those needing full control over the callback behavior,
- internally <code class="literal">JaasAuthenticationProvider</code> wraps these
+ </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">21. Java Authentication and Authorization Service (JAAS) Provider</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="taglibs.html">Prev</a> </td><th width="60%" align="center">Part V. Additional Topics</th><td width="20%" align="right"> <a accesskey="n" href="cas.html">Next</a></td></tr></table><hr></div><div class="chapter" title="21. Java Authentication and Authorization Service (JAAS) Provider"><div class="titlepage"><div><div><h1 class="title"><a name="jaas"></a>Java Authentication and Authorization Service (JAAS) Provider</h1></div></div></div><div class="section" title="21.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e7027"></a>21.1 Overview</h2></div></div></div><p>Spring Security provides a package able to delegate authentication requests to the
+ Java Authentication and Authorization Service (JAAS). This package is discussed in
+ detail below.</p></div><div class="section" title="21.2 AbstractJaasAuthenticationProvider"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="jaas-abstractjaasauthenticationprovider"></a>21.2 AbstractJaasAuthenticationProvider</h2></div></div></div><p>The <code class="classname">AbstractJaasAuthenticationProvider</code> is the basis for the
+ provided JAAS <code class="interfacename">AuthenticationProvider</code> implementations. Subclasses
+ must implement a method that creates the <code class="classname">LoginContext</code>. The
+ <code class="classname">AbstractJaasAuthenticationProvider</code> has a number of dependencies that can
+ be injected into it that are discussed below.</p><div class="section" title="21.2.1 JAAS CallbackHandler"><div class="titlepage"><div><div><h3 class="title"><a name="jaas-callbackhandler"></a>21.2.1 JAAS CallbackHandler</h3></div></div></div><p>Most JAAS <code class="literal">LoginModule</code>s require a callback of some sort. These
+ callbacks are usually used to obtain the username and password from the user.</p><p>In a Spring Security deployment, Spring Security is responsible for this user
+ interaction (via the authentication mechanism). Thus, by the time the authentication
+ request is delegated through to JAAS, Spring Security's authentication mechanism
+ will already have fully-populated an <code class="interfacename">Authentication</code>
+ object containing all the information required by the JAAS
+ <code class="literal">LoginModule</code>.</p><p>Therefore, the JAAS package for Spring Security provides two default callback
+ handlers, <code class="literal">JaasNameCallbackHandler</code> and
+ <code class="literal">JaasPasswordCallbackHandler</code>. Each of these callback handlers
+ implement <code class="literal">JaasAuthenticationCallbackHandler</code>. In most cases these
+ callback handlers can simply be used without understanding the internal
+ mechanics.</p><p>For those needing full control over the callback behavior, internally
+ <code class="classname">AbstractJaasAuthenticationProvider</code> wraps these
<code class="literal">JaasAuthenticationCallbackHandler</code>s with an
<code class="literal">InternalCallbackHandler</code>. The
- <code class="literal">InternalCallbackHandler</code> is the class that
- actually implements JAAS’ normal <code class="literal">CallbackHandler</code>
- interface. Any time that the JAAS <code class="literal">LoginModule</code> is
- used, it is passed a list of application context configured
- <code class="literal">InternalCallbackHandler</code>s. If the
+ <code class="literal">InternalCallbackHandler</code> is the class that actually implements
+ JAAS’ normal <code class="literal">CallbackHandler</code> interface. Any time that the JAAS
+ <code class="literal">LoginModule</code> is used, it is passed a list of application context
+ configured <code class="literal">InternalCallbackHandler</code>s. If the
<code class="literal">LoginModule</code> requests a callback against the
- <code class="literal">InternalCallbackHandler</code>s, the callback is in-turn
- passed to the <code class="literal">JaasAuthenticationCallbackHandler</code>s
- being wrapped.</p></div><div class="section" title="20.2.2 JAAS AuthorityGranter"><div class="titlepage"><div><div><h3 class="title"><a name="jaas-authoritygranter"></a>20.2.2 JAAS AuthorityGranter</h3></div></div></div><p>JAAS works with principals. Even "roles" are represented as
- principals in JAAS. Spring Security, on the other hand, works with
+ <code class="literal">InternalCallbackHandler</code>s, the callback is in-turn passed to the
+ <code class="literal">JaasAuthenticationCallbackHandler</code>s being wrapped.</p></div><div class="section" title="21.2.2 JAAS AuthorityGranter"><div class="titlepage"><div><div><h3 class="title"><a name="jaas-authoritygranter"></a>21.2.2 JAAS AuthorityGranter</h3></div></div></div><p>JAAS works with principals. Even "roles" are represented as principals in JAAS.
+ Spring Security, on the other hand, works with
<code class="interfacename">Authentication</code> objects. Each
- <code class="interfacename">Authentication</code> object contains a single
- principal, and multiple <code class="interfacename">GrantedAuthority</code>[]s. To
- facilitate mapping between these different concepts, Spring
- Security's JAAS package includes an
- <code class="literal">AuthorityGranter</code> interface.</p><p>An <code class="literal">AuthorityGranter</code> is responsible for
- inspecting a JAAS principal and returning a set of
- <code class="literal">String</code>s, representing the authorities assigned to the principal.
- For each returned authority string, the
- <code class="classname">JaasAuthenticationProvider</code> creates a
- <code class="classname">JaasGrantedAuthority</code> (which implements Spring
- Security’s <code class="interfacename">GrantedAuthority</code> interface) containing
- the authority string and the JAAS principal that the
+ <code class="interfacename">Authentication</code> object contains a single principal,
+ and multiple <code class="interfacename">GrantedAuthority</code>s. To facilitate
+ mapping between these different concepts, Spring Security's JAAS package includes an
+ <code class="literal">AuthorityGranter</code> interface.</p><p>An <code class="literal">AuthorityGranter</code> is responsible for inspecting a JAAS
+ principal and returning a set of <code class="literal">String</code>s, representing the
+ authorities assigned to the principal. For each returned authority string, the
+ <code class="classname">AbstractJaasAuthenticationProvider</code> creates a
+ <code class="classname">JaasGrantedAuthority</code> (which implements Spring Security’s
+ <code class="interfacename">GrantedAuthority</code> interface) containing the authority
+ string and the JAAS principal that the
<code class="interfacename">AuthorityGranter</code> was passed. The
- <code class="classname">JaasAuthenticationProvider</code> obtains the JAAS
- principals by firstly successfully authenticating the user’s
- credentials using the JAAS <code class="literal">LoginModule</code>, and then
- accessing the <code class="literal">LoginContext</code> it returns. A call to
- <code class="literal">LoginContext.getSubject().getPrincipals()</code> is
- made, with each resulting principal passed to each
- <code class="interfacename">AuthorityGranter</code> defined against the
- <code class="literal">JaasAuthenticationProvider.setAuthorityGranters(List)</code>
+ <code class="classname">AbstractJaasAuthenticationProvider</code> obtains the JAAS principals by
+ firstly successfully authenticating the user’s credentials using the JAAS
+ <code class="literal">LoginModule</code>, and then accessing the
+ <code class="literal">LoginContext</code> it returns. A call to
+ <code class="literal">LoginContext.getSubject().getPrincipals()</code> is made, with each
+ resulting principal passed to each <code class="interfacename">AuthorityGranter</code>
+ defined against the
+ <code class="literal">AbstractJaasAuthenticationProvider.setAuthorityGranters(List)</code>
property.</p><p>Spring Security does not include any production
- <code class="interfacename">AuthorityGranter</code>s given that every JAAS principal
- has an implementation-specific meaning. However, there is a
- <code class="literal">TestAuthorityGranter</code> in the unit tests that
- demonstrates a simple <code class="literal">AuthorityGranter</code>
- implementation.</p></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
+ <code class="interfacename">AuthorityGranter</code>s given that every JAAS principal has
+ an implementation-specific meaning. However, there is a
+ <code class="literal">TestAuthorityGranter</code> in the unit tests that demonstrates a simple
+ <code class="literal">AuthorityGranter</code> implementation.</p></div></div><div class="section" title="21.3 DefaultJaasAuthenticationProvider"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="jaas-defaultjaasauthenticationprovider"></a>21.3 DefaultJaasAuthenticationProvider</h2></div></div></div><p>The <code class="classname">DefaultJaasAuthenticationProvider</code> allows a JAAS
+ <code class="classname">Configuration</code> object to be injected into it as a dependency. It then
+ creates a <code class="classname">LoginContext</code> using the injected JAAS <code class="classname">Configuration</code>.
+ This means that <code class="classname">DefaultJaasAuthenticationProvider</code> is not bound any particular implementation
+ of <code class="classname">Configuration</code> as <code class="classname">JaasAuthenticationProvider</code> is.</p><div class="section" title="21.3.1 InMemoryConfiguration"><div class="titlepage"><div><div><h3 class="title"><a name="jaas-inmemoryconfiguration"></a>21.3.1 InMemoryConfiguration</h3></div></div></div><p>In order to make it easy to inject a <code class="classname">Configuration</code> into
+ <code class="classname">DefaultJaasAuthenticationProvider</code>, a default in memory
+ implementation named <code class="classname">InMemoryConfiguration</code> is provided. The
+ implementation constructor accepts a <code class="interfacename">Map</code> where each key represents a
+ login configuration name and the value represents an <code class="classname">Array</code> of
+ <code class="classname">AppConfigurationEntry</code>s.
+ <code class="classname">InMemoryConfiguration</code> also supports a default
+ <code class="classname">Array</code> of <code class="classname">AppConfigurationEntry</code> objects that
+ will be used if no mapping is found within the provided <code class="interfacename">Map</code>. For
+ details, refer to the class level javadoc of <code class="classname">InMemoryConfiguration</code>.</p></div><div class="section" title="21.3.2 DefaultJaasAuthenticationProvider Example Configuration"><div class="titlepage"><div><div><h3 class="title"><a name="jaas-djap-config"></a>21.3.2 DefaultJaasAuthenticationProvider Example Configuration</h3></div></div></div><p>While the Spring configuration for <code class="classname">InMemoryConfiguration</code> can be
+ more verbose than the standarad JAAS configuration files, using it in conjuction with
+ <code class="classname">DefaultJaasAuthenticationProvider</code> is more flexible than
+ <code class="classname">JaasAuthenticationProvider</code> since it not dependant on the default
+ <code class="classname">Configuration</code> implementation.</p><p>An example configuration of <code class="classname">DefaultJaasAuthenticationProvider</code> using
+ <code class="classname">InMemoryConfiguration</code> is provided below. Note that custom implementations of
+ <code class="classname">Configuration</code> can easily be injected into
+ <code class="classname">DefaultJaasAuthenticationProvider</code> as well.</p><pre class="programlisting">
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"jaasAuthProvider"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.authentication.jaas.DefaultJaasAuthenticationProvider"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"configuration"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.authentication.jaas.memory.InMemoryConfiguration"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><constructor-arg></span>
+ <span class="hl-tag"><map></span>
+ <span class="hl-comment"><!--
+ SPRINGSECURITY is the default loginContextName
+ for AbstractJaasAuthenticationProvider
+ --></span>
+ <span class="hl-tag"><entry</span> <span class="hl-attribute">key</span>=<span class="hl-value">"SPRINGSECURITY"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><array></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"javax.security.auth.login.AppConfigurationEntry"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">value</span>=<span class="hl-value">"sample.SampleLoginModule"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"><constructor-arg></span>
+ <span class="hl-tag"><util:constant</span> <span class="hl-attribute">static-field</span>=
+ <span class="hl-value">"javax.security.auth.login.AppConfigurationEntry$LoginModuleControlFlag.REQUIRED"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></constructor-arg></span>
+ <span class="hl-tag"><constructor-arg></span>
+ <span class="hl-tag"><map></span><span class="hl-tag"></map></span>
+ <span class="hl-tag"></constructor-arg></span>
+ <span class="hl-tag"></bean></span>
+ <span class="hl-tag"></array></span>
+ <span class="hl-tag"></entry></span>
+ <span class="hl-tag"></map></span>
+ <span class="hl-tag"></constructor-arg></span>
+ <span class="hl-tag"></bean></span>
+ <span class="hl-tag"></property></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authorityGranters"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><list></span>
+ <span class="hl-comment"><!-- You will need to write your own implementation of AuthorityGranter --></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.authentication.jaas.TestAuthorityGranter"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></list></span>
+ <span class="hl-tag"></property></span>
+<span class="hl-tag"></bean></span>
+</pre></div></div><div class="section" title="21.4 JaasAuthenticationProvider"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="jaas-jaasauthenticationprovider"></a>21.4 JaasAuthenticationProvider</h2></div></div></div><p>The <code class="classname">JaasAuthenticationProvider</code> assumes the default <code class="classname">Configuration</code> is an instance of
+ <a class="link" href="http://download.oracle.com/javase/1.4.2/docs/guide/security/jaas/spec/com/sun/security/auth/login/ConfigFile.html" target="_top">
+ ConfigFile</a>. This assumption is made in order to attempt to update the <code class="classname">Configuration</code>. The
+ <code class="classname">JaasAuthenticationProvider</code> then uses the default <code class="classname">Configuration</code> to create the
+ <code class="classname">LoginContext</code>.</p><p>Let’s assume we have a JAAS login configuration file,
+ <code class="literal">/WEB-INF/login.conf</code>, with the following contents:
+ </p><pre class="programlisting">
+JAASTest {
+ sample.SampleLoginModule required;
+};</pre><p>Like all Spring Security beans, the <code class="classname">JaasAuthenticationProvider</code>
+ is configured via the application context. The following definitions would correspond to
+ the above JAAS login configuration file: </p><pre class="programlisting">
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"jaasAuthenticationProvider"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.authentication.jaas.JaasAuthenticationProvider"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"loginConfig"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"/WEB-INF/login.conf"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"loginContextName"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"JAASTest"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"callbackHandlers"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><list></span>
+ <span class="hl-tag"><bean</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.authentication.jaas.JaasNameCallbackHandler"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><bean</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.authentication.jaas.JaasPasswordCallbackHandler"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></list></span>
+ <span class="hl-tag"></property></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authorityGranters"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><list></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.authentication.jaas.TestAuthorityGranter"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></list></span>
+ <span class="hl-tag"></property></span>
+<span class="hl-tag"></bean></span>
+</pre></div><div class="section" title="21.5 Running as a Subject"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="jaas-apiprovision"></a>21.5 Running as a Subject</h2></div></div></div><p>If configured, the <code class="classname">JaasApiIntegrationFilter</code> will attempt to
+ run as the <code class="literal">Subject</code> on the
+ <code class="classname">JaasAuthenticationToken</code>. This means that the
+ <code class="literal">Subject</code> can be accessed using:
+ </p><pre class="programlisting">
+ Subject subject = Subject.getSubject(AccessController.getContext());
+</pre><p>
+ This integration can easily be configured using the
+ <a class="link" href="appendix-namespace.html#nsa-http-jaas-api-provision" title="jaas-api-provision">jaas-api-provision</a> attribute. This
+ feature is useful when integrating with legacy or external API's that rely on the
+ JAAS Subject being populated.</p></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
- </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="taglibs.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="advanced-topics.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="cas.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">19. JSP Tag Libraries </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 21. CAS Authentication</td></tr></table></div></body></html>
\ No newline at end of file
+ </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="taglibs.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="advanced-topics.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="cas.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">20. JSP Tag Libraries </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 22. CAS Authentication</td></tr></table></div></body></html>
\ No newline at end of file
diff --git a/docs/reference/ldap.html b/docs/reference/ldap.html
index 30ca853..3bcf066 100644
--- a/docs/reference/ldap.html
+++ b/docs/reference/ldap.html
@@ -1,6 +1,6 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>18. LDAP Authentication</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="advanced-topics.html" title="Part V. Additional Topics"><link rel="prev" href="preauth.html" title="17. Pre-Authentication Scenarios"><link rel="next" href="taglibs.html" title="19. JSP Tag Libraries"><!--Begin Google Analytics code--><script type="text/javascript">
+ <title>19. LDAP Authentication</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="advanced-topics.html" title="Part V. Additional Topics"><link rel="prev" href="preauth.html" title="18. Pre-Authentication Scenarios"><link rel="next" href="taglibs.html" title="20. JSP Tag Libraries"><!--Begin Google Analytics code--><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
@@ -8,226 +8,221 @@
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
- </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">18. LDAP Authentication</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="preauth.html">Prev</a> </td><th width="60%" align="center">Part V. Additional Topics</th><td width="20%" align="right"> <a accesskey="n" href="taglibs.html">Next</a></td></tr></table><hr></div><div class="chapter" title="18. LDAP Authentication"><div class="titlepage"><div><div><h1 class="title"><a name="ldap"></a>LDAP Authentication</h1></div></div></div><div class="section" title="18.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ldap-overview"></a>18.1 Overview</h2></div></div></div><p>LDAP is often used by organizations as a central repository for user information and
+ </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">19. LDAP Authentication</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="preauth.html">Prev</a> </td><th width="60%" align="center">Part V. Additional Topics</th><td width="20%" align="right"> <a accesskey="n" href="taglibs.html">Next</a></td></tr></table><hr></div><div class="chapter" title="19. LDAP Authentication"><div class="titlepage"><div><div><h1 class="title"><a name="ldap"></a>LDAP Authentication</h1></div></div></div><div class="section" title="19.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ldap-overview"></a>19.1 Overview</h2></div></div></div><p>LDAP is often used by organizations as a central repository for user information and
as an authentication service. It can also be used to store the role information for
application users.</p><p>There are many different scenarios for how an LDAP server may be configured so Spring
Security's LDAP provider is fully configurable. It uses separate strategy interfaces for
authentication and role retrieval and provides default implementations which can be
configured to handle a wide range of situations.</p><p>You should be familiar with LDAP before trying to use it with Spring Security. The
following link provides a good introduction to the concepts involved and a guide to
- setting up a directory using the free LDAP server OpenLDAP: <code class="uri"><a class="uri" href="http://www.zytrax.com/books/ldap/" target="_top">http://www.zytrax.com/books/ldap/</a></code>. Some familiarity with the JNDI APIs used
- to access LDAP from Java may also be useful. We don't use any third-party LDAP libraries
- (Mozilla, JLDAP etc.) in the LDAP provider, but extensive use is made of Spring LDAP, so
- some familiarity with that project may be useful if you plan on adding your own
- customizations.</p></div><div class="section" title="18.2 Using LDAP with Spring Security"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e5734"></a>18.2 Using LDAP with Spring Security</h2></div></div></div><p> LDAP authentication in Spring Security can be roughly divided into the following
- stages. </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>Obtaining the unique LDAP <span class="quote">“<span class="quote">Distinguished Name</span>”</span>, or DN, from
- the login name. This will often mean performing a search in the directory,
- unless the exact mapping of usernames to DNs is known in advance.</p></li><li class="listitem"><p>Authenticating the user, either by binding as that user or by performing a
- remote <span class="quote">“<span class="quote">compare</span>”</span> operation of the user's password against the
- password attribute in the directory entry for the DN.</p></li><li class="listitem"><p>Loading the list of authorities for the user.</p></li></ol></div><p> The exception is when the LDAP directory is just being used to retrieve
+ setting up a directory using the free LDAP server OpenLDAP: <code class="uri"><a class="uri" href="http://www.zytrax.com/books/ldap/" target="_top">http://www.zytrax.com/books/ldap/</a></code>.
+ Some familiarity with the JNDI APIs used to access LDAP from Java may also be useful. We
+ don't use any third-party LDAP libraries (Mozilla, JLDAP etc.) in the LDAP provider, but
+ extensive use is made of Spring LDAP, so some familiarity with that project may be
+ useful if you plan on adding your own customizations.</p></div><div class="section" title="19.2 Using LDAP with Spring Security"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e6365"></a>19.2 Using LDAP with Spring Security</h2></div></div></div><p> LDAP authentication in Spring Security can be roughly divided into the following
+ stages. </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>Obtaining the unique LDAP <span class="quote">“<span class="quote">Distinguished Name</span>”</span>, or DN, from the
+ login name. This will often mean performing a search in the directory, unless
+ the exact mapping of usernames to DNs is known in advance. So a user might enter
+ the name <span class="quote">“<span class="quote">joe</span>”</span> when logging in, but the actual name used to
+ authenticate to LDAP will be the full DN, such as
+ <code class="literal">uid=joe,ou=users,dc=springsource,dc=com</code>.</p></li><li class="listitem"><p>Authenticating the user, either by <span class="quote">“<span class="quote">binding</span>”</span> as that user or by
+ performing a remote <span class="quote">“<span class="quote">compare</span>”</span> operation of the user's password
+ against the password attribute in the directory entry for the DN.</p></li><li class="listitem"><p>Loading the list of authorities for the user.</p></li></ol></div><p> The exception is when the LDAP directory is just being used to retrieve
user information and authenticate against it locally. This may not be possible as
directories are often set up with limited read access for attributes such as user
passwords. </p><p> We will look at some configuration scenarios below. For full information on available
configuration options, please consult the security namespace schema (information from
- which should be available in your XML editor). </p></div><div class="section" title="18.3 Configuring an LDAP Server"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ldap-server"></a>18.3 Configuring an LDAP Server</h2></div></div></div><p> The first thing you need to do is configure the server against which authentication
+ which should be available in your XML editor). </p></div><div class="section" title="19.3 Configuring an LDAP Server"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ldap-server"></a>19.3 Configuring an LDAP Server</h2></div></div></div><p> The first thing you need to do is configure the server against which authentication
should take place. This is done using the <code class="literal"><ldap-server></code> element
from the security namespace. This can be configured to point at an external LDAP server,
using the <code class="literal">url</code> attribute: </p><pre class="programlisting">
- <ldap-server url="ldap://springframework.org:389/dc=springframework,dc=org" />
+ <span class="hl-tag"><ldap-server</span> <span class="hl-attribute">url</span>=<span class="hl-value">"ldap://springframework.org:389/dc=springframework,dc=org"</span><span class="hl-tag"> /></span>
- </pre><div class="section" title="18.3.1 Using an Embedded Test Server"><div class="titlepage"><div><div><h3 class="title"><a name="d0e5773"></a>18.3.1 Using an Embedded Test Server</h3></div></div></div><p> The <code class="literal"><ldap-server></code> element can also be used to create an
+ </pre><div class="section" title="19.3.1 Using an Embedded Test Server"><div class="titlepage"><div><div><h3 class="title"><a name="d0e6413"></a>19.3.1 Using an Embedded Test Server</h3></div></div></div><p> The <code class="literal"><ldap-server></code> element can also be used to create an
embedded server, which can be very useful for testing and demonstrations. In this
case you use it without the <code class="literal">url</code> attribute: </p><pre class="programlisting">
- <ldap-server root="dc=springframework,dc=org"/>
+ <span class="hl-tag"><ldap-server</span> <span class="hl-attribute">root</span>=<span class="hl-value">"dc=springframework,dc=org"</span><span class="hl-tag">/></span>
</pre><p> Here we've specified that the root DIT of the directory should be
- <span class="quote">“<span class="quote">dc=springframework,dc=org</span>”</span>, which is the default. Used this way,
- the namespace parser will create an embedded Apache Directory server and scan the
+ <span class="quote">“<span class="quote">dc=springframework,dc=org</span>”</span>, which is the default. Used this way, the
+ namespace parser will create an embedded Apache Directory server and scan the
classpath for any LDIF files, which it will attempt to load into the server. You can
customize this behaviour using the <code class="literal">ldif</code> attribute, which defines
an LDIF resource to be loaded: </p><pre class="programlisting">
- <ldap-server ldif="classpath:users.ldif" />
+ <span class="hl-tag"><ldap-server</span> <span class="hl-attribute">ldif</span>=<span class="hl-value">"classpath:users.ldif"</span><span class="hl-tag"> /></span>
</pre><p> This makes it a lot easier to get up and running with LDAP, since it
can be inconvenient to work all the time with an external server. It also insulates
the user from the complex bean configuration needed to wire up an Apache Directory
server. Using plain Spring Beans the configuration would be much more cluttered. You
must have the necessary Apache Directory dependency jars available for your
- application to use. These can be obtained from the LDAP sample application. </p></div><div class="section" title="18.3.2 Using Bind Authentication"><div class="titlepage"><div><div><h3 class="title"><a name="d0e5797"></a>18.3.2 Using Bind Authentication</h3></div></div></div><p> This is the most common LDAP authentication scenario. </p><pre class="programlisting">
- <ldap-authentication-provider user-dn-pattern="uid={0},ou=people"/>
+ application to use. These can be obtained from the LDAP sample application. </p></div><div class="section" title="19.3.2 Using Bind Authentication"><div class="titlepage"><div><div><h3 class="title"><a name="d0e6437"></a>19.3.2 Using Bind Authentication</h3></div></div></div><p> This is the most common LDAP authentication scenario. </p><pre class="programlisting">
+ <span class="hl-tag"><ldap-authentication-provider</span> <span class="hl-attribute">user-dn-pattern</span>=<span class="hl-value">"uid={0},ou=people"</span><span class="hl-tag">/></span>
</pre><p> This simple example would obtain the DN for the user by
substituting the user login name in the supplied pattern and attempting to bind as
that user with the login password. This is OK if all your users are stored under a
single node in the directory. If instead you wished to configure an LDAP search
filter to locate the user, you could use the following: </p><pre class="programlisting">
- <ldap-authentication-provider user-search-filter="(uid={0})"
- user-search-base="ou=people"/>
+ <span class="hl-tag"><ldap-authentication-provider</span> <span class="hl-attribute">user-search-filter</span>=<span class="hl-value">"(uid={0})"</span>
+ <span class="hl-attribute">user-search-base</span>=<span class="hl-value">"ou=people"</span><span class="hl-tag">/></span>
</pre><p> If used with the server definition above, this would
perform a search under the DN <code class="literal">ou=people,dc=springframework,dc=org</code>
using the value of the <code class="literal">user-search-filter</code> attribute as a filter.
- Again the user login name is substituted for the parameter in the filter name. If
- <code class="literal">user-search-base</code> isn't supplied, the search will be performed
- from the root. </p></div><div class="section" title="18.3.3 Loading Authorities"><div class="titlepage"><div><div><h3 class="title"><a name="d0e5818"></a>18.3.3 Loading Authorities</h3></div></div></div><p> How authorities are loaded from groups in the LDAP directory is controlled by the
- following attributes. </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>
- <code class="literal">group-search-base</code>. Defines the part of the directory
- tree under which group searches should be performed.</p></li><li class="listitem"><p>
- <code class="literal">group-role-attribute</code>. The attribute which contains
- the name of the authority defined by the group entry. Defaults to
- <code class="literal">cn</code>
- </p></li><li class="listitem"><p>
- <code class="literal">group-search-filter</code>. The filter which is used to
- search for group membership. The default is
- <code class="literal">uniqueMember={0}</code>, corresponding to the
- <code class="literal">groupOfUniqueMembers</code> LDAP class. In this case,
- the substituted parameter is the full distinguished name of the user.
- The parameter <code class="literal">{1}</code> can be used if you want to filter
- on the login name.</p></li></ul></div><p> So if we used the following configuration </p><pre class="programlisting">
- <ldap-authentication-provider user-dn-pattern="uid={0},ou=people"
- group-search-base="ou=groups" />
+ Again the user login name is substituted for the parameter in the filter name, so it
+ will search for an entry with the <code class="literal">uid</code> attribute equal to the user
+ name. If <code class="literal">user-search-base</code> isn't supplied, the search will be
+ performed from the root. </p></div><div class="section" title="19.3.3 Loading Authorities"><div class="titlepage"><div><div><h3 class="title"><a name="d0e6461"></a>19.3.3 Loading Authorities</h3></div></div></div><p> How authorities are loaded from groups in the LDAP directory is controlled by the
+ following attributes. </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> <code class="literal">group-search-base</code>. Defines the part of the directory
+ tree under which group searches should be performed.</p></li><li class="listitem"><p> <code class="literal">group-role-attribute</code>. The attribute which contains the
+ name of the authority defined by the group entry. Defaults to
+ <code class="literal">cn</code> </p></li><li class="listitem"><p> <code class="literal">group-search-filter</code>. The filter which is used to
+ search for group membership. The default is
+ <code class="literal">uniqueMember={0}</code>, corresponding to the
+ <code class="literal">groupOfUniqueMembers</code> LDAP class. In this case, the
+ substituted parameter is the full distinguished name of the user. The
+ parameter <code class="literal">{1}</code> can be used if you want to filter on the
+ login name.</p></li></ul></div><p> So if we used the following configuration </p><pre class="programlisting">
+ <span class="hl-tag"><ldap-authentication-provider</span> <span class="hl-attribute">user-dn-pattern</span>=<span class="hl-value">"uid={0},ou=people"</span>
+ <span class="hl-attribute">group-search-base</span>=<span class="hl-value">"ou=groups"</span><span class="hl-tag"> /></span>
</pre><p> and authenticated successfully as user <span class="quote">“<span class="quote">ben</span>”</span>, the subsequent
loading of authorities would perform a search under the directory entry
- <code class="literal">ou=groups,dc=springframework,dc=org</code>, looking for entries
- which contain the attribute <code class="literal">uniqueMember</code> with value
- <code class="literal">uid=ben,ou=people,dc=springframework,dc=org</code>. By default the
+ <code class="literal">ou=groups,dc=springframework,dc=org</code>, looking for entries which
+ contain the attribute <code class="literal">uniqueMember</code> with value
+ <code class="literal">uid=ben,ou=people,dc=springframework,dc=org</code>. By default the
authority names will have the prefix <code class="literal">ROLE_</code> prepended. You can
change this using the <code class="literal">role-prefix</code> attribute. If you don't want
any prefix, use <code class="literal">role-prefix="none"</code>. For more information on
loading authorities, see the Javadoc for the
- <code class="classname">DefaultLdapAuthoritiesPopulator</code> class. </p></div></div><div class="section" title="18.4 Implementation Classes"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e5883"></a>18.4 Implementation Classes</h2></div></div></div><p>The namespace configuration options we've used above are simple to use and much more
+ <code class="classname">DefaultLdapAuthoritiesPopulator</code> class. </p></div></div><div class="section" title="19.4 Implementation Classes"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e6526"></a>19.4 Implementation Classes</h2></div></div></div><p>The namespace configuration options we've used above are simple to use and much more
concise than using Spring beans explicitly. There are situations when you may need to
know how to configure Spring Security LDAP directly in your application context. You may
wish to customize the behaviour of some of the classes, for example. If you're happy
using namespace configuration then you can skip this section and the next one. </p><p> The main LDAP provider class, <code class="classname">LdapAuthenticationProvider</code>,
doesn't actually do much itself but delegates the work to two other beans, an
- <code class="interfacename">LdapAuthenticator</code> and an
- <code class="interfacename">LdapAuthoritiesPopulator</code> which are responsible for
+ <code class="interfacename">LdapAuthenticator</code> and an
+ <code class="interfacename">LdapAuthoritiesPopulator</code> which are responsible for
authenticating the user and retrieving the user's set of
- <code class="interfacename">GrantedAuthority</code>s respectively.</p><div class="section" title="18.4.1 LdapAuthenticator Implementations"><div class="titlepage"><div><div><h3 class="title"><a name="ldap-ldap-authenticators"></a>18.4.1 LdapAuthenticator Implementations</h3></div></div></div><p>The authenticator is also responsible for retrieving any required user attributes.
+ <code class="interfacename">GrantedAuthority</code>s respectively.</p><div class="section" title="19.4.1 LdapAuthenticator Implementations"><div class="titlepage"><div><div><h3 class="title"><a name="ldap-ldap-authenticators"></a>19.4.1 LdapAuthenticator Implementations</h3></div></div></div><p>The authenticator is also responsible for retrieving any required user attributes.
This is because the permissions on the attributes may depend on the type of
authentication being used. For example, if binding as the user, it may be necessary
- to read them with the user's own permissions.</p><p>There are currently two authentication strategies supplied with Spring Security: </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>Authentication directly to the LDAP server ("bind"
- authentication).</p></li><li class="listitem"><p>Password comparison, where the password supplied by the user is
- compared with the one stored in the repository. This can either be done
- by retrieving the value of the password attribute and checking it
- locally or by performing an LDAP "compare" operation, where the supplied
- password is passed to the server for comparison and the real password
- value is never retrieved.</p></li></ul></div><div class="section" title="Common Functionality"><div class="titlepage"><div><div><h4 class="title"><a name="ldap-ldap-authenticators-common"></a>Common Functionality</h4></div></div></div><p>Before it is possible to authenticate a user (by either strategy), the
+ to read them with the user's own permissions.</p><p>There are currently two authentication strategies supplied with Spring Security: </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>Authentication directly to the LDAP server ("bind" authentication).</p></li><li class="listitem"><p>Password comparison, where the password supplied by the user is compared
+ with the one stored in the repository. This can either be done by retrieving
+ the value of the password attribute and checking it locally or by performing
+ an LDAP "compare" operation, where the supplied password is passed to the
+ server for comparison and the real password value is never retrieved.</p></li></ul></div><div class="section" title="Common Functionality"><div class="titlepage"><div><div><h4 class="title"><a name="ldap-ldap-authenticators-common"></a>Common Functionality</h4></div></div></div><p>Before it is possible to authenticate a user (by either strategy), the
distinguished name (DN) has to be obtained from the login name supplied to the
application. This can be done either by simple pattern-matching (by setting the
- <span class="property">setUserDnPatterns</span> array property) or by setting the
- <span class="property">userSearch</span> property. For the DN pattern-matching
- approach, a standard Java pattern format is used, and the login name will be
- substituted for the parameter <em class="parameter"><code>{0}</code></em>. The pattern should be
- relative to the DN that the configured
- <code class="interfacename">SpringSecurityContextSource</code> will bind to (see
- the section on <a class="link" href="ldap.html#ldap-context-source" title="18.4.2 Connecting to the LDAP Server">connecting to the LDAP
- server</a> for more information on this). For example, if you are using
- an LDAP server with the URL
- <code class="literal">ldap://monkeymachine.co.uk/dc=springframework,dc=org</code>, and
+ <span class="property">setUserDnPatterns</span> array property) or by setting the
+ <span class="property">userSearch</span> property. For the DN pattern-matching approach,
+ a standard Java pattern format is used, and the login name will be substituted
+ for the parameter <em class="parameter"><code>{0}</code></em>. The pattern should be relative to
+ the DN that the configured
+ <code class="interfacename">SpringSecurityContextSource</code> will bind to (see the
+ section on <a class="link" href="ldap.html#ldap-context-source" title="19.4.2 Connecting to the LDAP Server">connecting to the LDAP
+ server</a> for more information on this). For example, if you are using an
+ LDAP server with the URL
+ <code class="literal">ldap://monkeymachine.co.uk/dc=springframework,dc=org</code>, and
have a pattern <code class="literal">uid={0},ou=greatapes</code>, then a login name of
"gorilla" will map to a DN
- <code class="literal">uid=gorilla,ou=greatapes,dc=springframework,dc=org</code>. Each
+ <code class="literal">uid=gorilla,ou=greatapes,dc=springframework,dc=org</code>. Each
configured DN pattern will be tried in turn until a match is found. For
- information on using a search, see the section on <a class="link" href="ldap.html#ldap-searchobjects" title="18.4.3 LDAP Search Objects">search objects</a> below. A combination of
- the two approaches can also be used - the patterns will be checked first and if
- no matching DN is found, the search will be used.</p></div><div class="section" title="BindAuthenticator"><div class="titlepage"><div><div><h4 class="title"><a name="ldap-ldap-authenticators-bind"></a>BindAuthenticator</h4></div></div></div><p>The class <code class="classname">BindAuthenticator</code> in the package
- <code class="filename">org.springframework.security.ldap.authentication</code>
- implements the bind authentication strategy. It simply attempts to bind as the
- user.</p></div><div class="section" title="PasswordComparisonAuthenticator"><div class="titlepage"><div><div><h4 class="title"><a name="ldap-ldap-authenticators-password"></a>PasswordComparisonAuthenticator</h4></div></div></div><p>The class <code class="classname">PasswordComparisonAuthenticator</code> implements
- the password comparison authentication strategy.</p></div><div class="section" title="Active Directory Authentication"><div class="titlepage"><div><div><h4 class="title"><a name="ldap-ldap-authenticators-active-directory"></a>Active Directory Authentication</h4></div></div></div><p>In addition to standard LDAP authentication (binding with a DN), Active
- Directory has its own non-standard syntax for user authentication.</p></div></div><div class="section" title="18.4.2 Connecting to the LDAP Server"><div class="titlepage"><div><div><h3 class="title"><a name="ldap-context-source"></a>18.4.2 Connecting to the LDAP Server</h3></div></div></div><p>The beans discussed above have to be able to connect to the server. They both have
+ information on using a search, see the section on <a class="link" href="ldap.html#ldap-searchobjects" title="19.4.3 LDAP Search Objects">search objects</a> below. A combination of the
+ two approaches can also be used - the patterns will be checked first and if no
+ matching DN is found, the search will be used.</p></div><div class="section" title="BindAuthenticator"><div class="titlepage"><div><div><h4 class="title"><a name="ldap-ldap-authenticators-bind"></a>BindAuthenticator</h4></div></div></div><p>The class <code class="classname">BindAuthenticator</code> in the package
+ <code class="filename">org.springframework.security.ldap.authentication</code> implements
+ the bind authentication strategy. It simply attempts to bind as the user.</p></div><div class="section" title="PasswordComparisonAuthenticator"><div class="titlepage"><div><div><h4 class="title"><a name="ldap-ldap-authenticators-password"></a>PasswordComparisonAuthenticator</h4></div></div></div><p>The class <code class="classname">PasswordComparisonAuthenticator</code> implements
+ the password comparison authentication strategy.</p></div></div><div class="section" title="19.4.2 Connecting to the LDAP Server"><div class="titlepage"><div><div><h3 class="title"><a name="ldap-context-source"></a>19.4.2 Connecting to the LDAP Server</h3></div></div></div><p>The beans discussed above have to be able to connect to the server. They both have
to be supplied with a <code class="interfacename">SpringSecurityContextSource</code>
which is an extension of Spring LDAP's <code class="interfacename">ContextSource</code>.
Unless you have special requirements, you will usually configure a
- <code class="classname">DefaultSpringSecurityContextSource</code> bean, which can be
+ <code class="classname">DefaultSpringSecurityContextSource</code> bean, which can be
configured with the URL of your LDAP server and optionally with the username and
password of a "manager" user which will be used by default when binding to the
server (instead of binding anonymously). For more information read the Javadoc for
this class and for Spring LDAP's <code class="classname">AbstractContextSource</code>.
- </p></div><div class="section" title="18.4.3 LDAP Search Objects"><div class="titlepage"><div><div><h3 class="title"><a name="ldap-searchobjects"></a>18.4.3 LDAP Search Objects</h3></div></div></div><p>Often a more complicated strategy than simple DN-matching is required to
- locate a user entry in the directory. This can be encapsulated in an
- <code class="interfacename">LdapUserSearch</code> instance which can be supplied to
- the authenticator implementations, for example, to allow them to locate a user. The
+ </p></div><div class="section" title="19.4.3 LDAP Search Objects"><div class="titlepage"><div><div><h3 class="title"><a name="ldap-searchobjects"></a>19.4.3 LDAP Search Objects</h3></div></div></div><p>Often a more complicated strategy than simple DN-matching is required to locate a
+ user entry in the directory. This can be encapsulated in an
+ <code class="interfacename">LdapUserSearch</code> instance which can be supplied to the
+ authenticator implementations, for example, to allow them to locate a user. The
supplied implementation is <code class="classname">FilterBasedLdapUserSearch</code>.</p><div class="section" title="FilterBasedLdapUserSearch"><div class="titlepage"><div><div><h4 class="title"><a name="ldap-searchobjects-filter"></a>
- <code class="classname">FilterBasedLdapUserSearch</code>
- </h4></div></div></div><p>This bean uses an LDAP filter to match the user object in the directory. The
+ <code class="classname">FilterBasedLdapUserSearch</code> </h4></div></div></div><p>This bean uses an LDAP filter to match the user object in the directory. The
process is explained in the Javadoc for the corresponding search method on the
- <a class="link" href="http://java.sun.com/j2se/1.4.2/docs/api/javax/naming/directory/DirContext.html#search(javax.naming.Name,%20java.lang.String,%20java.lang.Object[],%20javax.naming.directory.SearchControls)" target="_top">JDK DirContext class</a>. As explained there, the search filter can be
+ <a class="link" href="http://java.sun.com/j2se/1.4.2/docs/api/javax/naming/directory/DirContext.html#search(javax.naming.Name,%20java.lang.String,%20java.lang.Object[],%20javax.naming.directory.SearchControls)" target="_top">JDK DirContext class</a>. As explained there, the search filter can be
supplied with parameters. For this class, the only valid parameter is
- <em class="parameter"><code>{0}</code></em> which will be replaced with the user's login
- name.</p></div></div><div class="section" title="18.4.4 LdapAuthoritiesPopulator"><div class="titlepage"><div><div><h3 class="title"><a name="ldap-authorities"></a>18.4.4 LdapAuthoritiesPopulator</h3></div></div></div><p> After authenticating the user successfully, the
- <code class="classname">LdapAuthenticationProvider</code> will attempt to load a set of
+ <em class="parameter"><code>{0}</code></em> which will be replaced with the user's login
+ name.</p></div></div><div class="section" title="19.4.4 LdapAuthoritiesPopulator"><div class="titlepage"><div><div><h3 class="title"><a name="ldap-authorities"></a>19.4.4 LdapAuthoritiesPopulator</h3></div></div></div><p> After authenticating the user successfully, the
+ <code class="classname">LdapAuthenticationProvider</code> will attempt to load a set of
authorities for the user by calling the configured
- <code class="interfacename">LdapAuthoritiesPopulator</code> bean. The
- <code class="classname">DefaultLdapAuthoritiesPopulator</code> is an implementation
- which will load the authorities by searching the directory for groups of which the
- user is a member (typically these will be <code class="literal">groupOfNames</code> or
- <code class="literal">groupOfUniqueNames</code> entries in the directory). Consult the
- Javadoc for this class for more details on how it works. </p><p>If you want to use LDAP only for authentication, but load the authorities from a
+ <code class="interfacename">LdapAuthoritiesPopulator</code> bean. The
+ <code class="classname">DefaultLdapAuthoritiesPopulator</code> is an implementation which
+ will load the authorities by searching the directory for groups of which the user is
+ a member (typically these will be <code class="literal">groupOfNames</code> or
+ <code class="literal">groupOfUniqueNames</code> entries in the directory). Consult the Javadoc
+ for this class for more details on how it works. </p><p>If you want to use LDAP only for authentication, but load the authorities from a
difference source (such as a database) then you can provide your own implementation
- of this interface and inject that instead.</p></div><div class="section" title="18.4.5 Spring Bean Configuration"><div class="titlepage"><div><div><h3 class="title"><a name="ldap-bean-config"></a>18.4.5 Spring Bean Configuration</h3></div></div></div><p>A typical configuration, using some of the beans we've discussed here, might look
+ of this interface and inject that instead.</p></div><div class="section" title="19.4.5 Spring Bean Configuration"><div class="titlepage"><div><div><h3 class="title"><a name="ldap-bean-config"></a>19.4.5 Spring Bean Configuration</h3></div></div></div><p>A typical configuration, using some of the beans we've discussed here, might look
like this: </p><pre class="programlisting">
-<bean id="contextSource"
- class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
- <constructor-arg value="ldap://monkeymachine:389/dc=springframework,dc=org"/>
- <property name="userDn" value="cn=manager,dc=springframework,dc=org"/>
- <property name="password" value="password"/>
-</bean>
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"contextSource"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.ldap.DefaultSpringSecurityContextSource"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">value</span>=<span class="hl-value">"ldap://monkeymachine:389/dc=springframework,dc=org"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"userDn"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"cn=manager,dc=springframework,dc=org"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"password"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"password"</span><span class="hl-tag">/></span>
+<span class="hl-tag"></bean></span>
-<bean id="ldapAuthProvider"
- class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
- <constructor-arg>
- <bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
- <constructor-arg ref="contextSource"/>
- <property name="userDnPatterns">
- <list><value>uid={0},ou=people</value></list>
- </property>
- </bean>
- </constructor-arg>
- <constructor-arg>
- <bean
- class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
- <constructor-arg ref="contextSource"/>
- <constructor-arg value="ou=groups"/>
- <property name="groupRoleAttribute" value="ou"/>
- </bean>
- </constructor-arg>
-</bean>
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"ldapAuthProvider"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.ldap.authentication.LdapAuthenticationProvider"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><constructor-arg></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.ldap.authentication.BindAuthenticator"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"contextSource"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"userDnPatterns"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><list></span><span class="hl-tag"><value></span>uid={0},ou=people<span class="hl-tag"></value></span><span class="hl-tag"></list></span>
+ <span class="hl-tag"></property></span>
+ <span class="hl-tag"></bean></span>
+ <span class="hl-tag"></constructor-arg></span>
+ <span class="hl-tag"><constructor-arg></span>
+ <span class="hl-tag"><bean</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"contextSource"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">value</span>=<span class="hl-value">"ou=groups"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"groupRoleAttribute"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"ou"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></bean></span>
+ <span class="hl-tag"></constructor-arg></span>
+<span class="hl-tag"></bean></span>
</pre><p> This would set up the provider to access an LDAP server
with URL <code class="literal">ldap://monkeymachine:389/dc=springframework,dc=org</code>.
Authentication will be performed by attempting to bind with the DN
- <code class="literal">uid=<user-login-name>,ou=people,dc=springframework,dc=org</code>.
+ <code class="literal">uid=<user-login-name>,ou=people,dc=springframework,dc=org</code>.
After successful authentication, roles will be assigned to the user by searching
under the DN <code class="literal">ou=groups,dc=springframework,dc=org</code> with the default
filter <code class="literal">(member=<user's-DN>)</code>. The role name will be taken
from the <span class="quote">“<span class="quote">ou</span>”</span> attribute of each match.</p><p>To configure a user search object, which uses the filter
- <code class="literal">(uid=<user-login-name>)</code> for use instead of the
- DN-pattern (or in addition to it), you would configure the following bean </p><pre class="programlisting">
-<bean id="userSearch"
- class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
- <constructor-arg index="0" value=""/>
- <constructor-arg index="1" value="(uid={0})"/>
- <constructor-arg index="2" ref="contextSource" />
-</bean>
+ <code class="literal">(uid=<user-login-name>)</code> for use instead of the DN-pattern
+ (or in addition to it), you would configure the following bean </p><pre class="programlisting">
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"userSearch"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.ldap.search.FilterBasedLdapUserSearch"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">index</span>=<span class="hl-value">"0"</span> <span class="hl-attribute">value</span>=<span class="hl-value">""</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">index</span>=<span class="hl-value">"1"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"(uid={0})"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">index</span>=<span class="hl-value">"2"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"contextSource"</span><span class="hl-tag"> /></span>
+<span class="hl-tag"></bean></span>
</pre><p> and use it by setting the
- <code class="classname">BindAuthenticator</code> bean's <span class="property">userSearch</span>
+ <code class="classname">BindAuthenticator</code> bean's <span class="property">userSearch</span>
property. The authenticator would then call the search object to obtain the correct
- user's DN before attempting to bind as this user.</p></div><div class="section" title="18.4.6 LDAP Attributes and Customized UserDetails"><div class="titlepage"><div><div><h3 class="title"><a name="ldap-custom-user-details"></a>18.4.6 LDAP Attributes and Customized UserDetails</h3></div></div></div><p> The net result of an authentication using
- <code class="classname">LdapAuthenticationProvider</code> is the same as a normal Spring
+ user's DN before attempting to bind as this user.</p></div><div class="section" title="19.4.6 LDAP Attributes and Customized UserDetails"><div class="titlepage"><div><div><h3 class="title"><a name="ldap-custom-user-details"></a>19.4.6 LDAP Attributes and Customized UserDetails</h3></div></div></div><p> The net result of an authentication using
+ <code class="classname">LdapAuthenticationProvider</code> is the same as a normal Spring
Security authentication using the standard
- <code class="interfacename">UserDetailsService</code> interface. A
- <code class="interfacename">UserDetails</code> object is created and stored in the
+ <code class="interfacename">UserDetailsService</code> interface. A
+ <code class="interfacename">UserDetails</code> object is created and stored in the
returned <code class="interfacename">Authentication</code> object. As with using a
- <code class="interfacename">UserDetailsService</code>, a common requirement is to be
+ <code class="interfacename">UserDetailsService</code>, a common requirement is to be
able to customize this implementation and add extra properties. When using LDAP,
these will normally be attributes from the user entry. The creation of the
- <code class="interfacename">UserDetails</code> object is controlled by the
- provider's <code class="interfacename">UserDetailsContextMapper</code> strategy, which
- is responsible for mapping user objects to and from LDAP context data: </p><pre class="programlisting">
-public interface UserDetailsContextMapper {
+ <code class="interfacename">UserDetails</code> object is controlled by the provider's
+ <code class="interfacename">UserDetailsContextMapper</code> strategy, which is
+ responsible for mapping user objects to and from LDAP context data: </p><pre class="programlisting">
+<span class="hl-keyword">public</span> <span class="hl-keyword">interface</span> UserDetailsContextMapper {
UserDetails mapUserFromContext(DirContextOperations ctx, String username,
Collection<GrantedAuthority> authorities);
- void mapUserToContext(UserDetails user, DirContextAdapter ctx);
+ <span class="hl-keyword">void</span> mapUserToContext(UserDetails user, DirContextAdapter ctx);
}
</pre><p> Only the first method is relevant for authentication. If you
provide an implementation of this interface and inject it into the
@@ -242,7 +237,43 @@ public interface UserDetailsContextMapper {
context returned from the bind operation will be used to read the attributes,
otherwise the data will be read using the standard context obtained from the
configured <code class="interfacename">ContextSource</code> (when a search is configured
- to locate the user, this will be the data returned by the search object). </p></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
+ to locate the user, this will be the data returned by the search object). </p></div></div><div class="section" title="19.5 Active Directory Authentication"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ldap-active-directory"></a>19.5 Active Directory Authentication</h2></div></div></div><p>Active Directory supports its own non-standard authentication options, and the normal usage pattern
+ doesn't fit too cleanly with the standard <code class="classname">LdapAuthenticationProvider</code>.
+ Typically authentication is performed using the domain username (in the form <code class="literal">user at domain</code>),
+ rather than using an LDAP distinguished name. To make this easier, Spring Security 3.1 has an
+ authentication provider which is customized for a typical Active Directory setup.
+ </p><div class="section" title="19.5.1 ActiveDirectoryLdapAuthenticationProvider"><div class="titlepage"><div><div><h3 class="title"><a name="d0e6780"></a>19.5.1 <code class="classname">ActiveDirectoryLdapAuthenticationProvider</code></h3></div></div></div><p> Configuring <code class="classname">ActiveDirectoryLdapAuthenticationProvider</code> is
+ quite straightforward. You just need to supply the domain name and an LDAP URL
+ supplying the address of the server <sup>[<a name="d0e6789" href="#ftn.d0e6789" class="footnote">22</a>]</sup>. An example configuration would then look like this: </p><pre class="programlisting">
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"adAuthenticationProvider"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">value</span>=<span class="hl-value">"mydomain.com"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">value</span>=<span class="hl-value">"ldap://adserver.mydomain.com/"</span><span class="hl-tag"> /></span>
+<span class="hl-tag"></bean></span>
+}
+ </pre><p> Note that there is no need to specify a separate
+ <code class="literal">ContextSource</code> in order to define the server location - the bean
+ is completely self-contained. A user named <span class="quote">“<span class="quote">Sharon</span>”</span>, for example, would
+ then be able to authenticate by entering either the username
+ <code class="literal">sharon</code> or the full Active Directory
+ <code class="literal">userPrincipalName</code>, namely <code class="literal">sharon at mydomain.com</code>.
+ The user's directory entry will then be located, and the attributes returned for
+ possible use in customizing the created <code class="interfacename">UserDetails</code>
+ object (a <code class="interfacename">UserDetailsContextMapper</code> can be injected
+ for this purpose, as described above). All interaction with the directory takes
+ place with the identity of the user themselves. There is no concept of a
+ <span class="quote">“<span class="quote">manager</span>”</span> user. </p><p>By default, the user authorities are obtained from the <code class="literal">memberOf</code>
+ attribute values of the user entry. The authorities allocated to the user can again
+ be customized using a <code class="interfacename">UserDetailsContextMapper</code>. You
+ can also inject a <code class="interfacename">GrantedAuthoritiesMaper</code> into the
+ provider instance to control the authorities which end up in the
+ <code class="interfacename">Authentication</code> object.</p><div class="section" title="Active Directory Error Codes"><div class="titlepage"><div><div><h4 class="title"><a name="d0e6834"></a>Active Directory Error Codes</h4></div></div></div><p>By default, a failed result will cause a standard Spring Security
+ <code class="classname">BadCredentialsException</code>. If you set the property
+ <code class="literal">convertSubErrorCodesToExceptions</code> to <code class="literal">true</code>,
+ the exception messages will be parsed to attempt to extract the Active
+ Directory-specific error code and raise a more specific exception. Check the
+ class Javadoc for more information.</p></div></div></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e6789" href="#d0e6789" class="para">22</a>] </sup>It is also possible to obtain the server's IP address using a DNS lookup. This
+ is not currently supported, but hopefully will be in a future version.</p></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
- </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="preauth.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="advanced-topics.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="taglibs.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">17. Pre-Authentication Scenarios </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 19. JSP Tag Libraries</td></tr></table></div></body></html>
\ No newline at end of file
+ </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="preauth.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="advanced-topics.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="taglibs.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">18. Pre-Authentication Scenarios </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 20. JSP Tag Libraries</td></tr></table></div></body></html>
\ No newline at end of file
diff --git a/docs/reference/ns-config.html b/docs/reference/ns-config.html
index e519412..ee71394 100644
--- a/docs/reference/ns-config.html
+++ b/docs/reference/ns-config.html
@@ -1,6 +1,6 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>2. Security Namespace Configuration</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="getting-started.html" title="Part I. Getting Started"><link rel="prev" href="introduction.html" title="1. Introduction"><link rel="next" href="sample-apps.html" title="3. Sample Applications"><!--Begin Google Analytics code--><script type="text/javascript">
+ <title>3. Security Namespace Configuration</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="getting-started.html" title="Part I. Getting Started"><link rel="prev" href="new-3.1.html" title="2. What's new in Spring Security 3.1"><link rel="next" href="sample-apps.html" title="4. Sample Applications"><!--Begin Google Analytics code--><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
@@ -8,25 +8,25 @@
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
- </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">2. Security Namespace Configuration</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="introduction.html">Prev</a> </td><th width="60%" align="center">Part I. Getting Started</th><td width="20%" align="right"> <a accesskey="n" href="sample-apps.html">Next</a></td></tr></table><hr></div><div class="chapter" title="2. Security Namespace Configuration"><div class="titlepage"><div><div><h1 class="title"><a name="ns-config"></a>Security Namespace Configuration</h1></div></div></div><div class="section" title="2.1 Introduction"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e344"></a>2.1 Introduction</h2></div></div></div><p> Namespace configuration has been available since version 2.0 of the Spring framework. It
- allows you to supplement the traditional Spring beans application context syntax with elements
- from additional XML schema. You can find more information in the Spring <a class="link" href="http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/htmlsingle/spring-framework-reference.htm" target="_top"> Reference Documentation</a>. A namespace element can be used simply to allow a more
- concise way of configuring an individual bean or, more powerfully, to define an alternative
- configuration syntax which more closely matches the problem domain and hides the underlying
- complexity from the user. A simple element may conceal the fact that multiple beans and
- processing steps are being added to the application context. For example, adding the following
- element from the security namespace to an application context will start up an embedded LDAP
- server for testing use within the application: </p><pre class="programlisting">
+ </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">3. Security Namespace Configuration</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="new-3.1.html">Prev</a> </td><th width="60%" align="center">Part I. Getting Started</th><td width="20%" align="right"> <a accesskey="n" href="sample-apps.html">Next</a></td></tr></table><hr></div><div class="chapter" title="3. Security Namespace Configuration"><div class="titlepage"><div><div><h1 class="title"><a name="ns-config"></a>Security Namespace Configuration</h1></div></div></div><div class="section" title="3.1 Introduction"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e507"></a>3.1 Introduction</h2></div></div></div><p> Namespace configuration has been available since version 2.0 of the Spring framework.
+ It allows you to supplement the traditional Spring beans application context syntax with
+ elements from additional XML schema. You can find more information in the Spring <a class="link" href="http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/htmlsingle/spring-framework-reference.html" target="_top"> Reference Documentation</a>. A namespace element can be used simply to allow a more
+ concise way of configuring an individual bean or, more powerfully, to define an
+ alternative configuration syntax which more closely matches the problem domain and hides
+ the underlying complexity from the user. A simple element may conceal the fact that
+ multiple beans and processing steps are being added to the application context. For
+ example, adding the following element from the security namespace to an application
+ context will start up an embedded LDAP server for testing use within the application: </p><pre class="programlisting">
<span class="hl-tag"><security:ldap-server /></span>
</pre><p> This is much simpler than wiring up the equivalent Apache Directory Server
- beans. The most common alternative configuration requirements are supported by attributes on
- the <code class="literal">ldap-server</code> element and the user is isolated from worrying about which
- beans they need to create and what the bean property names are. <sup>[<a name="d0e358" href="#ftn.d0e358" class="footnote">1</a>]</sup>. Use of a good XML editor while
- editing the application context file should provide information on the attributes and elements
- that are available. We would recommend that you try out the <a class="link" href="http://www.springsource.com/products/sts" target="_top">SpringSource Tool Suite</a> as it
- has special features for working with standard Spring namespaces. </p><p> To start using the security namespace in your application context, you first need to make
- sure that the <code class="literal">spring-security-config</code> jar is on your classpath. Then all you need to do is
- add the schema declaration to your application context file: </p><pre class="programlisting">
+ beans. The most common alternative configuration requirements are supported by
+ attributes on the <code class="literal">ldap-server</code> element and the user is isolated from
+ worrying about which beans they need to create and what the bean property names are. <sup>[<a name="d0e521" href="#ftn.d0e521" class="footnote">1</a>]</sup>. Use of a good XML editor while editing the application context file should
+ provide information on the attributes and elements that are available. We would
+ recommend that you try out the <a class="link" href="http://www.springsource.com/products/sts" target="_top">SpringSource Tool Suite</a> as
+ it has special features for working with standard Spring namespaces. </p><p> To start using the security namespace in your application context, you need to have
+ the <code class="literal">spring-security-config</code> jar on your classpath. Then all you need
+ to do is add the schema declaration to your application context file: </p><pre class="programlisting">
<span class="hl-tag"><beans</span> <span class="hl-attribute">xmlns</span>=<span class="hl-value">"http://www.springframework.org/schema/beans"</span>
<span class="hl-attribute">xmlns:security</span>=<span class="hl-value">"http://www.springframework.org/schema/security"</span>
@@ -34,52 +34,46 @@
<span class="hl-attribute">xsi:schemaLocation</span>=<span class="hl-value">"http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
- http://www.springframework.org/schema/security/spring-security-3.0.3.xsd"</span><span class="hl-tag">></span>
+ http://www.springframework.org/schema/security/spring-security-3.1.xsd"</span><span class="hl-tag">></span>
...
<span class="hl-tag"></beans></span>
</pre><p> In many of the examples you will see (and in the sample) applications, we
- will often use "security" as the default namespace rather than "beans", which means we can
- omit the prefix on all the security namespace elements, making the content easier to read. You
- may also want to do this if you have your application context divided up into separate files
- and have most of your security configuration in one of them. Your security application context
- file would then start like this </p><pre class="programlisting">
+ will often use "security" as the default namespace rather than "beans", which means we
+ can omit the prefix on all the security namespace elements, making the content easier to
+ read. You may also want to do this if you have your application context divided up into
+ separate files and have most of your security configuration in one of them. Your
+ security application context file would then start like this </p><pre class="programlisting">
<span class="hl-tag"><beans:beans</span> <span class="hl-attribute">xmlns</span>=<span class="hl-value">"http://www.springframework.org/schema/security"</span>
<span class="hl-attribute">xmlns:beans</span>=<span class="hl-value">"http://www.springframework.org/schema/beans"</span>
<span class="hl-attribute">xmlns:xsi</span>=<span class="hl-value">"http://www.w3.org/2001/XMLSchema-instance"</span>
<span class="hl-attribute">xsi:schemaLocation</span>=<span class="hl-value">"http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
- http://www.springframework.org/schema/security/spring-security-3.0.3.xsd"</span><span class="hl-tag">></span>
+ http://www.springframework.org/schema/security/spring-security-3.1.xsd"</span><span class="hl-tag">></span>
...
<span class="hl-tag"></beans:beans></span>
-</pre><p> We'll assume this syntax is being used from now on in this chapter. </p><div class="section" title="2.1.1 Design of the Namespace"><div class="titlepage"><div><div><h3 class="title"><a name="d0e382"></a>2.1.1 Design of the Namespace</h3></div></div></div><p> The namespace is designed to capture the most common uses of the framework and provide
- a simplified and concise syntax for enabling them within an application. The design is based
- around the large-scale dependencies within the framework, and can be divided up into the
- following areas: </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>
- <span class="emphasis"><em>Web/HTTP Security</em></span> - the most complex part. Sets up the filters
- and related service beans used to apply the framework authentication mechanisms, to
- secure URLs, render login and error pages and much
- more.</p></li><li class="listitem"><p>
- <span class="emphasis"><em>Business Object (Method) Security</em></span> - options for securing the
- service layer.</p></li><li class="listitem"><p>
- <span class="emphasis"><em>AuthenticationManager</em></span> - handles authentication requests from
- other parts of the framework.</p></li><li class="listitem"><p>
- <span class="emphasis"><em>AccessDecisionManager</em></span> - provides access decisions for web and
- method security. A default one will be registered, but you can also choose to use a
- custom one, declared using normal Spring bean
- syntax.</p></li><li class="listitem"><p>
- <span class="emphasis"><em>AuthenticationProvider</em></span>s - mechanisms against which the
- authentication manager authenticates users. The namespace provides supports for
- several standard options and also a means of adding custom beans declared using a
- traditional syntax. </p></li><li class="listitem"><p>
- <span class="emphasis"><em>UserDetailsService</em></span> - closely related to authentication providers,
- but often also required by other beans.</p></li></ul></div><p>We'll see how to configure these in the following sections.</p></div></div><div class="section" title="2.2 Getting Started with Security Namespace Configuration"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ns-getting-started"></a>2.2 Getting Started with Security Namespace Configuration</h2></div></div></div><p> In this section, we'll look at how you can build up a namespace configuration to use some
- of the main features of the framework. Let's assume you initially want to get up and running
- as quickly as possible and add authentication support and access control to an existing web
- application, with a few test logins. Then we'll look at how to change over to authenticating
- against a database or other security repository. In later sections we'll introduce more
- advanced namespace configuration options. </p><div class="section" title="2.2.1 web.xml Configuration"><div class="titlepage"><div><div><h3 class="title"><a name="ns-web-xml"></a>2.2.1 <code class="literal">web.xml</code> Configuration</h3></div></div></div><p> The first thing you need to do is add the following filter declaration to your
- <code class="literal">web.xml</code> file: </p><pre class="programlisting">
+</pre><p> We'll assume this syntax is being used from now on in this chapter. </p><div class="section" title="3.1.1 Design of the Namespace"><div class="titlepage"><div><div><h3 class="title"><a name="d0e545"></a>3.1.1 Design of the Namespace</h3></div></div></div><p> The namespace is designed to capture the most common uses of the framework and
+ provide a simplified and concise syntax for enabling them within an application. The
+ design is based around the large-scale dependencies within the framework, and can be
+ divided up into the following areas: </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> <span class="emphasis"><em>Web/HTTP Security</em></span> - the most complex part. Sets up
+ the filters and related service beans used to apply the framework
+ authentication mechanisms, to secure URLs, render login and error pages and
+ much more.</p></li><li class="listitem"><p> <span class="emphasis"><em>Business Object (Method) Security</em></span> - options for
+ securing the service layer.</p></li><li class="listitem"><p> <span class="emphasis"><em>AuthenticationManager</em></span> - handles authentication
+ requests from other parts of the framework.</p></li><li class="listitem"><p> <span class="emphasis"><em>AccessDecisionManager</em></span> - provides access decisions
+ for web and method security. A default one will be registered, but you can
+ also choose to use a custom one, declared using normal Spring bean
+ syntax.</p></li><li class="listitem"><p> <span class="emphasis"><em>AuthenticationProvider</em></span>s - mechanisms against which
+ the authentication manager authenticates users. The namespace provides
+ supports for several standard options and also a means of adding custom
+ beans declared using a traditional syntax. </p></li><li class="listitem"><p> <span class="emphasis"><em>UserDetailsService</em></span> - closely related to
+ authentication providers, but often also required by other beans.</p></li></ul></div><p>We'll see how to configure these in the following sections.</p></div></div><div class="section" title="3.2 Getting Started with Security Namespace Configuration"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ns-getting-started"></a>3.2 Getting Started with Security Namespace Configuration</h2></div></div></div><p> In this section, we'll look at how you can build up a namespace configuration to use
+ some of the main features of the framework. Let's assume you initially want to get up
+ and running as quickly as possible and add authentication support and access control to
+ an existing web application, with a few test logins. Then we'll look at how to change
+ over to authenticating against a database or other security repository. In later
+ sections we'll introduce more advanced namespace configuration options. </p><div class="section" title="3.2.1 web.xml Configuration"><div class="titlepage"><div><div><h3 class="title"><a name="ns-web-xml"></a>3.2.1 <code class="literal">web.xml</code> Configuration</h3></div></div></div><p> The first thing you need to do is add the following filter declaration to your
+ <code class="literal">web.xml</code> file: </p><pre class="programlisting">
<span class="hl-tag"><filter></span>
<span class="hl-tag"><filter-name></span>springSecurityFilterChain<span class="hl-tag"></filter-name></span>
<span class="hl-tag"><filter-class></span>org.springframework.web.filter.DelegatingFilterProxy<span class="hl-tag"></filter-class></span>
@@ -90,37 +84,40 @@
<span class="hl-tag"><url-pattern></span>/*<span class="hl-tag"></url-pattern></span>
<span class="hl-tag"></filter-mapping></span>
</pre><p> This provides a hook into the Spring Security web
- infrastructure. <code class="classname">DelegatingFilterProxy</code> is a Spring Framework class
- which delegates to a filter implementation which is defined as a Spring bean in your
- application context. In this case, the bean is named
- <span class="quote">“<span class="quote">springSecurityFilterChain</span>”</span>, which is an internal infrastructure bean created
- by the namespace to handle web security. Note that you should not use this bean name
- yourself. Once you've added this to your <code class="filename">web.xml</code>, you're ready to start
- editing your application context file. Web security services are configured using the
- <code class="literal"><http></code> element. </p></div><div class="section" title="2.2.2 A Minimal <http> Configuration"><div class="titlepage"><div><div><h3 class="title"><a name="ns-minimal"></a>2.2.2 A Minimal <code class="literal"><http></code> Configuration</h3></div></div></div><p> All you need to enable web security to begin with is </p><pre class="programlisting">
+ infrastructure. <code class="classname">DelegatingFilterProxy</code> is a Spring Framework
+ class which delegates to a filter implementation which is defined as a Spring bean
+ in your application context. In this case, the bean is named
+ <span class="quote">“<span class="quote">springSecurityFilterChain</span>”</span>, which is an internal infrastructure bean
+ created by the namespace to handle web security. Note that you should not use this
+ bean name yourself. Once you've added this to your <code class="filename">web.xml</code>,
+ you're ready to start editing your application context file. Web security services
+ are configured using the <code class="literal"><http></code> element. </p></div><div class="section" title="3.2.2 A Minimal <http> Configuration"><div class="titlepage"><div><div><h3 class="title"><a name="ns-minimal"></a>3.2.2 A Minimal <code class="literal"><http></code> Configuration</h3></div></div></div><p> All you need to enable web security to begin with is </p><pre class="programlisting">
<span class="hl-tag"><http</span> <span class="hl-attribute">auto-config</span>=<span class="hl-value">'true'</span><span class="hl-tag">></span>
<span class="hl-tag"><intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/**"</span> <span class="hl-attribute">access</span>=<span class="hl-value">"ROLE_USER"</span><span class="hl-tag"> /></span>
<span class="hl-tag"></http></span>
</pre><p> Which says that we want all URLs within our application to be secured,
- requiring the role <code class="literal">ROLE_USER</code> to access them. The
- <code class="literal"><http></code> element is the parent for all web-related namespace
- functionality. The <code class="literal"><intercept-url></code> element defines a
- <code class="literal">pattern</code> which is matched against the URLs of incoming requests using an
- ant path style syntax<sup>[<a name="d0e480" href="#ftn.d0e480" class="footnote">2</a>]</sup>. The <code class="literal">access</code> attribute defines the access
- requirements for requests matching the given pattern. With the default configuration, this
- is typically a comma-separated list of roles, one of which a user must have to be allowed to
- make the request. The prefix <span class="quote">“<span class="quote">ROLE_</span>”</span> is a marker which indicates that a simple
- comparison with the user's authorities should be made. In other words, a normal role-based
- check should be used. Access-control in Spring Security is not limited to the use of simple
- roles (hence the use of the prefix to differentiate between different types of security
- attributes). We'll see later how the interpretation can vary<sup>[<a name="d0e493" href="#ftn.d0e493" class="footnote">3</a>]</sup>.</p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>You can use multiple <code class="literal"><intercept-url></code> elements to define
- different access requirements for different sets of URLs, but they will be evaluated in
- the order listed and the first match will be used. So you must put the most specific
- matches at the top. You can also add a <code class="literal">method</code> attribute to limit the
- match to a particular HTTP method (<code class="literal">GET</code>, <code class="literal">POST</code>,
- <code class="literal">PUT</code> etc.). If a request matches multiple patterns, the
- method-specific match will take precedence regardless of ordering.</p></td></tr></table></div><p> To add some users, you can define a set of test data directly in the namespace: </p><pre class="programlisting">
+ requiring the role <code class="literal">ROLE_USER</code> to access them. The
+ <code class="literal"><http></code> element is the parent for all web-related namespace
+ functionality. The <code class="literal"><intercept-url></code> element defines a
+ <code class="literal">pattern</code> which is matched against the URLs of incoming requests
+ using an ant path style syntax<sup>[<a name="d0e643" href="#ftn.d0e643" class="footnote">2</a>]</sup>. You can also use regular-expression matching as an alternative (see the
+ namespace appendix for more details). The <code class="literal">access</code> attribute
+ defines the access requirements for requests matching the given pattern. With the
+ default configuration, this is typically a comma-separated list of roles, one of
+ which a user must have to be allowed to make the request. The prefix
+ <span class="quote">“<span class="quote">ROLE_</span>”</span> is a marker which indicates that a simple comparison with the
+ user's authorities should be made. In other words, a normal role-based check should
+ be used. Access-control in Spring Security is not limited to the use of simple roles
+ (hence the use of the prefix to differentiate between different types of security
+ attributes). We'll see later how the interpretation can vary<sup>[<a name="d0e656" href="#ftn.d0e656" class="footnote">3</a>]</sup>.</p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>You can use multiple <code class="literal"><intercept-url></code> elements to
+ define different access requirements for different sets of URLs, but they will
+ be evaluated in the order listed and the first match will be used. So you must
+ put the most specific matches at the top. You can also add a
+ <code class="literal">method</code> attribute to limit the match to a particular HTTP
+ method (<code class="literal">GET</code>, <code class="literal">POST</code>, <code class="literal">PUT</code>
+ etc.). If a request matches multiple patterns, the method-specific match will
+ take precedence regardless of ordering.</p></td></tr></table></div><p> To add some users, you can define a set of test data directly in the namespace: </p><pre class="programlisting">
<span class="hl-tag"><authentication-manager></span>
<span class="hl-tag"><authentication-provider></span>
<span class="hl-tag"><user-service></span>
@@ -130,107 +127,132 @@
<span class="hl-tag"></authentication-provider></span>
<span class="hl-tag"></authentication-manager></span>
- </pre><div class="sidebar"><p class="title"><b></b></p><p>If you are familiar with pre-namespace versions of the framework, you can probably
- already guess roughly what's going on here. The <code class="literal"><http></code> element is
- responsible for creating a <code class="classname">FilterChainProxy</code> and the filter beans
- which it uses. Common problems like incorrect filter ordering are no longer an issue as
- the filter positions are predefined.</p><p>The <code class="literal"><authentication-provider></code> element creates a
- <code class="classname">DaoAuthenticationProvider</code> bean and the
- <code class="literal"><user-service></code> element creates an
- <code class="classname">InMemoryDaoImpl</code>. All <code class="literal">authentication-provider</code>
- elements must be children of the <code class="literal"><authentication-manager></code> element,
- which creates a <code class="classname">ProviderManager</code> and registers the authentication
- providers with it. You can find more detailed information on the beans that are created in
- the <a class="link" href="appendix-namespace.html" title="Appendix B. The Security Namespace">namespace appendix</a>. It's worth
- cross-checking this if you want to start understanding what the important classes in the
- framework are and how they are used, particularly if you want to customise things
- later.</p></div><p> The configuration above defines two users, their passwords and their roles within the
- application (which will be used for access control). It is also possible to load user
- information from a standard properties file using the <code class="literal">properties</code>
- attribute on <code class="literal">user-service</code>. See the section on <a class="link" href="core-services.html#core-services-in-memory-service" title="6.2.1 In-Memory Authentication">in-memory authentication</a> for more
- details on the file format. Using the <code class="literal"><authentication-provider></code>
- element means that the user information will be used by the authentication manager to
- process authentication requests. You can have multiple
- <code class="literal"><authentication-provider></code> elements to define different
- authentication sources and each will be consulted in turn.</p><p> At this point you should be able to start up your application and you will be required
- to log in to proceed. Try it out, or try experimenting with the <span class="quote">“<span class="quote">tutorial</span>”</span>
- sample application that comes with the project. The above configuration actually adds quite
- a few services to the application because we have used the <code class="literal">auto-config</code>
- attribute. For example, form-based login processing is automatically enabled. </p><div class="section" title="What does auto-config Include?"><div class="titlepage"><div><div><h4 class="title"><a name="ns-auto-config"></a>What does <code class="literal">auto-config</code> Include?</h4></div></div></div><p> The <code class="literal">auto-config</code> attribute, as we have used it above, is just a
- shorthand syntax for: </p><pre class="programlisting">
+ </pre><div class="sidebar"><p class="title"><b></b></p><p>If you are familiar with pre-namespace versions of the framework, you can
+ probably already guess roughly what's going on here. The
+ <code class="literal"><http></code> element is responsible for creating a
+ <code class="classname">FilterChainProxy</code> and the filter beans which it uses.
+ Common problems like incorrect filter ordering are no longer an issue as the
+ filter positions are predefined.</p><p>The <code class="literal"><authentication-provider></code> element creates a
+ <code class="classname">DaoAuthenticationProvider</code> bean and the
+ <code class="literal"><user-service></code> element creates an
+ <code class="classname">InMemoryDaoImpl</code>. All
+ <code class="literal">authentication-provider</code> elements must be children of the
+ <code class="literal"><authentication-manager></code> element, which creates a
+ <code class="classname">ProviderManager</code> and registers the authentication
+ providers with it. You can find more detailed information on the beans that are
+ created in the <a class="link" href="appendix-namespace.html" title="Appendix B. The Security Namespace">namespace appendix</a>.
+ It's worth cross-checking this if you want to start understanding what the
+ important classes in the framework are and how they are used, particularly if
+ you want to customise things later.</p></div><p> The configuration above defines two users, their passwords and their roles within
+ the application (which will be used for access control). It is also possible to load
+ user information from a standard properties file using the
+ <code class="literal">properties</code> attribute on <code class="literal">user-service</code>. See the
+ section on <a class="link" href="core-services.html#core-services-in-memory-service" title="7.2.1 In-Memory Authentication">in-memory
+ authentication</a> for more details on the file format. Using the
+ <code class="literal"><authentication-provider></code> element means that the user
+ information will be used by the authentication manager to process authentication
+ requests. You can have multiple <code class="literal"><authentication-provider></code>
+ elements to define different authentication sources and each will be consulted in
+ turn.</p><p> At this point you should be able to start up your application and you will be
+ required to log in to proceed. Try it out, or try experimenting with the
+ <span class="quote">“<span class="quote">tutorial</span>”</span> sample application that comes with the project. The above
+ configuration actually adds quite a few services to the application because we have
+ used the <code class="literal">auto-config</code> attribute. For example, form-based login
+ processing is automatically enabled. </p><div class="section" title="What does auto-config Include?"><div class="titlepage"><div><div><h4 class="title"><a name="ns-auto-config"></a>What does <code class="literal">auto-config</code> Include?</h4></div></div></div><p> The <code class="literal">auto-config</code> attribute, as we have used it above, is
+ just a shorthand syntax for: </p><pre class="programlisting">
<span class="hl-tag"><http></span>
<span class="hl-tag"><form-login /></span>
<span class="hl-tag"><http-basic /></span>
<span class="hl-tag"><logout /></span>
<span class="hl-tag"></http></span>
</pre><p> These other elements are responsible for setting up form-login, basic
- authentication and logout handling services respectively <sup>[<a name="d0e602" href="#ftn.d0e602" class="footnote">4</a>]</sup> . They each have attributes which can be used to alter
- their behaviour. </p></div><div class="section" title="Form and Basic Login Options"><div class="titlepage"><div><div><h4 class="title"><a name="ns-form-and-basic"></a>Form and Basic Login Options</h4></div></div></div><p> You might be wondering where the login form came from when you were prompted to log
- in, since we made no mention of any HTML files or JSPs. In fact, since we didn't
- explicitly set a URL for the login page, Spring Security generates one automatically,
- based on the features that are enabled and using standard values for the URL which
- processes the submitted login, the default target URL the user will be sent to after
- loggin in and so on. However, the namespace offers plenty of support to allow you to
- customize these options. For example, if you want to supply your own login page, you could
- use: </p><pre class="programlisting">
+ authentication and logout handling services respectively <sup>[<a name="d0e765" href="#ftn.d0e765" class="footnote">4</a>]</sup>. They each have attributes which can be used to alter their
+ behaviour. In anything other than very basic scenarios, it is probably better to
+ omit the <code class="literal">auto-config</code> attribute and configure what you require
+ explicitly in the interest of clarity.</p></div></div><div class="section" title="3.2.3 Form and Basic Login Options"><div class="titlepage"><div><div><h3 class="title"><a name="ns-form-and-basic"></a>3.2.3 Form and Basic Login Options</h3></div></div></div><p> You might be wondering where the login form came from when you were prompted to
+ log in, since we made no mention of any HTML files or JSPs. In fact, since we didn't
+ explicitly set a URL for the login page, Spring Security generates one
+ automatically, based on the features that are enabled and using standard values for
+ the URL which processes the submitted login, the default target URL the user will be
+ sent to after loggin in and so on. However, the namespace offers plenty of support
+ to allow you to customize these options. For example, if you want to supply your own
+ login page, you could use: </p><pre class="programlisting">
<span class="hl-tag"><http</span> <span class="hl-attribute">auto-config</span>=<span class="hl-value">'true'</span><span class="hl-tag">></span>
<span class="hl-tag"><intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/login.jsp*"</span> <span class="hl-attribute">access</span>=<span class="hl-value">"IS_AUTHENTICATED_ANONYMOUSLY"</span><span class="hl-tag">/></span>
<span class="hl-tag"><intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/**"</span> <span class="hl-attribute">access</span>=<span class="hl-value">"ROLE_USER"</span><span class="hl-tag"> /></span>
<span class="hl-tag"><form-login</span> <span class="hl-attribute">login-page</span>=<span class="hl-value">'/login.jsp'</span><span class="hl-tag">/></span>
<span class="hl-tag"></http></span>
- </pre><p> Note that you can still use <code class="literal">auto-config</code>. The
- <code class="literal">form-login</code> element just overrides the default settings. Also note
- that we've added an extra <code class="literal">intercept-url</code> element to say that any
- requests for the login page should be available to anonymous users <sup>[<a name="d0e635" href="#ftn.d0e635" class="footnote">5</a>]</sup>. Otherwise the request would be matched by the pattern
- <code class="literal">/**</code> and it wouldn't be possible to access the login page itself! This
- is a common configuration error and will result in an infinite loop in the application.
- Spring Security will emit a warning in the log if your login page appears to be secured.
- It is also possible to have all requests matching a particular pattern bypass the security
- filter chain completely: </p><pre class="programlisting">
+ </pre><p> Note that you can still use <code class="literal">auto-config</code>. The
+ <code class="literal">form-login</code> element just overrides the default settings. Also note
+ that we've added an extra <code class="literal">intercept-url</code> element to say that any
+ requests for the login page should be available to anonymous users <sup>[<a name="d0e801" href="#ftn.d0e801" class="footnote">5</a>]</sup>. Otherwise the request would be matched by the pattern
+ <code class="literal">/**</code> and it wouldn't be possible to access the login page itself!
+ This is a common configuration error and will result in an infinite loop in the
+ application. Spring Security will emit a warning in the log if your login page
+ appears to be secured. It is also possible to have all requests matching a
+ particular pattern bypass the security filter chain completely, by defining a
+ separate <code class="literal">http</code> element for the pattern like this: </p><pre class="programlisting">
+ <span class="hl-tag"><http</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/css/**"</span> <span class="hl-attribute">security</span>=<span class="hl-value">"none"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><http</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/login.jsp*"</span> <span class="hl-attribute">security</span>=<span class="hl-value">"none"</span><span class="hl-tag">/></span>
+
<span class="hl-tag"><http</span> <span class="hl-attribute">auto-config</span>=<span class="hl-value">'true'</span><span class="hl-tag">></span>
- <span class="hl-tag"><intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/css/**"</span> <span class="hl-attribute">filters</span>=<span class="hl-value">"none"</span><span class="hl-tag">/></span>
- <span class="hl-tag"><intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/login.jsp*"</span> <span class="hl-attribute">filters</span>=<span class="hl-value">"none"</span><span class="hl-tag">/></span>
<span class="hl-tag"><intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/**"</span> <span class="hl-attribute">access</span>=<span class="hl-value">"ROLE_USER"</span><span class="hl-tag"> /></span>
<span class="hl-tag"><form-login</span> <span class="hl-attribute">login-page</span>=<span class="hl-value">'/login.jsp'</span><span class="hl-tag">/></span>
<span class="hl-tag"></http></span>
- </pre><p>It's important to realise that these requests will be completely
- oblivious to any further Spring Security web-related configuration or additional
- attributes such as <code class="literal">requires-channel</code>, so you will not be able to access
- information on the current user or call secured methods during the request. Use
- <code class="literal">access='IS_AUTHENTICATED_ANONYMOUSLY'</code> as an alternative if you still
- want the security filter chain to be applied.</p><p>If you want to use basic authentication instead of form login, then change the
- configuration to </p><pre class="programlisting">
+ </pre><p> From Spring Security 3.1 it is now possible to use multiple
+ <code class="literal">http</code> elements to define separate security filter chain
+ configurations for different request patterns. If the <code class="literal">pattern</code>
+ attribute is omitted from an <code class="literal">http</code> element, it matches all
+ requests. Creating an unsecured pattern is a simple example of this syntax, where
+ the pattern is mapped to an empty filter chain <sup>[<a name="d0e832" href="#ftn.d0e832" class="footnote">6</a>]</sup>. We'll look at this new syntax in more detail in the chapter on the
+ <a class="link" href="security-filter-chain.html#filter-chains-with-ns" title="8.6 Advanced Namespace Configuration">Security Filter Chain</a>. </p><p> It's important to realise that these unsecured requests will be completely
+ oblivious to any Spring Security web-related configuration or additional attributes
+ such as <code class="literal">requires-channel</code>, so you will not be able to access
+ information on the current user or call secured methods during the request. Use
+ <code class="literal">access='IS_AUTHENTICATED_ANONYMOUSLY'</code> as an alternative if you
+ still want the security filter chain to be applied.</p><p>If you want to use basic authentication instead of form login, then change the
+ configuration to </p><pre class="programlisting">
<span class="hl-tag"><http</span> <span class="hl-attribute">auto-config</span>=<span class="hl-value">'true'</span><span class="hl-tag">></span>
<span class="hl-tag"><intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/**"</span> <span class="hl-attribute">access</span>=<span class="hl-value">"ROLE_USER"</span><span class="hl-tag"> /></span>
<span class="hl-tag"><http-basic /></span>
<span class="hl-tag"></http></span>
- </pre><p> Basic authentication will then take precedence and will be used to
- prompt for a login when a user attempts to access a protected resource. Form login is
- still available in this configuration if you wish to use it, for example through a login
- form embedded in another web page. </p><div class="section" title="Setting a Default Post-Login Destination"><div class="titlepage"><div><div><h5 class="title"><a name="ns-form-target"></a>Setting a Default Post-Login Destination</h5></div></div></div><p> If a form login isn't prompted by an attempt to access a protected resource, the
- <code class="literal">default-target-url</code> option comes into play. This is the URL the user
- will be taken to after logging in, and defaults to "/". You can also configure things so
- that they user <span class="emphasis"><em>always</em></span> ends up at this page (regardless of whether
- the login was "on-demand" or they explicitly chose to log in) by setting the
- <code class="literal">always-use-default-target</code> attribute to "true". This is useful if
- your application always requires that the user starts at a "home" page, for example: </p><pre class="programlisting">
+ </pre><p> Basic authentication will then take precedence and will be used to
+ prompt for a login when a user attempts to access a protected resource. Form login
+ is still available in this configuration if you wish to use it, for example through
+ a login form embedded in another web page. </p><div class="section" title="Setting a Default Post-Login Destination"><div class="titlepage"><div><div><h4 class="title"><a name="ns-form-target"></a>Setting a Default Post-Login Destination</h4></div></div></div><p> If a form login isn't prompted by an attempt to access a protected resource,
+ the <code class="literal">default-target-url</code> option comes into play. This is the
+ URL the user will be taken to after successfully logging in, and defaults to
+ "/". You can also configure things so that the user <span class="emphasis"><em>always</em></span>
+ ends up at this page (regardless of whether the login was "on-demand" or they
+ explicitly chose to log in) by setting the
+ <code class="literal">always-use-default-target</code> attribute to "true". This is useful
+ if your application always requires that the user starts at a "home" page, for
+ example: </p><pre class="programlisting">
+ <span class="hl-tag"><http</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/login.htm*"</span> <span class="hl-attribute">security</span>=<span class="hl-value">"none"</span><span class="hl-tag">/></span>
<span class="hl-tag"><http></span>
- <span class="hl-tag"><intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">'/login.htm*'</span> <span class="hl-attribute">filters</span>=<span class="hl-value">'none'</span><span class="hl-tag">/></span>
<span class="hl-tag"><intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">'/**'</span> <span class="hl-attribute">access</span>=<span class="hl-value">'ROLE_USER'</span><span class="hl-tag"> /></span>
<span class="hl-tag"><form-login</span> <span class="hl-attribute">login-page</span>=<span class="hl-value">'/login.htm'</span> <span class="hl-attribute">default-target-url</span>=<span class="hl-value">'/home.htm'</span>
<span class="hl-attribute">always-use-default-target</span>=<span class="hl-value">'true'</span><span class="hl-tag"> /></span>
<span class="hl-tag"></http></span>
-
- </pre></div></div></div><div class="section" title="2.2.3 Using other Authentication Providers"><div class="titlepage"><div><div><h3 class="title"><a name="ns-auth-providers"></a>2.2.3 Using other Authentication Providers</h3></div></div></div><p> In practice you will need a more scalable source of user information than a few names
- added to the application context file. Most likely you will want to store your user
- information in something like a database or an LDAP server. LDAP namespace configuration is
- dealt with in the <a class="link" href="ldap.html" title="18. LDAP Authentication">LDAP chapter</a>, so we won't cover it here.
- If you have a custom implementation of Spring Security's
- <code class="classname">UserDetailsService</code>, called "myUserDetailsService" in your
- application context, then you can authenticate against this using </p><pre class="programlisting">
+ </pre><p>For even more control over the destination, you can use the
+ <code class="literal">authentication-success-handler-ref</code> attribute as an
+ alternative to <code class="literal">default-target-url</code>. The referenced bean should
+ be an instance of <code class="interfacename">AuthenticationSuccessHandler</code>.
+ You'll find more on this in the <a class="link" href="core-web-filters.html#form-login-flow-handling" title="9.4.1 Application Flow on Authentication Success and Failure">Core Filters</a> chapter and also in the namespace appendix, as well as
+ information on how to customize the flow when authentication fails. </p></div></div><div class="section" title="3.2.4 Logout Handling"><div class="titlepage"><div><div><h3 class="title"><a name="ns-logout"></a>3.2.4 Logout Handling</h3></div></div></div><p>The <code class="literal">logout</code> element adds support for logging out by navigating
+ to a particular URL. The default logout URL is <code class="literal">/j_spring_security_logout</code>,
+ but you can set it to something else using the <code class="literal">logout-url</code> attribute.
+ More information on other available attributes may be found in the namespace appendix.
+ </p></div><div class="section" title="3.2.5 Using other Authentication Providers"><div class="titlepage"><div><div><h3 class="title"><a name="ns-auth-providers"></a>3.2.5 Using other Authentication Providers</h3></div></div></div><p> In practice you will need a more scalable source of user information than a few
+ names added to the application context file. Most likely you will want to store your
+ user information in something like a database or an LDAP server. LDAP namespace
+ configuration is dealt with in the <a class="link" href="ldap.html" title="19. LDAP Authentication">LDAP chapter</a>, so
+ we won't cover it here. If you have a custom implementation of Spring Security's
+ <code class="classname">UserDetailsService</code>, called "myUserDetailsService" in your
+ application context, then you can authenticate against this using </p><pre class="programlisting">
<span class="hl-tag"><authentication-manager></span>
<span class="hl-tag"><authentication-provider</span> <span class="hl-attribute">user-service-ref</span>=<span class="hl-value">'myUserDetailsService'</span><span class="hl-tag">/></span>
<span class="hl-tag"></authentication-manager></span>
@@ -243,11 +265,10 @@
<span class="hl-tag"></authentication-manager></span>
</pre><p> Where <span class="quote">“<span class="quote">securityDataSource</span>”</span> is the name of a
- <code class="classname">DataSource</code> bean in the application context, pointing at a database
- containing the standard Spring Security <a class="link" href="appendix-schema.html#db_schema_users_authorities">user
- data tables</a>. Alternatively, you could configure a Spring Security
- <code class="classname">JdbcDaoImpl</code> bean and point at that using the
- <code class="literal">user-service-ref</code> attribute: </p><pre class="programlisting">
+ <code class="classname">DataSource</code> bean in the application context, pointing at a
+ database containing the standard Spring Security <a class="link" href="appendix-schema.html#db_schema_users_authorities">user data tables</a>. Alternatively,
+ you could configure a Spring Security <code class="classname">JdbcDaoImpl</code> bean and
+ point at that using the <code class="literal">user-service-ref</code> attribute: </p><pre class="programlisting">
<span class="hl-tag"><authentication-manager></span>
<span class="hl-tag"><authentication-provider</span> <span class="hl-attribute">user-service-ref</span>=<span class="hl-value">'myUserDetailsService'</span><span class="hl-tag">/></span>
<span class="hl-tag"></authentication-manager></span>
@@ -258,19 +279,21 @@
<span class="hl-tag"></beans:bean></span>
</pre><p> You can also use standard
- <code class="interfacename">AuthenticationProvider</code> beans as follows </p><pre class="programlisting">
+ <code class="interfacename">AuthenticationProvider</code> beans as follows </p><pre class="programlisting">
<span class="hl-tag"><authentication-manager></span>
<span class="hl-tag"><authentication-provider</span> <span class="hl-attribute">ref</span>=<span class="hl-value">'myAuthenticationProvider'</span><span class="hl-tag">/></span>
<span class="hl-tag"></authentication-manager></span>
</pre><p> where <code class="literal">myAuthenticationProvider</code> is the name of a
- bean in your application context which implements
- <code class="interfacename">AuthenticationProvider</code>. You can use multiple
- <code class="literal">authentication-provider</code> elements, in which case they will be checked
- in the order they are declared when attempting to authenticated a user. See <a class="xref" href="ns-config.html#ns-auth-manager" title="2.6 The Authentication Manager and the Namespace">Section 2.6, “The Authentication Manager and the Namespace”</a> for more on information on how the Spring Security
- <code class="interfacename">AuthenticationManager</code> is configured using the namespace. </p><div class="section" title="Adding a Password Encoder"><div class="titlepage"><div><div><h4 class="title"><a name="ns-password-encoder"></a>Adding a Password Encoder</h4></div></div></div><p> Often your password data will be encoded using a hashing algorithm. This is supported
- by the <code class="literal"><password-encoder></code> element. With SHA encoded passwords,
- the original authentication provider configuration would look like this: </p><pre class="programlisting">
+ bean in your application context which implements
+ <code class="interfacename">AuthenticationProvider</code>. You can use multiple
+ <code class="literal">authentication-provider</code> elements, in which case the providers
+ will be queried in the order they are declared. See <a class="xref" href="ns-config.html#ns-auth-manager" title="3.6 The Authentication Manager and the Namespace">Section 3.6, “The Authentication Manager and the Namespace”</a> for more on information on how the Spring Security
+ <code class="interfacename">AuthenticationManager</code> is configured using the
+ namespace. </p><div class="section" title="Adding a Password Encoder"><div class="titlepage"><div><div><h4 class="title"><a name="ns-password-encoder"></a>Adding a Password Encoder</h4></div></div></div><p> Often your password data will be encoded using a hashing algorithm. This is
+ supported by the <code class="literal"><password-encoder></code> element. With SHA
+ encoded passwords, the original authentication provider configuration would look
+ like this: </p><pre class="programlisting">
<span class="hl-tag"><authentication-manager></span>
<span class="hl-tag"><authentication-provider></span>
<span class="hl-tag"><password-encoder</span> <span class="hl-attribute">hash</span>=<span class="hl-value">"sha"</span><span class="hl-tag">/></span>
@@ -283,49 +306,67 @@
<span class="hl-tag"></authentication-provider></span>
<span class="hl-tag"></authentication-manager></span>
- </pre><p> When using hashed passwords, it's also a good idea to use a salt value to protect
- against dictionary attacks and Spring Security supports this too. Ideally you would want
- to use a randomly generated salt value for each user, but you can use any property of the
- <code class="classname">UserDetails</code> object which is loaded by your
- <code class="classname">UserDetailsService</code>. For example, to use the
- <code class="literal">username</code> property, you would use </p><pre class="programlisting">
- <password-encoder hash="sha">
- <salt-source user-property="username"/>
- </password-encoder>
+ </pre><p> When using hashed passwords, it's also a good idea to use a salt value to
+ protect against dictionary attacks and Spring Security supports this too.
+ Ideally you would want to use a randomly generated salt value for each user, but
+ you can use any property of the <code class="classname">UserDetails</code> object which
+ is loaded by your <code class="classname">UserDetailsService</code>. For example, to use
+ the <code class="literal">username</code> property, you would use </p><pre class="programlisting">
+ <span class="hl-tag"><password-encoder</span> <span class="hl-attribute">hash</span>=<span class="hl-value">"sha"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><salt-source</span> <span class="hl-attribute">user-property</span>=<span class="hl-value">"username"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></password-encoder></span>
</pre><p> You can use a custom password encoder bean by using the
- <code class="literal">ref</code> attribute of <code class="literal">password-encoder</code>. This should
- contain the name of a bean in the application context which is an instance of Spring
- Security's <code class="interfacename">PasswordEncoder</code> interface. </p></div></div></div><div class="section" title="2.3 Advanced Web Features"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ns-web-advanced"></a>2.3 Advanced Web Features</h2></div></div></div><div class="section" title="2.3.1 Remember-Me Authentication"><div class="titlepage"><div><div><h3 class="title"><a name="ns-remember-me"></a>2.3.1 Remember-Me Authentication</h3></div></div></div><p>See the separate <a class="link" href="remember-me.html" title="10. Remember-Me Authentication">Remember-Me chapter</a> for
- information on remember-me namespace configuration.</p></div><div class="section" title="2.3.2 Adding HTTP/HTTPS Channel Security"><div class="titlepage"><div><div><h3 class="title"><a name="ns-requires-channel"></a>2.3.2 Adding HTTP/HTTPS Channel Security</h3></div></div></div><p>If your application supports both HTTP and HTTPS, and you require that particular URLs
- can only be accessed over HTTPS, then this is directly supported using the
- <code class="literal">requires-channel</code> attribute on <code class="literal"><intercept-url></code>: </p><pre class="programlisting">
+ <code class="literal">ref</code> attribute of <code class="literal">password-encoder</code>. This
+ should contain the name of a bean in the application context which is an
+ instance of Spring Security's <code class="interfacename">PasswordEncoder</code>
+ interface. </p></div></div></div><div class="section" title="3.3 Advanced Web Features"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ns-web-advanced"></a>3.3 Advanced Web Features</h2></div></div></div><div class="section" title="3.3.1 Remember-Me Authentication"><div class="titlepage"><div><div><h3 class="title"><a name="ns-remember-me"></a>3.3.1 Remember-Me Authentication</h3></div></div></div><p>See the separate <a class="link" href="remember-me.html" title="11. Remember-Me Authentication">Remember-Me chapter</a> for
+ information on remember-me namespace configuration.</p></div><div class="section" title="3.3.2 Adding HTTP/HTTPS Channel Security"><div class="titlepage"><div><div><h3 class="title"><a name="ns-requires-channel"></a>3.3.2 Adding HTTP/HTTPS Channel Security</h3></div></div></div><p>If your application supports both HTTP and HTTPS, and you require that particular
+ URLs can only be accessed over HTTPS, then this is directly supported using the
+ <code class="literal">requires-channel</code> attribute on
+ <code class="literal"><intercept-url></code>: </p><pre class="programlisting">
<span class="hl-tag"><http></span>
<span class="hl-tag"><intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/secure/**"</span> <span class="hl-attribute">access</span>=<span class="hl-value">"ROLE_USER"</span> <span class="hl-attribute">requires-channel</span>=<span class="hl-value">"https"</span><span class="hl-tag">/></span>
<span class="hl-tag"><intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/**"</span> <span class="hl-attribute">access</span>=<span class="hl-value">"ROLE_USER"</span> <span class="hl-attribute">requires-channel</span>=<span class="hl-value">"any"</span><span class="hl-tag">/></span>
...
<span class="hl-tag"></http></span>
</pre><p>With this configuration in place, if a user attempts to access
- anything matching the "/secure/**" pattern using HTTP, they will first be redirected to an
- HTTPS URL. The available options are "http", "https" or "any". Using the value "any" means
- that either HTTP or HTTPS can be used. </p><p>If your application uses non-standard ports for HTTP and/or HTTPS, you can specify a
- list of port mappings as follows: </p><pre class="programlisting">
- <http>
+ anything matching the "/secure/**" pattern using HTTP, they will first be redirected
+ to an HTTPS URL
+ <sup>[<a name="d0e1018" href="#ftn.d0e1018" class="footnote">7</a>]</sup>.
+ The available options are "http", "https" or "any". Using the value
+ "any" means that either HTTP or HTTPS can be used. </p><p>If your application uses non-standard ports for HTTP and/or HTTPS, you can specify
+ a list of port mappings as follows: </p><pre class="programlisting">
+ <span class="hl-tag"><http></span>
...
- <port-mappings>
- <port-mapping http="9080" https="9443"/>
- </port-mappings>
- </http>
- </pre></div><div class="section" title="2.3.3 Session Management"><div class="titlepage"><div><div><h3 class="title"><a name="ns-session-mgmt"></a>2.3.3 Session Management</h3></div></div></div><div class="section" title="Detecting Timeouts"><div class="titlepage"><div><div><h4 class="title"><a name="d0e802"></a>Detecting Timeouts</h4></div></div></div><p> You can configure Spring Security to detect the submission of an invalid session ID
- and redirect the user to an appropriate URL. This is achieved through the
- <code class="literal">session-management</code> element: </p><pre class="programlisting">
+ <span class="hl-tag"><port-mappings></span>
+ <span class="hl-tag"><port-mapping</span> <span class="hl-attribute">http</span>=<span class="hl-value">"9080"</span> <span class="hl-attribute">https</span>=<span class="hl-value">"9443"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></port-mappings></span>
+ <span class="hl-tag"></http></span>
+ </pre><p>
+ Note that in order to be truly secure, an application should not use HTTP at all or switch
+ between HTTP and HTTPS. It should start in HTTPS (with the user entering an HTTPS URL) and
+ use a secure connection throughout to avoid any possibility of man-in-the-middle attacks.
+ </p></div><div class="section" title="3.3.3 Session Management"><div class="titlepage"><div><div><h3 class="title"><a name="ns-session-mgmt"></a>3.3.3 Session Management</h3></div></div></div><div class="section" title="Detecting Timeouts"><div class="titlepage"><div><div><h4 class="title"><a name="d0e1033"></a>Detecting Timeouts</h4></div></div></div><p> You can configure Spring Security to detect the submission of an invalid
+ session ID and redirect the user to an appropriate URL. This is achieved through
+ the <code class="literal">session-management</code> element: </p><pre class="programlisting">
<span class="hl-tag"><http></span>
...
- <span class="hl-tag"><session-management</span> <span class="hl-attribute">invalid-session-url</span>=<span class="hl-value">"/sessionTimeout.htm"</span><span class="hl-tag"> /></span>
- <span class="hl-tag"></http></span></pre></div><div class="section" title="Concurrent Session Control"><div class="titlepage"><div><div><h4 class="title"><a name="ns-concurrent-sessions"></a>Concurrent Session Control</h4></div></div></div><p>If you wish to place constraints on a single user's ability to log in to your
- application, Spring Security supports this out of the box with the following simple
- additions. First you need to add the following listener to your
- <code class="filename">web.xml</code> file to keep Spring Security updated about session
- lifecycle events: </p><pre class="programlisting">
+ <span class="hl-tag"><session-management</span> <span class="hl-attribute">invalid-session-url</span>=<span class="hl-value">"/invalidSession.htm"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"></http></span></pre><p>Note that if you use this mechanism to detect session timeouts, it
+ may falsely report an error if the user logs out and then logs back in without
+ closing the browser. This is because the session cookie is not cleared when you
+ invalidate the session and will be resubmitted even if the user has logged out.
+ You may be able to explicitly delete the JSESSIONID cookie on logging out, for
+ example by using the following syntax in the logout handler: </p><pre class="programlisting">
+ <span class="hl-tag"><http></span>
+ <span class="hl-tag"><logout</span> <span class="hl-attribute">delete-cookies</span>=<span class="hl-value">"JSESSIONID"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"></http></span>
+ </pre><p> Unfortunately this can't be guaranteed to work with every servlet container,
+ so you will need to test it in your environment<sup>[<a name="d0e1047" href="#ftn.d0e1047" class="footnote">8</a>]</sup>. </p></div><div class="section" title="Concurrent Session Control"><div class="titlepage"><div><div><h4 class="title"><a name="ns-concurrent-sessions"></a>Concurrent Session Control</h4></div></div></div><p>If you wish to place constraints on a single user's ability to log in to your
+ application, Spring Security supports this out of the box with the following
+ simple additions. First you need to add the following listener to your
+ <code class="filename">web.xml</code> file to keep Spring Security updated about session
+ lifecycle events: </p><pre class="programlisting">
<span class="hl-tag"><listener></span>
<span class="hl-tag"><listener-class></span>
org.springframework.security.web.session.HttpSessionEventPublisher
@@ -339,8 +380,8 @@
<span class="hl-tag"></session-management></span>
<span class="hl-tag"></http></span>
</pre><p> This will prevent a user from logging in multiple times - a
- second login will cause the first to be invalidated. Often you would prefer to prevent a
- second login, in which case you can use </p><pre class="programlisting">
+ second login will cause the first to be invalidated. Often you would prefer to
+ prevent a second login, in which case you can use </p><pre class="programlisting">
<span class="hl-tag"><http></span>
...
<span class="hl-tag"><session-management></span>
@@ -348,121 +389,103 @@
<span class="hl-tag"></session-management></span>
<span class="hl-tag"></http></span>
</pre><p>The second login will then be rejected. By
- <span class="quote">“<span class="quote">rejected</span>”</span>, we mean that the user will be sent to the
- <code class="literal">authentication-failure-url</code> if form-based login is being used. If the
- second authentication takes place through another non-interactive mechanism, such as
- <span class="quote">“<span class="quote">remember-me</span>”</span>, an <span class="quote">“<span class="quote">unauthorized</span>”</span> (402) error will be sent to
- the client. If instead you want to use an error page, you can add the attribute
- <code class="literal">session-authentication-error-url</code> to the
- <code class="literal">session-management</code> element. </p><p>If you are using a customized authentication filter for form-based login, then you
- have to configure concurrent session control support explicitly. More details can be found
- in the <a class="link" href="session-mgmt.html" title="11. Session Management">Session Management chapter</a>. </p></div><div class="section" title="Session Fixation Attack Protection"><div class="titlepage"><div><div><h4 class="title"><a name="ns-session-fixation"></a>Session Fixation Attack Protection</h4></div></div></div><p>
- <a class="link" href="http://en.wikipedia.org/wiki/Session_fixation" target="_top">Session fixation</a>
- attacks are a potential risk where it is possible for a malicious attacker to create a
- session by accessing a site, then persuade another user to log in with the same session
- (by sending them a link containing the session identifier as a parameter, for example).
- Spring Security protects against this automatically by creating a new session when a user
- logs in. If you don't require this protection, or it conflicts with some other
- requirement, you can control the behaviour using the
- <code class="literal">session-fixation-protection</code> attribute on
- <code class="literal"><session-management></code>, which has three options
- </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p><code class="literal">migrateSession</code> - creates a new
- session and copies the existing session attributes to the new session. This is the
- default.</p></li><li class="listitem"><p><code class="literal">none</code> - Don't do
- anything. The original session will be
- retained.</p></li><li class="listitem"><p><code class="literal">newSession</code> - Create
- a new "clean" session, without copying the existing session
- data.</p></li></ul></div></div></div><div class="section" title="2.3.4 OpenID Support"><div class="titlepage"><div><div><h3 class="title"><a name="ns-openid"></a>2.3.4 OpenID Support</h3></div></div></div><p>The namespace supports <a class="link" href="http://openid.net/" target="_top">OpenID</a> login either
- instead of, or in addition to normal form-based login, with a simple change: </p><pre class="programlisting">
+ <span class="quote">“<span class="quote">rejected</span>”</span>, we mean that the user will be sent to the
+ <code class="literal">authentication-failure-url</code> if form-based login is being used.
+ If the second authentication takes place through another non-interactive
+ mechanism, such as <span class="quote">“<span class="quote">remember-me</span>”</span>, an <span class="quote">“<span class="quote">unauthorized</span>”</span>
+ (402) error will be sent to the client. If instead you want to use an error
+ page, you can add the attribute
+ <code class="literal">session-authentication-error-url</code> to the
+ <code class="literal">session-management</code> element. </p><p>If you are using a customized authentication filter for form-based login, then
+ you have to configure concurrent session control support explicitly. More
+ details can be found in the <a class="link" href="session-mgmt.html" title="12. Session Management">Session Management
+ chapter</a>. </p></div><div class="section" title="Session Fixation Attack Protection"><div class="titlepage"><div><div><h4 class="title"><a name="ns-session-fixation"></a>Session Fixation Attack Protection</h4></div></div></div><p> <a class="link" href="http://en.wikipedia.org/wiki/Session_fixation" target="_top">Session
+ fixation</a> attacks are a potential risk where it is possible for a
+ malicious attacker to create a session by accessing a site, then persuade
+ another user to log in with the same session (by sending them a link containing
+ the session identifier as a parameter, for example). Spring Security protects
+ against this automatically by creating a new session when a user logs in. If you
+ don't require this protection, or it conflicts with some other requirement, you
+ can control the behaviour using the
+ <code class="literal">session-fixation-protection</code> attribute on
+ <code class="literal"><session-management></code>, which has three options </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p><code class="literal">migrateSession</code> - creates a new session and copies
+ the existing session attributes to the new session. This is the
+ default.</p></li><li class="listitem"><p><code class="literal">none</code> - Don't do anything. The original session will
+ be retained.</p></li><li class="listitem"><p><code class="literal">newSession</code> - Create a new "clean" session, without
+ copying the existing session data.</p></li></ul></div><p>
+ See the <a class="link" href="session-mgmt.html" title="12. Session Management">Session Management</a> chapter for
+ additional information.
+ </p></div></div><div class="section" title="3.3.4 OpenID Support"><div class="titlepage"><div><div><h3 class="title"><a name="ns-openid"></a>3.3.4 OpenID Support</h3></div></div></div><p>The namespace supports <a class="link" href="http://openid.net/" target="_top">OpenID</a> login
+ either instead of, or in addition to normal form-based login, with a simple change: </p><pre class="programlisting">
<span class="hl-tag"><http></span>
<span class="hl-tag"><intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/**"</span> <span class="hl-attribute">access</span>=<span class="hl-value">"ROLE_USER"</span><span class="hl-tag"> /></span>
<span class="hl-tag"><openid-login /></span>
<span class="hl-tag"></http></span>
</pre><p>You should then register yourself with an OpenID provider (such as
- myopenid.com), and add the user information to your in-memory
- <code class="literal"><user-service></code> : </p><pre class="programlisting">
+ myopenid.com), and add the user information to your in-memory
+ <code class="literal"><user-service></code> : </p><pre class="programlisting">
<span class="hl-tag"><user</span> <span class="hl-attribute">name</span>=<span class="hl-value">"http://jimi.hendrix.myopenid.com/"</span> <span class="hl-attribute">authorities</span>=<span class="hl-value">"ROLE_USER"</span><span class="hl-tag"> /></span>
</pre><p> You should be able to login using the <code class="literal">myopenid.com</code> site to
- authenticate. It is also possible to select a specific
- <code class="interfacename">UserDetailsService</code> bean for use OpenID by setting the
- <code class="literal">user-service-ref</code> attribute on the <code class="literal">openid-login</code>
- element. See the previous section on <a class="link" href="ns-config.html#ns-auth-providers" title="2.2.3 Using other Authentication Providers">authentication
- providers</a> for more information. Note that we have omitted the password attribute
- from the above user configuration, since this set of user data is only being used to load
- the authorities for the user. A random password will be generate internally, preventing you
- from accidentally using this user data as an authentication source elsewhere in your
- configuration.</p><div class="section" title="Attribute Exchange"><div class="titlepage"><div><div><h4 class="title"><a name="d0e914"></a>Attribute Exchange</h4></div></div></div><p>Support for OpenID <a class="link" href="http://openid.net/specs/openid-attribute-exchange-1_0.html" target="_top">attribute
- exchange</a>. As an example, the following configuration would attempt to retrieve
- the email and full name from the OpenID provider, for use by the application:</p><pre class="programlisting">
- <span class="hl-tag"><openid-login></span>
- <span class="hl-tag"><attribute-exchange></span>
- <span class="hl-tag"><openid-attribute</span> <span class="hl-attribute">name</span>=<span class="hl-value">"email"</span> <span class="hl-attribute">type</span>=<span class="hl-value">"http://axschema.org/contact/email"</span> <span class="hl-attribute">required</span>=<span class="hl-value">"true"</span><span class="hl-tag"> /></span>
- <span class="hl-tag"><openid-attribute</span> <span class="hl-attribute">name</span>=<span class="hl-value">"name"</span> <span class="hl-attribute">type</span>=<span class="hl-value">"http://axschema.org/namePerson"</span><span class="hl-tag"> /></span>
- <span class="hl-tag"></attribute-exchange></span>
- <span class="hl-tag"></openid-login></span></pre><p>The <span class="quote">“<span class="quote">type</span>”</span> of each OpenID attribute is a URI,
- determined by a particular schema, in this case <a class="link" href="http://axschema.org/" target="_top">http://axschema.org/</a>. If an attribute must be retrieved for successful
- authentication, the <code class="literal">required</code> attribute can be set. The exact schema and
- attributes supported will depend on your OpenID provider. The attribute values are
- returned as part of the authentication process and can be accessed afterwards using the
- following
- code:</p><pre class="programlisting">OpenIDAuthenticationToken token = (OpenIDAuthenticationToken)SecurityContextHolder.getContext().getAuthentication();
+ authenticate. It is also possible to select a specific
+ <code class="interfacename">UserDetailsService</code> bean for use OpenID by setting the
+ <code class="literal">user-service-ref</code> attribute on the <code class="literal">openid-login</code>
+ element. See the previous section on <a class="link" href="ns-config.html#ns-auth-providers" title="3.2.5 Using other Authentication Providers">authentication providers</a> for more information. Note that we have omitted the
+ password attribute from the above user configuration, since this set of user data is
+ only being used to load the authorities for the user. A random password will be
+ generate internally, preventing you from accidentally using this user data as an
+ authentication source elsewhere in your configuration.</p><div class="section" title="Attribute Exchange"><div class="titlepage"><div><div><h4 class="title"><a name="d0e1165"></a>Attribute Exchange</h4></div></div></div><p>Support for OpenID <a class="link" href="http://openid.net/specs/openid-attribute-exchange-1_0.html" target="_top">attribute exchange</a>. As an example, the following configuration would
+ attempt to retrieve the email and full name from the OpenID provider, for use by
+ the application:</p><pre class="programlisting">
+ <span class="hl-tag"><openid-login></span>
+ <span class="hl-tag"><attribute-exchange></span>
+ <span class="hl-tag"><openid-attribute</span> <span class="hl-attribute">name</span>=<span class="hl-value">"email"</span> <span class="hl-attribute">type</span>=<span class="hl-value">"http://axschema.org/contact/email"</span> <span class="hl-attribute">required</span>=<span class="hl-value">"true"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><openid-attribute</span> <span class="hl-attribute">name</span>=<span class="hl-value">"name"</span> <span class="hl-attribute">type</span>=<span class="hl-value">"http://axschema.org/namePerson"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></attribute-exchange></span>
+ <span class="hl-tag"></openid-login></span></pre><p>The <span class="quote">“<span class="quote">type</span>”</span> of each OpenID attribute is a URI,
+ determined by a particular schema, in this case <a class="link" href="http://axschema.org/" target="_top">http://axschema.org/</a>. If an attribute
+ must be retrieved for successful authentication, the <code class="literal">required</code>
+ attribute can be set. The exact schema and attributes supported will depend on
+ your OpenID provider. The attribute values are returned as part of the
+ authentication process and can be accessed afterwards using the following code:
+ </p><pre class="programlisting">
+OpenIDAuthenticationToken token =
+ (OpenIDAuthenticationToken)SecurityContextHolder.getContext().getAuthentication();
List<OpenIDAttribute> attributes = token.getAttributes();</pre><p>The
- <code class="classname">OpenIDAttribute</code> contains the attribute type and the retrieved
- value (or values in the case of multi-valued attributes). We'll see more about how the
- <code class="classname">SecurityContextHolder</code> class is used when we look at core Spring
- Security components in the <a class="link" href="technical-overview.html#core-components" title="5.2 Core Components">technical overview</a>
- chapter.</p></div></div><div class="section" title="2.3.5 Adding in Your Own Filters"><div class="titlepage"><div><div><h3 class="title"><a name="ns-custom-filters"></a>2.3.5 Adding in Your Own Filters</h3></div></div></div><p>If you've used Spring Security before, you'll know that the framework maintains a chain
- of filters in order to apply its services. You may want to add your own filters to the stack
- at particular locations or use a Spring Security filter for which there isn't currently a
- namespace configuration option (CAS, for example). Or you might want to use a customized
- version of a standard namespace filter, such as the
- <code class="literal">UsernamePasswordAuthenticationFilter</code> which is created by the
- <code class="literal"><form-login></code> element, taking advantage of some of the extra
- configuration options which are available by using the bean explicitly. How can you do this
- with namespace configuration, since the filter chain is not directly exposed? </p><p>The order of the filters is always strictly enforced when using the namespace. When the
- application context is being created, the filter beans are sorted by the namespace handling
- code and the standard Spring Security filters each have an alias in the namespace and a
- well-known position.</p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>In previous versions, the sorting took place after the
- filter instances had been created, during post-processing of the application context. In
- version 3.0+ the sorting is now done at the bean metadata level, before the classes have
- been instantiated. This has implications for how you add your own filters to the stack
- as the entire filter list must be known during the parsing of the
- <code class="literal"><http></code> element, so the syntax has changed slightly in
- 3.0.</p></td></tr></table></div><p>The filters, aliases and namespace elements/attributes which create
- the filters are shown in <a class="xref" href="ns-config.html#filter-stack" title="Table 2.1. Standard Filter Aliases and Ordering">Table 2.1, “Standard Filter
- Aliases and Ordering”</a>. The filters are listed in the order
- in which they occur in the filter chain. </p><div class="table"><a name="filter-stack"></a><p class="title"><b>Table 2.1. Standard Filter
- Aliases and Ordering</b></p><div class="table-contents"><table summary="Standard Filter
 Aliases and Ordering" style="border-collapse: collapse;border-top: 0.5pt solid ; border-bottom: 0.5pt solid ; border-left: 0.5pt solid ; border-right: 0.5pt solid ; "><colgroup><col><col><col></colgroup><thead><tr><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="center">Alias</th><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="center">Filter Class</th><th style="border-bottom: 0.5pt solid ; " align="center">Namespace Element or
- Attribute</th></tr></thead><tbody><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">
- CHANNEL_FILTER</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">ChannelProcessingFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/intercept-url at requires-channel</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">
- CONCURRENT_SESSION_FILTER</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">ConcurrentSessionFilter</code>
- </td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">session-management/concurrency-control</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">
- SECURITY_CONTEXT_FILTER</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="classname">SecurityContextPersistenceFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">
- LOGOUT_FILTER
- </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">LogoutFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/logout</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">
- X509_FILTER
- </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">X509AuthenticationFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/x509</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">
- PRE_AUTH_FILTER
- </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">AstractPreAuthenticatedProcessingFilter</code>
- Subclasses</td><td style="border-bottom: 0.5pt solid ; " align="left">N/A</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> CAS_FILTER
- </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">CasAuthenticationFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left">N/A</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">
- FORM_LOGIN_FILTER
- </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">UsernamePasswordAuthenticationFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/form-login</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">
- BASIC_AUTH_FILTER
- </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">BasicAuthenticationFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/http-basic</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">
- SERVLET_API_SUPPORT_FILTER</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">SecurityContextHolderAwareFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/@servlet-api-provision</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">
- REMEMBER_ME_FILTER
- </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="classname">RememberMeAuthenticationFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/remember-me</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">
- ANONYMOUS_FILTER
- </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">AnonymousAuthenticationFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/anonymous</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">
- SESSION_MANAGEMENT_FILTER</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">SessionManagementFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">session-management</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">EXCEPTION_TRANSLATION_FILTER
- </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="classname">ExceptionTranslationFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">
- FILTER_SECURITY_INTERCEPTOR
- </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="classname">FilterSecurityInterceptor</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http</code></td></tr><tr><td style="border-right: 0.5pt solid ; " align="left">
- SWITCH_USER_FILTER
- </td><td style="border-right: 0.5pt solid ; " align="left"><code class="literal">SwitchUserFilter</code></td><td style="" align="left">N/A</td></tr></tbody></table></div></div><p><br class="table-break">
- You can add your own filter to the stack, using the <code class="literal">custom-filter</code> element
- and one of these names to specify the position your filter should appear at: </p><pre class="programlisting">
+ <code class="classname">OpenIDAttribute</code> contains the attribute type and the
+ retrieved value (or values in the case of multi-valued attributes). We'll see
+ more about how the <code class="classname">SecurityContextHolder</code> class is used
+ when we look at core Spring Security components in the <a class="link" href="technical-overview.html#core-components" title="6.2 Core Components">technical overview</a> chapter. Multiple
+ attribute exchange configurations are also be supported, if you wish to use
+ multiple identity providers. You can supply multiple
+ <code class="literal">attribute-exchange</code> elements, using an
+ <code class="literal">identifier-matcher</code> attribute on each. This contains a regular
+ expression which will be matched against the OpenID identifier supplied by the
+ user. See the OpenID sample application in the codebase for an example
+ configuration, providing different attribute lists for the Google, Yahoo and
+ MyOpenID providers.</p></div></div><div class="section" title="3.3.5 Adding in Your Own Filters"><div class="titlepage"><div><div><h3 class="title"><a name="ns-custom-filters"></a>3.3.5 Adding in Your Own Filters</h3></div></div></div><p>If you've used Spring Security before, you'll know that the framework maintains a
+ chain of filters in order to apply its services. You may want to add your own
+ filters to the stack at particular locations or use a Spring Security filter for
+ which there isn't currently a namespace configuration option (CAS, for example). Or
+ you might want to use a customized version of a standard namespace filter, such as
+ the <code class="classname">UsernamePasswordAuthenticationFilter</code> which is created by the
+ <code class="literal"><form-login></code> element, taking advantage of some of the extra
+ configuration options which are available by using the bean explicitly. How can you
+ do this with namespace configuration, since the filter chain is not directly
+ exposed? </p><p>The order of the filters is always strictly enforced when using the namespace.
+ When the application context is being created, the filter beans are sorted by the
+ namespace handling code and the standard Spring Security filters each have an alias
+ in the namespace and a well-known position.</p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>In previous versions, the sorting took place after the filter instances had
+ been created, during post-processing of the application context. In version 3.0+
+ the sorting is now done at the bean metadata level, before the classes have been
+ instantiated. This has implications for how you add your own filters to the
+ stack as the entire filter list must be known during the parsing of the
+ <code class="literal"><http></code> element, so the syntax has changed slightly in
+ 3.0.</p></td></tr></table></div><p>The filters, aliases and namespace elements/attributes which create the
+ filters are shown in <a class="xref" href="ns-config.html#filter-stack" title="Table 3.1. Standard Filter Aliases and Ordering">Table 3.1, “Standard Filter Aliases and Ordering”</a>. The filters are listed in the
+ order in which they occur in the filter chain. </p><div class="table"><a name="filter-stack"></a><p class="title"><b>Table 3.1. Standard Filter Aliases and Ordering</b></p><div class="table-contents"><table summary="Standard Filter Aliases and Ordering" style="border-collapse: collapse;border-top: 0.5pt solid ; border-bottom: 0.5pt solid ; border-left: 0.5pt solid ; border-right: 0.5pt solid ; "><colgroup><col align="left"><col align="left"><col align="left"></colgroup><thead><tr><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="center">Alias</th><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="center">Filter Class</th><th style="border-bottom: 0.5pt solid ; " align="center">Namespace Element or Attribute</th></tr></thead><tbody><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> CHANNEL_FILTER</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">ChannelProcessingFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/intercept-url at requires-channel</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> CONCURRENT_SESSION_FILTER</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">ConcurrentSessionFilter</code> </td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">session-management/concurrency-control</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> SECURITY_CONTEXT_FILTER</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="classname">SecurityContextPersistenceFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> LOGOUT_FILTER </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">LogoutFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/logout</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> X509_FILTER </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">X509AuthenticationFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/x509</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> PRE_AUTH_FILTER </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">AstractPreAuthenticatedProcessingFilter</code>
+ Subclasses</td><td style="border-bottom: 0.5pt solid ; " align="left">N/A</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> CAS_FILTER </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">CasAuthenticationFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left">N/A</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> FORM_LOGIN_FILTER </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">UsernamePasswordAuthenticationFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/form-login</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> BASIC_AUTH_FILTER </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">BasicAuthenticationFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/http-basic</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> SERVLET_API_SUPPORT_FILTER</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">SecurityContextHolderAwareFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/@servlet-api-provision</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">JAAS_API_SUPPORT_FILTER</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">JaasApiIntegrationFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/@jaas-api-provision</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> REMEMBER_ME_FILTER </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="classname">RememberMeAuthenticationFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/remember-me</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> ANONYMOUS_FILTER </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">AnonymousAuthenticationFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/anonymous</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> SESSION_MANAGEMENT_FILTER</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">SessionManagementFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">session-management</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">EXCEPTION_TRANSLATION_FILTER </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="classname">ExceptionTranslationFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> FILTER_SECURITY_INTERCEPTOR </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="classname">FilterSecurityInterceptor</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http</code></td></tr><tr><td style="border-right: 0.5pt solid ; " align="left"> SWITCH_USER_FILTER </td><td style="border-right: 0.5pt solid ; " align="left"><code class="literal">SwitchUserFilter</code></td><td style="" align="left">N/A</td></tr></tbody></table></div></div><p><br class="table-break"> You can add your own filter to the stack, using the
+ <code class="literal">custom-filter</code> element and one of these names to specify the
+ position your filter should appear at: </p><pre class="programlisting">
<span class="hl-tag"><http></span>
<span class="hl-tag"><custom-filter</span> <span class="hl-attribute">position</span>=<span class="hl-value">"FORM_LOGIN_FILTER"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"myFilter"</span><span class="hl-tag"> /></span>
<span class="hl-tag"></http></span>
@@ -470,45 +493,56 @@ List<OpenIDAttribute> attributes = token.getAttributes();</pre><p>The
<span class="hl-tag"><beans:bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"myFilter"</span> <span class="hl-attribute">class</span>=<span class="hl-value">"com.mycompany.MySpecialAuthenticationFilter"</span><span class="hl-tag">/></span>
</pre><p> You can also use the <code class="literal">after</code> or <code class="literal">before</code>
- attributes if you want your filter to be inserted before or after another filter in the
- stack. The names "FIRST" and "LAST" can be used with the <code class="literal">position</code>
- attribute to indicate that you want your filter to appear before or after the entire stack,
- respectively. </p><div class="tip" title="Avoiding filter position conflicts" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip: Avoiding filter position conflicts"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Avoiding filter position conflicts</th></tr><tr><td align="left" valign="top"><p> If you are inserting a custom filter which may occupy the same position as one of the
- standard filters created by the namespace then it's important that you don't include the
- namespace versions by mistake. Avoid using the <code class="literal">auto-config</code> attribute
- and remove any elements which create filters whose functionality you want to replace. </p><p> Note that you can't replace filters which are created by the use of the
- <code class="literal"><http></code> element itself -
- <code class="classname">SecurityContextPersistenceFilter</code>,
- <code class="classname">ExceptionTranslationFilter</code> or
- <code class="classname">FilterSecurityInterceptor</code>. </p></td></tr></table></div><p> If you're replacing a namespace filter which requires an authentication entry point
- (i.e. where the authentication process is triggered by an attempt by an unauthenticated user
- to access to a secured resource), you will need to add a custom entry point bean too. </p><div class="section" title="Setting a Custom AuthenticationEntryPoint"><div class="titlepage"><div><div><h4 class="title"><a name="ns-entry-point-ref"></a>Setting a Custom <code class="interfacename">AuthenticationEntryPoint</code></h4></div></div></div><p> If you aren't using form login, OpenID or basic authentication through the namespace,
- you may want to define an authentication filter and entry point using a traditional bean
- syntax and link them into the namespace, as we've just seen. The corresponding
- <code class="interfacename">AuthenticationEntryPoint</code> can be set using the
- <code class="literal">entry-point-ref</code> attribute on the <code class="literal"><http></code>
- element. </p><p> The CAS sample application is a good example of the use of custom beans with the
- namespace, including this syntax. If you aren't familiar with authentication entry points,
- they are discussed in the <a class="link" href="technical-overview.html#tech-intro-auth-entry-point" title="5.4.2 AuthenticationEntryPoint">technical
- overview</a> chapter. </p></div></div></div><div class="section" title="2.4 Method Security"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ns-method-security"></a>2.4 Method Security</h2></div></div></div><p>From version 2.0 onwards Spring Security has improved support substantially for adding
- security to your service layer methods. It provides support for JSR-250 annotation security as
- well as the framework's original <code class="literal">@Secured</code> annotation. From 3.0 you can also
- make use of new <a class="link" href="el-access.html" title="15. Expression-Based Access Control">expression-based annotations</a>. You can
- apply security to a single bean, using the <code class="literal">intercept-methods</code> element to
- decorate the bean declaration, or you can secure multiple beans across the entire service
- layer using the AspectJ style pointcuts. </p><div class="section" title="2.4.1 The <global-method-security> Element"><div class="titlepage"><div><div><h3 class="title"><a name="ns-global-method"></a>2.4.1 The <code class="literal"><global-method-security></code> Element</h3></div></div></div><p> This element is used to enable annotation-based security in your application (by
- setting the appropriate attributes on the element), and also to group together security
- pointcut declarations which will be applied across your entire application context. You
- should only declare one <code class="literal"><global-method-security></code> element. The
- following declaration would enable support for Spring Security's
- <code class="literal">@Secured</code>: </p><pre class="programlisting">
- <global-method-security secured-annotations="enabled" />
+ attributes if you want your filter to be inserted before or after another filter in
+ the stack. The names "FIRST" and "LAST" can be used with the
+ <code class="literal">position</code> attribute to indicate that you want your filter to
+ appear before or after the entire stack, respectively. </p><div class="tip" title="Avoiding filter position conflicts" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip: Avoiding filter position conflicts"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Avoiding filter position conflicts</th></tr><tr><td align="left" valign="top"><p> If you are inserting a custom filter which may occupy the same position as
+ one of the standard filters created by the namespace then it's important that
+ you don't include the namespace versions by mistake. Avoid using the
+ <code class="literal">auto-config</code> attribute and remove any elements which create
+ filters whose functionality you want to replace. </p><p> Note that you can't replace filters which are created by the use of the
+ <code class="literal"><http></code> element itself -
+ <code class="classname">SecurityContextPersistenceFilter</code>,
+ <code class="classname">ExceptionTranslationFilter</code> or
+ <code class="classname">FilterSecurityInterceptor</code>. Some other filters are added
+ by default, but you can disable them. An <code class="classname">AnonymousAuthenticationFilter</code>
+ is added by default and unless you have
+ <a class="link" href="ns-config.html#ns-session-fixation" title="Session Fixation Attack Protection">session-fixation protection</a>
+ disabled, a <code class="classname">SessionManagementFilter</code> will also be added
+ to the filter chain.
+ </p></td></tr></table></div><p> If you're replacing a namespace filter which requires an authentication entry
+ point (i.e. where the authentication process is triggered by an attempt by an
+ unauthenticated user to access to a secured resource), you will need to add a custom
+ entry point bean too. </p><div class="section" title="Setting a Custom AuthenticationEntryPoint"><div class="titlepage"><div><div><h4 class="title"><a name="ns-entry-point-ref"></a>Setting a Custom
+ <code class="interfacename">AuthenticationEntryPoint</code></h4></div></div></div><p> If you aren't using form login, OpenID or basic authentication through the
+ namespace, you may want to define an authentication filter and entry point using
+ a traditional bean syntax and link them into the namespace, as we've just seen.
+ The corresponding <code class="interfacename">AuthenticationEntryPoint</code> can be
+ set using the <code class="literal">entry-point-ref</code> attribute on the
+ <code class="literal"><http></code> element. </p><p> The CAS sample application is a good example of the use of custom beans with
+ the namespace, including this syntax. If you aren't familiar with authentication
+ entry points, they are discussed in the <a class="link" href="technical-overview.html#tech-intro-auth-entry-point" title="6.4.2 AuthenticationEntryPoint">technical overview</a> chapter.
+ </p></div></div></div><div class="section" title="3.4 Method Security"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ns-method-security"></a>3.4 Method Security</h2></div></div></div><p>From version 2.0 onwards Spring Security has improved support substantially for adding
+ security to your service layer methods. It provides support for JSR-250 annotation
+ security as well as the framework's original <code class="literal">@Secured</code> annotation.
+ From 3.0 you can also make use of new <a class="link" href="el-access.html" title="16. Expression-Based Access Control">expression-based
+ annotations</a>. You can apply security to a single bean, using the
+ <code class="literal">intercept-methods</code> element to decorate the bean declaration, or you
+ can secure multiple beans across the entire service layer using the AspectJ style
+ pointcuts. </p><div class="section" title="3.4.1 The <global-method-security> Element"><div class="titlepage"><div><div><h3 class="title"><a name="ns-global-method"></a>3.4.1 The <code class="literal"><global-method-security></code> Element</h3></div></div></div><p> This element is used to enable annotation-based security in your application (by
+ setting the appropriate attributes on the element), and also to group together
+ security pointcut declarations which will be applied across your entire application
+ context. You should only declare one
+ <code class="literal"><global-method-security></code> element. The following declaration
+ would enable support for Spring Security's <code class="literal">@Secured</code>: </p><pre class="programlisting">
+ <span class="hl-tag"><global-method-security</span> <span class="hl-attribute">secured-annotations</span>=<span class="hl-value">"enabled"</span><span class="hl-tag"> /></span>
</pre><p> Adding an annotation to a method (on an class or interface) would then limit
- the access to that method accordingly. Spring Security's native annotation support defines a
- set of attributes for the method. These will be passed to the
- <code class="interfacename">AccessDecisionManager</code> for it to make the actual decision:
- </p><pre class="programlisting">
+ the access to that method accordingly. Spring Security's native annotation support
+ defines a set of attributes for the method. These will be passed to the
+ <code class="interfacename">AccessDecisionManager</code> for it to make the actual
+ decision:
+ </p><pre class="programlisting">
<span class="hl-keyword">public</span> <span class="hl-keyword">interface</span> BankService {
<i><span class="hl-annotation" style="color: gray">@Secured("IS_AUTHENTICATED_ANONYMOUSLY")</span></i>
@@ -521,16 +555,15 @@ List<OpenIDAttribute> attributes = token.getAttributes();</pre><p>The
<span class="hl-keyword">public</span> Account post(Account account, <span class="hl-keyword">double</span> amount);
}
</pre><p>Support
- for JSR-250 annotations can be enabled using </p><pre class="programlisting">
- <global-method-security jsr250-annotations="enabled" />
+ for JSR-250 annotations can be enabled using </p><pre class="programlisting">
+ <span class="hl-tag"><global-method-security</span> <span class="hl-attribute">jsr250-annotations</span>=<span class="hl-value">"enabled"</span><span class="hl-tag"> /></span>
- </pre><p>These are standards-based and allow simple role-based constraints to be
- applied but do not have the power Spring Security's native annotations.
- To use the new expression-based syntax, you would use
-</p><pre class="programlisting">
- <global-method-security pre-post-annotations="enabled" />
+ </pre><p>These are standards-based and allow simple role-based constraints to
+ be applied but do not have the power Spring Security's native annotations. To use
+ the new expression-based syntax, you would use </p><pre class="programlisting">
+ <span class="hl-tag"><global-method-security</span> <span class="hl-attribute">pre-post-annotations</span>=<span class="hl-value">"enabled"</span><span class="hl-tag"> /></span>
</pre><p>and the equivalent Java code would
- be</p><pre class="programlisting">
+ be</p><pre class="programlisting">
<span class="hl-keyword">public</span> <span class="hl-keyword">interface</span> BankService {
<i><span class="hl-annotation" style="color: gray">@PreAuthorize("isAnonymous()")</span></i>
@@ -543,56 +576,65 @@ List<OpenIDAttribute> attributes = token.getAttributes();</pre><p>The
<span class="hl-keyword">public</span> Account post(Account account, <span class="hl-keyword">double</span> amount);
}
</pre><p>Expression-based
- annotations are a good choice if you need to define simple rules that go beyond checking the
- role names against the user's list of authorities. You can enable more than one type of
- annotation in the same application, but you should avoid mixing annotations types in the
- same interface or class to avoid confusion.</p><div class="section" title="Adding Security Pointcuts using protect-pointcut"><div class="titlepage"><div><div><h4 class="title"><a name="ns-protect-pointcut"></a>Adding Security Pointcuts using <code class="literal">protect-pointcut</code></h4></div></div></div><p> The use of <code class="literal">protect-pointcut</code> is particularly powerful, as it allows
- you to apply security to many beans with only a simple declaration. Consider the following
- example: </p><pre class="programlisting">
+ annotations are a good choice if you need to define simple rules that go beyond
+ checking the role names against the user's list of authorities. You can enable more
+ than one type of annotation in the same application, but you should avoid mixing
+ annotations types in the same interface or class to avoid confusion. </p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>The annotated methods will only be secured for instances which are defined as
+ Spring beans (in the same application context in which method-security is
+ enabled). If you want to secure instances which are not created by Spring (using
+ the <code class="literal">new</code> operator, for example) then you need to use AspectJ.
+ </p></td></tr></table></div><p> </p><div class="section" title="Adding Security Pointcuts using protect-pointcut"><div class="titlepage"><div><div><h4 class="title"><a name="ns-protect-pointcut"></a>Adding Security Pointcuts using <code class="literal">protect-pointcut</code></h4></div></div></div><p> The use of <code class="literal">protect-pointcut</code> is particularly powerful, as
+ it allows you to apply security to many beans with only a simple declaration.
+ Consider the following example: </p><pre class="programlisting">
<span class="hl-tag"><global-method-security></span>
<span class="hl-tag"><protect-pointcut</span> <span class="hl-attribute">expression</span>=<span class="hl-value">"execution(* com.mycompany.*Service.*(..))"</span>
<span class="hl-attribute">access</span>=<span class="hl-value">"ROLE_USER"</span><span class="hl-tag">/></span>
<span class="hl-tag"></global-method-security></span>
</pre><p> This will protect all methods on beans declared in the application
- context whose classes are in the <code class="literal">com.mycompany</code> package and whose class
- names end in "Service". Only users with the <code class="literal">ROLE_USER</code> role will be able
- to invoke these methods. As with URL matching, the most specific matches must come first
- in the list of pointcuts, as the first matching expression will be used. </p></div></div></div><div class="section" title="2.5 The Default AccessDecisionManager"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ns-access-manager"></a>2.5 The Default AccessDecisionManager</h2></div></div></div><p> This section assumes you have some knowledge of the underlying architecture for
- access-control within Spring Security. If you don't you can skip it and come back to it later,
- as this section is only really relevant for people who need to do some customization in order
- to use more than simple role-based security. </p><p> When you use a namespace configuration, a default instance of
- <code class="interfacename">AccessDecisionManager</code> is automatically registered for you and
- will be used for making access decisions for method invocations and web URL access, based on
- the access attributes you specify in your <code class="literal">intercept-url</code> and
- <code class="literal">protect-pointcut</code> declarations (and in annotations if you are using
- annotation secured methods). </p><p> The default strategy is to use an <code class="classname">AffirmativeBased</code>
- <code class="interfacename">AccessDecisionManager</code> with a <code class="classname">RoleVoter</code>
- and an <code class="classname">AuthenticatedVoter</code>. You can find out more about these in the
- chapter on <a class="link" href="authorization" target="_top">authorization</a>.</p><div class="section" title="2.5.1 Customizing the AccessDecisionManager"><div class="titlepage"><div><div><h3 class="title"><a name="ns-custom-access-mgr"></a>2.5.1 Customizing the AccessDecisionManager</h3></div></div></div><p> If you need to use a more complicated access control strategy then it is easy to set an
- alternative for both method and web security. </p><p> For method security, you do this by setting the
- <code class="literal">access-decision-manager-ref</code> attribute on
- <code class="literal">global-method-security</code> to the Id of the appropriate
- <code class="interfacename">AccessDecisionManager</code> bean in the application context: </p><pre class="programlisting">
+ context whose classes are in the <code class="literal">com.mycompany</code> package and
+ whose class names end in "Service". Only users with the
+ <code class="literal">ROLE_USER</code> role will be able to invoke these methods. As with
+ URL matching, the most specific matches must come first in the list of
+ pointcuts, as the first matching expression will be used. </p></div></div></div><div class="section" title="3.5 The Default AccessDecisionManager"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ns-access-manager"></a>3.5 The Default AccessDecisionManager</h2></div></div></div><p> This section assumes you have some knowledge of the underlying architecture for
+ access-control within Spring Security. If you don't you can skip it and come back to it
+ later, as this section is only really relevant for people who need to do some
+ customization in order to use more than simple role-based security. </p><p> When you use a namespace configuration, a default instance of
+ <code class="interfacename">AccessDecisionManager</code> is automatically registered for you
+ and will be used for making access decisions for method invocations and web URL access,
+ based on the access attributes you specify in your <code class="literal">intercept-url</code> and
+ <code class="literal">protect-pointcut</code> declarations (and in annotations if you are using
+ annotation secured methods). </p><p> The default strategy is to use an <code class="classname">AffirmativeBased</code>
+ <code class="interfacename">AccessDecisionManager</code> with a
+ <code class="classname">RoleVoter</code> and an <code class="classname">AuthenticatedVoter</code>. You
+ can find out more about these in the chapter on <a class="link" href="authz-arch.html" title="14. Authorization Architecture">authorization</a>.</p><div class="section" title="3.5.1 Customizing the AccessDecisionManager"><div class="titlepage"><div><div><h3 class="title"><a name="ns-custom-access-mgr"></a>3.5.1 Customizing the AccessDecisionManager</h3></div></div></div><p> If you need to use a more complicated access control strategy then it is easy to
+ set an alternative for both method and web security. </p><p> For method security, you do this by setting the
+ <code class="literal">access-decision-manager-ref</code> attribute on
+ <code class="literal">global-method-security</code> to the <code class="literal">id</code> of the appropriate
+ <code class="interfacename">AccessDecisionManager</code> bean in the application
+ context: </p><pre class="programlisting">
<span class="hl-tag"><global-method-security</span> <span class="hl-attribute">access-decision-manager-ref</span>=<span class="hl-value">"myAccessDecisionManagerBean"</span><span class="hl-tag">></span>
...
<span class="hl-tag"></global-method-security></span>
- </pre><p> The syntax for web security is the same, but on the <code class="literal">http</code> element: </p><pre class="programlisting">
+ </pre><p> The syntax for web security is the same, but on the <code class="literal">http</code>
+ element: </p><pre class="programlisting">
<span class="hl-tag"><http</span> <span class="hl-attribute">access-decision-manager-ref</span>=<span class="hl-value">"myAccessDecisionManagerBean"</span><span class="hl-tag">></span>
...
<span class="hl-tag"></http></span>
- </pre></div></div><div class="section" title="2.6 The Authentication Manager and the Namespace"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ns-auth-manager"></a>2.6 The Authentication Manager and the Namespace</h2></div></div></div><p> The main interface which provides authentication services in Spring Security is the
- <code class="interfacename">AuthenticationManager</code>. This is usually an instance of Spring
- Security's <code class="classname">ProviderManager</code> class, which you may already be familiar
- with if you've used the framework before. If not, it will be covered later, in the <a class="link" href="technical-overview.html#tech-intro-authentication" title="5.3 Authentication">technical overview chapter</a>. The bean instance
- is registered using the <code class="literal">authentication-manager</code> namespace element. You can't
- use a custom <code class="classname">AuthenticationManager</code> if you are using either HTTP or
- method security through the namespace, but this should not be a problem as you have full
- control over the <code class="classname">AuthenticationProvider</code>s that are used.</p><p> You may want to register additional <code class="classname">AuthenticationProvider</code> beans
- with the <code class="classname">ProviderManager</code> and you can do this using the
- <code class="literal"><authentication-provider></code> element with the <code class="literal">ref</code>
- attribute, where the value of the attribute is the name of the provider bean you want to add.
- For example: </p><pre class="programlisting">
+ </pre></div></div><div class="section" title="3.6 The Authentication Manager and the Namespace"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ns-auth-manager"></a>3.6 The Authentication Manager and the Namespace</h2></div></div></div><p> The main interface which provides authentication services in Spring Security is the
+ <code class="interfacename">AuthenticationManager</code>. This is usually an instance of
+ Spring Security's <code class="classname">ProviderManager</code> class, which you may already be
+ familiar with if you've used the framework before. If not, it will be covered later, in
+ the <a class="link" href="technical-overview.html#tech-intro-authentication" title="6.3 Authentication">technical overview chapter</a>. The
+ bean instance is registered using the <code class="literal">authentication-manager</code>
+ namespace element. You can't use a custom <code class="classname">AuthenticationManager</code>
+ if you are using either HTTP or method security through the namespace, but this should
+ not be a problem as you have full control over the
+ <code class="classname">AuthenticationProvider</code>s that are used.</p><p> You may want to register additional <code class="classname">AuthenticationProvider</code>
+ beans with the <code class="classname">ProviderManager</code> and you can do this using the
+ <code class="literal"><authentication-provider></code> element with the
+ <code class="literal">ref</code> attribute, where the value of the attribute is the name of the
+ provider bean you want to add. For example: </p><pre class="programlisting">
<span class="hl-tag"><authentication-manager></span>
<span class="hl-tag"><authentication-provider</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"casAuthenticationProvider"</span><span class="hl-tag">/></span>
<span class="hl-tag"></authentication-manager></span>
@@ -601,10 +643,10 @@ List<OpenIDAttribute> attributes = token.getAttributes();</pre><p>The
<span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.cas.authentication.CasAuthenticationProvider"</span><span class="hl-tag">></span>
...
<span class="hl-tag"></bean></span>
- </pre><p> Another common requirement is that another bean in the context may require a reference to
- the <code class="interfacename">AuthenticationManager</code>. You can easily register an alias for
- the <code class="interfacename">AuthenticationManager</code> and use this name elsewhere in your
- application context. </p><pre class="programlisting">
+ </pre><p> Another common requirement is that another bean in the context may require a
+ reference to the <code class="interfacename">AuthenticationManager</code>. You can easily
+ register an alias for the <code class="interfacename">AuthenticationManager</code> and use
+ this name elsewhere in your application context. </p><pre class="programlisting">
<span class="hl-tag"><security:authentication-manager</span> <span class="hl-attribute">alias</span>=<span class="hl-value">"authenticationManager"</span><span class="hl-tag">></span>
...
<span class="hl-tag"></security:authentication-manager></span>
@@ -614,25 +656,35 @@ List<OpenIDAttribute> attributes = token.getAttributes();</pre><p>The
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"authenticationManager"</span><span class="hl-tag">/></span>
...
<span class="hl-tag"></bean></span>
- </pre></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e358" href="#d0e358" class="para">1</a>] </sup>You can find
- out more about the use of the <code class="literal">ldap-server</code> element in the chapter on
- <a class="link" href="ldap.html" title="18. LDAP Authentication">LDAP</a>.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e480" href="#d0e480" class="para">2</a>] </sup>See the section on Request
- Matching in the Web Application Infrastructure chapter for more details
- on how matches are actually performed.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e493" href="#d0e493" class="para">3</a>] </sup>The
- interpretation of the comma-separated values in the <code class="literal">access</code> attribute
- depends on the implementation of the <a class="link" href="ns-config.html#ns-access-manager" title="2.5 The Default AccessDecisionManager">AccessDecisionManager</a> which is used. In Spring Security 3.0, the attribute can
- also be populated with an <a class="link" href="el-access.html" title="15. Expression-Based Access Control">EL
- expression</a>.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e602" href="#d0e602" class="para">4</a>] </sup>In versions prior
- to 3.0, this list also included remember-me functionality. This could cause some
- confusing errors with some configurations and was removed in 3.0. In 3.0, the addition
- of an <code class="classname">AnonymousAuthenticationFilter</code> is part of the default
- <code class="literal"><http></code> configuration, so the <code class="literal"><anonymous
- /></code> element is added regardless of whether <code class="literal">auto-config</code>
- is enabled.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e635" href="#d0e635" class="para">5</a>] </sup>See the
- chapter on <a class="link" href="anonymous.html" title="12. Anonymous Authentication">anonymous authentication</a> and also the
- <a class="link" href="authz-arch.html#authz-authenticated-voter" title="AuthenticatedVoter">AuthenticatedVoter</a> class for
- more details on how the value <code class="literal">IS_AUTHENTICATED_ANONYMOUSLY</code> is
- processed.</p></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
+ </pre></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e521" href="#d0e521" class="para">1</a>] </sup>You can find out more about the use of the <code class="literal">ldap-server</code> element
+ in the chapter on <a class="link" href="ldap.html" title="19. LDAP Authentication">LDAP</a>.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e643" href="#d0e643" class="para">2</a>] </sup>See the section on <a class="link" href="security-filter-chain.html#request-matching" title="8.4 Request Matching and HttpFirewall">Request
+ Matching</a> in the Web Application Infrastructure chapter for more details
+ on how matches are actually performed.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e656" href="#d0e656" class="para">3</a>] </sup>The interpretation of the comma-separated values in the
+ <code class="literal">access</code> attribute depends on the implementation of the <a class="link" href="ns-config.html#ns-access-manager" title="3.5 The Default AccessDecisionManager">AccessDecisionManager</a> which is used. In
+ Spring Security 3.0, the attribute can also be populated with an <a class="link" href="el-access.html" title="16. Expression-Based Access Control">EL expression</a>.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e765" href="#d0e765" class="para">4</a>] </sup>In versions prior to 3.0, this list also included remember-me
+ functionality. This could cause some confusing errors with some
+ configurations and was removed in 3.0. In 3.0, the addition of an
+ <code class="classname">AnonymousAuthenticationFilter</code> is part of the default
+ <code class="literal"><http></code> configuration, so the <code class="literal"><anonymous
+ /></code> element is added regardless of whether
+ <code class="literal">auto-config</code> is enabled.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e801" href="#d0e801" class="para">5</a>] </sup>See the chapter on <a class="link" href="anonymous.html" title="13. Anonymous Authentication">anonymous
+ authentication</a> and also the <a class="link" href="authz-arch.html#authz-authenticated-voter" title="AuthenticatedVoter">AuthenticatedVoter</a> class for more details on how the value
+ <code class="literal">IS_AUTHENTICATED_ANONYMOUSLY</code> is processed.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e832" href="#d0e832" class="para">6</a>] </sup>The use of multiple <code class="literal"><http></code> elements is an important
+ feature, allowing the namespace to simultaneously support both stateful and
+ stateless paths within the same application, for example. The previous syntax,
+ using the attribute <code class="literal">filters="none"</code> on an
+ <code class="literal">intercept-url</code> element is incompatible with this change and is
+ no longer supported in 3.1.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e1018" href="#d0e1018" class="para">7</a>] </sup>For more details on how channel-processing is implemented, see the Javadoc
+ for <code class="classname">ChannelProcessingFilter</code> and related classes.
+ </p></div><div class="footnote"><p><sup>[<a name="ftn.d0e1047" href="#d0e1047" class="para">8</a>] </sup>If you are running your application behind a proxy, you may also be able
+ to remove the session cookie by configuring the proxy server. For example,
+ using Apache HTTPD's mod_headers, the following directive would delete the
+ <code class="literal">JSESSIONID</code> cookie by expiring it in the response to a
+ logout request (assuming the application is deployed under the path
+ <code class="literal">/tutorial</code>):
+ <pre class="programlisting"> <span class="hl-tag"><LocationMatch</span> <span class="hl-attribute">"/tutorial/j_spring_security_logout"></span>
+ <span class="hl-attribute">Header</span> <span class="hl-attribute">always</span> <span class="hl-attribute">set</span> <span class="hl-attribute">Set-Cookie</span> <span class="hl-attribute">"JSESSIONID</span>=<span class="hl-value">;Path=</span><span class="hl-tag">/t</span>utorial;Expires=Thu, 01 Jan 1970 00:00:00 GMT"
+ <span class="hl-tag"></LocationMatch></span></pre></p></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
- </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="introduction.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="getting-started.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="sample-apps.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">1. Introduction </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 3. Sample Applications</td></tr></table></div></body></html>
\ No newline at end of file
+ </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="new-3.1.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="getting-started.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="sample-apps.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">2. What's new in Spring Security 3.1 </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 4. Sample Applications</td></tr></table></div></body></html>
\ No newline at end of file
diff --git a/docs/reference/overall-architecture.html b/docs/reference/overall-architecture.html
index cf288a9..202dc1a 100644
--- a/docs/reference/overall-architecture.html
+++ b/docs/reference/overall-architecture.html
@@ -1,6 +1,6 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>Part II. Architecture and Implementation</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="springsecurity.html" title="Spring Security"><link rel="prev" href="community.html" title="4. Spring Security Community"><link rel="next" href="technical-overview.html" title="5. Technical Overview"><!--Begin Google Analytics code--><script type="text/javascript">
+ <title>Part II. Architecture and Implementation</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="springsecurity.html" title="Spring Security"><link rel="prev" href="community.html" title="5. Spring Security Community"><link rel="next" href="technical-overview.html" title="6. Technical Overview"><!--Begin Google Analytics code--><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
@@ -8,13 +8,13 @@
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
- </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Part II. Architecture and Implementation</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="community.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="technical-overview.html">Next</a></td></tr></table><hr></div><div class="part" title="Part II. Architecture and Implementation"><div class="titlepage"><div><div><h1 class="title"><a name="overall-architecture"></a>Part II. Architecture and Implementation</h1></div></div></div><div class="partintro" title="Architecture and Implementation"><div></div><p>Once you are familiar with setting up and running some namespace-configuration based
- applications, you may wish to develop more of an understanding of how the framework actually
- works behind the namespace facade. Like most software, Spring Security has certain central
- interfaces, classes and conceptual abstractions that are commonly used throughout the
- framework. In this part of the reference guide we will look at some of these and see how
- they work together to support authentication and access-control within Spring
- Security.</p></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
+ </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Part II. Architecture and Implementation</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="community.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="technical-overview.html">Next</a></td></tr></table><hr></div><div class="part" title="Part II. Architecture and Implementation"><div class="titlepage"><div><div><h1 class="title"><a name="overall-architecture"></a>Part II. Architecture and Implementation</h1></div></div></div><div class="partintro" title="Architecture and Implementation"><div></div><p>Once you are familiar with setting up and running some namespace-configuration
+ based applications, you may wish to develop more of an understanding of how the
+ framework actually works behind the namespace facade. Like most software, Spring
+ Security has certain central interfaces, classes and conceptual abstractions that
+ are commonly used throughout the framework. In this part of the reference guide we
+ will look at some of these and see how they work together to support authentication
+ and access-control within Spring Security.</p></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
- </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="community.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="technical-overview.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">4. Spring Security Community </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 5. Technical Overview</td></tr></table></div></body></html>
\ No newline at end of file
+ </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="community.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="technical-overview.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">5. Spring Security Community </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 6. Technical Overview</td></tr></table></div></body></html>
\ No newline at end of file
diff --git a/docs/reference/preauth.html b/docs/reference/preauth.html
index 98bae7c..e1b286a 100644
--- a/docs/reference/preauth.html
+++ b/docs/reference/preauth.html
@@ -1,6 +1,6 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>17. Pre-Authentication Scenarios</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="advanced-topics.html" title="Part V. Additional Topics"><link rel="prev" href="domain-acls.html" title="16. Domain Object Security (ACLs)"><link rel="next" href="ldap.html" title="18. LDAP Authentication"><!--Begin Google Analytics code--><script type="text/javascript">
+ <title>18. Pre-Authentication Scenarios</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="advanced-topics.html" title="Part V. Additional Topics"><link rel="prev" href="domain-acls.html" title="17. Domain Object Security (ACLs)"><link rel="next" href="ldap.html" title="19. LDAP Authentication"><!--Begin Google Analytics code--><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
@@ -8,140 +8,145 @@
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
- </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">17. Pre-Authentication Scenarios</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="domain-acls.html">Prev</a> </td><th width="60%" align="center">Part V. Additional Topics</th><td width="20%" align="right"> <a accesskey="n" href="ldap.html">Next</a></td></tr></table><hr></div><div class="chapter" title="17. Pre-Authentication Scenarios"><div class="titlepage"><div><div><h1 class="title"><a name="preauth"></a>Pre-Authentication Scenarios</h1></div></div></div><p> There are situations where you want to use Spring Security for authorization, but the user
- has already been reliably authenticated by some external system prior to accessing the
- application. We refer to these situations as <span class="quote">“<span class="quote">pre-authenticated</span>”</span> scenarios.
- Examples include X.509, Siteminder and authentication by the J2EE container in which the
- application is running. When using pre-authentication, Spring Security has to
- </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>Identify the user making the request.
- </p></li><li class="listitem"><p>Obtain the authorities for the
- user.</p></li></ol></div><p>The details will depend on the external authentication
- mechanism. A user might be identified by their certificate information in the case of X.509, or
- by an HTTP request header in the case of Siteminder. If relying on container authentication, the
- user will be identified by calling the <code class="methodname">getUserPrincipal()</code> method on the
- incoming HTTP request. In some cases, the external mechanism may supply role/authority
- information for the user but in others the authorities must be obtained from a separate source,
- such as a <code class="interfacename">UserDetailsService</code>. </p><div class="section" title="17.1 Pre-Authentication Framework Classes"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e5505"></a>17.1 Pre-Authentication Framework Classes</h2></div></div></div><p> Because most pre-authentication mechanisms follow the same pattern, Spring Security has a
- set of classes which provide an internal framework for implementing pre-authenticated
- authentication providers. This removes duplication and allows new implementations to be added
- in a structured fashion, without having to write everything from scratch. You don't need to
- know about these classes if you want to use something like <a class="link" href="x509.html" title="22. X.509 Authentication">X.509
- authentication</a>, as it already has a namespace configuration option which is simpler
- to use and get started with. If you need to use explicit bean configuration or are planning on
- writing your own implementation then an understanding of how the provided implementations work
- will be useful. You will find classes under the
- <span class="package">org.springframework.security.web.authentication.preauth</span>. We just provide
- an outline here so you should consult the Javadoc and source where appropriate. </p><div class="section" title="17.1.1 AbstractPreAuthenticatedProcessingFilter"><div class="titlepage"><div><div><h3 class="title"><a name="d0e5516"></a>17.1.1 AbstractPreAuthenticatedProcessingFilter</h3></div></div></div><p> This class will check the current contents of the security context and, if empty, it
- will attempt to extract user information from the HTTP request and submit it to the
- <code class="interfacename">AuthenticationManager</code>. Subclasses override the following
- methods to obtain this information:
- </p><pre class="programlisting">
+ </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">18. Pre-Authentication Scenarios</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="domain-acls.html">Prev</a> </td><th width="60%" align="center">Part V. Additional Topics</th><td width="20%" align="right"> <a accesskey="n" href="ldap.html">Next</a></td></tr></table><hr></div><div class="chapter" title="18. Pre-Authentication Scenarios"><div class="titlepage"><div><div><h1 class="title"><a name="preauth"></a>Pre-Authentication Scenarios</h1></div></div></div><p> There are situations where you want to use Spring Security for authorization, but the
+ user has already been reliably authenticated by some external system prior to accessing the
+ application. We refer to these situations as <span class="quote">“<span class="quote">pre-authenticated</span>”</span> scenarios.
+ Examples include X.509, Siteminder and authentication by the J2EE container in which the
+ application is running. When using pre-authentication, Spring Security has to </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>Identify the user making the request. </p></li><li class="listitem"><p>Obtain the authorities for the user.</p></li></ol></div><p>The details will depend on the external authentication mechanism. A user might
+ be identified by their certificate information in the case of X.509, or by an HTTP request
+ header in the case of Siteminder. If relying on container authentication, the user will be
+ identified by calling the <code class="methodname">getUserPrincipal()</code> method on the incoming
+ HTTP request. In some cases, the external mechanism may supply role/authority information
+ for the user but in others the authorities must be obtained from a separate source, such as
+ a <code class="interfacename">UserDetailsService</code>. </p><div class="section" title="18.1 Pre-Authentication Framework Classes"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e6142"></a>18.1 Pre-Authentication Framework Classes</h2></div></div></div><p> Because most pre-authentication mechanisms follow the same pattern, Spring Security
+ has a set of classes which provide an internal framework for implementing
+ pre-authenticated authentication providers. This removes duplication and allows new
+ implementations to be added in a structured fashion, without having to write everything
+ from scratch. You don't need to know about these classes if you want to use something
+ like <a class="link" href="x509.html" title="23. X.509 Authentication">X.509 authentication</a>, as it already has a namespace
+ configuration option which is simpler to use and get started with. If you need to use
+ explicit bean configuration or are planning on writing your own implementation then an
+ understanding of how the provided implementations work will be useful. You will find
+ classes under the
+ <span class="package">org.springframework.security.web.authentication.preauth</span>. We just
+ provide an outline here so you should consult the Javadoc and source where appropriate. </p><div class="section" title="18.1.1 AbstractPreAuthenticatedProcessingFilter"><div class="titlepage"><div><div><h3 class="title"><a name="d0e6153"></a>18.1.1 AbstractPreAuthenticatedProcessingFilter</h3></div></div></div><p> This class will check the current contents of the security context and, if empty,
+ it will attempt to extract user information from the HTTP request and submit it to
+ the <code class="interfacename">AuthenticationManager</code>. Subclasses override the
+ following methods to obtain this information:
+ </p><pre class="programlisting">
<span class="hl-keyword">protected</span> <span class="hl-keyword">abstract</span> Object getPreAuthenticatedPrincipal(HttpServletRequest request);
<span class="hl-keyword">protected</span> <span class="hl-keyword">abstract</span> Object getPreAuthenticatedCredentials(HttpServletRequest request);
</pre><p>
- After calling these, the filter will create a
- <code class="classname">PreAuthenticatedAuthenticationToken</code> containing the returned data
- and submit it for authentication. By <span class="quote">“<span class="quote">authentication</span>”</span> here, we really just mean
- further processing to perhaps load the user's authorities, but the standard Spring Security
- authentication architecture is followed. </p></div><div class="section" title="17.1.2 AbstractPreAuthenticatedAuthenticationDetailsSource"><div class="titlepage"><div><div><h3 class="title"><a name="d0e5533"></a>17.1.2 AbstractPreAuthenticatedAuthenticationDetailsSource</h3></div></div></div><p> Like other Spring Security authentication filters, the pre-authentication filter has an
- <code class="literal">authenticationDetailsSource</code> property which by default will create a
- <code class="classname">WebAuthenticationDetails</code> object to store additional information
- such as the session-identifier and originating IP address in the <code class="literal">details</code>
- property of the <code class="interfacename">Authentication</code> object. In cases where user
- role information can be obtained from the pre-authentication mechanism, the data is also
- stored in this property. Subclasses of
- <code class="classname">AbstractPreAuthenticatedAuthenticationDetailsSource</code> use an extended
- details object which implements the
- <code class="interfacename">GrantedAuthoritiesContainer</code> interface, thus enabling the
- authentication provider to read the authorities which were externally allocated to the user.
- We'll look at a concrete example next. </p><div class="section" title="J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource"><div class="titlepage"><div><div><h4 class="title"><a name="j2ee-preauth-details"></a>J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource</h4></div></div></div><p> If the filter is configured with an <code class="literal">authenticationDetailsSource</code>
- which is an instance of this class, the authority information is obtained by calling the
- <code class="methodname">isUserInRole(String role)</code> method for each of a pre-determined
- set of <span class="quote">“<span class="quote">mappable roles</span>”</span>. The class gets these from a configured
- <code class="interfacename">MappableAttributesRetriever</code>. Possible implementations
- include hard-coding a list in the application context and reading the role information
- from the <code class="literal"><security-role></code> information in a
- <code class="filename">web.xml</code> file. The pre-authentication sample application uses the
- latter approach. </p><p>There is an additional stage where the roles (or attributes) are mapped to Spring
- Security <code class="interfacename">GrantedAuthority</code> objects using a configured
- <code class="interfacename">Attributes2GrantedAuthoritiesMapper</code>. The default will
- just add the usual <code class="literal">ROLE_</code> prefix to the names, but it gives you full
- control over the behaviour. </p></div></div><div class="section" title="17.1.3 PreAuthenticatedAuthenticationProvider"><div class="titlepage"><div><div><h3 class="title"><a name="d0e5590"></a>17.1.3 PreAuthenticatedAuthenticationProvider</h3></div></div></div><p> The pre-authenticated provider has little more to do than load the
- <code class="interfacename">UserDetails</code> object for the user. It does this by delegating
- to a <code class="interfacename">AuthenticationUserDetailsService</code>. The latter is similar
- to the standard <code class="interfacename">UserDetailsService</code> but takes an
- <code class="interfacename">Authentication</code> object rather than just user name:
- </p><pre class="programlisting">
+ After calling these, the filter will create a
+ <code class="classname">PreAuthenticatedAuthenticationToken</code> containing the returned
+ data and submit it for authentication. By <span class="quote">“<span class="quote">authentication</span>”</span> here, we
+ really just mean further processing to perhaps load the user's authorities, but the
+ standard Spring Security authentication architecture is followed. </p><p> Like other Spring Security authentication filters, the pre-authentication filter
+ has an <code class="literal">authenticationDetailsSource</code> property which by default will
+ create a <code class="classname">WebAuthenticationDetails</code> object to store additional
+ information such as the session-identifier and originating IP address in the
+ <code class="literal">details</code> property of the
+ <code class="interfacename">Authentication</code> object. In cases where user role
+ information can be obtained from the pre-authentication mechanism, the data is also
+ stored in this property, with the details implementing the
+ <code class="interfacename">GrantedAuthoritiesContainer</code> interface. This
+ enables the authentication provider to read the authorities which were externally
+ allocated to the user. We'll look at a concrete example next. </p><div class="section" title="J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource"><div class="titlepage"><div><div><h4 class="title"><a name="j2ee-preauth-details"></a>J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource</h4></div></div></div><p> If the filter is configured with an
+ <code class="literal">authenticationDetailsSource</code> which is an instance of this
+ class, the authority information is obtained by calling the
+ <code class="methodname">isUserInRole(String role)</code> method for each of a
+ pre-determined set of <span class="quote">“<span class="quote">mappable roles</span>”</span>. The class gets these from a
+ configured <code class="interfacename">MappableAttributesRetriever</code>. Possible
+ implementations include hard-coding a list in the application context and
+ reading the role information from the <code class="literal"><security-role></code>
+ information in a <code class="filename">web.xml</code> file. The pre-authentication
+ sample application uses the latter approach.</p><p>There is an additional stage where the roles (or attributes) are mapped to
+ Spring Security <code class="interfacename">GrantedAuthority</code> objects using a
+ configured <code class="interfacename">Attributes2GrantedAuthoritiesMapper</code>.
+ The default will just add the usual <code class="literal">ROLE_</code> prefix to the
+ names, but it gives you full control over the behaviour. </p></div></div><div class="section" title="18.1.2 PreAuthenticatedAuthenticationProvider"><div class="titlepage"><div><div><h3 class="title"><a name="d0e6221"></a>18.1.2 PreAuthenticatedAuthenticationProvider</h3></div></div></div><p> The pre-authenticated provider has little more to do than load the
+ <code class="interfacename">UserDetails</code> object for the user. It does this by
+ delegating to a <code class="interfacename">AuthenticationUserDetailsService</code>. The
+ latter is similar to the standard <code class="interfacename">UserDetailsService</code>
+ but takes an <code class="interfacename">Authentication</code> object rather than just
+ user name:
+ </p><pre class="programlisting">
<span class="hl-keyword">public</span> <span class="hl-keyword">interface</span> AuthenticationUserDetailsService {
UserDetails loadUserDetails(Authentication token) <span class="hl-keyword">throws</span> UsernameNotFoundException;
}
</pre><p>
- This interface may have also other uses but with pre-authentication it allows access to the
- authorities which were packaged in the <code class="interfacename">Authentication</code> object,
- as we saw in the previous section. The
- <code class="classname">PreAuthenticatedGrantedAuthoritiesUserDetailsService</code> class does
- this. Alternatively, it may delegate to a standard
- <code class="interfacename">UserDetailsService</code> via the
- <code class="classname">UserDetailsByNameServiceWrapper</code> implementation. </p></div><div class="section" title="17.1.4 Http403ForbiddenEntryPoint"><div class="titlepage"><div><div><h3 class="title"><a name="d0e5622"></a>17.1.4 Http403ForbiddenEntryPoint</h3></div></div></div><p> The <code class="interfacename">AuthenticationEntryPoint</code> was discussed in the <a class="link" href="technical-overview.html#tech-intro-auth-entry-point" title="5.4.2 AuthenticationEntryPoint">technical overview</a> chapter. Normally it
- is responsible for kick-starting the authentication process for an unauthenticated user
- (when they try to access a protected resource), but in the pre-authenticated case this
- doesn't apply. You would only configure the
- <code class="classname">ExceptionTranslationFilter</code> with an instance of this class if you
- aren't using pre-authentication in combination with other authentication mechanisms. It will
- be called if the user is rejected by the
- <code class="classname">AbstractPreAuthenticatedProcessingFilter</code> resulting in a null
- authentication. It always returns a <code class="literal">403</code>-forbidden response code if
- called. </p></div></div><div class="section" title="17.2 Concrete Implementations"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e5642"></a>17.2 Concrete Implementations</h2></div></div></div><p> X.509 authentication is covered in its <a class="link" href="x509.html" title="22. X.509 Authentication">own chapter</a>. Here
- we'll look at some classes which provide support for other pre-authenticated scenarios. </p><div class="section" title="17.2.1 Request-Header Authentication (Siteminder)"><div class="titlepage"><div><div><h3 class="title"><a name="d0e5650"></a>17.2.1 Request-Header Authentication (Siteminder)</h3></div></div></div><p> An external authentication system may supply information to the application by setting
- specific headers on the HTTP request. A well known example of this is Siteminder, which
- passes the username in a header called <code class="literal">SM_USER</code>. This mechanism is
- supported by the class <code class="classname">RequestHeaderAuthenticationFilter</code> which simply
- extracts the username from the header. It defaults to using the name
- <code class="literal">SM_USER</code> as the header name. See the Javadoc for more details. </p><div class="tip" title="Tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>Note that when using a system like this, the framework performs no authentication
- checks at all and it is <span class="emphasis"><em>extremely</em></span> important that the external system
- is configured properly and protects all access to the application. If an attacker is able
- to forge the headers in their original request without this being detected then they could
- potentially choose any username they wished. </p></td></tr></table></div><div class="section" title="Siteminder Example Configuration"><div class="titlepage"><div><div><h4 class="title"><a name="d0e5670"></a>Siteminder Example Configuration</h4></div></div></div><p> A typical configuration using this filter would look like this: </p><pre class="programlisting">
- <security:http>
- <!-- Additional http configuration omitted -->
- <security:custom-filter position="PRE_AUTH_FILTER" ref="siteminderFilter" />
- </security:http>
+ This interface may have also other uses but with pre-authentication it allows access
+ to the authorities which were packaged in the
+ <code class="interfacename">Authentication</code> object, as we saw in the previous
+ section. The
+ <code class="classname">PreAuthenticatedGrantedAuthoritiesUserDetailsService</code> class
+ does this. Alternatively, it may delegate to a standard
+ <code class="interfacename">UserDetailsService</code> via the
+ <code class="classname">UserDetailsByNameServiceWrapper</code> implementation. </p></div><div class="section" title="18.1.3 Http403ForbiddenEntryPoint"><div class="titlepage"><div><div><h3 class="title"><a name="d0e6253"></a>18.1.3 Http403ForbiddenEntryPoint</h3></div></div></div><p> The <code class="interfacename">AuthenticationEntryPoint</code> was discussed in the
+ <a class="link" href="technical-overview.html#tech-intro-auth-entry-point" title="6.4.2 AuthenticationEntryPoint">technical overview</a> chapter.
+ Normally it is responsible for kick-starting the authentication process for an
+ unauthenticated user (when they try to access a protected resource), but in the
+ pre-authenticated case this doesn't apply. You would only configure the
+ <code class="classname">ExceptionTranslationFilter</code> with an instance of this class if
+ you aren't using pre-authentication in combination with other authentication
+ mechanisms. It will be called if the user is rejected by the
+ <code class="classname">AbstractPreAuthenticatedProcessingFilter</code> resulting in a null
+ authentication. It always returns a <code class="literal">403</code>-forbidden response code
+ if called. </p></div></div><div class="section" title="18.2 Concrete Implementations"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e6273"></a>18.2 Concrete Implementations</h2></div></div></div><p> X.509 authentication is covered in its <a class="link" href="x509.html" title="23. X.509 Authentication">own chapter</a>.
+ Here we'll look at some classes which provide support for other pre-authenticated
+ scenarios. </p><div class="section" title="18.2.1 Request-Header Authentication (Siteminder)"><div class="titlepage"><div><div><h3 class="title"><a name="d0e6281"></a>18.2.1 Request-Header Authentication (Siteminder)</h3></div></div></div><p> An external authentication system may supply information to the application by
+ setting specific headers on the HTTP request. A well known example of this is
+ Siteminder, which passes the username in a header called <code class="literal">SM_USER</code>.
+ This mechanism is supported by the class
+ <code class="classname">RequestHeaderAuthenticationFilter</code> which simply extracts the
+ username from the header. It defaults to using the name <code class="literal">SM_USER</code>
+ as the header name. See the Javadoc for more details. </p><div class="tip" title="Tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>Note that when using a system like this, the framework performs no
+ authentication checks at all and it is <span class="emphasis"><em>extremely</em></span> important
+ that the external system is configured properly and protects all access to the
+ application. If an attacker is able to forge the headers in their original
+ request without this being detected then they could potentially choose any
+ username they wished. </p></td></tr></table></div><div class="section" title="Siteminder Example Configuration"><div class="titlepage"><div><div><h4 class="title"><a name="d0e6301"></a>Siteminder Example Configuration</h4></div></div></div><p> A typical configuration using this filter would look like this: </p><pre class="programlisting">
+ <span class="hl-tag"><security:http></span>
+ <span class="hl-comment"><!-- Additional http configuration omitted --></span>
+ <span class="hl-tag"><security:custom-filter</span> <span class="hl-attribute">position</span>=<span class="hl-value">"PRE_AUTH_FILTER"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"siteminderFilter"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"></security:http></span>
- <bean id="siteminderFilter" class=
-"org.springframework.security.web.authentication.preauth.header.RequestHeaderAuthenticationFilter">
- <property name="principalRequestHeader" value="SM_USER"/>
- <property name="authenticationManager" ref="authenticationManager" />
- </bean>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"siteminderFilter"</span> <span class="hl-attribute">class</span>=
+<span class="hl-value">"org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"principalRequestHeader"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"SM_USER"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"authenticationManager"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"></bean></span>
- <bean id="preauthAuthProvider"
-class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
- <property name="preAuthenticatedUserDetailsService">
- <bean id="userDetailsServiceWrapper"
- class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
- <property name="userDetailsService" ref="userDetailsService"/>
- </bean>
- </property>
- </bean>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"preauthAuthProvider"</span>
+<span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"preAuthenticatedUserDetailsService"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"userDetailsServiceWrapper"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"userDetailsService"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"userDetailsService"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></bean></span>
+ <span class="hl-tag"></property></span>
+ <span class="hl-tag"></bean></span>
- <security:authentication-manager alias="authenticationManager">
- <security:authentication-provider ref="preauthAuthProvider" />
- </security-authentication-manager>
+ <span class="hl-tag"><security:authentication-manager</span> <span class="hl-attribute">alias</span>=<span class="hl-value">"authenticationManager"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><security:authentication-provider</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"preauthAuthProvider"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"></security:authentication-manager></span>
-</pre><p> We've assumed here that the security namespace is being used for
- configuration (hence the user of the <code class="literal">custom-filter</code>,
- <code class="literal">authentication-manager</code> and
- <code class="literal">custom-authentication-provider</code> elements (you can read more about them
- in the <a class="link" href="ns-config.html" title="2. Security Namespace Configuration">namespace chapter</a>). You would leave these out
- of a traditional bean configuration. It's also assumed that you have added a
- <code class="interfacename">UserDetailsService</code> (called
- <span class="quote">“<span class="quote">userDetailsService</span>”</span>) to your configuration to load the user's roles.
- </p></div></div><div class="section" title="17.2.2 J2EE Container Authentication"><div class="titlepage"><div><div><h3 class="title"><a name="d0e5696"></a>17.2.2 J2EE Container Authentication</h3></div></div></div><p> The class <code class="classname">J2eePreAuthenticatedProcessingFilter</code> will extract the
- username from the <code class="literal">userPrincipal</code> property of the
- <code class="interfacename">HttpServletRequest</code>. Use of this filter would usually be
- combined with the use of J2EE roles as described above in <a class="xref" href="preauth.html#j2ee-preauth-details" title="J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource">the section called “J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource”</a>. </p><p> There is a sample application in the codebase which uses this approach, so get hold of
- the code from subversion and have a look at the application context file if you are
- interested. The code is in the <code class="filename">samples/preauth</code> directory. </p></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
+</pre><p> We've assumed here that the security namespace is being used for configuration
+ (hence the user of the <code class="literal">custom-filter</code>,
+ <code class="literal">authentication-manager</code> and
+ <code class="literal">custom-authentication-provider</code> elements (you can read more
+ about them in the <a class="link" href="ns-config.html" title="3. Security Namespace Configuration">namespace chapter</a>). You
+ would leave these out of a traditional bean configuration. It's also assumed
+ that you have added a <code class="interfacename">UserDetailsService</code> (called
+ <span class="quote">“<span class="quote">userDetailsService</span>”</span>) to your configuration to load the user's
+ roles. </p></div></div><div class="section" title="18.2.2 J2EE Container Authentication"><div class="titlepage"><div><div><h3 class="title"><a name="d0e6327"></a>18.2.2 J2EE Container Authentication</h3></div></div></div><p> The class <code class="classname">J2eePreAuthenticatedProcessingFilter</code> will
+ extract the username from the <code class="literal">userPrincipal</code> property of the
+ <code class="interfacename">HttpServletRequest</code>. Use of this filter would usually
+ be combined with the use of J2EE roles as described above in <a class="xref" href="preauth.html#j2ee-preauth-details" title="J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource">the section called “J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource”</a>. </p><p> There is a sample application in the codebase which uses this approach, so get
+ hold of the code from subversion and have a look at the application context file if
+ you are interested. The code is in the <code class="filename">samples/preauth</code>
+ directory. </p></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
- </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="domain-acls.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="advanced-topics.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="ldap.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">16. Domain Object Security (ACLs) </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 18. LDAP Authentication</td></tr></table></div></body></html>
\ No newline at end of file
+ </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="domain-acls.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="advanced-topics.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="ldap.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">17. Domain Object Security (ACLs) </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 19. LDAP Authentication</td></tr></table></div></body></html>
\ No newline at end of file
diff --git a/docs/reference/preface.html b/docs/reference/preface.html
index 9e1460b..bdad90e 100644
--- a/docs/reference/preface.html
+++ b/docs/reference/preface.html
@@ -9,47 +9,52 @@
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
</script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Preface</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="springsecurity.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="getting-started.html">Next</a></td></tr></table><hr></div><div class="preface" title="Preface"><div class="titlepage"><div><div><h2 class="title"><a name="preface"></a>Preface</h2></div></div></div><p>Spring Security provides a comprehensive security solution for J2EE-based enterprise
- software applications. As you will discover as you venture through this reference guide, we
- have tried to provide you a useful and highly configurable security system.</p><p>Security is an ever-moving target, and it's important to pursue a comprehensive,
- system-wide approach. In security circles we encourage you to adopt "layers of security", so
- that each layer tries to be as secure as possible in its own right, with successive layers
- providing additional security. The "tighter" the security of each layer, the more robust and
- safe your application will be. At the bottom level you'll need to deal with issues such as
- transport security and system identification, in order to mitigate man-in-the-middle attacks.
- Next you'll generally utilise firewalls, perhaps with VPNs or IP security to ensure only
- authorised systems can attempt to connect. In corporate environments you may deploy a DMZ to
- separate public-facing servers from backend database and application servers. Your operating
- system will also play a critical part, addressing issues such as running processes as
- non-privileged users and maximising file system security. An operating system will usually
- also be configured with its own firewall. Hopefully somewhere along the way you'll be trying
- to prevent denial of service and brute force attacks against the system. An intrusion
- detection system will also be especially useful for monitoring and responding to attacks, with
- such systems able to take protective action such as blocking offending TCP/IP addresses in
- real-time. Moving to the higher layers, your Java Virtual Machine will hopefully be configured
- to minimize the permissions granted to different Java types, and then your application will
- add its own problem domain-specific security configuration. Spring Security makes this latter
- area - application security - much easier. </p><p>Of course, you will need to properly address all security layers mentioned above, together
- with managerial factors that encompass every layer. A non-exhaustive list of such managerial
- factors would include security bulletin monitoring, patching, personnel vetting, audits,
- change control, engineering management systems, data backup, disaster recovery, performance
- benchmarking, load monitoring, centralised logging, incident response procedures etc.</p><p>With Spring Security being focused on helping you with the enterprise application security
- layer, you will find that there are as many different requirements as there are business
- problem domains. A banking application has different needs from an ecommerce application. An
- ecommerce application has different needs from a corporate sales force automation tool. These
- custom requirements make application security interesting, challenging and rewarding. </p><p>Please read <a class="xref" href="getting-started.html" title="Part I. Getting Started">Part I, “Getting Started”</a>, in its entirety to begin with. This will
- introduce you to the framework and the namespace-based configuration system with which you can
- get up and running quite quickly. To get more of an understanding of how Spring Security
- works, and some of the classes you might need to use, you should then read <a class="xref" href="overall-architecture.html" title="Part II. Architecture and Implementation">Part II, “Architecture and Implementation”</a>. The remaining parts of this guide are structured in a more
- traditional reference style, designed to be read on an as-required basis. We'd also recommend
- that you read up as much as possible on application security issues in general. Spring
- Security is not a panacea which will solve all security issues. It is important that the
- application is designed with security in mind from the start. Attempting to retrofit it is not
- a good idea. In particular, if you are building a web application, you should be aware of the
- many potential vulnerabilities such as cross-site scripting, request-forgery and
- session-hijacking which you should be taking into account from the start. The OWASP web site
- (http://www.owasp.org/) maintains a top ten list of web application vulnerabilities as well as
- a lot of useful reference information. </p><p>We hope that you find this reference guide useful, and we welcome your feedback and <a class="link" href="community.html#jira" title="4.1 Issue Tracking">suggestions</a>. </p><p>Finally, welcome to the Spring Security <a class="link" href="community.html" title="4. Spring Security Community">community</a>.
- </p></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
+ software applications. As you will discover as you venture through this reference guide,
+ we have tried to provide you a useful and highly configurable security system.</p><p>Security is an ever-moving target, and it's important to pursue a comprehensive,
+ system-wide approach. In security circles we encourage you to adopt "layers of
+ security", so that each layer tries to be as secure as possible in its own right, with
+ successive layers providing additional security. The "tighter" the security of each
+ layer, the more robust and safe your application will be. At the bottom level you'll
+ need to deal with issues such as transport security and system identification, in order
+ to mitigate man-in-the-middle attacks. Next you'll generally utilise firewalls, perhaps
+ with VPNs or IP security to ensure only authorised systems can attempt to connect. In
+ corporate environments you may deploy a DMZ to separate public-facing servers from
+ backend database and application servers. Your operating system will also play a
+ critical part, addressing issues such as running processes as non-privileged users and
+ maximising file system security. An operating system will usually also be configured
+ with its own firewall. Hopefully somewhere along the way you'll be trying to prevent
+ denial of service and brute force attacks against the system. An intrusion detection
+ system will also be especially useful for monitoring and responding to attacks, with
+ such systems able to take protective action such as blocking offending TCP/IP addresses
+ in real-time. Moving to the higher layers, your Java Virtual Machine will hopefully be
+ configured to minimize the permissions granted to different Java types, and then your
+ application will add its own problem domain-specific security configuration. Spring
+ Security makes this latter area - application security - much easier. </p><p>Of course, you will need to properly address all security layers mentioned above,
+ together with managerial factors that encompass every layer. A non-exhaustive list of
+ such managerial factors would include security bulletin monitoring, patching, personnel
+ vetting, audits, change control, engineering management systems, data backup, disaster
+ recovery, performance benchmarking, load monitoring, centralised logging, incident
+ response procedures etc.</p><p>With Spring Security being focused on helping you with the enterprise application
+ security layer, you will find that there are as many different requirements as there are
+ business problem domains. A banking application has different needs from an ecommerce
+ application. An ecommerce application has different needs from a corporate sales force
+ automation tool. These custom requirements make application security interesting,
+ challenging and rewarding. </p><p>Please read <a class="xref" href="getting-started.html" title="Part I. Getting Started">Part I, “Getting Started”</a>, in its entirety to begin with. This
+ will introduce you to the framework and the namespace-based configuration system with
+ which you can get up and running quite quickly. To get more of an understanding of how
+ Spring Security works, and some of the classes you might need to use, you should then
+ read <a class="xref" href="overall-architecture.html" title="Part II. Architecture and Implementation">Part II, “Architecture and Implementation”</a>. The remaining parts of this guide are
+ structured in a more traditional reference style, designed to be read on an as-required
+ basis. We'd also recommend that you read up as much as possible on application security
+ issues in general. Spring Security is not a panacea which will solve all security
+ issues. It is important that the application is designed with security in mind from the
+ start. Attempting to retrofit it is not a good idea. In particular, if you are building
+ a web application, you should be aware of the many potential vulnerabilities such as
+ cross-site scripting, request-forgery and session-hijacking which you should be taking
+ into account from the start. The OWASP web site (http://www.owasp.org/) maintains a top
+ ten list of web application vulnerabilities as well as a lot of useful reference
+ information. </p><p>We hope that you find this reference guide useful, and we welcome your feedback and
+ <a class="link" href="community.html#jira" title="5.1 Issue Tracking">suggestions</a>. </p><p>Finally, welcome to the Spring Security <a class="link" href="community.html" title="5. Spring Security Community">community</a>. </p></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
</script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="springsecurity.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="getting-started.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Spring Security </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> Part I. Getting Started</td></tr></table></div></body></html>
\ No newline at end of file
diff --git a/docs/reference/remember-me.html b/docs/reference/remember-me.html
index 673aa74..7982f38 100644
--- a/docs/reference/remember-me.html
+++ b/docs/reference/remember-me.html
@@ -1,6 +1,6 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>10. Remember-Me Authentication</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="web-app-security.html" title="Part III. Web Application Security"><link rel="prev" href="basic.html" title="9. Basic and Digest Authentication"><link rel="next" href="session-mgmt.html" title="11. Session Management"><!--Begin Google Analytics code--><script type="text/javascript">
+ <title>11. Remember-Me Authentication</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="web-app-security.html" title="Part III. Web Application Security"><link rel="prev" href="basic.html" title="10. Basic and Digest Authentication"><link rel="next" href="session-mgmt.html" title="12. Session Management"><!--Begin Google Analytics code--><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
@@ -8,19 +8,18 @@
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
- </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">10. Remember-Me Authentication</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="basic.html">Prev</a> </td><th width="60%" align="center">Part III. Web Application Security</th><td width="20%" align="right"> <a accesskey="n" href="session-mgmt.html">Next</a></td></tr></table><hr></div><div class="chapter" title="10. Remember-Me Authentication"><div class="titlepage"><div><div><h1 class="title"><a name="remember-me"></a>Remember-Me Authentication</h1></div></div></div><div class="section" title="10.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="remember-me-overview"></a>10.1 Overview</h2></div></div></div><p>Remember-me or persistent-login authentication refers to web sites being able to
+ </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">11. Remember-Me Authentication</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="basic.html">Prev</a> </td><th width="60%" align="center">Part III. Web Application Security</th><td width="20%" align="right"> <a accesskey="n" href="session-mgmt.html">Next</a></td></tr></table><hr></div><div class="chapter" title="11. Remember-Me Authentication"><div class="titlepage"><div><div><h1 class="title"><a name="remember-me"></a>Remember-Me Authentication</h1></div></div></div><div class="section" title="11.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="remember-me-overview"></a>11.1 Overview</h2></div></div></div><p>Remember-me or persistent-login authentication refers to web sites being able to
remember the identity of a principal between sessions. This is typically accomplished by
sending a cookie to the browser, with the cookie being detected during future sessions
and causing automated login to take place. Spring Security provides the necessary hooks
for these operations to take place, and has two concrete remember-me implementations.
One uses hashing to preserve the security of cookie-based tokens and the other uses a
database or other persistent storage mechanism to store the generated tokens. </p><p> Note that both implemementations require a
- <code class="interfacename">UserDetailsService</code>. If you are using an
- authentication provider which doesn't use a
- <code class="interfacename">UserDetailsService</code> (for example, the LDAP provider)
- then it won't work unless you also have a
- <code class="interfacename">UserDetailsService</code> bean in your application context.
- </p></div><div class="section" title="10.2 Simple Hash-Based Token Approach"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="remember-me-hash-token"></a>10.2 Simple Hash-Based Token Approach</h2></div></div></div><p>This approach uses hashing to achieve a useful remember-me strategy. In essence a
+ <code class="interfacename">UserDetailsService</code>. If you are using an authentication
+ provider which doesn't use a <code class="interfacename">UserDetailsService</code> (for
+ example, the LDAP provider) then it won't work unless you also have a
+ <code class="interfacename">UserDetailsService</code> bean in your application context.
+ </p></div><div class="section" title="11.2 Simple Hash-Based Token Approach"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="remember-me-hash-token"></a>11.2 Simple Hash-Based Token Approach</h2></div></div></div><p>This approach uses hashing to achieve a useful remember-me strategy. In essence a
cookie is sent to the browser upon successful interactive authentication, with the
cookie being composed as follows:
</p><pre class="programlisting">
@@ -39,37 +38,39 @@
authentication. If a principal is aware a token has been captured, they can easily
change their password and immediately invalidate all remember-me tokens on issue. If
more significant security is needed you should use the approach described in the next
- section. Alternatively remember-me services should simply not be used at all.</p><p>If you are familiar with the topics discussed in the chapter on <a class="link" href="ns-config.html" title="2. Security Namespace Configuration">namespace configuration</a>, you can enable remember-me
+ section. Alternatively remember-me services should simply not be used at all.</p><p>If you are familiar with the topics discussed in the chapter on <a class="link" href="ns-config.html" title="3. Security Namespace Configuration">namespace configuration</a>, you can enable remember-me
authentication just by adding the <code class="literal"><remember-me></code> element: </p><pre class="programlisting">
- <http>
+ <span class="hl-tag"><http></span>
...
- <remember-me key="myAppKey"/>
- </http>
+ <span class="hl-tag"><remember-me</span> <span class="hl-attribute">key</span>=<span class="hl-value">"myAppKey"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></http></span>
</pre><p> The <code class="interfacename">UserDetailsService</code> will
normally be selected automatically. If you have more than one in your application
context, you need to specify which one should be used with the
- <code class="literal">user-service-ref</code> attribute, where the value is the name of your
- <code class="interfacename">UserDetailsService</code> bean. </p></div><div class="section" title="10.3 Persistent Token Approach"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="remember-me-persistent-token"></a>10.3 Persistent Token Approach</h2></div></div></div><p>This approach is based on the article <a class="link" href="http://jaspan.com/improved_persistent_login_cookie_best_practice" target="_top">http://jaspan.com/improved_persistent_login_cookie_best_practice</a> with some
- minor modifications <sup>[<a name="d0e3651" href="#ftn.d0e3651" class="footnote">12</a>]</sup>.
- To use the this approach with namespace configuration, you would supply a datasource
- reference: </p><pre class="programlisting">
- <http>
+ <code class="literal">user-service-ref</code> attribute, where the value is the name of your
+ <code class="interfacename">UserDetailsService</code> bean. </p></div><div class="section" title="11.3 Persistent Token Approach"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="remember-me-persistent-token"></a>11.3 Persistent Token Approach</h2></div></div></div><p>This approach is based on the article <a class="link" href="http://jaspan.com/improved_persistent_login_cookie_best_practice" target="_top">http://jaspan.com/improved_persistent_login_cookie_best_practice</a> with some minor
+ modifications <sup>[<a name="d0e4213" href="#ftn.d0e4213" class="footnote">19</a>]</sup>. To use the this approach with namespace configuration, you would supply a
+ datasource reference: </p><pre class="programlisting">
+ <span class="hl-tag"><http></span>
...
- <remember-me data-source-ref="someDataSource"/>
- </http>
+ <span class="hl-tag"><remember-me</span> <span class="hl-attribute">data-source-ref</span>=<span class="hl-value">"someDataSource"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></http></span>
</pre><p> The database should contain a
- <code class="literal">persistent_logins</code> table, created using the following SQL (or
+ <code class="literal">persistent_logins</code> table, created using the following SQL (or
equivalent):
</p><pre class="programlisting">
- create table persistent_logins (username varchar(64) not null, series varchar(64) primary key, token varchar(64) not null, last_used timestamp not null)
-</pre></div><div class="section" title="10.4 Remember-Me Interfaces and Implementations"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="remember-me-impls"></a>10.4 Remember-Me Interfaces and Implementations</h2></div></div></div><p>Remember-me authentication is not used with basic authentication, given it is often
+ create table persistent_logins (username varchar(64) not null,
+ series varchar(64) primary key,
+ token varchar(64) not null,
+ last_used timestamp not null)
+</pre></div><div class="section" title="11.4 Remember-Me Interfaces and Implementations"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="remember-me-impls"></a>11.4 Remember-Me Interfaces and Implementations</h2></div></div></div><p>Remember-me authentication is not used with basic authentication, given it is often
not used with <code class="literal">HttpSession</code>s. Remember-me is used with
- <code class="literal">UsernamePasswordAuthenticationFilter</code>, and is implemented via
- hooks in the <code class="literal">AbstractAuthenticationProcessingFilter</code> superclass. The
- hooks will invoke a concrete <code class="interfacename">RememberMeServices</code> at the
- appropriate times. The interface looks like this:
+ <code class="literal">UsernamePasswordAuthenticationFilter</code>, and is implemented via hooks in
+ the <code class="literal">AbstractAuthenticationProcessingFilter</code> superclass. The hooks will
+ invoke a concrete <code class="interfacename">RememberMeServices</code> at the appropriate
+ times. The interface looks like this:
</p><pre class="programlisting">
Authentication autoLogin(HttpServletRequest request, HttpServletResponse response);
<span class="hl-keyword">void</span> loginFail(HttpServletRequest request, HttpServletResponse response);
@@ -80,25 +81,25 @@
note at this stage that <code class="literal">AbstractAuthenticationProcessingFilter</code> only
calls the <code class="literal">loginFail()</code> and <code class="literal">loginSuccess()</code> methods.
The <code class="literal">autoLogin()</code> method is called by
- <code class="classname">RememberMeAuthenticationFilter</code> whenever the
- <code class="classname">SecurityContextHolder</code> does not contain an
- <code class="interfacename">Authentication</code>. This interface therefore provides the
+ <code class="classname">RememberMeAuthenticationFilter</code> whenever the
+ <code class="classname">SecurityContextHolder</code> does not contain an
+ <code class="interfacename">Authentication</code>. This interface therefore provides the
underlying remember-me implementation with sufficient notification of
authentication-related events, and delegates to the implementation whenever a candidate
web request might contain a cookie and wish to be remembered. This design allows any
number of remember-me implementation strategies. We've seen above that Spring Security
- provides two implementations. We'll look at these in turn.</p><div class="section" title="10.4.1 TokenBasedRememberMeServices"><div class="titlepage"><div><div><h3 class="title"><a name="d0e3706"></a>10.4.1 TokenBasedRememberMeServices</h3></div></div></div><p> This implementation supports the simpler approach described in <a class="xref" href="remember-me.html#remember-me-hash-token" title="10.2 Simple Hash-Based Token Approach">Section 10.2, “Simple Hash-Based Token Approach”</a>.
- <code class="classname">TokenBasedRememberMeServices</code> generates a
- <code class="literal">RememberMeAuthenticationToken</code>, which is processed by
- <code class="literal">RememberMeAuthenticationProvider</code>. A <code class="literal">key</code> is
+ provides two implementations. We'll look at these in turn.</p><div class="section" title="11.4.1 TokenBasedRememberMeServices"><div class="titlepage"><div><div><h3 class="title"><a name="d0e4268"></a>11.4.1 TokenBasedRememberMeServices</h3></div></div></div><p> This implementation supports the simpler approach described in <a class="xref" href="remember-me.html#remember-me-hash-token" title="11.2 Simple Hash-Based Token Approach">Section 11.2, “Simple Hash-Based Token Approach”</a>.
+ <code class="classname">TokenBasedRememberMeServices</code> generates a
+ <code class="literal">RememberMeAuthenticationToken</code>, which is processed by
+ <code class="literal">RememberMeAuthenticationProvider</code>. A <code class="literal">key</code> is
shared between this authentication provider and the
- <code class="literal">TokenBasedRememberMeServices</code>. In addition,
- <code class="literal">TokenBasedRememberMeServices</code> requires A UserDetailsService
- from which it can retrieve the username and password for signature comparison
- purposes, and generate the <code class="literal">RememberMeAuthenticationToken</code> to
- contain the correct <code class="interfacename">GrantedAuthority</code>[]s. Some sort of
- logout command should be provided by the application that invalidates the cookie if
- the user requests this. <code class="classname">TokenBasedRememberMeServices</code> also
+ <code class="literal">TokenBasedRememberMeServices</code>. In addition,
+ <code class="literal">TokenBasedRememberMeServices</code> requires A UserDetailsService from
+ which it can retrieve the username and password for signature comparison purposes,
+ and generate the <code class="literal">RememberMeAuthenticationToken</code> to contain the
+ correct <code class="interfacename">GrantedAuthority</code>s. Some sort of logout
+ command should be provided by the application that invalidates the cookie if the
+ user requests this. <code class="classname">TokenBasedRememberMeServices</code> also
implements Spring Security's <code class="interfacename">LogoutHandler</code> interface
so can be used with <code class="classname">LogoutFilter</code> to have the cookie cleared
automatically. </p><p>The beans required in an application context to enable remember-me services are as
@@ -121,23 +122,20 @@
<span class="hl-tag"></bean></span>
</pre><p>Don't forget to add your
- <code class="interfacename">RememberMeServices</code> implementation to your
- <code class="literal">UsernamePasswordAuthenticationFilter.setRememberMeServices()</code>
+ <code class="interfacename">RememberMeServices</code> implementation to your
+ <code class="literal">UsernamePasswordAuthenticationFilter.setRememberMeServices()</code>
property, include the <code class="literal">RememberMeAuthenticationProvider</code> in your
- <code class="literal">AuthenticationManager.setProviders()</code> list, and add
- <code class="classname">RememberMeAuthenticationFilter</code> into your
- <code class="classname">FilterChainProxy</code> (typically immediately after your
- <code class="literal">UsernamePasswordAuthenticationFilter</code>).</p></div><div class="section" title="10.4.2 PersistentTokenBasedRememberMeServices"><div class="titlepage"><div><div><h3 class="title"><a name="d0e3772"></a>10.4.2 PersistentTokenBasedRememberMeServices</h3></div></div></div><p> This class can be used in the same way as
- <code class="classname">TokenBasedRememberMeServices</code>, but it additionally needs
- to be configured with a <code class="interfacename">PersistentTokenRepository</code> to
- store the tokens. There are two standard implementations.
- </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p><code class="classname">InMemoryTokenRepositoryImpl</code>
- which is intended for testing
- only.</p></li><li class="listitem"><p><code class="classname">JdbcTokenRepositoryImpl</code>
- which stores the tokens in a database. </p></li></ul></div><p>
- The database schema is described above in <a class="xref" href="remember-me.html#remember-me-persistent-token" title="10.3 Persistent Token Approach">Section 10.3, “Persistent Token Approach”</a>. </p></div></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e3651" href="#d0e3651" class="para">12</a>] </sup>Essentially, the username is not included in the
- cookie, to prevent exposing a valid login name unecessarily. There is a
- discussion on this in the comments section of this article.</p></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
+ <code class="literal">AuthenticationManager.setProviders()</code> list, and add
+ <code class="classname">RememberMeAuthenticationFilter</code> into your
+ <code class="classname">FilterChainProxy</code> (typically immediately after your
+ <code class="literal">UsernamePasswordAuthenticationFilter</code>).</p></div><div class="section" title="11.4.2 PersistentTokenBasedRememberMeServices"><div class="titlepage"><div><div><h3 class="title"><a name="d0e4334"></a>11.4.2 PersistentTokenBasedRememberMeServices</h3></div></div></div><p> This class can be used in the same way as
+ <code class="classname">TokenBasedRememberMeServices</code>, but it additionally needs to be
+ configured with a <code class="interfacename">PersistentTokenRepository</code> to store
+ the tokens. There are two standard implementations. </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p><code class="classname">InMemoryTokenRepositoryImpl</code> which is intended for
+ testing only.</p></li><li class="listitem"><p><code class="classname">JdbcTokenRepositoryImpl</code> which stores the tokens in
+ a database. </p></li></ul></div><p> The database schema is described above in <a class="xref" href="remember-me.html#remember-me-persistent-token" title="11.3 Persistent Token Approach">Section 11.3, “Persistent Token Approach”</a>. </p></div></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e4213" href="#d0e4213" class="para">19</a>] </sup>Essentially, the username is not included in the cookie, to prevent exposing a
+ valid login name unecessarily. There is a discussion on this in the comments section
+ of this article.</p></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
- </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="basic.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="web-app-security.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="session-mgmt.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">9. Basic and Digest Authentication </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 11. Session Management</td></tr></table></div></body></html>
\ No newline at end of file
+ </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="basic.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="web-app-security.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="session-mgmt.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">10. Basic and Digest Authentication </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 12. Session Management</td></tr></table></div></body></html>
\ No newline at end of file
diff --git a/docs/reference/runas.html b/docs/reference/runas.html
index 9eaccfc..168abe5 100644
--- a/docs/reference/runas.html
+++ b/docs/reference/runas.html
@@ -1,6 +1,6 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>23. Run-As Authentication Replacement</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="advanced-topics.html" title="Part V. Additional Topics"><link rel="prev" href="x509.html" title="22. X.509 Authentication"><link rel="next" href="appendix-schema.html" title="Appendix A. Security Database Schema"><!--Begin Google Analytics code--><script type="text/javascript">
+ <title>24. Run-As Authentication Replacement</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="advanced-topics.html" title="Part V. Additional Topics"><link rel="prev" href="x509.html" title="23. X.509 Authentication"><link rel="next" href="crypto.html" title="25. Spring Security Crypto Module"><!--Begin Google Analytics code--><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
@@ -8,88 +8,73 @@
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
- </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">23. Run-As Authentication Replacement</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="x509.html">Prev</a> </td><th width="60%" align="center">Part V. Additional Topics</th><td width="20%" align="right"> <a accesskey="n" href="appendix-schema.html">Next</a></td></tr></table><hr></div><div class="chapter" title="23. Run-As Authentication Replacement"><div class="titlepage"><div><div><h1 class="title"><a name="runas"></a>Run-As Authentication Replacement</h1></div></div></div><div class="section" title="23.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="runas-overview"></a>23.1 Overview</h2></div></div></div><p>The <code class="classname">AbstractSecurityInterceptor</code> is able to
- temporarily replace the <code class="interfacename">Authentication</code> object in
- the <code class="interfacename">SecurityContext</code> and
- <code class="classname">SecurityContextHolder</code> during the secure object
- callback phase. This only occurs if the original
- <code class="interfacename">Authentication</code> object was successfully processed by
- the <code class="interfacename">AuthenticationManager</code> and
- <code class="interfacename">AccessDecisionManager</code>. The
+ </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">24. Run-As Authentication Replacement</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="x509.html">Prev</a> </td><th width="60%" align="center">Part V. Additional Topics</th><td width="20%" align="right"> <a accesskey="n" href="crypto.html">Next</a></td></tr></table><hr></div><div class="chapter" title="24. Run-As Authentication Replacement"><div class="titlepage"><div><div><h1 class="title"><a name="runas"></a>Run-As Authentication Replacement</h1></div></div></div><div class="section" title="24.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="runas-overview"></a>24.1 Overview</h2></div></div></div><p>The <code class="classname">AbstractSecurityInterceptor</code> is able to temporarily replace
+ the <code class="interfacename">Authentication</code> object in the
+ <code class="interfacename">SecurityContext</code> and
+ <code class="classname">SecurityContextHolder</code> during the secure object callback phase.
+ This only occurs if the original <code class="interfacename">Authentication</code> object
+ was successfully processed by the <code class="interfacename">AuthenticationManager</code>
+ and <code class="interfacename">AccessDecisionManager</code>. The
<code class="literal">RunAsManager</code> will indicate the replacement
- <code class="interfacename">Authentication</code> object, if any, that should be used
- during the <code class="literal">SecurityInterceptorCallback</code>.</p><p>By temporarily replacing the <code class="interfacename">Authentication</code>
- object during the secure object callback phase, the secured invocation
- will be able to call other objects which require different
- authentication and authorization credentials. It will also be able to
- perform any internal security checks for specific
+ <code class="interfacename">Authentication</code> object, if any, that should be used during
+ the <code class="literal">SecurityInterceptorCallback</code>.</p><p>By temporarily replacing the <code class="interfacename">Authentication</code> object
+ during the secure object callback phase, the secured invocation will be able to call
+ other objects which require different authentication and authorization credentials. It
+ will also be able to perform any internal security checks for specific
<code class="interfacename">GrantedAuthority</code> objects. Because Spring Security
- provides a number of helper classes that automatically configure
- remoting protocols based on the contents of the
- <code class="classname">SecurityContextHolder</code>, these run-as replacements
- are particularly useful when calling remote web services</p></div><div class="section" title="23.2 Configuration"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="runas-config"></a>23.2 Configuration</h2></div></div></div><p>A <code class="literal">RunAsManager</code> interface is provided by Spring Security:
+ provides a number of helper classes that automatically configure remoting protocols
+ based on the contents of the <code class="classname">SecurityContextHolder</code>, these run-as
+ replacements are particularly useful when calling remote web services</p></div><div class="section" title="24.2 Configuration"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="runas-config"></a>24.2 Configuration</h2></div></div></div><p>A <code class="literal">RunAsManager</code> interface is provided by Spring Security:
</p><pre class="programlisting">
Authentication buildRunAs(Authentication authentication, Object object,
List<ConfigAttribute> config);
- boolean supports(ConfigAttribute attribute);
- boolean supports(Class clazz);
- </pre><p>
- </p><p>The first method returns the <code class="interfacename">Authentication</code>
- object that should replace the existing
- <code class="interfacename">Authentication</code> object for the duration of the
- method invocation. If the method returns <code class="literal">null</code>, it
- indicates no replacement should be made. The second method is used by
- the <code class="classname">AbstractSecurityInterceptor</code> as part of its
- startup validation of configuration attributes. The
- <code class="literal">supports(Class)</code> method is called by a security
- interceptor implementation to ensure the configured
- <code class="literal">RunAsManager</code> supports the type of secure object
- that the security interceptor will present.</p><p>One concrete implementation of a <code class="literal">RunAsManager</code>
- is provided with Spring Security. The
- <code class="literal">RunAsManagerImpl</code> class returns a replacement
- <code class="literal">RunAsUserToken</code> if any
- <code class="literal">ConfigAttribute</code> starts with
- <code class="literal">RUN_AS_</code>. If any such
- <code class="literal">ConfigAttribute</code> is found, the replacement
- <code class="literal">RunAsUserToken</code> will contain the same principal,
+ <span class="hl-keyword">boolean</span> supports(ConfigAttribute attribute);
+ <span class="hl-keyword">boolean</span> supports(Class clazz);
+ </pre><p> </p><p>The first method returns the <code class="interfacename">Authentication</code> object that
+ should replace the existing <code class="interfacename">Authentication</code> object for the
+ duration of the method invocation. If the method returns <code class="literal">null</code>, it
+ indicates no replacement should be made. The second method is used by the
+ <code class="classname">AbstractSecurityInterceptor</code> as part of its startup validation of
+ configuration attributes. The <code class="literal">supports(Class)</code> method is called by a
+ security interceptor implementation to ensure the configured
+ <code class="literal">RunAsManager</code> supports the type of secure object that the security
+ interceptor will present.</p><p>One concrete implementation of a <code class="literal">RunAsManager</code> is provided with
+ Spring Security. The <code class="literal">RunAsManagerImpl</code> class returns a replacement
+ <code class="literal">RunAsUserToken</code> if any <code class="literal">ConfigAttribute</code> starts with
+ <code class="literal">RUN_AS_</code>. If any such <code class="literal">ConfigAttribute</code> is found, the
+ replacement <code class="literal">RunAsUserToken</code> will contain the same principal,
credentials and granted authorities as the original
<code class="interfacename">Authentication</code> object, along with a new
- <code class="literal">GrantedAuthorityImpl</code> for each
- <code class="literal">RUN_AS_</code> <code class="literal">ConfigAttribute</code>. Each
- new <code class="literal">GrantedAuthorityImpl</code> will be prefixed with
- <code class="literal">ROLE_</code>, followed by the <code class="literal">RUN_AS</code>
- <code class="literal">ConfigAttribute</code>. For example, a
+ <code class="literal">GrantedAuthorityImpl</code> for each <code class="literal">RUN_AS_</code>
+ <code class="literal">ConfigAttribute</code>. Each new <code class="literal">GrantedAuthorityImpl</code>
+ will be prefixed with <code class="literal">ROLE_</code>, followed by the
+ <code class="literal">RUN_AS</code> <code class="literal">ConfigAttribute</code>. For example, a
<code class="literal">RUN_AS_SERVER</code> will result in the replacement
- <code class="literal">RunAsUserToken</code> containing a
- <code class="literal">ROLE_RUN_AS_SERVER</code> granted authority.</p><p>The replacement <code class="literal">RunAsUserToken</code> is just like
- any other <code class="interfacename">Authentication</code> object. It needs to be
- authenticated by the <code class="interfacename">AuthenticationManager</code>,
- probably via delegation to a suitable
- <code class="classname">AuthenticationProvider</code>. The
- <code class="literal">RunAsImplAuthenticationProvider</code> performs such
- authentication. It simply accepts as valid any
- <code class="literal">RunAsUserToken</code> presented.</p><p>To ensure malicious code does not create a
- <code class="literal">RunAsUserToken</code> and present it for guaranteed
- acceptance by the <code class="literal">RunAsImplAuthenticationProvider</code>,
- the hash of a key is stored in all generated tokens. The
- <code class="literal">RunAsManagerImpl</code> and
- <code class="literal">RunAsImplAuthenticationProvider</code> is created in the
- bean context with the same key:
- </p><pre class="programlisting">
+ <code class="literal">RunAsUserToken</code> containing a <code class="literal">ROLE_RUN_AS_SERVER</code>
+ granted authority.</p><p>The replacement <code class="literal">RunAsUserToken</code> is just like any other
+ <code class="interfacename">Authentication</code> object. It needs to be authenticated by
+ the <code class="interfacename">AuthenticationManager</code>, probably via delegation to a
+ suitable <code class="classname">AuthenticationProvider</code>. The
+ <code class="literal">RunAsImplAuthenticationProvider</code> performs such authentication. It
+ simply accepts as valid any <code class="literal">RunAsUserToken</code> presented.</p><p>To ensure malicious code does not create a <code class="literal">RunAsUserToken</code> and
+ present it for guaranteed acceptance by the
+ <code class="literal">RunAsImplAuthenticationProvider</code>, the hash of a key is stored in all
+ generated tokens. The <code class="literal">RunAsManagerImpl</code> and
+ <code class="literal">RunAsImplAuthenticationProvider</code> is created in the bean context with
+ the same key: </p><pre class="programlisting">
-<bean id="runAsManager"
- class="org.springframework.security.access.intercept.RunAsManagerImpl">
- <property name="key" value="my_run_as_password"/>
-</bean>
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"runAsManager"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.access.intercept.RunAsManagerImpl"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"key"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"my_run_as_password"</span><span class="hl-tag">/></span>
+<span class="hl-tag"></bean></span>
-<bean id="runAsAuthenticationProvider"
- class="org.springframework.security.access.intercept.RunAsImplAuthenticationProvider">
- <property name="key" value="my_run_as_password"/>
-</bean></pre><p>By using the same key, each <code class="literal">RunAsUserToken</code>
- can be validated it was created by an approved
- <code class="literal">RunAsManagerImpl</code>. The
- <code class="literal">RunAsUserToken</code> is immutable after creation for
- security reasons</p></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"runAsAuthenticationProvider"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.access.intercept.RunAsImplAuthenticationProvider"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"key"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"my_run_as_password"</span><span class="hl-tag">/></span>
+<span class="hl-tag"></bean></span></pre><p>By using the same key, each <code class="literal">RunAsUserToken</code> can be validated it was
+ created by an approved <code class="literal">RunAsManagerImpl</code>. The
+ <code class="literal">RunAsUserToken</code> is immutable after creation for security
+ reasons</p></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
- </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="x509.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="advanced-topics.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="appendix-schema.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">22. X.509 Authentication </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> Appendix A. Security Database Schema</td></tr></table></div></body></html>
\ No newline at end of file
+ </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="x509.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="advanced-topics.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="crypto.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">23. X.509 Authentication </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 25. Spring Security Crypto Module</td></tr></table></div></body></html>
\ No newline at end of file
diff --git a/docs/reference/sample-apps.html b/docs/reference/sample-apps.html
index a4e7ac8..a0a59d3 100644
--- a/docs/reference/sample-apps.html
+++ b/docs/reference/sample-apps.html
@@ -1,6 +1,6 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>3. Sample Applications</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="getting-started.html" title="Part I. Getting Started"><link rel="prev" href="ns-config.html" title="2. Security Namespace Configuration"><link rel="next" href="community.html" title="4. Spring Security Community"><!--Begin Google Analytics code--><script type="text/javascript">
+ <title>4. Sample Applications</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="getting-started.html" title="Part I. Getting Started"><link rel="prev" href="ns-config.html" title="3. Security Namespace Configuration"><link rel="next" href="community.html" title="5. Spring Security Community"><!--Begin Google Analytics code--><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
@@ -8,32 +8,30 @@
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
- </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">3. Sample Applications</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ns-config.html">Prev</a> </td><th width="60%" align="center">Part I. Getting Started</th><td width="20%" align="right"> <a accesskey="n" href="community.html">Next</a></td></tr></table><hr></div><div class="chapter" title="3. Sample Applications"><div class="titlepage"><div><div><h1 class="title"><a name="sample-apps"></a>Sample Applications</h1></div></div></div><p> There are several sample web applications that are available with the project. To avoid
+ </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">4. Sample Applications</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ns-config.html">Prev</a> </td><th width="60%" align="center">Part I. Getting Started</th><td width="20%" align="right"> <a accesskey="n" href="community.html">Next</a></td></tr></table><hr></div><div class="chapter" title="4. Sample Applications"><div class="titlepage"><div><div><h1 class="title"><a name="sample-apps"></a>Sample Applications</h1></div></div></div><p> There are several sample web applications that are available with the project. To avoid
an overly large download, only the "tutorial" and "contacts" samples are included in the
- distribution zip file. You can either build the others yourself, or you can obtain the war
- files individually from the central Maven repository. We'd recommend the former. You can get
- the source as described in <a class="link" href="introduction.html#get-source" title="1.4.2 Checking out the Source">the introduction</a> and it's
- easy to build the project using Maven. There is more information on the project web site at
- <a class="link" href="http://www.springsource.org/security/" target="_top">
- http://www.springsource.org/security/ </a> if you need it. All paths referred to in
- this chapter are relative to the project source directory. </p><div class="section" title="3.1 Tutorial Sample"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="tutorial-sample"></a>3.1 Tutorial Sample</h2></div></div></div><p> The tutorial sample is a nice basic example to get you started. It uses simple
+ distribution zip file. The others can be built directly from the source which you can obtain
+ as described in <a class="link" href="introduction.html#get-source" title="1.4.2 Checking out the Source">the introduction</a>. It's easy to build
+ the project yourself and there's more information on the project web site at <a class="link" href="http://www.springsource.org/security/" target="_top">
+ http://www.springsource.org/security/ </a>. All paths referred to in this chapter are
+ relative to the project source directory. </p><div class="section" title="4.1 Tutorial Sample"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="tutorial-sample"></a>4.1 Tutorial Sample</h2></div></div></div><p> The tutorial sample is a nice basic example to get you started. It uses simple
namespace configuration throughout. The compiled application is included in the
distribution zip file, ready to be deployed into your web container
- (<code class="filename">spring-security-samples-tutorial-3.0.x.war</code>). The <a class="link" href="ns-config.html#ns-form-and-basic" title="Form and Basic Login Options">form-based</a> authentication mechanism is used
- in combination with the commonly-used <a class="link" href="remember-me.html" title="10. Remember-Me Authentication">remember-me</a>
+ (<code class="filename">spring-security-samples-tutorial-3.1.x.war</code>). The <a class="link" href="ns-config.html#ns-form-and-basic" title="3.2.3 Form and Basic Login Options">form-based</a> authentication mechanism is used in
+ combination with the commonly-used <a class="link" href="remember-me.html" title="11. Remember-Me Authentication">remember-me</a>
authentication provider to automatically remember the login using cookies.</p><p>We recommend you start with the tutorial sample, as the XML is minimal and easy to
follow. Most importantly, you can easily add this one XML file (and its corresponding
- <code class="literal">web.xml</code> entries) to your existing application. Only when this
- basic integration is achieved do we suggest you attempt adding in method authorization
- or domain object security.</p></div><div class="section" title="3.2 Contacts"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="contacts-sample"></a>3.2 Contacts</h2></div></div></div><p> The Contacts Sample is an advanced example in that it illustrates the more powerful
+ <code class="literal">web.xml</code> entries) to your existing application. Only when this basic
+ integration is achieved do we suggest you attempt adding in method authorization or
+ domain object security.</p></div><div class="section" title="4.2 Contacts"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="contacts-sample"></a>4.2 Contacts</h2></div></div></div><p> The Contacts Sample is an advanced example in that it illustrates the more powerful
features of domain object access control lists (ACLs) in addition to basic application
security. The application provides an interface with which the users are able to
administer a simple database of contacts (the domain objects).</p><p>To deploy, simply copy the WAR file from Spring Security distribution into your
container’s <code class="literal">webapps</code> directory. The war should be called
- <code class="filename">spring-security-samples-contacts-3.0.x.war</code> (the appended
- version number will vary depending on what release you are using). </p><p>After starting your container, check the application can load. Visit
- <code class="literal">http://localhost:8080/contacts</code> (or whichever URL is appropriate
- for your web container and the WAR you deployed). </p><p>Next, click "Debug". You will be prompted to authenticate, and a series of usernames
+ <code class="filename">spring-security-samples-contacts-3.1.x.war</code> (the appended version
+ number will vary depending on what release you are using). </p><p>After starting your container, check the application can load. Visit
+ <code class="literal">http://localhost:8080/contacts</code> (or whichever URL is appropriate for
+ your web container and the WAR you deployed). </p><p>Next, click "Debug". You will be prompted to authenticate, and a series of usernames
and passwords are suggested on that page. Simply authenticate with any of these and view
the resulting page. It should contain a success message similar to the following:
</p><div class="literallayout"><p><br>
@@ -63,23 +61,39 @@ Success! Your web filters appear to be proper
</p></div><p>Once you successfully receive the above message, return to the sample application's
home page and click "Manage". You can then try out the application. Notice that only the
contacts available to the currently logged on user are displayed, and only users with
- <code class="literal">ROLE_SUPERVISOR</code> are granted access to delete their contacts.
- Behind the scenes, the <code class="classname">MethodSecurityInterceptor</code> is securing the
+ <code class="literal">ROLE_SUPERVISOR</code> are granted access to delete their contacts. Behind
+ the scenes, the <code class="classname">MethodSecurityInterceptor</code> is securing the
business objects. </p><p>The application allows you to modify the access control lists associated with
different contacts. Be sure to give this a try and understand how it works by reviewing
- the application context XML files.</p></div><div class="section" title="3.3 LDAP Sample"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ldap-sample"></a>3.3 LDAP Sample</h2></div></div></div><p> The LDAP sample application provides a basic configuration and sets up both a
+ the application context XML files.</p></div><div class="section" title="4.3 LDAP Sample"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ldap-sample"></a>4.3 LDAP Sample</h2></div></div></div><p> The LDAP sample application provides a basic configuration and sets up both a
namespace configuration and an equivalent configuration using traditional beans, both in
the same application context file. This means there are actually two identical
- authentication providers configured in this application. </p></div><div class="section" title="3.4 CAS Sample"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="cas-sample"></a>3.4 CAS Sample</h2></div></div></div><p> The CAS sample requires that you run both a CAS server and CAS client. It isn't
+ authentication providers configured in this application. </p></div><div class="section" title="4.4 OpenID Sample"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="openid-sample"></a>4.4 OpenID Sample</h2></div></div></div><p>
+ The OpenID sample demonstrates how to use the namespace to configure OpenID and how to set up
+ <a class="link" href="http://openid.net/specs/openid-attribute-exchange-1_0.html" target="_top">attribute exchange</a>
+ configurations for Google, Yahoo and MyOpenID identity providers (you can experiment with adding others
+ if you wish). It uses the JQuery-based <a class="link" href="http://code.google.com/p/openid-selector/" target="_top">openid-selector</a>
+ project to provide a user-friendly login page which allows the user to easily select a provider, rather than
+ typing in the full OpenID identifier.
+ </p><p>
+ The application differs from normal authentication scenarios in that it allows any user to access the site (provided
+ their OpenID authentication is successful). The first time you login, you will get a <span class="quote">“<span class="quote">Welcome [your name]"</span>”</span>
+ message. If you logout and log back in (with the same OpenID identity) then this should change to <span class="quote">“<span class="quote">Welcome Back</span>”</span>.
+ This is achieved by using a custom <code class="interfacename">UserDetailsService</code> which assigns a standard role
+ to any user and stores the identities internally in a map. Obviously a real application would use a database instead.
+ Have a look at the source form more information. This class also takes into account the fact that different attributes may be returned
+ from different providers and builds the name with which it addresses the user accordingly.
+ </p></div><div class="section" title="4.5 CAS Sample"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="cas-sample"></a>4.5 CAS Sample</h2></div></div></div><p> The CAS sample requires that you run both a CAS server and CAS client. It isn't
included in the distribution so you should check out the project code as described in
- <a class="link" href="introduction.html#get-source" title="1.4.2 Checking out the Source">the introduction</a>. You'll find the relevant
- files under the <code class="filename">sample/cas</code> directory. There's also a
- <code class="filename">Readme.txt</code> file in there which explains how to run both the
- server and the client directly from the source tree, complete with SSL support. You have
- to download the CAS Server web application (a war file) from the CAS site and drop it
- into the <code class="filename">samples/cas/server</code> directory. </p></div><div class="section" title="3.5 Pre-Authentication Sample"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="preauth-sample"></a>3.5 Pre-Authentication Sample</h2></div></div></div><p> This sample application demonstrates how to wire up beans from the <a class="link" href="preauth.html" title="17. Pre-Authentication Scenarios">pre-authentication</a> framework to make use of login
+ <a class="link" href="introduction.html#get-source" title="1.4.2 Checking out the Source">the introduction</a>. You'll find the relevant files
+ under the <code class="filename">sample/cas</code> directory. There's also a
+ <code class="filename">Readme.txt</code> file in there which explains how to run both the server
+ and the client directly from the source tree, complete with SSL support.</p></div><div class="section" title="4.6 JAAS Sample"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="jaas-sample"></a>4.6 JAAS Sample</h2></div></div></div><p>The JAAS sample is very simple example of how to use a JAAS LoginModule with Spring Security. The provided LoginModule will
+ successfully authenticate a user if the username equals the password otherwise a LoginException is thrown. The AuthorityGranter
+ used in this example always grants the role ROLE_USER. The sample application also demonstrates how to run as the JAAS Subject
+ returned by the LoginModule by setting <a class="link" href="appendix-namespace.html#nsa-http-jaas-api-provision" title="jaas-api-provision">jaas-api-provision</a> equal to "true".</p></div><div class="section" title="4.7 Pre-Authentication Sample"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="preauth-sample"></a>4.7 Pre-Authentication Sample</h2></div></div></div><p> This sample application demonstrates how to wire up beans from the <a class="link" href="preauth.html" title="18. Pre-Authentication Scenarios">pre-authentication</a> framework to make use of login
information from a J2EE container. The user name and roles are those setup by the
container. </p><p> The code is in <code class="filename">samples/preauth</code>. </p></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
- </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ns-config.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="getting-started.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="community.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">2. Security Namespace Configuration </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 4. Spring Security Community</td></tr></table></div></body></html>
\ No newline at end of file
+ </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ns-config.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="getting-started.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="community.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">3. Security Namespace Configuration </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 5. Spring Security Community</td></tr></table></div></body></html>
\ No newline at end of file
diff --git a/docs/reference/secure-object-impls.html b/docs/reference/secure-object-impls.html
index de465b7..d947c90 100644
--- a/docs/reference/secure-object-impls.html
+++ b/docs/reference/secure-object-impls.html
@@ -1,6 +1,6 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>14. Secure Object Implementations</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="authorization.html" title="Part IV. Authorization"><link rel="prev" href="authz-arch.html" title="13. Authorization Architecture"><link rel="next" href="el-access.html" title="15. Expression-Based Access Control"><!--Begin Google Analytics code--><script type="text/javascript">
+ <title>15. Secure Object Implementations</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="authorization.html" title="Part IV. Authorization"><link rel="prev" href="authz-arch.html" title="14. Authorization Architecture"><link rel="next" href="el-access.html" title="16. Expression-Based Access Control"><!--Begin Google Analytics code--><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
@@ -8,66 +8,69 @@
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
- </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">14. Secure Object Implementations</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="authz-arch.html">Prev</a> </td><th width="60%" align="center">Part IV. Authorization</th><td width="20%" align="right"> <a accesskey="n" href="el-access.html">Next</a></td></tr></table><hr></div><div class="chapter" title="14. Secure Object Implementations"><div class="titlepage"><div><div><h1 class="title"><a name="secure-object-impls"></a>Secure Object Implementations</h1></div></div></div><div class="section" title="14.1 AOP Alliance (MethodInvocation) Security Interceptor"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="aop-alliance"></a>14.1 AOP Alliance (MethodInvocation) Security Interceptor</h2></div></div></div><p> Prior to Spring Security 2.0, securing <code class="classname">MethodInvocation</code>s needed
- quite a lot of boiler plate configuration. Now the recommended approach for method security is
- to use <a class="link" href="ns-config.html#ns-method-security" title="2.4 Method Security">namespace configuration</a>. This way the
- method security infrastructure beans are configured automatically for you so you don't really
- need to know about the implementation classes. We'll just provide a quick overview of the
- classes that are involved here. </p><p> Method security in enforced using a <code class="classname">MethodSecurityInterceptor</code>,
- which secures <code class="classname">MethodInvocation</code>s. Depending on the configuration
- approach, an interceptor may be specific to a single bean or shared between multiple beans.
- The interceptor uses a <code class="interfacename">MethodSecurityMetadataSource</code> instance to
- obtain the configuration attributes that apply to a particular method invocation.
- <code class="classname">MapBasedMethodSecurityMetadataSource</code> is used to store configuration
- attributes keyed by method names (which can be wildcarded) and will be used internally when
- the attributes are defined in the application context using the
- <code class="literal"><intercept-methods></code> or <code class="literal"><protect-point></code>
- elements. Other implementations will be used to handle annotation-based configuration. </p><div class="section" title="14.1.1 Explicit MethodSecurityInterceptor Configuration"><div class="titlepage"><div><div><h3 class="title"><a name="d0e4677"></a>14.1.1 Explicit MethodSecurityInterceptor Configuration</h3></div></div></div><p> You can of course configure a <code class="classname">MethodSecurityIterceptor</code> directly
- in your application context for use with one of Spring AOP's proxying mechanisms: </p><pre class="programlisting">
-<bean id="bankManagerSecurity"
- class="org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor">
- <property name="authenticationManager" ref="authenticationManager"/>
- <property name="accessDecisionManager" ref="accessDecisionManager"/>
- <property name="afterInvocationManager" ref="afterInvocationManager"/>
- <property name="securityMetadataSource">
- <value>
+ </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">15. Secure Object Implementations</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="authz-arch.html">Prev</a> </td><th width="60%" align="center">Part IV. Authorization</th><td width="20%" align="right"> <a accesskey="n" href="el-access.html">Next</a></td></tr></table><hr></div><div class="chapter" title="15. Secure Object Implementations"><div class="titlepage"><div><div><h1 class="title"><a name="secure-object-impls"></a>Secure Object Implementations</h1></div></div></div><div class="section" title="15.1 AOP Alliance (MethodInvocation) Security Interceptor"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="aop-alliance"></a>15.1 AOP Alliance (MethodInvocation) Security Interceptor</h2></div></div></div><p> Prior to Spring Security 2.0, securing <code class="classname">MethodInvocation</code>s
+ needed quite a lot of boiler plate configuration. Now the recommended approach for
+ method security is to use <a class="link" href="ns-config.html#ns-method-security" title="3.4 Method Security">namespace
+ configuration</a>. This way the method security infrastructure beans are configured
+ automatically for you so you don't really need to know about the implementation classes.
+ We'll just provide a quick overview of the classes that are involved here. </p><p> Method security in enforced using a <code class="classname">MethodSecurityInterceptor</code>,
+ which secures <code class="classname">MethodInvocation</code>s. Depending on the configuration
+ approach, an interceptor may be specific to a single bean or shared between multiple
+ beans. The interceptor uses a
+ <code class="interfacename">MethodSecurityMetadataSource</code> instance to obtain the
+ configuration attributes that apply to a particular method invocation.
+ <code class="classname">MapBasedMethodSecurityMetadataSource</code> is used to store
+ configuration attributes keyed by method names (which can be wildcarded) and will be
+ used internally when the attributes are defined in the application context using the
+ <code class="literal"><intercept-methods></code> or <code class="literal"><protect-point></code>
+ elements. Other implementations will be used to handle annotation-based configuration. </p><div class="section" title="15.1.1 Explicit MethodSecurityInterceptor Configuration"><div class="titlepage"><div><div><h3 class="title"><a name="d0e5314"></a>15.1.1 Explicit MethodSecurityInterceptor Configuration</h3></div></div></div><p> You can of course configure a <code class="classname">MethodSecurityIterceptor</code>
+ directly in your application context for use with one of Spring AOP's proxying
+ mechanisms: </p><pre class="programlisting">
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"bankManagerSecurity"</span> <span class="hl-attribute">class</span>=
+ <span class="hl-value">"org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"authenticationManager"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"accessDecisionManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"accessDecisionManager"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"afterInvocationManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"afterInvocationManager"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"securityMetadataSource"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><value></span>
com.mycompany.BankManager.delete*=ROLE_SUPERVISOR
com.mycompany.BankManager.getBalance=ROLE_TELLER,ROLE_SUPERVISOR
- </value>
- </property>
-</bean>
-</pre></div></div><div class="section" title="14.2 AspectJ (JoinPoint) Security Interceptor"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="aspectj"></a>14.2 AspectJ (JoinPoint) Security Interceptor</h2></div></div></div><p>The AspectJ security interceptor is very similar to the AOP Alliance security interceptor
- discussed in the previous section. Indeed we will only discuss the differences in this
- section.</p><p>The AspectJ interceptor is named <code class="literal">AspectJSecurityInterceptor</code>. Unlike the
- AOP Alliance security interceptor, which relies on the Spring application context to weave in
- the security interceptor via proxying, the <code class="literal">AspectJSecurityInterceptor</code> is
- weaved in via the AspectJ compiler. It would not be uncommon to use both types of security
- interceptors in the same application, with <code class="literal">AspectJSecurityInterceptor</code> being
- used for domain object instance security and the AOP Alliance
- <code class="classname">MethodSecurityInterceptor</code> being used for services layer
- security.</p><p>Let's first consider how the <code class="literal">AspectJSecurityInterceptor</code> is configured
- in the Spring application context:</p><pre class="programlisting">
-<bean id="bankManagerSecurity"
- class="org.springframework.security.access.intercept.aspectj.AspectJSecurityInterceptor">
- <property name="authenticationManager" ref="authenticationManager"/>
- <property name="accessDecisionManager" ref="accessDecisionManager"/>
- <property name="afterInvocationManager" ref="afterInvocationManager"/>
- <property name="securityMetadataSource">
- <value>
+ <span class="hl-tag"></value></span>
+ <span class="hl-tag"></property></span>
+<span class="hl-tag"></bean></span>
+</pre></div></div><div class="section" title="15.2 AspectJ (JoinPoint) Security Interceptor"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="aspectj"></a>15.2 AspectJ (JoinPoint) Security Interceptor</h2></div></div></div><p>The AspectJ security interceptor is very similar to the AOP Alliance security
+ interceptor discussed in the previous section. Indeed we will only discuss the
+ differences in this section.</p><p>The AspectJ interceptor is named <code class="literal">AspectJSecurityInterceptor</code>. Unlike
+ the AOP Alliance security interceptor, which relies on the Spring application context to
+ weave in the security interceptor via proxying, the
+ <code class="literal">AspectJSecurityInterceptor</code> is weaved in via the AspectJ compiler. It
+ would not be uncommon to use both types of security interceptors in the same
+ application, with <code class="literal">AspectJSecurityInterceptor</code> being used for domain
+ object instance security and the AOP Alliance
+ <code class="classname">MethodSecurityInterceptor</code> being used for services layer
+ security.</p><p>Let's first consider how the <code class="literal">AspectJSecurityInterceptor</code> is
+ configured in the Spring application context:</p><pre class="programlisting">
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"bankManagerSecurity"</span> <span class="hl-attribute">class</span>=
+ <span class="hl-value">"org.springframework.security.access.intercept.aspectj.AspectJSecurityInterceptor"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"authenticationManager"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"accessDecisionManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"accessDecisionManager"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"afterInvocationManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"afterInvocationManager"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"securityMetadataSource"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><value></span>
com.mycompany.BankManager.delete*=ROLE_SUPERVISOR
com.mycompany.BankManager.getBalance=ROLE_TELLER,ROLE_SUPERVISOR
- </value>
-</property>
-</bean> </pre><p>As you can see, aside from the class name, the
- <code class="literal">AspectJSecurityInterceptor</code> is exactly the same as the AOP Alliance
- security interceptor. Indeed the two interceptors can share the same
- <code class="literal">securityMetadataSource</code>, as the
- <code class="interfacename">SecurityMetadataSource</code> works with
- <code class="literal">java.lang.reflect.Method</code>s rather than an AOP library-specific class. Of
- course, your access decisions have access to the relevant AOP library-specific invocation (ie
- <code class="classname">MethodInvocation</code> or <code class="literal">JoinPoint</code>) and as such can
- consider a range of addition criteria when making access decisions (such as method
- arguments).</p><p>Next you'll need to define an AspectJ <code class="literal">aspect</code>. For example:</p><pre class="programlisting">
+ <span class="hl-tag"></value></span>
+<span class="hl-tag"></property></span>
+<span class="hl-tag"></bean></span> </pre><p>As you can see, aside from the class name, the
+ <code class="literal">AspectJSecurityInterceptor</code> is exactly the same as the AOP Alliance
+ security interceptor. Indeed the two interceptors can share the same
+ <code class="literal">securityMetadataSource</code>, as the
+ <code class="interfacename">SecurityMetadataSource</code> works with
+ <code class="literal">java.lang.reflect.Method</code>s rather than an AOP library-specific class.
+ Of course, your access decisions have access to the relevant AOP library-specific
+ invocation (ie <code class="classname">MethodInvocation</code> or <code class="literal">JoinPoint</code>)
+ and as such can consider a range of addition criteria when making access decisions (such
+ as method arguments).</p><p>Next you'll need to define an AspectJ <code class="literal">aspect</code>. For example:</p><pre class="programlisting">
<span class="hl-keyword">package</span> org.springframework.security.samples.aspectj;
<span class="hl-keyword">import</span> org.springframework.security.access.intercept.aspectj.AspectJSecurityInterceptor;
@@ -110,22 +113,23 @@
}
}
</pre><p>In the above example, the security interceptor will be applied to every instance of
- <code class="literal">PersistableEntity</code>, which is an abstract class not shown (you can use any
- other class or <code class="literal">pointcut</code> expression you like). For those curious,
- <code class="literal">AspectJCallback</code> is needed because the <code class="literal">proceed();</code>
- statement has special meaning only within an <code class="literal">around()</code> body. The
- <code class="literal">AspectJSecurityInterceptor</code> calls this anonymous
- <code class="literal">AspectJCallback</code> class when it wants the target object to continue.</p><p>You will need to configure Spring to load the aspect and wire it with the
- <code class="literal">AspectJSecurityInterceptor</code>. A bean declaration which achieves this is
- shown below:</p><pre class="programlisting">
-<bean id="domainObjectInstanceSecurityAspect"
- class="security.samples.aspectj.DomainObjectInstanceSecurityAspect"
- factory-method="aspectOf">
- <property name="securityInterceptor" ref="bankManagerSecurity"/>
-</bean>
+ <code class="literal">PersistableEntity</code>, which is an abstract class not shown (you can use
+ any other class or <code class="literal">pointcut</code> expression you like). For those curious,
+ <code class="literal">AspectJCallback</code> is needed because the <code class="literal">proceed();</code>
+ statement has special meaning only within an <code class="literal">around()</code> body. The
+ <code class="literal">AspectJSecurityInterceptor</code> calls this anonymous
+ <code class="literal">AspectJCallback</code> class when it wants the target object to
+ continue.</p><p>You will need to configure Spring to load the aspect and wire it with the
+ <code class="literal">AspectJSecurityInterceptor</code>. A bean declaration which achieves this is
+ shown below:</p><pre class="programlisting">
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"domainObjectInstanceSecurityAspect"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"security.samples.aspectj.DomainObjectInstanceSecurityAspect"</span>
+ <span class="hl-attribute">factory-method</span>=<span class="hl-value">"aspectOf"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"securityInterceptor"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"bankManagerSecurity"</span><span class="hl-tag">/></span>
+<span class="hl-tag"></bean></span>
</pre><p>That's it! Now you can create your beans from anywhere within your application, using
- whatever means you think fit (eg <code class="literal">new Person();</code>) and they will have the
- security interceptor applied.</p></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
+ whatever means you think fit (eg <code class="literal">new Person();</code>) and they will have
+ the security interceptor applied.</p></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
- </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="authz-arch.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="authorization.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="el-access.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">13. Authorization Architecture </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 15. Expression-Based Access Control</td></tr></table></div></body></html>
\ No newline at end of file
+ </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="authz-arch.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="authorization.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="el-access.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">14. Authorization Architecture </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 16. Expression-Based Access Control</td></tr></table></div></body></html>
\ No newline at end of file
diff --git a/docs/reference/security-filter-chain.html b/docs/reference/security-filter-chain.html
index 2ce71d9..ffb04a8 100644
--- a/docs/reference/security-filter-chain.html
+++ b/docs/reference/security-filter-chain.html
@@ -1,6 +1,6 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>7. The Security Filter Chain</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="web-app-security.html" title="Part III. Web Application Security"><link rel="prev" href="web-app-security.html" title="Part III. Web Application Security"><link rel="next" href="core-web-filters.html" title="8. Core Security Filters"><!--Begin Google Analytics code--><script type="text/javascript">
+ <title>8. The Security Filter Chain</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="web-app-security.html" title="Part III. Web Application Security"><link rel="prev" href="web-app-security.html" title="Part III. Web Application Security"><link rel="next" href="core-web-filters.html" title="9. Core Security Filters"><!--Begin Google Analytics code--><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
@@ -8,151 +8,231 @@
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
- </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">7. The Security Filter Chain</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="web-app-security.html">Prev</a> </td><th width="60%" align="center">Part III. Web Application Security</th><td width="20%" align="right"> <a accesskey="n" href="core-web-filters.html">Next</a></td></tr></table><hr></div><div class="chapter" title="7. The Security Filter Chain"><div class="titlepage"><div><div><h1 class="title"><a name="security-filter-chain"></a>The Security Filter Chain</h1></div></div></div><p>Spring Security's web infrastructure is based entirely on standard servlet filters. It
- doesn't use servlets or any other servlet-based frameworks (such as Spring MVC) internally, so
- it has no strong links to any particular web technology. It deals in
- <code class="classname">HttpServletRequest</code>s and <code class="classname">HttpServletResponse</code>s and
- doesn't care whether the requests come from a browser, a web service client, an
- <code class="classname">HttpInvoker</code> or an AJAX application. </p><p> Spring Security maintains a filter chain internally where each of the filters has a
- particular responsibility and filters are added or removed from the configuration depending on
- which services are required. The ordering of the filters is important as there are dependencies
- between them. If you have been using <a class="link" href="ns-config.html" title="2. Security Namespace Configuration">namespace
- configuration</a>, then the filters are automatically configured for you and you don't have
- to define any Spring beans explicitly but here may be times when you want full control over the
- security filter chain, either because you are using features which aren't supported in the
- namespace, or you are using your own customized versions of classes.</p><div class="section" title="7.1 DelegatingFilterProxy"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="delegating-filter-proxy"></a>7.1 <code class="classname">DelegatingFilterProxy</code></h2></div></div></div><p> When using servlet filters, you obviously need to declare them in your
- <code class="filename">web.xml</code>, or they will be ignored by the servlet container. In Spring
- Security, the filter classes are also Spring beans defined in the application context and thus
- able to take advantage of Spring's rich dependency-injection facilities and lifecycle
- interfaces. Spring's <code class="classname">DelegatingFilterProxy</code> provides the link between
- <code class="filename">web.xml</code> and the application context. </p><p>When using <code class="classname">DelegatingFilterProxy</code>, you will see something like this
- in the <code class="filename">web.xml</code> file: </p><pre class="programlisting">
- <filter>
- <filter-name>myFilter</filter-name>
- <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
- </filter>
+ </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">8. The Security Filter Chain</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="web-app-security.html">Prev</a> </td><th width="60%" align="center">Part III. Web Application Security</th><td width="20%" align="right"> <a accesskey="n" href="core-web-filters.html">Next</a></td></tr></table><hr></div><div class="chapter" title="8. The Security Filter Chain"><div class="titlepage"><div><div><h1 class="title"><a name="security-filter-chain"></a>The Security Filter Chain</h1></div></div></div><p>Spring Security's web infrastructure is based entirely on standard servlet filters. It
+ doesn't use servlets or any other servlet-based frameworks (such as Spring MVC) internally,
+ so it has no strong links to any particular web technology. It deals in
+ <code class="classname">HttpServletRequest</code>s and <code class="classname">HttpServletResponse</code>s
+ and doesn't care whether the requests come from a browser, a web service client, an
+ <code class="classname">HttpInvoker</code> or an AJAX application. </p><p> Spring Security maintains a filter chain internally where each of the filters has a
+ particular responsibility and filters are added or removed from the configuration depending
+ on which services are required. The ordering of the filters is important as there are
+ dependencies between them. If you have been using <a class="link" href="ns-config.html" title="3. Security Namespace Configuration">namespace
+ configuration</a>, then the filters are automatically configured for you and you don't
+ have to define any Spring beans explicitly but here may be times when you want full control
+ over the security filter chain, either because you are using features which aren't supported
+ in the namespace, or you are using your own customized versions of classes.</p><div class="section" title="8.1 DelegatingFilterProxy"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="delegating-filter-proxy"></a>8.1 <code class="classname">DelegatingFilterProxy</code></h2></div></div></div><p> When using servlet filters, you obviously need to declare them in your
+ <code class="filename">web.xml</code>, or they will be ignored by the servlet container. In
+ Spring Security, the filter classes are also Spring beans defined in the application
+ context and thus able to take advantage of Spring's rich dependency-injection facilities
+ and lifecycle interfaces. Spring's <code class="classname">DelegatingFilterProxy</code> provides
+ the link between <code class="filename">web.xml</code> and the application context. </p><p>When using <code class="classname">DelegatingFilterProxy</code>, you will see something like
+ this in the <code class="filename">web.xml</code> file: </p><pre class="programlisting">
+ <span class="hl-tag"><filter></span>
+ <span class="hl-tag"><filter-name></span>myFilter<span class="hl-tag"></filter-name></span>
+ <span class="hl-tag"><filter-class></span>org.springframework.web.filter.DelegatingFilterProxy<span class="hl-tag"></filter-class></span>
+ <span class="hl-tag"></filter></span>
- <filter-mapping>
- <filter-name>myFilter</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
+ <span class="hl-tag"><filter-mapping></span>
+ <span class="hl-tag"><filter-name></span>myFilter<span class="hl-tag"></filter-name></span>
+ <span class="hl-tag"><url-pattern></span>/*<span class="hl-tag"></url-pattern></span>
+ <span class="hl-tag"></filter-mapping></span>
</pre><p> Notice that the filter is actually a
- <code class="literal">DelegatingFilterProxy</code>, and not the class that will actually implement the
- logic of the filter. What <code class="classname">DelegatingFilterProxy</code> does is delegate the
- <code class="interfacename">Filter</code>'s methods through to a bean which is obtained from the
- Spring application context. This enables the bean to benefit from the Spring web application
- context lifecycle support and configuration flexibility. The bean must implement
- <code class="interfacename">javax.servlet.Filter</code> and it must have the same name as that
- in the <code class="literal">filter-name</code> element. Read the Javadoc for
- <code class="classname">DelegatingFilterProxy</code> for more information</p></div><div class="section" title="7.2 FilterChainProxy"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="filter-chain-proxy"></a>7.2 <code class="classname">FilterChainProxy</code></h2></div></div></div><p> It should now be clear that you can declare each Spring Security filter bean that you
- require in your application context file and add a corresponding
- <code class="classname">DelegatingFilterProxy</code> entry to <code class="filename">web.xml</code> for each
- filter, making sure that they are ordered correctly. This is a cumbersome approach and
- clutters up the <code class="filename">web.xml</code> file quickly if we have a lot of filters. We
- would prefer to just add a single entry to <code class="filename">web.xml</code> and deal entirely with
- the application context file for managing our web security beans. This is where Spring
- Secuiryt's <code class="classname">FilterChainProxy</code> comes in. It is wired using a
- <code class="literal">DelegatingFilterProxy</code>, just like in the example above, but with the
- <code class="literal">filter-name</code> set to the bean name <span class="quote">“<span class="quote">filterChainProxy</span>”</span>. The
- filter chain is then declared in the application context with the same bean name. Here's an
- example: </p><pre class="programlisting">
+ <code class="literal">DelegatingFilterProxy</code>, and not the class that will actually implement
+ the logic of the filter. What <code class="classname">DelegatingFilterProxy</code> does is
+ delegate the <code class="interfacename">Filter</code>'s methods through to a bean which is
+ obtained from the Spring application context. This enables the bean to benefit from the
+ Spring web application context lifecycle support and configuration flexibility. The bean
+ must implement <code class="interfacename">javax.servlet.Filter</code> and it must have the
+ same name as that in the <code class="literal">filter-name</code> element. Read the Javadoc for
+ <code class="classname">DelegatingFilterProxy</code> for more information</p></div><div class="section" title="8.2 FilterChainProxy"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="filter-chain-proxy"></a>8.2 <code class="classname">FilterChainProxy</code></h2></div></div></div><p>Spring Security's web infrastructure should only be used by delegating to an
+ instance of <code class="classname">FilterChainProxy</code>. The security filters should not
+ be used by themselves. In theory you could declare each Spring Security filter bean
+ that you require in your application context file and add a corresponding
+ <code class="classname">DelegatingFilterProxy</code> entry to <code class="filename">web.xml</code>
+ for each filter, making sure that they are ordered correctly, but this would be
+ cumbersome and would clutter up the <code class="filename">web.xml</code> file quickly if you
+ have a lot of filters. <code class="classname">FilterChainProxy</code> lets us add a single
+ entry to <code class="filename">web.xml</code> and deal entirely with the application context
+ file for managing our web security beans. It is wired using a
+ <code class="literal">DelegatingFilterProxy</code>, just like in the example above, but with
+ the <code class="literal">filter-name</code> set to the bean name
+ <span class="quote">“<span class="quote">filterChainProxy</span>”</span>. The filter chain is then declared in the application
+ context with the same bean name. Here's an example: </p><pre class="programlisting">
<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"filterChainProxy"</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.FilterChainProxy"</span><span class="hl-tag">></span>
- <span class="hl-tag"><sec:filter-chain-map</span> <span class="hl-attribute">path-type</span>=<span class="hl-value">"ant"</span><span class="hl-tag">></span>
- <span class="hl-tag"><sec:filter-chain</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/webServices/**"</span> <span class="hl-attribute">filters</span>=<span class="hl-value">"
+ <span class="hl-tag"><constructor-arg></span>
+ <span class="hl-tag"><list></span>
+ <span class="hl-tag"><sec:filter-chain</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/restful/**"</span> <span class="hl-attribute">filters</span>=<span class="hl-value">"
securityContextPersistenceFilterWithASCFalse,
basicAuthenticationFilter,
exceptionTranslationFilter,
filterSecurityInterceptor"</span><span class="hl-tag"> /></span>
- <span class="hl-tag"><sec:filter-chain</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/**"</span> <span class="hl-attribute">filters</span>=<span class="hl-value">"
+ <span class="hl-tag"><sec:filter-chain</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/**"</span> <span class="hl-attribute">filters</span>=<span class="hl-value">"
securityContextPersistenceFilterWithASCTrue,
formLoginFilter,
exceptionTranslationFilter,
filterSecurityInterceptor"</span><span class="hl-tag"> /></span>
- <span class="hl-tag"></sec:filter-chain-map></span>
+ <span class="hl-tag"></list></span>
+ <span class="hl-tag"></constructor-arg></span>
<span class="hl-tag"></bean></span>
- </pre><p> The namespace element <code class="literal">filter-chain-map</code> is used
- to set up the security filter chain(s) which are required within the
- application<sup>[<a name="d0e2819" href="#ftn.d0e2819" class="footnote">7</a>]</sup>. It maps a
- particular URL pattern to a chain of filters built up from the bean names specified in the
- <code class="literal">filters</code> element. Both regular expressions and Ant Paths are supported,
- and the most specific URIs appear first. At runtime the
- <code class="classname">FilterChainProxy</code> will locate the first URI pattern that matches the
- current web request and the list of filter beans specified by the <code class="literal">filters</code>
- attribute will be applied to that request. The filters will be invoked in the order they are
- defined, so you have complete control over the filter chain which is applied to a particular
- URL.</p><p>You may have noticed we have declared two
- <code class="classname">SecurityContextPersistenceFilter</code>s in the filter chain
- (<code class="literal">ASC</code> is short for <code class="literal">allowSessionCreation</code>, a property of
- <code class="classname">SecurityContextPersistenceFilter</code>). As web services will never present
- a <code class="literal">jsessionid</code> on future requests, creating <code class="literal">HttpSession</code>s
- for such user agents would be wasteful. If you had a high-volume application which required
- maximum scalability, we recommend you use the approach shown above. For smaller applications,
- using a single <code class="classname">SecurityContextPersistenceFilter</code> (with its default
- <code class="literal">allowSessionCreation</code> as <code class="literal">true</code>) would likely be
- sufficient.</p><p>In relation to lifecycle issues, the <code class="classname">FilterChainProxy</code> will always
- delegate <code class="methodname">init(FilterConfig)</code> and <code class="methodname">destroy()</code>
- methods through to the underlaying <code class="interfacename">Filter</code>s if such methods are
- called against <code class="classname">FilterChainProxy</code> itself. In this case,
- <code class="classname">FilterChainProxy</code> guarantees to only initialize and destroy each
- <code class="literal">Filter</code> bean once, no matter how many times it is declared in the filter
- chain(s). You control the overall choice as to whether these methods are called or not via the
- <code class="literal">targetFilterLifecycle</code> initialization parameter of
- <code class="literal">DelegatingFilterProxy</code>. By default this property is
- <code class="literal">false</code> and servlet container lifecycle invocations are not delegated
- through <code class="literal">DelegatingFilterProxy</code>.</p><p> When we looked at how to set up web security using <a class="link" href="ns-config.html#ns-web-xml" title="2.2.1 web.xml Configuration">namespace configuration</a>, we used a <code class="literal">DelegatingFilterProxy</code> with the
- name <span class="quote">“<span class="quote">springSecurityFilterChain</span>”</span>. You should now be able to see that this is the
- name of the <code class="classname">FilterChainProxy</code> which is created by the namespace. </p><div class="section" title="7.2.1 Bypassing the Filter Chain"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2910"></a>7.2.1 Bypassing the Filter Chain</h3></div></div></div><p> As with the namespace, you can use the attribute <code class="literal">filters = "none"</code> as
- an alternative to supplying a filter bean list. This will omit the request pattern from the
- security filter chain entirely. Note that anything matching this path will then have no
- authentication or authorization services applied and will be freely accessible. If you want
- to make use of the contents of the <code class="classname">SecurityContext</code> contents during a
- request, then it must have passed through the security filter chain. Otherwise the
- <code class="classname">SecurityContextHolder</code> will not have been populated and the contents
- will be null.</p></div></div><div class="section" title="7.3 Filter Ordering"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e2924"></a>7.3 Filter Ordering</h2></div></div></div><p>The order that filters are defined in the chain is very important. Irrespective of which
- filters you are actually using, the order should be as follows:
- </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p><code class="classname">ChannelProcessingFilter</code>, because
- it might need to redirect to a different
- protocol</p></li><li class="listitem"><p><code class="classname">ConcurrentSessionFilter</code>,
- because it doesn't use any <code class="classname">SecurityContextHolder</code> functionality
- but needs to update the <code class="interfacename">SessionRegistry</code> to reflect
- ongoing requests from the
- principal</p></li><li class="listitem"><p><code class="classname">SecurityContextPersistenceFilter</code>,
- so a <code class="interfacename">SecurityContext</code> can be set up in the
- <code class="classname">SecurityContextHolder</code> at the beginning of a web request, and
- any changes to the <code class="interfacename">SecurityContext</code> can be copied to the
- <code class="literal">HttpSession</code> when the web request ends (ready for use with the next
- web request)</p></li><li class="listitem"><p>Authentication processing mechanisms -
- <code class="classname">UsernamePasswordAuthenticationFilter</code>,
- <code class="classname">CasAuthenticationFilter</code>,
- <code class="classname">BasicAuthenticationFilter</code> etc - so that the
- <code class="classname">SecurityContextHolder</code> can be modified to contain a valid
- <code class="interfacename">Authentication</code> request
- token</p></li><li class="listitem"><p>The
- <code class="literal">SecurityContextHolderAwareRequestFilter</code>, if you are using it to
- install a Spring Security aware <code class="literal">HttpServletRequestWrapper</code> into your
- servlet
- container</p></li><li class="listitem"><p><code class="classname">RememberMeAuthenticationFilter</code>,
- so that if no earlier authentication processing mechanism updated the
- <code class="classname">SecurityContextHolder</code>, and the request presents a cookie that
- enables remember-me services to take place, a suitable remembered
- <code class="interfacename">Authentication</code> object will be put
- there</p></li><li class="listitem"><p><code class="classname">AnonymousAuthenticationFilter</code>,
- so that if no earlier authentication processing mechanism updated the
- <code class="classname">SecurityContextHolder</code>, an anonymous
- <code class="interfacename">Authentication</code> object will be put
- there</p></li><li class="listitem"><p><code class="classname">ExceptionTranslationFilter</code>,
- to catch any Spring Security exceptions so that either an HTTP error response can be
- returned or an appropriate <code class="interfacename">AuthenticationEntryPoint</code> can
- be
- launched</p></li><li class="listitem"><p><code class="classname">FilterSecurityInterceptor</code>,
- to protect web URIs and raise exceptions when access is
- denied</p></li></ol></div></div><div class="section" title="7.4 Use with other Filter-Based Frameworks"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e3025"></a>7.4 Use with other Filter-Based Frameworks</h2></div></div></div><p>If you're using some other framework that is also filter-based, then you need to make sure
- that the Spring Security filters come first. This enables the
- <code class="classname">SecurityContextHolder</code> to be populated in time for use by the other
- filters. Examples are the use of SiteMesh to decorate your web pages or a web framework like
- Wicket which uses a filter to handle its requests. </p></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e2819" href="#d0e2819" class="para">7</a>] </sup>Note that you'll need to include the security namespace in your
- application context XML file in order to use this syntax.</p></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
+ </pre><p> The namespace element <code class="literal">filter-chain</code> is used for convenience
+ to set up the security filter chain(s) which are required within the application.
+ <sup>[<a name="d0e3180" href="#ftn.d0e3180" class="footnote">10</a>]</sup>. It maps a particular URL pattern to a list of filters built up from the
+ bean names specified in the <code class="literal">filters</code> element, and combines them in
+ a bean of type <code class="classname">SecurityFilterChain</code>. The <code class="literal">pattern</code>
+ attribute takes an Ant Paths and the most specific URIs should appear first
+ <sup>[<a name="d0e3196" href="#ftn.d0e3196" class="footnote">11</a>]</sup>. At runtime the <code class="classname">FilterChainProxy</code> will
+ locate the first URI pattern that matches the current web request and the list of filter beans
+ specified by the <code class="literal">filters</code> attribute will be applied to that request.
+ The filters will be invoked in the order they are defined, so you have complete control
+ over the filter chain which is applied to a particular URL.</p><p>You may have noticed we have declared two
+ <code class="classname">SecurityContextPersistenceFilter</code>s in the filter chain
+ (<code class="literal">ASC</code> is short for <code class="literal">allowSessionCreation</code>, a property
+ of <code class="classname">SecurityContextPersistenceFilter</code>). As web services will never
+ present a <code class="literal">jsessionid</code> on future requests, creating
+ <code class="literal">HttpSession</code>s for such user agents would be wasteful. If you had a
+ high-volume application which required maximum scalability, we recommend you use the
+ approach shown above. For smaller applications, using a single
+ <code class="classname">SecurityContextPersistenceFilter</code> (with its default
+ <code class="literal">allowSessionCreation</code> as <code class="literal">true</code>) would likely be
+ sufficient.</p><p>Note that <code class="classname">FilterChainProxy</code> does not invoke standard filter
+ lifecycle methods on the filters it is configured with. We recommend you use
+ Spring's application context lifecycle interfaces as an alternative, just as you
+ would for any other Spring bean.</p><p> When we looked at how to set up web security using <a class="link" href="ns-config.html#ns-web-xml" title="3.2.1 web.xml Configuration">namespace configuration</a>, we used a <code class="literal">DelegatingFilterProxy</code> with
+ the name <span class="quote">“<span class="quote">springSecurityFilterChain</span>”</span>. You should now be able to see that
+ this is the name of the <code class="classname">FilterChainProxy</code> which is created by the
+ namespace. </p><div class="section" title="8.2.1 Bypassing the Filter Chain"><div class="titlepage"><div><div><h3 class="title"><a name="d0e3260"></a>8.2.1 Bypassing the Filter Chain</h3></div></div></div><p> You can use the attribute <code class="literal">filters =
+ "none"</code> as an alternative to supplying a filter bean list. This will omit
+ the request pattern from the security filter chain entirely. Note that anything
+ matching this path will then have no authentication or authorization services
+ applied and will be freely accessible. If you want to make use of the contents of
+ the <code class="classname">SecurityContext</code> contents during a request, then it must
+ have passed through the security filter chain. Otherwise the
+ <code class="classname">SecurityContextHolder</code> will not have been populated and the
+ contents will be null.</p></div></div><div class="section" title="8.3 Filter Ordering"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e3274"></a>8.3 Filter Ordering</h2></div></div></div><p>The order that filters are defined in the chain is very important. Irrespective of
+ which filters you are actually using, the order should be as follows: </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p><code class="classname">ChannelProcessingFilter</code>, because it might need to
+ redirect to a different protocol</p></li><li class="listitem"><p><code class="classname">ConcurrentSessionFilter</code>, because it doesn't use any
+ <code class="classname">SecurityContextHolder</code> functionality but needs to update
+ the <code class="interfacename">SessionRegistry</code> to reflect ongoing requests
+ from the principal</p></li><li class="listitem"><p><code class="classname">SecurityContextPersistenceFilter</code>, so a
+ <code class="interfacename">SecurityContext</code> can be set up in the
+ <code class="classname">SecurityContextHolder</code> at the beginning of a web request,
+ and any changes to the <code class="interfacename">SecurityContext</code> can be
+ copied to the <code class="literal">HttpSession</code> when the web request ends (ready
+ for use with the next web request)</p></li><li class="listitem"><p>Authentication processing mechanisms -
+ <code class="classname">UsernamePasswordAuthenticationFilter</code>,
+ <code class="classname">CasAuthenticationFilter</code>,
+ <code class="classname">BasicAuthenticationFilter</code> etc - so that the
+ <code class="classname">SecurityContextHolder</code> can be modified to contain a valid
+ <code class="interfacename">Authentication</code> request token</p></li><li class="listitem"><p>The <code class="literal">SecurityContextHolderAwareRequestFilter</code>, if you are
+ using it to install a Spring Security aware
+ <code class="literal">HttpServletRequestWrapper</code> into your servlet container</p></li><li class="listitem"><p>The <code class="classname">JaasApiIntegrationFilter</code>, if a
+ <code class="classname">JaasAuthenticationToken</code> is in the
+ <code class="classname">SecurityContextHolder</code> this will process the
+ <code class="classname">FilterChain</code> as the <code class="classname">Subject</code> in the
+ <code class="classname">JaasAuthenticationToken</code></p></li><li class="listitem"><p><code class="classname">RememberMeAuthenticationFilter</code>, so that if no earlier
+ authentication processing mechanism updated the
+ <code class="classname">SecurityContextHolder</code>, and the request presents a cookie
+ that enables remember-me services to take place, a suitable remembered
+ <code class="interfacename">Authentication</code> object will be put there</p></li><li class="listitem"><p><code class="classname">AnonymousAuthenticationFilter</code>, so that if no earlier
+ authentication processing mechanism updated the
+ <code class="classname">SecurityContextHolder</code>, an anonymous
+ <code class="interfacename">Authentication</code> object will be put there</p></li><li class="listitem"><p><code class="classname">ExceptionTranslationFilter</code>, to catch any Spring
+ Security exceptions so that either an HTTP error response can be returned or an
+ appropriate <code class="interfacename">AuthenticationEntryPoint</code> can be
+ launched</p></li><li class="listitem"><p><code class="classname">FilterSecurityInterceptor</code>, to protect web URIs and
+ raise exceptions when access is denied</p></li></ol></div></div><div class="section" title="8.4 Request Matching and HttpFirewall"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="request-matching"></a>8.4 Request Matching and <code class="interfacename">HttpFirewall</code></h2></div></div></div><p>Spring Security has several areas where patterns you have defined are tested
+ against incoming requests in order to decide how the request should be handled. This
+ occurs when the <code class="classname">FilterChainProxy</code> decides which filter chain a
+ request should be passed through and also when the
+ <code class="classname">FilterSecurityInterceptor</code> decides which security constraints
+ apply to a request. It's important to understand what the mechanism is and what URL
+ value is used when testing against the patterns that you define.</p><p>The Servlet Specification defines several properties for the
+ <code class="interfacename">HttpServletRequest</code> which are accessible via getter
+ methods, and which we might want to match against. These are the
+ <code class="literal">contextPath</code>, <code class="literal">servletPath</code>,
+ <code class="literal">pathInfo</code> and <code class="literal">queryString</code>. Spring Security is
+ only interested in securing paths within the application, so the
+ <code class="literal">contextPath</code> is ignored. Unfortunately, the servlet spec does not
+ define exactly what the values of <code class="literal">servletPath</code> and
+ <code class="literal">pathInfo</code> will contain for a particular request URI. For example,
+ each path segment of a URL may contain parameters, as defined in <a class="link" href="http://www.ietf.org/rfc/rfc2396.txt" target="_top">RFC 2396</a><sup>[<a name="d0e3436" href="#ftn.d0e3436" class="footnote">12</a>]</sup>. The Specification does not clearly state whether these should be
+ included in the <code class="literal">servletPath</code> and <code class="literal">pathInfo</code>
+ values and the behaviour varies between different servlet containers. There is a
+ danger that when an application is deployed in a container which does not strip path
+ parameters from these values, an attacker could add them to the requested URL in
+ order to cause a pattern match to succeed or fail unexpectedly.<sup>[<a name="d0e3449" href="#ftn.d0e3449" class="footnote">13</a>]</sup>. Other variations in the incoming URL are also possible. For example, it
+ could contain path-traversal sequences (like <code class="literal">/../</code>) or multiple
+ forward slashes (<code class="literal">//</code>) which could also cause pattern-matches to
+ fail. Some containers normalize these out before performing the servlet mapping, but
+ others don't. To protect against issues like these,
+ <code class="classname">FilterChainProxy</code> uses an
+ <code class="interfacename">HttpFirewall</code> strategy to check and wrap the request.
+ Un-normalized requests are automatically rejected by default, and path parameters
+ and duplicate slashes are removed for matching purposes.<sup>[<a name="d0e3468" href="#ftn.d0e3468" class="footnote">14</a>]</sup>. It is therefore essential that a
+ <code class="classname">FilterChainProxy</code> is used to manage the security filter chain.
+ Note that the <code class="literal">servletPath</code> and <code class="literal">pathInfo</code> values
+ are decoded by the container, so your application should not have any valid paths
+ which contain semi-colons, as these parts will be removed for matching purposes. </p><p>As mentioned above, the default strategy is to use Ant-style paths for matching
+ and this is likely to be the best choice for most users. The strategy is implemented
+ in the class <code class="classname">AntPathRequestMatcher</code> which uses Spring's
+ <code class="classname">AntPathMatcher</code> to perform a case-insensitive match of the
+ pattern against the concatenated <code class="literal">servletPath</code> and
+ <code class="literal">pathInfo</code>, ignoring the <code class="literal">queryString</code>.</p><p>If for some reason, you need a more powerful matching strategy, you can use
+ regular expressions. The strategy implementation is then
+ <code class="classname">RegexRequestMatcher</code>. See the Javadoc for this class for more
+ information.</p><p>In practice we recommend that you use method security at your service layer, to
+ control access to your application, and do not rely entirely on the use of security
+ constraints defined at the web-application level. URLs change and it is difficult to
+ take account of all the possible URLs that an application might support and how
+ requests might be manipulated. You should try and restrict yourself to using a few
+ simple ant paths which are simple to understand. Always try to use a
+ <span class="quote">“<span class="quote">deny-by-default</span>”</span> approach where you have a catch-all wildcard
+ (<code class="literal">/**</code> or <code class="literal">**</code>) defined last and denying access.</p><p>Security defined at the service layer is much more robust and harder to bypass, so
+ you should always take advantage of Spring Security's method security
+ options.</p></div><div class="section" title="8.5 Use with other Filter-Based Frameworks"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e3522"></a>8.5 Use with other Filter-Based Frameworks</h2></div></div></div><p>If you're using some other framework that is also filter-based, then you need to make
+ sure that the Spring Security filters come first. This enables the
+ <code class="classname">SecurityContextHolder</code> to be populated in time for use by the
+ other filters. Examples are the use of SiteMesh to decorate your web pages or a web
+ framework like Wicket which uses a filter to handle its requests. </p></div><div class="section" title="8.6 Advanced Namespace Configuration"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="filter-chains-with-ns"></a>8.6 Advanced Namespace Configuration</h2></div></div></div><p>As we saw earlier in the namespace chapter, it's possible to use multiple <code class="literal">http</code>
+ elements to define different security configurations for different URL patterns.
+ Each element creates a filter chain within the internal <code class="classname">FilterChainProxy</code> and the
+ URL pattern that should be mapped to it. The elements will be added in the order they are declared, so the
+ most specific patterns must again be declared first. Here's another example, for a similar situation to
+ that above, where the application supports both a stateless RESTful API and also a normal web application
+ which users log into using a form.
+</p><pre class="programlisting">
+
+ <span class="hl-comment"><!-- Stateless RESTful service using Basic authentication --></span>
+ <span class="hl-tag"><http</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/restful/**"</span> <span class="hl-attribute">create-session</span>=<span class="hl-value">"stateless"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">'/**'</span> <span class="hl-attribute">access</span>=<span class="hl-value">'ROLE_REMOTE'</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"><http-basic /></span>
+ <span class="hl-tag"></http></span>
+
+ <span class="hl-comment"><!-- Empty filter chain for the login page --></span>
+ <span class="hl-tag"><http</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/login.htm*"</span> <span class="hl-attribute">security</span>=<span class="hl-value">"none"</span><span class="hl-tag">/></span>
+
+ <span class="hl-comment"><!-- Additional filter chain for normal users, matching all other requests --></span>
+ <span class="hl-tag"><http></span>
+ <span class="hl-tag"><intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">'/**'</span> <span class="hl-attribute">access</span>=<span class="hl-value">'ROLE_USER'</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"><form-login</span> <span class="hl-attribute">login-page</span>=<span class="hl-value">'/login.htm'</span> <span class="hl-attribute">default-target-url</span>=<span class="hl-value">"/home.htm"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><logout /></span>
+ <span class="hl-tag"></http></span>
+
+</pre><p>
+ </p></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e3180" href="#d0e3180" class="para">10</a>] </sup>Note that you'll need to include the security namespace in your application
+ context XML file in order to use this syntax. The older syntax which used a
+ <code class="literal">filter-chain-map</code> is still supported, but is deprecated in favour of
+ the constructor argument injection.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e3196" href="#d0e3196" class="para">11</a>] </sup>Instead of a path pattern, the <code class="literal">request-matcher-ref</code> attribute
+ can be used to specify a <code class="interfacename">RequestMatcher</code> instance for more powerful
+ matching</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e3436" href="#d0e3436" class="para">12</a>] </sup>You have probably seen this when a browser doesn't support cookies and the
+ <code class="literal">jsessionid</code> parameter is appended to the URL after a
+ semi-colon. However the RFC allows the presence of these parameters in any path
+ segment of the URL</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e3449" href="#d0e3449" class="para">13</a>] </sup>The original values will be returned once the request leaves the
+ <code class="classname">FilterChainProxy</code>, so will still be available to the
+ application.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e3468" href="#d0e3468" class="para">14</a>] </sup>So, for example, an original request path
+ <code class="literal">/secure;hack=1/somefile.html;hack=2</code> will be returned as
+ <code class="literal">/secure/somefile.html</code>.</p></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
- </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="web-app-security.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="web-app-security.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="core-web-filters.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Part III. Web Application Security </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 8. Core Security Filters</td></tr></table></div></body></html>
\ No newline at end of file
+ </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="web-app-security.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="web-app-security.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="core-web-filters.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Part III. Web Application Security </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 9. Core Security Filters</td></tr></table></div></body></html>
\ No newline at end of file
diff --git a/docs/reference/session-mgmt.html b/docs/reference/session-mgmt.html
index d4789db..4b913f4 100644
--- a/docs/reference/session-mgmt.html
+++ b/docs/reference/session-mgmt.html
@@ -1,6 +1,6 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>11. Session Management</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="web-app-security.html" title="Part III. Web Application Security"><link rel="prev" href="remember-me.html" title="10. Remember-Me Authentication"><link rel="next" href="anonymous.html" title="12. Anonymous Authentication"><!--Begin Google Analytics code--><script type="text/javascript">
+ <title>12. Session Management</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="web-app-security.html" title="Part III. Web Application Security"><link rel="prev" href="remember-me.html" title="11. Remember-Me Authentication"><link rel="next" href="anonymous.html" title="13. Anonymous Authentication"><!--Begin Google Analytics code--><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
@@ -8,114 +8,143 @@
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
- </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">11. Session Management</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="remember-me.html">Prev</a> </td><th width="60%" align="center">Part III. Web Application Security</th><td width="20%" align="right"> <a accesskey="n" href="anonymous.html">Next</a></td></tr></table><hr></div><div class="chapter" title="11. Session Management"><div class="titlepage"><div><div><h1 class="title"><a name="session-mgmt"></a>Session Management</h1></div></div></div><p>HTTP session related functonality is handled by a combination of the
- <code class="classname">SessionManagementFilter</code> and the
- <code class="interfacename">SessionAuthenticationStrategy</code> interface, which the filter
- delegates to. Typical usage includes session-fixation protection attack prevention, detection of
- session timeouts and restrictions on how many sessions an authenticated user may have open
- concurrently.</p><div class="section" title="11.1 SessionManagementFilter"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e3809"></a>11.1 SessionManagementFilter</h2></div></div></div><p>The <code class="classname">SessionManagementFilter</code> checks the contents of the
- <code class="interfacename">SecurityContextRepository</code> against the current contents of the
- <code class="classname">SecurityContextHolder</code> to determine whether a user has been
- authenticated during the current request, typically by a non-interactive authentication
- mechanism, such as pre-authentication or remember-me <sup>[<a name="d0e3823" href="#ftn.d0e3823" class="footnote">13</a>]</sup>. If the repository contains a
- security context, the filter does nothing. If it doesn't, and the thread-local
- <code class="interfacename">SecurityContext</code> contains a (non-anonymous)
- <code class="interfacename">Authentication</code> object, the filter assumes they have been
- authenticated by a previous filter in the stack. It will then invoke the configured
- <code class="interfacename">SessionAuthenticationStrategy</code>.</p><p>If the user is not currently authenticated, the filter will check whether an invalid
- session ID has been requested (because of a timeout, for example) and will redirect to the
- configured <code class="literal">invalidSessionUrl</code> if set. The easiest way to configure this is
- through the namespace, <a class="link" href="ns-config.html#ns-session-mgmt" title="2.3.3 Session Management">as described earlier</a>.</p></div><div class="section" title="11.2 SessionAuthenticationStrategy"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e3847"></a>11.2 <code class="interfacename">SessionAuthenticationStrategy</code></h2></div></div></div><p>
- <code class="interfacename">SessionAuthenticationStrategy</code> is used by both
- <code class="classname">SessionManagementFilter</code> and
- <code class="classname">AbstractAuthenticationProcessingFilter</code>, so if you are using a
- customized form-login class, for example, you will need to inject it into both of these. In
- this case, a typical configuration, combining the namespace and custom beans might look like this:</p><pre class="programlisting">
- <http>
- <custom-filter position="FORM_LOGIN_FILTER" ref="myAuthFilter" />
- <session-management session-authentication-strategy-ref="sas"/>
- </http>
+ </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">12. Session Management</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="remember-me.html">Prev</a> </td><th width="60%" align="center">Part III. Web Application Security</th><td width="20%" align="right"> <a accesskey="n" href="anonymous.html">Next</a></td></tr></table><hr></div><div class="chapter" title="12. Session Management"><div class="titlepage"><div><div><h1 class="title"><a name="session-mgmt"></a>Session Management</h1></div></div></div><p>HTTP session related functonality is handled by a combination of the
+ <code class="classname">SessionManagementFilter</code> and the
+ <code class="interfacename">SessionAuthenticationStrategy</code> interface, which the filter
+ delegates to. Typical usage includes session-fixation protection attack prevention,
+ detection of session timeouts and restrictions on how many sessions an authenticated user
+ may have open concurrently.</p><div class="section" title="12.1 SessionManagementFilter"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e4371"></a>12.1 SessionManagementFilter</h2></div></div></div><p>The <code class="classname">SessionManagementFilter</code> checks the contents of the
+ <code class="interfacename">SecurityContextRepository</code> against the current contents of
+ the <code class="classname">SecurityContextHolder</code> to determine whether a user has been
+ authenticated during the current request, typically by a non-interactive authentication
+ mechanism, such as pre-authentication or remember-me <sup>[<a name="d0e4385" href="#ftn.d0e4385" class="footnote">20</a>]</sup>. If the repository contains a security context, the filter does nothing. If
+ it doesn't, and the thread-local <code class="interfacename">SecurityContext</code> contains
+ a (non-anonymous) <code class="interfacename">Authentication</code> object, the filter
+ assumes they have been authenticated by a previous filter in the stack. It will then
+ invoke the configured
+ <code class="interfacename">SessionAuthenticationStrategy</code>.</p><p>If the user is not currently authenticated, the filter will check whether an invalid
+ session ID has been requested (because of a timeout, for example) and will invoke the configured
+ <code class="interfacename">InvalidSessionStrategy</code>, if one is set. The most common behaviour
+ is just to redirect to a fixed URL and this is encapsulated in the standard implementation
+ <code class="classname">SimpleRedirectInvalidSessionStrategy</code>. The latter is also used
+ when configuring an invalid session URL through the namespace,
+ <a class="link" href="ns-config.html#ns-session-mgmt" title="3.3.3 Session Management">as described earlier</a>.</p></div><div class="section" title="12.2 SessionAuthenticationStrategy"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e4412"></a>12.2 <code class="interfacename">SessionAuthenticationStrategy</code></h2></div></div></div><p> <code class="interfacename">SessionAuthenticationStrategy</code> is used by both
+ <code class="classname">SessionManagementFilter</code> and
+ <code class="classname">AbstractAuthenticationProcessingFilter</code>, so if you are using a
+ customized form-login class, for example, you will need to inject it into both of these.
+ In this case, a typical configuration, combining the namespace and custom beans might
+ look like this:</p><pre class="programlisting">
+<span class="hl-tag"><http></span>
+ <span class="hl-tag"><custom-filter</span> <span class="hl-attribute">position</span>=<span class="hl-value">"FORM_LOGIN_FILTER"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"myAuthFilter"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"><session-management</span> <span class="hl-attribute">session-authentication-strategy-ref</span>=<span class="hl-value">"sas"</span><span class="hl-tag">/></span>
+<span class="hl-tag"></http></span>
- <beans:bean id="myAuthFilter"
- class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
- <beans:property name="sessionAuthenticationStrategy" ref="sas" />
+<span class="hl-tag"><beans:bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"myAuthFilter"</span> <span class="hl-attribute">class</span>=
+ <span class="hl-value">"org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><beans:property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"sessionAuthenticationStrategy"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"sas"</span><span class="hl-tag"> /></span>
...
- </beans:bean>
+<span class="hl-tag"></beans:bean></span>
- <beans:bean id="sas"
- class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy"/>
-
- </pre></div><div class="section" title="11.3 Concurrency Control"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="concurrent-sessions"></a>11.3 Concurrency Control</h2></div></div></div><p>Spring Security is able to prevent a principal from concurrently authenticating to the
- same application more than a specified number of times. Many ISVs take advantage of this to
- enforce licensing, whilst network administrators like this feature because it helps prevent
- people from sharing login names. You can, for example, stop user <span class="quote">“<span class="quote">Batman</span>”</span> from
- logging onto the web application from two different sessions. You can either expire their
- previous login or you can report an error when they try to log in again, preventing the second
- login. Note that if you are using the second approach, a user who has not explicitly logged
- out (but who has just closed their browser, for example) will not be able to log in again
- until their original session expires.</p><p>Concurrency control is supported by the namespace, so please check the earlier namespace
- chapter for the simplest configuration. Sometimes you need to customize things though. </p><p>The implementation uses a specialized version of
- <code class="interfacename">SessionAuthenticationStrategy</code>, called
- <code class="classname">ConcurrentSessionControlStrategy</code>. </p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Previously the
- concurrent authentication check was made by the <code class="classname">ProviderManager</code>,
- which could be injected with a <code class="literal">ConcurrentSessionController</code>. The latter
- would check if the user was attempting to exceed the number of permitted sessions.
- However, this approach required that an HTTP session be created in advance, which is
- undesirable. In Spring Security 3, the user is first authenticated by the
- <code class="interfacename">AuthenticationManager</code> and once they are successfully
- authenticated, a session is created and the check is made whether they are allowed to have
- another session open.</p></td></tr></table></div><p>To use concurrent session support, you'll need to add the following to
- <code class="literal">web.xml</code>: </p><pre class="programlisting">
- <listener>
- <listener-class>
+<span class="hl-tag"><beans:bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"sas"</span> <span class="hl-attribute">class</span>=
+ <span class="hl-value">"org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy"</span><span class="hl-tag"> /></span>
+</pre><p>
+ Note that the use of the default, <code class="classname">SessionFixationProtectionStrategy</code>
+ may cause issues if you are storing beans in the session which implement
+ <code class="interfacename">HttpSessionBindingListener</code>, including Spring session-scoped
+ beans. See the Javadoc for this class for more information.
+ </p></div><div class="section" title="12.3 Concurrency Control"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="concurrent-sessions"></a>12.3 Concurrency Control</h2></div></div></div><p>Spring Security is able to prevent a principal from concurrently authenticating to the
+ same application more than a specified number of times. Many ISVs take advantage of this
+ to enforce licensing, whilst network administrators like this feature because it helps
+ prevent people from sharing login names. You can, for example, stop user
+ <span class="quote">“<span class="quote">Batman</span>”</span> from logging onto the web application from two different sessions.
+ You can either expire their previous login or you can report an error when they try to
+ log in again, preventing the second login. Note that if you are using the second
+ approach, a user who has not explicitly logged out (but who has just closed their
+ browser, for example) will not be able to log in again until their original session
+ expires.</p><p>Concurrency control is supported by the namespace, so please check the earlier
+ namespace chapter for the simplest configuration. Sometimes you need to customize things
+ though. </p><p>The implementation uses a specialized version of
+ <code class="interfacename">SessionAuthenticationStrategy</code>, called
+ <code class="classname">ConcurrentSessionControlStrategy</code>. </p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Previously the concurrent authentication check was made by the
+ <code class="classname">ProviderManager</code>, which could be injected with a
+ <code class="literal">ConcurrentSessionController</code>. The latter would check if the user
+ was attempting to exceed the number of permitted sessions. However, this approach
+ required that an HTTP session be created in advance, which is undesirable. In Spring
+ Security 3, the user is first authenticated by the
+ <code class="interfacename">AuthenticationManager</code> and once they are successfully
+ authenticated, a session is created and the check is made whether they are allowed
+ to have another session open.</p></td></tr></table></div><p>To use concurrent session support, you'll need to add the following to
+ <code class="literal">web.xml</code>: </p><pre class="programlisting">
+ <span class="hl-tag"><listener></span>
+ <span class="hl-tag"><listener-class></span>
org.springframework.security.web.session.HttpSessionEventPublisher
- </listener-class>
- </listener>
- </pre><p>In addition, you will need to add the <code class="literal">ConcurrentSessionFilter</code> to your
- <code class="classname">FilterChainProxy</code>. The <code class="classname">ConcurrentSessionFilter</code>
- requires two properties, <code class="literal">sessionRegistry</code>, which generally points to an
- instance of <code class="classname">SessionRegistryImpl</code>, and <code class="literal">expiredUrl</code>, which
- points to the page to display when a session has expired. A configuration using the namespace
- to create the <code class="classname">FilterChainProxy</code> and other default beans might look like
- this: </p><pre class="programlisting">
- <http>
- <custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" />
- <custom-filter position="FORM_LOGIN_FILTER" ref="myAuthFilter" />
+ <span class="hl-tag"></listener-class></span>
+ <span class="hl-tag"></listener></span>
+ </pre><p>In addition, you will need to add the <code class="literal">ConcurrentSessionFilter</code> to
+ your <code class="classname">FilterChainProxy</code>. The
+ <code class="classname">ConcurrentSessionFilter</code> requires two properties,
+ <code class="literal">sessionRegistry</code>, which generally points to an instance of
+ <code class="classname">SessionRegistryImpl</code>, and <code class="literal">expiredUrl</code>, which
+ points to the page to display when a session has expired. A configuration using the
+ namespace to create the <code class="classname">FilterChainProxy</code> and other default beans
+ might look like this: </p><pre class="programlisting">
+<span class="hl-tag"><http></span>
+ <span class="hl-tag"><custom-filter</span> <span class="hl-attribute">position</span>=<span class="hl-value">"CONCURRENT_SESSION_FILTER"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"concurrencyFilter"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"><custom-filter</span> <span class="hl-attribute">position</span>=<span class="hl-value">"FORM_LOGIN_FILTER"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"myAuthFilter"</span><span class="hl-tag"> /></span>
- <session-management session-authentication-strategy-ref="sas"/>
- </http>
+ <span class="hl-tag"><session-management</span> <span class="hl-attribute">session-authentication-strategy-ref</span>=<span class="hl-value">"sas"</span><span class="hl-tag">/></span>
+<span class="hl-tag"></http></span>
- <beans:bean id="concurrencyFilter"
- class="org.springframework.security.web.session.ConcurrentSessionFilter">
- <beans:property name="sessionRegistry" ref="sessionRegistry" />
- <beans:property name="expiredUrl" value="/session-expired.htm" />
- </beans:bean>
+<span class="hl-tag"><beans:bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"concurrencyFilter"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.session.ConcurrentSessionFilter"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><beans:property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"sessionRegistry"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"sessionRegistry"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"><beans:property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"expiredUrl"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"/session-expired.htm"</span><span class="hl-tag"> /></span>
+<span class="hl-tag"></beans:bean></span>
- <beans:bean id="myAuthFilter"
- class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
- <beans:property name="sessionAuthenticationStrategy" ref="sas" />
- <beans:property name="authenticationManager" ref="authenticationManager" />
- </beans:bean>
+<span class="hl-tag"><beans:bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"myAuthFilter"</span> <span class="hl-attribute">class</span>=
+ <span class="hl-value">"org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><beans:property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"sessionAuthenticationStrategy"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"sas"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"><beans:property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"authenticationManager"</span><span class="hl-tag"> /></span>
+<span class="hl-tag"></beans:bean></span>
- <beans:bean id="sas"
- class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
- <beans:constructor-arg name="sessionRegistry" ref="sessionRegistry" />
- <beans:property name="maximumSessions" value="1" />
- </beans:bean>
+<span class="hl-tag"><beans:bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"sas"</span> <span class="hl-attribute">class</span>=
+ <span class="hl-value">"org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><beans:constructor-arg</span> <span class="hl-attribute">name</span>=<span class="hl-value">"sessionRegistry"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"sessionRegistry"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"><beans:property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"maximumSessions"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"1"</span><span class="hl-tag"> /></span>
+<span class="hl-tag"></beans:bean></span>
- <beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl" />
+<span class="hl-tag"><beans:bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"sessionRegistry"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.core.session.SessionRegistryImpl"</span><span class="hl-tag"> /></span>
</pre><p>Adding the listener to <code class="filename">web.xml</code> causes an
- <code class="literal">ApplicationEvent</code> to be published to the Spring
- <code class="literal">ApplicationContext</code> every time a <code class="literal">HttpSession</code> commences
- or terminates. This is critical, as it allows the <code class="classname">SessionRegistryImpl</code>
- to be notified when a session ends. Without it, a user will never be able to log back in again
- once they have exceeded their session allowance, even if they log out of another session or it
- times out.</p></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e3823" href="#d0e3823" class="para">13</a>] </sup>Authentication by
- mechanisms which perform a redirect after authenticating (such as form-login) will not be
- detected by <code class="classname">SessionManagementFilter</code>, as the filter will not be
- invoked during the authenticating request. Session-management functionality has to be
- handled separately in these cases. </p></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
+ <code class="literal">ApplicationEvent</code> to be published to the Spring
+ <code class="literal">ApplicationContext</code> every time a <code class="literal">HttpSession</code>
+ commences or terminates. This is critical, as it allows the
+ <code class="classname">SessionRegistryImpl</code> to be notified when a session ends. Without
+ it, a user will never be able to log back in again once they have exceeded their session
+ allowance, even if they log out of another session or it times out.</p><div class="section" title="12.3.1 Querying the SessionRegistry for currently authenticated users and their sessions"><div class="titlepage"><div><div><h3 class="title"><a name="list-authenticated-principals"></a>12.3.1 Querying the <code class="interfacename">SessionRegistry</code> for currently authenticated
+ users and their sessions</h3></div></div></div><p>
+ Setting up concurrency-control, either through the namespace or using plain beans has the
+ useful side effect of providing you with a reference to the <code class="interfacename">SessionRegistry</code>
+ which you can use directly within your application, so even if you don't want to restrict the
+ number of sessions a user may have, it may be worth setting up the infrastructure anyway. You can
+ set the <code class="literal">maximumSession</code> property to -1 to allow unlimited sessions. If
+ you're using the namespace, you can set an alias for the internally-created
+ <code class="interfacename">SessionRegistry</code> using the <code class="literal">session-registry-alias</code>
+ attribute, providing a reference which you can inject into your own beans.</p><p>
+ The <code class="methodname">getAllPrincipals()</code>
+ method supplies you with a list of the currently authenticated users. You can list a user's
+ sessions by calling the <code class="methodname">getAllSessions(Object principal, boolean includeExpiredSessions)</code> method,
+ which returns a list of <code class="classname">SessionInformation</code> objects. You can also
+ expire a user's session by calling <code class="methodname">expireNow()</code> on a
+ <code class="methodname">SessionInformation</code> instance. When the user returns to the application, they
+ will be prevented from proceeding. You may find these methods useful in an administration
+ application, for example. Have a look at the Javadoc for more information.
+ </p></div></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e4385" href="#d0e4385" class="para">20</a>] </sup>Authentication by mechanisms which perform a redirect after authenticating (such
+ as form-login) will not be detected by
+ <code class="classname">SessionManagementFilter</code>, as the filter will not be invoked
+ during the authenticating request. Session-management functionality has to be
+ handled separately in these cases. </p></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
- </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="remember-me.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="web-app-security.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="anonymous.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">10. Remember-Me Authentication </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 12. Anonymous Authentication</td></tr></table></div></body></html>
\ No newline at end of file
+ </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="remember-me.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="web-app-security.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="anonymous.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">11. Remember-Me Authentication </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 13. Anonymous Authentication</td></tr></table></div></body></html>
\ No newline at end of file
diff --git a/docs/reference/springsecurity-single.html b/docs/reference/springsecurity-single.html
index 571b4f5..b56d2db 100644
--- a/docs/reference/springsecurity-single.html
+++ b/docs/reference/springsecurity-single.html
@@ -8,61 +8,69 @@ var pageTracker = _gat._getTracker("UA-2728886-3");
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
-</script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="book" title="Spring Security"><div class="titlepage"><div><div><h1 class="title"><a name="spring-security-reference-guide"></a>Spring Security</h1></div><div><h2 class="subtitle">Reference Documentation</h2></div><div><div class="authorgroup"><div class="author"><h3 class="author">Ben Alex</h3></div><div class="author"><h3 class="author">Luke Taylor</h3></div></div></div><div><p class="releaseinfo">3.0.5.RELEASE</p></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="preface"><a href="#preface">Preface</a></span></dt><dt><span class="part"><a href="#getting-started">I. Getting Started</a></span></dt><dd><dl><dt><span class="chapter"><a href="#introduction">1. Introduction</a></span></dt><dd><dl><dt><span class="section"><a href="#what-is-acegi-security">1.1. What is Spring Security?</a></span></dt><dt><span class="section"><a href="#history">1.2. History</a></span></dt><dt><span class="section"><a href="#release-numbering">1.3. Release Numbering</a></span></dt><dt><span class="section"><a href="#get-spring-security">1.4. Getting Spring Security</a></span></dt><dd><dl><dt><span class="section"><a href="#modules">1.4.1. Project Modules</a></span></dt><dt><span class="section"><a href="#get-source">1.4.2. Checking out the Source</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="#ns-config">2. Security Namespace Configuration</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e344">2.1. Introduction</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e382">2.1.1. Design of the Namespace</a></span></dt></dl></dd><dt><span class="section"><a href="#ns-getting-started">2.2. Getting Started with Security Namespace Configuration</a></span></dt><dd><dl><dt><span class="section"><a href="#ns-web-xml">2.2.1. <code class="literal">web.xml</code> Configuration</a></span></dt><dt><span class="section"><a href="#ns-minimal">2.2.2. A Minimal <code class="literal"><http></code> Configuration</a></span></dt><dt><span class="section"><a href="#ns-auth-providers">2.2.3. Using other Authentication Providers</a></span></dt></dl></dd><dt><span class="section"><a href="#ns-web-advanced">2.3. Advanced Web Features</a></span></dt><dd><dl><dt><span class="section"><a href="#ns-remember-me">2.3.1. Remember-Me Authentication</a></span></dt><dt><span class="section"><a href="#ns-requires-channel">2.3.2. Adding HTTP/HTTPS Channel Security</a></span></dt><dt><span class="section"><a href="#ns-session-mgmt">2.3.3. Session Management</a></span></dt><dt><span class="section"><a href="#ns-openid">2.3.4. OpenID Support</a></span></dt><dt><span class="section"><a href="#ns-custom-filters">2.3.5. Adding in Your Own Filters</a></span></dt></dl></dd><dt><span class="section"><a href="#ns-method-security">2.4. Method Security</a></span></dt><dd><dl><dt><span class="section"><a href="#ns-global-method">2.4.1. The <code class="literal"><global-method-security></code> Element</a></span></dt></dl></dd><dt><span class="section"><a href="#ns-access-manager">2.5. The Default AccessDecisionManager</a></span></dt><dd><dl><dt><span class="section"><a href="#ns-custom-access-mgr">2.5.1. Customizing the AccessDecisionManager</a></span></dt></dl></dd><dt><span class="section"><a href="#ns-auth-manager">2.6. The Authentication Manager and the Namespace</a></span></dt></dl></dd><dt><span class="chapter"><a href="#sample-apps">3. Sample Applications</a></span></dt><dd><dl><dt><span class="section"><a href="#tutorial-sample">3.1. Tutorial Sample</a></span></dt><dt><span class="section"><a href="#contacts-sample">3.2. Contacts</a></span></dt><dt><span class="section"><a href="#ldap-sample">3.3. LDAP Sample</a></span></dt><dt><span class="section"><a href="#cas-sample">3.4. CAS Sample</a></span></dt><dt><span class="section"><a href="#preauth-sample">3.5. Pre-Authentication Sample</a></span></dt></dl></dd><dt><span class="chapter"><a href="#community">4. Spring Security Community</a></span></dt><dd><dl><dt><span class="section"><a href="#jira">4.1. Issue Tracking</a></span></dt><dt><span class="section"><a href="#becoming-involved">4.2. Becoming Involved</a></span></dt><dt><span class="section"><a href="#further-info">4.3. Further Information</a></span></dt></dl></dd></dl></dd><dt><span class="part"><a href="#overall-architecture">II. Architecture and Implementation</a></span></dt><dd><dl><dt><span class="chapter"><a href="#technical-overview">5. Technical Overview</a></span></dt><dd><dl><dt><span class="section"><a href="#runtime-environment">5.1. Runtime Environment</a></span></dt><dt><span class="section"><a href="#core-components">5.2. Core Components</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e1518">5.2.1. SecurityContextHolder, SecurityContext and Authentication Objects </a></span></dt><dt><span class="section"><a href="#d0e1588">5.2.2. The UserDetailsService</a></span></dt><dt><span class="section"><a href="#tech-granted-authority">5.2.3. GrantedAuthority</a></span></dt><dt><span class="section"><a href="#d0e1709">5.2.4. Summary</a></span></dt></dl></dd><dt><span class="section"><a href="#tech-intro-authentication">5.3. Authentication</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e1765">5.3.1. What is authentication in Spring Security?</a></span></dt><dt><span class="section"><a href="#d0e1835">5.3.2. Setting the SecurityContextHolder Contents Directly</a></span></dt></dl></dd><dt><span class="section"><a href="#tech-intro-web-authentication">5.4. Authentication in a Web Application</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e1917">5.4.1. ExceptionTranslationFilter</a></span></dt><dt><span class="section"><a href="#tech-intro-auth-entry-point">5.4.2. AuthenticationEntryPoint</a></span></dt><dt><span class="section"><a href="#d0e1947">5.4.3. Authentication Mechanism</a></span></dt><dt><span class="section"><a href="#tech-intro-sec-context-persistence">5.4.4. Storing the <code class="interfacename">SecurityContext</code> between requests</a></span></dt></dl></dd><dt><span class="section"><a href="#tech-intro-access-control">5.5. Access-Control (Authorization) in Spring Security</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e2068">5.5.1. Security and AOP Advice</a></span></dt><dt><span class="section"><a href="#secure-objects">5.5.2. Secure Objects and the <code class="classname">AbstractSecurityInterceptor</code></a></span></dt></dl></dd><dt><span class="section"><a href="#localization">5.6. Localization</a></span></dt></dl></dd><dt><span class="chapter"><a href="#core-services">6. Core Services</a></span></dt><dd><dl><dt><span class="section"><a href="#core-services-authentication-manager">6.1. The <code class="interfacename">AuthenticationManager</code>,
- <code class="classname">ProviderManager</code> and
- <code class="classname">AuthenticationProvider</code>s</a></span></dt><dd><dl><dt><span class="section"><a href="#core-services-dao-provider">6.1.1. <code class="literal">DaoAuthenticationProvider</code></a></span></dt><dt><span class="section"><a href="#core-services-erasing-credentials">6.1.2. Erasing Credentials on Successful Authentication</a></span></dt></dl></dd><dt><span class="section"><a href="#d0e2530">6.2. <code class="interfacename">UserDetailsService</code> Implementations</a></span></dt><dd><dl><dt><span class="section"><a href="#core-services-in-memory-service">6.2.1. In-Memory Authentication</a></span></dt><dt><span class="section"><a href="#core-services-jdbc-user-service">6.2.2. <code class="literal">JdbcDaoImpl</code></a></span></dt></dl></dd><dt><span class="section"><a href="#core-services-password-encoding">6.3. Password Encoding</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e2649">6.3.1. What is a hash?</a></span></dt><dt><span class="section"><a href="#d0e2663">6.3.2. Adding Salt to a Hash</a></span></dt><dt><span class="section"><a href="#d0e2680">6.3.3. Hashing and Authentication</a></span></dt></dl></dd></dl></dd></dl></dd><dt><span class="part"><a href="#web-app-security">III. Web Application Security</a></span></dt><dd><dl><dt><span class="chapter"><a href="#security-filter-chain">7. The Security Filter Chain</a></span></dt><dd><dl><dt><span class="section"><a href="#delegating-filter-proxy">7.1. <code class="classname">DelegatingFilterProxy</code></a></span></dt><dt><span class="section"><a href="#filter-chain-proxy">7.2. <code class="classname">FilterChainProxy</code></a></span></dt><dd><dl><dt><span class="section"><a href="#d0e2910">7.2.1. Bypassing the Filter Chain</a></span></dt></dl></dd><dt><span class="section"><a href="#d0e2924">7.3. Filter Ordering</a></span></dt><dt><span class="section"><a href="#d0e3025">7.4. Use with other Filter-Based Frameworks</a></span></dt></dl></dd><dt><span class="chapter"><a href="#core-web-filters">8. Core Security Filters</a></span></dt><dd><dl><dt><span class="section"><a href="#filter-security-interceptor">8.1. <code class="classname">FilterSecurityInterceptor</code></a></span></dt><dt><span class="section"><a href="#exception-translation-filter">8.2.
- <code class="classname">ExceptionTranslationFilter</code></a></span></dt><dd><dl><dt><span class="section"><a href="#auth-entry-point">8.2.1. <code class="interfacename">AuthenticationEntryPoint</code></a></span></dt><dt><span class="section"><a href="#access-denied-handler">8.2.2. <code class="interfacename">AccessDeniedHandler</code></a></span></dt></dl></dd><dt><span class="section"><a href="#security-context-persistence-filter">8.3. <code class="classname">SecurityContextPersistenceFilter</code></a></span></dt><dd><dl><dt><span class="section"><a href="#security-context-repository">8.3.1. <code class="interfacename">SecurityContextRepository</code></a></span></dt></dl></dd><dt><span class="section"><a href="#form-login-filter">8.4. <code class="classname">UsernamePasswordAuthenticationFilter</code></a></span></dt><dd><dl><dt><span class="section"><a href="#form-login-flow-handling">8.4.1. Application Flow on Authentication Success and Failure</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="#basic">9. Basic and Digest Authentication</a></span></dt><dd><dl><dt><span class="section"><a href="#basic-processing-filter">9.1. <code class="classname">BasicAuthenticationFilter</code></a></span></dt><dd><dl><dt><span class="section"><a href="#basic-config">9.1.1. Configuration</a></span></dt></dl></dd><dt><span class="section"><a href="#digest-processing-filter">9.2. <code class="classname">DigestAuthenticationFilter</code></a></span></dt><dd><dl><dt><span class="section"><a href="#digest-config">9.2.1. Configuration</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="#remember-me">10. Remember-Me Authentication</a></span></dt><dd><dl><dt><span class="section"><a href="#remember-me-overview">10.1. Overview</a></span></dt><dt><span class="section"><a href="#remember-me-hash-token">10.2. Simple Hash-Based Token Approach</a></span></dt><dt><span class="section"><a href="#remember-me-persistent-token">10.3. Persistent Token Approach</a></span></dt><dt><span class="section"><a href="#remember-me-impls">10.4. Remember-Me Interfaces and Implementations</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e3706">10.4.1. TokenBasedRememberMeServices</a></span></dt><dt><span class="section"><a href="#d0e3772">10.4.2. PersistentTokenBasedRememberMeServices</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="#session-mgmt">11. Session Management</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e3809">11.1. SessionManagementFilter</a></span></dt><dt><span class="section"><a href="#d0e3847">11.2. <code class="interfacename">SessionAuthenticationStrategy</code></a></span></dt><dt><span class="section"><a href="#concurrent-sessions">11.3. Concurrency Control</a></span></dt></dl></dd><dt><span class="chapter"><a href="#anonymous">12. Anonymous Authentication</a></span></dt><dd><dl><dt><span class="section"><a href="#anonymous-overview">12.1. Overview</a></span></dt><dt><span class="section"><a href="#anonymous-config">12.2. Configuration</a></span></dt><dt><span class="section"><a href="#anonymous-auth-trust-resolver">12.3. <code class="interfacename">AuthenticationTrustResolver</code></a></span></dt></dl></dd></dl></dd><dt><span class="part"><a href="#authorization">IV. Authorization</a></span></dt><dd><dl><dt><span class="chapter"><a href="#authz-arch">13. Authorization Architecture</a></span></dt><dd><dl><dt><span class="section"><a href="#authz-authorities">13.1. Authorities</a></span></dt><dt><span class="section"><a href="#authz-pre-invocation">13.2. Pre-Invocation Handling</a></span></dt><dd><dl><dt><span class="section"><a href="#authz-access-decision-manager">13.2.1. The AccessDecisionManager</a></span></dt><dt><span class="section"><a href="#authz-voting-based">13.2.2. Voting-Based AccessDecisionManager Implementations</a></span></dt></dl></dd><dt><span class="section"><a href="#authz-after-invocation-handling">13.3. After Invocation Handling</a></span></dt></dl></dd><dt><span class="chapter"><a href="#secure-object-impls">14. Secure Object Implementations</a></span></dt><dd><dl><dt><span class="section"><a href="#aop-alliance">14.1. AOP Alliance (MethodInvocation) Security Interceptor</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e4677">14.1.1. Explicit MethodSecurityInterceptor Configuration</a></span></dt></dl></dd><dt><span class="section"><a href="#aspectj">14.2. AspectJ (JoinPoint) Security Interceptor</a></span></dt></dl></dd><dt><span class="chapter"><a href="#el-access">15. Expression-Based Access Control</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e4781">15.1. Overview</a></span></dt><dd><dl><dt><span class="section"><a href="#el-common-built-in">15.1.1. Common Built-In Expressions</a></span></dt></dl></dd><dt><span class="section"><a href="#el-access-web">15.2. Web Security Expressions</a></span></dt><dt><span class="section"><a href="#d0e4949">15.3. Method Security Expressions</a></span></dt><dd><dl><dt><span class="section"><a href="#el-pre-post-annotations">15.3.1. <code class="literal">@Pre</code> and <code class="literal">@Post</code> Annotations</a></span></dt><dt><span class="section"><a href="#el-method-built-in">15.3.2. Built-In Expressions</a></span></dt></dl></dd></dl></dd></dl></dd><dt><span class="part"><a href="#advanced-topics">V. Additional Topics</a></span></dt><dd><dl><dt><span class="chapter"><a href="#domain-acls">16. Domain Object Security (ACLs)</a></span></dt><dd><dl><dt><span class="section"><a href="#domain-acls-overview">16.1. Overview</a></span></dt><dt><span class="section"><a href="#domain-acls-key-concepts">16.2. Key Concepts</a></span></dt><dt><span class="section"><a href="#domain-acls-getting-started">16.3. Getting Started</a></span></dt></dl></dd><dt><span class="chapter"><a href="#preauth">17. Pre-Authentication Scenarios</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e5505">17.1. Pre-Authentication Framework Classes</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e5516">17.1.1. AbstractPreAuthenticatedProcessingFilter</a></span></dt><dt><span class="section"><a href="#d0e5533">17.1.2. AbstractPreAuthenticatedAuthenticationDetailsSource</a></span></dt><dt><span class="section"><a href="#d0e5590">17.1.3. PreAuthenticatedAuthenticationProvider</a></span></dt><dt><span class="section"><a href="#d0e5622">17.1.4. Http403ForbiddenEntryPoint</a></span></dt></dl></dd><dt><span class="section"><a href="#d0e5642">17.2. Concrete Implementations</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e5650">17.2.1. Request-Header Authentication (Siteminder)</a></span></dt><dt><span class="section"><a href="#d0e5696">17.2.2. J2EE Container Authentication</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="#ldap">18. LDAP Authentication</a></span></dt><dd><dl><dt><span class="section"><a href="#ldap-overview">18.1. Overview</a></span></dt><dt><span class="section"><a href="#d0e5734">18.2. Using LDAP with Spring Security</a></span></dt><dt><span class="section"><a href="#ldap-server">18.3. Configuring an LDAP Server</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e5773">18.3.1. Using an Embedded Test Server</a></span></dt><dt><span class="section"><a href="#d0e5797">18.3.2. Using Bind Authentication</a></span></dt><dt><span class="section"><a href="#d0e5818">18.3.3. Loading Authorities</a></span></dt></dl></dd><dt><span class="section"><a href="#d0e5883">18.4. Implementation Classes</a></span></dt><dd><dl><dt><span class="section"><a href="#ldap-ldap-authenticators">18.4.1. LdapAuthenticator Implementations</a></span></dt><dt><span class="section"><a href="#ldap-context-source">18.4.2. Connecting to the LDAP Server</a></span></dt><dt><span class="section"><a href="#ldap-searchobjects">18.4.3. LDAP Search Objects</a></span></dt><dt><span class="section"><a href="#ldap-authorities">18.4.4. LdapAuthoritiesPopulator</a></span></dt><dt><span class="section"><a href="#ldap-bean-config">18.4.5. Spring Bean Configuration</a></span></dt><dt><span class="section"><a href="#ldap-custom-user-details">18.4.6. LDAP Attributes and Customized UserDetails</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="#taglibs">19. JSP Tag Libraries</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e6137">19.1. Declaring the Taglib</a></span></dt><dt><span class="section"><a href="#d0e6144">19.2. The <code class="literal">authorize</code> Tag</a></span></dt><dt><span class="section"><a href="#d0e6190">19.3. The <code class="literal">authentication</code>Tag</a></span></dt><dt><span class="section"><a href="#d0e6221">19.4. The <code class="literal">accesscontrollist</code> Tag</a></span></dt></dl></dd><dt><span class="chapter"><a href="#jaas">20. Java Authentication and Authorization Service (JAAS) Provider</a></span></dt><dd><dl><dt><span class="section"><a href="#jaas-overview">20.1. Overview</a></span></dt><dt><span class="section"><a href="#jaas-config">20.2. Configuration</a></span></dt><dd><dl><dt><span class="section"><a href="#jaas-callbackhandler">20.2.1. JAAS CallbackHandler</a></span></dt><dt><span class="section"><a href="#jaas-authoritygranter">20.2.2. JAAS AuthorityGranter</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="#cas">21. CAS Authentication</a></span></dt><dd><dl><dt><span class="section"><a href="#cas-overview">21.1. Overview</a></span></dt><dt><span class="section"><a href="#cas-how-it-works">21.2. How CAS Works</a></span></dt><dt><span class="section"><a href="#cas-client">21.3. Configuration of CAS Client</a></span></dt></dl></dd><dt><span class="chapter"><a href="#x509">22. X.509 Authentication</a></span></dt><dd><dl><dt><span class="section"><a href="#x509-overview">22.1. Overview</a></span></dt><dt><span class="section"><a href="#d0e6578">22.2. Adding X.509 Authentication to Your Web Application</a></span></dt><dt><span class="section"><a href="#x509-ssl-config">22.3. Setting up SSL in Tomcat</a></span></dt></dl></dd><dt><span class="chapter"><a href="#runas">23. Run-As Authentication Replacement</a></span></dt><dd><dl><dt><span class="section"><a href="#runas-overview">23.1. Overview</a></span></dt><dt><span class="section"><a href="#runas-config">23.2. Configuration</a></span></dt></dl></dd></dl></dd><dt><span class="appendix"><a href="#appendix-schema">A. Security Database Schema</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e6840">A.1. User Schema</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e6853">A.1.1. Group Authorities</a></span></dt></dl></dd><dt><span class="section"><a href="#d0e6863">A.2. Persistent Login (Remember-Me) Schema</a></span></dt><dt><span class="section"><a href="#dbschema-acl">A.3. ACL Schema</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e6927">A.3.1. Hypersonic SQL</a></span></dt></dl></dd></dl></dd><dt><span class="appendix"><a href="#appendix-namespace">B. The Security Namespace</a></span></dt><dd><dl><dt><span class="section"><a href="#nsa-http">B.1. Web Application Security - the <code class="literal"><http></code> Element</a></span></dt><dd><dl><dt><span class="section"><a href="#nsa-http-attributes">B.1.1. <code class="literal"><http></code> Attributes</a></span></dt><dt><span class="section"><a href="#nsa-access-denied-handler">B.1.2. <code class="literal"><access-denied-handler></code></a></span></dt><dt><span class="section"><a href="#d0e7289">B.1.3. The <code class="literal"><intercept-url></code> Element</a></span></dt><dt><span class="section"><a href="#d0e7375">B.1.4. The <code class="literal"><port-mappings></code> Element</a></span></dt><dt><span class="section"><a href="#nsa-form-login">B.1.5. The <code class="literal"><form-login></code> Element</a></span></dt><dt><span class="section"><a href="#nsa-http-basic">B.1.6. The <code class="literal"><http-basic></code> Element</a></span></dt><dt><span class="section"><a href="#nsa-remember-me">B.1.7. The <code class="literal"><remember-me></code> Element</a></span></dt><dt><span class="section"><a href="#nsa-session-mgmt">B.1.8. The <code class="literal"><session-management></code> Element</a></span></dt><dt><span class="section"><a href="#nsa-concurrent-session-control">B.1.9. The <code class="literal"><concurrency-control></code> Element</a></span></dt><dt><span class="section"><a href="#nsa-anonymous">B.1.10. The <code class="literal"><anonymous></code> Element</a></span></dt><dt><span class="section"><a href="#nsa-x509">B.1.11. The <code class="literal"><x509></code> Element</a></span></dt><dt><span class="section"><a href="#nsa-openid-login">B.1.12. The <code class="literal"><openid-login></code> Element</a></span></dt><dt><span class="section"><a href="#nsa-logout">B.1.13. The <code class="literal"><logout></code> Element</a></span></dt><dt><span class="section"><a href="#d0e7898">B.1.14. The <code class="literal"><custom-filter></code> Element</a></span></dt><dt><span class="section"><a href="#nsa-request-cache">B.1.15. The <code class="literal">request-cache</code> Element</a></span></dt><dt><span class="section"><a href="#d0e7926">B.1.16. The <code class="literal"><http-firewall></code> Element</a></span></dt></dl></dd><dt><span class="section"><a href="#nsa-authentication">B.2. Authentication Services</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e7960">B.2.1. The <code class="literal"><authentication-manager></code> Element</a></span></dt></dl></dd><dt><span class="section"><a href="#nsa-method-security">B.3. Method Security</a></span></dt><dd><dl><dt><span class="section"><a href="#nsa-gms">B.3.1. The <code class="literal"><global-method-security></code> Element</a></span></dt><dt><span class="section"><a href="#d0e8166">B.3.2. LDAP Namespace Options</a></span></dt></dl></dd></dl></dd></dl></div><div class="preface" title="Preface"><div class="titlepage"><div><div><h2 class="title"><a name="preface"></a>Preface</h2></div></div></div><p>Spring Security provides a comprehensive security solution for J2EE-based enterprise
- software applications. As you will discover as you venture through this reference guide, we
- have tried to provide you a useful and highly configurable security system.</p><p>Security is an ever-moving target, and it's important to pursue a comprehensive,
- system-wide approach. In security circles we encourage you to adopt "layers of security", so
- that each layer tries to be as secure as possible in its own right, with successive layers
- providing additional security. The "tighter" the security of each layer, the more robust and
- safe your application will be. At the bottom level you'll need to deal with issues such as
- transport security and system identification, in order to mitigate man-in-the-middle attacks.
- Next you'll generally utilise firewalls, perhaps with VPNs or IP security to ensure only
- authorised systems can attempt to connect. In corporate environments you may deploy a DMZ to
- separate public-facing servers from backend database and application servers. Your operating
- system will also play a critical part, addressing issues such as running processes as
- non-privileged users and maximising file system security. An operating system will usually
- also be configured with its own firewall. Hopefully somewhere along the way you'll be trying
- to prevent denial of service and brute force attacks against the system. An intrusion
- detection system will also be especially useful for monitoring and responding to attacks, with
- such systems able to take protective action such as blocking offending TCP/IP addresses in
- real-time. Moving to the higher layers, your Java Virtual Machine will hopefully be configured
- to minimize the permissions granted to different Java types, and then your application will
- add its own problem domain-specific security configuration. Spring Security makes this latter
- area - application security - much easier. </p><p>Of course, you will need to properly address all security layers mentioned above, together
- with managerial factors that encompass every layer. A non-exhaustive list of such managerial
- factors would include security bulletin monitoring, patching, personnel vetting, audits,
- change control, engineering management systems, data backup, disaster recovery, performance
- benchmarking, load monitoring, centralised logging, incident response procedures etc.</p><p>With Spring Security being focused on helping you with the enterprise application security
- layer, you will find that there are as many different requirements as there are business
- problem domains. A banking application has different needs from an ecommerce application. An
- ecommerce application has different needs from a corporate sales force automation tool. These
- custom requirements make application security interesting, challenging and rewarding. </p><p>Please read <a class="xref" href="#getting-started" title="Part I. Getting Started">Part I, “Getting Started”</a>, in its entirety to begin with. This will
- introduce you to the framework and the namespace-based configuration system with which you can
- get up and running quite quickly. To get more of an understanding of how Spring Security
- works, and some of the classes you might need to use, you should then read <a class="xref" href="#overall-architecture" title="Part II. Architecture and Implementation">Part II, “Architecture and Implementation”</a>. The remaining parts of this guide are structured in a more
- traditional reference style, designed to be read on an as-required basis. We'd also recommend
- that you read up as much as possible on application security issues in general. Spring
- Security is not a panacea which will solve all security issues. It is important that the
- application is designed with security in mind from the start. Attempting to retrofit it is not
- a good idea. In particular, if you are building a web application, you should be aware of the
- many potential vulnerabilities such as cross-site scripting, request-forgery and
- session-hijacking which you should be taking into account from the start. The OWASP web site
- (http://www.owasp.org/) maintains a top ten list of web application vulnerabilities as well as
- a lot of useful reference information. </p><p>We hope that you find this reference guide useful, and we welcome your feedback and <a class="link" href="#jira" title="4.1 Issue Tracking">suggestions</a>. </p><p>Finally, welcome to the Spring Security <a class="link" href="#community" title="4. Spring Security Community">community</a>.
- </p></div><div class="part" title="Part I. Getting Started"><div class="titlepage"><div><div><h1 class="title"><a name="getting-started"></a>Part I. Getting Started</h1></div></div></div><div class="partintro" title="Getting Started"><div></div><p>The later parts of this guide provide an in-depth discussion of the framework
- architecture and implementation classes, which you need to understand if you want to do any
- serious customization. In this part, we'll introduce Spring Security 3.0, give a brief
- overview of the project's history and take a slightly gentler look at how to get started
- using the framework. In particular, we'll look at namespace configuration which provides a
- much simpler way of securing your application compared to the traditional Spring bean
- approach where you have to wire up all the implementation classes individually. </p><p> We'll also take a look at the sample applications that are available. It's worth trying
- to run these and experimenting with them a bit even before you read the later sections - you
- can dip back into them as your understanding of the framework increases. Please also check
- out the <a class="link" href="http://static.springsource.org/spring-security/site/index.html" target="_top">project website</a> as it has useful information on building the project, plus links
- to articles, videos and tutorials. </p></div><div class="chapter" title="1. Introduction"><div class="titlepage"><div><div><h2 class="title"><a name="introduction"></a>1. Introduction</h2></div></div></div><div class="section" title="1.1 What is Spring Security?"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="what-is-acegi-security"></a>1.1 What is Spring Security?</h2></div></div></div><p>Spring Security provides comprehensive security services for J2EE-based enterprise
+</script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="book" title="Spring Security"><div class="titlepage"><div><div><h1 class="title"><a name="spring-security-reference-guide"></a>Spring Security</h1></div><div><h2 class="subtitle">Reference Documentation</h2></div><div><div class="authorgroup"><div class="author"><h3 class="author">Ben Alex</h3></div><div class="author"><h3 class="author">Luke Taylor</h3></div></div></div><div><p class="releaseinfo">3.1.0</p></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="preface"><a href="#preface">Preface</a></span></dt><dt><span class="part"><a href="#getting-started">I. Getting Started</a></span></dt><dd><dl><dt><span class="chapter"><a href="#introduction">1. Introduction</a></span></dt><dd><dl><dt><span class="section"><a href="#what-is-acegi-security">1.1. What is Spring Security?</a></span></dt><dt><span class="section"><a href="#history">1.2. History</a></span></dt><dt><span class="section"><a href="#release-numbering">1.3. Release Numbering</a></span></dt><dt><span class="section"><a href="#get-spring-security">1.4. Getting Spring Security</a></span></dt><dd><dl><dt><span class="section"><a href="#modules">1.4.1. Project Modules</a></span></dt><dt><span class="section"><a href="#get-source">1.4.2. Checking out the Source</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="#new-3.1">2. What's new in Spring Security 3.1</a></span></dt><dd><dl><dt><span class="section"><a href="#new-3.1-highlevel">2.1. High level updates found Spring Security 3.1</a></span></dt><dt><span class="section"><a href="#new-3.1-ns">2.2. Spring Security 3.1 namespace updates</a></span></dt></dl></dd><dt><span class="chapter"><a href="#ns-config">3. Security Namespace Configuration</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e507">3.1. Introduction</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e545">3.1.1. Design of the Namespace</a></span></dt></dl></dd><dt><span class="section"><a href="#ns-getting-started">3.2. Getting Started with Security Namespace Configuration</a></span></dt><dd><dl><dt><span class="section"><a href="#ns-web-xml">3.2.1. <code class="literal">web.xml</code> Configuration</a></span></dt><dt><span class="section"><a href="#ns-minimal">3.2.2. A Minimal <code class="literal"><http></code> Configuration</a></span></dt><dt><span class="section"><a href="#ns-form-and-basic">3.2.3. Form and Basic Login Options</a></span></dt><dt><span class="section"><a href="#ns-logout">3.2.4. Logout Handling</a></span></dt><dt><span class="section"><a href="#ns-auth-providers">3.2.5. Using other Authentication Providers</a></span></dt></dl></dd><dt><span class="section"><a href="#ns-web-advanced">3.3. Advanced Web Features</a></span></dt><dd><dl><dt><span class="section"><a href="#ns-remember-me">3.3.1. Remember-Me Authentication</a></span></dt><dt><span class="section"><a href="#ns-requires-channel">3.3.2. Adding HTTP/HTTPS Channel Security</a></span></dt><dt><span class="section"><a href="#ns-session-mgmt">3.3.3. Session Management</a></span></dt><dt><span class="section"><a href="#ns-openid">3.3.4. OpenID Support</a></span></dt><dt><span class="section"><a href="#ns-custom-filters">3.3.5. Adding in Your Own Filters</a></span></dt></dl></dd><dt><span class="section"><a href="#ns-method-security">3.4. Method Security</a></span></dt><dd><dl><dt><span class="section"><a href="#ns-global-method">3.4.1. The <code class="literal"><global-method-security></code> Element</a></span></dt></dl></dd><dt><span class="section"><a href="#ns-access-manager">3.5. The Default AccessDecisionManager</a></span></dt><dd><dl><dt><span class="section"><a href="#ns-custom-access-mgr">3.5.1. Customizing the AccessDecisionManager</a></span></dt></dl></dd><dt><span class="section"><a href="#ns-auth-manager">3.6. The Authentication Manager and the Namespace</a></span></dt></dl></dd><dt><span class="chapter"><a href="#sample-apps">4. Sample Applications</a></span></dt><dd><dl><dt><span class="section"><a href="#tutorial-sample">4.1. Tutorial Sample</a></span></dt><dt><span class="section"><a href="#contacts-sample">4.2. Contacts</a></span></dt><dt><span class="section"><a href="#ldap-sample">4.3. LDAP Sample</a></span></dt><dt><span class="section"><a href="#openid-sample">4.4. OpenID Sample</a></span></dt><dt><span class="section"><a href="#cas-sample">4.5. CAS Sample</a></span></dt><dt><span class="section"><a href="#jaas-sample">4.6. JAAS Sample</a></span></dt><dt><span class="section"><a href="#preauth-sample">4.7. Pre-Authentication Sample</a></span></dt></dl></dd><dt><span class="chapter"><a href="#community">5. Spring Security Community</a></span></dt><dd><dl><dt><span class="section"><a href="#jira">5.1. Issue Tracking</a></span></dt><dt><span class="section"><a href="#becoming-involved">5.2. Becoming Involved</a></span></dt><dt><span class="section"><a href="#further-info">5.3. Further Information</a></span></dt></dl></dd></dl></dd><dt><span class="part"><a href="#overall-architecture">II. Architecture and Implementation</a></span></dt><dd><dl><dt><span class="chapter"><a href="#technical-overview">6. Technical Overview</a></span></dt><dd><dl><dt><span class="section"><a href="#runtime-environment">6.1. Runtime Environment</a></span></dt><dt><span class="section"><a href="#core-components">6.2. Core Components</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e1833">6.2.1. SecurityContextHolder, SecurityContext and Authentication Objects </a></span></dt><dt><span class="section"><a href="#tech-userdetailsservice">6.2.2. The UserDetailsService</a></span></dt><dt><span class="section"><a href="#tech-granted-authority">6.2.3. GrantedAuthority</a></span></dt><dt><span class="section"><a href="#d0e2041">6.2.4. Summary</a></span></dt></dl></dd><dt><span class="section"><a href="#tech-intro-authentication">6.3. Authentication</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e2097">6.3.1. What is authentication in Spring Security?</a></span></dt><dt><span class="section"><a href="#d0e2167">6.3.2. Setting the SecurityContextHolder Contents Directly</a></span></dt></dl></dd><dt><span class="section"><a href="#tech-intro-web-authentication">6.4. Authentication in a Web Application</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e2256">6.4.1. ExceptionTranslationFilter</a></span></dt><dt><span class="section"><a href="#tech-intro-auth-entry-point">6.4.2. AuthenticationEntryPoint</a></span></dt><dt><span class="section"><a href="#d0e2286">6.4.3. Authentication Mechanism</a></span></dt><dt><span class="section"><a href="#tech-intro-sec-context-persistence">6.4.4. Storing the <code class="interfacename">SecurityContext</code> between
+ requests</a></span></dt></dl></dd><dt><span class="section"><a href="#tech-intro-access-control">6.5. Access-Control (Authorization) in Spring Security</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e2410">6.5.1. Security and AOP Advice</a></span></dt><dt><span class="section"><a href="#secure-objects">6.5.2. Secure Objects and the <code class="classname">AbstractSecurityInterceptor</code></a></span></dt></dl></dd><dt><span class="section"><a href="#localization">6.6. Localization</a></span></dt></dl></dd><dt><span class="chapter"><a href="#core-services">7. Core Services</a></span></dt><dd><dl><dt><span class="section"><a href="#core-services-authentication-manager">7.1. The <code class="interfacename">AuthenticationManager</code>,
+ <code class="classname">ProviderManager</code> and
+ <code class="classname">AuthenticationProvider</code>s</a></span></dt><dd><dl><dt><span class="section"><a href="#core-services-erasing-credentials">7.1.1. Erasing Credentials on Successful Authentication</a></span></dt><dt><span class="section"><a href="#core-services-dao-provider">7.1.2. <code class="literal">DaoAuthenticationProvider</code></a></span></dt></dl></dd><dt><span class="section"><a href="#d0e2871">7.2. <code class="interfacename">UserDetailsService</code> Implementations</a></span></dt><dd><dl><dt><span class="section"><a href="#core-services-in-memory-service">7.2.1. In-Memory Authentication</a></span></dt><dt><span class="section"><a href="#core-services-jdbc-user-service">7.2.2. <code class="literal">JdbcDaoImpl</code></a></span></dt></dl></dd><dt><span class="section"><a href="#core-services-password-encoding">7.3. Password Encoding</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e3003">7.3.1. What is a hash?</a></span></dt><dt><span class="section"><a href="#d0e3017">7.3.2. Adding Salt to a Hash</a></span></dt><dt><span class="section"><a href="#d0e3052">7.3.3. Hashing and Authentication</a></span></dt></dl></dd></dl></dd></dl></dd><dt><span class="part"><a href="#web-app-security">III. Web Application Security</a></span></dt><dd><dl><dt><span class="chapter"><a href="#security-filter-chain">8. The Security Filter Chain</a></span></dt><dd><dl><dt><span class="section"><a href="#delegating-filter-proxy">8.1. <code class="classname">DelegatingFilterProxy</code></a></span></dt><dt><span class="section"><a href="#filter-chain-proxy">8.2. <code class="classname">FilterChainProxy</code></a></span></dt><dd><dl><dt><span class="section"><a href="#d0e3260">8.2.1. Bypassing the Filter Chain</a></span></dt></dl></dd><dt><span class="section"><a href="#d0e3274">8.3. Filter Ordering</a></span></dt><dt><span class="section"><a href="#request-matching">8.4. Request Matching and <code class="interfacename">HttpFirewall</code></a></span></dt><dt><span class="section"><a href="#d0e3522">8.5. Use with other Filter-Based Frameworks</a></span></dt><dt><span class="section"><a href="#filter-chains-with-ns">8.6. Advanced Namespace Configuration</a></span></dt></dl></dd><dt><span class="chapter"><a href="#core-web-filters">9. Core Security Filters</a></span></dt><dd><dl><dt><span class="section"><a href="#filter-security-interceptor">9.1. <code class="classname">FilterSecurityInterceptor</code></a></span></dt><dt><span class="section"><a href="#exception-translation-filter">9.2. <code class="classname">ExceptionTranslationFilter</code></a></span></dt><dd><dl><dt><span class="section"><a href="#auth-entry-point">9.2.1. <code class="interfacename">AuthenticationEntryPoint</code></a></span></dt><dt><span class="section"><a href="#access-denied-handler">9.2.2. <code class="interfacename">AccessDeniedHandler</code></a></span></dt><dt><span class="section"><a href="#request-caching">9.2.3. <code class="interfacename">SavedRequest</code>s and the <code class="interfacename">RequestCache</code> Interface</a></span></dt></dl></dd><dt><span class="section"><a href="#security-context-persistence-filter">9.3. <code class="classname">SecurityContextPersistenceFilter</code></a></span></dt><dd><dl><dt><span class="section"><a href="#security-context-repository">9.3.1. <code class="interfacename">SecurityContextRepository</code></a></span></dt></dl></dd><dt><span class="section"><a href="#form-login-filter">9.4. <code class="classname">UsernamePasswordAuthenticationFilter</code></a></span></dt><dd><dl><dt><span class="section"><a href="#form-login-flow-handling">9.4.1. Application Flow on Authentication Success and Failure</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="#basic">10. Basic and Digest Authentication</a></span></dt><dd><dl><dt><span class="section"><a href="#basic-processing-filter">10.1. <code class="classname">BasicAuthenticationFilter</code></a></span></dt><dd><dl><dt><span class="section"><a href="#basic-config">10.1.1. Configuration</a></span></dt></dl></dd><dt><span class="section"><a href="#digest-processing-filter">10.2. <code class="classname">DigestAuthenticationFilter</code></a></span></dt><dd><dl><dt><span class="section"><a href="#digest-config">10.2.1. Configuration</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="#remember-me">11. Remember-Me Authentication</a></span></dt><dd><dl><dt><span class="section"><a href="#remember-me-overview">11.1. Overview</a></span></dt><dt><span class="section"><a href="#remember-me-hash-token">11.2. Simple Hash-Based Token Approach</a></span></dt><dt><span class="section"><a href="#remember-me-persistent-token">11.3. Persistent Token Approach</a></span></dt><dt><span class="section"><a href="#remember-me-impls">11.4. Remember-Me Interfaces and Implementations</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e4268">11.4.1. TokenBasedRememberMeServices</a></span></dt><dt><span class="section"><a href="#d0e4334">11.4.2. PersistentTokenBasedRememberMeServices</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="#session-mgmt">12. Session Management</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e4371">12.1. SessionManagementFilter</a></span></dt><dt><span class="section"><a href="#d0e4412">12.2. <code class="interfacename">SessionAuthenticationStrategy</code></a></span></dt><dt><span class="section"><a href="#concurrent-sessions">12.3. Concurrency Control</a></span></dt><dd><dl><dt><span class="section"><a href="#list-authenticated-principals">12.3.1. Querying the <code class="interfacename">SessionRegistry</code> for currently authenticated
+ users and their sessions</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="#anonymous">13. Anonymous Authentication</a></span></dt><dd><dl><dt><span class="section"><a href="#anonymous-overview">13.1. Overview</a></span></dt><dt><span class="section"><a href="#anonymous-config">13.2. Configuration</a></span></dt><dt><span class="section"><a href="#anonymous-auth-trust-resolver">13.3. <code class="interfacename">AuthenticationTrustResolver</code></a></span></dt></dl></dd></dl></dd><dt><span class="part"><a href="#authorization">IV. Authorization</a></span></dt><dd><dl><dt><span class="chapter"><a href="#authz-arch">14. Authorization Architecture</a></span></dt><dd><dl><dt><span class="section"><a href="#authz-authorities">14.1. Authorities</a></span></dt><dt><span class="section"><a href="#authz-pre-invocation">14.2. Pre-Invocation Handling</a></span></dt><dd><dl><dt><span class="section"><a href="#authz-access-decision-manager">14.2.1. The AccessDecisionManager</a></span></dt><dt><span class="section"><a href="#authz-voting-based">14.2.2. Voting-Based AccessDecisionManager Implementations</a></span></dt></dl></dd><dt><span class="section"><a href="#authz-after-invocation-handling">14.3. After Invocation Handling</a></span></dt><dt><span class="section"><a href="#authz-hierarchical-roles">14.4. Hierarchical Roles</a></span></dt></dl></dd><dt><span class="chapter"><a href="#secure-object-impls">15. Secure Object Implementations</a></span></dt><dd><dl><dt><span class="section"><a href="#aop-alliance">15.1. AOP Alliance (MethodInvocation) Security Interceptor</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e5314">15.1.1. Explicit MethodSecurityInterceptor Configuration</a></span></dt></dl></dd><dt><span class="section"><a href="#aspectj">15.2. AspectJ (JoinPoint) Security Interceptor</a></span></dt></dl></dd><dt><span class="chapter"><a href="#el-access">16. Expression-Based Access Control</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e5418">16.1. Overview</a></span></dt><dd><dl><dt><span class="section"><a href="#el-common-built-in">16.1.1. Common Built-In Expressions</a></span></dt></dl></dd><dt><span class="section"><a href="#el-access-web">16.2. Web Security Expressions</a></span></dt><dt><span class="section"><a href="#d0e5586">16.3. Method Security Expressions</a></span></dt><dd><dl><dt><span class="section"><a href="#el-pre-post-annotations">16.3.1. <code class="literal">@Pre</code> and <code class="literal">@Post</code> Annotations</a></span></dt><dt><span class="section"><a href="#el-method-built-in">16.3.2. Built-In Expressions</a></span></dt></dl></dd></dl></dd></dl></dd><dt><span class="part"><a href="#advanced-topics">V. Additional Topics</a></span></dt><dd><dl><dt><span class="chapter"><a href="#domain-acls">17. Domain Object Security (ACLs)</a></span></dt><dd><dl><dt><span class="section"><a href="#domain-acls-overview">17.1. Overview</a></span></dt><dt><span class="section"><a href="#domain-acls-key-concepts">17.2. Key Concepts</a></span></dt><dt><span class="section"><a href="#domain-acls-getting-started">17.3. Getting Started</a></span></dt></dl></dd><dt><span class="chapter"><a href="#preauth">18. Pre-Authentication Scenarios</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e6142">18.1. Pre-Authentication Framework Classes</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e6153">18.1.1. AbstractPreAuthenticatedProcessingFilter</a></span></dt><dt><span class="section"><a href="#d0e6221">18.1.2. PreAuthenticatedAuthenticationProvider</a></span></dt><dt><span class="section"><a href="#d0e6253">18.1.3. Http403ForbiddenEntryPoint</a></span></dt></dl></dd><dt><span class="section"><a href="#d0e6273">18.2. Concrete Implementations</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e6281">18.2.1. Request-Header Authentication (Siteminder)</a></span></dt><dt><span class="section"><a href="#d0e6327">18.2.2. J2EE Container Authentication</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="#ldap">19. LDAP Authentication</a></span></dt><dd><dl><dt><span class="section"><a href="#ldap-overview">19.1. Overview</a></span></dt><dt><span class="section"><a href="#d0e6365">19.2. Using LDAP with Spring Security</a></span></dt><dt><span class="section"><a href="#ldap-server">19.3. Configuring an LDAP Server</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e6413">19.3.1. Using an Embedded Test Server</a></span></dt><dt><span class="section"><a href="#d0e6437">19.3.2. Using Bind Authentication</a></span></dt><dt><span class="section"><a href="#d0e6461">19.3.3. Loading Authorities</a></span></dt></dl></dd><dt><span class="section"><a href="#d0e6526">19.4. Implementation Classes</a></span></dt><dd><dl><dt><span class="section"><a href="#ldap-ldap-authenticators">19.4.1. LdapAuthenticator Implementations</a></span></dt><dt><span class="section"><a href="#ldap-context-source">19.4.2. Connecting to the LDAP Server</a></span></dt><dt><span class="section"><a href="#ldap-searchobjects">19.4.3. LDAP Search Objects</a></span></dt><dt><span class="section"><a href="#ldap-authorities">19.4.4. LdapAuthoritiesPopulator</a></span></dt><dt><span class="section"><a href="#ldap-bean-config">19.4.5. Spring Bean Configuration</a></span></dt><dt><span class="section"><a href="#ldap-custom-user-details">19.4.6. LDAP Attributes and Customized UserDetails</a></span></dt></dl></dd><dt><span class="section"><a href="#ldap-active-directory">19.5. Active Directory Authentication</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e6780">19.5.1. <code class="classname">ActiveDirectoryLdapAuthenticationProvider</code></a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="#taglibs">20. JSP Tag Libraries</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e6853">20.1. Declaring the Taglib</a></span></dt><dt><span class="section"><a href="#d0e6860">20.2. The <code class="literal">authorize</code> Tag</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e6911">20.2.1. Disabling Tag Authorization for Testing</a></span></dt></dl></dd><dt><span class="section"><a href="#d0e6945">20.3. The <code class="literal">authentication</code>Tag</a></span></dt><dt><span class="section"><a href="#d0e6976">20.4. The <code class="literal">accesscontrollist</code> Tag</a></span></dt></dl></dd><dt><span class="chapter"><a href="#jaas">21. Java Authentication and Authorization Service (JAAS) Provider</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e7027">21.1. Overview</a></span></dt><dt><span class="section"><a href="#jaas-abstractjaasauthenticationprovider">21.2. AbstractJaasAuthenticationProvider</a></span></dt><dd><dl><dt><span class="section"><a href="#jaas-callbackhandler">21.2.1. JAAS CallbackHandler</a></span></dt><dt><span class="section"><a href="#jaas-authoritygranter">21.2.2. JAAS AuthorityGranter</a></span></dt></dl></dd><dt><span class="section"><a href="#jaas-defaultjaasauthenticationprovider">21.3. DefaultJaasAuthenticationProvider</a></span></dt><dd><dl><dt><span class="section"><a href="#jaas-inmemoryconfiguration">21.3.1. InMemoryConfiguration</a></span></dt><dt><span class="section"><a href="#jaas-djap-config">21.3.2. DefaultJaasAuthenticationProvider Example Configuration</a></span></dt></dl></dd><dt><span class="section"><a href="#jaas-jaasauthenticationprovider">21.4. JaasAuthenticationProvider</a></span></dt><dt><span class="section"><a href="#jaas-apiprovision">21.5. Running as a Subject</a></span></dt></dl></dd><dt><span class="chapter"><a href="#cas">22. CAS Authentication</a></span></dt><dd><dl><dt><span class="section"><a href="#cas-overview">22.1. Overview</a></span></dt><dt><span class="section"><a href="#cas-how-it-works">22.2. How CAS Works</a></span></dt><dd><dl><dt><span class="section"><a href="#cas-sequence">22.2.1. Spring Security and CAS Interaction Sequence</a></span></dt></dl></dd><dt><span class="section"><a href="#cas-client">22.3. Configuration of CAS Client</a></span></dt><dd><dl><dt><span class="section"><a href="#cas-st">22.3.1. Service Ticket Authentication</a></span></dt><dt><span class="section"><a href="#cas-singlelogout">22.3.2. Single Logout</a></span></dt><dt><span class="section"><a href="#cas-pt-client">22.3.3. Authenticating to a Stateless Service with CAS</a></span></dt><dt><span class="section"><a href="#cas-pt">22.3.4. Proxy Ticket Authentication</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="#x509">23. X.509 Authentication</a></span></dt><dd><dl><dt><span class="section"><a href="#x509-overview">23.1. Overview</a></span></dt><dt><span class="section"><a href="#d0e8013">23.2. Adding X.509 Authentication to Your Web Application</a></span></dt><dt><span class="section"><a href="#x509-ssl-config">23.3. Setting up SSL in Tomcat</a></span></dt></dl></dd><dt><span class="chapter"><a href="#runas">24. Run-As Authentication Replacement</a></span></dt><dd><dl><dt><span class="section"><a href="#runas-overview">24.1. Overview</a></span></dt><dt><span class="section"><a href="#runas-config">24.2. Configuration</a></span></dt></dl></dd><dt><span class="chapter"><a href="#crypto">25. Spring Security Crypto Module</a></span></dt><dd><dl><dt><span class="section"><a href="#spring-security-crypto-introduction">25.1. Introduction</a></span></dt><dt><span class="section"><a href="#spring-security-crypto-encryption">25.2. Encryptors</a></span></dt><dd><dl><dt><span class="section"><a href="#spring-security-crypto-encryption-bytes">25.2.1. BytesEncryptor</a></span></dt><dt><span class="section"><a href="#spring-security-crypto-encryption-text">25.2.2. TextEncryptor</a></span></dt></dl></dd><dt><span class="section"><a href="#spring-security-crypto-keygenerators">25.3. Key Generators</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e8311">25.3.1. BytesKeyGenerator</a></span></dt><dt><span class="section"><a href="#d0e8329">25.3.2. StringKeyGenerator</a></span></dt></dl></dd><dt><span class="section"><a href="#spring-security-crypto-passwordencoders">25.4. Password Encoding</a></span></dt></dl></dd></dl></dd><dt><span class="appendix"><a href="#appendix-schema">A. Security Database Schema</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e8365">A.1. User Schema</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e8378">A.1.1. Group Authorities</a></span></dt></dl></dd><dt><span class="section"><a href="#d0e8399">A.2. Persistent Login (Remember-Me) Schema</a></span></dt><dt><span class="section"><a href="#dbschema-acl">A.3. ACL Schema</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e8463">A.3.1. Hypersonic SQL</a></span></dt><dt><span class="section"><a href="#d0e8470">A.3.2. PostgreSQL</a></span></dt></dl></dd></dl></dd><dt><span class="appendix"><a href="#appendix-namespace">B. The Security Namespace</a></span></dt><dd><dl><dt><span class="section"><a href="#nsa-web">B.1. Web Application Security</a></span></dt><dd><dl><dt><span class="section"><a href="#nsa-debug">B.1.1. <code class="literal"><debug></code></a></span></dt><dt><span class="section"><a href="#nsa-http">B.1.2. <code class="literal"><http></code></a></span></dt><dt><span class="section"><a href="#nsa-access-denied-handler">B.1.3. <code class="literal"><access-denied-handler></code></a></span></dt><dt><span class="section"><a href="#nsa-anonymous">B.1.4. <code class="literal"><anonymous></code></a></span></dt><dt><span class="section"><a href="#nsa-custom-filter">B.1.5. <code class="literal"><custom-filter></code></a></span></dt><dt><span class="section"><a href="#nsa-expression-handler">B.1.6. <code class="literal"><expression-handler></code></a></span></dt><dt><span class="section"><a href="#nsa-form-login">B.1.7. <code class="literal"><form-login></code></a></span></dt><dt><span class="section"><a href="#nsa-http-basic">B.1.8. <code class="literal"><http-basic></code></a></span></dt><dt><span class="section"><a href="#nsa-http-firewall">B.1.9. <code class="literal"><http-firewall></code> Element</a></span></dt><dt><span class="section"><a href="#nsa-intercept-url">B.1.10. <code class="literal"><intercept-url></code></a></span></dt><dt><span class="section"><a href="#nsa-jee">B.1.11. <code class="literal"><jee></code></a></span></dt><dt><span class="section"><a href="#nsa-logout">B.1.12. <code class="literal"><logout></code></a></span></dt><dt><span class="section"><a href="#nsa-openid-login">B.1.13. <code class="literal"><openid-login></code></a></span></dt><dt><span class="section"><a href="#nsa-attribute-exchange">B.1.14. <code class="literal"><attribute-exchange></code></a></span></dt><dt><span class="section"><a href="#nsa-openid-attribute">B.1.15. <code class="literal"><openid-attribute></code></a></span></dt><dt><span class="section"><a href="#nsa-port-mappings">B.1.16. <code class="literal"><port-mappings></code></a></span></dt><dt><span class="section"><a href="#nsa-port-mapping">B.1.17. <code class="literal"><port-mapping></code></a></span></dt><dt><span class="section"><a href="#nsa-remember-me">B.1.18. <code class="literal"><remember-me></code></a></span></dt><dt><span class="section"><a href="#nsa-request-cache">B.1.19. <code class="literal"><request-cache></code> Element</a></span></dt><dt><span class="section"><a href="#nsa-session-management">B.1.20. <code class="literal"><session-management></code></a></span></dt><dt><span class="section"><a href="#nsa-concurrency-control">B.1.21. <code class="literal"><concurrency-control></code></a></span></dt><dt><span class="section"><a href="#nsa-x509">B.1.22. <code class="literal"><x509></code></a></span></dt><dt><span class="section"><a href="#nsa-filter-chain-map">B.1.23. <code class="literal"><filter-chain-map></code></a></span></dt><dt><span class="section"><a href="#nsa-filter-chain">B.1.24. <code class="literal"><filter-chain></code></a></span></dt><dt><span class="section"><a href="#nsa-filter-invocation-definition-source">B.1.25. <code class="literal"><filter-invocation-definition-source></code></a></span></dt><dt><span class="section"><a href="#nsa-filter-security-metadata-source">B.1.26. <code class="literal"><filter-security-metadata-source></code></a></span></dt></dl></dd><dt><span class="section"><a href="#nsa-authentication">B.2. Authentication Services</a></span></dt><dd><dl><dt><span class="section"><a href="#nsa-authentication-manager">B.2.1. <code class="literal"><authentication-manager></code></a></span></dt><dt><span class="section"><a href="#nsa-authentication-provider">B.2.2. <code class="literal"><authentication-provider></code></a></span></dt><dt><span class="section"><a href="#nsa-jdbc-user-service">B.2.3. <code class="literal"><jdbc-user-service></code></a></span></dt><dt><span class="section"><a href="#nsa-password-encoder">B.2.4. <code class="literal"><password-encoder></code></a></span></dt><dt><span class="section"><a href="#nsa-salt-source">B.2.5. <code class="literal"><salt-source></code></a></span></dt><dt><span class="section"><a href="#nsa-user-service">B.2.6. <code class="literal"><user-service></code></a></span></dt><dt><span class="section"><a href="#nsa-user">B.2.7. <code class="literal"><user></code></a></span></dt></dl></dd><dt><span class="section"><a href="#nsa-method-security">B.3. Method Security</a></span></dt><dd><dl><dt><span class="section"><a href="#nsa-global-method-security">B.3.1. <code class="literal"><global-method-security></code></a></span></dt><dt><span class="section"><a href="#nsa-after-invocation-provider">B.3.2. <code class="literal"><after-invocation-provider></code></a></span></dt><dt><span class="section"><a href="#nsa-pre-post-annotation-handling">B.3.3. <code class="literal"><pre-post-annotation-handling></code></a></span></dt><dt><span class="section"><a href="#nsa-invocation-attribute-factory">B.3.4. <code class="literal"><invocation-attribute-factory></code></a></span></dt><dt><span class="section"><a href="#nsa-post-invocation-advice">B.3.5. <code class="literal"><post-invocation-advice></code></a></span></dt><dt><span class="section"><a href="#nsa-pre-invocation-advice">B.3.6. <code class="literal"><pre-invocation-advice></code></a></span></dt><dt><span class="section"><a href="#nsa-protect-pointcut">B.3.7. Securing Methods using <code class="literal"><protect-pointcut></code></a></span></dt><dt><span class="section"><a href="#nsa-intercept-methods">B.3.8. <code class="literal"><intercept-methods></code></a></span></dt><dt><span class="section"><a href="#nsa-method-security-metadata-source">B.3.9. <code class="literal"><method-security-metadata-source></code></a></span></dt><dt><span class="section"><a href="#nsa-protect">B.3.10. <code class="literal"><protect></code></a></span></dt></dl></dd><dt><span class="section"><a href="#nsa-ldap">B.4. LDAP Namespace Options</a></span></dt><dd><dl><dt><span class="section"><a href="#nsa-ldap-server">B.4.1. Defining the LDAP Server using the <code class="literal"><ldap-server></code>
+ Element</a></span></dt><dt><span class="section"><a href="#nsa-ldap-authentication-provider">B.4.2. <code class="literal"><ldap-authentication-provider></code></a></span></dt><dt><span class="section"><a href="#nsa-password-compare">B.4.3. <code class="literal"><password-compare></code></a></span></dt><dt><span class="section"><a href="#nsa-ldap-user-service">B.4.4. <code class="literal"><ldap-user-service></code></a></span></dt></dl></dd></dl></dd><dt><span class="appendix"><a href="#appendix-dependencies">C. Spring Security Dependencies</a></span></dt><dd><dl><dt><span class="section"><a href="#d0e11729">C.1. <code class="literal">spring-security-core</code></a></span></dt><dt><span class="section"><a href="#d0e11819">C.2. <code class="literal">spring-security-remoting</code></a></span></dt><dt><span class="section"><a href="#d0e11854">C.3. <code class="literal">spring-security-web</code></a></span></dt><dt><span class="section"><a href="#d0e11903">C.4. <code class="literal">spring-security-ldap</code></a></span></dt><dt><span class="section"><a href="#d0e11990">C.5. <code class="literal">spring-security-config</code></a></span></dt><dt><span class="section"><a href="#d0e12044">C.6. <code class="literal">spring-security-acl</code></a></span></dt><dt><span class="section"><a href="#d0e12094">C.7. <code class="literal">spring-security-cas</code></a></span></dt><dt><span class="section"><a href="#d0e12142">C.8. <code class="literal">spring-security-openid</code></a></span></dt><dt><span class="section"><a href="#d0e12196">C.9. <code class="literal">spring-security-taglibs</code></a></span></dt></dl></dd></dl></div><div class="preface" title="Preface"><div class="titlepage"><div><div><h2 class="title"><a name="preface"></a>Preface</h2></div></div></div><p>Spring Security provides a comprehensive security solution for J2EE-based enterprise
+ software applications. As you will discover as you venture through this reference guide,
+ we have tried to provide you a useful and highly configurable security system.</p><p>Security is an ever-moving target, and it's important to pursue a comprehensive,
+ system-wide approach. In security circles we encourage you to adopt "layers of
+ security", so that each layer tries to be as secure as possible in its own right, with
+ successive layers providing additional security. The "tighter" the security of each
+ layer, the more robust and safe your application will be. At the bottom level you'll
+ need to deal with issues such as transport security and system identification, in order
+ to mitigate man-in-the-middle attacks. Next you'll generally utilise firewalls, perhaps
+ with VPNs or IP security to ensure only authorised systems can attempt to connect. In
+ corporate environments you may deploy a DMZ to separate public-facing servers from
+ backend database and application servers. Your operating system will also play a
+ critical part, addressing issues such as running processes as non-privileged users and
+ maximising file system security. An operating system will usually also be configured
+ with its own firewall. Hopefully somewhere along the way you'll be trying to prevent
+ denial of service and brute force attacks against the system. An intrusion detection
+ system will also be especially useful for monitoring and responding to attacks, with
+ such systems able to take protective action such as blocking offending TCP/IP addresses
+ in real-time. Moving to the higher layers, your Java Virtual Machine will hopefully be
+ configured to minimize the permissions granted to different Java types, and then your
+ application will add its own problem domain-specific security configuration. Spring
+ Security makes this latter area - application security - much easier. </p><p>Of course, you will need to properly address all security layers mentioned above,
+ together with managerial factors that encompass every layer. A non-exhaustive list of
+ such managerial factors would include security bulletin monitoring, patching, personnel
+ vetting, audits, change control, engineering management systems, data backup, disaster
+ recovery, performance benchmarking, load monitoring, centralised logging, incident
+ response procedures etc.</p><p>With Spring Security being focused on helping you with the enterprise application
+ security layer, you will find that there are as many different requirements as there are
+ business problem domains. A banking application has different needs from an ecommerce
+ application. An ecommerce application has different needs from a corporate sales force
+ automation tool. These custom requirements make application security interesting,
+ challenging and rewarding. </p><p>Please read <a class="xref" href="#getting-started" title="Part I. Getting Started">Part I, “Getting Started”</a>, in its entirety to begin with. This
+ will introduce you to the framework and the namespace-based configuration system with
+ which you can get up and running quite quickly. To get more of an understanding of how
+ Spring Security works, and some of the classes you might need to use, you should then
+ read <a class="xref" href="#overall-architecture" title="Part II. Architecture and Implementation">Part II, “Architecture and Implementation”</a>. The remaining parts of this guide are
+ structured in a more traditional reference style, designed to be read on an as-required
+ basis. We'd also recommend that you read up as much as possible on application security
+ issues in general. Spring Security is not a panacea which will solve all security
+ issues. It is important that the application is designed with security in mind from the
+ start. Attempting to retrofit it is not a good idea. In particular, if you are building
+ a web application, you should be aware of the many potential vulnerabilities such as
+ cross-site scripting, request-forgery and session-hijacking which you should be taking
+ into account from the start. The OWASP web site (http://www.owasp.org/) maintains a top
+ ten list of web application vulnerabilities as well as a lot of useful reference
+ information. </p><p>We hope that you find this reference guide useful, and we welcome your feedback and
+ <a class="link" href="#jira" title="5.1 Issue Tracking">suggestions</a>. </p><p>Finally, welcome to the Spring Security <a class="link" href="#community" title="5. Spring Security Community">community</a>. </p></div><div class="part" title="Part I. Getting Started"><div class="titlepage"><div><div><h1 class="title"><a name="getting-started"></a>Part I. Getting Started</h1></div></div></div><div class="partintro" title="Getting Started"><div></div><p>The later parts of this guide provide an in-depth discussion of the framework
+ architecture and implementation classes, which you need to understand if you want to
+ do any serious customization. In this part, we'll introduce Spring Security 3.0,
+ give a brief overview of the project's history and take a slightly gentler look at
+ how to get started using the framework. In particular, we'll look at namespace
+ configuration which provides a much simpler way of securing your application
+ compared to the traditional Spring bean approach where you have to wire up all the
+ implementation classes individually. </p><p> We'll also take a look at the sample applications that are available. It's worth
+ trying to run these and experimenting with them a bit even before you read the later
+ sections - you can dip back into them as your understanding of the framework
+ increases. Please also check out the <a class="link" href="http://static.springsource.org/spring-security/site/index.html" target="_top">project website</a> as it has useful information on building the project,
+ plus links to articles, videos and tutorials. </p></div><div class="chapter" title="1. Introduction"><div class="titlepage"><div><div><h2 class="title"><a name="introduction"></a>1. Introduction</h2></div></div></div><div class="section" title="1.1 What is Spring Security?"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="what-is-acegi-security"></a>1.1 What is Spring Security?</h2></div></div></div><p>Spring Security provides comprehensive security services for J2EE-based enterprise
software applications. There is a particular emphasis on supporting projects built using
The Spring Framework, which is the leading J2EE solution for enterprise software
development. If you're not using Spring for developing enterprise applications, we
@@ -76,13 +84,13 @@ pageTracker._trackPageview();
reconfigure your application's security in the new target environment. Using Spring
Security overcomes these problems, and also brings you dozens of other useful,
customisable security features.</p><p>As you probably know two major areas of application security are
- <span class="quote">“<span class="quote">authentication</span>”</span> and <span class="quote">“<span class="quote">authorization</span>”</span> (or
- <span class="quote">“<span class="quote">access-control</span>”</span>). These are the two main areas that Spring Security
+ <span class="quote">“<span class="quote">authentication</span>”</span> and <span class="quote">“<span class="quote">authorization</span>”</span> (or
+ <span class="quote">“<span class="quote">access-control</span>”</span>). These are the two main areas that Spring Security
targets. <span class="quote">“<span class="quote">Authentication</span>”</span> is the process of establishing a principal is who
they claim to be (a <span class="quote">“<span class="quote">principal</span>”</span> generally means a user, device or some
other system which can perform an action in your application).
- <span class="quote">“<span class="quote">Authorization</span>”</span> refers to the process of deciding whether a principal
- is allowed to perform an action within your application. To arrive at the point where an
+ <span class="quote">“<span class="quote">Authorization</span>”</span> refers to the process of deciding whether a principal is
+ allowed to perform an action within your application. To arrive at the point where an
authorization decision is needed, the identity of the principal has already been
established by the authentication process. These concepts are common, and not at all
specific to Spring Security. </p><p>At an authentication level, Spring Security supports a wide range of authentication
@@ -90,16 +98,15 @@ pageTracker._trackPageview();
developed by relevant standards bodies such as the Internet Engineering Task Force. In
addition, Spring Security provides its own set of authentication features. Specifically,
Spring Security currently supports authentication integration with all of these
- technologies:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc" compact><li class="listitem"><p>HTTP BASIC authentication headers (an IEFT RFC-based standard)</p></li><li class="listitem"><p>HTTP Digest authentication headers (an IEFT RFC-based standard)</p></li><li class="listitem"><p>HTTP X.509 client certificate exchange (an IEFT RFC-based standard)</p></li><li class="listitem"><p>LDAP (a very common approach to cross-platform authentication needs,
+ technologies:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc" compact><li class="listitem"><p>HTTP BASIC authentication headers (an IETF RFC-based standard)</p></li><li class="listitem"><p>HTTP Digest authentication headers (an IETF RFC-based standard)</p></li><li class="listitem"><p>HTTP X.509 client certificate exchange (an IETF RFC-based standard)</p></li><li class="listitem"><p>LDAP (a very common approach to cross-platform authentication needs,
especially in large environments)</p></li><li class="listitem"><p>Form-based authentication (for simple user interface needs)</p></li><li class="listitem"><p>OpenID authentication</p></li><li class="listitem"><p>Authentication based on pre-established request headers (such as Computer
Associates Siteminder)</p></li><li class="listitem"><p>JA-SIG Central Authentication Service (otherwise known as CAS, which is a
- popular open source single sign on system)</p></li><li class="listitem"><p>Transparent authentication context propagation for Remote Method Invocation
+ popular open source single sign-on system)</p></li><li class="listitem"><p>Transparent authentication context propagation for Remote Method Invocation
(RMI) and HttpInvoker (a Spring remoting protocol)</p></li><li class="listitem"><p>Automatic "remember-me" authentication (so you can tick a box to avoid
- re-authentication for a predetermined period of time)</p></li><li class="listitem"><p>Anonymous authentication (allowing every call to automatically assume a
+ re-authentication for a predetermined period of time)</p></li><li class="listitem"><p>Anonymous authentication (allowing every unauthenticated call to automatically assume a
particular security identity)</p></li><li class="listitem"><p>Run-as authentication (which is useful if one call should proceed with a
different security identity)</p></li><li class="listitem"><p>Java Authentication and Authorization Service (JAAS)</p></li><li class="listitem"><p>JEE container autentication (so you can still use Container Managed
- Authentication if desired)</p></li><li class="listitem"><p>Kerberos</p></li><li class="listitem"><p>Java Open Source Single Sign On (JOSSO) *</p></li><li class="listitem"><p>OpenNMS Network Management Platform *</p></li><li class="listitem"><p>AppFuse *</p></li><li class="listitem"><p>AndroMDA *</p></li><li class="listitem"><p>Mule ESB *</p></li><li class="listitem"><p>Direct Web Request (DWR) *</p></li><li class="listitem"><p>Grails *</p></li><li class="listitem"><p>Tapestry *</p></li><li class="listitem"><p>JTrac *</p></li><li class="listitem"><p>Jasypt *</p></li><li class="listitem"><p>Roller *</p></li><li class="listitem"><p>Elastic Path *</p></li><li class="listitem"><p>Atlassian Crowd *</p></li><li class="listitem"><p>Your own authentication systems (see below)</p></li></ul></div><p>(* Denotes provided by a third party; check our <a class="link" href="http://acegisecurity.org/powering.html" target="_top">integration page</a> for
- links to the latest details)</p><p>Many independent software vendors (ISVs) adopt Spring Security because of this
+ Authentication if desired)</p></li><li class="listitem"><p>Kerberos</p></li><li class="listitem"><p>Java Open Source Single Sign On (JOSSO) *</p></li><li class="listitem"><p>OpenNMS Network Management Platform *</p></li><li class="listitem"><p>AppFuse *</p></li><li class="listitem"><p>AndroMDA *</p></li><li class="listitem"><p>Mule ESB *</p></li><li class="listitem"><p>Direct Web Request (DWR) *</p></li><li class="listitem"><p>Grails *</p></li><li class="listitem"><p>Tapestry *</p></li><li class="listitem"><p>JTrac *</p></li><li class="listitem"><p>Jasypt *</p></li><li class="listitem"><p>Roller *</p></li><li class="listitem"><p>Elastic Path *</p></li><li class="listitem"><p>Atlassian Crowd *</p></li><li class="listitem"><p>Your own authentication systems (see below)</p></li></ul></div><p>(* Denotes provided by a third party</p><p>Many independent software vendors (ISVs) adopt Spring Security because of this
significant choice of flexible authentication models. Doing so allows them to quickly
integrate their solutions with whatever their end clients need, without undertaking a
lot of engineering or requiring the client to change their environment. If none of the
@@ -107,22 +114,15 @@ pageTracker._trackPageview();
it is quite simple to write your own authentication mechanism. Many corporate users of
Spring Security need to integrate with "legacy" systems that don't follow any particular
security standards, and Spring Security is happy to "play nicely" with such
- systems.</p><p>Sometimes the mere process of authentication isn't enough. Sometimes you need to also
- differentiate security based on the way a principal is interacting with your
- application. For example, you might want to ensure requests only arrive over HTTPS, in
- order to protect passwords from eavesdropping or end users from man-in-the-middle
- attacks. This is especially helpful to protect password recovery processes from brute
- force attacks, or simply to make it harder for people to duplicate your application's
- key content. To help you achieve these goals, Spring Security fully supports automatic
- "channel security", together with JCaptcha integration for human user detection.</p><p>Irrespective of how authentication was undertaken, Spring Security provides a deep set
- of authorization capabilities. There are three main areas of interest in respect of
- authorization, these being authorizing web requests, authorizing whether methods can be
+ systems.</p><p>Irrespective of the authentication mechanism, Spring Security provides a deep set
+ of authorization capabilities. There are three main areas of interest
+ - authorizing web requests, authorizing whether methods can be
invoked, and authorizing access to individual domain object instances. To help you
understand the differences, consider the authorization capabilities found in the Servlet
Specification web pattern security, EJB Container Managed Security and file system
security respectively. Spring Security provides deep capabilities in all of these
important areas, which we'll explore later in this reference guide.</p></div><div class="section" title="1.2 History"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="history"></a>1.2 History</h2></div></div></div><p>Spring Security began in late 2003 as <span class="quote">“<span class="quote">The Acegi Security System for
- Spring</span>”</span>. A question was posed on the Spring Developers' mailing list asking
+ Spring</span>”</span>. A question was posed on the Spring Developers' mailing list asking
whether there had been any consideration given to a Spring-based security
implementation. At the time the Spring community was relatively small (especially
compared with the size today!), and indeed Spring itself had only existed as a
@@ -148,16 +148,17 @@ pageTracker._trackPageview();
core of developers who work on the code itself and an active community which also
regularly share patches and support their peers.</p></div><div class="section" title="1.3 Release Numbering"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="release-numbering"></a>1.3 Release Numbering</h2></div></div></div><p>It is useful to understand how Spring Security release numbers work, as it will help
you identify the effort (or lack thereof) involved in migrating to future releases of
- the project. Officially, we use the Apache Portable Runtime Project versioning
- guidelines, which can be viewed at
- <code class="literal">http://apr.apache.org/versioning.html</code>. We quote the introduction
- contained on that page for your convenience:</p><p><span class="quote">“<span class="quote">Versions are denoted using a standard triplet of integers: MAJOR.MINOR.PATCH.
- The basic intent is that MAJOR versions are incompatible, large-scale upgrades of
- the API. MINOR versions retain source and binary compatibility with older minor
- versions, and changes in the PATCH level are perfectly compatible, forwards and
- backwards.</span>”</span></p></div><div class="section" title="1.4 Getting Spring Security"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="get-spring-security"></a>1.4 Getting Spring Security</h2></div></div></div><p>You can get hold of Spring Security in several ways. You can download a packaged
- distribution from the main Spring <a class="link" href="http://www.springsource.com/download/community?project=Spring%20Security" target="_top">download page</a>, download individual jars (and sample WAR files) from the
- Maven Central repository (or a SpringSource Maven repository for snapshot and milestone
+ the project. Each release uses a standard triplet of integers: MAJOR.MINOR.PATCH. The
+ intent is that MAJOR versions are incompatible, large-scale upgrades of the API. MINOR
+ versions should largely retain source and binary compatibility with older minor
+ versions, thought there may be some design changes and incompatible udates. PATCH level
+ should be perfectly compatible, forwards and backwards, with the possible exception of
+ changes which are to fix bugs and defects.</p><p>The extent to which you are affected by changes will depend on how tightly integrated
+ your code is. If you are doing a lot of customization you are more likely to be affected
+ than if you are using a simple namespace configuration.</p><p>You should always test your application thoroughly before rolling out a new
+ version.</p></div><div class="section" title="1.4 Getting Spring Security"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="get-spring-security"></a>1.4 Getting Spring Security</h2></div></div></div><p>You can get hold of Spring Security in several ways. You can download a packaged
+ distribution from the main Spring <a class="link" href="http://www.springsource.com/download/community?project=Spring%20Security" target="_top">download page</a>, download individual jars (and sample WAR files) from the Maven
+ Central repository (or a SpringSource Maven repository for snapshot and milestone
releases) or, alternatively, you can build the project from source yourself. See the
project web site for more details. </p><div class="section" title="1.4.1 Project Modules"><div class="titlepage"><div><div><h3 class="title"><a name="modules"></a>1.4.1 Project Modules</h3></div></div></div><p>In Spring Security 3.0, the codebase has been sub-divided into separate jars which
more clearly separate different functionaltiy areas and third-party dependencies. If
@@ -168,20 +169,21 @@ pageTracker._trackPageview();
libraries that are included in the sample applications.</p><div class="section" title="Core - spring-security-core.jar"><div class="titlepage"><div><div><h4 class="title"><a name="spring-security-core"></a>Core - <code class="literal">spring-security-core.jar</code></h4></div></div></div><p>Contains core authentication and access-contol classes and interfaces,
remoting support and basic provisioning APIs. Required by any application which
uses Spring Security. Supports standalone applications, remote clients, method
- (service layer) security and JDBC user provisioning. Contains the top-level
- packages:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p><code class="literal">org.springframework.security.core</code></p></li><li class="listitem"><p><code class="literal">org.springframework.security.access</code></p></li><li class="listitem"><p><code class="literal">org.springframework.security.authentication</code></p></li><li class="listitem"><p><code class="literal">org.springframework.security.provisioning</code></p></li><li class="listitem"><p><code class="literal">org.springframework.security.remoting</code></p></li></ul></div></div><div class="section" title="Web - spring-security-web.jar"><div class="titlepage"><div><div><h4 class="title"><a name="spring-security-web"></a>Web - <code class="literal">spring-security-web.jar</code></h4></div></div></div><p>Contains filters and related web-security infrastructure code. Anything with a
+ (service layer) security and JDBC user provisioning. Contains the top-level packages:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p><code class="literal">org.springframework.security.core</code></p></li><li class="listitem"><p><code class="literal">org.springframework.security.access</code></p></li><li class="listitem"><p><code class="literal">org.springframework.security.authentication</code></p></li><li class="listitem"><p><code class="literal">org.springframework.security.provisioning</code></p></li></ul></div></div><div class="section" title="Remoting - spring-security-remoting.jar"><div class="titlepage"><div><div><h4 class="title"><a name="spring-security-remoting"></a>Remoting - <code class="literal">spring-security-remoting.jar</code></h4></div></div></div><p>Provides intergration with Spring Remoting. You don't need this unless you are
+ writing a remote client which uses Spring Remoting. The main package is
+ <code class="literal">org.springframework.security.remoting</code>.</p></div><div class="section" title="Web - spring-security-web.jar"><div class="titlepage"><div><div><h4 class="title"><a name="spring-security-web"></a>Web - <code class="literal">spring-security-web.jar</code></h4></div></div></div><p>Contains filters and related web-security infrastructure code. Anything with a
servlet API dependency. You'll need it if you require Spring Security web
authentication services and URL-based access-control. The main package is
- <code class="literal">org.springframework.security.web</code>.</p></div><div class="section" title="Config - spring-security-config.jar"><div class="titlepage"><div><div><h4 class="title"><a name="spring-security-config"></a>Config - <code class="literal">spring-security-config.jar</code></h4></div></div></div><p>Contains the security namespace parsing code (and hence nothing that you are
- likely yo use directly in your application). You need it if you are using the
+ <code class="literal">org.springframework.security.web</code>.</p></div><div class="section" title="Config - spring-security-config.jar"><div class="titlepage"><div><div><h4 class="title"><a name="spring-security-config"></a>Config - <code class="literal">spring-security-config.jar</code></h4></div></div></div><p>Contains the security namespace parsing code. You need it if you are using the
Spring Security XML namespace for configuration. The main package is
- <code class="literal">org.springframework.security.config</code>.</p></div><div class="section" title="LDAP - spring-security-ldap.jar"><div class="titlepage"><div><div><h4 class="title"><a name="spring-security-ldap"></a>LDAP - <code class="literal">spring-security-ldap.jar</code></h4></div></div></div><p>LDAP authentication and provisioning code. Required if you need to use LDAP
+ <code class="literal">org.springframework.security.config</code>. None of the
+ classes are intended for direct use in an application.</p></div><div class="section" title="LDAP - spring-security-ldap.jar"><div class="titlepage"><div><div><h4 class="title"><a name="spring-security-ldap"></a>LDAP - <code class="literal">spring-security-ldap.jar</code></h4></div></div></div><p>LDAP authentication and provisioning code. Required if you need to use LDAP
authentication or manage LDAP user entries. The top-level package is
- <code class="literal">org.springframework.security.ldap</code>.</p></div><div class="section" title="ACL - spring-security-acl.jar"><div class="titlepage"><div><div><h4 class="title"><a name="spring-security-acl"></a>ACL - <code class="literal">spring-security-acl.jar</code></h4></div></div></div><p>Specialized domain object ACL implementation. Used to apply security to
+ <code class="literal">org.springframework.security.ldap</code>.</p></div><div class="section" title="ACL - spring-security-acl.jar"><div class="titlepage"><div><div><h4 class="title"><a name="spring-security-acl"></a>ACL - <code class="literal">spring-security-acl.jar</code></h4></div></div></div><p>Specialized domain object ACL implementation. Used to apply security to
specific domain object instances within your application. The top-level package
- is <code class="literal">org.springframework.security.acls</code>.</p></div><div class="section" title="CAS - spring-security-cas-client.jar"><div class="titlepage"><div><div><h4 class="title"><a name="spring-security-cas"></a>CAS - <code class="literal">spring-security-cas-client.jar</code></h4></div></div></div><p>Spring Security's CAS client integration. If you want to use Spring Security
+ is <code class="literal">org.springframework.security.acls</code>.</p></div><div class="section" title="CAS - spring-security-cas.jar"><div class="titlepage"><div><div><h4 class="title"><a name="spring-security-cas"></a>CAS - <code class="literal">spring-security-cas.jar</code></h4></div></div></div><p>Spring Security's CAS client integration. If you want to use Spring Security
web authentication with a CAS single sign-on server. The top-level package is
- <code class="literal">org.springframework.security.cas</code>.</p></div><div class="section" title="OpenID - spring-security-openid.jar"><div class="titlepage"><div><div><h4 class="title"><a name="spring-security-openid"></a>OpenID - <code class="literal">spring-security-openid.jar</code></h4></div></div></div><p>OpenID web authentication support. Used to authenticate users against an
+ <code class="literal">org.springframework.security.cas</code>.</p></div><div class="section" title="OpenID - spring-security-openid.jar"><div class="titlepage"><div><div><h4 class="title"><a name="spring-security-openid"></a>OpenID - <code class="literal">spring-security-openid.jar</code></h4></div></div></div><p>OpenID web authentication support. Used to authenticate users against an
external OpenID server. <code class="literal">org.springframework.security.openid</code>.
Requires OpenID4Java.</p></div></div><div class="section" title="1.4.2 Checking out the Source"><div class="titlepage"><div><div><h3 class="title"><a name="get-source"></a>1.4.2 Checking out the Source</h3></div></div></div><p> Since Spring Security is an Open Source project, we'd strongly encourage you to
check out the source code using git. This will give you full access to all the
@@ -190,31 +192,42 @@ pageTracker._trackPageview();
stack traces are no longer obscure black-box issues but you can get straight to the
line that's causing the problem and work out what's happening. The source is the
ultimate documentation for a project and often the simplest place to find out how
- something actually works. </p><p>To obtain the source for the project trunk, use the following git command:
+ something actually works. </p><p>To obtain the source for the project, use the following git command:
</p><pre class="programlisting">
git clone git://git.springsource.org/spring-security/spring-security.git
</pre><p>
- You can checkout specific versions from
- <code class="literal">https://src.springframework.org/svn/spring-security/tags/</code>.
- </p></div></div></div><div class="chapter" title="2. Security Namespace Configuration"><div class="titlepage"><div><div><h1 class="title"><a name="ns-config"></a>Security Namespace Configuration</h1></div></div></div><div class="section" title="2.1 Introduction"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e344"></a>2.1 Introduction</h2></div></div></div><p> Namespace configuration has been available since version 2.0 of the Spring framework. It
- allows you to supplement the traditional Spring beans application context syntax with elements
- from additional XML schema. You can find more information in the Spring <a class="link" href="http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/htmlsingle/spring-framework-reference.htm" target="_top"> Reference Documentation</a>. A namespace element can be used simply to allow a more
- concise way of configuring an individual bean or, more powerfully, to define an alternative
- configuration syntax which more closely matches the problem domain and hides the underlying
- complexity from the user. A simple element may conceal the fact that multiple beans and
- processing steps are being added to the application context. For example, adding the following
- element from the security namespace to an application context will start up an embedded LDAP
- server for testing use within the application: </p><pre class="programlisting">
+ </p><p>This will give you access to the entire project history (including all releases
+ and branches) on your local machine.</p></div></div></div><div class="chapter" title="2. What's new in Spring Security 3.1"><div class="titlepage"><div><div><h1 class="title"><a name="new-3.1"></a>What's new in Spring Security 3.1</h1></div></div></div><p>This section contains summary of the updates found in Spring Security 3.1. A detailed list of changes can be found in the project's
+ <a class="link" href="https://jira.springsource.org/secure/IssueNavigator!executeAdvanced.jspa?jqlQuery=project+%3D+SEC+AND+fixVersion+in+%2812315%2C+11892%2C+11634%2C+11633%2C+11632%2C+11174%29+order+by+priority%2C+type&runQuery=true&clear=true" target="_top">JIRA</a></p><div class="section" title="2.1 High level updates found Spring Security 3.1"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="new-3.1-highlevel"></a>2.1 High level updates found Spring Security 3.1</h2></div></div></div><p>Below you can find a high level summary of updates to Spring Security 3.1.</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">Support for multiple http elements</li><li class="listitem">Support for stateless authentication</li><li class="listitem">DebugFilter provides additional debugging information</li><li class="listitem">Improved Active Directory LDAP support (i.e. ActiveDirectoryLdapAuthenticationProvider)</li><li class="listitem">Added Basic Crypto Module.</li><li class="listitem">The namespace is fully documented in the reference appendix.</li><li class="listitem">Added dependencies section to the reference appendix</li><li class="listitem">Support HttpOnly Flag for Cookies in Servlet 3.0 environments</li><li class="listitem">InMemoryUserDetailsManager provides in memory implementation of UserDetailsManager</li><li class="listitem">Support for hasPermission expression on the authorize JSP tag</li><li class="listitem">Support for disabling UI security (for testing purposes)</li><li class="listitem">Support erasing credentials after successful authentication</li><li class="listitem">Support clearing cookies on logout</li><li class="listitem">Spring Security Google App Engine example application</li><li class="listitem">Support for CAS proxy tickets</li><li class="listitem">Support for arbitrary implementations of JAAS Configuration</li><li class="listitem">Support nested switching of users for SwitchUserFilter</li></ul></div></div><div class="section" title="2.2 Spring Security 3.1 namespace updates"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="new-3.1-ns"></a>2.2 Spring Security 3.1 namespace updates</h2></div></div></div><p>Below you can find a summary of updates to the Spring Security 3.1 namespace.</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">Added support for multiple <a class="link" href="#nsa-http" title="B.1.2 <http>"><http></a> elements and support for determining which one to use with
+ <a class="link" href="#nsa-http-pattern" title="pattern">http at pattern</a>, <a class="link" href="#nsa-http-request-matcher" title="request-matcher">http at request-matcher</a>, and
+ <a class="link" href="#nsa-http-security" title="security">http at security</a>.
+ Further information can be found in <a class="link" href="#ns-config" title="3. Security Namespace Configuration">Namespace Configuration</a> section of the reference.</li><li class="listitem">Added stateless option for <a class="link" href="#nsa-http-create-session" title="create-session">http at create-session</a></li><li class="listitem">Added support for <a class="link" href="#nsa-http-authentication-manager-ref" title="authentication-manager-ref">http at authentication-manager-ref</a>
+ and <a class="link" href="#nsa-global-method-security-authentication-manager-ref" title="authentication-manager-ref">global-method-security at authentication-manager-ref</a>.</li><li class="listitem">Added <a class="link" href="#nsa-http-name" title="name">http at name</a></li><li class="listitem">Added <a class="link" href="#nsa-http-request-matcher-ref" title="request-matcher-ref">http at request-matcher-ref</a> and
+ <a class="link" href="#nsa-filter-chain-request-matcher-ref" title="request-matcher-ref">filter-chain at request-matcher-ref</a></li><li class="listitem">Added <a class="link" href="#nsa-debug" title="B.1.1 <debug>"><debug></a></li><li class="listitem">Added Support for setting the AuthenticationDetailsSource using the namespace. See
+ <a class="link" href="#nsa-form-login-authentication-details-source-ref" title="authentication-details-source-ref">form-login at authentication-details-source-ref</a>,
+ <a class="link" href="#nsa-openid-login-authentication-details-source-ref" title="authentication-details-source-ref">openid-login at authentication-details-source-ref</a>,
+ <a class="link" href="#nsa-http-basic-authentication-details-source-ref" title="authentication-details-source-ref">http-basic at authentication-details-source-ref</a>, and
+ <a class="link" href="#nsa-x509-authentication-details-source-ref" title="authentication-details-source-ref">x509 at authentication-details-source-ref</a>.</li><li class="listitem">Added support for http/expression-handler. This allows
+ <a class="link" href="#nsa-expression-handler" title="B.1.6 <expression-handler>"><expression-handler></a> to be used for web access expressions.</li><li class="listitem">Added <a class="link" href="#nsa-authentication-manager-erase-credentials" title="erase-credentials">authentication-manager at erase-credentials</a></li><li class="listitem">Added <a class="link" href="#nsa-http-basic-entry-point-ref" title="entry-point-ref">http-basic at entry-point-ref</a></li><li class="listitem">Added <a class="link" href="#nsa-logout-delete-cookies" title="The delete-cookies attribute">logout at delete-cookies</a></li><li class="listitem">Added <a class="link" href="#nsa-remember-me-authentication-success-handler-ref" title="authentication-success-handler-ref">remember-me at authentication-success-handler-ref</a></li><li class="listitem">Added <a class="link" href="#nsa-method-security-metadata-source" title="B.3.9 <method-security-metadata-source>"><metadata-source-ref></a></li><li class="listitem">Added <a class="link" href="#nsa-global-method-security-metadata-source-ref" title="<metadata-source-ref> Attribute">global-method-security at metadata-source-ref</a></li><li class="listitem">Added <a class="link" href="#nsa-global-method-security-mode" title="The mode Attribute">global-method-security at mode</a></li><li class="listitem">Added <a class="link" href="#nsa-attribute-exchange" title="B.1.14 <attribute-exchange>"><attribute-exchange></a></li><li class="listitem">Added <a class="link" href="#nsa-remember-me-use-secure-cookie" title="use-secure-cookie">remember-me at use-secure-cookie</a></li><li class="listitem">Added <a class="link" href="#nsa-http-jaas-api-provision" title="jaas-api-provision">http at jaas-api-provision</a></li><li class="listitem">Added <a class="link" href="#nsa-form-login-username-parameter" title="username-parameter">form-login at username-parameter</a> and
+ <a class="link" href="#nsa-form-login-password-parameter" title="password-parameter">form-login at password-parameter</a></li></ul></div></div></div><div class="chapter" title="3. Security Namespace Configuration"><div class="titlepage"><div><div><h1 class="title"><a name="ns-config"></a>Security Namespace Configuration</h1></div></div></div><div class="section" title="3.1 Introduction"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e507"></a>3.1 Introduction</h2></div></div></div><p> Namespace configuration has been available since version 2.0 of the Spring framework.
+ It allows you to supplement the traditional Spring beans application context syntax with
+ elements from additional XML schema. You can find more information in the Spring <a class="link" href="http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/htmlsingle/spring-framework-reference.html" target="_top"> Reference Documentation</a>. A namespace element can be used simply to allow a more
+ concise way of configuring an individual bean or, more powerfully, to define an
+ alternative configuration syntax which more closely matches the problem domain and hides
+ the underlying complexity from the user. A simple element may conceal the fact that
+ multiple beans and processing steps are being added to the application context. For
+ example, adding the following element from the security namespace to an application
+ context will start up an embedded LDAP server for testing use within the application: </p><pre class="programlisting">
<span class="hl-tag"><security:ldap-server /></span>
</pre><p> This is much simpler than wiring up the equivalent Apache Directory Server
- beans. The most common alternative configuration requirements are supported by attributes on
- the <code class="literal">ldap-server</code> element and the user is isolated from worrying about which
- beans they need to create and what the bean property names are. <sup>[<a name="d0e358" href="#ftn.d0e358" class="footnote">1</a>]</sup>. Use of a good XML editor while
- editing the application context file should provide information on the attributes and elements
- that are available. We would recommend that you try out the <a class="link" href="http://www.springsource.com/products/sts" target="_top">SpringSource Tool Suite</a> as it
- has special features for working with standard Spring namespaces. </p><p> To start using the security namespace in your application context, you first need to make
- sure that the <code class="literal">spring-security-config</code> jar is on your classpath. Then all you need to do is
- add the schema declaration to your application context file: </p><pre class="programlisting">
+ beans. The most common alternative configuration requirements are supported by
+ attributes on the <code class="literal">ldap-server</code> element and the user is isolated from
+ worrying about which beans they need to create and what the bean property names are. <sup>[<a name="d0e521" href="#ftn.d0e521" class="footnote">1</a>]</sup>. Use of a good XML editor while editing the application context file should
+ provide information on the attributes and elements that are available. We would
+ recommend that you try out the <a class="link" href="http://www.springsource.com/products/sts" target="_top">SpringSource Tool Suite</a> as
+ it has special features for working with standard Spring namespaces. </p><p> To start using the security namespace in your application context, you need to have
+ the <code class="literal">spring-security-config</code> jar on your classpath. Then all you need
+ to do is add the schema declaration to your application context file: </p><pre class="programlisting">
<span class="hl-tag"><beans</span> <span class="hl-attribute">xmlns</span>=<span class="hl-value">"http://www.springframework.org/schema/beans"</span>
<span class="hl-attribute">xmlns:security</span>=<span class="hl-value">"http://www.springframework.org/schema/security"</span>
@@ -222,52 +235,46 @@ pageTracker._trackPageview();
<span class="hl-attribute">xsi:schemaLocation</span>=<span class="hl-value">"http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
- http://www.springframework.org/schema/security/spring-security-3.0.3.xsd"</span><span class="hl-tag">></span>
+ http://www.springframework.org/schema/security/spring-security-3.1.xsd"</span><span class="hl-tag">></span>
...
<span class="hl-tag"></beans></span>
</pre><p> In many of the examples you will see (and in the sample) applications, we
- will often use "security" as the default namespace rather than "beans", which means we can
- omit the prefix on all the security namespace elements, making the content easier to read. You
- may also want to do this if you have your application context divided up into separate files
- and have most of your security configuration in one of them. Your security application context
- file would then start like this </p><pre class="programlisting">
+ will often use "security" as the default namespace rather than "beans", which means we
+ can omit the prefix on all the security namespace elements, making the content easier to
+ read. You may also want to do this if you have your application context divided up into
+ separate files and have most of your security configuration in one of them. Your
+ security application context file would then start like this </p><pre class="programlisting">
<span class="hl-tag"><beans:beans</span> <span class="hl-attribute">xmlns</span>=<span class="hl-value">"http://www.springframework.org/schema/security"</span>
<span class="hl-attribute">xmlns:beans</span>=<span class="hl-value">"http://www.springframework.org/schema/beans"</span>
<span class="hl-attribute">xmlns:xsi</span>=<span class="hl-value">"http://www.w3.org/2001/XMLSchema-instance"</span>
<span class="hl-attribute">xsi:schemaLocation</span>=<span class="hl-value">"http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
- http://www.springframework.org/schema/security/spring-security-3.0.3.xsd"</span><span class="hl-tag">></span>
+ http://www.springframework.org/schema/security/spring-security-3.1.xsd"</span><span class="hl-tag">></span>
...
<span class="hl-tag"></beans:beans></span>
-</pre><p> We'll assume this syntax is being used from now on in this chapter. </p><div class="section" title="2.1.1 Design of the Namespace"><div class="titlepage"><div><div><h3 class="title"><a name="d0e382"></a>2.1.1 Design of the Namespace</h3></div></div></div><p> The namespace is designed to capture the most common uses of the framework and provide
- a simplified and concise syntax for enabling them within an application. The design is based
- around the large-scale dependencies within the framework, and can be divided up into the
- following areas: </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>
- <span class="emphasis"><em>Web/HTTP Security</em></span> - the most complex part. Sets up the filters
- and related service beans used to apply the framework authentication mechanisms, to
- secure URLs, render login and error pages and much
- more.</p></li><li class="listitem"><p>
- <span class="emphasis"><em>Business Object (Method) Security</em></span> - options for securing the
- service layer.</p></li><li class="listitem"><p>
- <span class="emphasis"><em>AuthenticationManager</em></span> - handles authentication requests from
- other parts of the framework.</p></li><li class="listitem"><p>
- <span class="emphasis"><em>AccessDecisionManager</em></span> - provides access decisions for web and
- method security. A default one will be registered, but you can also choose to use a
- custom one, declared using normal Spring bean
- syntax.</p></li><li class="listitem"><p>
- <span class="emphasis"><em>AuthenticationProvider</em></span>s - mechanisms against which the
- authentication manager authenticates users. The namespace provides supports for
- several standard options and also a means of adding custom beans declared using a
- traditional syntax. </p></li><li class="listitem"><p>
- <span class="emphasis"><em>UserDetailsService</em></span> - closely related to authentication providers,
- but often also required by other beans.</p></li></ul></div><p>We'll see how to configure these in the following sections.</p></div></div><div class="section" title="2.2 Getting Started with Security Namespace Configuration"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ns-getting-started"></a>2.2 Getting Started with Security Namespace Configuration</h2></div></div></div><p> In this section, we'll look at how you can build up a namespace configuration to use some
- of the main features of the framework. Let's assume you initially want to get up and running
- as quickly as possible and add authentication support and access control to an existing web
- application, with a few test logins. Then we'll look at how to change over to authenticating
- against a database or other security repository. In later sections we'll introduce more
- advanced namespace configuration options. </p><div class="section" title="2.2.1 web.xml Configuration"><div class="titlepage"><div><div><h3 class="title"><a name="ns-web-xml"></a>2.2.1 <code class="literal">web.xml</code> Configuration</h3></div></div></div><p> The first thing you need to do is add the following filter declaration to your
- <code class="literal">web.xml</code> file: </p><pre class="programlisting">
+</pre><p> We'll assume this syntax is being used from now on in this chapter. </p><div class="section" title="3.1.1 Design of the Namespace"><div class="titlepage"><div><div><h3 class="title"><a name="d0e545"></a>3.1.1 Design of the Namespace</h3></div></div></div><p> The namespace is designed to capture the most common uses of the framework and
+ provide a simplified and concise syntax for enabling them within an application. The
+ design is based around the large-scale dependencies within the framework, and can be
+ divided up into the following areas: </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> <span class="emphasis"><em>Web/HTTP Security</em></span> - the most complex part. Sets up
+ the filters and related service beans used to apply the framework
+ authentication mechanisms, to secure URLs, render login and error pages and
+ much more.</p></li><li class="listitem"><p> <span class="emphasis"><em>Business Object (Method) Security</em></span> - options for
+ securing the service layer.</p></li><li class="listitem"><p> <span class="emphasis"><em>AuthenticationManager</em></span> - handles authentication
+ requests from other parts of the framework.</p></li><li class="listitem"><p> <span class="emphasis"><em>AccessDecisionManager</em></span> - provides access decisions
+ for web and method security. A default one will be registered, but you can
+ also choose to use a custom one, declared using normal Spring bean
+ syntax.</p></li><li class="listitem"><p> <span class="emphasis"><em>AuthenticationProvider</em></span>s - mechanisms against which
+ the authentication manager authenticates users. The namespace provides
+ supports for several standard options and also a means of adding custom
+ beans declared using a traditional syntax. </p></li><li class="listitem"><p> <span class="emphasis"><em>UserDetailsService</em></span> - closely related to
+ authentication providers, but often also required by other beans.</p></li></ul></div><p>We'll see how to configure these in the following sections.</p></div></div><div class="section" title="3.2 Getting Started with Security Namespace Configuration"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ns-getting-started"></a>3.2 Getting Started with Security Namespace Configuration</h2></div></div></div><p> In this section, we'll look at how you can build up a namespace configuration to use
+ some of the main features of the framework. Let's assume you initially want to get up
+ and running as quickly as possible and add authentication support and access control to
+ an existing web application, with a few test logins. Then we'll look at how to change
+ over to authenticating against a database or other security repository. In later
+ sections we'll introduce more advanced namespace configuration options. </p><div class="section" title="3.2.1 web.xml Configuration"><div class="titlepage"><div><div><h3 class="title"><a name="ns-web-xml"></a>3.2.1 <code class="literal">web.xml</code> Configuration</h3></div></div></div><p> The first thing you need to do is add the following filter declaration to your
+ <code class="literal">web.xml</code> file: </p><pre class="programlisting">
<span class="hl-tag"><filter></span>
<span class="hl-tag"><filter-name></span>springSecurityFilterChain<span class="hl-tag"></filter-name></span>
<span class="hl-tag"><filter-class></span>org.springframework.web.filter.DelegatingFilterProxy<span class="hl-tag"></filter-class></span>
@@ -278,37 +285,40 @@ pageTracker._trackPageview();
<span class="hl-tag"><url-pattern></span>/*<span class="hl-tag"></url-pattern></span>
<span class="hl-tag"></filter-mapping></span>
</pre><p> This provides a hook into the Spring Security web
- infrastructure. <code class="classname">DelegatingFilterProxy</code> is a Spring Framework class
- which delegates to a filter implementation which is defined as a Spring bean in your
- application context. In this case, the bean is named
- <span class="quote">“<span class="quote">springSecurityFilterChain</span>”</span>, which is an internal infrastructure bean created
- by the namespace to handle web security. Note that you should not use this bean name
- yourself. Once you've added this to your <code class="filename">web.xml</code>, you're ready to start
- editing your application context file. Web security services are configured using the
- <code class="literal"><http></code> element. </p></div><div class="section" title="2.2.2 A Minimal <http> Configuration"><div class="titlepage"><div><div><h3 class="title"><a name="ns-minimal"></a>2.2.2 A Minimal <code class="literal"><http></code> Configuration</h3></div></div></div><p> All you need to enable web security to begin with is </p><pre class="programlisting">
+ infrastructure. <code class="classname">DelegatingFilterProxy</code> is a Spring Framework
+ class which delegates to a filter implementation which is defined as a Spring bean
+ in your application context. In this case, the bean is named
+ <span class="quote">“<span class="quote">springSecurityFilterChain</span>”</span>, which is an internal infrastructure bean
+ created by the namespace to handle web security. Note that you should not use this
+ bean name yourself. Once you've added this to your <code class="filename">web.xml</code>,
+ you're ready to start editing your application context file. Web security services
+ are configured using the <code class="literal"><http></code> element. </p></div><div class="section" title="3.2.2 A Minimal <http> Configuration"><div class="titlepage"><div><div><h3 class="title"><a name="ns-minimal"></a>3.2.2 A Minimal <code class="literal"><http></code> Configuration</h3></div></div></div><p> All you need to enable web security to begin with is </p><pre class="programlisting">
<span class="hl-tag"><http</span> <span class="hl-attribute">auto-config</span>=<span class="hl-value">'true'</span><span class="hl-tag">></span>
<span class="hl-tag"><intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/**"</span> <span class="hl-attribute">access</span>=<span class="hl-value">"ROLE_USER"</span><span class="hl-tag"> /></span>
<span class="hl-tag"></http></span>
</pre><p> Which says that we want all URLs within our application to be secured,
- requiring the role <code class="literal">ROLE_USER</code> to access them. The
- <code class="literal"><http></code> element is the parent for all web-related namespace
- functionality. The <code class="literal"><intercept-url></code> element defines a
- <code class="literal">pattern</code> which is matched against the URLs of incoming requests using an
- ant path style syntax<sup>[<a name="d0e480" href="#ftn.d0e480" class="footnote">2</a>]</sup>. The <code class="literal">access</code> attribute defines the access
- requirements for requests matching the given pattern. With the default configuration, this
- is typically a comma-separated list of roles, one of which a user must have to be allowed to
- make the request. The prefix <span class="quote">“<span class="quote">ROLE_</span>”</span> is a marker which indicates that a simple
- comparison with the user's authorities should be made. In other words, a normal role-based
- check should be used. Access-control in Spring Security is not limited to the use of simple
- roles (hence the use of the prefix to differentiate between different types of security
- attributes). We'll see later how the interpretation can vary<sup>[<a name="d0e493" href="#ftn.d0e493" class="footnote">3</a>]</sup>.</p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>You can use multiple <code class="literal"><intercept-url></code> elements to define
- different access requirements for different sets of URLs, but they will be evaluated in
- the order listed and the first match will be used. So you must put the most specific
- matches at the top. You can also add a <code class="literal">method</code> attribute to limit the
- match to a particular HTTP method (<code class="literal">GET</code>, <code class="literal">POST</code>,
- <code class="literal">PUT</code> etc.). If a request matches multiple patterns, the
- method-specific match will take precedence regardless of ordering.</p></td></tr></table></div><p> To add some users, you can define a set of test data directly in the namespace: </p><pre class="programlisting">
+ requiring the role <code class="literal">ROLE_USER</code> to access them. The
+ <code class="literal"><http></code> element is the parent for all web-related namespace
+ functionality. The <code class="literal"><intercept-url></code> element defines a
+ <code class="literal">pattern</code> which is matched against the URLs of incoming requests
+ using an ant path style syntax<sup>[<a name="d0e643" href="#ftn.d0e643" class="footnote">2</a>]</sup>. You can also use regular-expression matching as an alternative (see the
+ namespace appendix for more details). The <code class="literal">access</code> attribute
+ defines the access requirements for requests matching the given pattern. With the
+ default configuration, this is typically a comma-separated list of roles, one of
+ which a user must have to be allowed to make the request. The prefix
+ <span class="quote">“<span class="quote">ROLE_</span>”</span> is a marker which indicates that a simple comparison with the
+ user's authorities should be made. In other words, a normal role-based check should
+ be used. Access-control in Spring Security is not limited to the use of simple roles
+ (hence the use of the prefix to differentiate between different types of security
+ attributes). We'll see later how the interpretation can vary<sup>[<a name="d0e656" href="#ftn.d0e656" class="footnote">3</a>]</sup>.</p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>You can use multiple <code class="literal"><intercept-url></code> elements to
+ define different access requirements for different sets of URLs, but they will
+ be evaluated in the order listed and the first match will be used. So you must
+ put the most specific matches at the top. You can also add a
+ <code class="literal">method</code> attribute to limit the match to a particular HTTP
+ method (<code class="literal">GET</code>, <code class="literal">POST</code>, <code class="literal">PUT</code>
+ etc.). If a request matches multiple patterns, the method-specific match will
+ take precedence regardless of ordering.</p></td></tr></table></div><p> To add some users, you can define a set of test data directly in the namespace: </p><pre class="programlisting">
<span class="hl-tag"><authentication-manager></span>
<span class="hl-tag"><authentication-provider></span>
<span class="hl-tag"><user-service></span>
@@ -318,107 +328,132 @@ pageTracker._trackPageview();
<span class="hl-tag"></authentication-provider></span>
<span class="hl-tag"></authentication-manager></span>
- </pre><div class="sidebar"><p class="title"><b></b></p><p>If you are familiar with pre-namespace versions of the framework, you can probably
- already guess roughly what's going on here. The <code class="literal"><http></code> element is
- responsible for creating a <code class="classname">FilterChainProxy</code> and the filter beans
- which it uses. Common problems like incorrect filter ordering are no longer an issue as
- the filter positions are predefined.</p><p>The <code class="literal"><authentication-provider></code> element creates a
- <code class="classname">DaoAuthenticationProvider</code> bean and the
- <code class="literal"><user-service></code> element creates an
- <code class="classname">InMemoryDaoImpl</code>. All <code class="literal">authentication-provider</code>
- elements must be children of the <code class="literal"><authentication-manager></code> element,
- which creates a <code class="classname">ProviderManager</code> and registers the authentication
- providers with it. You can find more detailed information on the beans that are created in
- the <a class="link" href="#appendix-namespace" title="Appendix B. The Security Namespace">namespace appendix</a>. It's worth
- cross-checking this if you want to start understanding what the important classes in the
- framework are and how they are used, particularly if you want to customise things
- later.</p></div><p> The configuration above defines two users, their passwords and their roles within the
- application (which will be used for access control). It is also possible to load user
- information from a standard properties file using the <code class="literal">properties</code>
- attribute on <code class="literal">user-service</code>. See the section on <a class="link" href="#core-services-in-memory-service" title="6.2.1 In-Memory Authentication">in-memory authentication</a> for more
- details on the file format. Using the <code class="literal"><authentication-provider></code>
- element means that the user information will be used by the authentication manager to
- process authentication requests. You can have multiple
- <code class="literal"><authentication-provider></code> elements to define different
- authentication sources and each will be consulted in turn.</p><p> At this point you should be able to start up your application and you will be required
- to log in to proceed. Try it out, or try experimenting with the <span class="quote">“<span class="quote">tutorial</span>”</span>
- sample application that comes with the project. The above configuration actually adds quite
- a few services to the application because we have used the <code class="literal">auto-config</code>
- attribute. For example, form-based login processing is automatically enabled. </p><div class="section" title="What does auto-config Include?"><div class="titlepage"><div><div><h4 class="title"><a name="ns-auto-config"></a>What does <code class="literal">auto-config</code> Include?</h4></div></div></div><p> The <code class="literal">auto-config</code> attribute, as we have used it above, is just a
- shorthand syntax for: </p><pre class="programlisting">
+ </pre><div class="sidebar"><p class="title"><b></b></p><p>If you are familiar with pre-namespace versions of the framework, you can
+ probably already guess roughly what's going on here. The
+ <code class="literal"><http></code> element is responsible for creating a
+ <code class="classname">FilterChainProxy</code> and the filter beans which it uses.
+ Common problems like incorrect filter ordering are no longer an issue as the
+ filter positions are predefined.</p><p>The <code class="literal"><authentication-provider></code> element creates a
+ <code class="classname">DaoAuthenticationProvider</code> bean and the
+ <code class="literal"><user-service></code> element creates an
+ <code class="classname">InMemoryDaoImpl</code>. All
+ <code class="literal">authentication-provider</code> elements must be children of the
+ <code class="literal"><authentication-manager></code> element, which creates a
+ <code class="classname">ProviderManager</code> and registers the authentication
+ providers with it. You can find more detailed information on the beans that are
+ created in the <a class="link" href="#appendix-namespace" title="Appendix B. The Security Namespace">namespace appendix</a>.
+ It's worth cross-checking this if you want to start understanding what the
+ important classes in the framework are and how they are used, particularly if
+ you want to customise things later.</p></div><p> The configuration above defines two users, their passwords and their roles within
+ the application (which will be used for access control). It is also possible to load
+ user information from a standard properties file using the
+ <code class="literal">properties</code> attribute on <code class="literal">user-service</code>. See the
+ section on <a class="link" href="#core-services-in-memory-service" title="7.2.1 In-Memory Authentication">in-memory
+ authentication</a> for more details on the file format. Using the
+ <code class="literal"><authentication-provider></code> element means that the user
+ information will be used by the authentication manager to process authentication
+ requests. You can have multiple <code class="literal"><authentication-provider></code>
+ elements to define different authentication sources and each will be consulted in
+ turn.</p><p> At this point you should be able to start up your application and you will be
+ required to log in to proceed. Try it out, or try experimenting with the
+ <span class="quote">“<span class="quote">tutorial</span>”</span> sample application that comes with the project. The above
+ configuration actually adds quite a few services to the application because we have
+ used the <code class="literal">auto-config</code> attribute. For example, form-based login
+ processing is automatically enabled. </p><div class="section" title="What does auto-config Include?"><div class="titlepage"><div><div><h4 class="title"><a name="ns-auto-config"></a>What does <code class="literal">auto-config</code> Include?</h4></div></div></div><p> The <code class="literal">auto-config</code> attribute, as we have used it above, is
+ just a shorthand syntax for: </p><pre class="programlisting">
<span class="hl-tag"><http></span>
<span class="hl-tag"><form-login /></span>
<span class="hl-tag"><http-basic /></span>
<span class="hl-tag"><logout /></span>
<span class="hl-tag"></http></span>
</pre><p> These other elements are responsible for setting up form-login, basic
- authentication and logout handling services respectively <sup>[<a name="d0e602" href="#ftn.d0e602" class="footnote">4</a>]</sup> . They each have attributes which can be used to alter
- their behaviour. </p></div><div class="section" title="Form and Basic Login Options"><div class="titlepage"><div><div><h4 class="title"><a name="ns-form-and-basic"></a>Form and Basic Login Options</h4></div></div></div><p> You might be wondering where the login form came from when you were prompted to log
- in, since we made no mention of any HTML files or JSPs. In fact, since we didn't
- explicitly set a URL for the login page, Spring Security generates one automatically,
- based on the features that are enabled and using standard values for the URL which
- processes the submitted login, the default target URL the user will be sent to after
- loggin in and so on. However, the namespace offers plenty of support to allow you to
- customize these options. For example, if you want to supply your own login page, you could
- use: </p><pre class="programlisting">
+ authentication and logout handling services respectively <sup>[<a name="d0e765" href="#ftn.d0e765" class="footnote">4</a>]</sup>. They each have attributes which can be used to alter their
+ behaviour. In anything other than very basic scenarios, it is probably better to
+ omit the <code class="literal">auto-config</code> attribute and configure what you require
+ explicitly in the interest of clarity.</p></div></div><div class="section" title="3.2.3 Form and Basic Login Options"><div class="titlepage"><div><div><h3 class="title"><a name="ns-form-and-basic"></a>3.2.3 Form and Basic Login Options</h3></div></div></div><p> You might be wondering where the login form came from when you were prompted to
+ log in, since we made no mention of any HTML files or JSPs. In fact, since we didn't
+ explicitly set a URL for the login page, Spring Security generates one
+ automatically, based on the features that are enabled and using standard values for
+ the URL which processes the submitted login, the default target URL the user will be
+ sent to after loggin in and so on. However, the namespace offers plenty of support
+ to allow you to customize these options. For example, if you want to supply your own
+ login page, you could use: </p><pre class="programlisting">
<span class="hl-tag"><http</span> <span class="hl-attribute">auto-config</span>=<span class="hl-value">'true'</span><span class="hl-tag">></span>
<span class="hl-tag"><intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/login.jsp*"</span> <span class="hl-attribute">access</span>=<span class="hl-value">"IS_AUTHENTICATED_ANONYMOUSLY"</span><span class="hl-tag">/></span>
<span class="hl-tag"><intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/**"</span> <span class="hl-attribute">access</span>=<span class="hl-value">"ROLE_USER"</span><span class="hl-tag"> /></span>
<span class="hl-tag"><form-login</span> <span class="hl-attribute">login-page</span>=<span class="hl-value">'/login.jsp'</span><span class="hl-tag">/></span>
<span class="hl-tag"></http></span>
- </pre><p> Note that you can still use <code class="literal">auto-config</code>. The
- <code class="literal">form-login</code> element just overrides the default settings. Also note
- that we've added an extra <code class="literal">intercept-url</code> element to say that any
- requests for the login page should be available to anonymous users <sup>[<a name="d0e635" href="#ftn.d0e635" class="footnote">5</a>]</sup>. Otherwise the request would be matched by the pattern
- <code class="literal">/**</code> and it wouldn't be possible to access the login page itself! This
- is a common configuration error and will result in an infinite loop in the application.
- Spring Security will emit a warning in the log if your login page appears to be secured.
- It is also possible to have all requests matching a particular pattern bypass the security
- filter chain completely: </p><pre class="programlisting">
+ </pre><p> Note that you can still use <code class="literal">auto-config</code>. The
+ <code class="literal">form-login</code> element just overrides the default settings. Also note
+ that we've added an extra <code class="literal">intercept-url</code> element to say that any
+ requests for the login page should be available to anonymous users <sup>[<a name="d0e801" href="#ftn.d0e801" class="footnote">5</a>]</sup>. Otherwise the request would be matched by the pattern
+ <code class="literal">/**</code> and it wouldn't be possible to access the login page itself!
+ This is a common configuration error and will result in an infinite loop in the
+ application. Spring Security will emit a warning in the log if your login page
+ appears to be secured. It is also possible to have all requests matching a
+ particular pattern bypass the security filter chain completely, by defining a
+ separate <code class="literal">http</code> element for the pattern like this: </p><pre class="programlisting">
+ <span class="hl-tag"><http</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/css/**"</span> <span class="hl-attribute">security</span>=<span class="hl-value">"none"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><http</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/login.jsp*"</span> <span class="hl-attribute">security</span>=<span class="hl-value">"none"</span><span class="hl-tag">/></span>
+
<span class="hl-tag"><http</span> <span class="hl-attribute">auto-config</span>=<span class="hl-value">'true'</span><span class="hl-tag">></span>
- <span class="hl-tag"><intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/css/**"</span> <span class="hl-attribute">filters</span>=<span class="hl-value">"none"</span><span class="hl-tag">/></span>
- <span class="hl-tag"><intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/login.jsp*"</span> <span class="hl-attribute">filters</span>=<span class="hl-value">"none"</span><span class="hl-tag">/></span>
<span class="hl-tag"><intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/**"</span> <span class="hl-attribute">access</span>=<span class="hl-value">"ROLE_USER"</span><span class="hl-tag"> /></span>
<span class="hl-tag"><form-login</span> <span class="hl-attribute">login-page</span>=<span class="hl-value">'/login.jsp'</span><span class="hl-tag">/></span>
<span class="hl-tag"></http></span>
- </pre><p>It's important to realise that these requests will be completely
- oblivious to any further Spring Security web-related configuration or additional
- attributes such as <code class="literal">requires-channel</code>, so you will not be able to access
- information on the current user or call secured methods during the request. Use
- <code class="literal">access='IS_AUTHENTICATED_ANONYMOUSLY'</code> as an alternative if you still
- want the security filter chain to be applied.</p><p>If you want to use basic authentication instead of form login, then change the
- configuration to </p><pre class="programlisting">
+ </pre><p> From Spring Security 3.1 it is now possible to use multiple
+ <code class="literal">http</code> elements to define separate security filter chain
+ configurations for different request patterns. If the <code class="literal">pattern</code>
+ attribute is omitted from an <code class="literal">http</code> element, it matches all
+ requests. Creating an unsecured pattern is a simple example of this syntax, where
+ the pattern is mapped to an empty filter chain <sup>[<a name="d0e832" href="#ftn.d0e832" class="footnote">6</a>]</sup>. We'll look at this new syntax in more detail in the chapter on the
+ <a class="link" href="#filter-chains-with-ns" title="8.6 Advanced Namespace Configuration">Security Filter Chain</a>. </p><p> It's important to realise that these unsecured requests will be completely
+ oblivious to any Spring Security web-related configuration or additional attributes
+ such as <code class="literal">requires-channel</code>, so you will not be able to access
+ information on the current user or call secured methods during the request. Use
+ <code class="literal">access='IS_AUTHENTICATED_ANONYMOUSLY'</code> as an alternative if you
+ still want the security filter chain to be applied.</p><p>If you want to use basic authentication instead of form login, then change the
+ configuration to </p><pre class="programlisting">
<span class="hl-tag"><http</span> <span class="hl-attribute">auto-config</span>=<span class="hl-value">'true'</span><span class="hl-tag">></span>
<span class="hl-tag"><intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/**"</span> <span class="hl-attribute">access</span>=<span class="hl-value">"ROLE_USER"</span><span class="hl-tag"> /></span>
<span class="hl-tag"><http-basic /></span>
<span class="hl-tag"></http></span>
- </pre><p> Basic authentication will then take precedence and will be used to
- prompt for a login when a user attempts to access a protected resource. Form login is
- still available in this configuration if you wish to use it, for example through a login
- form embedded in another web page. </p><div class="section" title="Setting a Default Post-Login Destination"><div class="titlepage"><div><div><h5 class="title"><a name="ns-form-target"></a>Setting a Default Post-Login Destination</h5></div></div></div><p> If a form login isn't prompted by an attempt to access a protected resource, the
- <code class="literal">default-target-url</code> option comes into play. This is the URL the user
- will be taken to after logging in, and defaults to "/". You can also configure things so
- that they user <span class="emphasis"><em>always</em></span> ends up at this page (regardless of whether
- the login was "on-demand" or they explicitly chose to log in) by setting the
- <code class="literal">always-use-default-target</code> attribute to "true". This is useful if
- your application always requires that the user starts at a "home" page, for example: </p><pre class="programlisting">
+ </pre><p> Basic authentication will then take precedence and will be used to
+ prompt for a login when a user attempts to access a protected resource. Form login
+ is still available in this configuration if you wish to use it, for example through
+ a login form embedded in another web page. </p><div class="section" title="Setting a Default Post-Login Destination"><div class="titlepage"><div><div><h4 class="title"><a name="ns-form-target"></a>Setting a Default Post-Login Destination</h4></div></div></div><p> If a form login isn't prompted by an attempt to access a protected resource,
+ the <code class="literal">default-target-url</code> option comes into play. This is the
+ URL the user will be taken to after successfully logging in, and defaults to
+ "/". You can also configure things so that the user <span class="emphasis"><em>always</em></span>
+ ends up at this page (regardless of whether the login was "on-demand" or they
+ explicitly chose to log in) by setting the
+ <code class="literal">always-use-default-target</code> attribute to "true". This is useful
+ if your application always requires that the user starts at a "home" page, for
+ example: </p><pre class="programlisting">
+ <span class="hl-tag"><http</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/login.htm*"</span> <span class="hl-attribute">security</span>=<span class="hl-value">"none"</span><span class="hl-tag">/></span>
<span class="hl-tag"><http></span>
- <span class="hl-tag"><intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">'/login.htm*'</span> <span class="hl-attribute">filters</span>=<span class="hl-value">'none'</span><span class="hl-tag">/></span>
<span class="hl-tag"><intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">'/**'</span> <span class="hl-attribute">access</span>=<span class="hl-value">'ROLE_USER'</span><span class="hl-tag"> /></span>
<span class="hl-tag"><form-login</span> <span class="hl-attribute">login-page</span>=<span class="hl-value">'/login.htm'</span> <span class="hl-attribute">default-target-url</span>=<span class="hl-value">'/home.htm'</span>
<span class="hl-attribute">always-use-default-target</span>=<span class="hl-value">'true'</span><span class="hl-tag"> /></span>
<span class="hl-tag"></http></span>
-
- </pre></div></div></div><div class="section" title="2.2.3 Using other Authentication Providers"><div class="titlepage"><div><div><h3 class="title"><a name="ns-auth-providers"></a>2.2.3 Using other Authentication Providers</h3></div></div></div><p> In practice you will need a more scalable source of user information than a few names
- added to the application context file. Most likely you will want to store your user
- information in something like a database or an LDAP server. LDAP namespace configuration is
- dealt with in the <a class="link" href="#ldap" title="18. LDAP Authentication">LDAP chapter</a>, so we won't cover it here.
- If you have a custom implementation of Spring Security's
- <code class="classname">UserDetailsService</code>, called "myUserDetailsService" in your
- application context, then you can authenticate against this using </p><pre class="programlisting">
+ </pre><p>For even more control over the destination, you can use the
+ <code class="literal">authentication-success-handler-ref</code> attribute as an
+ alternative to <code class="literal">default-target-url</code>. The referenced bean should
+ be an instance of <code class="interfacename">AuthenticationSuccessHandler</code>.
+ You'll find more on this in the <a class="link" href="#form-login-flow-handling" title="9.4.1 Application Flow on Authentication Success and Failure">Core Filters</a> chapter and also in the namespace appendix, as well as
+ information on how to customize the flow when authentication fails. </p></div></div><div class="section" title="3.2.4 Logout Handling"><div class="titlepage"><div><div><h3 class="title"><a name="ns-logout"></a>3.2.4 Logout Handling</h3></div></div></div><p>The <code class="literal">logout</code> element adds support for logging out by navigating
+ to a particular URL. The default logout URL is <code class="literal">/j_spring_security_logout</code>,
+ but you can set it to something else using the <code class="literal">logout-url</code> attribute.
+ More information on other available attributes may be found in the namespace appendix.
+ </p></div><div class="section" title="3.2.5 Using other Authentication Providers"><div class="titlepage"><div><div><h3 class="title"><a name="ns-auth-providers"></a>3.2.5 Using other Authentication Providers</h3></div></div></div><p> In practice you will need a more scalable source of user information than a few
+ names added to the application context file. Most likely you will want to store your
+ user information in something like a database or an LDAP server. LDAP namespace
+ configuration is dealt with in the <a class="link" href="#ldap" title="19. LDAP Authentication">LDAP chapter</a>, so
+ we won't cover it here. If you have a custom implementation of Spring Security's
+ <code class="classname">UserDetailsService</code>, called "myUserDetailsService" in your
+ application context, then you can authenticate against this using </p><pre class="programlisting">
<span class="hl-tag"><authentication-manager></span>
<span class="hl-tag"><authentication-provider</span> <span class="hl-attribute">user-service-ref</span>=<span class="hl-value">'myUserDetailsService'</span><span class="hl-tag">/></span>
<span class="hl-tag"></authentication-manager></span>
@@ -431,11 +466,10 @@ pageTracker._trackPageview();
<span class="hl-tag"></authentication-manager></span>
</pre><p> Where <span class="quote">“<span class="quote">securityDataSource</span>”</span> is the name of a
- <code class="classname">DataSource</code> bean in the application context, pointing at a database
- containing the standard Spring Security <a class="link" href="#db_schema_users_authorities">user
- data tables</a>. Alternatively, you could configure a Spring Security
- <code class="classname">JdbcDaoImpl</code> bean and point at that using the
- <code class="literal">user-service-ref</code> attribute: </p><pre class="programlisting">
+ <code class="classname">DataSource</code> bean in the application context, pointing at a
+ database containing the standard Spring Security <a class="link" href="#db_schema_users_authorities">user data tables</a>. Alternatively,
+ you could configure a Spring Security <code class="classname">JdbcDaoImpl</code> bean and
+ point at that using the <code class="literal">user-service-ref</code> attribute: </p><pre class="programlisting">
<span class="hl-tag"><authentication-manager></span>
<span class="hl-tag"><authentication-provider</span> <span class="hl-attribute">user-service-ref</span>=<span class="hl-value">'myUserDetailsService'</span><span class="hl-tag">/></span>
<span class="hl-tag"></authentication-manager></span>
@@ -446,19 +480,21 @@ pageTracker._trackPageview();
<span class="hl-tag"></beans:bean></span>
</pre><p> You can also use standard
- <code class="interfacename">AuthenticationProvider</code> beans as follows </p><pre class="programlisting">
+ <code class="interfacename">AuthenticationProvider</code> beans as follows </p><pre class="programlisting">
<span class="hl-tag"><authentication-manager></span>
<span class="hl-tag"><authentication-provider</span> <span class="hl-attribute">ref</span>=<span class="hl-value">'myAuthenticationProvider'</span><span class="hl-tag">/></span>
<span class="hl-tag"></authentication-manager></span>
</pre><p> where <code class="literal">myAuthenticationProvider</code> is the name of a
- bean in your application context which implements
- <code class="interfacename">AuthenticationProvider</code>. You can use multiple
- <code class="literal">authentication-provider</code> elements, in which case they will be checked
- in the order they are declared when attempting to authenticated a user. See <a class="xref" href="#ns-auth-manager" title="2.6 The Authentication Manager and the Namespace">Section 2.6, “The Authentication Manager and the Namespace”</a> for more on information on how the Spring Security
- <code class="interfacename">AuthenticationManager</code> is configured using the namespace. </p><div class="section" title="Adding a Password Encoder"><div class="titlepage"><div><div><h4 class="title"><a name="ns-password-encoder"></a>Adding a Password Encoder</h4></div></div></div><p> Often your password data will be encoded using a hashing algorithm. This is supported
- by the <code class="literal"><password-encoder></code> element. With SHA encoded passwords,
- the original authentication provider configuration would look like this: </p><pre class="programlisting">
+ bean in your application context which implements
+ <code class="interfacename">AuthenticationProvider</code>. You can use multiple
+ <code class="literal">authentication-provider</code> elements, in which case the providers
+ will be queried in the order they are declared. See <a class="xref" href="#ns-auth-manager" title="3.6 The Authentication Manager and the Namespace">Section 3.6, “The Authentication Manager and the Namespace”</a> for more on information on how the Spring Security
+ <code class="interfacename">AuthenticationManager</code> is configured using the
+ namespace. </p><div class="section" title="Adding a Password Encoder"><div class="titlepage"><div><div><h4 class="title"><a name="ns-password-encoder"></a>Adding a Password Encoder</h4></div></div></div><p> Often your password data will be encoded using a hashing algorithm. This is
+ supported by the <code class="literal"><password-encoder></code> element. With SHA
+ encoded passwords, the original authentication provider configuration would look
+ like this: </p><pre class="programlisting">
<span class="hl-tag"><authentication-manager></span>
<span class="hl-tag"><authentication-provider></span>
<span class="hl-tag"><password-encoder</span> <span class="hl-attribute">hash</span>=<span class="hl-value">"sha"</span><span class="hl-tag">/></span>
@@ -471,49 +507,67 @@ pageTracker._trackPageview();
<span class="hl-tag"></authentication-provider></span>
<span class="hl-tag"></authentication-manager></span>
- </pre><p> When using hashed passwords, it's also a good idea to use a salt value to protect
- against dictionary attacks and Spring Security supports this too. Ideally you would want
- to use a randomly generated salt value for each user, but you can use any property of the
- <code class="classname">UserDetails</code> object which is loaded by your
- <code class="classname">UserDetailsService</code>. For example, to use the
- <code class="literal">username</code> property, you would use </p><pre class="programlisting">
- <password-encoder hash="sha">
- <salt-source user-property="username"/>
- </password-encoder>
+ </pre><p> When using hashed passwords, it's also a good idea to use a salt value to
+ protect against dictionary attacks and Spring Security supports this too.
+ Ideally you would want to use a randomly generated salt value for each user, but
+ you can use any property of the <code class="classname">UserDetails</code> object which
+ is loaded by your <code class="classname">UserDetailsService</code>. For example, to use
+ the <code class="literal">username</code> property, you would use </p><pre class="programlisting">
+ <span class="hl-tag"><password-encoder</span> <span class="hl-attribute">hash</span>=<span class="hl-value">"sha"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><salt-source</span> <span class="hl-attribute">user-property</span>=<span class="hl-value">"username"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></password-encoder></span>
</pre><p> You can use a custom password encoder bean by using the
- <code class="literal">ref</code> attribute of <code class="literal">password-encoder</code>. This should
- contain the name of a bean in the application context which is an instance of Spring
- Security's <code class="interfacename">PasswordEncoder</code> interface. </p></div></div></div><div class="section" title="2.3 Advanced Web Features"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ns-web-advanced"></a>2.3 Advanced Web Features</h2></div></div></div><div class="section" title="2.3.1 Remember-Me Authentication"><div class="titlepage"><div><div><h3 class="title"><a name="ns-remember-me"></a>2.3.1 Remember-Me Authentication</h3></div></div></div><p>See the separate <a class="link" href="#remember-me" title="10. Remember-Me Authentication">Remember-Me chapter</a> for
- information on remember-me namespace configuration.</p></div><div class="section" title="2.3.2 Adding HTTP/HTTPS Channel Security"><div class="titlepage"><div><div><h3 class="title"><a name="ns-requires-channel"></a>2.3.2 Adding HTTP/HTTPS Channel Security</h3></div></div></div><p>If your application supports both HTTP and HTTPS, and you require that particular URLs
- can only be accessed over HTTPS, then this is directly supported using the
- <code class="literal">requires-channel</code> attribute on <code class="literal"><intercept-url></code>: </p><pre class="programlisting">
+ <code class="literal">ref</code> attribute of <code class="literal">password-encoder</code>. This
+ should contain the name of a bean in the application context which is an
+ instance of Spring Security's <code class="interfacename">PasswordEncoder</code>
+ interface. </p></div></div></div><div class="section" title="3.3 Advanced Web Features"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ns-web-advanced"></a>3.3 Advanced Web Features</h2></div></div></div><div class="section" title="3.3.1 Remember-Me Authentication"><div class="titlepage"><div><div><h3 class="title"><a name="ns-remember-me"></a>3.3.1 Remember-Me Authentication</h3></div></div></div><p>See the separate <a class="link" href="#remember-me" title="11. Remember-Me Authentication">Remember-Me chapter</a> for
+ information on remember-me namespace configuration.</p></div><div class="section" title="3.3.2 Adding HTTP/HTTPS Channel Security"><div class="titlepage"><div><div><h3 class="title"><a name="ns-requires-channel"></a>3.3.2 Adding HTTP/HTTPS Channel Security</h3></div></div></div><p>If your application supports both HTTP and HTTPS, and you require that particular
+ URLs can only be accessed over HTTPS, then this is directly supported using the
+ <code class="literal">requires-channel</code> attribute on
+ <code class="literal"><intercept-url></code>: </p><pre class="programlisting">
<span class="hl-tag"><http></span>
<span class="hl-tag"><intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/secure/**"</span> <span class="hl-attribute">access</span>=<span class="hl-value">"ROLE_USER"</span> <span class="hl-attribute">requires-channel</span>=<span class="hl-value">"https"</span><span class="hl-tag">/></span>
<span class="hl-tag"><intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/**"</span> <span class="hl-attribute">access</span>=<span class="hl-value">"ROLE_USER"</span> <span class="hl-attribute">requires-channel</span>=<span class="hl-value">"any"</span><span class="hl-tag">/></span>
...
<span class="hl-tag"></http></span>
</pre><p>With this configuration in place, if a user attempts to access
- anything matching the "/secure/**" pattern using HTTP, they will first be redirected to an
- HTTPS URL. The available options are "http", "https" or "any". Using the value "any" means
- that either HTTP or HTTPS can be used. </p><p>If your application uses non-standard ports for HTTP and/or HTTPS, you can specify a
- list of port mappings as follows: </p><pre class="programlisting">
- <http>
+ anything matching the "/secure/**" pattern using HTTP, they will first be redirected
+ to an HTTPS URL
+ <sup>[<a name="d0e1018" href="#ftn.d0e1018" class="footnote">7</a>]</sup>.
+ The available options are "http", "https" or "any". Using the value
+ "any" means that either HTTP or HTTPS can be used. </p><p>If your application uses non-standard ports for HTTP and/or HTTPS, you can specify
+ a list of port mappings as follows: </p><pre class="programlisting">
+ <span class="hl-tag"><http></span>
...
- <port-mappings>
- <port-mapping http="9080" https="9443"/>
- </port-mappings>
- </http>
- </pre></div><div class="section" title="2.3.3 Session Management"><div class="titlepage"><div><div><h3 class="title"><a name="ns-session-mgmt"></a>2.3.3 Session Management</h3></div></div></div><div class="section" title="Detecting Timeouts"><div class="titlepage"><div><div><h4 class="title"><a name="d0e802"></a>Detecting Timeouts</h4></div></div></div><p> You can configure Spring Security to detect the submission of an invalid session ID
- and redirect the user to an appropriate URL. This is achieved through the
- <code class="literal">session-management</code> element: </p><pre class="programlisting">
+ <span class="hl-tag"><port-mappings></span>
+ <span class="hl-tag"><port-mapping</span> <span class="hl-attribute">http</span>=<span class="hl-value">"9080"</span> <span class="hl-attribute">https</span>=<span class="hl-value">"9443"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></port-mappings></span>
+ <span class="hl-tag"></http></span>
+ </pre><p>
+ Note that in order to be truly secure, an application should not use HTTP at all or switch
+ between HTTP and HTTPS. It should start in HTTPS (with the user entering an HTTPS URL) and
+ use a secure connection throughout to avoid any possibility of man-in-the-middle attacks.
+ </p></div><div class="section" title="3.3.3 Session Management"><div class="titlepage"><div><div><h3 class="title"><a name="ns-session-mgmt"></a>3.3.3 Session Management</h3></div></div></div><div class="section" title="Detecting Timeouts"><div class="titlepage"><div><div><h4 class="title"><a name="d0e1033"></a>Detecting Timeouts</h4></div></div></div><p> You can configure Spring Security to detect the submission of an invalid
+ session ID and redirect the user to an appropriate URL. This is achieved through
+ the <code class="literal">session-management</code> element: </p><pre class="programlisting">
<span class="hl-tag"><http></span>
...
- <span class="hl-tag"><session-management</span> <span class="hl-attribute">invalid-session-url</span>=<span class="hl-value">"/sessionTimeout.htm"</span><span class="hl-tag"> /></span>
- <span class="hl-tag"></http></span></pre></div><div class="section" title="Concurrent Session Control"><div class="titlepage"><div><div><h4 class="title"><a name="ns-concurrent-sessions"></a>Concurrent Session Control</h4></div></div></div><p>If you wish to place constraints on a single user's ability to log in to your
- application, Spring Security supports this out of the box with the following simple
- additions. First you need to add the following listener to your
- <code class="filename">web.xml</code> file to keep Spring Security updated about session
- lifecycle events: </p><pre class="programlisting">
+ <span class="hl-tag"><session-management</span> <span class="hl-attribute">invalid-session-url</span>=<span class="hl-value">"/invalidSession.htm"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"></http></span></pre><p>Note that if you use this mechanism to detect session timeouts, it
+ may falsely report an error if the user logs out and then logs back in without
+ closing the browser. This is because the session cookie is not cleared when you
+ invalidate the session and will be resubmitted even if the user has logged out.
+ You may be able to explicitly delete the JSESSIONID cookie on logging out, for
+ example by using the following syntax in the logout handler: </p><pre class="programlisting">
+ <span class="hl-tag"><http></span>
+ <span class="hl-tag"><logout</span> <span class="hl-attribute">delete-cookies</span>=<span class="hl-value">"JSESSIONID"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"></http></span>
+ </pre><p> Unfortunately this can't be guaranteed to work with every servlet container,
+ so you will need to test it in your environment<sup>[<a name="d0e1047" href="#ftn.d0e1047" class="footnote">8</a>]</sup>. </p></div><div class="section" title="Concurrent Session Control"><div class="titlepage"><div><div><h4 class="title"><a name="ns-concurrent-sessions"></a>Concurrent Session Control</h4></div></div></div><p>If you wish to place constraints on a single user's ability to log in to your
+ application, Spring Security supports this out of the box with the following
+ simple additions. First you need to add the following listener to your
+ <code class="filename">web.xml</code> file to keep Spring Security updated about session
+ lifecycle events: </p><pre class="programlisting">
<span class="hl-tag"><listener></span>
<span class="hl-tag"><listener-class></span>
org.springframework.security.web.session.HttpSessionEventPublisher
@@ -527,8 +581,8 @@ pageTracker._trackPageview();
<span class="hl-tag"></session-management></span>
<span class="hl-tag"></http></span>
</pre><p> This will prevent a user from logging in multiple times - a
- second login will cause the first to be invalidated. Often you would prefer to prevent a
- second login, in which case you can use </p><pre class="programlisting">
+ second login will cause the first to be invalidated. Often you would prefer to
+ prevent a second login, in which case you can use </p><pre class="programlisting">
<span class="hl-tag"><http></span>
...
<span class="hl-tag"><session-management></span>
@@ -536,121 +590,103 @@ pageTracker._trackPageview();
<span class="hl-tag"></session-management></span>
<span class="hl-tag"></http></span>
</pre><p>The second login will then be rejected. By
- <span class="quote">“<span class="quote">rejected</span>”</span>, we mean that the user will be sent to the
- <code class="literal">authentication-failure-url</code> if form-based login is being used. If the
- second authentication takes place through another non-interactive mechanism, such as
- <span class="quote">“<span class="quote">remember-me</span>”</span>, an <span class="quote">“<span class="quote">unauthorized</span>”</span> (402) error will be sent to
- the client. If instead you want to use an error page, you can add the attribute
- <code class="literal">session-authentication-error-url</code> to the
- <code class="literal">session-management</code> element. </p><p>If you are using a customized authentication filter for form-based login, then you
- have to configure concurrent session control support explicitly. More details can be found
- in the <a class="link" href="#session-mgmt" title="11. Session Management">Session Management chapter</a>. </p></div><div class="section" title="Session Fixation Attack Protection"><div class="titlepage"><div><div><h4 class="title"><a name="ns-session-fixation"></a>Session Fixation Attack Protection</h4></div></div></div><p>
- <a class="link" href="http://en.wikipedia.org/wiki/Session_fixation" target="_top">Session fixation</a>
- attacks are a potential risk where it is possible for a malicious attacker to create a
- session by accessing a site, then persuade another user to log in with the same session
- (by sending them a link containing the session identifier as a parameter, for example).
- Spring Security protects against this automatically by creating a new session when a user
- logs in. If you don't require this protection, or it conflicts with some other
- requirement, you can control the behaviour using the
- <code class="literal">session-fixation-protection</code> attribute on
- <code class="literal"><session-management></code>, which has three options
- </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p><code class="literal">migrateSession</code> - creates a new
- session and copies the existing session attributes to the new session. This is the
- default.</p></li><li class="listitem"><p><code class="literal">none</code> - Don't do
- anything. The original session will be
- retained.</p></li><li class="listitem"><p><code class="literal">newSession</code> - Create
- a new "clean" session, without copying the existing session
- data.</p></li></ul></div></div></div><div class="section" title="2.3.4 OpenID Support"><div class="titlepage"><div><div><h3 class="title"><a name="ns-openid"></a>2.3.4 OpenID Support</h3></div></div></div><p>The namespace supports <a class="link" href="http://openid.net/" target="_top">OpenID</a> login either
- instead of, or in addition to normal form-based login, with a simple change: </p><pre class="programlisting">
+ <span class="quote">“<span class="quote">rejected</span>”</span>, we mean that the user will be sent to the
+ <code class="literal">authentication-failure-url</code> if form-based login is being used.
+ If the second authentication takes place through another non-interactive
+ mechanism, such as <span class="quote">“<span class="quote">remember-me</span>”</span>, an <span class="quote">“<span class="quote">unauthorized</span>”</span>
+ (402) error will be sent to the client. If instead you want to use an error
+ page, you can add the attribute
+ <code class="literal">session-authentication-error-url</code> to the
+ <code class="literal">session-management</code> element. </p><p>If you are using a customized authentication filter for form-based login, then
+ you have to configure concurrent session control support explicitly. More
+ details can be found in the <a class="link" href="#session-mgmt" title="12. Session Management">Session Management
+ chapter</a>. </p></div><div class="section" title="Session Fixation Attack Protection"><div class="titlepage"><div><div><h4 class="title"><a name="ns-session-fixation"></a>Session Fixation Attack Protection</h4></div></div></div><p> <a class="link" href="http://en.wikipedia.org/wiki/Session_fixation" target="_top">Session
+ fixation</a> attacks are a potential risk where it is possible for a
+ malicious attacker to create a session by accessing a site, then persuade
+ another user to log in with the same session (by sending them a link containing
+ the session identifier as a parameter, for example). Spring Security protects
+ against this automatically by creating a new session when a user logs in. If you
+ don't require this protection, or it conflicts with some other requirement, you
+ can control the behaviour using the
+ <code class="literal">session-fixation-protection</code> attribute on
+ <code class="literal"><session-management></code>, which has three options </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p><code class="literal">migrateSession</code> - creates a new session and copies
+ the existing session attributes to the new session. This is the
+ default.</p></li><li class="listitem"><p><code class="literal">none</code> - Don't do anything. The original session will
+ be retained.</p></li><li class="listitem"><p><code class="literal">newSession</code> - Create a new "clean" session, without
+ copying the existing session data.</p></li></ul></div><p>
+ See the <a class="link" href="#session-mgmt" title="12. Session Management">Session Management</a> chapter for
+ additional information.
+ </p></div></div><div class="section" title="3.3.4 OpenID Support"><div class="titlepage"><div><div><h3 class="title"><a name="ns-openid"></a>3.3.4 OpenID Support</h3></div></div></div><p>The namespace supports <a class="link" href="http://openid.net/" target="_top">OpenID</a> login
+ either instead of, or in addition to normal form-based login, with a simple change: </p><pre class="programlisting">
<span class="hl-tag"><http></span>
<span class="hl-tag"><intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/**"</span> <span class="hl-attribute">access</span>=<span class="hl-value">"ROLE_USER"</span><span class="hl-tag"> /></span>
<span class="hl-tag"><openid-login /></span>
<span class="hl-tag"></http></span>
</pre><p>You should then register yourself with an OpenID provider (such as
- myopenid.com), and add the user information to your in-memory
- <code class="literal"><user-service></code> : </p><pre class="programlisting">
+ myopenid.com), and add the user information to your in-memory
+ <code class="literal"><user-service></code> : </p><pre class="programlisting">
<span class="hl-tag"><user</span> <span class="hl-attribute">name</span>=<span class="hl-value">"http://jimi.hendrix.myopenid.com/"</span> <span class="hl-attribute">authorities</span>=<span class="hl-value">"ROLE_USER"</span><span class="hl-tag"> /></span>
</pre><p> You should be able to login using the <code class="literal">myopenid.com</code> site to
- authenticate. It is also possible to select a specific
- <code class="interfacename">UserDetailsService</code> bean for use OpenID by setting the
- <code class="literal">user-service-ref</code> attribute on the <code class="literal">openid-login</code>
- element. See the previous section on <a class="link" href="#ns-auth-providers" title="2.2.3 Using other Authentication Providers">authentication
- providers</a> for more information. Note that we have omitted the password attribute
- from the above user configuration, since this set of user data is only being used to load
- the authorities for the user. A random password will be generate internally, preventing you
- from accidentally using this user data as an authentication source elsewhere in your
- configuration.</p><div class="section" title="Attribute Exchange"><div class="titlepage"><div><div><h4 class="title"><a name="d0e914"></a>Attribute Exchange</h4></div></div></div><p>Support for OpenID <a class="link" href="http://openid.net/specs/openid-attribute-exchange-1_0.html" target="_top">attribute
- exchange</a>. As an example, the following configuration would attempt to retrieve
- the email and full name from the OpenID provider, for use by the application:</p><pre class="programlisting">
- <span class="hl-tag"><openid-login></span>
- <span class="hl-tag"><attribute-exchange></span>
- <span class="hl-tag"><openid-attribute</span> <span class="hl-attribute">name</span>=<span class="hl-value">"email"</span> <span class="hl-attribute">type</span>=<span class="hl-value">"http://axschema.org/contact/email"</span> <span class="hl-attribute">required</span>=<span class="hl-value">"true"</span><span class="hl-tag"> /></span>
- <span class="hl-tag"><openid-attribute</span> <span class="hl-attribute">name</span>=<span class="hl-value">"name"</span> <span class="hl-attribute">type</span>=<span class="hl-value">"http://axschema.org/namePerson"</span><span class="hl-tag"> /></span>
- <span class="hl-tag"></attribute-exchange></span>
- <span class="hl-tag"></openid-login></span></pre><p>The <span class="quote">“<span class="quote">type</span>”</span> of each OpenID attribute is a URI,
- determined by a particular schema, in this case <a class="link" href="http://axschema.org/" target="_top">http://axschema.org/</a>. If an attribute must be retrieved for successful
- authentication, the <code class="literal">required</code> attribute can be set. The exact schema and
- attributes supported will depend on your OpenID provider. The attribute values are
- returned as part of the authentication process and can be accessed afterwards using the
- following
- code:</p><pre class="programlisting">OpenIDAuthenticationToken token = (OpenIDAuthenticationToken)SecurityContextHolder.getContext().getAuthentication();
+ authenticate. It is also possible to select a specific
+ <code class="interfacename">UserDetailsService</code> bean for use OpenID by setting the
+ <code class="literal">user-service-ref</code> attribute on the <code class="literal">openid-login</code>
+ element. See the previous section on <a class="link" href="#ns-auth-providers" title="3.2.5 Using other Authentication Providers">authentication providers</a> for more information. Note that we have omitted the
+ password attribute from the above user configuration, since this set of user data is
+ only being used to load the authorities for the user. A random password will be
+ generate internally, preventing you from accidentally using this user data as an
+ authentication source elsewhere in your configuration.</p><div class="section" title="Attribute Exchange"><div class="titlepage"><div><div><h4 class="title"><a name="d0e1165"></a>Attribute Exchange</h4></div></div></div><p>Support for OpenID <a class="link" href="http://openid.net/specs/openid-attribute-exchange-1_0.html" target="_top">attribute exchange</a>. As an example, the following configuration would
+ attempt to retrieve the email and full name from the OpenID provider, for use by
+ the application:</p><pre class="programlisting">
+ <span class="hl-tag"><openid-login></span>
+ <span class="hl-tag"><attribute-exchange></span>
+ <span class="hl-tag"><openid-attribute</span> <span class="hl-attribute">name</span>=<span class="hl-value">"email"</span> <span class="hl-attribute">type</span>=<span class="hl-value">"http://axschema.org/contact/email"</span> <span class="hl-attribute">required</span>=<span class="hl-value">"true"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><openid-attribute</span> <span class="hl-attribute">name</span>=<span class="hl-value">"name"</span> <span class="hl-attribute">type</span>=<span class="hl-value">"http://axschema.org/namePerson"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></attribute-exchange></span>
+ <span class="hl-tag"></openid-login></span></pre><p>The <span class="quote">“<span class="quote">type</span>”</span> of each OpenID attribute is a URI,
+ determined by a particular schema, in this case <a class="link" href="http://axschema.org/" target="_top">http://axschema.org/</a>. If an attribute
+ must be retrieved for successful authentication, the <code class="literal">required</code>
+ attribute can be set. The exact schema and attributes supported will depend on
+ your OpenID provider. The attribute values are returned as part of the
+ authentication process and can be accessed afterwards using the following code:
+ </p><pre class="programlisting">
+OpenIDAuthenticationToken token =
+ (OpenIDAuthenticationToken)SecurityContextHolder.getContext().getAuthentication();
List<OpenIDAttribute> attributes = token.getAttributes();</pre><p>The
- <code class="classname">OpenIDAttribute</code> contains the attribute type and the retrieved
- value (or values in the case of multi-valued attributes). We'll see more about how the
- <code class="classname">SecurityContextHolder</code> class is used when we look at core Spring
- Security components in the <a class="link" href="#core-components" title="5.2 Core Components">technical overview</a>
- chapter.</p></div></div><div class="section" title="2.3.5 Adding in Your Own Filters"><div class="titlepage"><div><div><h3 class="title"><a name="ns-custom-filters"></a>2.3.5 Adding in Your Own Filters</h3></div></div></div><p>If you've used Spring Security before, you'll know that the framework maintains a chain
- of filters in order to apply its services. You may want to add your own filters to the stack
- at particular locations or use a Spring Security filter for which there isn't currently a
- namespace configuration option (CAS, for example). Or you might want to use a customized
- version of a standard namespace filter, such as the
- <code class="literal">UsernamePasswordAuthenticationFilter</code> which is created by the
- <code class="literal"><form-login></code> element, taking advantage of some of the extra
- configuration options which are available by using the bean explicitly. How can you do this
- with namespace configuration, since the filter chain is not directly exposed? </p><p>The order of the filters is always strictly enforced when using the namespace. When the
- application context is being created, the filter beans are sorted by the namespace handling
- code and the standard Spring Security filters each have an alias in the namespace and a
- well-known position.</p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>In previous versions, the sorting took place after the
- filter instances had been created, during post-processing of the application context. In
- version 3.0+ the sorting is now done at the bean metadata level, before the classes have
- been instantiated. This has implications for how you add your own filters to the stack
- as the entire filter list must be known during the parsing of the
- <code class="literal"><http></code> element, so the syntax has changed slightly in
- 3.0.</p></td></tr></table></div><p>The filters, aliases and namespace elements/attributes which create
- the filters are shown in <a class="xref" href="#filter-stack" title="Table 2.1. Standard Filter Aliases and Ordering">Table 2.1, “Standard Filter
- Aliases and Ordering”</a>. The filters are listed in the order
- in which they occur in the filter chain. </p><div class="table"><a name="filter-stack"></a><p class="title"><b>Table 2.1. Standard Filter
- Aliases and Ordering</b></p><div class="table-contents"><table summary="Standard Filter
 Aliases and Ordering" style="border-collapse: collapse;border-top: 0.5pt solid ; border-bottom: 0.5pt solid ; border-left: 0.5pt solid ; border-right: 0.5pt solid ; "><colgroup><col><col><col></colgroup><thead><tr><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="center">Alias</th><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="center">Filter Class</th><th style="border-bottom: 0.5pt solid ; " align="center">Namespace Element or
- Attribute</th></tr></thead><tbody><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">
- CHANNEL_FILTER</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">ChannelProcessingFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/intercept-url at requires-channel</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">
- CONCURRENT_SESSION_FILTER</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">ConcurrentSessionFilter</code>
- </td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">session-management/concurrency-control</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">
- SECURITY_CONTEXT_FILTER</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="classname">SecurityContextPersistenceFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">
- LOGOUT_FILTER
- </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">LogoutFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/logout</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">
- X509_FILTER
- </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">X509AuthenticationFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/x509</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">
- PRE_AUTH_FILTER
- </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">AstractPreAuthenticatedProcessingFilter</code>
- Subclasses</td><td style="border-bottom: 0.5pt solid ; " align="left">N/A</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> CAS_FILTER
- </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">CasAuthenticationFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left">N/A</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">
- FORM_LOGIN_FILTER
- </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">UsernamePasswordAuthenticationFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/form-login</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">
- BASIC_AUTH_FILTER
- </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">BasicAuthenticationFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/http-basic</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">
- SERVLET_API_SUPPORT_FILTER</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">SecurityContextHolderAwareFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/@servlet-api-provision</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">
- REMEMBER_ME_FILTER
- </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="classname">RememberMeAuthenticationFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/remember-me</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">
- ANONYMOUS_FILTER
- </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">AnonymousAuthenticationFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/anonymous</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">
- SESSION_MANAGEMENT_FILTER</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">SessionManagementFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">session-management</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">EXCEPTION_TRANSLATION_FILTER
- </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="classname">ExceptionTranslationFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">
- FILTER_SECURITY_INTERCEPTOR
- </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="classname">FilterSecurityInterceptor</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http</code></td></tr><tr><td style="border-right: 0.5pt solid ; " align="left">
- SWITCH_USER_FILTER
- </td><td style="border-right: 0.5pt solid ; " align="left"><code class="literal">SwitchUserFilter</code></td><td style="" align="left">N/A</td></tr></tbody></table></div></div><p><br class="table-break">
- You can add your own filter to the stack, using the <code class="literal">custom-filter</code> element
- and one of these names to specify the position your filter should appear at: </p><pre class="programlisting">
+ <code class="classname">OpenIDAttribute</code> contains the attribute type and the
+ retrieved value (or values in the case of multi-valued attributes). We'll see
+ more about how the <code class="classname">SecurityContextHolder</code> class is used
+ when we look at core Spring Security components in the <a class="link" href="#core-components" title="6.2 Core Components">technical overview</a> chapter. Multiple
+ attribute exchange configurations are also be supported, if you wish to use
+ multiple identity providers. You can supply multiple
+ <code class="literal">attribute-exchange</code> elements, using an
+ <code class="literal">identifier-matcher</code> attribute on each. This contains a regular
+ expression which will be matched against the OpenID identifier supplied by the
+ user. See the OpenID sample application in the codebase for an example
+ configuration, providing different attribute lists for the Google, Yahoo and
+ MyOpenID providers.</p></div></div><div class="section" title="3.3.5 Adding in Your Own Filters"><div class="titlepage"><div><div><h3 class="title"><a name="ns-custom-filters"></a>3.3.5 Adding in Your Own Filters</h3></div></div></div><p>If you've used Spring Security before, you'll know that the framework maintains a
+ chain of filters in order to apply its services. You may want to add your own
+ filters to the stack at particular locations or use a Spring Security filter for
+ which there isn't currently a namespace configuration option (CAS, for example). Or
+ you might want to use a customized version of a standard namespace filter, such as
+ the <code class="classname">UsernamePasswordAuthenticationFilter</code> which is created by the
+ <code class="literal"><form-login></code> element, taking advantage of some of the extra
+ configuration options which are available by using the bean explicitly. How can you
+ do this with namespace configuration, since the filter chain is not directly
+ exposed? </p><p>The order of the filters is always strictly enforced when using the namespace.
+ When the application context is being created, the filter beans are sorted by the
+ namespace handling code and the standard Spring Security filters each have an alias
+ in the namespace and a well-known position.</p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>In previous versions, the sorting took place after the filter instances had
+ been created, during post-processing of the application context. In version 3.0+
+ the sorting is now done at the bean metadata level, before the classes have been
+ instantiated. This has implications for how you add your own filters to the
+ stack as the entire filter list must be known during the parsing of the
+ <code class="literal"><http></code> element, so the syntax has changed slightly in
+ 3.0.</p></td></tr></table></div><p>The filters, aliases and namespace elements/attributes which create the
+ filters are shown in <a class="xref" href="#filter-stack" title="Table 3.1. Standard Filter Aliases and Ordering">Table 3.1, “Standard Filter Aliases and Ordering”</a>. The filters are listed in the
+ order in which they occur in the filter chain. </p><div class="table"><a name="filter-stack"></a><p class="title"><b>Table 3.1. Standard Filter Aliases and Ordering</b></p><div class="table-contents"><table summary="Standard Filter Aliases and Ordering" style="border-collapse: collapse;border-top: 0.5pt solid ; border-bottom: 0.5pt solid ; border-left: 0.5pt solid ; border-right: 0.5pt solid ; "><colgroup><col align="left"><col align="left"><col align="left"></colgroup><thead><tr><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="center">Alias</th><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="center">Filter Class</th><th style="border-bottom: 0.5pt solid ; " align="center">Namespace Element or Attribute</th></tr></thead><tbody><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> CHANNEL_FILTER</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">ChannelProcessingFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/intercept-url at requires-channel</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> CONCURRENT_SESSION_FILTER</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">ConcurrentSessionFilter</code> </td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">session-management/concurrency-control</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> SECURITY_CONTEXT_FILTER</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="classname">SecurityContextPersistenceFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> LOGOUT_FILTER </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">LogoutFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/logout</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> X509_FILTER </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">X509AuthenticationFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/x509</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> PRE_AUTH_FILTER </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">AstractPreAuthenticatedProcessingFilter</code>
+ Subclasses</td><td style="border-bottom: 0.5pt solid ; " align="left">N/A</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> CAS_FILTER </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">CasAuthenticationFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left">N/A</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> FORM_LOGIN_FILTER </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">UsernamePasswordAuthenticationFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/form-login</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> BASIC_AUTH_FILTER </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">BasicAuthenticationFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/http-basic</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> SERVLET_API_SUPPORT_FILTER</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">SecurityContextHolderAwareFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/@servlet-api-provision</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">JAAS_API_SUPPORT_FILTER</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">JaasApiIntegrationFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/@jaas-api-provision</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> REMEMBER_ME_FILTER </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="classname">RememberMeAuthenticationFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/remember-me</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> ANONYMOUS_FILTER </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">AnonymousAuthenticationFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http/anonymous</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> SESSION_MANAGEMENT_FILTER</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="literal">SessionManagementFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">session-management</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">EXCEPTION_TRANSLATION_FILTER </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="classname">ExceptionTranslationFilter</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> FILTER_SECURITY_INTERCEPTOR </td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"><code class="classname">FilterSecurityInterceptor</code></td><td style="border-bottom: 0.5pt solid ; " align="left"><code class="literal">http</code></td></tr><tr><td style="border-right: 0.5pt solid ; " align="left"> SWITCH_USER_FILTER </td><td style="border-right: 0.5pt solid ; " align="left"><code class="literal">SwitchUserFilter</code></td><td style="" align="left">N/A</td></tr></tbody></table></div></div><p><br class="table-break"> You can add your own filter to the stack, using the
+ <code class="literal">custom-filter</code> element and one of these names to specify the
+ position your filter should appear at: </p><pre class="programlisting">
<span class="hl-tag"><http></span>
<span class="hl-tag"><custom-filter</span> <span class="hl-attribute">position</span>=<span class="hl-value">"FORM_LOGIN_FILTER"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"myFilter"</span><span class="hl-tag"> /></span>
<span class="hl-tag"></http></span>
@@ -658,45 +694,56 @@ List<OpenIDAttribute> attributes = token.getAttributes();</pre><p>The
<span class="hl-tag"><beans:bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"myFilter"</span> <span class="hl-attribute">class</span>=<span class="hl-value">"com.mycompany.MySpecialAuthenticationFilter"</span><span class="hl-tag">/></span>
</pre><p> You can also use the <code class="literal">after</code> or <code class="literal">before</code>
- attributes if you want your filter to be inserted before or after another filter in the
- stack. The names "FIRST" and "LAST" can be used with the <code class="literal">position</code>
- attribute to indicate that you want your filter to appear before or after the entire stack,
- respectively. </p><div class="tip" title="Avoiding filter position conflicts" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip: Avoiding filter position conflicts"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Avoiding filter position conflicts</th></tr><tr><td align="left" valign="top"><p> If you are inserting a custom filter which may occupy the same position as one of the
- standard filters created by the namespace then it's important that you don't include the
- namespace versions by mistake. Avoid using the <code class="literal">auto-config</code> attribute
- and remove any elements which create filters whose functionality you want to replace. </p><p> Note that you can't replace filters which are created by the use of the
- <code class="literal"><http></code> element itself -
- <code class="classname">SecurityContextPersistenceFilter</code>,
- <code class="classname">ExceptionTranslationFilter</code> or
- <code class="classname">FilterSecurityInterceptor</code>. </p></td></tr></table></div><p> If you're replacing a namespace filter which requires an authentication entry point
- (i.e. where the authentication process is triggered by an attempt by an unauthenticated user
- to access to a secured resource), you will need to add a custom entry point bean too. </p><div class="section" title="Setting a Custom AuthenticationEntryPoint"><div class="titlepage"><div><div><h4 class="title"><a name="ns-entry-point-ref"></a>Setting a Custom <code class="interfacename">AuthenticationEntryPoint</code></h4></div></div></div><p> If you aren't using form login, OpenID or basic authentication through the namespace,
- you may want to define an authentication filter and entry point using a traditional bean
- syntax and link them into the namespace, as we've just seen. The corresponding
- <code class="interfacename">AuthenticationEntryPoint</code> can be set using the
- <code class="literal">entry-point-ref</code> attribute on the <code class="literal"><http></code>
- element. </p><p> The CAS sample application is a good example of the use of custom beans with the
- namespace, including this syntax. If you aren't familiar with authentication entry points,
- they are discussed in the <a class="link" href="#tech-intro-auth-entry-point" title="5.4.2 AuthenticationEntryPoint">technical
- overview</a> chapter. </p></div></div></div><div class="section" title="2.4 Method Security"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ns-method-security"></a>2.4 Method Security</h2></div></div></div><p>From version 2.0 onwards Spring Security has improved support substantially for adding
- security to your service layer methods. It provides support for JSR-250 annotation security as
- well as the framework's original <code class="literal">@Secured</code> annotation. From 3.0 you can also
- make use of new <a class="link" href="#el-access" title="15. Expression-Based Access Control">expression-based annotations</a>. You can
- apply security to a single bean, using the <code class="literal">intercept-methods</code> element to
- decorate the bean declaration, or you can secure multiple beans across the entire service
- layer using the AspectJ style pointcuts. </p><div class="section" title="2.4.1 The <global-method-security> Element"><div class="titlepage"><div><div><h3 class="title"><a name="ns-global-method"></a>2.4.1 The <code class="literal"><global-method-security></code> Element</h3></div></div></div><p> This element is used to enable annotation-based security in your application (by
- setting the appropriate attributes on the element), and also to group together security
- pointcut declarations which will be applied across your entire application context. You
- should only declare one <code class="literal"><global-method-security></code> element. The
- following declaration would enable support for Spring Security's
- <code class="literal">@Secured</code>: </p><pre class="programlisting">
- <global-method-security secured-annotations="enabled" />
+ attributes if you want your filter to be inserted before or after another filter in
+ the stack. The names "FIRST" and "LAST" can be used with the
+ <code class="literal">position</code> attribute to indicate that you want your filter to
+ appear before or after the entire stack, respectively. </p><div class="tip" title="Avoiding filter position conflicts" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip: Avoiding filter position conflicts"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Avoiding filter position conflicts</th></tr><tr><td align="left" valign="top"><p> If you are inserting a custom filter which may occupy the same position as
+ one of the standard filters created by the namespace then it's important that
+ you don't include the namespace versions by mistake. Avoid using the
+ <code class="literal">auto-config</code> attribute and remove any elements which create
+ filters whose functionality you want to replace. </p><p> Note that you can't replace filters which are created by the use of the
+ <code class="literal"><http></code> element itself -
+ <code class="classname">SecurityContextPersistenceFilter</code>,
+ <code class="classname">ExceptionTranslationFilter</code> or
+ <code class="classname">FilterSecurityInterceptor</code>. Some other filters are added
+ by default, but you can disable them. An <code class="classname">AnonymousAuthenticationFilter</code>
+ is added by default and unless you have
+ <a class="link" href="#ns-session-fixation" title="Session Fixation Attack Protection">session-fixation protection</a>
+ disabled, a <code class="classname">SessionManagementFilter</code> will also be added
+ to the filter chain.
+ </p></td></tr></table></div><p> If you're replacing a namespace filter which requires an authentication entry
+ point (i.e. where the authentication process is triggered by an attempt by an
+ unauthenticated user to access to a secured resource), you will need to add a custom
+ entry point bean too. </p><div class="section" title="Setting a Custom AuthenticationEntryPoint"><div class="titlepage"><div><div><h4 class="title"><a name="ns-entry-point-ref"></a>Setting a Custom
+ <code class="interfacename">AuthenticationEntryPoint</code></h4></div></div></div><p> If you aren't using form login, OpenID or basic authentication through the
+ namespace, you may want to define an authentication filter and entry point using
+ a traditional bean syntax and link them into the namespace, as we've just seen.
+ The corresponding <code class="interfacename">AuthenticationEntryPoint</code> can be
+ set using the <code class="literal">entry-point-ref</code> attribute on the
+ <code class="literal"><http></code> element. </p><p> The CAS sample application is a good example of the use of custom beans with
+ the namespace, including this syntax. If you aren't familiar with authentication
+ entry points, they are discussed in the <a class="link" href="#tech-intro-auth-entry-point" title="6.4.2 AuthenticationEntryPoint">technical overview</a> chapter.
+ </p></div></div></div><div class="section" title="3.4 Method Security"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ns-method-security"></a>3.4 Method Security</h2></div></div></div><p>From version 2.0 onwards Spring Security has improved support substantially for adding
+ security to your service layer methods. It provides support for JSR-250 annotation
+ security as well as the framework's original <code class="literal">@Secured</code> annotation.
+ From 3.0 you can also make use of new <a class="link" href="#el-access" title="16. Expression-Based Access Control">expression-based
+ annotations</a>. You can apply security to a single bean, using the
+ <code class="literal">intercept-methods</code> element to decorate the bean declaration, or you
+ can secure multiple beans across the entire service layer using the AspectJ style
+ pointcuts. </p><div class="section" title="3.4.1 The <global-method-security> Element"><div class="titlepage"><div><div><h3 class="title"><a name="ns-global-method"></a>3.4.1 The <code class="literal"><global-method-security></code> Element</h3></div></div></div><p> This element is used to enable annotation-based security in your application (by
+ setting the appropriate attributes on the element), and also to group together
+ security pointcut declarations which will be applied across your entire application
+ context. You should only declare one
+ <code class="literal"><global-method-security></code> element. The following declaration
+ would enable support for Spring Security's <code class="literal">@Secured</code>: </p><pre class="programlisting">
+ <span class="hl-tag"><global-method-security</span> <span class="hl-attribute">secured-annotations</span>=<span class="hl-value">"enabled"</span><span class="hl-tag"> /></span>
</pre><p> Adding an annotation to a method (on an class or interface) would then limit
- the access to that method accordingly. Spring Security's native annotation support defines a
- set of attributes for the method. These will be passed to the
- <code class="interfacename">AccessDecisionManager</code> for it to make the actual decision:
- </p><pre class="programlisting">
+ the access to that method accordingly. Spring Security's native annotation support
+ defines a set of attributes for the method. These will be passed to the
+ <code class="interfacename">AccessDecisionManager</code> for it to make the actual
+ decision:
+ </p><pre class="programlisting">
<span class="hl-keyword">public</span> <span class="hl-keyword">interface</span> BankService {
<i><span class="hl-annotation" style="color: gray">@Secured("IS_AUTHENTICATED_ANONYMOUSLY")</span></i>
@@ -709,16 +756,15 @@ List<OpenIDAttribute> attributes = token.getAttributes();</pre><p>The
<span class="hl-keyword">public</span> Account post(Account account, <span class="hl-keyword">double</span> amount);
}
</pre><p>Support
- for JSR-250 annotations can be enabled using </p><pre class="programlisting">
- <global-method-security jsr250-annotations="enabled" />
+ for JSR-250 annotations can be enabled using </p><pre class="programlisting">
+ <span class="hl-tag"><global-method-security</span> <span class="hl-attribute">jsr250-annotations</span>=<span class="hl-value">"enabled"</span><span class="hl-tag"> /></span>
- </pre><p>These are standards-based and allow simple role-based constraints to be
- applied but do not have the power Spring Security's native annotations.
- To use the new expression-based syntax, you would use
-</p><pre class="programlisting">
- <global-method-security pre-post-annotations="enabled" />
+ </pre><p>These are standards-based and allow simple role-based constraints to
+ be applied but do not have the power Spring Security's native annotations. To use
+ the new expression-based syntax, you would use </p><pre class="programlisting">
+ <span class="hl-tag"><global-method-security</span> <span class="hl-attribute">pre-post-annotations</span>=<span class="hl-value">"enabled"</span><span class="hl-tag"> /></span>
</pre><p>and the equivalent Java code would
- be</p><pre class="programlisting">
+ be</p><pre class="programlisting">
<span class="hl-keyword">public</span> <span class="hl-keyword">interface</span> BankService {
<i><span class="hl-annotation" style="color: gray">@PreAuthorize("isAnonymous()")</span></i>
@@ -731,56 +777,65 @@ List<OpenIDAttribute> attributes = token.getAttributes();</pre><p>The
<span class="hl-keyword">public</span> Account post(Account account, <span class="hl-keyword">double</span> amount);
}
</pre><p>Expression-based
- annotations are a good choice if you need to define simple rules that go beyond checking the
- role names against the user's list of authorities. You can enable more than one type of
- annotation in the same application, but you should avoid mixing annotations types in the
- same interface or class to avoid confusion.</p><div class="section" title="Adding Security Pointcuts using protect-pointcut"><div class="titlepage"><div><div><h4 class="title"><a name="ns-protect-pointcut"></a>Adding Security Pointcuts using <code class="literal">protect-pointcut</code></h4></div></div></div><p> The use of <code class="literal">protect-pointcut</code> is particularly powerful, as it allows
- you to apply security to many beans with only a simple declaration. Consider the following
- example: </p><pre class="programlisting">
+ annotations are a good choice if you need to define simple rules that go beyond
+ checking the role names against the user's list of authorities. You can enable more
+ than one type of annotation in the same application, but you should avoid mixing
+ annotations types in the same interface or class to avoid confusion. </p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>The annotated methods will only be secured for instances which are defined as
+ Spring beans (in the same application context in which method-security is
+ enabled). If you want to secure instances which are not created by Spring (using
+ the <code class="literal">new</code> operator, for example) then you need to use AspectJ.
+ </p></td></tr></table></div><p> </p><div class="section" title="Adding Security Pointcuts using protect-pointcut"><div class="titlepage"><div><div><h4 class="title"><a name="ns-protect-pointcut"></a>Adding Security Pointcuts using <code class="literal">protect-pointcut</code></h4></div></div></div><p> The use of <code class="literal">protect-pointcut</code> is particularly powerful, as
+ it allows you to apply security to many beans with only a simple declaration.
+ Consider the following example: </p><pre class="programlisting">
<span class="hl-tag"><global-method-security></span>
<span class="hl-tag"><protect-pointcut</span> <span class="hl-attribute">expression</span>=<span class="hl-value">"execution(* com.mycompany.*Service.*(..))"</span>
<span class="hl-attribute">access</span>=<span class="hl-value">"ROLE_USER"</span><span class="hl-tag">/></span>
<span class="hl-tag"></global-method-security></span>
</pre><p> This will protect all methods on beans declared in the application
- context whose classes are in the <code class="literal">com.mycompany</code> package and whose class
- names end in "Service". Only users with the <code class="literal">ROLE_USER</code> role will be able
- to invoke these methods. As with URL matching, the most specific matches must come first
- in the list of pointcuts, as the first matching expression will be used. </p></div></div></div><div class="section" title="2.5 The Default AccessDecisionManager"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ns-access-manager"></a>2.5 The Default AccessDecisionManager</h2></div></div></div><p> This section assumes you have some knowledge of the underlying architecture for
- access-control within Spring Security. If you don't you can skip it and come back to it later,
- as this section is only really relevant for people who need to do some customization in order
- to use more than simple role-based security. </p><p> When you use a namespace configuration, a default instance of
- <code class="interfacename">AccessDecisionManager</code> is automatically registered for you and
- will be used for making access decisions for method invocations and web URL access, based on
- the access attributes you specify in your <code class="literal">intercept-url</code> and
- <code class="literal">protect-pointcut</code> declarations (and in annotations if you are using
- annotation secured methods). </p><p> The default strategy is to use an <code class="classname">AffirmativeBased</code>
- <code class="interfacename">AccessDecisionManager</code> with a <code class="classname">RoleVoter</code>
- and an <code class="classname">AuthenticatedVoter</code>. You can find out more about these in the
- chapter on <a class="link" href="authorization" target="_top">authorization</a>.</p><div class="section" title="2.5.1 Customizing the AccessDecisionManager"><div class="titlepage"><div><div><h3 class="title"><a name="ns-custom-access-mgr"></a>2.5.1 Customizing the AccessDecisionManager</h3></div></div></div><p> If you need to use a more complicated access control strategy then it is easy to set an
- alternative for both method and web security. </p><p> For method security, you do this by setting the
- <code class="literal">access-decision-manager-ref</code> attribute on
- <code class="literal">global-method-security</code> to the Id of the appropriate
- <code class="interfacename">AccessDecisionManager</code> bean in the application context: </p><pre class="programlisting">
+ context whose classes are in the <code class="literal">com.mycompany</code> package and
+ whose class names end in "Service". Only users with the
+ <code class="literal">ROLE_USER</code> role will be able to invoke these methods. As with
+ URL matching, the most specific matches must come first in the list of
+ pointcuts, as the first matching expression will be used. </p></div></div></div><div class="section" title="3.5 The Default AccessDecisionManager"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ns-access-manager"></a>3.5 The Default AccessDecisionManager</h2></div></div></div><p> This section assumes you have some knowledge of the underlying architecture for
+ access-control within Spring Security. If you don't you can skip it and come back to it
+ later, as this section is only really relevant for people who need to do some
+ customization in order to use more than simple role-based security. </p><p> When you use a namespace configuration, a default instance of
+ <code class="interfacename">AccessDecisionManager</code> is automatically registered for you
+ and will be used for making access decisions for method invocations and web URL access,
+ based on the access attributes you specify in your <code class="literal">intercept-url</code> and
+ <code class="literal">protect-pointcut</code> declarations (and in annotations if you are using
+ annotation secured methods). </p><p> The default strategy is to use an <code class="classname">AffirmativeBased</code>
+ <code class="interfacename">AccessDecisionManager</code> with a
+ <code class="classname">RoleVoter</code> and an <code class="classname">AuthenticatedVoter</code>. You
+ can find out more about these in the chapter on <a class="link" href="#authz-arch" title="14. Authorization Architecture">authorization</a>.</p><div class="section" title="3.5.1 Customizing the AccessDecisionManager"><div class="titlepage"><div><div><h3 class="title"><a name="ns-custom-access-mgr"></a>3.5.1 Customizing the AccessDecisionManager</h3></div></div></div><p> If you need to use a more complicated access control strategy then it is easy to
+ set an alternative for both method and web security. </p><p> For method security, you do this by setting the
+ <code class="literal">access-decision-manager-ref</code> attribute on
+ <code class="literal">global-method-security</code> to the <code class="literal">id</code> of the appropriate
+ <code class="interfacename">AccessDecisionManager</code> bean in the application
+ context: </p><pre class="programlisting">
<span class="hl-tag"><global-method-security</span> <span class="hl-attribute">access-decision-manager-ref</span>=<span class="hl-value">"myAccessDecisionManagerBean"</span><span class="hl-tag">></span>
...
<span class="hl-tag"></global-method-security></span>
- </pre><p> The syntax for web security is the same, but on the <code class="literal">http</code> element: </p><pre class="programlisting">
+ </pre><p> The syntax for web security is the same, but on the <code class="literal">http</code>
+ element: </p><pre class="programlisting">
<span class="hl-tag"><http</span> <span class="hl-attribute">access-decision-manager-ref</span>=<span class="hl-value">"myAccessDecisionManagerBean"</span><span class="hl-tag">></span>
...
<span class="hl-tag"></http></span>
- </pre></div></div><div class="section" title="2.6 The Authentication Manager and the Namespace"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ns-auth-manager"></a>2.6 The Authentication Manager and the Namespace</h2></div></div></div><p> The main interface which provides authentication services in Spring Security is the
- <code class="interfacename">AuthenticationManager</code>. This is usually an instance of Spring
- Security's <code class="classname">ProviderManager</code> class, which you may already be familiar
- with if you've used the framework before. If not, it will be covered later, in the <a class="link" href="#tech-intro-authentication" title="5.3 Authentication">technical overview chapter</a>. The bean instance
- is registered using the <code class="literal">authentication-manager</code> namespace element. You can't
- use a custom <code class="classname">AuthenticationManager</code> if you are using either HTTP or
- method security through the namespace, but this should not be a problem as you have full
- control over the <code class="classname">AuthenticationProvider</code>s that are used.</p><p> You may want to register additional <code class="classname">AuthenticationProvider</code> beans
- with the <code class="classname">ProviderManager</code> and you can do this using the
- <code class="literal"><authentication-provider></code> element with the <code class="literal">ref</code>
- attribute, where the value of the attribute is the name of the provider bean you want to add.
- For example: </p><pre class="programlisting">
+ </pre></div></div><div class="section" title="3.6 The Authentication Manager and the Namespace"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ns-auth-manager"></a>3.6 The Authentication Manager and the Namespace</h2></div></div></div><p> The main interface which provides authentication services in Spring Security is the
+ <code class="interfacename">AuthenticationManager</code>. This is usually an instance of
+ Spring Security's <code class="classname">ProviderManager</code> class, which you may already be
+ familiar with if you've used the framework before. If not, it will be covered later, in
+ the <a class="link" href="#tech-intro-authentication" title="6.3 Authentication">technical overview chapter</a>. The
+ bean instance is registered using the <code class="literal">authentication-manager</code>
+ namespace element. You can't use a custom <code class="classname">AuthenticationManager</code>
+ if you are using either HTTP or method security through the namespace, but this should
+ not be a problem as you have full control over the
+ <code class="classname">AuthenticationProvider</code>s that are used.</p><p> You may want to register additional <code class="classname">AuthenticationProvider</code>
+ beans with the <code class="classname">ProviderManager</code> and you can do this using the
+ <code class="literal"><authentication-provider></code> element with the
+ <code class="literal">ref</code> attribute, where the value of the attribute is the name of the
+ provider bean you want to add. For example: </p><pre class="programlisting">
<span class="hl-tag"><authentication-manager></span>
<span class="hl-tag"><authentication-provider</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"casAuthenticationProvider"</span><span class="hl-tag">/></span>
<span class="hl-tag"></authentication-manager></span>
@@ -789,10 +844,10 @@ List<OpenIDAttribute> attributes = token.getAttributes();</pre><p>The
<span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.cas.authentication.CasAuthenticationProvider"</span><span class="hl-tag">></span>
...
<span class="hl-tag"></bean></span>
- </pre><p> Another common requirement is that another bean in the context may require a reference to
- the <code class="interfacename">AuthenticationManager</code>. You can easily register an alias for
- the <code class="interfacename">AuthenticationManager</code> and use this name elsewhere in your
- application context. </p><pre class="programlisting">
+ </pre><p> Another common requirement is that another bean in the context may require a
+ reference to the <code class="interfacename">AuthenticationManager</code>. You can easily
+ register an alias for the <code class="interfacename">AuthenticationManager</code> and use
+ this name elsewhere in your application context. </p><pre class="programlisting">
<span class="hl-tag"><security:authentication-manager</span> <span class="hl-attribute">alias</span>=<span class="hl-value">"authenticationManager"</span><span class="hl-tag">></span>
...
<span class="hl-tag"></security:authentication-manager></span>
@@ -802,50 +857,58 @@ List<OpenIDAttribute> attributes = token.getAttributes();</pre><p>The
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"authenticationManager"</span><span class="hl-tag">/></span>
...
<span class="hl-tag"></bean></span>
- </pre></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e358" href="#d0e358" class="para">1</a>] </sup>You can find
- out more about the use of the <code class="literal">ldap-server</code> element in the chapter on
- <a class="link" href="#ldap" title="18. LDAP Authentication">LDAP</a>.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e480" href="#d0e480" class="para">2</a>] </sup>See the section on Request
- Matching in the Web Application Infrastructure chapter for more details
- on how matches are actually performed.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e493" href="#d0e493" class="para">3</a>] </sup>The
- interpretation of the comma-separated values in the <code class="literal">access</code> attribute
- depends on the implementation of the <a class="link" href="#ns-access-manager" title="2.5 The Default AccessDecisionManager">AccessDecisionManager</a> which is used. In Spring Security 3.0, the attribute can
- also be populated with an <a class="link" href="#el-access" title="15. Expression-Based Access Control">EL
- expression</a>.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e602" href="#d0e602" class="para">4</a>] </sup>In versions prior
- to 3.0, this list also included remember-me functionality. This could cause some
- confusing errors with some configurations and was removed in 3.0. In 3.0, the addition
- of an <code class="classname">AnonymousAuthenticationFilter</code> is part of the default
- <code class="literal"><http></code> configuration, so the <code class="literal"><anonymous
- /></code> element is added regardless of whether <code class="literal">auto-config</code>
- is enabled.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e635" href="#d0e635" class="para">5</a>] </sup>See the
- chapter on <a class="link" href="#anonymous" title="12. Anonymous Authentication">anonymous authentication</a> and also the
- <a class="link" href="#authz-authenticated-voter" title="AuthenticatedVoter">AuthenticatedVoter</a> class for
- more details on how the value <code class="literal">IS_AUTHENTICATED_ANONYMOUSLY</code> is
- processed.</p></div></div></div><div class="chapter" title="3. Sample Applications"><div class="titlepage"><div><div><h1 class="title"><a name="sample-apps"></a>Sample Applications</h1></div></div></div><p> There are several sample web applications that are available with the project. To avoid
+ </pre></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e521" href="#d0e521" class="para">1</a>] </sup>You can find out more about the use of the <code class="literal">ldap-server</code> element
+ in the chapter on <a class="link" href="#ldap" title="19. LDAP Authentication">LDAP</a>.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e643" href="#d0e643" class="para">2</a>] </sup>See the section on <a class="link" href="#request-matching" title="8.4 Request Matching and HttpFirewall">Request
+ Matching</a> in the Web Application Infrastructure chapter for more details
+ on how matches are actually performed.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e656" href="#d0e656" class="para">3</a>] </sup>The interpretation of the comma-separated values in the
+ <code class="literal">access</code> attribute depends on the implementation of the <a class="link" href="#ns-access-manager" title="3.5 The Default AccessDecisionManager">AccessDecisionManager</a> which is used. In
+ Spring Security 3.0, the attribute can also be populated with an <a class="link" href="#el-access" title="16. Expression-Based Access Control">EL expression</a>.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e765" href="#d0e765" class="para">4</a>] </sup>In versions prior to 3.0, this list also included remember-me
+ functionality. This could cause some confusing errors with some
+ configurations and was removed in 3.0. In 3.0, the addition of an
+ <code class="classname">AnonymousAuthenticationFilter</code> is part of the default
+ <code class="literal"><http></code> configuration, so the <code class="literal"><anonymous
+ /></code> element is added regardless of whether
+ <code class="literal">auto-config</code> is enabled.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e801" href="#d0e801" class="para">5</a>] </sup>See the chapter on <a class="link" href="#anonymous" title="13. Anonymous Authentication">anonymous
+ authentication</a> and also the <a class="link" href="#authz-authenticated-voter" title="AuthenticatedVoter">AuthenticatedVoter</a> class for more details on how the value
+ <code class="literal">IS_AUTHENTICATED_ANONYMOUSLY</code> is processed.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e832" href="#d0e832" class="para">6</a>] </sup>The use of multiple <code class="literal"><http></code> elements is an important
+ feature, allowing the namespace to simultaneously support both stateful and
+ stateless paths within the same application, for example. The previous syntax,
+ using the attribute <code class="literal">filters="none"</code> on an
+ <code class="literal">intercept-url</code> element is incompatible with this change and is
+ no longer supported in 3.1.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e1018" href="#d0e1018" class="para">7</a>] </sup>For more details on how channel-processing is implemented, see the Javadoc
+ for <code class="classname">ChannelProcessingFilter</code> and related classes.
+ </p></div><div class="footnote"><p><sup>[<a name="ftn.d0e1047" href="#d0e1047" class="para">8</a>] </sup>If you are running your application behind a proxy, you may also be able
+ to remove the session cookie by configuring the proxy server. For example,
+ using Apache HTTPD's mod_headers, the following directive would delete the
+ <code class="literal">JSESSIONID</code> cookie by expiring it in the response to a
+ logout request (assuming the application is deployed under the path
+ <code class="literal">/tutorial</code>):
+ <pre class="programlisting"> <span class="hl-tag"><LocationMatch</span> <span class="hl-attribute">"/tutorial/j_spring_security_logout"></span>
+ <span class="hl-attribute">Header</span> <span class="hl-attribute">always</span> <span class="hl-attribute">set</span> <span class="hl-attribute">Set-Cookie</span> <span class="hl-attribute">"JSESSIONID</span>=<span class="hl-value">;Path=</span><span class="hl-tag">/t</span>utorial;Expires=Thu, 01 Jan 1970 00:00:00 GMT"
+ <span class="hl-tag"></LocationMatch></span></pre></p></div></div></div><div class="chapter" title="4. Sample Applications"><div class="titlepage"><div><div><h1 class="title"><a name="sample-apps"></a>Sample Applications</h1></div></div></div><p> There are several sample web applications that are available with the project. To avoid
an overly large download, only the "tutorial" and "contacts" samples are included in the
- distribution zip file. You can either build the others yourself, or you can obtain the war
- files individually from the central Maven repository. We'd recommend the former. You can get
- the source as described in <a class="link" href="#get-source" title="1.4.2 Checking out the Source">the introduction</a> and it's
- easy to build the project using Maven. There is more information on the project web site at
- <a class="link" href="http://www.springsource.org/security/" target="_top">
- http://www.springsource.org/security/ </a> if you need it. All paths referred to in
- this chapter are relative to the project source directory. </p><div class="section" title="3.1 Tutorial Sample"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="tutorial-sample"></a>3.1 Tutorial Sample</h2></div></div></div><p> The tutorial sample is a nice basic example to get you started. It uses simple
+ distribution zip file. The others can be built directly from the source which you can obtain
+ as described in <a class="link" href="#get-source" title="1.4.2 Checking out the Source">the introduction</a>. It's easy to build
+ the project yourself and there's more information on the project web site at <a class="link" href="http://www.springsource.org/security/" target="_top">
+ http://www.springsource.org/security/ </a>. All paths referred to in this chapter are
+ relative to the project source directory. </p><div class="section" title="4.1 Tutorial Sample"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="tutorial-sample"></a>4.1 Tutorial Sample</h2></div></div></div><p> The tutorial sample is a nice basic example to get you started. It uses simple
namespace configuration throughout. The compiled application is included in the
distribution zip file, ready to be deployed into your web container
- (<code class="filename">spring-security-samples-tutorial-3.0.x.war</code>). The <a class="link" href="#ns-form-and-basic" title="Form and Basic Login Options">form-based</a> authentication mechanism is used
- in combination with the commonly-used <a class="link" href="#remember-me" title="10. Remember-Me Authentication">remember-me</a>
+ (<code class="filename">spring-security-samples-tutorial-3.1.x.war</code>). The <a class="link" href="#ns-form-and-basic" title="3.2.3 Form and Basic Login Options">form-based</a> authentication mechanism is used in
+ combination with the commonly-used <a class="link" href="#remember-me" title="11. Remember-Me Authentication">remember-me</a>
authentication provider to automatically remember the login using cookies.</p><p>We recommend you start with the tutorial sample, as the XML is minimal and easy to
follow. Most importantly, you can easily add this one XML file (and its corresponding
- <code class="literal">web.xml</code> entries) to your existing application. Only when this
- basic integration is achieved do we suggest you attempt adding in method authorization
- or domain object security.</p></div><div class="section" title="3.2 Contacts"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="contacts-sample"></a>3.2 Contacts</h2></div></div></div><p> The Contacts Sample is an advanced example in that it illustrates the more powerful
+ <code class="literal">web.xml</code> entries) to your existing application. Only when this basic
+ integration is achieved do we suggest you attempt adding in method authorization or
+ domain object security.</p></div><div class="section" title="4.2 Contacts"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="contacts-sample"></a>4.2 Contacts</h2></div></div></div><p> The Contacts Sample is an advanced example in that it illustrates the more powerful
features of domain object access control lists (ACLs) in addition to basic application
security. The application provides an interface with which the users are able to
administer a simple database of contacts (the domain objects).</p><p>To deploy, simply copy the WAR file from Spring Security distribution into your
container’s <code class="literal">webapps</code> directory. The war should be called
- <code class="filename">spring-security-samples-contacts-3.0.x.war</code> (the appended
- version number will vary depending on what release you are using). </p><p>After starting your container, check the application can load. Visit
- <code class="literal">http://localhost:8080/contacts</code> (or whichever URL is appropriate
- for your web container and the WAR you deployed). </p><p>Next, click "Debug". You will be prompted to authenticate, and a series of usernames
+ <code class="filename">spring-security-samples-contacts-3.1.x.war</code> (the appended version
+ number will vary depending on what release you are using). </p><p>After starting your container, check the application can load. Visit
+ <code class="literal">http://localhost:8080/contacts</code> (or whichever URL is appropriate for
+ your web container and the WAR you deployed). </p><p>Next, click "Debug". You will be prompted to authenticate, and a series of usernames
and passwords are suggested on that page. Simply authenticate with any of these and view
the resulting page. It should contain a success message similar to the following:
</p><div class="literallayout"><p><br>
@@ -875,84 +938,102 @@ Success! Your web filters appear to be proper
</p></div><p>Once you successfully receive the above message, return to the sample application's
home page and click "Manage". You can then try out the application. Notice that only the
contacts available to the currently logged on user are displayed, and only users with
- <code class="literal">ROLE_SUPERVISOR</code> are granted access to delete their contacts.
- Behind the scenes, the <code class="classname">MethodSecurityInterceptor</code> is securing the
+ <code class="literal">ROLE_SUPERVISOR</code> are granted access to delete their contacts. Behind
+ the scenes, the <code class="classname">MethodSecurityInterceptor</code> is securing the
business objects. </p><p>The application allows you to modify the access control lists associated with
different contacts. Be sure to give this a try and understand how it works by reviewing
- the application context XML files.</p></div><div class="section" title="3.3 LDAP Sample"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ldap-sample"></a>3.3 LDAP Sample</h2></div></div></div><p> The LDAP sample application provides a basic configuration and sets up both a
+ the application context XML files.</p></div><div class="section" title="4.3 LDAP Sample"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ldap-sample"></a>4.3 LDAP Sample</h2></div></div></div><p> The LDAP sample application provides a basic configuration and sets up both a
namespace configuration and an equivalent configuration using traditional beans, both in
the same application context file. This means there are actually two identical
- authentication providers configured in this application. </p></div><div class="section" title="3.4 CAS Sample"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="cas-sample"></a>3.4 CAS Sample</h2></div></div></div><p> The CAS sample requires that you run both a CAS server and CAS client. It isn't
+ authentication providers configured in this application. </p></div><div class="section" title="4.4 OpenID Sample"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="openid-sample"></a>4.4 OpenID Sample</h2></div></div></div><p>
+ The OpenID sample demonstrates how to use the namespace to configure OpenID and how to set up
+ <a class="link" href="http://openid.net/specs/openid-attribute-exchange-1_0.html" target="_top">attribute exchange</a>
+ configurations for Google, Yahoo and MyOpenID identity providers (you can experiment with adding others
+ if you wish). It uses the JQuery-based <a class="link" href="http://code.google.com/p/openid-selector/" target="_top">openid-selector</a>
+ project to provide a user-friendly login page which allows the user to easily select a provider, rather than
+ typing in the full OpenID identifier.
+ </p><p>
+ The application differs from normal authentication scenarios in that it allows any user to access the site (provided
+ their OpenID authentication is successful). The first time you login, you will get a <span class="quote">“<span class="quote">Welcome [your name]"</span>”</span>
+ message. If you logout and log back in (with the same OpenID identity) then this should change to <span class="quote">“<span class="quote">Welcome Back</span>”</span>.
+ This is achieved by using a custom <code class="interfacename">UserDetailsService</code> which assigns a standard role
+ to any user and stores the identities internally in a map. Obviously a real application would use a database instead.
+ Have a look at the source form more information. This class also takes into account the fact that different attributes may be returned
+ from different providers and builds the name with which it addresses the user accordingly.
+ </p></div><div class="section" title="4.5 CAS Sample"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="cas-sample"></a>4.5 CAS Sample</h2></div></div></div><p> The CAS sample requires that you run both a CAS server and CAS client. It isn't
included in the distribution so you should check out the project code as described in
- <a class="link" href="#get-source" title="1.4.2 Checking out the Source">the introduction</a>. You'll find the relevant
- files under the <code class="filename">sample/cas</code> directory. There's also a
- <code class="filename">Readme.txt</code> file in there which explains how to run both the
- server and the client directly from the source tree, complete with SSL support. You have
- to download the CAS Server web application (a war file) from the CAS site and drop it
- into the <code class="filename">samples/cas/server</code> directory. </p></div><div class="section" title="3.5 Pre-Authentication Sample"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="preauth-sample"></a>3.5 Pre-Authentication Sample</h2></div></div></div><p> This sample application demonstrates how to wire up beans from the <a class="link" href="#preauth" title="17. Pre-Authentication Scenarios">pre-authentication</a> framework to make use of login
+ <a class="link" href="#get-source" title="1.4.2 Checking out the Source">the introduction</a>. You'll find the relevant files
+ under the <code class="filename">sample/cas</code> directory. There's also a
+ <code class="filename">Readme.txt</code> file in there which explains how to run both the server
+ and the client directly from the source tree, complete with SSL support.</p></div><div class="section" title="4.6 JAAS Sample"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="jaas-sample"></a>4.6 JAAS Sample</h2></div></div></div><p>The JAAS sample is very simple example of how to use a JAAS LoginModule with Spring Security. The provided LoginModule will
+ successfully authenticate a user if the username equals the password otherwise a LoginException is thrown. The AuthorityGranter
+ used in this example always grants the role ROLE_USER. The sample application also demonstrates how to run as the JAAS Subject
+ returned by the LoginModule by setting <a class="link" href="#nsa-http-jaas-api-provision" title="jaas-api-provision">jaas-api-provision</a> equal to "true".</p></div><div class="section" title="4.7 Pre-Authentication Sample"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="preauth-sample"></a>4.7 Pre-Authentication Sample</h2></div></div></div><p> This sample application demonstrates how to wire up beans from the <a class="link" href="#preauth" title="18. Pre-Authentication Scenarios">pre-authentication</a> framework to make use of login
information from a J2EE container. The user name and roles are those setup by the
- container. </p><p> The code is in <code class="filename">samples/preauth</code>. </p></div></div><div class="chapter" title="4. Spring Security Community"><div class="titlepage"><div><div><h1 class="title"><a name="community"></a>Spring Security Community</h1></div></div></div><div class="section" title="4.1 Issue Tracking"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="jira"></a>4.1 Issue Tracking</h2></div></div></div><p>Spring Security uses JIRA to manage bug reports and enhancement requests. If you find
+ container. </p><p> The code is in <code class="filename">samples/preauth</code>. </p></div></div><div class="chapter" title="5. Spring Security Community"><div class="titlepage"><div><div><h1 class="title"><a name="community"></a>Spring Security Community</h1></div></div></div><div class="section" title="5.1 Issue Tracking"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="jira"></a>5.1 Issue Tracking</h2></div></div></div><p>Spring Security uses JIRA to manage bug reports and enhancement requests. If you find
a bug, please log a report using JIRA. Do not log it on the support forum, mailing list
or by emailing the project's developers. Such approaches are ad-hoc and we prefer to
manage bugs using a more formal process.</p><p>If possible, in your issue report please provide a JUnit test that demonstrates any
incorrect behaviour. Or, better yet, provide a patch that corrects the issue. Similarly,
enhancements are welcome to be logged in the issue tracker, although we only accept
enhancement requests if you include corresponding unit tests. This is necessary to
- ensure project test coverage is adequately maintained.</p><p>You can access the issue tracker at <a class="link" href="http://jira.springsource.org/browse/SEC" target="_top">http://jira.springsource.org/browse/SEC</a>. </p></div><div class="section" title="4.2 Becoming Involved"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="becoming-involved"></a>4.2 Becoming Involved</h2></div></div></div><p>We welcome your involvement in the Spring Security project. There are many ways of
+ ensure project test coverage is adequately maintained.</p><p>You can access the issue tracker at <a class="link" href="http://jira.springsource.org/browse/SEC" target="_top">http://jira.springsource.org/browse/SEC</a>. </p></div><div class="section" title="5.2 Becoming Involved"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="becoming-involved"></a>5.2 Becoming Involved</h2></div></div></div><p>We welcome your involvement in the Spring Security project. There are many ways of
contributing, including reading the forum and responding to questions from other people,
writing new code, improving existing code, assisting with documentation, developing
- samples or tutorials, or simply making suggestions.</p></div><div class="section" title="4.3 Further Information"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="further-info"></a>4.3 Further Information</h2></div></div></div><p>Questions and comments on Spring Security are welcome. You can use the Spring
- Community Forum web site at <code class="uri"><a class="uri" href="http://forum.springsource.org" target="_top">http://forum.springsource.org</a></code> to discuss Spring Security with other users of
- the framework. Remember to use JIRA for bug reports, as explained above.</p></div></div></div><div class="part" title="Part II. Architecture and Implementation"><div class="titlepage"><div><div><h1 class="title"><a name="overall-architecture"></a>Part II. Architecture and Implementation</h1></div></div></div><div class="partintro" title="Architecture and Implementation"><div></div><p>Once you are familiar with setting up and running some namespace-configuration based
- applications, you may wish to develop more of an understanding of how the framework actually
- works behind the namespace facade. Like most software, Spring Security has certain central
- interfaces, classes and conceptual abstractions that are commonly used throughout the
- framework. In this part of the reference guide we will look at some of these and see how
- they work together to support authentication and access-control within Spring
- Security.</p></div><div class="chapter" title="5. Technical Overview"><div class="titlepage"><div><div><h1 class="title"><a name="technical-overview"></a>Technical Overview</h1></div></div></div><div class="section" title="5.1 Runtime Environment"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="runtime-environment"></a>5.1 Runtime Environment</h2></div></div></div><p>Spring Security 3.0 requires a Java 5.0 Runtime Environment or higher. As Spring Security
- aims to operate in a self-contained manner, there is no need to place any special
- configuration files into your Java Runtime Environment. In particular, there is no need to
- configure a special Java Authentication and Authorization Service (JAAS) policy file or place
- Spring Security into common classpath locations.</p><p>Similarly, if you are using an EJB Container or Servlet Container there is no need to put
- any special configuration files anywhere, nor include Spring Security in a server classloader.
- All the required files will be contained within your application.</p><p>This design offers maximum deployment time flexibility, as you can simply copy your target
- artifact (be it a JAR, WAR or EAR) from one system to another and it will immediately
- work.</p></div><div class="section" title="5.2 Core Components"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="core-components"></a>5.2 Core Components</h2></div></div></div><p>In Spring Security 3.0, the contents of the <code class="filename">spring-security-core</code> jar
- were stripped down to the bare minimum. It no longer contains any code related to
- web-application security, LDAP or namespace configuration. We'll take a look here at some of
- the Java types that you'll find in the core module. They represent the building blocks of the
- the framework, so if you ever need to go beyond a simple namespace configuration then it's
- important that you understand what they are, even if you don't actually need to interact with
- them directly.</p><div class="section" title="5.2.1 SecurityContextHolder, SecurityContext and Authentication Objects"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1518"></a>5.2.1 SecurityContextHolder, SecurityContext and Authentication Objects </h3></div></div></div><p>The most fundamental object is <code class="classname">SecurityContextHolder</code>. This is
- where we store details of the present security context of the application, which includes
- details of the principal currently using the application. By default the
- <code class="classname">SecurityContextHolder</code> uses a <code class="literal">ThreadLocal</code> to
- store these details, which means that the security context is always available to methods in
- the same thread of execution, even if the security context is not explicitly passed around
- as an argument to those methods. Using a <code class="literal">ThreadLocal</code> in this way is quite
- safe if care is taken to clear the thread after the present principal's request is
- processed. Of course, Spring Security takes care of this for you automatically so there is
- no need to worry about it.</p><p>Some applications aren't entirely suitable for using a <code class="literal">ThreadLocal</code>,
- because of the specific way they work with threads. For example, a Swing client might want
- all threads in a Java Virtual Machine to use the same security context.
- <code class="classname">SecurityContextHolder</code> can be configured with a strategy on startup
- to specify how you would like the context to be stored. For a standalone application you
- would use the <code class="literal">SecurityContextHolder.MODE_GLOBAL</code> strategy. Other
- applications might want to have threads spawned by the secure thread also assume the same
- security identity. This is achieved by using
- <code class="literal">SecurityContextHolder.MODE_INHERITABLETHREADLOCAL</code>. You can change the
- mode from the default <code class="literal">SecurityContextHolder.MODE_THREADLOCAL</code> in two ways.
- The first is to set a system property, the second is to call a static method on
- <code class="classname">SecurityContextHolder</code>. Most applications won't need to change from
- the default, but if you do, take a look at the JavaDocs for
- <code class="classname">SecurityContextHolder</code> to learn more.</p><div class="section" title="Obtaining information about the current user"><div class="titlepage"><div><div><h4 class="title"><a name="d0e1558"></a>Obtaining information about the current user</h4></div></div></div><p>Inside the <code class="classname">SecurityContextHolder</code> we store details of the
- principal currently interacting with the application. Spring Security uses an
- <code class="interfacename">Authentication</code> object to represent this information. You
- won't normally need to create an <code class="interfacename">Authentication</code> object
- yourself, but it is fairly common for users to query the
- <code class="interfacename">Authentication</code> object. You can use the following code
- block - from anywhere in your application - to obtain the name of the currently
- authenticated user, for example:</p><pre class="programlisting">
+ samples or tutorials, or simply making suggestions.</p></div><div class="section" title="5.3 Further Information"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="further-info"></a>5.3 Further Information</h2></div></div></div><p>Questions and comments on Spring Security are welcome. You can use the Spring
+ Community Forum web site at <code class="uri"><a class="uri" href="http://forum.springsource.org" target="_top">http://forum.springsource.org</a></code> to discuss Spring Security with other users of the
+ framework. Remember to use JIRA for bug reports, as explained above.</p></div></div></div><div class="part" title="Part II. Architecture and Implementation"><div class="titlepage"><div><div><h1 class="title"><a name="overall-architecture"></a>Part II. Architecture and Implementation</h1></div></div></div><div class="partintro" title="Architecture and Implementation"><div></div><p>Once you are familiar with setting up and running some namespace-configuration
+ based applications, you may wish to develop more of an understanding of how the
+ framework actually works behind the namespace facade. Like most software, Spring
+ Security has certain central interfaces, classes and conceptual abstractions that
+ are commonly used throughout the framework. In this part of the reference guide we
+ will look at some of these and see how they work together to support authentication
+ and access-control within Spring Security.</p></div><div class="chapter" title="6. Technical Overview"><div class="titlepage"><div><div><h1 class="title"><a name="technical-overview"></a>Technical Overview</h1></div></div></div><div class="section" title="6.1 Runtime Environment"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="runtime-environment"></a>6.1 Runtime Environment</h2></div></div></div><p>Spring Security 3.0 requires a Java 5.0 Runtime Environment or higher. As Spring
+ Security aims to operate in a self-contained manner, there is no need to place any
+ special configuration files into your Java Runtime Environment. In particular, there is
+ no need to configure a special Java Authentication and Authorization Service (JAAS)
+ policy file or place Spring Security into common classpath locations.</p><p>Similarly, if you are using an EJB Container or Servlet Container there is no need to
+ put any special configuration files anywhere, nor include Spring Security in a server
+ classloader. All the required files will be contained within your application.</p><p>This design offers maximum deployment time flexibility, as you can simply copy your
+ target artifact (be it a JAR, WAR or EAR) from one system to another and it will
+ immediately work.</p></div><div class="section" title="6.2 Core Components"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="core-components"></a>6.2 Core Components</h2></div></div></div><p>In Spring Security 3.0, the contents of the <code class="filename">spring-security-core</code>
+ jar were stripped down to the bare minimum. It no longer contains any code related to
+ web-application security, LDAP or namespace configuration. We'll take a look here at
+ some of the Java types that you'll find in the core module. They represent the building
+ blocks of the the framework, so if you ever need to go beyond a simple namespace
+ configuration then it's important that you understand what they are, even if you don't
+ actually need to interact with them directly.</p><div class="section" title="6.2.1 SecurityContextHolder, SecurityContext and Authentication Objects"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1833"></a>6.2.1 SecurityContextHolder, SecurityContext and Authentication Objects </h3></div></div></div><p>The most fundamental object is <code class="classname">SecurityContextHolder</code>. This
+ is where we store details of the present security context of the application, which
+ includes details of the principal currently using the application. By default the
+ <code class="classname">SecurityContextHolder</code> uses a <code class="literal">ThreadLocal</code>
+ to store these details, which means that the security context is always available to
+ methods in the same thread of execution, even if the security context is not
+ explicitly passed around as an argument to those methods. Using a
+ <code class="literal">ThreadLocal</code> in this way is quite safe if care is taken to clear
+ the thread after the present principal's request is processed. Of course, Spring
+ Security takes care of this for you automatically so there is no need to worry about
+ it.</p><p>Some applications aren't entirely suitable for using a
+ <code class="literal">ThreadLocal</code>, because of the specific way they work with threads.
+ For example, a Swing client might want all threads in a Java Virtual Machine to use
+ the same security context. <code class="classname">SecurityContextHolder</code> can be
+ configured with a strategy on startup to specify how you would like the context to
+ be stored. For a standalone application you would use the
+ <code class="literal">SecurityContextHolder.MODE_GLOBAL</code> strategy. Other applications
+ might want to have threads spawned by the secure thread also assume the same
+ security identity. This is achieved by using
+ <code class="literal">SecurityContextHolder.MODE_INHERITABLETHREADLOCAL</code>. You can change
+ the mode from the default <code class="literal">SecurityContextHolder.MODE_THREADLOCAL</code>
+ in two ways. The first is to set a system property, the second is to call a static
+ method on <code class="classname">SecurityContextHolder</code>. Most applications won't need
+ to change from the default, but if you do, take a look at the JavaDocs for
+ <code class="classname">SecurityContextHolder</code> to learn more.</p><div class="section" title="Obtaining information about the current user"><div class="titlepage"><div><div><h4 class="title"><a name="d0e1873"></a>Obtaining information about the current user</h4></div></div></div><p>Inside the <code class="classname">SecurityContextHolder</code> we store details of
+ the principal currently interacting with the application. Spring Security uses
+ an <code class="interfacename">Authentication</code> object to represent this
+ information. You won't normally need to create an
+ <code class="interfacename">Authentication</code> object yourself, but it is fairly
+ common for users to query the <code class="interfacename">Authentication</code>
+ object. You can use the following code block - from anywhere in your application
+ - to obtain the name of the currently authenticated user, for example:</p><pre class="programlisting">
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
<span class="hl-keyword">if</span> (principal <span class="hl-keyword">instanceof</span> UserDetails) {
@@ -960,100 +1041,106 @@ Object principal = SecurityContextHolder.getContext().getAuthentication().getPri
} <span class="hl-keyword">else</span> {
String username = principal.toString();
}</pre><p>The object returned by the call to <code class="methodname">getContext()</code> is an
- instance of the <code class="interfacename">SecurityContext</code> interface. This is the
- object that is kept in thread-local storage. As we'll see below, most authentication
- mechanisms withing Spring Security return an instance of
- <code class="interfacename">UserDetails</code> as the principal. </p></div></div><div class="section" title="5.2.2 The UserDetailsService"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1588"></a>5.2.2 The UserDetailsService</h3></div></div></div><p>Another item to note from the above code fragment is that you can obtain a principal
- from the <code class="interfacename">Authentication</code> object. The principal is just an
- <code class="literal">Object</code>. Most of the time this can be cast into a
- <code class="interfacename">UserDetails</code> object.
- <code class="interfacename">UserDetails</code> is a central interface in Spring Security. It
- represents a principal, but in an extensible and application-specific way. Think of
- <code class="interfacename">UserDetails</code> as the adapter between your own user database
- and what Spring Security needs inside the <code class="classname">SecurityContextHolder</code>.
- Being a representation of something from your own user database, quite often you will cast
- the <code class="interfacename">UserDetails</code> to the original object that your application
- provided, so you can call business-specific methods (like <code class="literal">getEmail()</code>,
- <code class="literal">getEmployeeNumber()</code> and so on).</p><p>By now you're probably wondering, so when do I provide a
- <code class="interfacename">UserDetails</code> object? How do I do that? I thought you said
- this thing was declarative and I didn't need to write any Java code - what gives? The short
- answer is that there is a special interface called
- <code class="interfacename">UserDetailsService</code>. The only method on this interface
- accepts a <code class="literal">String</code>-based username argument and returns a
- <code class="interfacename">UserDetails</code>:
- </p><pre class="programlisting">
+ instance of the <code class="interfacename">SecurityContext</code> interface. This
+ is the object that is kept in thread-local storage. As we'll see below, most
+ authentication mechanisms withing Spring Security return an instance of
+ <code class="interfacename">UserDetails</code> as the principal. </p></div></div><div class="section" title="6.2.2 The UserDetailsService"><div class="titlepage"><div><div><h3 class="title"><a name="tech-userdetailsservice"></a>6.2.2 The UserDetailsService</h3></div></div></div><p>Another item to note from the above code fragment is that you can obtain a
+ principal from the <code class="interfacename">Authentication</code> object. The
+ principal is just an <code class="literal">Object</code>. Most of the time this can be cast
+ into a <code class="interfacename">UserDetails</code> object.
+ <code class="interfacename">UserDetails</code> is a core interface in Spring
+ Security. It represents a principal, but in an extensible and application-specific
+ way. Think of <code class="interfacename">UserDetails</code> as the adapter between your
+ own user database and what Spring Security needs inside the
+ <code class="classname">SecurityContextHolder</code>. Being a representation of something
+ from your own user database, quite often you will cast the
+ <code class="interfacename">UserDetails</code> to the original object that your
+ application provided, so you can call business-specific methods (like
+ <code class="literal">getEmail()</code>, <code class="literal">getEmployeeNumber()</code> and so
+ on).</p><p>By now you're probably wondering, so when do I provide a
+ <code class="interfacename">UserDetails</code> object? How do I do that? I thought you
+ said this thing was declarative and I didn't need to write any Java code - what
+ gives? The short answer is that there is a special interface called
+ <code class="interfacename">UserDetailsService</code>. The only method on this interface
+ accepts a <code class="literal">String</code>-based username argument and returns a
+ <code class="interfacename">UserDetails</code>:
+ </p><pre class="programlisting">
UserDetails loadUserByUsername(String username) <span class="hl-keyword">throws</span> UsernameNotFoundException;
</pre><p>
- This is the most common approach to loading information for a user within Spring Security
- and you will see it used throughout the framework whenever information on a user is
- required.</p><p> On successful authentication, <code class="interfacename">UserDetails</code> is used to
- build the <code class="interfacename">Authentication</code> object that is stored in the
- <code class="classname">SecurityContextHolder</code> (more on this <a class="link" href="#tech-intro-authentication" title="5.3 Authentication">below</a>). The good news is that we provide a
- number of <code class="interfacename">UserDetailsService</code> implementations, including one
- that uses an in-memory map (<code class="classname">InMemoryDaoImpl</code>) and another that uses
- JDBC (<code class="classname">JdbcDaoImpl</code>). Most users tend to write their own, though, with
- their implementations often simply sitting on top of an existing Data Access Object (DAO)
- that represents their employees, customers, or other users of the application. Remember the
- advantage that whatever your <code class="interfacename">UserDetailsService</code> returns can
- always be obtained from the <code class="classname">SecurityContextHolder</code> using the above
- code fragment. </p></div><div class="section" title="5.2.3 GrantedAuthority"><div class="titlepage"><div><div><h3 class="title"><a name="tech-granted-authority"></a>5.2.3 GrantedAuthority</h3></div></div></div><p>Besides the principal, another important method provided by
- <code class="interfacename">Authentication</code> is <code class="literal">getAuthorities(</code>). This
- method provides an array of <code class="interfacename">GrantedAuthority</code> objects. A
- <code class="interfacename">GrantedAuthority</code> is, not surprisingly, an authority that is
- granted to the principal. Such authorities are usually <span class="quote">“<span class="quote">roles</span>”</span>, such as
- <code class="literal">ROLE_ADMINISTRATOR</code> or <code class="literal">ROLE_HR_SUPERVISOR</code>. These
- roles are later on configured for web authorization, method authorization and domain object
- authorization. Other parts of Spring Security are capable of interpreting these authorities,
- and expect them to be present. <code class="interfacename">GrantedAuthority</code> objects are
- usually loaded by the <code class="interfacename">UserDetailsService</code>.</p><p>Usually the <code class="interfacename">GrantedAuthority</code> objects are application-wide
- permissions. They are not specific to a given domain object. Thus, you wouldn't likely have
- a <code class="interfacename">GrantedAuthority</code> to represent a permission to
- <code class="literal">Employee</code> object number 54, because if there are thousands of such
- authorities you would quickly run out of memory (or, at the very least, cause the
- application to take a long time to authenticate a user). Of course, Spring Security is
- expressly designed to handle this common requirement, but you'd instead use the project's
- domain object security capabilities for this purpose.</p></div><div class="section" title="5.2.4 Summary"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1709"></a>5.2.4 Summary</h3></div></div></div><p>Just to recap, the major building blocks of Spring Security that we've seen so far
- are:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc" compact><li class="listitem"><p><code class="classname">SecurityContextHolder</code>, to provide access to the
- <code class="interfacename">SecurityContext</code>.</p></li><li class="listitem"><p><code class="interfacename">SecurityContext</code>, to hold the
- <code class="interfacename">Authentication</code> and possibly request-specific security
- information.</p></li><li class="listitem"><p><code class="interfacename">Authentication</code>, to represent the principal in a
- Spring Security-specific manner.</p></li><li class="listitem"><p><code class="interfacename">GrantedAuthority</code>, to reflect the application-wide
- permissions granted to a principal.</p></li><li class="listitem"><p><code class="interfacename">UserDetails</code>, to provide the necessary information to
- build an Authentication object from your application's DAOs or other source source of
- security data.</p></li><li class="listitem"><p><code class="interfacename">UserDetailsService</code>, to create a
- <code class="interfacename">UserDetails</code> when passed in a
- <code class="literal">String</code>-based username (or certificate ID or the like).</p></li></ul></div><p>Now that you've gained an understanding of these repeatedly-used components, let's take
- a closer look at the process of authentication.</p></div></div><div class="section" title="5.3 Authentication"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="tech-intro-authentication"></a>5.3 Authentication</h2></div></div></div><p>Spring Security can participate in many different authentication environments. While we
- recommend people use Spring Security for authentication and not integrate with existing
- Container Managed Authentication, it is nevertheless supported - as is integrating with your
- own proprietary authentication system. </p><div class="section" title="5.3.1 What is authentication in Spring Security?"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1765"></a>5.3.1 What is authentication in Spring Security?</h3></div></div></div><p> Let's consider a standard authentication scenario that everyone is familiar with.
- </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>A user is prompted to log in with a username and
- password.</p></li><li class="listitem"><p>The system (successfully) verifies that the
- password is correct for the username.</p></li><li class="listitem"><p>The context
- information for that user is obtained (their list of roles and so
- on).</p></li><li class="listitem"><p>A security context is established for the
- user</p></li><li class="listitem"><p>The user proceeds, potentially to perform some
- operation which is potentially protected by an access control mechanism which checks
- the required permissions for the operation against the current security context
- information. </p></li></ol></div><p> The first three items constitute the
- authentication process so we'll take a look at how these take place within Spring
- Security.</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>The username and password are obtained and
- combined into an instance of
- <code class="classname">UsernamePasswordAuthenticationToken</code> (an instance of the
- <code class="interfacename">Authentication</code> interface, which we saw
- earlier).</p></li><li class="listitem"><p>The token is passed to an instance of
- <code class="interfacename">AuthenticationManager</code> for
- validation.</p></li><li class="listitem"><p>The
- <code class="interfacename">AuthenticationManager</code> returns a fully populated
- <code class="interfacename">Authentication</code> instance on successful
- authentication.</p></li><li class="listitem"><p>The security context is established
- by calling <code class="code">SecurityContextHolder.getContext().setAuthentication(...)</code>,
- passing in the returned authentication object.</p></li></ol></div><p>From
- that point on, the user is considered to be authenticated. Let's look at some code as an
- example.
- </p><pre class="programlisting"><span class="hl-keyword">import</span> org.springframework.security.authentication.*;
+ This is the most common approach to loading information for a user within Spring
+ Security and you will see it used throughout the framework whenever information on a
+ user is required.</p><p> On successful authentication, <code class="interfacename">UserDetails</code> is used
+ to build the <code class="interfacename">Authentication</code> object that is stored in
+ the <code class="classname">SecurityContextHolder</code> (more on this <a class="link" href="#tech-intro-authentication" title="6.3 Authentication">below</a>). The good news is that we
+ provide a number of <code class="interfacename">UserDetailsService</code>
+ implementations, including one that uses an in-memory map
+ (<code class="classname">InMemoryDaoImpl</code>) and another that uses JDBC
+ (<code class="classname">JdbcDaoImpl</code>). Most users tend to write their own, though,
+ with their implementations often simply sitting on top of an existing Data Access
+ Object (DAO) that represents their employees, customers, or other users of the
+ application. Remember the advantage that whatever your
+ <code class="interfacename">UserDetailsService</code> returns can always be obtained
+ from the <code class="classname">SecurityContextHolder</code> using the above code fragment.
+ </p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>There is often some confusion about <code class="interfacename">UserDetailsService</code>.
+ It is purely a DAO for user data and performs no other function other than to supply that data
+ to other components within the framework. In particular, it <span class="emphasis"><em>does not</em></span>
+ authenticate the user, which is done by the <code class="interfacename">AuthenticationManager</code>.
+ In many cases it makes more sense to
+ <a class="link" href="#core-services-authentication-manager" title="7.1 The AuthenticationManager, ProviderManager and AuthenticationProviders">implement <code class="interfacename">AuthenticationProvider</code></a>
+ directly if you require a custom authentication process.
+ </p></td></tr></table></div></div><div class="section" title="6.2.3 GrantedAuthority"><div class="titlepage"><div><div><h3 class="title"><a name="tech-granted-authority"></a>6.2.3 GrantedAuthority</h3></div></div></div><p>Besides the principal, another important method provided by
+ <code class="interfacename">Authentication</code> is
+ <code class="literal">getAuthorities(</code>). This method provides an array of
+ <code class="interfacename">GrantedAuthority</code> objects. A
+ <code class="interfacename">GrantedAuthority</code> is, not surprisingly, an authority
+ that is granted to the principal. Such authorities are usually <span class="quote">“<span class="quote">roles</span>”</span>,
+ such as <code class="literal">ROLE_ADMINISTRATOR</code> or
+ <code class="literal">ROLE_HR_SUPERVISOR</code>. These roles are later on configured for web
+ authorization, method authorization and domain object authorization. Other parts of
+ Spring Security are capable of interpreting these authorities, and expect them to be
+ present. <code class="interfacename">GrantedAuthority</code> objects are usually loaded
+ by the <code class="interfacename">UserDetailsService</code>.</p><p>Usually the <code class="interfacename">GrantedAuthority</code> objects are
+ application-wide permissions. They are not specific to a given domain object. Thus,
+ you wouldn't likely have a <code class="interfacename">GrantedAuthority</code> to
+ represent a permission to <code class="literal">Employee</code> object number 54, because if
+ there are thousands of such authorities you would quickly run out of memory (or, at
+ the very least, cause the application to take a long time to authenticate a user).
+ Of course, Spring Security is expressly designed to handle this common requirement,
+ but you'd instead use the project's domain object security capabilities for this
+ purpose.</p></div><div class="section" title="6.2.4 Summary"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2041"></a>6.2.4 Summary</h3></div></div></div><p>Just to recap, the major building blocks of Spring Security that we've seen so far
+ are:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc" compact><li class="listitem"><p><code class="classname">SecurityContextHolder</code>, to provide access to the
+ <code class="interfacename">SecurityContext</code>.</p></li><li class="listitem"><p><code class="interfacename">SecurityContext</code>, to hold the
+ <code class="interfacename">Authentication</code> and possibly request-specific
+ security information.</p></li><li class="listitem"><p><code class="interfacename">Authentication</code>, to represent the principal
+ in a Spring Security-specific manner.</p></li><li class="listitem"><p><code class="interfacename">GrantedAuthority</code>, to reflect the
+ application-wide permissions granted to a principal.</p></li><li class="listitem"><p><code class="interfacename">UserDetails</code>, to provide the necessary
+ information to build an Authentication object from your application's DAOs
+ or other source source of security data.</p></li><li class="listitem"><p><code class="interfacename">UserDetailsService</code>, to create a
+ <code class="interfacename">UserDetails</code> when passed in a
+ <code class="literal">String</code>-based username (or certificate ID or the
+ like).</p></li></ul></div><p>Now that you've gained an understanding of these repeatedly-used components, let's
+ take a closer look at the process of authentication.</p></div></div><div class="section" title="6.3 Authentication"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="tech-intro-authentication"></a>6.3 Authentication</h2></div></div></div><p>Spring Security can participate in many different authentication environments. While
+ we recommend people use Spring Security for authentication and not integrate with
+ existing Container Managed Authentication, it is nevertheless supported - as is
+ integrating with your own proprietary authentication system. </p><div class="section" title="6.3.1 What is authentication in Spring Security?"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2097"></a>6.3.1 What is authentication in Spring Security?</h3></div></div></div><p> Let's consider a standard authentication scenario that everyone is familiar with. </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>A user is prompted to log in with a username and password.</p></li><li class="listitem"><p>The system (successfully) verifies that the password is correct for the
+ username.</p></li><li class="listitem"><p>The context information for that user is obtained (their list of roles and
+ so on).</p></li><li class="listitem"><p>A security context is established for the user</p></li><li class="listitem"><p>The user proceeds, potentially to perform some operation which is
+ potentially protected by an access control mechanism which checks the
+ required permissions for the operation against the current security context
+ information. </p></li></ol></div><p> The first three items constitute the authentication process so we'll
+ take a look at how these take place within Spring Security.</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>The username and password are obtained and combined into an instance of
+ <code class="classname">UsernamePasswordAuthenticationToken</code> (an instance of
+ the <code class="interfacename">Authentication</code> interface, which we saw
+ earlier).</p></li><li class="listitem"><p>The token is passed to an instance of
+ <code class="interfacename">AuthenticationManager</code> for validation.</p></li><li class="listitem"><p>The <code class="interfacename">AuthenticationManager</code> returns a fully
+ populated <code class="interfacename">Authentication</code> instance on
+ successful authentication.</p></li><li class="listitem"><p>The security context is established by calling
+ <code class="code">SecurityContextHolder.getContext().setAuthentication(...)</code>,
+ passing in the returned authentication object.</p></li></ol></div><p>From that point on, the user is considered to be authenticated. Let's
+ look at some code as an example.
+ </p><pre class="programlisting"><span class="hl-keyword">import</span> org.springframework.security.authentication.*;
<span class="hl-keyword">import</span> org.springframework.security.core.*;
-<span class="hl-keyword">import</span> org.springframework.security.core.authority.GrantedAuthorityImpl;
+<span class="hl-keyword">import</span> org.springframework.security.core.authority.SimpleGrantedAuthority;
<span class="hl-keyword">import</span> org.springframework.security.core.context.SecurityContextHolder;
<span class="hl-keyword">public</span> <span class="hl-keyword">class</span> AuthenticationExample {
@@ -1085,7 +1172,7 @@ Object principal = SecurityContextHolder.getContext().getAuthentication().getPri
<span class="hl-keyword">static</span> <span class="hl-keyword">final</span> List<GrantedAuthority> AUTHORITIES = <span class="hl-keyword">new</span> ArrayList<GrantedAuthority>();
<span class="hl-keyword">static</span> {
- AUTHORITIES.add(<span class="hl-keyword">new</span> GrantedAuthorityImpl(<span class="hl-string">"ROLE_USER"</span>));
+ AUTHORITIES.add(<span class="hl-keyword">new</span> SimpleGrantedAuthority(<span class="hl-string">"ROLE_USER"</span>));
}
<span class="hl-keyword">public</span> Authentication authenticate(Authentication auth) <span class="hl-keyword">throws</span> AuthenticationException {
@@ -1096,11 +1183,12 @@ Object principal = SecurityContextHolder.getContext().getAuthentication().getPri
<span class="hl-keyword">throw</span> <span class="hl-keyword">new</span> BadCredentialsException(<span class="hl-string">"Bad Credentials"</span>);
}
}</pre><p>Here
- we have written a little program that asks the user to enter a username and password and
- performs the above sequence. The <code class="interfacename">AuthenticationManager</code> which
- we've implemented here will authenticate any user whose username and password are the same.
- It assigns a single role to every user. The output from the above will be something
- like:</p><pre class="programlisting">
+ we have written a little program that asks the user to enter a username and password
+ and performs the above sequence. The
+ <code class="interfacename">AuthenticationManager</code> which we've implemented here
+ will authenticate any user whose username and password are the same. It assigns a
+ single role to every user. The output from the above will be something
+ like:</p><pre class="programlisting">
Please enter your username:
bob
Please enter your password:
@@ -1115,273 +1203,305 @@ Successfully authenticated. Security context contains: \
Principal: bob; Password: [PROTECTED]; \
Authenticated: true; Details: null; \
Granted Authorities: ROLE_USER
- </pre><p>Note that you don't normally need to write any code like this. The process will normally
- occur internally, in a web authentication filter for example. We've just included the code
- here to show that the question of what actually constitutes authentication in Spring
- Security has quite a simple answer. A user is authenticated when the
- <code class="classname">SecurityContextHolder</code> contains a fully populated
- <code class="interfacename">Authentication</code> object.</p></div><div class="section" title="5.3.2 Setting the SecurityContextHolder Contents Directly"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1835"></a>5.3.2 Setting the SecurityContextHolder Contents Directly</h3></div></div></div><p>In fact, Spring Security doesn't mind how you put the
- <code class="interfacename">Authentication</code> object inside the
- <code class="classname">SecurityContextHolder</code>. The only critical requirement is that the
- <code class="classname">SecurityContextHolder</code> contains an
- <code class="interfacename">Authentication</code> which represents a principal before the
- <code class="classname">AbstractSecurityInterceptor</code> (which we'll see more about later)
- needs to authorize a user operation.</p><p>You can (and many users do) write their own filters or MVC controllers to provide
- interoperability with authentication systems that are not based on Spring Security. For
- example, you might be using Container-Managed Authentication which makes the current user
- available from a ThreadLocal or JNDI location. Or you might work for a company that has a
- legacy proprietary authentication system, which is a corporate "standard" over which you
- have little control. In situations like this it's quite easy to get Spring Security to work,
- and still provide authorization capabilities. All you need to do is write a filter (or
- equivalent) that reads the third-party user information from a location, build a Spring
- Security-specific <code class="interfacename">Authentication</code> object, and put it into the
- <code class="classname">SecurityContextHolder</code>.</p><p> If you're wondering how the <code class="interfacename">AuthenticationManager</code>
- manager is implemented in a real world example, we'll look at that in the <a class="link" href="#core-services-authentication-manager" title="6.1 The AuthenticationManager, ProviderManager and AuthenticationProviders">core services chapter</a>.</p></div></div><div class="section" title="5.4 Authentication in a Web Application"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="tech-intro-web-authentication"></a>5.4 Authentication in a Web Application</h2></div></div></div><p> Now let's explore the situation where you are using Spring Security in a web application
- (without <code class="filename">web.xml</code> security enabled). How is a user authenticated and the
- security context established?</p><p>Consider a typical web application's authentication process:</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>You visit the home page, and click on a link.</p></li><li class="listitem"><p>A request goes to the server, and the server decides that you've asked for a protected
- resource.</p></li><li class="listitem"><p>As you're not presently authenticated, the server sends back a response indicating
- that you must authenticate. The response will either be an HTTP response code, or a
- redirect to a particular web page.</p></li><li class="listitem"><p>Depending on the authentication mechanism, your browser will either redirect to the
- specific web page so that you can fill out the form, or the browser will somehow retrieve
- your identity (via a BASIC authentication dialogue box, a cookie, a X.509 certificate
- etc.).</p></li><li class="listitem"><p>The browser will send back a response to the server. This will either be an HTTP POST
- containing the contents of the form that you filled out, or an HTTP header containing your
- authentication details.</p></li><li class="listitem"><p>Next the server will decide whether or not the presented credentials are valid. If
- they're valid, the next step will happen. If they're invalid, usually your browser will be
- asked to try again (so you return to step two above).</p></li><li class="listitem"><p>The original request that you made to cause the authentication process will be
- retried. Hopefully you've authenticated with sufficient granted authorities to access the
- protected resource. If you have sufficient access, the request will be successful.
- Otherwise, you'll receive back an HTTP error code 403, which means "forbidden".</p></li></ol></div><p>Spring Security has distinct classes responsible for most of the steps described above.
- The main participants (in the order that they are used) are the
- <code class="classname">ExceptionTranslationFilter</code>, an
- <code class="interfacename">AuthenticationEntryPoint</code> and an <span class="quote">“<span class="quote">authentication
- mechanism</span>”</span>, which is responsible for calling the
- <code class="classname">AuthenticationManager</code> which we saw in the previous section.</p><div class="section" title="5.4.1 ExceptionTranslationFilter"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1917"></a>5.4.1 ExceptionTranslationFilter</h3></div></div></div><p><code class="classname">ExceptionTranslationFilter</code> is a Spring Security filter that has
- responsibility for detecting any Spring Security exceptions that are thrown. Such exceptions
- will generally be thrown by an <code class="classname">AbstractSecurityInterceptor</code>, which is
- the main provider of authorization services. We will discuss
- <code class="classname">AbstractSecurityInterceptor</code> in the next section, but for now we
- just need to know that it produces Java exceptions and knows nothing about HTTP or how to go
- about authenticating a principal. Instead the
- <code class="classname">ExceptionTranslationFilter</code> offers this service, with specific
- responsibility for either returning error code 403 (if the principal has been authenticated
- and therefore simply lacks sufficient access - as per step seven above), or launching an
- <code class="interfacename">AuthenticationEntryPoint</code> (if the principal has not been
- authenticated and therefore we need to go commence step three).</p></div><div class="section" title="5.4.2 AuthenticationEntryPoint"><div class="titlepage"><div><div><h3 class="title"><a name="tech-intro-auth-entry-point"></a>5.4.2 AuthenticationEntryPoint</h3></div></div></div><p>The <code class="interfacename">AuthenticationEntryPoint</code> is responsible for step
- three in the above list. As you can imagine, each web application will have a default
- authentication strategy (well, this can be configured like nearly everything else in Spring
- Security, but let's keep it simple for now). Each major authentication system will have its
- own <code class="interfacename">AuthenticationEntryPoint</code> implementation, which typically
- performs one of the actions described in step 3.</p></div><div class="section" title="5.4.3 Authentication Mechanism"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1947"></a>5.4.3 Authentication Mechanism</h3></div></div></div><p>Once your browser submits your authentication credentials (either as an HTTP form post
- or HTTP header) there needs to be something on the server that <span class="quote">“<span class="quote">collects</span>”</span> these
- authentication details. By now we're at step six in the above list. In Spring Security we
- have a special name for the function of collecting authentication details from a user agent
- (usually a web browser), referring to it as the <span class="quote">“<span class="quote">authentication mechanism</span>”</span>.
- Examples are form-base login and Basic authentication. Once the authentication details have
- been collected from the user agent, an <code class="interfacename">Authentication</code>
- <span class="quote">“<span class="quote">request</span>”</span> object is built and then presented to the
- <code class="interfacename">AuthenticationManager</code>.</p><p>After the authentication mechanism receives back the fully-populated
- <code class="interfacename">Authentication</code> object, it will deem the request valid, put
- the <code class="interfacename">Authentication</code> into the
- <code class="classname">SecurityContextHolder</code>, and cause the original request to be retried
- (step seven above). If, on the other hand, the <code class="classname">AuthenticationManager</code>
- rejected the request, the authentication mechanism will ask the user agent to retry (step
- two above).</p></div><div class="section" title="5.4.4 Storing the SecurityContext between requests"><div class="titlepage"><div><div><h3 class="title"><a name="tech-intro-sec-context-persistence"></a>5.4.4 Storing the <code class="interfacename">SecurityContext</code> between requests</h3></div></div></div><p>Depending on the type of application, there may need to be a strategy in place to store
- the security context between user operations. In a typical web application, a user logs in
- once and is subsequently identified by their session Id. The server caches the principal
- information for the duration session. In Spring Security, the responsibility for storing the
- <code class="interfacename">SecurityContext</code> between requests falls to the
- <code class="classname">SecurityContextPersistenceFilter</code>, which by default stores the
- context as an <code class="literal">HttpSession</code> attribute between HTTP requests. It restores
- the context to the <code class="classname">SecurityContextHolder</code> for each request and,
- crucially, clears the <code class="classname">SecurityContextHolder</code> when the request
- completes. You shouldn't interact directly with the <code class="literal">HttpSession</code> for
- security purposes. There is simply no justification for doing so - always use the
- <code class="classname">SecurityContextHolder</code> instead. </p><p> Many other types of application (for example, a stateless RESTful web service) do not
- use HTTP sessions and will re-authenticate on every request. However, it is still important
- that the <code class="classname">SecurityContextPersistenceFilter</code> is included in the chain to
- make sure that the <code class="classname">SecurityContextHolder</code> is cleared after each
- request.</p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>In an application which receives concurrent requests in a single session, the same
- <code class="interfacename">SecurityContext</code> instance will be shared between threads.
- Even though a <code class="classname">ThreadLocal</code> is being used, it is the same instance
- that is retrieved from the <code class="interfacename">HttpSession</code> for each thread.
- This has implications if you wish to temporarily change the context under which a thread
- is running. If you just use
- <code class="code">SecurityContextHolder.getContext().setAuthentication(anAuthentication)</code>,
- then the <code class="interfacename">Authentication</code> object will change in
- <span class="emphasis"><em>all</em></span> concurrent threads which share the same
- <code class="interfacename">SecurityContext</code> instance. You can customize the behaviour
- of <code class="classname">SecurityContextPersistenceFilter</code> to create a completely new
- <code class="interfacename">SecurityContext</code> for each request, preventing changes in
- one thread from affecting another. Alternatively you can create a new instance just at the
- point where you temporarily change the context. The method
- <code class="code">SecurityContextHolder.createEmptyContext()</code> always returns a new context
- instance.</p></td></tr></table></div></div></div><div class="section" title="5.5 Access-Control (Authorization) in Spring Security"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="tech-intro-access-control"></a>5.5 Access-Control (Authorization) in Spring Security</h2></div></div></div><p> The main interface responsible for making access-control decisions in Spring Security is
- the <code class="interfacename">AccessDecisionManager</code>. It has a
- <code class="methodname">decide</code> method which takes an
- <code class="interfacename">Authentication</code> object representing the principal requesting
- access, a <span class="quote">“<span class="quote">secure object</span>”</span> (see below) and a list of security metadata attributes
- which apply for the object (such as a list of roles which are required for access to be
- granted). </p><div class="section" title="5.5.1 Security and AOP Advice"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2068"></a>5.5.1 Security and AOP Advice</h3></div></div></div><p>If you're familiar with AOP, you'd be aware there are different types of advice
- available: before, after, throws and around. An around advice is very useful, because an
- advisor can elect whether or not to proceed with a method invocation, whether or not to
- modify the response, and whether or not to throw an exception. Spring Security provides an
- around advice for method invocations as well as web requests. We achieve an around advice
- for method invocations using Spring's standard AOP support and we achieve an around advice
- for web requests using a standard Filter.</p><p>For those not familiar with AOP, the key point to understand is that Spring Security can
- help you protect method invocations as well as web requests. Most people are interested in
- securing method invocations on their services layer. This is because the services layer is
- where most business logic resides in current-generation J2EE applications. If you just need
- to secure method invocations in the services layer, Spring's standard AOP will be adequate.
- If you need to secure domain objects directly, you will likely find that AspectJ is worth
- considering.</p><p>You can elect to perform method authorization using AspectJ or Spring AOP, or you can
- elect to perform web request authorization using filters. You can use zero, one, two or
- three of these approaches together. The mainstream usage pattern is to perform some web
- request authorization, coupled with some Spring AOP method invocation authorization on the
- services layer.</p></div><div class="section" title="5.5.2 Secure Objects and the AbstractSecurityInterceptor"><div class="titlepage"><div><div><h3 class="title"><a name="secure-objects"></a>5.5.2 Secure Objects and the <code class="classname">AbstractSecurityInterceptor</code></h3></div></div></div><p>So what <span class="emphasis"><em>is</em></span> a <span class="quote">“<span class="quote">secure object</span>”</span> anyway? Spring Security
- uses the term to refer to any object that can have security (such as an authorization
- decision) applied to it. The most common examples are method invocations and web
- requests.</p><p>Each supported secure object type has its own interceptor class, which is a subclass of
- <code class="classname">AbstractSecurityInterceptor</code>. Importantly, by the time the
- <code class="classname">AbstractSecurityInterceptor</code> is called, the
- <code class="classname">SecurityContextHolder</code> will contain a valid
- <code class="interfacename">Authentication</code> if the principal has been
- authenticated.</p><p><code class="classname">AbstractSecurityInterceptor</code> provides a consistent workflow for
- handling secure object requests, typically: </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>Look up the
- <span class="quote">“<span class="quote">configuration attributes</span>”</span> associated with the present
- request</p></li><li class="listitem"><p>Submitting the secure object, current
- <code class="interfacename">Authentication</code> and configuration attributes to the
- <code class="interfacename">AccessDecisionManager</code> for an authorization
- decision</p></li><li class="listitem"><p>Optionally change the
- <code class="interfacename">Authentication</code> under which the invocation takes
- place</p></li><li class="listitem"><p>Allow the secure object invocation to proceed
- (assuming access was granted)</p></li><li class="listitem"><p>Call the
- <code class="interfacename">AfterInvocationManager</code> if configured, once the
- invocation has returned.</p></li></ol></div><div class="section" title="What are Configuration Attributes?"><div class="titlepage"><div><div><h4 class="title"><a name="tech-intro-config-attributes"></a>What are Configuration Attributes?</h4></div></div></div><p> A <span class="quote">“<span class="quote">configuration attribute</span>”</span> can be thought of as a String that has
- special meaning to the classes used by <code class="classname">AbstractSecurityInterceptor</code>.
- They are represented by the interface <code class="interfacename">ConfigAttribute</code>
- within the framework. They may be simple role names or have more complex meaning,
- depending on the how sophisticated the
- <code class="interfacename">AccessDecisionManager</code> implementation is. The
- <code class="classname">AbstractSecurityInterceptor</code> is configured with a
- <code class="interfacename">SecurityMetadataSource</code> which it uses to look up the
- attributes for a secure object. Usually this configuration will be hidden from the user.
- Configuration attributes will be entered as annotations on secured methods or as access
- attributes on secured URLs. For example, when we saw something like
- <code class="literal"><intercept-url pattern='/secure/**' access='ROLE_A,ROLE_B'/></code> in
- the namespace introduction, this is saying that the configuration attributes
- <code class="literal">ROLE_A</code> and <code class="literal">ROLE_B</code> apply to web requests matching
- the given pattern. In practice, with the default
- <code class="interfacename">AccessDecisionManager</code> configuration, this means that
- anyone who has a <code class="interfacename">GrantedAuthority</code> matching either of these
- two attributes will be allowed access. Strictly speaking though, they are just attributes
- and the interpretation is dependent on the
- <code class="interfacename">AccessDecisionManager</code> implementation. The use of the
- prefix <code class="literal">ROLE_</code> is a marker to indicate that these attributes are roles
- and should be consumed by Spring Security's <code class="classname">RoleVoter</code>. This is only
- relevant when a voter-based <code class="interfacename">AccessDecisionManager</code> is in
- use. We'll see how the <code class="interfacename">AccessDecisionManager</code> is implemented
- in the <a class="link" href="#authz-arch" title="13. Authorization Architecture">authorization chapter</a>.</p></div><div class="section" title="RunAsManager"><div class="titlepage"><div><div><h4 class="title"><a name="d0e2195"></a>RunAsManager</h4></div></div></div><p>Assuming <code class="interfacename">AccessDecisionManager</code> decides to allow the
- request, the <code class="classname">AbstractSecurityInterceptor</code> will normally just proceed
- with the request. Having said that, on rare occasions users may want to replace the
- <code class="interfacename">Authentication</code> inside the
- <code class="interfacename">SecurityContext</code> with a different
- <code class="interfacename">Authentication</code>, which is handled by the
- <code class="interfacename">AccessDecisionManager</code> calling a
- <code class="literal">RunAsManager</code>. This might be useful in reasonably unusual situations,
- such as if a services layer method needs to call a remote system and present a different
- identity. Because Spring Security automatically propagates security identity from one
- server to another (assuming you're using a properly-configured RMI or HttpInvoker remoting
- protocol client), this may be useful.</p></div><div class="section" title="AfterInvocationManager"><div class="titlepage"><div><div><h4 class="title"><a name="d0e2221"></a>AfterInvocationManager</h4></div></div></div><p>Following the secure object proceeding and then returning - which may mean a method
- invocation completing or a filter chain proceeding - the
- <code class="classname">AbstractSecurityInterceptor</code> gets one final chance to handle the
- invocation. At this stage the <code class="classname">AbstractSecurityInterceptor</code> is
- interested in possibly modifying the return object. We might want this to happen because
- an authorization decision couldn't be made <span class="quote">“<span class="quote">on the way in</span>”</span> to a secure object
- invocation. Being highly pluggable, <code class="classname">AbstractSecurityInterceptor</code>
- will pass control to an <code class="literal">AfterInvocationManager</code> to actually modify the
- object if needed. This class can even entirely replace the object, or throw an exception,
- or not change it in any way as it chooses.</p><p><code class="classname">AbstractSecurityInterceptor</code> and its related objects are shown
- in <a class="xref" href="#abstract-security-interceptor" title="Figure 5.1. Security interceptors and the “secure object” model">Figure 5.1, “Security interceptors and the
- <span class="quote">“<span class="quote">secure object</span>”</span> model”</a>. </p><div class="figure"><a name="abstract-security-interceptor"></a><p class="title"><b>Figure 5.1. Security interceptors and the
- <span class="quote">“<span class="quote">secure object</span>”</span> model</b></p><div class="figure-contents"><div class="mediaobject" align="center"><img src="images/security-interception.png" align="middle" alt="Security interceptors and the secure object model"></div></div></div><p><br class="figure-break"></p></div><div class="section" title="Extending the Secure Object Model"><div class="titlepage"><div><div><h4 class="title"><a name="d0e2256"></a>Extending the Secure Object Model</h4></div></div></div><p>Only developers contemplating an entirely new way of intercepting and authorizing
- requests would need to use secure objects directly. For example, it would be possible to
- build a new secure object to secure calls to a messaging system. Anything that requires
- security and also provides a way of intercepting a call (like the AOP around advice
- semantics) is capable of being made into a secure object. Having said that, most Spring
- applications will simply use the three currently supported secure object types (AOP
- Alliance <code class="classname">MethodInvocation</code>, AspectJ <code class="classname">JoinPoint</code>
- and web request <code class="classname">FilterInvocation</code>) with complete
- transparency.</p></div></div></div><div class="section" title="5.6 Localization"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="localization"></a>5.6 Localization</h2></div></div></div><p>Spring Security supports localization of exception messages that end users are likely to
- see. If your application is designed for English-speaking users, you don't need to do anything
- as by default all Security Security messages are in English. If you need to support other
- locales, everything you need to know is contained in this section.</p><p>All exception messages can be localized, including messages related to authentication
- failures and access being denied (authorization failures). Exceptions and logging that is
- focused on developers or system deployers (including incorrect attributes, interface contract
- violations, using incorrect constructors, startup time validation, debug-level logging) etc
- are not localized and instead are hard-coded in English within Spring Security's code.</p><p>Shipping in the <code class="literal">spring-security-core-xx.jar</code> you will find an
- <code class="literal">org.springframework.security</code> package that in turn contains a
- <code class="literal">messages.properties</code> file. This should be referred to by your
- <code class="literal">ApplicationContext</code>, as Spring Security classes implement Spring's
- <code class="literal">MessageSourceAware</code> interface and expect the message resolver to be
- dependency injected at application context startup time. Usually all you need to do is
- register a bean inside your application context to refer to the messages. An example is shown
- below:</p><p>
- </p><pre class="programlisting">
-<bean id="messageSource"
- class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
- <property name="basename" value="org/springframework/security/messages"/>
-</bean>
+ </pre><p>Note that you don't normally need to write any code like this. The process will
+ normally occur internally, in a web authentication filter for example. We've just
+ included the code here to show that the question of what actually constitutes
+ authentication in Spring Security has quite a simple answer. A user is authenticated
+ when the <code class="classname">SecurityContextHolder</code> contains a fully populated
+ <code class="interfacename">Authentication</code> object.</p></div><div class="section" title="6.3.2 Setting the SecurityContextHolder Contents Directly"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2167"></a>6.3.2 Setting the SecurityContextHolder Contents Directly</h3></div></div></div><p>In fact, Spring Security doesn't mind how you put the
+ <code class="interfacename">Authentication</code> object inside the
+ <code class="classname">SecurityContextHolder</code>. The only critical requirement is that
+ the <code class="classname">SecurityContextHolder</code> contains an
+ <code class="interfacename">Authentication</code> which represents a principal before
+ the <code class="classname">AbstractSecurityInterceptor</code> (which we'll see more about
+ later) needs to authorize a user operation.</p><p>You can (and many users do) write their own filters or MVC controllers to provide
+ interoperability with authentication systems that are not based on Spring Security.
+ For example, you might be using Container-Managed Authentication which makes the
+ current user available from a ThreadLocal or JNDI location. Or you might work for a
+ company that has a legacy proprietary authentication system, which is a corporate
+ "standard" over which you have little control. In situations like this it's quite
+ easy to get Spring Security to work, and still provide authorization capabilities.
+ All you need to do is write a filter (or equivalent) that reads the third-party user
+ information from a location, build a Spring Security-specific
+ <code class="interfacename">Authentication</code> object, and put it into the
+ <code class="classname">SecurityContextHolder</code>. In this case you also need to think
+ about things which are normally taken care of automatically by the built-in authentication
+ infrastructure. For example, you might need to pre-emptively create an HTTP session to
+ <a class="link" href="tech-intro-sec-context-persistence" target="_top">cache the context between requests</a>,
+ before you write the response to the client<sup>[<a name="d0e2198" href="#ftn.d0e2198" class="footnote">9</a>]</sup>.
+ </p><p> If you're wondering how the <code class="interfacename">AuthenticationManager</code>
+ is implemented in a real world example, we'll look at that in the <a class="link" href="#core-services-authentication-manager" title="7.1 The AuthenticationManager, ProviderManager and AuthenticationProviders">core services
+ chapter</a>.</p></div></div><div class="section" title="6.4 Authentication in a Web Application"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="tech-intro-web-authentication"></a>6.4 Authentication in a Web Application</h2></div></div></div><p> Now let's explore the situation where you are using Spring Security in a web
+ application (without <code class="filename">web.xml</code> security enabled). How is a user
+ authenticated and the security context established?</p><p>Consider a typical web application's authentication process:</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>You visit the home page, and click on a link.</p></li><li class="listitem"><p>A request goes to the server, and the server decides that you've asked for a
+ protected resource.</p></li><li class="listitem"><p>As you're not presently authenticated, the server sends back a response
+ indicating that you must authenticate. The response will either be an HTTP
+ response code, or a redirect to a particular web page.</p></li><li class="listitem"><p>Depending on the authentication mechanism, your browser will either redirect
+ to the specific web page so that you can fill out the form, or the browser will
+ somehow retrieve your identity (via a BASIC authentication dialogue box, a
+ cookie, a X.509 certificate etc.).</p></li><li class="listitem"><p>The browser will send back a response to the server. This will either be an
+ HTTP POST containing the contents of the form that you filled out, or an HTTP
+ header containing your authentication details.</p></li><li class="listitem"><p>Next the server will decide whether or not the presented credentials are
+ valid. If they're valid, the next step will happen. If they're invalid, usually
+ your browser will be asked to try again (so you return to step two
+ above).</p></li><li class="listitem"><p>The original request that you made to cause the authentication process will be
+ retried. Hopefully you've authenticated with sufficient granted authorities to
+ access the protected resource. If you have sufficient access, the request will
+ be successful. Otherwise, you'll receive back an HTTP error code 403, which
+ means "forbidden".</p></li></ol></div><p>Spring Security has distinct classes responsible for most of the steps described
+ above. The main participants (in the order that they are used) are the
+ <code class="classname">ExceptionTranslationFilter</code>, an
+ <code class="interfacename">AuthenticationEntryPoint</code> and an <span class="quote">“<span class="quote">authentication
+ mechanism</span>”</span>, which is responsible for calling the
+ <code class="classname">AuthenticationManager</code> which we saw in the previous
+ section.</p><div class="section" title="6.4.1 ExceptionTranslationFilter"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2256"></a>6.4.1 ExceptionTranslationFilter</h3></div></div></div><p><code class="classname">ExceptionTranslationFilter</code> is a Spring Security filter that
+ has responsibility for detecting any Spring Security exceptions that are thrown.
+ Such exceptions will generally be thrown by an
+ <code class="classname">AbstractSecurityInterceptor</code>, which is the main provider of
+ authorization services. We will discuss
+ <code class="classname">AbstractSecurityInterceptor</code> in the next section, but for now
+ we just need to know that it produces Java exceptions and knows nothing about HTTP
+ or how to go about authenticating a principal. Instead the
+ <code class="classname">ExceptionTranslationFilter</code> offers this service, with specific
+ responsibility for either returning error code 403 (if the principal has been
+ authenticated and therefore simply lacks sufficient access - as per step seven
+ above), or launching an <code class="interfacename">AuthenticationEntryPoint</code> (if
+ the principal has not been authenticated and therefore we need to go commence step
+ three).</p></div><div class="section" title="6.4.2 AuthenticationEntryPoint"><div class="titlepage"><div><div><h3 class="title"><a name="tech-intro-auth-entry-point"></a>6.4.2 AuthenticationEntryPoint</h3></div></div></div><p>The <code class="interfacename">AuthenticationEntryPoint</code> is responsible for
+ step three in the above list. As you can imagine, each web application will have a
+ default authentication strategy (well, this can be configured like nearly everything
+ else in Spring Security, but let's keep it simple for now). Each major
+ authentication system will have its own
+ <code class="interfacename">AuthenticationEntryPoint</code> implementation, which
+ typically performs one of the actions described in step 3.</p></div><div class="section" title="6.4.3 Authentication Mechanism"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2286"></a>6.4.3 Authentication Mechanism</h3></div></div></div><p>Once your browser submits your authentication credentials (either as an HTTP form
+ post or HTTP header) there needs to be something on the server that
+ <span class="quote">“<span class="quote">collects</span>”</span> these authentication details. By now we're at step six in
+ the above list. In Spring Security we have a special name for the function of
+ collecting authentication details from a user agent (usually a web browser),
+ referring to it as the <span class="quote">“<span class="quote">authentication mechanism</span>”</span>. Examples are
+ form-base login and Basic authentication. Once the authentication details have been
+ collected from the user agent, an <code class="interfacename">Authentication</code>
+ <span class="quote">“<span class="quote">request</span>”</span> object is built and then presented to the
+ <code class="interfacename">AuthenticationManager</code>.</p><p>After the authentication mechanism receives back the fully-populated
+ <code class="interfacename">Authentication</code> object, it will deem the request
+ valid, put the <code class="interfacename">Authentication</code> into the
+ <code class="classname">SecurityContextHolder</code>, and cause the original request to be
+ retried (step seven above). If, on the other hand, the
+ <code class="classname">AuthenticationManager</code> rejected the request, the
+ authentication mechanism will ask the user agent to retry (step two above).</p></div><div class="section" title="6.4.4 Storing the SecurityContext between requests"><div class="titlepage"><div><div><h3 class="title"><a name="tech-intro-sec-context-persistence"></a>6.4.4 Storing the <code class="interfacename">SecurityContext</code> between
+ requests</h3></div></div></div><p>Depending on the type of application, there may need to be a strategy in place to
+ store the security context between user operations. In a typical web application, a
+ user logs in once and is subsequently identified by their session Id. The server
+ caches the principal information for the duration session. In Spring Security, the
+ responsibility for storing the <code class="interfacename">SecurityContext</code>
+ between requests falls to the
+ <code class="classname">SecurityContextPersistenceFilter</code>, which by default stores the
+ context as an <code class="literal">HttpSession</code> attribute between HTTP requests. It
+ restores the context to the <code class="classname">SecurityContextHolder</code> for each
+ request and, crucially, clears the <code class="classname">SecurityContextHolder</code> when
+ the request completes. You shouldn't interact directly with the
+ <code class="literal">HttpSession</code> for security purposes. There is simply no
+ justification for doing so - always use the
+ <code class="classname">SecurityContextHolder</code> instead. </p><p> Many other types of application (for example, a stateless RESTful web service) do
+ not use HTTP sessions and will re-authenticate on every request. However, it is
+ still important that the <code class="classname">SecurityContextPersistenceFilter</code> is
+ included in the chain to make sure that the
+ <code class="classname">SecurityContextHolder</code> is cleared after each request.</p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>In an application which receives concurrent requests in a single session, the
+ same <code class="interfacename">SecurityContext</code> instance will be shared
+ between threads. Even though a <code class="classname">ThreadLocal</code> is being used,
+ it is the same instance that is retrieved from the
+ <code class="interfacename">HttpSession</code> for each thread. This has
+ implications if you wish to temporarily change the context under which a thread
+ is running. If you just use <code class="code">SecurityContextHolder.getContext()</code>, and
+ call <code class="code">setAuthentication(anAuthentication)</code> on the returned context
+ object, then the <code class="interfacename">Authentication</code> object will
+ change in <span class="emphasis"><em>all</em></span> concurrent threads which share the same
+ <code class="interfacename">SecurityContext</code> instance. You can customize the
+ behaviour of <code class="classname">SecurityContextPersistenceFilter</code> to create a
+ completely new <code class="interfacename">SecurityContext</code> for each request,
+ preventing changes in one thread from affecting another. Alternatively you can
+ create a new instance just at the point where you temporarily change the
+ context. The method <code class="code">SecurityContextHolder.createEmptyContext()</code>
+ always returns a new context instance.</p></td></tr></table></div></div></div><div class="section" title="6.5 Access-Control (Authorization) in Spring Security"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="tech-intro-access-control"></a>6.5 Access-Control (Authorization) in Spring Security</h2></div></div></div><p> The main interface responsible for making access-control decisions in Spring Security
+ is the <code class="interfacename">AccessDecisionManager</code>. It has a
+ <code class="methodname">decide</code> method which takes an
+ <code class="interfacename">Authentication</code> object representing the principal
+ requesting access, a <span class="quote">“<span class="quote">secure object</span>”</span> (see below) and a list of security
+ metadata attributes which apply for the object (such as a list of roles which are
+ required for access to be granted). </p><div class="section" title="6.5.1 Security and AOP Advice"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2410"></a>6.5.1 Security and AOP Advice</h3></div></div></div><p>If you're familiar with AOP, you'd be aware there are different types of advice
+ available: before, after, throws and around. An around advice is very useful,
+ because an advisor can elect whether or not to proceed with a method invocation,
+ whether or not to modify the response, and whether or not to throw an exception.
+ Spring Security provides an around advice for method invocations as well as web
+ requests. We achieve an around advice for method invocations using Spring's standard
+ AOP support and we achieve an around advice for web requests using a standard
+ Filter.</p><p>For those not familiar with AOP, the key point to understand is that Spring
+ Security can help you protect method invocations as well as web requests. Most
+ people are interested in securing method invocations on their services layer. This
+ is because the services layer is where most business logic resides in
+ current-generation J2EE applications. If you just need to secure method invocations
+ in the services layer, Spring's standard AOP will be adequate. If you need to secure
+ domain objects directly, you will likely find that AspectJ is worth
+ considering.</p><p>You can elect to perform method authorization using AspectJ or Spring AOP, or you
+ can elect to perform web request authorization using filters. You can use zero, one,
+ two or three of these approaches together. The mainstream usage pattern is to
+ perform some web request authorization, coupled with some Spring AOP method
+ invocation authorization on the services layer.</p></div><div class="section" title="6.5.2 Secure Objects and the AbstractSecurityInterceptor"><div class="titlepage"><div><div><h3 class="title"><a name="secure-objects"></a>6.5.2 Secure Objects and the <code class="classname">AbstractSecurityInterceptor</code></h3></div></div></div><p>So what <span class="emphasis"><em>is</em></span> a <span class="quote">“<span class="quote">secure object</span>”</span> anyway? Spring
+ Security uses the term to refer to any object that can have security (such as an
+ authorization decision) applied to it. The most common examples are method
+ invocations and web requests.</p><p>Each supported secure object type has its own interceptor class, which is a
+ subclass of <code class="classname">AbstractSecurityInterceptor</code>. Importantly, by the
+ time the <code class="classname">AbstractSecurityInterceptor</code> is called, the
+ <code class="classname">SecurityContextHolder</code> will contain a valid
+ <code class="interfacename">Authentication</code> if the principal has been
+ authenticated.</p><p><code class="classname">AbstractSecurityInterceptor</code> provides a consistent workflow
+ for handling secure object requests, typically: </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>Look up the <span class="quote">“<span class="quote">configuration attributes</span>”</span> associated with the
+ present request</p></li><li class="listitem"><p>Submitting the secure object, current
+ <code class="interfacename">Authentication</code> and configuration attributes
+ to the <code class="interfacename">AccessDecisionManager</code> for an
+ authorization decision</p></li><li class="listitem"><p>Optionally change the <code class="interfacename">Authentication</code> under
+ which the invocation takes place</p></li><li class="listitem"><p>Allow the secure object invocation to proceed (assuming access was
+ granted)</p></li><li class="listitem"><p>Call the <code class="interfacename">AfterInvocationManager</code> if
+ configured, once the invocation has returned. If the invocation raised an
+ exception, the <code class="interfacename">AfterInvocationManager</code>
+ will not be invoked.</p></li></ol></div><div class="section" title="What are Configuration Attributes?"><div class="titlepage"><div><div><h4 class="title"><a name="tech-intro-config-attributes"></a>What are Configuration Attributes?</h4></div></div></div><p> A <span class="quote">“<span class="quote">configuration attribute</span>”</span> can be thought of as a String that
+ has special meaning to the classes used by
+ <code class="classname">AbstractSecurityInterceptor</code>. They are represented by the
+ interface <code class="interfacename">ConfigAttribute</code> within the framework.
+ They may be simple role names or have more complex meaning, depending on the how
+ sophisticated the <code class="interfacename">AccessDecisionManager</code>
+ implementation is. The <code class="classname">AbstractSecurityInterceptor</code> is
+ configured with a <code class="interfacename">SecurityMetadataSource</code> which it
+ uses to look up the attributes for a secure object. Usually this configuration
+ will be hidden from the user. Configuration attributes will be entered as
+ annotations on secured methods or as access attributes on secured URLs. For
+ example, when we saw something like <code class="literal"><intercept-url
+ pattern='/secure/**' access='ROLE_A,ROLE_B'/></code> in the namespace
+ introduction, this is saying that the configuration attributes
+ <code class="literal">ROLE_A</code> and <code class="literal">ROLE_B</code> apply to web requests
+ matching the given pattern. In practice, with the default
+ <code class="interfacename">AccessDecisionManager</code> configuration, this means
+ that anyone who has a <code class="interfacename">GrantedAuthority</code> matching
+ either of these two attributes will be allowed access. Strictly speaking though,
+ they are just attributes and the interpretation is dependent on the
+ <code class="interfacename">AccessDecisionManager</code> implementation. The use of
+ the prefix <code class="literal">ROLE_</code> is a marker to indicate that these
+ attributes are roles and should be consumed by Spring Security's
+ <code class="classname">RoleVoter</code>. This is only relevant when a voter-based
+ <code class="interfacename">AccessDecisionManager</code> is in use. We'll see how
+ the <code class="interfacename">AccessDecisionManager</code> is implemented in the
+ <a class="link" href="#authz-arch" title="14. Authorization Architecture">authorization chapter</a>.</p></div><div class="section" title="RunAsManager"><div class="titlepage"><div><div><h4 class="title"><a name="d0e2540"></a>RunAsManager</h4></div></div></div><p>Assuming <code class="interfacename">AccessDecisionManager</code> decides to allow
+ the request, the <code class="classname">AbstractSecurityInterceptor</code> will
+ normally just proceed with the request. Having said that, on rare occasions
+ users may want to replace the <code class="interfacename">Authentication</code>
+ inside the <code class="interfacename">SecurityContext</code> with a different
+ <code class="interfacename">Authentication</code>, which is handled by the
+ <code class="interfacename">AccessDecisionManager</code> calling a
+ <code class="literal">RunAsManager</code>. This might be useful in reasonably unusual
+ situations, such as if a services layer method needs to call a remote system and
+ present a different identity. Because Spring Security automatically propagates
+ security identity from one server to another (assuming you're using a
+ properly-configured RMI or HttpInvoker remoting protocol client), this may be
+ useful.</p></div><div class="section" title="AfterInvocationManager"><div class="titlepage"><div><div><h4 class="title"><a name="d0e2566"></a>AfterInvocationManager</h4></div></div></div><p>Following the secure object invocation proceeding and then returning - which may mean a
+ method invocation completing or a filter chain proceeding - the
+ <code class="classname">AbstractSecurityInterceptor</code> gets one final chance to
+ handle the invocation. At this stage the
+ <code class="classname">AbstractSecurityInterceptor</code> is interested in possibly
+ modifying the return object. We might want this to happen because an
+ authorization decision couldn't be made <span class="quote">“<span class="quote">on the way in</span>”</span> to a secure
+ object invocation. Being highly pluggable,
+ <code class="classname">AbstractSecurityInterceptor</code> will pass control to an
+ <code class="literal">AfterInvocationManager</code> to actually modify the object if
+ needed. This class can even entirely replace the object, or throw an exception,
+ or not change it in any way as it chooses. The after-invocation checks will only
+ be executed if the invocation is successful. If an exception occurs, the additional
+ checks will be skipped.
+ </p><p><code class="classname">AbstractSecurityInterceptor</code> and its related objects are
+ shown in <a class="xref" href="#abstract-security-interceptor" title="Figure 6.1. Security interceptors and the “secure object” model">Figure 6.1, “Security interceptors and the <span class="quote">“<span class="quote">secure object</span>”</span> model”</a>. </p><div class="figure"><a name="abstract-security-interceptor"></a><p class="title"><b>Figure 6.1. Security interceptors and the <span class="quote">“<span class="quote">secure object</span>”</span> model</b></p><div class="figure-contents"><div class="mediaobject" align="center"><img src="images/security-interception.png" align="middle" alt="Security interceptors and the secure object model"></div></div></div><p><br class="figure-break"></p></div><div class="section" title="Extending the Secure Object Model"><div class="titlepage"><div><div><h4 class="title"><a name="d0e2601"></a>Extending the Secure Object Model</h4></div></div></div><p>Only developers contemplating an entirely new way of intercepting and
+ authorizing requests would need to use secure objects directly. For example, it
+ would be possible to build a new secure object to secure calls to a messaging
+ system. Anything that requires security and also provides a way of intercepting
+ a call (like the AOP around advice semantics) is capable of being made into a
+ secure object. Having said that, most Spring applications will simply use the
+ three currently supported secure object types (AOP Alliance
+ <code class="classname">MethodInvocation</code>, AspectJ
+ <code class="classname">JoinPoint</code> and web request
+ <code class="classname">FilterInvocation</code>) with complete transparency.</p></div></div></div><div class="section" title="6.6 Localization"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="localization"></a>6.6 Localization</h2></div></div></div><p>Spring Security supports localization of exception messages that end users are likely
+ to see. If your application is designed for English-speaking users, you don't need to do
+ anything as by default all Security Security messages are in English. If you need to
+ support other locales, everything you need to know is contained in this section.</p><p>All exception messages can be localized, including messages related to authentication
+ failures and access being denied (authorization failures). Exceptions and logging
+ messages that are focused on developers or system deployers (including incorrect
+ attributes, interface contract violations, using incorrect constructors, startup time
+ validation, debug-level logging) are not localized and instead are hard-coded in English
+ within Spring Security's code.</p><p>Shipping in the <code class="literal">spring-security-core-xx.jar</code> you will find an
+ <code class="literal">org.springframework.security</code> package that in turn contains a
+ <code class="literal">messages.properties</code> file, as well as localized versions for some
+ common languages. This should be referred to by your
+ <code class="literal">ApplicationContext</code>, as Spring Security classes implement Spring's
+ <code class="literal">MessageSourceAware</code> interface and expect the message resolver to be
+ dependency injected at application context startup time. Usually all you need to do is
+ register a bean inside your application context to refer to the messages. An example is
+ shown below:</p><p>
+ </p><pre class="programlisting">
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"messageSource"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.context.support.ReloadableResourceBundleMessageSource"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"basename"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"classpath:org/springframework/security/messages"</span><span class="hl-tag">/></span>
+<span class="hl-tag"></bean></span>
</pre><p>
- </p><p>The <code class="literal">messages.properties</code> is named in accordance with standard resource
- bundles and represents the default language supported by Spring Security messages. This
- default file is in English. If you do not register a message source, Spring Security will
- still work correctly and fallback to hard-coded English versions of the messages.</p><p>If you wish to customize the <code class="literal">messages.properties</code> file, or support other
- languages, you should copy the file, rename it accordingly, and register it inside the above
- bean definition. There are not a large number of message keys inside this file, so
- localization should not be considered a major initiative. If you do perform localization of
- this file, please consider sharing your work with the community by logging a JIRA task and
- attaching your appropriately-named localized version of
- <code class="literal">messages.properties</code>.</p><p>Rounding out the discussion on localization is the Spring <code class="literal">ThreadLocal</code>
- known as <code class="classname">org.springframework.context.i18n.LocaleContextHolder</code>. You
- should set the <code class="classname">LocaleContextHolder</code> to represent the preferred
- <code class="literal">Locale</code> of each user. Spring Security will attempt to locate a message
- from the message source using the <code class="literal">Locale</code> obtained from this
- <code class="literal">ThreadLocal</code>. Please refer to the Spring Framework documentation for
- further details on using <code class="literal">LocaleContextHolder</code>.</p></div></div><div class="chapter" title="6. Core Services"><div class="titlepage"><div><div><h2 class="title"><a name="core-services"></a>6. Core Services</h2></div></div></div><p> Now that we have a high-level overview of the Spring Security architecture and its core
+ </p><p>The <code class="literal">messages.properties</code> is named in accordance with standard
+ resource bundles and represents the default language supported by Spring Security
+ messages. This default file is in English. </p><p>If you wish to customize the <code class="literal">messages.properties</code> file, or support
+ other languages, you should copy the file, rename it accordingly, and register it inside
+ the above bean definition. There are not a large number of message keys inside this
+ file, so localization should not be considered a major initiative. If you do perform
+ localization of this file, please consider sharing your work with the community by
+ logging a JIRA task and attaching your appropriately-named localized version of
+ <code class="literal">messages.properties</code>.</p><p>Spring Security relies on Spring's localization support in order to actually lookup
+ the appropriate message. In order for this to work, you have to make sure that the
+ locale from the incoming request is stored in Spring's
+ <code class="classname">org.springframework.context.i18n.LocaleContextHolder</code>. Spring
+ MVC's <code class="classname">DispatcherServlet</code> does this for your application
+ automatically, but since Spring Security's filters are invoked before this, the
+ <code class="classname">LocaleContextHolder</code> needs to be set up to contain the correct
+ <code class="literal">Locale</code> before the filters are called. You can either do this in a
+ filter yourself (which must come before the Spring Security filters in
+ <code class="filename">web.xml</code>) or you can use Spring's
+ <code class="classname">RequestContextFilter</code>. Please refer to the Spring Framework
+ documentation for further details on using localization with Spring. </p><p>The <span class="quote">“<span class="quote">contacts</span>”</span> sample application is set up to use localized messages.
+ </p></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e2198" href="#d0e2198" class="para">9</a>] </sup>It isn't possible to create a session once the
+ response has been committed.</p></div></div></div><div class="chapter" title="7. Core Services"><div class="titlepage"><div><div><h2 class="title"><a name="core-services"></a>7. Core Services</h2></div></div></div><p> Now that we have a high-level overview of the Spring Security architecture and its core
classes, let's take a closer look at one or two of the core interfaces and their
implementations, in particular the <code class="interfacename">AuthenticationManager</code>,
- <code class="interfacename">UserDetailsService</code> and the
- <code class="interfacename">AccessDecisionManager</code>. These crop up regularly throughout
- the remainder of this document so it's important you know how they are configured and how
- they operate. </p><div class="section" title="6.1 The AuthenticationManager, ProviderManager and AuthenticationProviders"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="core-services-authentication-manager"></a>6.1 The <code class="interfacename">AuthenticationManager</code>,
- <code class="classname">ProviderManager</code> and
- <code class="classname">AuthenticationProvider</code>s</h2></div></div></div><p>The <code class="interfacename">AuthenticationManager</code> is just an interface, so the
+ <code class="interfacename">UserDetailsService</code> and the
+ <code class="interfacename">AccessDecisionManager</code>. These crop up regularly throughout the
+ remainder of this document so it's important you know how they are configured and how they
+ operate. </p><div class="section" title="7.1 The AuthenticationManager, ProviderManager and AuthenticationProviders"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="core-services-authentication-manager"></a>7.1 The <code class="interfacename">AuthenticationManager</code>,
+ <code class="classname">ProviderManager</code> and
+ <code class="classname">AuthenticationProvider</code>s</h2></div></div></div><p>The <code class="interfacename">AuthenticationManager</code> is just an interface, so the
implementation can be anything we choose, but how does it work in practice? What if we
need to check multiple authentication databases or a combination of different
authentication services such as a database and an LDAP server?</p><p>The default implementation in Spring Security is called
- <code class="classname">ProviderManager</code> and rather than handling the authentication
+ <code class="classname">ProviderManager</code> and rather than handling the authentication
request itself, it delegates to a list of configured
- <code class="classname">AuthenticationProvider</code>s, each of which is queried in turn to
- see if it can perform the authentication. Each provider will either throw an exception
- or return a fully populated <code class="interfacename">Authentication</code> object.
- Remember our good friends, <code class="interfacename">UserDetails</code> and
- <code class="interfacename">UserDetailsService</code>? If not, head back to the previous
+ <code class="classname">AuthenticationProvider</code>s, each of which is queried in turn to see
+ if it can perform the authentication. Each provider will either throw an exception or
+ return a fully populated <code class="interfacename">Authentication</code> object. Remember
+ our good friends, <code class="interfacename">UserDetails</code> and
+ <code class="interfacename">UserDetailsService</code>? If not, head back to the previous
chapter and refresh your memory. The most common approach to verifying an authentication
request is to load the corresponding <code class="interfacename">UserDetails</code> and
check the loaded password against the one that has been entered by the user. This is the
approach used by the <code class="classname">DaoAuthenticationProvider</code> (see below). The
loaded <code class="interfacename">UserDetails</code> object - and particularly the
- <code class="literal">GrantedAuthority</code>s it contains - will be used when building the
- fully populated <code class="interfacename">Authentication</code> object which is returned
- from a successful authentication and stored in the
- <code class="classname">SecurityContext</code>. </p><p> If you are using the namespace, an instance of
- <code class="classname">ProviderManager</code> is created and maintained internally, and
- you add providers to it by using the namespace authentication provider elements
- (see <a class="link" href="#ns-auth-manager" title="2.6 The Authentication Manager and the Namespace">the namespace chapter</a>). In this
- case, you should not declare a <code class="classname">ProviderManager</code> bean in your
- application context. However, if you are not using the namespace then you would declare
- it like so: </p><pre class="programlisting">
+ <code class="literal">GrantedAuthority</code>s it contains - will be used when building the fully
+ populated <code class="interfacename">Authentication</code> object which is returned from a
+ successful authentication and stored in the <code class="classname">SecurityContext</code>. </p><p> If you are using the namespace, an instance of <code class="classname">ProviderManager</code>
+ is created and maintained internally, and you add providers to it by using the namespace
+ authentication provider elements (see <a class="link" href="#ns-auth-manager" title="3.6 The Authentication Manager and the Namespace">the namespace
+ chapter</a>). In this case, you should not declare a
+ <code class="classname">ProviderManager</code> bean in your application context. However, if you
+ are not using the namespace then you would declare it like so: </p><pre class="programlisting">
<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"authenticationManager"</span>
<span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.authentication.ProviderManager"</span><span class="hl-tag">></span>
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"providers"</span><span class="hl-tag">></span>
@@ -1395,15 +1515,15 @@ Successfully authenticated. Security context contains: \
is implied by the use of a <code class="literal">List</code>), with each provider able to attempt
authentication, or skip authentication by simply returning <code class="literal">null</code>. If
all implementations return null, the <code class="literal">ProviderManager</code> will throw a
- <code class="exceptionname">ProviderNotFoundException</code>. If you're interested in
+ <code class="exceptionname">ProviderNotFoundException</code>. If you're interested in
learning more about chaining providers, please refer to the
- <code class="literal">ProviderManager</code> JavaDocs.</p><p> Authentication mechanisms such as a web form-login processing filter are injected
+ <code class="literal">ProviderManager</code> JavaDocs.</p><p> Authentication mechanisms such as a web form-login processing filter are injected
with a reference to the <code class="interfacename">ProviderManager</code> and will call it
to handle their authentication requests. The providers you require will sometimes be
interchangeable with the authentication mechanisms, while at other times they will
depend on a specific authentication mechanism. For example,
- <code class="classname">DaoAuthenticationProvider</code> and
- <code class="classname">LdapAuthenticationProvider</code> are compatible with any mechanism
+ <code class="classname">DaoAuthenticationProvider</code> and
+ <code class="classname">LdapAuthenticationProvider</code> are compatible with any mechanism
which submits a simple username/password authentication request and so will work with
form-based logins or HTTP Basic authentication. On the other hand, some authentication
mechanisms create an authentication request object which can only be interpreted by a
@@ -1412,93 +1532,87 @@ Successfully authenticated. Security context contains: \
authenticated by a <code class="classname">CasAuthenticationProvider</code>. You needn't be too
concerned about this, because if you forget to register a suitable provider, you'll
simply receive a <code class="literal">ProviderNotFoundException</code> when an attempt to
- authenticate is made.</p><div class="section" title="6.1.1 DaoAuthenticationProvider"><div class="titlepage"><div><div><h3 class="title"><a name="core-services-dao-provider"></a>6.1.1 <code class="literal">DaoAuthenticationProvider</code></h3></div></div></div><p>The simplest <code class="interfacename">AuthenticationProvider</code> implemented by
+ authenticate is made.</p><div class="section" title="7.1.1 Erasing Credentials on Successful Authentication"><div class="titlepage"><div><div><h3 class="title"><a name="core-services-erasing-credentials"></a>7.1.1 Erasing Credentials on Successful Authentication</h3></div></div></div><p> By default (from Spring Security 3.1 onwards) the
+ <code class="classname">ProviderManager</code> will attempt to clear any sensitive
+ credentials information from the <code class="interfacename">Authentication</code>
+ object which is returned by a successful authentication request. This prevents
+ information like passwords being retained longer than necessary. </p><p> This may cause issues when you are using a cache of user objects, for example, to
+ improve performance in a stateless application. If the
+ <code class="interfacename">Authentication</code> contains a reference to an object in
+ the cache (such as a <code class="interfacename">UserDetails</code> instance) and this
+ has its credentials removed, then it will no longer be possible to authenticate
+ against the cached value. You need to take this into account if you are using a
+ cache. An obvious solution is to make a copy of the object first, either in the
+ cache implementation or in the <code class="interfacename">AuthenticationProvider</code>
+ which creates the returned <code class="interfacename">Authentication</code> object.
+ Alternatively, you can disable the
+ <code class="literal">eraseCredentialsAfterAuthentication</code> property on
+ <code class="classname">ProviderManager</code>. See the Javadoc for more information.
+ </p></div><div class="section" title="7.1.2 DaoAuthenticationProvider"><div class="titlepage"><div><div><h3 class="title"><a name="core-services-dao-provider"></a>7.1.2 <code class="literal">DaoAuthenticationProvider</code></h3></div></div></div><p>The simplest <code class="interfacename">AuthenticationProvider</code> implemented by
Spring Security is <code class="literal">DaoAuthenticationProvider</code>, which is also one
of the earliest supported by the framework. It leverages a
- <code class="interfacename">UserDetailsService</code> (as a DAO) in order to lookup
- the username, password and <code class="interfacename">GrantedAuthority</code>s. It
+ <code class="interfacename">UserDetailsService</code> (as a DAO) in order to lookup the
+ username, password and <code class="interfacename">GrantedAuthority</code>s. It
authenticates the user simply by comparing the password submitted in a
- <code class="classname">UsernamePasswordAuthenticationToken</code> against the one
- loaded by the <code class="interfacename">UserDetailsService</code>. Configuring the
- provider is quite simple: </p><pre class="programlisting">
+ <code class="classname">UsernamePasswordAuthenticationToken</code> against the one loaded by
+ the <code class="interfacename">UserDetailsService</code>. Configuring the provider is
+ quite simple: </p><pre class="programlisting">
<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"daoAuthenticationProvider"</span>
<span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.authentication.dao.DaoAuthenticationProvider"</span><span class="hl-tag">></span>
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"userDetailsService"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"inMemoryDaoImpl"</span><span class="hl-tag">/></span>
- <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"saltSource"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"saltSource"</span><span class="hl-tag">/></span>
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"passwordEncoder"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"passwordEncoder"</span><span class="hl-tag">/></span>
-<span class="hl-tag"></bean></span></pre><p> The <code class="interfacename">PasswordEncoder</code> and
- <code class="interfacename">SaltSource</code> are optional. A
- <code class="interfacename">PasswordEncoder</code> provides encoding and decoding of
+<span class="hl-tag"></bean></span></pre><p> The <code class="interfacename">PasswordEncoder</code> is optional. A
+ <code class="interfacename">PasswordEncoder</code> provides encoding and decoding of
passwords presented in the <code class="interfacename">UserDetails</code> object that is
- returned from the configured <code class="interfacename">UserDetailsService</code>. A
- <code class="interfacename">SaltSource</code> enables the passwords to be populated
- with a "salt", which enhances the security of the passwords in the authentication
- repository. These will be discussed in more detail <a class="link" href="#core-services-password-encoding" title="6.3 Password Encoding">below</a>. </p></div><div class="section" title="6.1.2 Erasing Credentials on Successful Authentication"><div class="titlepage"><div><div><h3 class="title"><a name="core-services-erasing-credentials"></a>6.1.2 Erasing Credentials on Successful Authentication</h3></div></div></div><p>
- From Spring Security 3.0.3, you can configure the <code class="classname">ProviderManager</code>
- will attempt to clear any sensitive credentials information from the
- <code class="interfacename">Authentication</code> object which is returned by a successful
- authentication request, to prevent information like passwords being retained longer
- than necessary. This feature is controlled by the <code class="literal">eraseCredentialsAfterAuthentication</code>
- property on <code class="classname">ProviderManager</code>. It is off by default.
- See the Javadoc for more information.
- </p><p>
- This may cause issues when you are using a cache of user objects, for example, to
- improve performance in a stateless application. If the <code class="interfacename">Authentication</code>
- contains a reference to an object in the cache (such as a <code class="interfacename">UserDetails</code>
- instance) and this has its credentials removed, then it will no longer be possible to authenticate
- against the cached value. You need to take this into account if you are using a cache. An obvious
- solution is to make a copy of the object first, either in the cache implementation or in
- the <code class="interfacename">AuthenticationProvider</code> which creates the returned
- <code class="interfacename">Authentication</code> object.
- </p></div></div><div class="section" title="6.2 UserDetailsService Implementations"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e2530"></a>6.2 <code class="interfacename">UserDetailsService</code> Implementations</h2></div></div></div><p>As mentioned in the earlier in this reference guide, most authentication providers
+ returned from the configured <code class="interfacename">UserDetailsService</code>. This
+ will be discussed in more detail <a class="link" href="#core-services-password-encoding" title="7.3 Password Encoding">below</a>. </p></div></div><div class="section" title="7.2 UserDetailsService Implementations"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e2871"></a>7.2 <code class="interfacename">UserDetailsService</code> Implementations</h2></div></div></div><p>As mentioned in the earlier in this reference guide, most authentication providers
take advantage of the <code class="interfacename">UserDetails</code> and
- <code class="interfacename">UserDetailsService</code> interfaces. Recall that the
- contract for <code class="interfacename">UserDetailsService</code> is a single
- method:</p><p>
+ <code class="interfacename">UserDetailsService</code> interfaces. Recall that the contract
+ for <code class="interfacename">UserDetailsService</code> is a single method:</p><p>
</p><pre class="programlisting">
- UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
+ UserDetails loadUserByUsername(String username) <span class="hl-keyword">throws</span> UsernameNotFoundException;
</pre><p>
</p><p>The returned <code class="interfacename">UserDetails</code> is an interface that provides
getters that guarantee non-null provision of authentication information such as the
username, password, granted authorities and whether the user account is enabled or
disabled. Most authentication providers will use a
- <code class="interfacename">UserDetailsService</code>, even if the username and password
- are not actually used as part of the authentication decision. They may use the returned
- <code class="interfacename">UserDetails</code> object just for its
- <code class="literal">GrantedAuthority</code> information, because some other system (like
- LDAP or X.509 or CAS etc) has undertaken the responsibility of actually validating the
+ <code class="interfacename">UserDetailsService</code>, even if the username and password are
+ not actually used as part of the authentication decision. They may use the returned
+ <code class="interfacename">UserDetails</code> object just for its
+ <code class="literal">GrantedAuthority</code> information, because some other system (like LDAP or
+ X.509 or CAS etc) has undertaken the responsibility of actually validating the
credentials.</p><p>Given <code class="interfacename">UserDetailsService</code> is so simple to implement, it
should be easy for users to retrieve authentication information using a persistence
strategy of their choice. Having said that, Spring Security does include a couple of
- useful base implementations, which we'll look at below.</p><div class="section" title="6.2.1 In-Memory Authentication"><div class="titlepage"><div><div><h3 class="title"><a name="core-services-in-memory-service"></a>6.2.1 In-Memory Authentication</h3></div></div></div><p>Is easy to use create a custom <code class="interfacename">UserDetailsService</code>
+ useful base implementations, which we'll look at below.</p><div class="section" title="7.2.1 In-Memory Authentication"><div class="titlepage"><div><div><h3 class="title"><a name="core-services-in-memory-service"></a>7.2.1 In-Memory Authentication</h3></div></div></div><p>Is easy to use create a custom <code class="interfacename">UserDetailsService</code>
implementation that extracts information from a persistence engine of choice, but
many applications do not require such complexity. This is particularly true if
you're building a prototype application or just starting integrating Spring
Security, when you don't really want to spend time configuring databases or writing
- <code class="interfacename">UserDetailsService</code> implementations. For this sort
- of situation, a simple option is to use the <code class="literal">user-service</code> element
- from the security <a class="link" href="#ns-minimal" title="2.2.2 A Minimal <http> Configuration">namespace</a>: </p><pre class="programlisting">
- <user-service id="userDetailsService">
- <user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
- <user name="bob" password="bobspassword" authorities="ROLE_USER" />
- </user-service>
+ <code class="interfacename">UserDetailsService</code> implementations. For this sort of
+ situation, a simple option is to use the <code class="literal">user-service</code> element
+ from the security <a class="link" href="#ns-minimal" title="3.2.2 A Minimal <http> Configuration">namespace</a>: </p><pre class="programlisting">
+ <span class="hl-tag"><user-service</span> <span class="hl-attribute">id</span>=<span class="hl-value">"userDetailsService"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><user</span> <span class="hl-attribute">name</span>=<span class="hl-value">"jimi"</span> <span class="hl-attribute">password</span>=<span class="hl-value">"jimispassword"</span> <span class="hl-attribute">authorities</span>=<span class="hl-value">"ROLE_USER, ROLE_ADMIN"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"><user</span> <span class="hl-attribute">name</span>=<span class="hl-value">"bob"</span> <span class="hl-attribute">password</span>=<span class="hl-value">"bobspassword"</span> <span class="hl-attribute">authorities</span>=<span class="hl-value">"ROLE_USER"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"></user-service></span>
</pre><p> This also supports the use of an external properties
file: </p><pre class="programlisting">
- <user-service id="userDetailsService" properties="users.properties"/>
+ <span class="hl-tag"><user-service</span> <span class="hl-attribute">id</span>=<span class="hl-value">"userDetailsService"</span> <span class="hl-attribute">properties</span>=<span class="hl-value">"users.properties"</span><span class="hl-tag">/></span>
</pre><p> The properties file should contain entries in the form
</p><pre class="programlisting">username=password,grantedAuthority[,grantedAuthority][,enabled|disabled]</pre><p>
For example
</p><pre class="programlisting">
jimi=jimispassword,ROLE_USER,ROLE_ADMIN,enabled
- bob=bobspassword,ROLE_USER,enabled</pre></div><div class="section" title="6.2.2 JdbcDaoImpl"><div class="titlepage"><div><div><h3 class="title"><a name="core-services-jdbc-user-service"></a>6.2.2 <code class="literal">JdbcDaoImpl</code></h3></div></div></div><p>Spring Security also includes a <code class="interfacename">UserDetailsService</code>
+ bob=bobspassword,ROLE_USER,enabled</pre></div><div class="section" title="7.2.2 JdbcDaoImpl"><div class="titlepage"><div><div><h3 class="title"><a name="core-services-jdbc-user-service"></a>7.2.2 <code class="literal">JdbcDaoImpl</code></h3></div></div></div><p>Spring Security also includes a <code class="interfacename">UserDetailsService</code>
that can obtain authentication information from a JDBC data source. Internally
Spring JDBC is used, so it avoids the complexity of a fully-featured object
relational mapper (ORM) just to store user details. If your application does use an
ORM tool, you might prefer to write a custom
- <code class="interfacename">UserDetailsService</code> to reuse the mapping files
- you've probably already created. Returning to <code class="literal">JdbcDaoImpl</code>, an
- example configuration is shown below:</p><p>
+ <code class="interfacename">UserDetailsService</code> to reuse the mapping files you've
+ probably already created. Returning to <code class="literal">JdbcDaoImpl</code>, an example
+ configuration is shown below:</p><p>
</p><pre class="programlisting">
<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"dataSource"</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.jdbc.datasource.DriverManagerDataSource"</span><span class="hl-tag">></span>
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"driverClassName"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"org.hsqldb.jdbcDriver"</span><span class="hl-tag">/></span>
@@ -1507,240 +1621,327 @@ Successfully authenticated. Security context contains: \
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"password"</span> <span class="hl-attribute">value</span>=<span class="hl-value">""</span><span class="hl-tag">/></span>
<span class="hl-tag"></bean></span>
-<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"userDetailsService"</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl"</span><span class="hl-tag">></span>
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"userDetailsService"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl"</span><span class="hl-tag">></span>
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"dataSource"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"dataSource"</span><span class="hl-tag">/></span>
<span class="hl-tag"></bean></span> </pre><p>
</p><p>You can use different relational database management systems by modifying the
- <code class="literal">DriverManagerDataSource</code> shown above. You can also use a
- global data source obtained from JNDI, as with any other Spring
- configuration.</p><div class="section" title="Authority Groups"><div class="titlepage"><div><div><h4 class="title"><a name="d0e2623"></a>Authority Groups</h4></div></div></div><p>By default, <code class="classname">JdbcDaoImpl</code> loads the authorities for a
+ <code class="literal">DriverManagerDataSource</code> shown above. You can also use a global
+ data source obtained from JNDI, as with any other Spring configuration.</p><div class="section" title="Authority Groups"><div class="titlepage"><div><div><h4 class="title"><a name="d0e2964"></a>Authority Groups</h4></div></div></div><p>By default, <code class="classname">JdbcDaoImpl</code> loads the authorities for a
single user with the assumption that the authorities are mapped directly to
users (see the <a class="link" href="#appendix-schema" title="Appendix A. Security Database Schema">database schema
- appendix</a>). An alternative approach is to partition the authorities
- into groups and assign groups to the user. Some people prefer this approach as a
+ appendix</a>). An alternative approach is to partition the authorities into
+ groups and assign groups to the user. Some people prefer this approach as a
means of administering user rights. See the <code class="classname">JdbcDaoImpl</code>
Javadoc for more information on how to enable the use of group authorities. The
- group schema is also included in the appendix.</p></div></div></div><div class="section" title="6.3 Password Encoding"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="core-services-password-encoding"></a>6.3 Password Encoding</h2></div></div></div><p>Spring Security's <code class="interfacename">PasswordEncoder</code> interface is used to
- support the use of passwords which are encoded in some way in persistent storage. This
- will normally mean that the passwords are <span class="quote">“<span class="quote">hashed</span>”</span> using a digest algorithm
- such as MD5 or SHA.</p><div class="section" title="6.3.1 What is a hash?"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2649"></a>6.3.1 What is a hash?</h3></div></div></div><p>Password hashing is not unique to Spring Security but is a common source of
+ group schema is also included in the appendix.</p></div></div></div><div class="section" title="7.3 Password Encoding"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="core-services-password-encoding"></a>7.3 Password Encoding</h2></div></div></div><p>Spring Security's
+ <code class="interfacename">PasswordEncoder</code> interface is used to support the use of
+ passwords which are encoded in some way in persistent storage. This will normally mean
+ that the passwords are <span class="quote">“<span class="quote">hashed</span>”</span> using a digest algorithm such as MD5 or
+ SHA. Spring Security 3.1's <a class="link" href="#spring-security-crypto-passwordencoders" title="25.4 Password Encoding"><code class="literal">crypto</code></a> package introduces a simpler API which encourages
+ best-practice for password hashing. We would encourage you to use these APIs for new
+ development and regard the classes in package
+ <code class="literal">org.springframework.security.authentication.encoding</code> as legacy
+ implementations. The <code class="classname">DaoAuthenticationProvider</code> can be injected
+ with either the new or legacy <code class="interfacename">PasswordEncoder</code>
+ types.</p><div class="section" title="7.3.1 What is a hash?"><div class="titlepage"><div><div><h3 class="title"><a name="d0e3003"></a>7.3.1 What is a hash?</h3></div></div></div><p>Password hashing is not unique to Spring Security but is a common source of
confusion for users who are not familiar with the concept. A hash (or digest)
algorithm is a one-way function which produces a piece of fixed-length output data
(the hash) from some input data, such as a password. As an example, the MD5 hash of
the string <span class="quote">“<span class="quote">password</span>”</span> (in hexadecimal) is
</p><pre class="programlisting">
5f4dcc3b5aa765d61d8327deb882cf99
-</pre><p> A hash is
- <span class="quote">“<span class="quote">one-way</span>”</span> in the sense that it is very difficult (effectively
+</pre><p>
+ A hash is <span class="quote">“<span class="quote">one-way</span>”</span> in the sense that it is very difficult (effectively
impossible) to obtain the original input given the hash value, or indeed any
possible input which would produce that hash value. This property makes hash values
very useful for authentication purposes. They can be stored in your user database as
an alternative to plaintext passwords and even if the values are compromised they do
not immediately reveal a password which can be used to login. Note that this also
- means you have no way of recovering the password once it is encoded.</p></div><div class="section" title="6.3.2 Adding Salt to a Hash"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2663"></a>6.3.2 Adding Salt to a Hash</h3></div></div></div><p> One potential problem with the use of password hashes that it is relatively easy
+ means you have no way of recovering the password once it is encoded.</p></div><div class="section" title="7.3.2 Adding Salt to a Hash"><div class="titlepage"><div><div><h3 class="title"><a name="d0e3017"></a>7.3.2 Adding Salt to a Hash</h3></div></div></div><p> One potential problem with the use of password hashes that it is relatively easy
to get round the one-way property of the hash if a common word is used for the
input. For example, if you search for the hash value
- <code class="literal">5f4dcc3b5aa765d61d8327deb882cf99</code> using google, you will
- quickly find the original word <span class="quote">“<span class="quote">password</span>”</span>. In a similar way, an
- attacker can build a dictionary of hashes from a standard word list and use this to
- lookup the original password. One way to help prevent this is to have a suitably
- strong password policy to try to prevent common words from being used. Another is to
- use a <span class="quote">“<span class="quote">salt</span>”</span> when calculating the hashes. This is an additional string
- of known data for each user which is combined with the password before calculating
- the hash. Ideally the data should be as random as possible, but in practice any salt
- value is usually preferable to none. Spring Security has a
- <code class="interfacename">SaltSource</code> interface which can be used by an
- authentication provider to generate a salt value for a particular user. Using a salt
- means that an attacker has to build a separate dictionary of hashes for each salt
- value, making the attack more complicated (but not impossible).</p></div><div class="section" title="6.3.3 Hashing and Authentication"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2680"></a>6.3.3 Hashing and Authentication</h3></div></div></div><p>When an authentication provider (such as Spring Security's
- <code class="classname">DaoAuthenticationProvider</code> needs to check the password in
- a submitted authentication request against the known value for a user, and the
- stored password is encoded in some way, then the submitted value must be encoded
- using exactly the same algorithm. It's up to you to check that these are compatible
- as Spring Security has no control over the persistent values. If you add password
+ <code class="literal">5f4dcc3b5aa765d61d8327deb882cf99</code> using google, you will quickly
+ find the original word <span class="quote">“<span class="quote">password</span>”</span>. In a similar way, an attacker can
+ build a dictionary of hashes from a standard word list and use this to lookup the
+ original password. One way to help prevent this is to have a suitably strong
+ password policy to try to prevent common words from being used. Another is to use a
+ <span class="quote">“<span class="quote">salt</span>”</span> when calculating the hashes. This is an additional string of
+ known data for each user which is combined with the password before calculating the
+ hash. Ideally the data should be as random as possible, but in practice any salt
+ value is usually preferable to none. Using a salt means that an attacker has to
+ build a separate dictionary of hashes for each salt value, making the attack more
+ complicated (but not impossible).</p><p>The <code class="classname">StandardPasswordEncoder</code> in the <a class="link" href="#spring-security-crypto-passwordencoders" title="25.4 Password Encoding"><code class="literal">crypto</code></a> package uses a random 8-byte salt, which is stored
+ in the same field as the password.</p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>The legacy approach to handling salt was to inject a
+ <code class="interfacename">SaltSource</code> into the
+ <code class="classname">DaoAuthenticationProvider</code>, which would obtain a salt
+ value for a particular user and pass it to the
+ <code class="interfacename">PasswordEncoder</code>. Using a random salt and
+ combining it with the password data field means you don't have to worry about
+ the details of salt handling (such as where the the value is stored), as it is
+ all done internally. So we'd strongly recommend you use this approach unless you
+ already have a system in place which stores the salt separately.</p></td></tr></table></div></div><div class="section" title="7.3.3 Hashing and Authentication"><div class="titlepage"><div><div><h3 class="title"><a name="d0e3052"></a>7.3.3 Hashing and Authentication</h3></div></div></div><p>When an authentication provider (such as Spring Security's
+ <code class="classname">DaoAuthenticationProvider</code>) needs to check the password in a
+ submitted authentication request against the known value for a user, and the stored
+ password is encoded in some way, then the submitted value must be encoded using
+ exactly the same algorithm. It's up to you to check that these are compatible as
+ Spring Security has no control over the persistent values. If you add password
hashing to your authentication configuration in Spring Security, and your database
contains plaintext passwords, then there is no way authentication can succeed. Even
if you are aware that your database is using MD5 to encode the passwords, for
example, and your application is configured to use Spring Security's
- <code class="classname">Md5PasswordEncoder</code>, there are still things that can go
- wrong. The database may have the passwords encoded in Base 64, for example while the
- enocoder is using hexadecimal strings (the default)<sup>[<a name="d0e2691" href="#ftn.d0e2691" class="footnote">6</a>]</sup>. Alternatively your database
- may be using upper-case while the output from the encoder is lower-case. Make sure
- you write a test to check the output from your configured password encoder with a
- known password and salt combination and check that it matches the database value
- before going further and attempting to authenticate through your application. For
- more information on the default method for merging salt and password, see the
- Javadoc for <code class="classname">BasePasswordEncoder</code>. If you want to generate
- encoded passwords directly in Java for storage in your user database, then you can
- use the <code class="methodname">encodePassword</code> method on the
- <code class="interfacename">PasswordEncoder</code>.</p></div></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e2691" href="#d0e2691" class="para">6</a>] </sup>You can configure
- the encoder to use Base 64 instead of hex by setting the
- <code class="literal">encodeHashAsBase64</code> property to
- <code class="literal">true</code>. Check the Javadoc for
- <code class="classname">MessageDigestPasswordEncoder</code> and its parent
- classes for more information.</p></div></div></div></div><div class="part" title="Part III. Web Application Security"><div class="titlepage"><div><div><h1 class="title"><a name="web-app-security"></a>Part III. Web Application Security</h1></div></div></div><div class="partintro" title="Web Application Security"><div></div><p> Most Spring Security users will be using the framework in applications which make user
- of HTTP and the Servlet API. In this part, we'll take a look at how Spring Security provides
- authentication and access-control features for the web layer of an application. We'll look
- behind the facade of the namespace and see which classes and interfaces are actually
- assembled to provide web-layer security. In some situations it is necessary to use
- traditional bean configuration to provide full control over the configuration, so we'll also
- see how to configure these classes directly without the namespace.</p></div><div class="chapter" title="7. The Security Filter Chain"><div class="titlepage"><div><div><h1 class="title"><a name="security-filter-chain"></a>The Security Filter Chain</h1></div></div></div><p>Spring Security's web infrastructure is based entirely on standard servlet filters. It
- doesn't use servlets or any other servlet-based frameworks (such as Spring MVC) internally, so
- it has no strong links to any particular web technology. It deals in
- <code class="classname">HttpServletRequest</code>s and <code class="classname">HttpServletResponse</code>s and
- doesn't care whether the requests come from a browser, a web service client, an
- <code class="classname">HttpInvoker</code> or an AJAX application. </p><p> Spring Security maintains a filter chain internally where each of the filters has a
- particular responsibility and filters are added or removed from the configuration depending on
- which services are required. The ordering of the filters is important as there are dependencies
- between them. If you have been using <a class="link" href="#ns-config" title="2. Security Namespace Configuration">namespace
- configuration</a>, then the filters are automatically configured for you and you don't have
- to define any Spring beans explicitly but here may be times when you want full control over the
- security filter chain, either because you are using features which aren't supported in the
- namespace, or you are using your own customized versions of classes.</p><div class="section" title="7.1 DelegatingFilterProxy"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="delegating-filter-proxy"></a>7.1 <code class="classname">DelegatingFilterProxy</code></h2></div></div></div><p> When using servlet filters, you obviously need to declare them in your
- <code class="filename">web.xml</code>, or they will be ignored by the servlet container. In Spring
- Security, the filter classes are also Spring beans defined in the application context and thus
- able to take advantage of Spring's rich dependency-injection facilities and lifecycle
- interfaces. Spring's <code class="classname">DelegatingFilterProxy</code> provides the link between
- <code class="filename">web.xml</code> and the application context. </p><p>When using <code class="classname">DelegatingFilterProxy</code>, you will see something like this
- in the <code class="filename">web.xml</code> file: </p><pre class="programlisting">
- <filter>
- <filter-name>myFilter</filter-name>
- <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
- </filter>
+ <code class="classname">Md5PasswordEncoder</code>, there are still things that can go wrong.
+ The database may have the passwords encoded in Base 64, for example while the
+ encoder is using hexadecimal strings (the default). Alternatively your database may
+ be using upper-case while the output from the encoder is lower-case. Make sure you
+ write a test to check the output from your configured password encoder with a known
+ password and salt combination and check that it matches the database value before
+ going further and attempting to authenticate through your application.</p><p>If you want to generate encoded passwords directly in Java for storage in your
+ user database, then you can use the <code class="methodname">encode</code> method on the
+ <code class="interfacename">PasswordEncoder</code>.</p></div></div></div></div><div class="part" title="Part III. Web Application Security"><div class="titlepage"><div><div><h1 class="title"><a name="web-app-security"></a>Part III. Web Application Security</h1></div></div></div><div class="partintro" title="Web Application Security"><div></div><p> Most Spring Security users will be using the framework in applications which make
+ user of HTTP and the Servlet API. In this part, we'll take a look at how Spring
+ Security provides authentication and access-control features for the web layer of an
+ application. We'll look behind the facade of the namespace and see which classes and
+ interfaces are actually assembled to provide web-layer security. In some situations
+ it is necessary to use traditional bean configuration to provide full control over
+ the configuration, so we'll also see how to configure these classes directly without
+ the namespace.</p></div><div class="chapter" title="8. The Security Filter Chain"><div class="titlepage"><div><div><h1 class="title"><a name="security-filter-chain"></a>The Security Filter Chain</h1></div></div></div><p>Spring Security's web infrastructure is based entirely on standard servlet filters. It
+ doesn't use servlets or any other servlet-based frameworks (such as Spring MVC) internally,
+ so it has no strong links to any particular web technology. It deals in
+ <code class="classname">HttpServletRequest</code>s and <code class="classname">HttpServletResponse</code>s
+ and doesn't care whether the requests come from a browser, a web service client, an
+ <code class="classname">HttpInvoker</code> or an AJAX application. </p><p> Spring Security maintains a filter chain internally where each of the filters has a
+ particular responsibility and filters are added or removed from the configuration depending
+ on which services are required. The ordering of the filters is important as there are
+ dependencies between them. If you have been using <a class="link" href="#ns-config" title="3. Security Namespace Configuration">namespace
+ configuration</a>, then the filters are automatically configured for you and you don't
+ have to define any Spring beans explicitly but here may be times when you want full control
+ over the security filter chain, either because you are using features which aren't supported
+ in the namespace, or you are using your own customized versions of classes.</p><div class="section" title="8.1 DelegatingFilterProxy"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="delegating-filter-proxy"></a>8.1 <code class="classname">DelegatingFilterProxy</code></h2></div></div></div><p> When using servlet filters, you obviously need to declare them in your
+ <code class="filename">web.xml</code>, or they will be ignored by the servlet container. In
+ Spring Security, the filter classes are also Spring beans defined in the application
+ context and thus able to take advantage of Spring's rich dependency-injection facilities
+ and lifecycle interfaces. Spring's <code class="classname">DelegatingFilterProxy</code> provides
+ the link between <code class="filename">web.xml</code> and the application context. </p><p>When using <code class="classname">DelegatingFilterProxy</code>, you will see something like
+ this in the <code class="filename">web.xml</code> file: </p><pre class="programlisting">
+ <span class="hl-tag"><filter></span>
+ <span class="hl-tag"><filter-name></span>myFilter<span class="hl-tag"></filter-name></span>
+ <span class="hl-tag"><filter-class></span>org.springframework.web.filter.DelegatingFilterProxy<span class="hl-tag"></filter-class></span>
+ <span class="hl-tag"></filter></span>
- <filter-mapping>
- <filter-name>myFilter</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
+ <span class="hl-tag"><filter-mapping></span>
+ <span class="hl-tag"><filter-name></span>myFilter<span class="hl-tag"></filter-name></span>
+ <span class="hl-tag"><url-pattern></span>/*<span class="hl-tag"></url-pattern></span>
+ <span class="hl-tag"></filter-mapping></span>
</pre><p> Notice that the filter is actually a
- <code class="literal">DelegatingFilterProxy</code>, and not the class that will actually implement the
- logic of the filter. What <code class="classname">DelegatingFilterProxy</code> does is delegate the
- <code class="interfacename">Filter</code>'s methods through to a bean which is obtained from the
- Spring application context. This enables the bean to benefit from the Spring web application
- context lifecycle support and configuration flexibility. The bean must implement
- <code class="interfacename">javax.servlet.Filter</code> and it must have the same name as that
- in the <code class="literal">filter-name</code> element. Read the Javadoc for
- <code class="classname">DelegatingFilterProxy</code> for more information</p></div><div class="section" title="7.2 FilterChainProxy"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="filter-chain-proxy"></a>7.2 <code class="classname">FilterChainProxy</code></h2></div></div></div><p> It should now be clear that you can declare each Spring Security filter bean that you
- require in your application context file and add a corresponding
- <code class="classname">DelegatingFilterProxy</code> entry to <code class="filename">web.xml</code> for each
- filter, making sure that they are ordered correctly. This is a cumbersome approach and
- clutters up the <code class="filename">web.xml</code> file quickly if we have a lot of filters. We
- would prefer to just add a single entry to <code class="filename">web.xml</code> and deal entirely with
- the application context file for managing our web security beans. This is where Spring
- Secuiryt's <code class="classname">FilterChainProxy</code> comes in. It is wired using a
- <code class="literal">DelegatingFilterProxy</code>, just like in the example above, but with the
- <code class="literal">filter-name</code> set to the bean name <span class="quote">“<span class="quote">filterChainProxy</span>”</span>. The
- filter chain is then declared in the application context with the same bean name. Here's an
- example: </p><pre class="programlisting">
+ <code class="literal">DelegatingFilterProxy</code>, and not the class that will actually implement
+ the logic of the filter. What <code class="classname">DelegatingFilterProxy</code> does is
+ delegate the <code class="interfacename">Filter</code>'s methods through to a bean which is
+ obtained from the Spring application context. This enables the bean to benefit from the
+ Spring web application context lifecycle support and configuration flexibility. The bean
+ must implement <code class="interfacename">javax.servlet.Filter</code> and it must have the
+ same name as that in the <code class="literal">filter-name</code> element. Read the Javadoc for
+ <code class="classname">DelegatingFilterProxy</code> for more information</p></div><div class="section" title="8.2 FilterChainProxy"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="filter-chain-proxy"></a>8.2 <code class="classname">FilterChainProxy</code></h2></div></div></div><p>Spring Security's web infrastructure should only be used by delegating to an
+ instance of <code class="classname">FilterChainProxy</code>. The security filters should not
+ be used by themselves. In theory you could declare each Spring Security filter bean
+ that you require in your application context file and add a corresponding
+ <code class="classname">DelegatingFilterProxy</code> entry to <code class="filename">web.xml</code>
+ for each filter, making sure that they are ordered correctly, but this would be
+ cumbersome and would clutter up the <code class="filename">web.xml</code> file quickly if you
+ have a lot of filters. <code class="classname">FilterChainProxy</code> lets us add a single
+ entry to <code class="filename">web.xml</code> and deal entirely with the application context
+ file for managing our web security beans. It is wired using a
+ <code class="literal">DelegatingFilterProxy</code>, just like in the example above, but with
+ the <code class="literal">filter-name</code> set to the bean name
+ <span class="quote">“<span class="quote">filterChainProxy</span>”</span>. The filter chain is then declared in the application
+ context with the same bean name. Here's an example: </p><pre class="programlisting">
<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"filterChainProxy"</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.FilterChainProxy"</span><span class="hl-tag">></span>
- <span class="hl-tag"><sec:filter-chain-map</span> <span class="hl-attribute">path-type</span>=<span class="hl-value">"ant"</span><span class="hl-tag">></span>
- <span class="hl-tag"><sec:filter-chain</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/webServices/**"</span> <span class="hl-attribute">filters</span>=<span class="hl-value">"
+ <span class="hl-tag"><constructor-arg></span>
+ <span class="hl-tag"><list></span>
+ <span class="hl-tag"><sec:filter-chain</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/restful/**"</span> <span class="hl-attribute">filters</span>=<span class="hl-value">"
securityContextPersistenceFilterWithASCFalse,
basicAuthenticationFilter,
exceptionTranslationFilter,
filterSecurityInterceptor"</span><span class="hl-tag"> /></span>
- <span class="hl-tag"><sec:filter-chain</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/**"</span> <span class="hl-attribute">filters</span>=<span class="hl-value">"
+ <span class="hl-tag"><sec:filter-chain</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/**"</span> <span class="hl-attribute">filters</span>=<span class="hl-value">"
securityContextPersistenceFilterWithASCTrue,
formLoginFilter,
exceptionTranslationFilter,
filterSecurityInterceptor"</span><span class="hl-tag"> /></span>
- <span class="hl-tag"></sec:filter-chain-map></span>
+ <span class="hl-tag"></list></span>
+ <span class="hl-tag"></constructor-arg></span>
<span class="hl-tag"></bean></span>
- </pre><p> The namespace element <code class="literal">filter-chain-map</code> is used
- to set up the security filter chain(s) which are required within the
- application<sup>[<a name="d0e2819" href="#ftn.d0e2819" class="footnote">7</a>]</sup>. It maps a
- particular URL pattern to a chain of filters built up from the bean names specified in the
- <code class="literal">filters</code> element. Both regular expressions and Ant Paths are supported,
- and the most specific URIs appear first. At runtime the
- <code class="classname">FilterChainProxy</code> will locate the first URI pattern that matches the
- current web request and the list of filter beans specified by the <code class="literal">filters</code>
- attribute will be applied to that request. The filters will be invoked in the order they are
- defined, so you have complete control over the filter chain which is applied to a particular
- URL.</p><p>You may have noticed we have declared two
- <code class="classname">SecurityContextPersistenceFilter</code>s in the filter chain
- (<code class="literal">ASC</code> is short for <code class="literal">allowSessionCreation</code>, a property of
- <code class="classname">SecurityContextPersistenceFilter</code>). As web services will never present
- a <code class="literal">jsessionid</code> on future requests, creating <code class="literal">HttpSession</code>s
- for such user agents would be wasteful. If you had a high-volume application which required
- maximum scalability, we recommend you use the approach shown above. For smaller applications,
- using a single <code class="classname">SecurityContextPersistenceFilter</code> (with its default
- <code class="literal">allowSessionCreation</code> as <code class="literal">true</code>) would likely be
- sufficient.</p><p>In relation to lifecycle issues, the <code class="classname">FilterChainProxy</code> will always
- delegate <code class="methodname">init(FilterConfig)</code> and <code class="methodname">destroy()</code>
- methods through to the underlaying <code class="interfacename">Filter</code>s if such methods are
- called against <code class="classname">FilterChainProxy</code> itself. In this case,
- <code class="classname">FilterChainProxy</code> guarantees to only initialize and destroy each
- <code class="literal">Filter</code> bean once, no matter how many times it is declared in the filter
- chain(s). You control the overall choice as to whether these methods are called or not via the
- <code class="literal">targetFilterLifecycle</code> initialization parameter of
- <code class="literal">DelegatingFilterProxy</code>. By default this property is
- <code class="literal">false</code> and servlet container lifecycle invocations are not delegated
- through <code class="literal">DelegatingFilterProxy</code>.</p><p> When we looked at how to set up web security using <a class="link" href="#ns-web-xml" title="2.2.1 web.xml Configuration">namespace configuration</a>, we used a <code class="literal">DelegatingFilterProxy</code> with the
- name <span class="quote">“<span class="quote">springSecurityFilterChain</span>”</span>. You should now be able to see that this is the
- name of the <code class="classname">FilterChainProxy</code> which is created by the namespace. </p><div class="section" title="7.2.1 Bypassing the Filter Chain"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2910"></a>7.2.1 Bypassing the Filter Chain</h3></div></div></div><p> As with the namespace, you can use the attribute <code class="literal">filters = "none"</code> as
- an alternative to supplying a filter bean list. This will omit the request pattern from the
- security filter chain entirely. Note that anything matching this path will then have no
- authentication or authorization services applied and will be freely accessible. If you want
- to make use of the contents of the <code class="classname">SecurityContext</code> contents during a
- request, then it must have passed through the security filter chain. Otherwise the
- <code class="classname">SecurityContextHolder</code> will not have been populated and the contents
- will be null.</p></div></div><div class="section" title="7.3 Filter Ordering"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e2924"></a>7.3 Filter Ordering</h2></div></div></div><p>The order that filters are defined in the chain is very important. Irrespective of which
- filters you are actually using, the order should be as follows:
- </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p><code class="classname">ChannelProcessingFilter</code>, because
- it might need to redirect to a different
- protocol</p></li><li class="listitem"><p><code class="classname">ConcurrentSessionFilter</code>,
- because it doesn't use any <code class="classname">SecurityContextHolder</code> functionality
- but needs to update the <code class="interfacename">SessionRegistry</code> to reflect
- ongoing requests from the
- principal</p></li><li class="listitem"><p><code class="classname">SecurityContextPersistenceFilter</code>,
- so a <code class="interfacename">SecurityContext</code> can be set up in the
- <code class="classname">SecurityContextHolder</code> at the beginning of a web request, and
- any changes to the <code class="interfacename">SecurityContext</code> can be copied to the
- <code class="literal">HttpSession</code> when the web request ends (ready for use with the next
- web request)</p></li><li class="listitem"><p>Authentication processing mechanisms -
- <code class="classname">UsernamePasswordAuthenticationFilter</code>,
- <code class="classname">CasAuthenticationFilter</code>,
- <code class="classname">BasicAuthenticationFilter</code> etc - so that the
- <code class="classname">SecurityContextHolder</code> can be modified to contain a valid
- <code class="interfacename">Authentication</code> request
- token</p></li><li class="listitem"><p>The
- <code class="literal">SecurityContextHolderAwareRequestFilter</code>, if you are using it to
- install a Spring Security aware <code class="literal">HttpServletRequestWrapper</code> into your
- servlet
- container</p></li><li class="listitem"><p><code class="classname">RememberMeAuthenticationFilter</code>,
- so that if no earlier authentication processing mechanism updated the
- <code class="classname">SecurityContextHolder</code>, and the request presents a cookie that
- enables remember-me services to take place, a suitable remembered
- <code class="interfacename">Authentication</code> object will be put
- there</p></li><li class="listitem"><p><code class="classname">AnonymousAuthenticationFilter</code>,
- so that if no earlier authentication processing mechanism updated the
- <code class="classname">SecurityContextHolder</code>, an anonymous
- <code class="interfacename">Authentication</code> object will be put
- there</p></li><li class="listitem"><p><code class="classname">ExceptionTranslationFilter</code>,
- to catch any Spring Security exceptions so that either an HTTP error response can be
- returned or an appropriate <code class="interfacename">AuthenticationEntryPoint</code> can
- be
- launched</p></li><li class="listitem"><p><code class="classname">FilterSecurityInterceptor</code>,
- to protect web URIs and raise exceptions when access is
- denied</p></li></ol></div></div><div class="section" title="7.4 Use with other Filter-Based Frameworks"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e3025"></a>7.4 Use with other Filter-Based Frameworks</h2></div></div></div><p>If you're using some other framework that is also filter-based, then you need to make sure
- that the Spring Security filters come first. This enables the
- <code class="classname">SecurityContextHolder</code> to be populated in time for use by the other
- filters. Examples are the use of SiteMesh to decorate your web pages or a web framework like
- Wicket which uses a filter to handle its requests. </p></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e2819" href="#d0e2819" class="para">7</a>] </sup>Note that you'll need to include the security namespace in your
- application context XML file in order to use this syntax.</p></div></div></div><div class="chapter" title="8. Core Security Filters"><div class="titlepage"><div><div><h2 class="title"><a name="core-web-filters"></a>8. Core Security Filters</h2></div></div></div><p> There are some key filters which will always be used in a web application which uses
+ </pre><p> The namespace element <code class="literal">filter-chain</code> is used for convenience
+ to set up the security filter chain(s) which are required within the application.
+ <sup>[<a name="d0e3180" href="#ftn.d0e3180" class="footnote">10</a>]</sup>. It maps a particular URL pattern to a list of filters built up from the
+ bean names specified in the <code class="literal">filters</code> element, and combines them in
+ a bean of type <code class="classname">SecurityFilterChain</code>. The <code class="literal">pattern</code>
+ attribute takes an Ant Paths and the most specific URIs should appear first
+ <sup>[<a name="d0e3196" href="#ftn.d0e3196" class="footnote">11</a>]</sup>. At runtime the <code class="classname">FilterChainProxy</code> will
+ locate the first URI pattern that matches the current web request and the list of filter beans
+ specified by the <code class="literal">filters</code> attribute will be applied to that request.
+ The filters will be invoked in the order they are defined, so you have complete control
+ over the filter chain which is applied to a particular URL.</p><p>You may have noticed we have declared two
+ <code class="classname">SecurityContextPersistenceFilter</code>s in the filter chain
+ (<code class="literal">ASC</code> is short for <code class="literal">allowSessionCreation</code>, a property
+ of <code class="classname">SecurityContextPersistenceFilter</code>). As web services will never
+ present a <code class="literal">jsessionid</code> on future requests, creating
+ <code class="literal">HttpSession</code>s for such user agents would be wasteful. If you had a
+ high-volume application which required maximum scalability, we recommend you use the
+ approach shown above. For smaller applications, using a single
+ <code class="classname">SecurityContextPersistenceFilter</code> (with its default
+ <code class="literal">allowSessionCreation</code> as <code class="literal">true</code>) would likely be
+ sufficient.</p><p>Note that <code class="classname">FilterChainProxy</code> does not invoke standard filter
+ lifecycle methods on the filters it is configured with. We recommend you use
+ Spring's application context lifecycle interfaces as an alternative, just as you
+ would for any other Spring bean.</p><p> When we looked at how to set up web security using <a class="link" href="#ns-web-xml" title="3.2.1 web.xml Configuration">namespace configuration</a>, we used a <code class="literal">DelegatingFilterProxy</code> with
+ the name <span class="quote">“<span class="quote">springSecurityFilterChain</span>”</span>. You should now be able to see that
+ this is the name of the <code class="classname">FilterChainProxy</code> which is created by the
+ namespace. </p><div class="section" title="8.2.1 Bypassing the Filter Chain"><div class="titlepage"><div><div><h3 class="title"><a name="d0e3260"></a>8.2.1 Bypassing the Filter Chain</h3></div></div></div><p> You can use the attribute <code class="literal">filters =
+ "none"</code> as an alternative to supplying a filter bean list. This will omit
+ the request pattern from the security filter chain entirely. Note that anything
+ matching this path will then have no authentication or authorization services
+ applied and will be freely accessible. If you want to make use of the contents of
+ the <code class="classname">SecurityContext</code> contents during a request, then it must
+ have passed through the security filter chain. Otherwise the
+ <code class="classname">SecurityContextHolder</code> will not have been populated and the
+ contents will be null.</p></div></div><div class="section" title="8.3 Filter Ordering"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e3274"></a>8.3 Filter Ordering</h2></div></div></div><p>The order that filters are defined in the chain is very important. Irrespective of
+ which filters you are actually using, the order should be as follows: </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p><code class="classname">ChannelProcessingFilter</code>, because it might need to
+ redirect to a different protocol</p></li><li class="listitem"><p><code class="classname">ConcurrentSessionFilter</code>, because it doesn't use any
+ <code class="classname">SecurityContextHolder</code> functionality but needs to update
+ the <code class="interfacename">SessionRegistry</code> to reflect ongoing requests
+ from the principal</p></li><li class="listitem"><p><code class="classname">SecurityContextPersistenceFilter</code>, so a
+ <code class="interfacename">SecurityContext</code> can be set up in the
+ <code class="classname">SecurityContextHolder</code> at the beginning of a web request,
+ and any changes to the <code class="interfacename">SecurityContext</code> can be
+ copied to the <code class="literal">HttpSession</code> when the web request ends (ready
+ for use with the next web request)</p></li><li class="listitem"><p>Authentication processing mechanisms -
+ <code class="classname">UsernamePasswordAuthenticationFilter</code>,
+ <code class="classname">CasAuthenticationFilter</code>,
+ <code class="classname">BasicAuthenticationFilter</code> etc - so that the
+ <code class="classname">SecurityContextHolder</code> can be modified to contain a valid
+ <code class="interfacename">Authentication</code> request token</p></li><li class="listitem"><p>The <code class="literal">SecurityContextHolderAwareRequestFilter</code>, if you are
+ using it to install a Spring Security aware
+ <code class="literal">HttpServletRequestWrapper</code> into your servlet container</p></li><li class="listitem"><p>The <code class="classname">JaasApiIntegrationFilter</code>, if a
+ <code class="classname">JaasAuthenticationToken</code> is in the
+ <code class="classname">SecurityContextHolder</code> this will process the
+ <code class="classname">FilterChain</code> as the <code class="classname">Subject</code> in the
+ <code class="classname">JaasAuthenticationToken</code></p></li><li class="listitem"><p><code class="classname">RememberMeAuthenticationFilter</code>, so that if no earlier
+ authentication processing mechanism updated the
+ <code class="classname">SecurityContextHolder</code>, and the request presents a cookie
+ that enables remember-me services to take place, a suitable remembered
+ <code class="interfacename">Authentication</code> object will be put there</p></li><li class="listitem"><p><code class="classname">AnonymousAuthenticationFilter</code>, so that if no earlier
+ authentication processing mechanism updated the
+ <code class="classname">SecurityContextHolder</code>, an anonymous
+ <code class="interfacename">Authentication</code> object will be put there</p></li><li class="listitem"><p><code class="classname">ExceptionTranslationFilter</code>, to catch any Spring
+ Security exceptions so that either an HTTP error response can be returned or an
+ appropriate <code class="interfacename">AuthenticationEntryPoint</code> can be
+ launched</p></li><li class="listitem"><p><code class="classname">FilterSecurityInterceptor</code>, to protect web URIs and
+ raise exceptions when access is denied</p></li></ol></div></div><div class="section" title="8.4 Request Matching and HttpFirewall"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="request-matching"></a>8.4 Request Matching and <code class="interfacename">HttpFirewall</code></h2></div></div></div><p>Spring Security has several areas where patterns you have defined are tested
+ against incoming requests in order to decide how the request should be handled. This
+ occurs when the <code class="classname">FilterChainProxy</code> decides which filter chain a
+ request should be passed through and also when the
+ <code class="classname">FilterSecurityInterceptor</code> decides which security constraints
+ apply to a request. It's important to understand what the mechanism is and what URL
+ value is used when testing against the patterns that you define.</p><p>The Servlet Specification defines several properties for the
+ <code class="interfacename">HttpServletRequest</code> which are accessible via getter
+ methods, and which we might want to match against. These are the
+ <code class="literal">contextPath</code>, <code class="literal">servletPath</code>,
+ <code class="literal">pathInfo</code> and <code class="literal">queryString</code>. Spring Security is
+ only interested in securing paths within the application, so the
+ <code class="literal">contextPath</code> is ignored. Unfortunately, the servlet spec does not
+ define exactly what the values of <code class="literal">servletPath</code> and
+ <code class="literal">pathInfo</code> will contain for a particular request URI. For example,
+ each path segment of a URL may contain parameters, as defined in <a class="link" href="http://www.ietf.org/rfc/rfc2396.txt" target="_top">RFC 2396</a><sup>[<a name="d0e3436" href="#ftn.d0e3436" class="footnote">12</a>]</sup>. The Specification does not clearly state whether these should be
+ included in the <code class="literal">servletPath</code> and <code class="literal">pathInfo</code>
+ values and the behaviour varies between different servlet containers. There is a
+ danger that when an application is deployed in a container which does not strip path
+ parameters from these values, an attacker could add them to the requested URL in
+ order to cause a pattern match to succeed or fail unexpectedly.<sup>[<a name="d0e3449" href="#ftn.d0e3449" class="footnote">13</a>]</sup>. Other variations in the incoming URL are also possible. For example, it
+ could contain path-traversal sequences (like <code class="literal">/../</code>) or multiple
+ forward slashes (<code class="literal">//</code>) which could also cause pattern-matches to
+ fail. Some containers normalize these out before performing the servlet mapping, but
+ others don't. To protect against issues like these,
+ <code class="classname">FilterChainProxy</code> uses an
+ <code class="interfacename">HttpFirewall</code> strategy to check and wrap the request.
+ Un-normalized requests are automatically rejected by default, and path parameters
+ and duplicate slashes are removed for matching purposes.<sup>[<a name="d0e3468" href="#ftn.d0e3468" class="footnote">14</a>]</sup>. It is therefore essential that a
+ <code class="classname">FilterChainProxy</code> is used to manage the security filter chain.
+ Note that the <code class="literal">servletPath</code> and <code class="literal">pathInfo</code> values
+ are decoded by the container, so your application should not have any valid paths
+ which contain semi-colons, as these parts will be removed for matching purposes. </p><p>As mentioned above, the default strategy is to use Ant-style paths for matching
+ and this is likely to be the best choice for most users. The strategy is implemented
+ in the class <code class="classname">AntPathRequestMatcher</code> which uses Spring's
+ <code class="classname">AntPathMatcher</code> to perform a case-insensitive match of the
+ pattern against the concatenated <code class="literal">servletPath</code> and
+ <code class="literal">pathInfo</code>, ignoring the <code class="literal">queryString</code>.</p><p>If for some reason, you need a more powerful matching strategy, you can use
+ regular expressions. The strategy implementation is then
+ <code class="classname">RegexRequestMatcher</code>. See the Javadoc for this class for more
+ information.</p><p>In practice we recommend that you use method security at your service layer, to
+ control access to your application, and do not rely entirely on the use of security
+ constraints defined at the web-application level. URLs change and it is difficult to
+ take account of all the possible URLs that an application might support and how
+ requests might be manipulated. You should try and restrict yourself to using a few
+ simple ant paths which are simple to understand. Always try to use a
+ <span class="quote">“<span class="quote">deny-by-default</span>”</span> approach where you have a catch-all wildcard
+ (<code class="literal">/**</code> or <code class="literal">**</code>) defined last and denying access.</p><p>Security defined at the service layer is much more robust and harder to bypass, so
+ you should always take advantage of Spring Security's method security
+ options.</p></div><div class="section" title="8.5 Use with other Filter-Based Frameworks"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e3522"></a>8.5 Use with other Filter-Based Frameworks</h2></div></div></div><p>If you're using some other framework that is also filter-based, then you need to make
+ sure that the Spring Security filters come first. This enables the
+ <code class="classname">SecurityContextHolder</code> to be populated in time for use by the
+ other filters. Examples are the use of SiteMesh to decorate your web pages or a web
+ framework like Wicket which uses a filter to handle its requests. </p></div><div class="section" title="8.6 Advanced Namespace Configuration"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="filter-chains-with-ns"></a>8.6 Advanced Namespace Configuration</h2></div></div></div><p>As we saw earlier in the namespace chapter, it's possible to use multiple <code class="literal">http</code>
+ elements to define different security configurations for different URL patterns.
+ Each element creates a filter chain within the internal <code class="classname">FilterChainProxy</code> and the
+ URL pattern that should be mapped to it. The elements will be added in the order they are declared, so the
+ most specific patterns must again be declared first. Here's another example, for a similar situation to
+ that above, where the application supports both a stateless RESTful API and also a normal web application
+ which users log into using a form.
+</p><pre class="programlisting">
+
+ <span class="hl-comment"><!-- Stateless RESTful service using Basic authentication --></span>
+ <span class="hl-tag"><http</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/restful/**"</span> <span class="hl-attribute">create-session</span>=<span class="hl-value">"stateless"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">'/**'</span> <span class="hl-attribute">access</span>=<span class="hl-value">'ROLE_REMOTE'</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"><http-basic /></span>
+ <span class="hl-tag"></http></span>
+
+ <span class="hl-comment"><!-- Empty filter chain for the login page --></span>
+ <span class="hl-tag"><http</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/login.htm*"</span> <span class="hl-attribute">security</span>=<span class="hl-value">"none"</span><span class="hl-tag">/></span>
+
+ <span class="hl-comment"><!-- Additional filter chain for normal users, matching all other requests --></span>
+ <span class="hl-tag"><http></span>
+ <span class="hl-tag"><intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">'/**'</span> <span class="hl-attribute">access</span>=<span class="hl-value">'ROLE_USER'</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"><form-login</span> <span class="hl-attribute">login-page</span>=<span class="hl-value">'/login.htm'</span> <span class="hl-attribute">default-target-url</span>=<span class="hl-value">"/home.htm"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><logout /></span>
+ <span class="hl-tag"></http></span>
+
+</pre><p>
+ </p></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e3180" href="#d0e3180" class="para">10</a>] </sup>Note that you'll need to include the security namespace in your application
+ context XML file in order to use this syntax. The older syntax which used a
+ <code class="literal">filter-chain-map</code> is still supported, but is deprecated in favour of
+ the constructor argument injection.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e3196" href="#d0e3196" class="para">11</a>] </sup>Instead of a path pattern, the <code class="literal">request-matcher-ref</code> attribute
+ can be used to specify a <code class="interfacename">RequestMatcher</code> instance for more powerful
+ matching</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e3436" href="#d0e3436" class="para">12</a>] </sup>You have probably seen this when a browser doesn't support cookies and the
+ <code class="literal">jsessionid</code> parameter is appended to the URL after a
+ semi-colon. However the RFC allows the presence of these parameters in any path
+ segment of the URL</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e3449" href="#d0e3449" class="para">13</a>] </sup>The original values will be returned once the request leaves the
+ <code class="classname">FilterChainProxy</code>, so will still be available to the
+ application.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e3468" href="#d0e3468" class="para">14</a>] </sup>So, for example, an original request path
+ <code class="literal">/secure;hack=1/somefile.html;hack=2</code> will be returned as
+ <code class="literal">/secure/somefile.html</code>.</p></div></div></div><div class="chapter" title="9. Core Security Filters"><div class="titlepage"><div><div><h2 class="title"><a name="core-web-filters"></a>9. Core Security Filters</h2></div></div></div><p> There are some key filters which will always be used in a web application which uses
Spring Security, so we'll look at these and their supporting classes and interfaces first.
We won't cover every feature, so be sure to look at the Javadoc for them if you want to get
- the complete picture.</p><div class="section" title="8.1 FilterSecurityInterceptor"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="filter-security-interceptor"></a>8.1 <code class="classname">FilterSecurityInterceptor</code></h2></div></div></div><p>We've already seen <code class="classname">FilterSecurityInterceptor</code> briefly when
- discussing <a class="link" href="#tech-intro-access-control" title="5.5 Access-Control (Authorization) in Spring Security">access-control in
- general</a>, and we've already used it with the namespace where the
- <code class="literal"><intercept-url></code> elements are combined to configure it
- internally. Now we'll see how to explicitly configure it for use with a
- <code class="classname">FilterChainProxy</code>, along with its companion filter
- <code class="classname">ExceptionTranslationFilter</code>. A typical configuration example
- is shown below: </p><pre class="programlisting">
+ the complete picture.</p><div class="section" title="9.1 FilterSecurityInterceptor"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="filter-security-interceptor"></a>9.1 <code class="classname">FilterSecurityInterceptor</code></h2></div></div></div><p>We've already seen <code class="classname">FilterSecurityInterceptor</code> briefly when
+ discussing <a class="link" href="#tech-intro-access-control" title="6.5 Access-Control (Authorization) in Spring Security">access-control in
+ general</a>, and we've already used it with the namespace where the
+ <code class="literal"><intercept-url></code> elements are combined to configure it internally.
+ Now we'll see how to explicitly configure it for use with a
+ <code class="classname">FilterChainProxy</code>, along with its companion filter
+ <code class="classname">ExceptionTranslationFilter</code>. A typical configuration example is
+ shown below: </p><pre class="programlisting">
<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"filterSecurityInterceptor"</span>
- <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.access.intercept.FilterSecurityInterceptor"</span><span class="hl-tag">></span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.access.intercept.FilterSecurityInterceptor"</span><span class="hl-tag">></span>
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"authenticationManager"</span><span class="hl-tag">/></span>
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"accessDecisionManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"accessDecisionManager"</span><span class="hl-tag">/></span>
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"securityMetadataSource"</span><span class="hl-tag">></span>
@@ -1751,44 +1952,42 @@ Successfully authenticated. Security context contains: \
<span class="hl-tag"></property></span>
<span class="hl-tag"></bean></span></pre><p><code class="classname">FilterSecurityInterceptor</code> is responsible for handling the
security of HTTP resources. It requires a reference to an
- <code class="interfacename">AuthenticationManager</code> and an
- <code class="interfacename">AccessDecisionManager</code>. It is also supplied with
- configuration attributes that apply to different HTTP URL requests. Refer back to <a class="link" href="#tech-intro-config-attributes" title="What are Configuration Attributes?">the original discussion on these</a>
- in the technical introduction.</p><p>The <code class="classname">FilterSecurityInterceptor</code> can be configured with
+ <code class="interfacename">AuthenticationManager</code> and an
+ <code class="interfacename">AccessDecisionManager</code>. It is also supplied with
+ configuration attributes that apply to different HTTP URL requests. Refer back to <a class="link" href="#tech-intro-config-attributes" title="What are Configuration Attributes?">the original discussion on these</a> in
+ the technical introduction.</p><p>The <code class="classname">FilterSecurityInterceptor</code> can be configured with
configuration attributes in two ways. The first, which is shown above, is using the
- <code class="literal"><filter-security-metadata-source></code> namespace element. This
- is similar to the <code class="literal"><filter-chain-map></code> used to configure a
- <code class="classname">FilterChainProxy</code> but the
- <code class="literal"><intercept-url></code> child elements only use the
- <code class="literal">pattern</code> and <code class="literal">access</code> attributes. Commas are used
- to delimit the different configuration attributes that apply to each HTTP URL. The
- second option is to write your own
+ <code class="literal"><filter-security-metadata-source></code> namespace element. This is
+ similar to the <code class="literal"><http></code> element from the namespace chapter
+ but the <code class="literal"><intercept-url></code>
+ child elements only use the <code class="literal">pattern</code> and <code class="literal">access</code>
+ attributes. Commas are used to delimit the different configuration attributes that apply
+ to each HTTP URL. The second option is to write your own
<code class="interfacename">SecurityMetadataSource</code>, but this is beyond the scope of
this document. Irrespective of the approach used, the
- <code class="interfacename">SecurityMetadataSource</code> is responsible for returning a
- <code class="literal">List<ConfigAttribute></code> containing all of the configuration
+ <code class="interfacename">SecurityMetadataSource</code> is responsible for returning a
+ <code class="literal">List<ConfigAttribute></code> containing all of the configuration
attributes associated with a single secure HTTP URL.</p><p>It should be noted that the
- <code class="literal">FilterSecurityInterceptor.setSecurityMetadataSource()</code> method
- actually expects an instance of
- <code class="interfacename">FilterSecurityMetadataSource</code>. This is a marker
- interface which subclasses <code class="interfacename">SecurityMetadataSource</code>. It
- simply denotes the <code class="interfacename">SecurityMetadataSource</code> understands
- <code class="classname">FilterInvocation</code>s. In the interests of simplicity we'll
- continue to refer to the
- <code class="interfacename">FilterInvocationSecurityMetadataSource</code> as a
- <code class="interfacename">SecurityMetadataSource</code>, as the distinction is of
- little relevance to most users.</p><p>The <code class="interfacename">SecurityMetadataSource</code> created by the namespace
+ <code class="literal">FilterSecurityInterceptor.setSecurityMetadataSource()</code> method actually
+ expects an instance of <code class="interfacename">FilterSecurityMetadataSource</code>. This
+ is a marker interface which subclasses
+ <code class="interfacename">SecurityMetadataSource</code>. It simply denotes the
+ <code class="interfacename">SecurityMetadataSource</code> understands
+ <code class="classname">FilterInvocation</code>s. In the interests of simplicity we'll continue
+ to refer to the <code class="interfacename">FilterInvocationSecurityMetadataSource</code> as
+ a <code class="interfacename">SecurityMetadataSource</code>, as the distinction is of little
+ relevance to most users.</p><p>The <code class="interfacename">SecurityMetadataSource</code> created by the namespace
syntax obtains the configuration attributes for a particular
- <code class="classname">FilterInvocation</code> by matching the request URL against the
+ <code class="classname">FilterInvocation</code> by matching the request URL against the
configured <code class="literal">pattern</code> attributes. This behaves in the same way as it
does for namespace configuration. The default is to treat all expressions as Apache Ant
paths and regular expressions are also supported for more complex cases. The
- <code class="literal">path-type</code> attribute is used to specify the type of pattern being
+ <code class="literal">path-type</code> attribute is used to specify the type of pattern being
used. It is not possible to mix expression syntaxes within the same definition. As an
example, the previous configuration using regular expressions instead of Ant paths would
be written as follows:</p><pre class="programlisting">
<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"filterInvocationInterceptor"</span>
- <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.access.intercept.FilterSecurityInterceptor"</span><span class="hl-tag">></span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.access.intercept.FilterSecurityInterceptor"</span><span class="hl-tag">></span>
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"authenticationManager"</span><span class="hl-tag">/></span>
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"accessDecisionManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"accessDecisionManager"</span><span class="hl-tag">/></span>
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"runAsManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"runAsManager"</span><span class="hl-tag">/></span>
@@ -1801,40 +2000,39 @@ Successfully authenticated. Security context contains: \
<span class="hl-tag"></bean></span> </pre><p>Patterns are always evaluated in the order they are defined. Thus it is important that
more specific patterns are defined higher in the list than less specific patterns. This
is reflected in our example above, where the more specific
- <code class="literal">/secure/super/</code> pattern appears higher than the less specific
- <code class="literal">/secure/</code> pattern. If they were reversed, the
- <code class="literal">/secure/</code> pattern would always match and the
- <code class="literal">/secure/super/</code> pattern would never be evaluated.</p></div><div class="section" title="8.2 ExceptionTranslationFilter"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="exception-translation-filter"></a>8.2
- <code class="classname">ExceptionTranslationFilter</code></h2></div></div></div><p>The <code class="classname">ExceptionTranslationFilter</code> sits above the
- <code class="classname">FilterSecurityInterceptor</code> in the security filter stack. It
+ <code class="literal">/secure/super/</code> pattern appears higher than the less specific
+ <code class="literal">/secure/</code> pattern. If they were reversed, the
+ <code class="literal">/secure/</code> pattern would always match and the
+ <code class="literal">/secure/super/</code> pattern would never be evaluated.</p></div><div class="section" title="9.2 ExceptionTranslationFilter"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="exception-translation-filter"></a>9.2 <code class="classname">ExceptionTranslationFilter</code></h2></div></div></div><p>The <code class="classname">ExceptionTranslationFilter</code> sits above the
+ <code class="classname">FilterSecurityInterceptor</code> in the security filter stack. It
doesn't do any actual security enforcement itself, but handles exceptions thrown by the
security interceptors and provides suitable and HTTP responses. </p><pre class="programlisting">
<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"exceptionTranslationFilter"</span>
- <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.access.ExceptionTranslationFilter"</span><span class="hl-tag">></span>
- <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationEntryPoint"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"authenticationEntryPoint"</span><span class="hl-tag">/></span>
- <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"accessDeniedHandler"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"accessDeniedHandler"</span><span class="hl-tag">/></span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.access.ExceptionTranslationFilter"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationEntryPoint"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"authenticationEntryPoint"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"accessDeniedHandler"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"accessDeniedHandler"</span><span class="hl-tag">/></span>
<span class="hl-tag"></bean></span>
<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"authenticationEntryPoint"</span>
- <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint"</span><span class="hl-tag">></span>
- <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"loginFormUrl"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"/login.jsp"</span><span class="hl-tag">/></span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"loginFormUrl"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"/login.jsp"</span><span class="hl-tag">/></span>
<span class="hl-tag"></bean></span>
<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"accessDeniedHandler"</span>
<span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.access.AccessDeniedHandlerImpl"</span><span class="hl-tag">></span>
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"errorPage"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"/accessDenied.htm"</span><span class="hl-tag">/></span>
<span class="hl-tag"></bean></span>
-</pre><div class="section" title="8.2.1 AuthenticationEntryPoint"><div class="titlepage"><div><div><h3 class="title"><a name="auth-entry-point"></a>8.2.1 <code class="interfacename">AuthenticationEntryPoint</code></h3></div></div></div><p> The <code class="interfacename">AuthenticationEntryPoint</code> will be called if the
+</pre><div class="section" title="9.2.1 AuthenticationEntryPoint"><div class="titlepage"><div><div><h3 class="title"><a name="auth-entry-point"></a>9.2.1 <code class="interfacename">AuthenticationEntryPoint</code></h3></div></div></div><p> The <code class="interfacename">AuthenticationEntryPoint</code> will be called if the
user requests a secure HTTP resource but they are not authenticated. An appropriate
- <code class="exceptionname">AuthenticationException</code> or
- <code class="exceptionname">AccessDeniedException</code> will be thrown by a
- security interceptor further down the call stack, triggering the
- <code class="methodname">commence</code> method on the entry point. This does the job
- of presenting the appropriate response to the user so that authentication can begin.
+ <code class="exceptionname">AuthenticationException</code> or
+ <code class="exceptionname">AccessDeniedException</code> will be thrown by a security
+ interceptor further down the call stack, triggering the
+ <code class="methodname">commence</code> method on the entry point. This does the job of
+ presenting the appropriate response to the user so that authentication can begin.
The one we've used here is <code class="classname">LoginUrlAuthenticationEntryPoint</code>,
which redirects the request to a different URL (typically a login page). The actual
implementation used will depend on the authentication mechanism you want to be used
- in your application. </p></div><div class="section" title="8.2.2 AccessDeniedHandler"><div class="titlepage"><div><div><h3 class="title"><a name="access-denied-handler"></a>8.2.2 <code class="interfacename">AccessDeniedHandler</code></h3></div></div></div><p>What happens if a user is already authenticated an they try to access a protected
+ in your application. </p></div><div class="section" title="9.2.2 AccessDeniedHandler"><div class="titlepage"><div><div><h3 class="title"><a name="access-denied-handler"></a>9.2.2 <code class="interfacename">AccessDeniedHandler</code></h3></div></div></div><p>What happens if a user is already authenticated and they try to access a protected
resource? In normal usage, this shouldn't happen because the application workflow
should be restricted to operations to which a user has access. For example, an HTML
link to an administration page might be hidden from users who do not have an admin
@@ -1847,22 +2045,39 @@ Successfully authenticated. Security context contains: \
service layer interfaces to really nail down what is permissible.</p><p>If an <code class="exceptionname">AccessDeniedException</code> is thrown and a user
has already been authenticated, then this means that an operation has been attempted
for which they don't have enough permissions. In this case,
- <code class="classname">ExceptionTranslationFilter</code> will invoke a second strategy,
- the <code class="interfacename">AccessDeniedHandler</code>. By default, an
- <code class="classname">AccessDeniedHandlerImpl</code> is used, which just sends a 403
+ <code class="classname">ExceptionTranslationFilter</code> will invoke a second strategy, the
+ <code class="interfacename">AccessDeniedHandler</code>. By default, an
+ <code class="classname">AccessDeniedHandlerImpl</code> is used, which just sends a 403
(Forbidden) response to the client. Alternatively you can configure an instance
explicitly (as in the above example) and set an error page URL which it will
- forwards the request to <sup>[<a name="d0e3217" href="#ftn.d0e3217" class="footnote">8</a>]</sup>. This can be a simple <span class="quote">“<span class="quote">access denied</span>”</span> page, such as a JSP,
+ forwards the request to <sup>[<a name="d0e3725" href="#ftn.d0e3725" class="footnote">15</a>]</sup>. This can be a simple <span class="quote">“<span class="quote">access denied</span>”</span> page, such as a JSP,
or it could be a more complex handler such as an MVC controller. And of course, you
can implement the interface yourself and use your own implementation. </p><p>It's also possible to supply a custom
- <code class="interfacename">AccessDeniedHandler</code> when you're using the
- namespace to configure your application. See <a class="link" href="#nsa-access-denied-handler" title="B.1.2 <access-denied-handler>">the namespace appendix</a> for more
- details.</p></div></div><div class="section" title="8.3 SecurityContextPersistenceFilter"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="security-context-persistence-filter"></a>8.3 <code class="classname">SecurityContextPersistenceFilter</code></h2></div></div></div><p> We covered the purpose of this all-important filter in the <a class="link" href="#tech-intro-sec-context-persistence" title="5.4.4 Storing the SecurityContext between requests">Technical Overview</a> chapter
- so you might want to re-read that section at this point. Let's first take a look at how
- you would configure it for use with a <code class="classname">FilterChainProxy</code>. A basic
+ <code class="interfacename">AccessDeniedHandler</code> when you're using the namespace
+ to configure your application. See <a class="link" href="#nsa-access-denied-handler" title="B.1.3 <access-denied-handler>">the
+ namespace appendix</a> for more details.</p></div><div class="section" title="9.2.3 SavedRequests and the RequestCache Interface"><div class="titlepage"><div><div><h3 class="title"><a name="request-caching"></a>9.2.3 <code class="interfacename">SavedRequest</code>s and the <code class="interfacename">RequestCache</code> Interface</h3></div></div></div><p>Another of <code class="classname">ExceptionTranslationFilter</code>'s responsibilities is
+ to save the current request before invoking the <code class="interfacename">AuthenticationEntryPoint</code>.
+ This allows the request to be restored after the use has authenticated (see previous overview
+ of <a class="link" href="#tech-intro-web-authentication" title="6.4 Authentication in a Web Application">web authentication</a>).
+ A typical example would be where the user logs in with a form, and is then redirected to the
+ original URL by the default <code class="classname">SavedRequestAwareAuthenticationSuccessHandler</code>
+ (see <a class="link" href="#form-login-flow-handling" title="9.4.1 Application Flow on Authentication Success and Failure">below</a>).
+ </p><p>The <code class="interfacename">RequestCache</code> encapsulates the functionality required for storing
+ and retrieving <code class="interfacename">HttpServletRequest</code> instances. By default
+ the <code class="classname">HttpSessionRequestCache</code> is used, which stores the request
+ in the <code class="interfacename">HttpSession</code>. The <code class="classname">RequestCacheFilter</code>
+ has the job of actually restoring the saved request from the cache when the user is redirected to
+ the original URL.
+ </p><p>Under normal circumstances, you shouldn't need to modify any of this functionality, but the
+ saved-request handling is a <span class="quote">“<span class="quote">best-effort</span>”</span> approach and there may be situations which
+ the default configuration isn't able to handle. The use of these interfaces makes it fully pluggable
+ from Spring Security 3.0 onwards.
+ </p></div></div><div class="section" title="9.3 SecurityContextPersistenceFilter"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="security-context-persistence-filter"></a>9.3 <code class="classname">SecurityContextPersistenceFilter</code></h2></div></div></div><p> We covered the purpose of this all-important filter in the <a class="link" href="#tech-intro-sec-context-persistence" title="6.4.4 Storing the SecurityContext between requests">Technical Overview</a> chapter so
+ you might want to re-read that section at this point. Let's first take a look at how you
+ would configure it for use with a <code class="classname">FilterChainProxy</code>. A basic
configuration only requires the bean itself </p><pre class="programlisting">
-<bean id="securityContextPersistenceFilter"
-class="org.springframework.security.web.context.SecurityContextPersistenceFilter"/>
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"securityContextPersistenceFilter"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.context.SecurityContextPersistenceFilter"</span><span class="hl-tag">/></span>
</pre><p> As we saw previously, this filter has two main tasks. It is responsible for
storage of the <code class="classname">SecurityContext</code> contents between HTTP requests and
for clearing the <code class="classname">SecurityContextHolder</code> when a request is
@@ -1870,7 +2085,7 @@ class="org.springframework.security.web.context.SecurityContextPersistenceFilter
stored is essential, as it might otherwise be possible for a thread to be replaced into
the servlet container's thread pool, with the security context for a particular user
still attached. This thread might then be used at a later stage, performing operations
- with the wrong credentials. </p><div class="section" title="8.3.1 SecurityContextRepository"><div class="titlepage"><div><div><h3 class="title"><a name="security-context-repository"></a>8.3.1 <code class="interfacename">SecurityContextRepository</code></h3></div></div></div><p>From Spring Security 3.0, the job of loading and storing the security context is
+ with the wrong credentials. </p><div class="section" title="9.3.1 SecurityContextRepository"><div class="titlepage"><div><div><h3 class="title"><a name="security-context-repository"></a>9.3.1 <code class="interfacename">SecurityContextRepository</code></h3></div></div></div><p>From Spring Security 3.0, the job of loading and storing the security context is
now delegated to a separate strategy interface:
</p><pre class="programlisting">
<span class="hl-keyword">public</span> <span class="hl-keyword">interface</span> SecurityContextRepository {
@@ -1882,104 +2097,104 @@ class="org.springframework.security.web.context.SecurityContextPersistenceFilter
The <code class="classname">HttpRequestResponseHolder</code> is simply a container for the
incoming request and response objects, allowing the implementation to replace these
with wrapper classes. The returned contents will be passed to the filter chain. </p><p> The default implementation is
- <code class="classname">HttpSessionSecurityContextRepository</code>, which stores the
- security context as an <code class="interfacename">HttpSession</code> attribute <sup>[<a name="d0e3276" href="#ftn.d0e3276" class="footnote">9</a>]</sup>. The most important configuration parameter for this implementation is
+ <code class="classname">HttpSessionSecurityContextRepository</code>, which stores the
+ security context as an <code class="interfacename">HttpSession</code> attribute <sup>[<a name="d0e3831" href="#ftn.d0e3831" class="footnote">16</a>]</sup>. The most important configuration parameter for this implementation is
the <code class="literal">allowSessionCreation</code> property, which defaults to
- <code class="literal">true</code>, thus allowing the class to create a session if it needs
- one to store the security context for an authenticated user (it won't create one
- unless authentication has taken place and the contents of the security context have
+ <code class="literal">true</code>, thus allowing the class to create a session if it needs one
+ to store the security context for an authenticated user (it won't create one unless
+ authentication has taken place and the contents of the security context have
changed). If you don't want a session to be created, then you can set this property
to <code class="literal">false</code>: </p><pre class="programlisting">
<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"securityContextPersistenceFilter"</span>
-<span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.context.SecurityContextPersistenceFilter"</span><span class="hl-tag">></span>
-<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">'securityContextRepository'</span><span class="hl-tag">></span>
-<span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">'org.springframework.security.web.context.HttpSessionSecurityContextRepository'</span><span class="hl-tag">></span>
- <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">'allowSessionCreation'</span> <span class="hl-attribute">value</span>=<span class="hl-value">'false'</span><span class="hl-tag"> /></span>
-<span class="hl-tag"></bean></span>
-<span class="hl-tag"></property></span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.context.SecurityContextPersistenceFilter"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">'securityContextRepository'</span><span class="hl-tag">></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">'org.springframework.security.web.context.HttpSessionSecurityContextRepository'</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">'allowSessionCreation'</span> <span class="hl-attribute">value</span>=<span class="hl-value">'false'</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"></bean></span>
+ <span class="hl-tag"></property></span>
<span class="hl-tag"></bean></span>
-</pre><p> Alternatively you could provide a null implementation of the
- <code class="interfacename">SecurityContextRepository</code> interface, which will
- prevent the security context from being stored, even if a session has already been
- created during the request. </p></div></div><div class="section" title="8.4 UsernamePasswordAuthenticationFilter"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="form-login-filter"></a>8.4 <code class="classname">UsernamePasswordAuthenticationFilter</code></h2></div></div></div><p>We've now seen the three main filters which are always present in a Spring Security
+</pre><p> Alternatively you could provide an instance of
+ <code class="classname">NullSecurityContextRepository</code>, a <span class="quote">“<span class="quote"><a class="link" href="http://en.wikipedia.org/wiki/Null_Object_pattern" target="_top">null object</a></span>”</span>
+ implementation, which will prevent the security context from being stored, even if a
+ session has already been created during the request. </p></div></div><div class="section" title="9.4 UsernamePasswordAuthenticationFilter"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="form-login-filter"></a>9.4 <code class="classname">UsernamePasswordAuthenticationFilter</code></h2></div></div></div><p>We've now seen the three main filters which are always present in a Spring Security
web configuration. These are also the three which are automatically created by the
namespace <code class="literal"><http></code> element and cannot be substituted with
alternatives. The only thing that's missing now is an actual authentication mechanism,
something that will allow a user to authenticate. This filter is the most commonly used
- authentication filter and the one that is most often customized <sup>[<a name="d0e3310" href="#ftn.d0e3310" class="footnote">10</a>]</sup>. It also provides the implementation used by the
- <code class="literal"><form-login></code> element from the namespace. There are three
- stages required to configure it. </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>Configure a <code class="classname">LoginUrlAuthenticationEntryPoint</code> with
- the URL of the login page, just as we did above, and set it on the
- <code class="classname">ExceptionTranslationFilter</code>. </p></li><li class="listitem"><p>Implement the login page (using a JSP or MVC controller).</p></li><li class="listitem"><p>Configure an instance of
- <code class="classname">UsernamePasswordAuthenticationFilter</code> in the
- application context</p></li><li class="listitem"><p>Add the filter bean to your filter chain proxy (making sure you pay
- attention to the order). </p></li></ol></div><p> The login form simply contains <code class="literal">j_username</code> and
- <code class="literal">j_password</code> input fields, and posts to the URL that is monitored
- by the filter (by default this is <code class="literal">/j_spring_security_check</code>). The
- basic filter configuration looks something like this: </p><pre class="programlisting">
-<bean id="authenticationFilter" class=
-"org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
- <property name="authenticationManager" ref="authenticationManager"/>
- <property name="filterProcessesUrl" value="/j_spring_security_check"/>
-</bean>
- </pre><div class="section" title="8.4.1 Application Flow on Authentication Success and Failure"><div class="titlepage"><div><div><h3 class="title"><a name="form-login-flow-handling"></a>8.4.1 Application Flow on Authentication Success and Failure</h3></div></div></div><p> The filter calls the configured
- <code class="interfacename">AuthenticationManager</code> to process each
- authentication request. The destination following a successful authentication or an
- authentication failure is controlled by the
- <code class="interfacename">AuthenticationSuccessHandler</code> and
- <code class="interfacename">AuthenticationFailureHandler</code> strategy interfaces,
+ authentication filter and the one that is most often customized <sup>[<a name="d0e3869" href="#ftn.d0e3869" class="footnote">17</a>]</sup>. It also provides the implementation used by the
+ <code class="literal"><form-login></code> element from the namespace. There are three stages
+ required to configure it. </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>Configure a <code class="classname">LoginUrlAuthenticationEntryPoint</code> with the
+ URL of the login page, just as we did above, and set it on the
+ <code class="classname">ExceptionTranslationFilter</code>. </p></li><li class="listitem"><p>Implement the login page (using a JSP or MVC controller).</p></li><li class="listitem"><p>Configure an instance of
+ <code class="classname">UsernamePasswordAuthenticationFilter</code> in the application
+ context</p></li><li class="listitem"><p>Add the filter bean to your filter chain proxy (making sure you pay attention
+ to the order). </p></li></ol></div><p> The login form simply contains <code class="literal">j_username</code> and
+ <code class="literal">j_password</code> input fields, and posts to the URL that is monitored by
+ the filter (by default this is <code class="literal">/j_spring_security_check</code>). The basic
+ filter configuration looks something like this: </p><pre class="programlisting">
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"authenticationFilter"</span> <span class="hl-attribute">class</span>=
+<span class="hl-value">"org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"authenticationManager"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"filterProcessesUrl"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"/j_spring_security_check"</span><span class="hl-tag">/></span>
+<span class="hl-tag"></bean></span>
+ </pre><div class="section" title="9.4.1 Application Flow on Authentication Success and Failure"><div class="titlepage"><div><div><h3 class="title"><a name="form-login-flow-handling"></a>9.4.1 Application Flow on Authentication Success and Failure</h3></div></div></div><p> The filter calls the configured
+ <code class="interfacename">AuthenticationManager</code> to process each authentication
+ request. The destination following a successful authentication or an authentication
+ failure is controlled by the
+ <code class="interfacename">AuthenticationSuccessHandler</code> and
+ <code class="interfacename">AuthenticationFailureHandler</code> strategy interfaces,
respectively. The filter has properties which allow you to set these so you can
- customize the behaviour completely <sup>[<a name="d0e3372" href="#ftn.d0e3372" class="footnote">11</a>]</sup>. Some standard implementations are supplied such as
- <code class="classname">SimpleUrlAuthenticationSuccessHandler</code>,
- <code class="classname">SavedRequestAwareAuthenticationSuccessHandler</code>,
- <code class="classname">SimpleUrlAuthenticationFailureHandler</code> and
- <code class="classname">ExceptionMappingAuthenticationFailureHandler</code>. Have a look
- at the Javadoc for these classes to see how they work. </p><p>If authentication is successful, the resulting
- <code class="interfacename">Authentication</code> object will be placed into the
- <code class="classname">SecurityContextHolder</code>. The configured
- <code class="interfacename">AuthenticationSuccessHandler</code> will then be called
- to either redirect or forward the user to the appropriate destination. By default a
- <code class="classname">SavedRequestAwareAuthenticationSuccessHandler</code> is used,
- which means that the user will be redirected to the original destination they
- requested before they were asked to login. </p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p> The <code class="classname">ExceptionTranslationFilter</code> caches the original
- request a user makes. When the user authenticates, the request handler makes
- use of this cached request to obtain the original URL and redirect to it.
- The original request is then rebuilt and used as an alternative. </p></td></tr></table></div><p> If authentication fails, the configured
- <code class="interfacename">AuthenticationFailureHandler</code> will be invoked.
- </p></div></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e3217" href="#d0e3217" class="para">8</a>] </sup>We use a forward so that the SecurityContextHolder still contains details
- of the principal, which may be useful for displaying to the user. In old
- releases of Spring Security we relied upon the servlet container to handle a
- 403 error message, which lacked this useful contextual information.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e3276" href="#d0e3276" class="para">9</a>] </sup>In Spring Security 2.0 and earlier, this filter was called
- <code class="classname">HttpSessionContextIntegrationFilter</code> and performed
- all the work of storing the context was performed by the filter itself. If
- you were familiar with this class, then most of the configuration options
- which were available can now be found on
- <code class="classname">HttpSessionSecurityContextRepository</code>. </p></div><div class="footnote"><p><sup>[<a name="ftn.d0e3310" href="#d0e3310" class="para">10</a>] </sup>For historical reasons, prior to Spring Security 3.0, this filter was called
- <code class="classname">AuthenticationProcessingFilter</code> and the entry point
- was called <code class="classname">AuthenticationProcessingFilterEntryPoint</code>.
- Since the framework now supports many different forms of authentication, they
- have both been given more specific names in 3.0.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e3372" href="#d0e3372" class="para">11</a>] </sup>In versions prior to 3.0, the application flow at this point had evolved
- to a stage was controlled by a mix of properties on this class and strategy
- plugins. The decision was made for 3.0 to refactor the code to make these
- two strategies entirely responsible. </p></div></div></div><div class="chapter" title="9. Basic and Digest Authentication"><div class="titlepage"><div><div><h1 class="title"><a name="basic"></a>Basic and Digest Authentication</h1></div></div></div><p>Basic and digest authentiation are alternative authentication mechanisms which are popular
+ customize the behaviour completely <sup>[<a name="d0e3931" href="#ftn.d0e3931" class="footnote">18</a>]</sup>. Some standard implementations are supplied such as
+ <code class="classname">SimpleUrlAuthenticationSuccessHandler</code>,
+ <code class="classname">SavedRequestAwareAuthenticationSuccessHandler</code>,
+ <code class="classname">SimpleUrlAuthenticationFailureHandler</code> and
+ <code class="classname">ExceptionMappingAuthenticationFailureHandler</code>. Have a look at
+ the Javadoc for these classes and also for <code class="classname">AbstractAuthenticationProcessingFilter</code>
+ to get an overview of how they work and the supported features.
+ </p><p>If authentication is successful, the resulting
+ <code class="interfacename">Authentication</code> object will be placed into the
+ <code class="classname">SecurityContextHolder</code>. The configured
+ <code class="interfacename">AuthenticationSuccessHandler</code> will then be called to
+ either redirect or forward the user to the appropriate destination. By default a
+ <code class="classname">SavedRequestAwareAuthenticationSuccessHandler</code> is used, which
+ means that the user will be redirected to the original destination they requested
+ before they were asked to login. </p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p> The <code class="classname">ExceptionTranslationFilter</code> caches the original
+ request a user makes. When the user authenticates, the request handler makes use
+ of this cached request to obtain the original URL and redirect to it. The
+ original request is then rebuilt and used as an alternative. </p></td></tr></table></div><p> If authentication fails, the configured
+ <code class="interfacename">AuthenticationFailureHandler</code> will be invoked. </p></div></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e3725" href="#d0e3725" class="para">15</a>] </sup>We use a forward so that the SecurityContextHolder still contains details of
+ the principal, which may be useful for displaying to the user. In old releases
+ of Spring Security we relied upon the servlet container to handle a 403 error
+ message, which lacked this useful contextual information.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e3831" href="#d0e3831" class="para">16</a>] </sup>In Spring Security 2.0 and earlier, this filter was called
+ <code class="classname">HttpSessionContextIntegrationFilter</code> and performed all the
+ work of storing the context was performed by the filter itself. If you were
+ familiar with this class, then most of the configuration options which were
+ available can now be found on
+ <code class="classname">HttpSessionSecurityContextRepository</code>. </p></div><div class="footnote"><p><sup>[<a name="ftn.d0e3869" href="#d0e3869" class="para">17</a>] </sup>For historical reasons, prior to Spring Security 3.0, this filter was called
+ <code class="classname">AuthenticationProcessingFilter</code> and the entry point was called
+ <code class="classname">AuthenticationProcessingFilterEntryPoint</code>. Since the framework
+ now supports many different forms of authentication, they have both been given more
+ specific names in 3.0.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e3931" href="#d0e3931" class="para">18</a>] </sup>In versions prior to 3.0, the application flow at this point had evolved to a
+ stage was controlled by a mix of properties on this class and strategy plugins.
+ The decision was made for 3.0 to refactor the code to make these two strategies
+ entirely responsible. </p></div></div></div><div class="chapter" title="10. Basic and Digest Authentication"><div class="titlepage"><div><div><h1 class="title"><a name="basic"></a>Basic and Digest Authentication</h1></div></div></div><p>Basic and digest authentiation are alternative authentication mechanisms which are popular
in web applications. Basic authentication is often used with stateless clients which pass
their credentials on each request. It's quite common to use it in combination with
form-based authentication where an application is used through both a browser-based user
interface and as a web-service. However, basic authentication transmits the password as
plain text so it should only really be used over an encrypted transport layer such as
- HTTPS.</p><div class="section" title="9.1 BasicAuthenticationFilter"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="basic-processing-filter"></a>9.1 <code class="classname">BasicAuthenticationFilter</code></h2></div></div></div><p><code class="literal">BasicAuthenticationFilter</code> is responsible for processing basic
+ HTTPS.</p><div class="section" title="10.1 BasicAuthenticationFilter"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="basic-processing-filter"></a>10.1 <code class="classname">BasicAuthenticationFilter</code></h2></div></div></div><p><code class="literal">BasicAuthenticationFilter</code> is responsible for processing basic
authentication credentials presented in HTTP headers. This can be used for
authenticating calls made by Spring remoting protocols (such as Hessian and Burlap), as
well as normal browser user agents (such as Firefox and Internet Explorer). The standard
governing HTTP Basic Authentication is defined by RFC 1945, Section 11, and
- <code class="literal">BasicAuthenticationFilter</code> conforms with this RFC. Basic
+ <code class="literal">BasicAuthenticationFilter</code> conforms with this RFC. Basic
Authentication is an attractive approach to authentication, because it is very widely
deployed in user agents and implementation is extremely simple (it's just a Base64
- encoding of the username:password, specified in an HTTP header).</p><div class="section" title="9.1.1 Configuration"><div class="titlepage"><div><div><h3 class="title"><a name="basic-config"></a>9.1.1 Configuration</h3></div></div></div><p>To implement HTTP Basic Authentication, you need to add a
- <code class="literal">BasicAuthenticationFilter</code> to your filter chain. The
- application context should contain <code class="literal">BasicAuthenticationFilter</code> and
- its required collaborator:</p><p>
- </p><pre class="programlisting">
+ encoding of the username:password, specified in an HTTP header).</p><div class="section" title="10.1.1 Configuration"><div class="titlepage"><div><div><h3 class="title"><a name="basic-config"></a>10.1.1 Configuration</h3></div></div></div><p>To implement HTTP Basic Authentication, you need to add a
+ <code class="literal">BasicAuthenticationFilter</code> to your filter chain. The application
+ context should contain <code class="literal">BasicAuthenticationFilter</code> and its required
+ collaborator:</p><p> </p><pre class="programlisting">
<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"basicAuthenticationFilter"</span>
<span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.authentication.www.BasicAuthenticationFilter"</span><span class="hl-tag">></span>
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"authenticationManager"</span><span class="hl-tag">/></span>
@@ -1990,19 +2205,18 @@ class="org.springframework.security.web.context.SecurityContextPersistenceFilter
<span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint"</span><span class="hl-tag">></span>
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"realmName"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"Name Of Your Realm"</span><span class="hl-tag">/></span>
<span class="hl-tag"></bean></span>
- </pre><p>
- </p><p>The configured <code class="interfacename">AuthenticationManager</code> processes each
+ </pre><p> </p><p>The configured <code class="interfacename">AuthenticationManager</code> processes each
authentication request. If authentication fails, the configured
- <code class="interfacename">AuthenticationEntryPoint</code> will be used to retry
- the authentication process. Usually you will use the filter in combination with a
- <code class="literal">BasicAuthenticationEntryPoint</code>, which returns a 401 response
- with a suitable header to retry HTTP Basic authentication. If authentication is
+ <code class="interfacename">AuthenticationEntryPoint</code> will be used to retry the
+ authentication process. Usually you will use the filter in combination with a
+ <code class="literal">BasicAuthenticationEntryPoint</code>, which returns a 401 response with
+ a suitable header to retry HTTP Basic authentication. If authentication is
successful, the resulting <code class="interfacename">Authentication</code> object will
be placed into the <code class="classname">SecurityContextHolder</code> as usual.</p><p>If the authentication event was successful, or authentication was not attempted
because the HTTP header did not contain a supported authentication request, the
filter chain will continue as normal. The only time the filter chain will be
interrupted is if authentication fails and the
- <code class="interfacename">AuthenticationEntryPoint</code> is called.</p></div></div><div class="section" title="9.2 DigestAuthenticationFilter"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="digest-processing-filter"></a>9.2 <code class="classname">DigestAuthenticationFilter</code></h2></div></div></div><p><code class="classname">DigestAuthenticationFilter</code> is capable of processing digest
+ <code class="interfacename">AuthenticationEntryPoint</code> is called.</p></div></div><div class="section" title="10.2 DigestAuthenticationFilter"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="digest-processing-filter"></a>10.2 <code class="classname">DigestAuthenticationFilter</code></h2></div></div></div><p><code class="classname">DigestAuthenticationFilter</code> is capable of processing digest
authentication credentials presented in HTTP headers. Digest Authentication attempts to
solve many of the weaknesses of Basic authentication, specifically by ensuring
credentials are never sent in clear text across the wire. Many user agents support
@@ -2011,7 +2225,7 @@ class="org.springframework.security.web.context.SecurityContextPersistenceFilter
the Digest Authentication standard prescribed by RFC 2069. Most user agents implement
RFC 2617. Spring Security's <code class="classname">DigestAuthenticationFilter</code> is
compatible with the "<code class="literal">auth</code>" quality of protection
- (<code class="literal">qop</code>) prescribed by RFC 2617, which also provides backward
+ (<code class="literal">qop</code>) prescribed by RFC 2617, which also provides backward
compatibility with RFC 2069. Digest Authentication is a more attractive option if you
need to use unencrypted HTTP (i.e. no TLS/HTTPS) and wish to maximise security of the
authentication process. Indeed Digest Authentication is a mandatory requirement for the
@@ -2021,14 +2235,13 @@ class="org.springframework.security.web.context.SecurityContextPersistenceFilter
a "nonce". This is a value the server generates. Spring Security's nonce adopts the
following format:</p><p>
</p><pre class="programlisting">
- base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key))
+ base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key))
- expirationTime: The date and time when the nonce expires, expressed in milliseconds
- key: A private key to prevent modification of the nonce token
- </pre><p>
- </p><p>The <code class="classname">DigestAuthenticatonEntryPoint</code> has a property specifying the
- <code class="literal">key</code> used for generating the nonce tokens, along with a
- <code class="literal">nonceValiditySeconds</code> property for determining the expiration time
+ expirationTime: The date and time when the nonce expires, expressed in milliseconds
+ key: A private key to prevent modification of the nonce token
+ </pre><p> </p><p>The <code class="classname">DigestAuthenticatonEntryPoint</code> has a property specifying the
+ <code class="literal">key</code> used for generating the nonce tokens, along with a
+ <code class="literal">nonceValiditySeconds</code> property for determining the expiration time
(default 300, which equals five minutes). Whist ever the nonce is valid, the digest is
computed by concatenating various strings including the username, password, nonce, URI
being requested, a client-generated nonce (merely a random value which the user agent
@@ -2037,51 +2250,48 @@ class="org.springframework.security.web.context.SecurityContextPersistenceFilter
if they disagree on an included value (eg password). In Spring Security implementation,
if the server-generated nonce has merely expired (but the digest was otherwise valid),
the <code class="classname">DigestAuthenticationEntryPoint</code> will send a
- <code class="literal">"stale=true"</code> header. This tells the user agent there is no need
- to disturb the user (as the password and username etc is correct), but simply to try
- again using a new nonce.</p><p>An appropriate value for <code class="classname">DigestAuthenticationEntryPoint</code>'s
- <code class="literal">nonceValiditySeconds</code> parameter will depend on your application.
+ <code class="literal">"stale=true"</code> header. This tells the user agent there is no need to
+ disturb the user (as the password and username etc is correct), but simply to try again
+ using a new nonce.</p><p>An appropriate value for <code class="classname">DigestAuthenticationEntryPoint</code>'s
+ <code class="literal">nonceValiditySeconds</code> parameter will depend on your application.
Extremely secure applications should note that an intercepted authentication header can
be used to impersonate the principal until the <code class="literal">expirationTime</code>
contained in the nonce is reached. This is the key principle when selecting an
appropriate setting, but it would be unusual for immensely secure applications to not be
running over TLS/HTTPS in the first instance.</p><p>Because of the more complex implementation of Digest Authentication, there are often
user agent issues. For example, Internet Explorer fails to present an
- "<code class="literal">opaque</code>" token on subsequent requests in the same session. Spring
+ "<code class="literal">opaque</code>" token on subsequent requests in the same session. Spring
Security filters therefore encapsulate all state information into the
- "<code class="literal">nonce</code>" token instead. In our testing, Spring Security's
+ "<code class="literal">nonce</code>" token instead. In our testing, Spring Security's
implementation works reliably with FireFox and Internet Explorer, correctly handling
- nonce timeouts etc.</p><div class="section" title="9.2.1 Configuration"><div class="titlepage"><div><div><h3 class="title"><a name="digest-config"></a>9.2.1 Configuration</h3></div></div></div><p>Now that we've reviewed the theory, let's see how to use it. To implement HTTP
+ nonce timeouts etc.</p><div class="section" title="10.2.1 Configuration"><div class="titlepage"><div><div><h3 class="title"><a name="digest-config"></a>10.2.1 Configuration</h3></div></div></div><p>Now that we've reviewed the theory, let's see how to use it. To implement HTTP
Digest Authentication, it is necessary to define
- <code class="literal">DigestAuthenticationFilter</code> in the filter chain. The
- application context will need to define the
- <code class="literal">DigestAuthenticationFilter</code> and its required
- collaborators:</p><p>
- </p><pre class="programlisting">
-<bean id="digestFilter" class=
- "org.springframework.security.web.authentication.www.DigestAuthenticationFilter">
- <property name="userDetailsService" ref="jdbcDaoImpl"/>
- <property name="authenticationEntryPoint" ref="digestEntryPoint"/>
- <property name="userCache" ref="userCache"/>
-</bean>
+ <code class="literal">DigestAuthenticationFilter</code> in the filter chain. The application
+ context will need to define the <code class="literal">DigestAuthenticationFilter</code> and
+ its required collaborators:</p><p> </p><pre class="programlisting">
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"digestFilter"</span> <span class="hl-attribute">class</span>=
+ <span class="hl-value">"org.springframework.security.web.authentication.www.DigestAuthenticationFilter"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"userDetailsService"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"jdbcDaoImpl"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationEntryPoint"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"digestEntryPoint"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"userCache"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"userCache"</span><span class="hl-tag">/></span>
+<span class="hl-tag"></bean></span>
-<bean id="digestEntryPoint" class=
- "org.springframework.security.web.authentication.www.DigestAuthenticationEntryPoint">
- <property name="realmName" value="Contacts Realm via Digest Authentication"/>
- <property name="key" value="acegi"/>
- <property name="nonceValiditySeconds" value="10"/>
-</bean>
- </pre><p>
- </p><p>The configured <code class="interfacename">UserDetailsService</code> is needed because
- <code class="literal">DigestAuthenticationFilter</code> must have direct access to the
- clear text password of a user. Digest Authentication will NOT work if you are using
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"digestEntryPoint"</span> <span class="hl-attribute">class</span>=
+ <span class="hl-value">"org.springframework.security.web.authentication.www.DigestAuthenticationEntryPoint"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"realmName"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"Contacts Realm via Digest Authentication"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"key"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"acegi"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"nonceValiditySeconds"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"10"</span><span class="hl-tag">/></span>
+<span class="hl-tag"></bean></span>
+ </pre><p> </p><p>The configured <code class="interfacename">UserDetailsService</code> is needed because
+ <code class="literal">DigestAuthenticationFilter</code> must have direct access to the clear
+ text password of a user. Digest Authentication will NOT work if you are using
encoded passwords in your DAO. The DAO collaborator, along with the
- <code class="literal">UserCache</code>, are typically shared directly with a
- <code class="classname">DaoAuthenticationProvider</code>. The
- <code class="literal">authenticationEntryPoint</code> property must be
- <code class="classname">DigestAuthenticationEntryPoint</code>, so that
- <code class="classname">DigestAuthenticationFilter</code> can obtain the correct
- <code class="literal">realmName</code> and <code class="literal">key</code> for digest
+ <code class="literal">UserCache</code>, are typically shared directly with a
+ <code class="classname">DaoAuthenticationProvider</code>. The
+ <code class="literal">authenticationEntryPoint</code> property must be
+ <code class="classname">DigestAuthenticationEntryPoint</code>, so that
+ <code class="classname">DigestAuthenticationFilter</code> can obtain the correct
+ <code class="literal">realmName</code> and <code class="literal">key</code> for digest
calculations.</p><p>Like <code class="literal">BasicAuthenticationFilter</code>, if authentication is successful
an <code class="interfacename">Authentication</code> request token will be placed into
the <code class="classname">SecurityContextHolder</code>. If the authentication event was
@@ -2095,19 +2305,18 @@ class="org.springframework.security.web.context.SecurityContextPersistenceFilter
implementation (and the doubtless user agent incompatibilities that would emerge),
and avoid needing to store server-side state. You are invited to review RFC 2617 if
you wish to explore these features in more detail. As far as we are aware, Spring
- Security's implementation does comply with the minimum standards of this RFC.</p></div></div></div><div class="chapter" title="10. Remember-Me Authentication"><div class="titlepage"><div><div><h1 class="title"><a name="remember-me"></a>Remember-Me Authentication</h1></div></div></div><div class="section" title="10.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="remember-me-overview"></a>10.1 Overview</h2></div></div></div><p>Remember-me or persistent-login authentication refers to web sites being able to
+ Security's implementation does comply with the minimum standards of this RFC.</p></div></div></div><div class="chapter" title="11. Remember-Me Authentication"><div class="titlepage"><div><div><h1 class="title"><a name="remember-me"></a>Remember-Me Authentication</h1></div></div></div><div class="section" title="11.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="remember-me-overview"></a>11.1 Overview</h2></div></div></div><p>Remember-me or persistent-login authentication refers to web sites being able to
remember the identity of a principal between sessions. This is typically accomplished by
sending a cookie to the browser, with the cookie being detected during future sessions
and causing automated login to take place. Spring Security provides the necessary hooks
for these operations to take place, and has two concrete remember-me implementations.
One uses hashing to preserve the security of cookie-based tokens and the other uses a
database or other persistent storage mechanism to store the generated tokens. </p><p> Note that both implemementations require a
- <code class="interfacename">UserDetailsService</code>. If you are using an
- authentication provider which doesn't use a
- <code class="interfacename">UserDetailsService</code> (for example, the LDAP provider)
- then it won't work unless you also have a
- <code class="interfacename">UserDetailsService</code> bean in your application context.
- </p></div><div class="section" title="10.2 Simple Hash-Based Token Approach"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="remember-me-hash-token"></a>10.2 Simple Hash-Based Token Approach</h2></div></div></div><p>This approach uses hashing to achieve a useful remember-me strategy. In essence a
+ <code class="interfacename">UserDetailsService</code>. If you are using an authentication
+ provider which doesn't use a <code class="interfacename">UserDetailsService</code> (for
+ example, the LDAP provider) then it won't work unless you also have a
+ <code class="interfacename">UserDetailsService</code> bean in your application context.
+ </p></div><div class="section" title="11.2 Simple Hash-Based Token Approach"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="remember-me-hash-token"></a>11.2 Simple Hash-Based Token Approach</h2></div></div></div><p>This approach uses hashing to achieve a useful remember-me strategy. In essence a
cookie is sent to the browser upon successful interactive authentication, with the
cookie being composed as follows:
</p><pre class="programlisting">
@@ -2126,37 +2335,39 @@ class="org.springframework.security.web.context.SecurityContextPersistenceFilter
authentication. If a principal is aware a token has been captured, they can easily
change their password and immediately invalidate all remember-me tokens on issue. If
more significant security is needed you should use the approach described in the next
- section. Alternatively remember-me services should simply not be used at all.</p><p>If you are familiar with the topics discussed in the chapter on <a class="link" href="#ns-config" title="2. Security Namespace Configuration">namespace configuration</a>, you can enable remember-me
+ section. Alternatively remember-me services should simply not be used at all.</p><p>If you are familiar with the topics discussed in the chapter on <a class="link" href="#ns-config" title="3. Security Namespace Configuration">namespace configuration</a>, you can enable remember-me
authentication just by adding the <code class="literal"><remember-me></code> element: </p><pre class="programlisting">
- <http>
+ <span class="hl-tag"><http></span>
...
- <remember-me key="myAppKey"/>
- </http>
+ <span class="hl-tag"><remember-me</span> <span class="hl-attribute">key</span>=<span class="hl-value">"myAppKey"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></http></span>
</pre><p> The <code class="interfacename">UserDetailsService</code> will
normally be selected automatically. If you have more than one in your application
context, you need to specify which one should be used with the
- <code class="literal">user-service-ref</code> attribute, where the value is the name of your
- <code class="interfacename">UserDetailsService</code> bean. </p></div><div class="section" title="10.3 Persistent Token Approach"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="remember-me-persistent-token"></a>10.3 Persistent Token Approach</h2></div></div></div><p>This approach is based on the article <a class="link" href="http://jaspan.com/improved_persistent_login_cookie_best_practice" target="_top">http://jaspan.com/improved_persistent_login_cookie_best_practice</a> with some
- minor modifications <sup>[<a name="d0e3651" href="#ftn.d0e3651" class="footnote">12</a>]</sup>.
- To use the this approach with namespace configuration, you would supply a datasource
- reference: </p><pre class="programlisting">
- <http>
+ <code class="literal">user-service-ref</code> attribute, where the value is the name of your
+ <code class="interfacename">UserDetailsService</code> bean. </p></div><div class="section" title="11.3 Persistent Token Approach"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="remember-me-persistent-token"></a>11.3 Persistent Token Approach</h2></div></div></div><p>This approach is based on the article <a class="link" href="http://jaspan.com/improved_persistent_login_cookie_best_practice" target="_top">http://jaspan.com/improved_persistent_login_cookie_best_practice</a> with some minor
+ modifications <sup>[<a name="d0e4213" href="#ftn.d0e4213" class="footnote">19</a>]</sup>. To use the this approach with namespace configuration, you would supply a
+ datasource reference: </p><pre class="programlisting">
+ <span class="hl-tag"><http></span>
...
- <remember-me data-source-ref="someDataSource"/>
- </http>
+ <span class="hl-tag"><remember-me</span> <span class="hl-attribute">data-source-ref</span>=<span class="hl-value">"someDataSource"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></http></span>
</pre><p> The database should contain a
- <code class="literal">persistent_logins</code> table, created using the following SQL (or
+ <code class="literal">persistent_logins</code> table, created using the following SQL (or
equivalent):
</p><pre class="programlisting">
- create table persistent_logins (username varchar(64) not null, series varchar(64) primary key, token varchar(64) not null, last_used timestamp not null)
-</pre></div><div class="section" title="10.4 Remember-Me Interfaces and Implementations"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="remember-me-impls"></a>10.4 Remember-Me Interfaces and Implementations</h2></div></div></div><p>Remember-me authentication is not used with basic authentication, given it is often
+ create table persistent_logins (username varchar(64) not null,
+ series varchar(64) primary key,
+ token varchar(64) not null,
+ last_used timestamp not null)
+</pre></div><div class="section" title="11.4 Remember-Me Interfaces and Implementations"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="remember-me-impls"></a>11.4 Remember-Me Interfaces and Implementations</h2></div></div></div><p>Remember-me authentication is not used with basic authentication, given it is often
not used with <code class="literal">HttpSession</code>s. Remember-me is used with
- <code class="literal">UsernamePasswordAuthenticationFilter</code>, and is implemented via
- hooks in the <code class="literal">AbstractAuthenticationProcessingFilter</code> superclass. The
- hooks will invoke a concrete <code class="interfacename">RememberMeServices</code> at the
- appropriate times. The interface looks like this:
+ <code class="literal">UsernamePasswordAuthenticationFilter</code>, and is implemented via hooks in
+ the <code class="literal">AbstractAuthenticationProcessingFilter</code> superclass. The hooks will
+ invoke a concrete <code class="interfacename">RememberMeServices</code> at the appropriate
+ times. The interface looks like this:
</p><pre class="programlisting">
Authentication autoLogin(HttpServletRequest request, HttpServletResponse response);
<span class="hl-keyword">void</span> loginFail(HttpServletRequest request, HttpServletResponse response);
@@ -2167,25 +2378,25 @@ class="org.springframework.security.web.context.SecurityContextPersistenceFilter
note at this stage that <code class="literal">AbstractAuthenticationProcessingFilter</code> only
calls the <code class="literal">loginFail()</code> and <code class="literal">loginSuccess()</code> methods.
The <code class="literal">autoLogin()</code> method is called by
- <code class="classname">RememberMeAuthenticationFilter</code> whenever the
- <code class="classname">SecurityContextHolder</code> does not contain an
- <code class="interfacename">Authentication</code>. This interface therefore provides the
+ <code class="classname">RememberMeAuthenticationFilter</code> whenever the
+ <code class="classname">SecurityContextHolder</code> does not contain an
+ <code class="interfacename">Authentication</code>. This interface therefore provides the
underlying remember-me implementation with sufficient notification of
authentication-related events, and delegates to the implementation whenever a candidate
web request might contain a cookie and wish to be remembered. This design allows any
number of remember-me implementation strategies. We've seen above that Spring Security
- provides two implementations. We'll look at these in turn.</p><div class="section" title="10.4.1 TokenBasedRememberMeServices"><div class="titlepage"><div><div><h3 class="title"><a name="d0e3706"></a>10.4.1 TokenBasedRememberMeServices</h3></div></div></div><p> This implementation supports the simpler approach described in <a class="xref" href="#remember-me-hash-token" title="10.2 Simple Hash-Based Token Approach">Section 10.2, “Simple Hash-Based Token Approach”</a>.
- <code class="classname">TokenBasedRememberMeServices</code> generates a
- <code class="literal">RememberMeAuthenticationToken</code>, which is processed by
- <code class="literal">RememberMeAuthenticationProvider</code>. A <code class="literal">key</code> is
+ provides two implementations. We'll look at these in turn.</p><div class="section" title="11.4.1 TokenBasedRememberMeServices"><div class="titlepage"><div><div><h3 class="title"><a name="d0e4268"></a>11.4.1 TokenBasedRememberMeServices</h3></div></div></div><p> This implementation supports the simpler approach described in <a class="xref" href="#remember-me-hash-token" title="11.2 Simple Hash-Based Token Approach">Section 11.2, “Simple Hash-Based Token Approach”</a>.
+ <code class="classname">TokenBasedRememberMeServices</code> generates a
+ <code class="literal">RememberMeAuthenticationToken</code>, which is processed by
+ <code class="literal">RememberMeAuthenticationProvider</code>. A <code class="literal">key</code> is
shared between this authentication provider and the
- <code class="literal">TokenBasedRememberMeServices</code>. In addition,
- <code class="literal">TokenBasedRememberMeServices</code> requires A UserDetailsService
- from which it can retrieve the username and password for signature comparison
- purposes, and generate the <code class="literal">RememberMeAuthenticationToken</code> to
- contain the correct <code class="interfacename">GrantedAuthority</code>[]s. Some sort of
- logout command should be provided by the application that invalidates the cookie if
- the user requests this. <code class="classname">TokenBasedRememberMeServices</code> also
+ <code class="literal">TokenBasedRememberMeServices</code>. In addition,
+ <code class="literal">TokenBasedRememberMeServices</code> requires A UserDetailsService from
+ which it can retrieve the username and password for signature comparison purposes,
+ and generate the <code class="literal">RememberMeAuthenticationToken</code> to contain the
+ correct <code class="interfacename">GrantedAuthority</code>s. Some sort of logout
+ command should be provided by the application that invalidates the cookie if the
+ user requests this. <code class="classname">TokenBasedRememberMeServices</code> also
implements Spring Security's <code class="interfacename">LogoutHandler</code> interface
so can be used with <code class="classname">LogoutFilter</code> to have the cookie cleared
automatically. </p><p>The beans required in an application context to enable remember-me services are as
@@ -2208,212 +2419,233 @@ class="org.springframework.security.web.context.SecurityContextPersistenceFilter
<span class="hl-tag"></bean></span>
</pre><p>Don't forget to add your
- <code class="interfacename">RememberMeServices</code> implementation to your
- <code class="literal">UsernamePasswordAuthenticationFilter.setRememberMeServices()</code>
+ <code class="interfacename">RememberMeServices</code> implementation to your
+ <code class="literal">UsernamePasswordAuthenticationFilter.setRememberMeServices()</code>
property, include the <code class="literal">RememberMeAuthenticationProvider</code> in your
- <code class="literal">AuthenticationManager.setProviders()</code> list, and add
- <code class="classname">RememberMeAuthenticationFilter</code> into your
- <code class="classname">FilterChainProxy</code> (typically immediately after your
- <code class="literal">UsernamePasswordAuthenticationFilter</code>).</p></div><div class="section" title="10.4.2 PersistentTokenBasedRememberMeServices"><div class="titlepage"><div><div><h3 class="title"><a name="d0e3772"></a>10.4.2 PersistentTokenBasedRememberMeServices</h3></div></div></div><p> This class can be used in the same way as
- <code class="classname">TokenBasedRememberMeServices</code>, but it additionally needs
- to be configured with a <code class="interfacename">PersistentTokenRepository</code> to
- store the tokens. There are two standard implementations.
- </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p><code class="classname">InMemoryTokenRepositoryImpl</code>
- which is intended for testing
- only.</p></li><li class="listitem"><p><code class="classname">JdbcTokenRepositoryImpl</code>
- which stores the tokens in a database. </p></li></ul></div><p>
- The database schema is described above in <a class="xref" href="#remember-me-persistent-token" title="10.3 Persistent Token Approach">Section 10.3, “Persistent Token Approach”</a>. </p></div></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e3651" href="#d0e3651" class="para">12</a>] </sup>Essentially, the username is not included in the
- cookie, to prevent exposing a valid login name unecessarily. There is a
- discussion on this in the comments section of this article.</p></div></div></div><div class="chapter" title="11. Session Management"><div class="titlepage"><div><div><h1 class="title"><a name="session-mgmt"></a>Session Management</h1></div></div></div><p>HTTP session related functonality is handled by a combination of the
- <code class="classname">SessionManagementFilter</code> and the
- <code class="interfacename">SessionAuthenticationStrategy</code> interface, which the filter
- delegates to. Typical usage includes session-fixation protection attack prevention, detection of
- session timeouts and restrictions on how many sessions an authenticated user may have open
- concurrently.</p><div class="section" title="11.1 SessionManagementFilter"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e3809"></a>11.1 SessionManagementFilter</h2></div></div></div><p>The <code class="classname">SessionManagementFilter</code> checks the contents of the
- <code class="interfacename">SecurityContextRepository</code> against the current contents of the
- <code class="classname">SecurityContextHolder</code> to determine whether a user has been
- authenticated during the current request, typically by a non-interactive authentication
- mechanism, such as pre-authentication or remember-me <sup>[<a name="d0e3823" href="#ftn.d0e3823" class="footnote">13</a>]</sup>. If the repository contains a
- security context, the filter does nothing. If it doesn't, and the thread-local
- <code class="interfacename">SecurityContext</code> contains a (non-anonymous)
- <code class="interfacename">Authentication</code> object, the filter assumes they have been
- authenticated by a previous filter in the stack. It will then invoke the configured
- <code class="interfacename">SessionAuthenticationStrategy</code>.</p><p>If the user is not currently authenticated, the filter will check whether an invalid
- session ID has been requested (because of a timeout, for example) and will redirect to the
- configured <code class="literal">invalidSessionUrl</code> if set. The easiest way to configure this is
- through the namespace, <a class="link" href="#ns-session-mgmt" title="2.3.3 Session Management">as described earlier</a>.</p></div><div class="section" title="11.2 SessionAuthenticationStrategy"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e3847"></a>11.2 <code class="interfacename">SessionAuthenticationStrategy</code></h2></div></div></div><p>
- <code class="interfacename">SessionAuthenticationStrategy</code> is used by both
- <code class="classname">SessionManagementFilter</code> and
- <code class="classname">AbstractAuthenticationProcessingFilter</code>, so if you are using a
- customized form-login class, for example, you will need to inject it into both of these. In
- this case, a typical configuration, combining the namespace and custom beans might look like this:</p><pre class="programlisting">
- <http>
- <custom-filter position="FORM_LOGIN_FILTER" ref="myAuthFilter" />
- <session-management session-authentication-strategy-ref="sas"/>
- </http>
+ <code class="literal">AuthenticationManager.setProviders()</code> list, and add
+ <code class="classname">RememberMeAuthenticationFilter</code> into your
+ <code class="classname">FilterChainProxy</code> (typically immediately after your
+ <code class="literal">UsernamePasswordAuthenticationFilter</code>).</p></div><div class="section" title="11.4.2 PersistentTokenBasedRememberMeServices"><div class="titlepage"><div><div><h3 class="title"><a name="d0e4334"></a>11.4.2 PersistentTokenBasedRememberMeServices</h3></div></div></div><p> This class can be used in the same way as
+ <code class="classname">TokenBasedRememberMeServices</code>, but it additionally needs to be
+ configured with a <code class="interfacename">PersistentTokenRepository</code> to store
+ the tokens. There are two standard implementations. </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p><code class="classname">InMemoryTokenRepositoryImpl</code> which is intended for
+ testing only.</p></li><li class="listitem"><p><code class="classname">JdbcTokenRepositoryImpl</code> which stores the tokens in
+ a database. </p></li></ul></div><p> The database schema is described above in <a class="xref" href="#remember-me-persistent-token" title="11.3 Persistent Token Approach">Section 11.3, “Persistent Token Approach”</a>. </p></div></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e4213" href="#d0e4213" class="para">19</a>] </sup>Essentially, the username is not included in the cookie, to prevent exposing a
+ valid login name unecessarily. There is a discussion on this in the comments section
+ of this article.</p></div></div></div><div class="chapter" title="12. Session Management"><div class="titlepage"><div><div><h1 class="title"><a name="session-mgmt"></a>Session Management</h1></div></div></div><p>HTTP session related functonality is handled by a combination of the
+ <code class="classname">SessionManagementFilter</code> and the
+ <code class="interfacename">SessionAuthenticationStrategy</code> interface, which the filter
+ delegates to. Typical usage includes session-fixation protection attack prevention,
+ detection of session timeouts and restrictions on how many sessions an authenticated user
+ may have open concurrently.</p><div class="section" title="12.1 SessionManagementFilter"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e4371"></a>12.1 SessionManagementFilter</h2></div></div></div><p>The <code class="classname">SessionManagementFilter</code> checks the contents of the
+ <code class="interfacename">SecurityContextRepository</code> against the current contents of
+ the <code class="classname">SecurityContextHolder</code> to determine whether a user has been
+ authenticated during the current request, typically by a non-interactive authentication
+ mechanism, such as pre-authentication or remember-me <sup>[<a name="d0e4385" href="#ftn.d0e4385" class="footnote">20</a>]</sup>. If the repository contains a security context, the filter does nothing. If
+ it doesn't, and the thread-local <code class="interfacename">SecurityContext</code> contains
+ a (non-anonymous) <code class="interfacename">Authentication</code> object, the filter
+ assumes they have been authenticated by a previous filter in the stack. It will then
+ invoke the configured
+ <code class="interfacename">SessionAuthenticationStrategy</code>.</p><p>If the user is not currently authenticated, the filter will check whether an invalid
+ session ID has been requested (because of a timeout, for example) and will invoke the configured
+ <code class="interfacename">InvalidSessionStrategy</code>, if one is set. The most common behaviour
+ is just to redirect to a fixed URL and this is encapsulated in the standard implementation
+ <code class="classname">SimpleRedirectInvalidSessionStrategy</code>. The latter is also used
+ when configuring an invalid session URL through the namespace,
+ <a class="link" href="#ns-session-mgmt" title="3.3.3 Session Management">as described earlier</a>.</p></div><div class="section" title="12.2 SessionAuthenticationStrategy"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e4412"></a>12.2 <code class="interfacename">SessionAuthenticationStrategy</code></h2></div></div></div><p> <code class="interfacename">SessionAuthenticationStrategy</code> is used by both
+ <code class="classname">SessionManagementFilter</code> and
+ <code class="classname">AbstractAuthenticationProcessingFilter</code>, so if you are using a
+ customized form-login class, for example, you will need to inject it into both of these.
+ In this case, a typical configuration, combining the namespace and custom beans might
+ look like this:</p><pre class="programlisting">
+<span class="hl-tag"><http></span>
+ <span class="hl-tag"><custom-filter</span> <span class="hl-attribute">position</span>=<span class="hl-value">"FORM_LOGIN_FILTER"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"myAuthFilter"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"><session-management</span> <span class="hl-attribute">session-authentication-strategy-ref</span>=<span class="hl-value">"sas"</span><span class="hl-tag">/></span>
+<span class="hl-tag"></http></span>
- <beans:bean id="myAuthFilter"
- class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
- <beans:property name="sessionAuthenticationStrategy" ref="sas" />
+<span class="hl-tag"><beans:bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"myAuthFilter"</span> <span class="hl-attribute">class</span>=
+ <span class="hl-value">"org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><beans:property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"sessionAuthenticationStrategy"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"sas"</span><span class="hl-tag"> /></span>
...
- </beans:bean>
+<span class="hl-tag"></beans:bean></span>
- <beans:bean id="sas"
- class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy"/>
-
- </pre></div><div class="section" title="11.3 Concurrency Control"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="concurrent-sessions"></a>11.3 Concurrency Control</h2></div></div></div><p>Spring Security is able to prevent a principal from concurrently authenticating to the
- same application more than a specified number of times. Many ISVs take advantage of this to
- enforce licensing, whilst network administrators like this feature because it helps prevent
- people from sharing login names. You can, for example, stop user <span class="quote">“<span class="quote">Batman</span>”</span> from
- logging onto the web application from two different sessions. You can either expire their
- previous login or you can report an error when they try to log in again, preventing the second
- login. Note that if you are using the second approach, a user who has not explicitly logged
- out (but who has just closed their browser, for example) will not be able to log in again
- until their original session expires.</p><p>Concurrency control is supported by the namespace, so please check the earlier namespace
- chapter for the simplest configuration. Sometimes you need to customize things though. </p><p>The implementation uses a specialized version of
- <code class="interfacename">SessionAuthenticationStrategy</code>, called
- <code class="classname">ConcurrentSessionControlStrategy</code>. </p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Previously the
- concurrent authentication check was made by the <code class="classname">ProviderManager</code>,
- which could be injected with a <code class="literal">ConcurrentSessionController</code>. The latter
- would check if the user was attempting to exceed the number of permitted sessions.
- However, this approach required that an HTTP session be created in advance, which is
- undesirable. In Spring Security 3, the user is first authenticated by the
- <code class="interfacename">AuthenticationManager</code> and once they are successfully
- authenticated, a session is created and the check is made whether they are allowed to have
- another session open.</p></td></tr></table></div><p>To use concurrent session support, you'll need to add the following to
- <code class="literal">web.xml</code>: </p><pre class="programlisting">
- <listener>
- <listener-class>
+<span class="hl-tag"><beans:bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"sas"</span> <span class="hl-attribute">class</span>=
+ <span class="hl-value">"org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy"</span><span class="hl-tag"> /></span>
+</pre><p>
+ Note that the use of the default, <code class="classname">SessionFixationProtectionStrategy</code>
+ may cause issues if you are storing beans in the session which implement
+ <code class="interfacename">HttpSessionBindingListener</code>, including Spring session-scoped
+ beans. See the Javadoc for this class for more information.
+ </p></div><div class="section" title="12.3 Concurrency Control"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="concurrent-sessions"></a>12.3 Concurrency Control</h2></div></div></div><p>Spring Security is able to prevent a principal from concurrently authenticating to the
+ same application more than a specified number of times. Many ISVs take advantage of this
+ to enforce licensing, whilst network administrators like this feature because it helps
+ prevent people from sharing login names. You can, for example, stop user
+ <span class="quote">“<span class="quote">Batman</span>”</span> from logging onto the web application from two different sessions.
+ You can either expire their previous login or you can report an error when they try to
+ log in again, preventing the second login. Note that if you are using the second
+ approach, a user who has not explicitly logged out (but who has just closed their
+ browser, for example) will not be able to log in again until their original session
+ expires.</p><p>Concurrency control is supported by the namespace, so please check the earlier
+ namespace chapter for the simplest configuration. Sometimes you need to customize things
+ though. </p><p>The implementation uses a specialized version of
+ <code class="interfacename">SessionAuthenticationStrategy</code>, called
+ <code class="classname">ConcurrentSessionControlStrategy</code>. </p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Previously the concurrent authentication check was made by the
+ <code class="classname">ProviderManager</code>, which could be injected with a
+ <code class="literal">ConcurrentSessionController</code>. The latter would check if the user
+ was attempting to exceed the number of permitted sessions. However, this approach
+ required that an HTTP session be created in advance, which is undesirable. In Spring
+ Security 3, the user is first authenticated by the
+ <code class="interfacename">AuthenticationManager</code> and once they are successfully
+ authenticated, a session is created and the check is made whether they are allowed
+ to have another session open.</p></td></tr></table></div><p>To use concurrent session support, you'll need to add the following to
+ <code class="literal">web.xml</code>: </p><pre class="programlisting">
+ <span class="hl-tag"><listener></span>
+ <span class="hl-tag"><listener-class></span>
org.springframework.security.web.session.HttpSessionEventPublisher
- </listener-class>
- </listener>
- </pre><p>In addition, you will need to add the <code class="literal">ConcurrentSessionFilter</code> to your
- <code class="classname">FilterChainProxy</code>. The <code class="classname">ConcurrentSessionFilter</code>
- requires two properties, <code class="literal">sessionRegistry</code>, which generally points to an
- instance of <code class="classname">SessionRegistryImpl</code>, and <code class="literal">expiredUrl</code>, which
- points to the page to display when a session has expired. A configuration using the namespace
- to create the <code class="classname">FilterChainProxy</code> and other default beans might look like
- this: </p><pre class="programlisting">
- <http>
- <custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" />
- <custom-filter position="FORM_LOGIN_FILTER" ref="myAuthFilter" />
+ <span class="hl-tag"></listener-class></span>
+ <span class="hl-tag"></listener></span>
+ </pre><p>In addition, you will need to add the <code class="literal">ConcurrentSessionFilter</code> to
+ your <code class="classname">FilterChainProxy</code>. The
+ <code class="classname">ConcurrentSessionFilter</code> requires two properties,
+ <code class="literal">sessionRegistry</code>, which generally points to an instance of
+ <code class="classname">SessionRegistryImpl</code>, and <code class="literal">expiredUrl</code>, which
+ points to the page to display when a session has expired. A configuration using the
+ namespace to create the <code class="classname">FilterChainProxy</code> and other default beans
+ might look like this: </p><pre class="programlisting">
+<span class="hl-tag"><http></span>
+ <span class="hl-tag"><custom-filter</span> <span class="hl-attribute">position</span>=<span class="hl-value">"CONCURRENT_SESSION_FILTER"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"concurrencyFilter"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"><custom-filter</span> <span class="hl-attribute">position</span>=<span class="hl-value">"FORM_LOGIN_FILTER"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"myAuthFilter"</span><span class="hl-tag"> /></span>
- <session-management session-authentication-strategy-ref="sas"/>
- </http>
+ <span class="hl-tag"><session-management</span> <span class="hl-attribute">session-authentication-strategy-ref</span>=<span class="hl-value">"sas"</span><span class="hl-tag">/></span>
+<span class="hl-tag"></http></span>
- <beans:bean id="concurrencyFilter"
- class="org.springframework.security.web.session.ConcurrentSessionFilter">
- <beans:property name="sessionRegistry" ref="sessionRegistry" />
- <beans:property name="expiredUrl" value="/session-expired.htm" />
- </beans:bean>
+<span class="hl-tag"><beans:bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"concurrencyFilter"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.session.ConcurrentSessionFilter"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><beans:property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"sessionRegistry"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"sessionRegistry"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"><beans:property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"expiredUrl"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"/session-expired.htm"</span><span class="hl-tag"> /></span>
+<span class="hl-tag"></beans:bean></span>
- <beans:bean id="myAuthFilter"
- class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
- <beans:property name="sessionAuthenticationStrategy" ref="sas" />
- <beans:property name="authenticationManager" ref="authenticationManager" />
- </beans:bean>
+<span class="hl-tag"><beans:bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"myAuthFilter"</span> <span class="hl-attribute">class</span>=
+ <span class="hl-value">"org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><beans:property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"sessionAuthenticationStrategy"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"sas"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"><beans:property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"authenticationManager"</span><span class="hl-tag"> /></span>
+<span class="hl-tag"></beans:bean></span>
- <beans:bean id="sas"
- class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
- <beans:constructor-arg name="sessionRegistry" ref="sessionRegistry" />
- <beans:property name="maximumSessions" value="1" />
- </beans:bean>
+<span class="hl-tag"><beans:bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"sas"</span> <span class="hl-attribute">class</span>=
+ <span class="hl-value">"org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><beans:constructor-arg</span> <span class="hl-attribute">name</span>=<span class="hl-value">"sessionRegistry"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"sessionRegistry"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"><beans:property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"maximumSessions"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"1"</span><span class="hl-tag"> /></span>
+<span class="hl-tag"></beans:bean></span>
- <beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl" />
+<span class="hl-tag"><beans:bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"sessionRegistry"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.core.session.SessionRegistryImpl"</span><span class="hl-tag"> /></span>
</pre><p>Adding the listener to <code class="filename">web.xml</code> causes an
- <code class="literal">ApplicationEvent</code> to be published to the Spring
- <code class="literal">ApplicationContext</code> every time a <code class="literal">HttpSession</code> commences
- or terminates. This is critical, as it allows the <code class="classname">SessionRegistryImpl</code>
- to be notified when a session ends. Without it, a user will never be able to log back in again
- once they have exceeded their session allowance, even if they log out of another session or it
- times out.</p></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e3823" href="#d0e3823" class="para">13</a>] </sup>Authentication by
- mechanisms which perform a redirect after authenticating (such as form-login) will not be
- detected by <code class="classname">SessionManagementFilter</code>, as the filter will not be
- invoked during the authenticating request. Session-management functionality has to be
- handled separately in these cases. </p></div></div></div><div class="chapter" title="12. Anonymous Authentication"><div class="titlepage"><div><div><h1 class="title"><a name="anonymous"></a>Anonymous Authentication</h1></div></div></div><div class="section" title="12.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="anonymous-overview"></a>12.1 Overview</h2></div></div></div><p>It's generally considered good security practice to adopt a
- <span class="quote">“<span class="quote">deny-by-default</span>”</span> where you explicitly specify what is allowed and
- disallow everything else. Defining what is accessible to unauthenticated users is a
- similar situation, particularly for web applications. Many sites require that users must
- be authenticated for anything other than a few URLs (for example the home and login
- pages). In this case it is easiest to define access configuration attributes for these
- specific URLs rather than have for every secured resource. Put differently, sometimes it
- is nice to say <code class="literal">ROLE_SOMETHING</code> is required by default and only allow
- certain exceptions to this rule, such as for login, logout and home pages of an
- application. You could also omit these pages from the filter chain entirely, thus
- bypassing the access control checks, but this may be undesirable for other reasons,
- particularly if the pages behave differently for authenticated users.</p><p>This is what we mean by anonymous authentication. Note that there is no real
+ <code class="literal">ApplicationEvent</code> to be published to the Spring
+ <code class="literal">ApplicationContext</code> every time a <code class="literal">HttpSession</code>
+ commences or terminates. This is critical, as it allows the
+ <code class="classname">SessionRegistryImpl</code> to be notified when a session ends. Without
+ it, a user will never be able to log back in again once they have exceeded their session
+ allowance, even if they log out of another session or it times out.</p><div class="section" title="12.3.1 Querying the SessionRegistry for currently authenticated users and their sessions"><div class="titlepage"><div><div><h3 class="title"><a name="list-authenticated-principals"></a>12.3.1 Querying the <code class="interfacename">SessionRegistry</code> for currently authenticated
+ users and their sessions</h3></div></div></div><p>
+ Setting up concurrency-control, either through the namespace or using plain beans has the
+ useful side effect of providing you with a reference to the <code class="interfacename">SessionRegistry</code>
+ which you can use directly within your application, so even if you don't want to restrict the
+ number of sessions a user may have, it may be worth setting up the infrastructure anyway. You can
+ set the <code class="literal">maximumSession</code> property to -1 to allow unlimited sessions. If
+ you're using the namespace, you can set an alias for the internally-created
+ <code class="interfacename">SessionRegistry</code> using the <code class="literal">session-registry-alias</code>
+ attribute, providing a reference which you can inject into your own beans.</p><p>
+ The <code class="methodname">getAllPrincipals()</code>
+ method supplies you with a list of the currently authenticated users. You can list a user's
+ sessions by calling the <code class="methodname">getAllSessions(Object principal, boolean includeExpiredSessions)</code> method,
+ which returns a list of <code class="classname">SessionInformation</code> objects. You can also
+ expire a user's session by calling <code class="methodname">expireNow()</code> on a
+ <code class="methodname">SessionInformation</code> instance. When the user returns to the application, they
+ will be prevented from proceeding. You may find these methods useful in an administration
+ application, for example. Have a look at the Javadoc for more information.
+ </p></div></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e4385" href="#d0e4385" class="para">20</a>] </sup>Authentication by mechanisms which perform a redirect after authenticating (such
+ as form-login) will not be detected by
+ <code class="classname">SessionManagementFilter</code>, as the filter will not be invoked
+ during the authenticating request. Session-management functionality has to be
+ handled separately in these cases. </p></div></div></div><div class="chapter" title="13. Anonymous Authentication"><div class="titlepage"><div><div><h1 class="title"><a name="anonymous"></a>Anonymous Authentication</h1></div></div></div><div class="section" title="13.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="anonymous-overview"></a>13.1 Overview</h2></div></div></div><p>It's generally considered good security practice to adopt a
+ <span class="quote">“<span class="quote">deny-by-default</span>”</span> where you explicitly specify what is allowed and disallow
+ everything else. Defining what is accessible to unauthenticated users is a similar
+ situation, particularly for web applications. Many sites require that users must be
+ authenticated for anything other than a few URLs (for example the home and login pages).
+ In this case it is easiest to define access configuration attributes for these specific
+ URLs rather than have for every secured resource. Put differently, sometimes it is nice
+ to say <code class="literal">ROLE_SOMETHING</code> is required by default and only allow certain
+ exceptions to this rule, such as for login, logout and home pages of an application. You
+ could also omit these pages from the filter chain entirely, thus bypassing the access
+ control checks, but this may be undesirable for other reasons, particularly if the pages
+ behave differently for authenticated users.</p><p>This is what we mean by anonymous authentication. Note that there is no real
conceptual difference between a user who is <span class="quote">“<span class="quote">anonymously authenticated</span>”</span> and
an unauthenticated user. Spring Security's anonymous authentication just gives you a
more convenient way to configure your access-control attributes. Calls to servlet API
calls such as <code class="methodname">getCallerPrincipal</code>, for example, will still
return null even though there is actually an anonymous authentication object in the
- <code class="classname">SecurityContextHolder</code>.</p><p>There are other situations where anonymous authentication is useful, such as when an
+ <code class="classname">SecurityContextHolder</code>.</p><p>There are other situations where anonymous authentication is useful, such as when an
auditing interceptor queries the <code class="classname">SecurityContextHolder</code> to
identify which principal was responsible for a given operation. Classes can be authored
more robustly if they know the <code class="classname">SecurityContextHolder</code> always
contains an <code class="interfacename">Authentication</code> object, and never
- <code class="literal">null</code>.</p></div><div class="section" title="12.2 Configuration"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="anonymous-config"></a>12.2 Configuration</h2></div></div></div><p>Anonymous authentication support is provided automatically when using the HTTP
+ <code class="literal">null</code>.</p></div><div class="section" title="13.2 Configuration"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="anonymous-config"></a>13.2 Configuration</h2></div></div></div><p>Anonymous authentication support is provided automatically when using the HTTP
configuration Spring Security 3.0 and can be customized (or disabled) using the
- <code class="literal"><anonymous></code> element. You don't need to configure the beans
+ <code class="literal"><anonymous></code> element. You don't need to configure the beans
described here unless you are using traditional bean configuration.</p><p>Three classes that together provide the anonymous authentication feature.
- <code class="literal">AnonymousAuthenticationToken</code> is an implementation of
- <code class="interfacename">Authentication</code>, and stores the
- <code class="interfacename">GrantedAuthority</code>s which apply to the anonymous
- principal. There is a corresponding <code class="literal">AnonymousAuthenticationProvider</code>,
- which is chained into the <code class="literal">ProviderManager</code> so that
- <code class="literal">AnonymousAuthenticationToken</code>s are accepted. Finally, there is an
- <code class="classname">AnonymousAuthenticationFilter</code>, which is chained after the
- normal authentication mechanisms and automatically adds an
- <code class="literal">AnonymousAuthenticationToken</code> to the
- <code class="classname">SecurityContextHolder</code> if there is no existing
- <code class="interfacename">Authentication</code> held there. The definition of the
- filter and authentication provider appears as follows:</p><p>
- </p><pre class="programlisting">
+ <code class="literal">AnonymousAuthenticationToken</code> is an implementation of
+ <code class="interfacename">Authentication</code>, and stores the
+ <code class="interfacename">GrantedAuthority</code>s which apply to the anonymous principal.
+ There is a corresponding <code class="literal">AnonymousAuthenticationProvider</code>, which is
+ chained into the <code class="literal">ProviderManager</code> so that
+ <code class="literal">AnonymousAuthenticationToken</code>s are accepted. Finally, there is an
+ <code class="classname">AnonymousAuthenticationFilter</code>, which is chained after the normal
+ authentication mechanisms and automatically adds an
+ <code class="literal">AnonymousAuthenticationToken</code> to the
+ <code class="classname">SecurityContextHolder</code> if there is no existing
+ <code class="interfacename">Authentication</code> held there. The definition of the filter
+ and authentication provider appears as follows:</p><p> </p><pre class="programlisting">
-<bean id="anonymousAuthFilter"
- class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter">
- <property name="key" value="foobar"/>
- <property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS"/>
-</bean>
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"anonymousAuthFilter"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.authentication.AnonymousAuthenticationFilter"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"key"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"foobar"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"userAttribute"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"anonymousUser,ROLE_ANONYMOUS"</span><span class="hl-tag">/></span>
+<span class="hl-tag"></bean></span>
-<bean id="anonymousAuthenticationProvider"
- class="org.springframework.security.authentication.AnonymousAuthenticationProvider">
- <property name="key" value="foobar"/>
-</bean>
- </pre><p>
- </p><p>The <code class="literal">key</code> is shared between the filter and authentication provider,
- so that tokens created by the former are accepted by the latter<sup>[<a name="d0e4035" href="#ftn.d0e4035" class="footnote">14</a>]</sup>. The
- <code class="literal">userAttribute</code> is expressed in the form of
- <code class="literal">usernameInTheAuthenticationToken,grantedAuthority[,grantedAuthority]</code>.
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"anonymousAuthenticationProvider"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.authentication.AnonymousAuthenticationProvider"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"key"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"foobar"</span><span class="hl-tag">/></span>
+<span class="hl-tag"></bean></span>
+ </pre><p> </p><p>The <code class="literal">key</code> is shared between the filter and authentication provider,
+ so that tokens created by the former are accepted by the latter<sup>[<a name="d0e4644" href="#ftn.d0e4644" class="footnote">21</a>]</sup>. The <code class="literal">userAttribute</code> is expressed in the form of
+ <code class="literal">usernameInTheAuthenticationToken,grantedAuthority[,grantedAuthority]</code>.
This is the same syntax as used after the equals sign for
- <code class="literal">InMemoryDaoImpl</code>'s <code class="literal">userMap</code> property.</p><p>As explained earlier, the benefit of anonymous authentication is that all URI patterns
- can have security applied to them. For example:</p><p>
- </p><pre class="programlisting">
+ <code class="literal">InMemoryDaoImpl</code>'s <code class="literal">userMap</code> property.</p><p>As explained earlier, the benefit of anonymous authentication is that all URI patterns
+ can have security applied to them. For example:</p><p> </p><pre class="programlisting">
-<bean id="filterSecurityInterceptor"
- class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
- <property name="authenticationManager" ref="authenticationManager"/>
- <property name="accessDecisionManager" ref="httpRequestAccessDecisionManager"/>
- <property name="securityMetadata">
- <security:filter-security-metadata-source>
- <security:intercept-url pattern='/index.jsp' access='ROLE_ANONYMOUS,ROLE_USER'/>
- <security:intercept-url pattern='/hello.htm' access='ROLE_ANONYMOUS,ROLE_USER'/>
- <security:intercept-url pattern='/logoff.jsp' access='ROLE_ANONYMOUS,ROLE_USER'/>
- <security:intercept-url pattern='/login.jsp' access='ROLE_ANONYMOUS,ROLE_USER'/>
- <security:intercept-url pattern='/**' access='ROLE_USER'/>
- </security:filter-security-metadata-source>" +
- </property>
-</bean>
- </pre><p>
- </p></div><div class="section" title="12.3 AuthenticationTrustResolver"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="anonymous-auth-trust-resolver"></a>12.3 <code class="interfacename">AuthenticationTrustResolver</code></h2></div></div></div><p> Rounding out the anonymous authentication discussion is the
- <code class="interfacename">AuthenticationTrustResolver</code> interface, with its
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"filterSecurityInterceptor"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.access.intercept.FilterSecurityInterceptor"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"authenticationManager"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"accessDecisionManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"httpRequestAccessDecisionManager"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"securityMetadata"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><security:filter-security-metadata-source></span>
+ <span class="hl-tag"><security:intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">'/index.jsp'</span> <span class="hl-attribute">access</span>=<span class="hl-value">'ROLE_ANONYMOUS,ROLE_USER'</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><security:intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">'/hello.htm'</span> <span class="hl-attribute">access</span>=<span class="hl-value">'ROLE_ANONYMOUS,ROLE_USER'</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><security:intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">'/logoff.jsp'</span> <span class="hl-attribute">access</span>=<span class="hl-value">'ROLE_ANONYMOUS,ROLE_USER'</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><security:intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">'/login.jsp'</span> <span class="hl-attribute">access</span>=<span class="hl-value">'ROLE_ANONYMOUS,ROLE_USER'</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><security:intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">'/**'</span> <span class="hl-attribute">access</span>=<span class="hl-value">'ROLE_USER'</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></security:filter-security-metadata-source></span>" +
+ <span class="hl-tag"></property></span>
+<span class="hl-tag"></bean></span>
+ </pre><p> </p></div><div class="section" title="13.3 AuthenticationTrustResolver"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="anonymous-auth-trust-resolver"></a>13.3 <code class="interfacename">AuthenticationTrustResolver</code></h2></div></div></div><p> Rounding out the anonymous authentication discussion is the
+ <code class="interfacename">AuthenticationTrustResolver</code> interface, with its
corresponding <code class="literal">AuthenticationTrustResolverImpl</code> implementation. This
interface provides an <code class="literal">isAnonymous(Authentication)</code> method, which
allows interested classes to take into account this special type of authentication
status. The <code class="classname">ExceptionTranslationFilter</code> uses this interface in
processing <code class="literal">AccessDeniedException</code>s. If an
- <code class="literal">AccessDeniedException</code> is thrown, and the authentication is of an
+ <code class="literal">AccessDeniedException</code> is thrown, and the authentication is of an
anonymous type, instead of throwing a 403 (forbidden) response, the filter will instead
commence the <code class="interfacename">AuthenticationEntryPoint</code> so the principal
can authenticate properly. This is a necessary distinction, otherwise principals would
@@ -2422,249 +2654,297 @@ class="org.springframework.security.web.context.SecurityContextPersistenceFilter
interceptor configuration replaced with <code class="literal">IS_AUTHENTICATED_ANONYMOUSLY</code>,
which is effectively the same thing when defining access controls. This is an example of
the use of the <code class="classname">AuthenticatedVoter</code> which we will see in the <a class="link" href="#authz-authenticated-voter" title="AuthenticatedVoter">authorization chapter</a>. It uses an
- <code class="interfacename">AuthenticationTrustResolver</code> to process this
- particular configuration attribute and grant access to anonymous users. The
- <code class="classname">AuthenticatedVoter</code> approach is more powerful, since it allows
- you to differentiate between anonymous, remember-me and fully-authenticated users. If
- you don't need this functionality though, then you can stick with
- <code class="literal">ROLE_ANONYMOUS</code>, which will be processed by Spring Security's
- standard <code class="classname">RoleVoter</code>. </p></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e4035" href="#d0e4035" class="para">14</a>] </sup>The use
- of the <code class="literal">key</code> property should not be regarded as providing any
- real security here. It is merely a book-keeping exercise. If you are sharing a
- <code class="classname">ProviderManager</code> which contains an
- <code class="classname">AnonymousAuthenticationProvider</code> in a scenario where
- it is possible for an authenticating client to construct the
- <code class="interfacename">Authentication</code> object (such as with RMI
- invocations), then a malicious client could submit an
- <code class="classname">AnonymousAuthenticationToken</code> which it had created
- itself (with chosen username and authority list). If the <code class="literal">key</code>
- is guessable or can be found out, then the token would be accepted by the
- anonymous provider. This isn't a problem with normal usage but if you are using
- RMI you would be best to use a customized <code class="classname">ProviderManager</code>
- which omits the anonymous provider rather than sharing the one you use for your
- HTTP authentication mechanisms.</p></div></div></div></div><div class="part" title="Part IV. Authorization"><div class="titlepage"><div><div><h1 class="title"><a name="authorization"></a>Part IV. Authorization</h1></div></div></div><div class="partintro" title="Authorization"><div></div><p>The advanced authorization capabilities within Spring Security represent one of the most
- compelling reasons for its popularity. Irrespective of how you choose to authenticate -
- whether using a Spring Security-provided mechanism and provider, or integrating with a
- container or other non-Spring Security authentication authority - you will find the
- authorization services can be used within your application in a consistent and simple
- way.</p><p>In this part we'll explore the different
- <code class="classname">AbstractSecurityInterceptor</code> implementations, which were introduced
- in Part I. We then move on to explore how to fine-tune authorization through use of domain
- access control lists.</p></div><div class="chapter" title="13. Authorization Architecture"><div class="titlepage"><div><div><h1 class="title"><a name="authz-arch"></a>Authorization Architecture</h1></div></div></div><div class="section" title="13.1 Authorities"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="authz-authorities"></a>13.1 Authorities</h2></div></div></div><p>As we saw in the <a class="link" href="#tech-granted-authority" title="5.2.3 GrantedAuthority">technical overview</a>, all
- <code class="interfacename">Authentication</code> implementations store a list of
- <code class="interfacename">GrantedAuthority</code> objects. These represent the authorities
- that have been granted to the principal. The <code class="interfacename">GrantedAuthority</code>
- objects are inserted into the <code class="interfacename">Authentication</code> object by the
- <code class="interfacename">AuthenticationManager</code> and are later read by
- <code class="interfacename">AccessDecisionManager</code>s when making authorization
- decisions.</p><p><code class="interfacename">GrantedAuthority</code> is an interface with only one method:
- </p><pre class="programlisting">
+ <code class="interfacename">AuthenticationTrustResolver</code> to process this particular
+ configuration attribute and grant access to anonymous users. The
+ <code class="classname">AuthenticatedVoter</code> approach is more powerful, since it allows you
+ to differentiate between anonymous, remember-me and fully-authenticated users. If you
+ don't need this functionality though, then you can stick with
+ <code class="literal">ROLE_ANONYMOUS</code>, which will be processed by Spring Security's standard
+ <code class="classname">RoleVoter</code>. </p></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e4644" href="#d0e4644" class="para">21</a>] </sup>The use of the <code class="literal">key</code> property should not be regarded as providing
+ any real security here. It is merely a book-keeping exercise. If you are sharing a
+ <code class="classname">ProviderManager</code> which contains an
+ <code class="classname">AnonymousAuthenticationProvider</code> in a scenario where it is
+ possible for an authenticating client to construct the
+ <code class="interfacename">Authentication</code> object (such as with RMI invocations),
+ then a malicious client could submit an
+ <code class="classname">AnonymousAuthenticationToken</code> which it had created itself
+ (with chosen username and authority list). If the <code class="literal">key</code> is
+ guessable or can be found out, then the token would be accepted by the anonymous
+ provider. This isn't a problem with normal usage but if you are using RMI you would
+ be best to use a customized <code class="classname">ProviderManager</code> which omits the
+ anonymous provider rather than sharing the one you use for your HTTP authentication
+ mechanisms.</p></div></div></div></div><div class="part" title="Part IV. Authorization"><div class="titlepage"><div><div><h1 class="title"><a name="authorization"></a>Part IV. Authorization</h1></div></div></div><div class="partintro" title="Authorization"><div></div><p>The advanced authorization capabilities within Spring Security represent one of
+ the most compelling reasons for its popularity. Irrespective of how you choose to
+ authenticate - whether using a Spring Security-provided mechanism and provider, or
+ integrating with a container or other non-Spring Security authentication authority -
+ you will find the authorization services can be used within your application in a
+ consistent and simple way.</p><p>In this part we'll explore the different
+ <code class="classname">AbstractSecurityInterceptor</code> implementations, which were
+ introduced in Part I. We then move on to explore how to fine-tune authorization
+ through use of domain access control lists.</p></div><div class="chapter" title="14. Authorization Architecture"><div class="titlepage"><div><div><h1 class="title"><a name="authz-arch"></a>Authorization Architecture</h1></div></div></div><div class="section" title="14.1 Authorities"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="authz-authorities"></a>14.1 Authorities</h2></div></div></div><p>As we saw in the <a class="link" href="#tech-granted-authority" title="6.2.3 GrantedAuthority">technical overview</a>,
+ all <code class="interfacename">Authentication</code> implementations store a list of
+ <code class="interfacename">GrantedAuthority</code> objects. These represent the authorities
+ that have been granted to the principal. The
+ <code class="interfacename">GrantedAuthority</code> objects are inserted into the
+ <code class="interfacename">Authentication</code> object by the
+ <code class="interfacename">AuthenticationManager</code> and are later read by
+ <code class="interfacename">AccessDecisionManager</code>s when making authorization
+ decisions.</p><p><code class="interfacename">GrantedAuthority</code> is an interface with only one method:
+ </p><pre class="programlisting">
String getAuthority();
</pre><p> This method allows
- <code class="interfacename">AccessDecisionManager</code>s to obtain a precise
- <code class="literal">String</code> representation of the
- <code class="interfacename">GrantedAuthority</code>. By returning a representation as a
- <code class="literal">String</code>, a <code class="interfacename">GrantedAuthority</code> can be easily
- <span class="quote">“<span class="quote">read</span>”</span> by most <code class="interfacename">AccessDecisionManager</code>s. If a
- <code class="interfacename">GrantedAuthority</code> cannot be precisely represented as a
- <code class="literal">String</code>, the <code class="interfacename">GrantedAuthority</code> is considered
- <span class="quote">“<span class="quote">complex</span>”</span> and <code class="literal">getAuthority()</code> must return
- <code class="literal">null</code>.</p><p>An example of a <span class="quote">“<span class="quote">complex</span>”</span>
- <code class="interfacename">GrantedAuthority</code> would be an implementation that stores a list
- of operations and authority thresholds that apply to different customer account numbers.
- Representing this complex <code class="interfacename">GrantedAuthority</code> as a
- <code class="literal">String</code> would be quite difficult, and as a result the
- <code class="literal">getAuthority()</code> method should return <code class="literal">null</code>. This will
- indicate to any <code class="interfacename">AccessDecisionManager</code> that it will need to
- specifically support the <code class="interfacename">GrantedAuthority</code> implementation in
- order to understand its contents.</p><p>Spring Security includes one concrete <code class="interfacename">GrantedAuthority</code>
- implementation, <code class="literal">GrantedAuthorityImpl</code>. This allows any user-specified
- <code class="literal">String</code> to be converted into a
- <code class="interfacename">GrantedAuthority</code>. All
- <code class="classname">AuthenticationProvider</code>s included with the security architecture use
- <code class="literal">GrantedAuthorityImpl</code> to populate the
- <code class="interfacename">Authentication</code> object.</p></div><div class="section" title="13.2 Pre-Invocation Handling"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="authz-pre-invocation"></a>13.2 Pre-Invocation Handling</h2></div></div></div><p> As we've also seen in the <a class="link" href="#secure-objects" title="5.5.2 Secure Objects and the AbstractSecurityInterceptor">Technical Overview</a>
- chapter, Spring Security provides interceptors which control access to secure objects such as
- method invocations or web requests. A pre-invocation decision on whether the invocation is
- allowed to proceed is made by the <code class="interfacename">AccessDecisionManager</code>. </p><div class="section" title="13.2.1 The AccessDecisionManager"><div class="titlepage"><div><div><h3 class="title"><a name="authz-access-decision-manager"></a>13.2.1 The AccessDecisionManager</h3></div></div></div><p>The <code class="interfacename">AccessDecisionManager</code> is called by the
- <code class="classname">AbstractSecurityInterceptor</code> and is responsible for making final
- access control decisions. The <code class="interfacename">AccessDecisionManager</code> interface
- contains three methods:
- </p><pre class="programlisting">
- void decide(Authentication authentication, Object secureObject,
- List<ConfigAttribute> config) throws AccessDeniedException;
- boolean supports(ConfigAttribute attribute);
- boolean supports(Class clazz);
+ <code class="interfacename">AccessDecisionManager</code>s to obtain a precise
+ <code class="literal">String</code> representation of the
+ <code class="interfacename">GrantedAuthority</code>. By returning a representation as a
+ <code class="literal">String</code>, a <code class="interfacename">GrantedAuthority</code> can be
+ easily <span class="quote">“<span class="quote">read</span>”</span> by most
+ <code class="interfacename">AccessDecisionManager</code>s. If a
+ <code class="interfacename">GrantedAuthority</code> cannot be precisely represented as a
+ <code class="literal">String</code>, the <code class="interfacename">GrantedAuthority</code> is
+ considered <span class="quote">“<span class="quote">complex</span>”</span> and <code class="literal">getAuthority()</code> must return
+ <code class="literal">null</code>.</p><p>An example of a <span class="quote">“<span class="quote">complex</span>”</span> <code class="interfacename">GrantedAuthority</code>
+ would be an implementation that stores a list of operations and authority thresholds
+ that apply to different customer account numbers. Representing this complex
+ <code class="interfacename">GrantedAuthority</code> as a <code class="literal">String</code> would be
+ quite difficult, and as a result the <code class="literal">getAuthority()</code> method should
+ return <code class="literal">null</code>. This will indicate to any
+ <code class="interfacename">AccessDecisionManager</code> that it will need to specifically
+ support the <code class="interfacename">GrantedAuthority</code> implementation in order to
+ understand its contents.</p><p>Spring Security includes one concrete <code class="interfacename">GrantedAuthority</code>
+ implementation, <code class="literal">GrantedAuthorityImpl</code>. This allows any user-specified
+ <code class="literal">String</code> to be converted into a
+ <code class="interfacename">GrantedAuthority</code>. All
+ <code class="classname">AuthenticationProvider</code>s included with the security architecture
+ use <code class="literal">GrantedAuthorityImpl</code> to populate the
+ <code class="interfacename">Authentication</code> object.</p></div><div class="section" title="14.2 Pre-Invocation Handling"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="authz-pre-invocation"></a>14.2 Pre-Invocation Handling</h2></div></div></div><p> As we've also seen in the <a class="link" href="#secure-objects" title="6.5.2 Secure Objects and the AbstractSecurityInterceptor">Technical
+ Overview</a> chapter, Spring Security provides interceptors which control access to
+ secure objects such as method invocations or web requests. A pre-invocation decision on
+ whether the invocation is allowed to proceed is made by the
+ <code class="interfacename">AccessDecisionManager</code>. </p><div class="section" title="14.2.1 The AccessDecisionManager"><div class="titlepage"><div><div><h3 class="title"><a name="authz-access-decision-manager"></a>14.2.1 The AccessDecisionManager</h3></div></div></div><p>The <code class="interfacename">AccessDecisionManager</code> is called by the
+ <code class="classname">AbstractSecurityInterceptor</code> and is responsible for making
+ final access control decisions. The
+ <code class="interfacename">AccessDecisionManager</code> interface contains three
+ methods:
+ </p><pre class="programlisting">
+ <span class="hl-keyword">void</span> decide(Authentication authentication, Object secureObject,
+ Collection<ConfigAttribute> attrs) <span class="hl-keyword">throws</span> AccessDeniedException;
+ <span class="hl-keyword">boolean</span> supports(ConfigAttribute attribute);
+ <span class="hl-keyword">boolean</span> supports(Class clazz);
</pre><p>
- The <code class="interfacename">AccessDecisionManager</code>'s <code class="methodname">decide</code>
- method is passed all the relevant information it needs in order to make an authorization
- decision. In particular, passing the secure <code class="literal">Object</code> enables those
- arguments contained in the actual secure object invocation to be inspected. For example,
- let's assume the secure object was a <code class="classname">MethodInvocation</code>. It would be
- easy to query the <code class="classname">MethodInvocation</code> for any
- <code class="literal">Customer</code> argument, and then implement some sort of security logic in
- the <code class="interfacename">AccessDecisionManager</code> to ensure the principal is
- permitted to operate on that customer. Implementations are expected to throw an
- <code class="literal">AccessDeniedException</code> if access is denied.</p><p>The <code class="literal">supports(ConfigAttribute)</code> method is called by the
- <code class="classname">AbstractSecurityInterceptor</code> at startup time to determine if the
- <code class="interfacename">AccessDecisionManager</code> can process the passed
- <code class="literal">ConfigAttribute</code>. The <code class="literal">supports(Class)</code> method is
- called by a security interceptor implementation to ensure the configured
- <code class="interfacename">AccessDecisionManager</code> supports the type of secure object
- that the security interceptor will present.</p></div><div class="section" title="13.2.2 Voting-Based AccessDecisionManager Implementations"><div class="titlepage"><div><div><h3 class="title"><a name="authz-voting-based"></a>13.2.2 Voting-Based AccessDecisionManager Implementations</h3></div></div></div><p>Whilst users can implement their own
- <code class="interfacename">AccessDecisionManager</code> to control all aspects of
- authorization, Spring Security includes several
- <code class="interfacename">AccessDecisionManager</code> implementations that are based on
- voting. <a class="xref" href="#authz-access-voting" title="Figure 13.1. Voting Decision Manager">Figure 13.1, “Voting Decision Manager”</a> illustrates the relevant classes.</p><div class="figure"><a name="authz-access-voting"></a><p class="title"><b>Figure 13.1. Voting Decision Manager</b></p><div class="figure-contents"><div class="mediaobject" align="center"><img src="images/access-decision-voting.png" align="middle" alt="Voting Decision Manager"></div></div></div><br class="figure-break"><p>Using this approach, a series of <code class="interfacename">AccessDecisionVoter</code>
- implementations are polled on an authorization decision. The
- <code class="interfacename">AccessDecisionManager</code> then decides whether or not to throw
- an <code class="literal">AccessDeniedException</code> based on its assessment of the votes.</p><p>The <code class="interfacename">AccessDecisionVoter</code> interface has three methods:
- </p><pre class="programlisting">
-int vote(Authentication authentication, Object object, List<ConfigAttribute> config);
-boolean supports(ConfigAttribute attribute);
-boolean supports(Class clazz);
+ The <code class="interfacename">AccessDecisionManager</code>'s
+ <code class="methodname">decide</code> method is passed all the relevant information it
+ needs in order to make an authorization decision. In particular, passing the secure
+ <code class="literal">Object</code> enables those arguments contained in the actual secure
+ object invocation to be inspected. For example, let's assume the secure object was a
+ <code class="classname">MethodInvocation</code>. It would be easy to query the
+ <code class="classname">MethodInvocation</code> for any <code class="literal">Customer</code>
+ argument, and then implement some sort of security logic in the
+ <code class="interfacename">AccessDecisionManager</code> to ensure the principal is
+ permitted to operate on that customer. Implementations are expected to throw an
+ <code class="literal">AccessDeniedException</code> if access is denied.</p><p>The <code class="literal">supports(ConfigAttribute)</code> method is called by the
+ <code class="classname">AbstractSecurityInterceptor</code> at startup time to determine if
+ the <code class="interfacename">AccessDecisionManager</code> can process the passed
+ <code class="literal">ConfigAttribute</code>. The <code class="literal">supports(Class)</code> method is
+ called by a security interceptor implementation to ensure the configured
+ <code class="interfacename">AccessDecisionManager</code> supports the type of secure
+ object that the security interceptor will present.</p></div><div class="section" title="14.2.2 Voting-Based AccessDecisionManager Implementations"><div class="titlepage"><div><div><h3 class="title"><a name="authz-voting-based"></a>14.2.2 Voting-Based AccessDecisionManager Implementations</h3></div></div></div><p>Whilst users can implement their own
+ <code class="interfacename">AccessDecisionManager</code> to control all aspects of
+ authorization, Spring Security includes several
+ <code class="interfacename">AccessDecisionManager</code> implementations that are based
+ on voting. <a class="xref" href="#authz-access-voting" title="Figure 14.1. Voting Decision Manager">Figure 14.1, “Voting Decision Manager”</a> illustrates the relevant
+ classes.</p><div class="figure"><a name="authz-access-voting"></a><p class="title"><b>Figure 14.1. Voting Decision Manager</b></p><div class="figure-contents"><div class="mediaobject" align="center"><img src="images/access-decision-voting.png" align="middle" alt="Voting Decision Manager"></div></div></div><br class="figure-break"><p>Using this approach, a series of
+ <code class="interfacename">AccessDecisionVoter</code> implementations are polled on an
+ authorization decision. The <code class="interfacename">AccessDecisionManager</code>
+ then decides whether or not to throw an <code class="literal">AccessDeniedException</code>
+ based on its assessment of the votes.</p><p>The <code class="interfacename">AccessDecisionVoter</code> interface has three
+ methods:
+ </p><pre class="programlisting">
+<span class="hl-keyword">int</span> vote(Authentication authentication, Object object, Collection<ConfigAttribute> attrs);
+<span class="hl-keyword">boolean</span> supports(ConfigAttribute attribute);
+<span class="hl-keyword">boolean</span> supports(Class clazz);
</pre><p>
- Concrete implementations return an <code class="literal">int</code>, with possible values being
- reflected in the <code class="interfacename">AccessDecisionVoter</code> static fields
- <code class="literal">ACCESS_ABSTAIN</code>, <code class="literal">ACCESS_DENIED</code> and
- <code class="literal">ACCESS_GRANTED</code>. A voting implementation will return
- <code class="literal">ACCESS_ABSTAIN</code> if it has no opinion on an authorization decision. If it
- does have an opinion, it must return either <code class="literal">ACCESS_DENIED</code> or
- <code class="literal">ACCESS_GRANTED</code>.</p><p>There are three concrete <code class="interfacename">AccessDecisionManager</code>s provided
- with Spring Security that tally the votes. The <code class="literal">ConsensusBased</code>
- implementation will grant or deny access based on the consensus of non-abstain votes.
- Properties are provided to control behavior in the event of an equality of votes or if all
- votes are abstain. The <code class="literal">AffirmativeBased</code> implementation will grant access
- if one or more <code class="literal">ACCESS_GRANTED</code> votes were received (i.e. a deny vote will
- be ignored, provided there was at least one grant vote). Like the
- <code class="literal">ConsensusBased</code> implementation, there is a parameter that controls the
- behavior if all voters abstain. The <code class="literal">UnanimousBased</code> provider expects
- unanimous <code class="literal">ACCESS_GRANTED</code> votes in order to grant access, ignoring
- abstains. It will deny access if there is any <code class="literal">ACCESS_DENIED</code> vote. Like
- the other implementations, there is a parameter that controls the behaviour if all voters
- abstain.</p><p>It is possible to implement a custom
- <code class="interfacename">AccessDecisionManager</code> that tallies votes differently. For
- example, votes from a particular <code class="interfacename">AccessDecisionVoter</code> might
- receive additional weighting, whilst a deny vote from a particular voter may have a veto
- effect.</p><div class="section" title="RoleVoter"><div class="titlepage"><div><div><h4 class="title"><a name="authz-role-voter"></a><code class="classname">RoleVoter</code></h4></div></div></div><p> The most commonly used <code class="interfacename">AccessDecisionVoter</code> provided
- with Spring Security is the simple <code class="classname">RoleVoter</code>, which treats
- configuration attributes as simple role names and votes to grant access if the user has
- been assigned that role.</p><p>It will vote if any <code class="interfacename">ConfigAttribute</code> begins with the
- prefix <code class="literal">ROLE_</code>. It will vote to grant access if there is a
- <code class="interfacename">GrantedAuthority</code> which returns a
- <code class="literal">String</code> representation (via the <code class="literal">getAuthority()</code>
- method) exactly equal to one or more <code class="literal">ConfigAttributes</code> starting with the
- prefix <code class="literal">ROLE_</code>. If there is no exact match of any
- <code class="literal">ConfigAttribute</code> starting with <code class="literal">ROLE_</code>, the
- <code class="literal">RoleVoter</code> will vote to deny access. If no
- <code class="literal">ConfigAttribute</code> begins with <code class="literal">ROLE_</code>, the voter will
- abstain.</p></div><div class="section" title="AuthenticatedVoter"><div class="titlepage"><div><div><h4 class="title"><a name="authz-authenticated-voter"></a><code class="classname">AuthenticatedVoter</code></h4></div></div></div><p> Another voter which we've implicitly seen is the
- <code class="classname">AuthenticatedVoter</code>, which can be used to differentiate between
- anonymous, fully-authenticated and remember-me authenticated users. Many sites allow
- certain limited access under remember-me authentication, but require a user to confirm
- their identity by logging in for full access.</p><p>When we've used the attribute <code class="literal">IS_AUTHENTICATED_ANONYMOUSLY</code> to grant
- anonymous access, this attribute was being processed by the
- <code class="classname">AuthenticatedVoter</code>. See the Javadoc for this class for more
- information. </p></div><div class="section" title="Custom Voters"><div class="titlepage"><div><div><h4 class="title"><a name="d0e4509"></a>Custom Voters</h4></div></div></div><p>It is also possible to implement a custom
- <code class="interfacename">AccessDecisionVoter</code>. Several examples are provided in
- Spring Security unit tests, including <code class="literal">ContactSecurityVoter</code> and
- <code class="literal">DenyVoter</code>. The <code class="literal">ContactSecurityVoter</code> abstains from
- voting decisions where a <code class="literal">CONTACT_OWNED_BY_CURRENT_USER</code>
- <code class="literal">ConfigAttribute</code> is not found. If voting, it queries the
- <code class="classname">MethodInvocation</code> to extract the owner of the
- <code class="literal">Contact</code> object that is subject of the method call. It votes to grant
- access if the <code class="literal">Contact</code> owner matches the principal presented in the
- <code class="interfacename">Authentication</code> object. It could have just as easily
- compared the <code class="literal">Contact</code> owner with some
- <code class="interfacename">GrantedAuthority</code> the
- <code class="interfacename">Authentication</code> object presented. All of this is achieved
- with relatively few lines of code and demonstrates the flexibility of the authorization
- model.</p></div></div></div><div class="section" title="13.3 After Invocation Handling"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="authz-after-invocation-handling"></a>13.3 After Invocation Handling</h2></div></div></div><p>Whilst the <code class="interfacename">AccessDecisionManager</code> is called by the
- <code class="classname">AbstractSecurityInterceptor</code> before proceeding with the secure object
- invocation, some applications need a way of modifying the object actually returned by the
- secure object invocation. Whilst you could easily implement your own AOP concern to achieve
- this, Spring Security provides a convenient hook that has several concrete implementations
- that integrate with its ACL capabilities.</p><p><a class="xref" href="#authz-after-invocation" title="Figure 13.2. After Invocation Implementation">Figure 13.2, “After Invocation Implementation”</a> illustrates Spring Security's
- <code class="literal">AfterInvocationManager</code> and its concrete implementations. </p><div class="figure"><a name="authz-after-invocation"></a><p class="title"><b>Figure 13.2. After Invocation Implementation</b></p><div class="figure-contents"><div class="mediaobject" align="center"><img src="images/after-invocation.png" align="middle" alt="After Invocation Implementation"></div></div></div><p><br class="figure-break"></p><p>Like many other parts of Spring Security, <code class="literal">AfterInvocationManager</code> has a
- single concrete implementation, <code class="literal">AfterInvocationProviderManager</code>, which polls
- a list of <code class="literal">AfterInvocationProvider</code>s. Each
- <code class="literal">AfterInvocationProvider</code> is allowed to modify the return object or throw
- an <code class="literal">AccessDeniedException</code>. Indeed multiple providers can modify the object,
- as the result of the previous provider is passed to the next in the list.</p><p>Please be aware that if you're using <code class="literal">AfterInvocationManager</code>, you will
- still need configuration attributes that allow the
- <code class="classname">MethodSecurityInterceptor</code>'s
- <code class="interfacename">AccessDecisionManager</code> to allow an operation. If you're using
- the typical Spring Security included <code class="interfacename">AccessDecisionManager</code>
- implementations, having no configuration attributes defined for a particular secure method
- invocation will cause each <code class="interfacename">AccessDecisionVoter</code> to abstain from
- voting. In turn, if the <code class="interfacename">AccessDecisionManager</code> property
- "<code class="literal">allowIfAllAbstainDecisions</code>" is <code class="literal">false</code>, an
- <code class="literal">AccessDeniedException</code> will be thrown. You may avoid this potential issue
- by either (i) setting "<code class="literal">allowIfAllAbstainDecisions</code>" to
- <code class="literal">true</code> (although this is generally not recommended) or (ii) simply ensure
- that there is at least one configuration attribute that an
- <code class="interfacename">AccessDecisionVoter</code> will vote to grant access for. This
- latter (recommended) approach is usually achieved through a <code class="literal">ROLE_USER</code> or
- <code class="literal">ROLE_AUTHENTICATED</code> configuration attribute.</p></div></div><div class="chapter" title="14. Secure Object Implementations"><div class="titlepage"><div><div><h1 class="title"><a name="secure-object-impls"></a>Secure Object Implementations</h1></div></div></div><div class="section" title="14.1 AOP Alliance (MethodInvocation) Security Interceptor"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="aop-alliance"></a>14.1 AOP Alliance (MethodInvocation) Security Interceptor</h2></div></div></div><p> Prior to Spring Security 2.0, securing <code class="classname">MethodInvocation</code>s needed
- quite a lot of boiler plate configuration. Now the recommended approach for method security is
- to use <a class="link" href="#ns-method-security" title="2.4 Method Security">namespace configuration</a>. This way the
- method security infrastructure beans are configured automatically for you so you don't really
- need to know about the implementation classes. We'll just provide a quick overview of the
- classes that are involved here. </p><p> Method security in enforced using a <code class="classname">MethodSecurityInterceptor</code>,
- which secures <code class="classname">MethodInvocation</code>s. Depending on the configuration
- approach, an interceptor may be specific to a single bean or shared between multiple beans.
- The interceptor uses a <code class="interfacename">MethodSecurityMetadataSource</code> instance to
- obtain the configuration attributes that apply to a particular method invocation.
- <code class="classname">MapBasedMethodSecurityMetadataSource</code> is used to store configuration
- attributes keyed by method names (which can be wildcarded) and will be used internally when
- the attributes are defined in the application context using the
- <code class="literal"><intercept-methods></code> or <code class="literal"><protect-point></code>
- elements. Other implementations will be used to handle annotation-based configuration. </p><div class="section" title="14.1.1 Explicit MethodSecurityInterceptor Configuration"><div class="titlepage"><div><div><h3 class="title"><a name="d0e4677"></a>14.1.1 Explicit MethodSecurityInterceptor Configuration</h3></div></div></div><p> You can of course configure a <code class="classname">MethodSecurityIterceptor</code> directly
- in your application context for use with one of Spring AOP's proxying mechanisms: </p><pre class="programlisting">
-<bean id="bankManagerSecurity"
- class="org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor">
- <property name="authenticationManager" ref="authenticationManager"/>
- <property name="accessDecisionManager" ref="accessDecisionManager"/>
- <property name="afterInvocationManager" ref="afterInvocationManager"/>
- <property name="securityMetadataSource">
- <value>
+ Concrete implementations return an <code class="literal">int</code>, with possible values
+ being reflected in the <code class="interfacename">AccessDecisionVoter</code> static
+ fields <code class="literal">ACCESS_ABSTAIN</code>, <code class="literal">ACCESS_DENIED</code> and
+ <code class="literal">ACCESS_GRANTED</code>. A voting implementation will return
+ <code class="literal">ACCESS_ABSTAIN</code> if it has no opinion on an authorization decision.
+ If it does have an opinion, it must return either <code class="literal">ACCESS_DENIED</code>
+ or <code class="literal">ACCESS_GRANTED</code>.</p><p>There are three concrete <code class="interfacename">AccessDecisionManager</code>s
+ provided with Spring Security that tally the votes. The
+ <code class="literal">ConsensusBased</code> implementation will grant or deny access based on
+ the consensus of non-abstain votes. Properties are provided to control behavior in
+ the event of an equality of votes or if all votes are abstain. The
+ <code class="literal">AffirmativeBased</code> implementation will grant access if one or more
+ <code class="literal">ACCESS_GRANTED</code> votes were received (i.e. a deny vote will be
+ ignored, provided there was at least one grant vote). Like the
+ <code class="literal">ConsensusBased</code> implementation, there is a parameter that controls
+ the behavior if all voters abstain. The <code class="literal">UnanimousBased</code> provider
+ expects unanimous <code class="literal">ACCESS_GRANTED</code> votes in order to grant access,
+ ignoring abstains. It will deny access if there is any
+ <code class="literal">ACCESS_DENIED</code> vote. Like the other implementations, there is a
+ parameter that controls the behaviour if all voters abstain.</p><p>It is possible to implement a custom
+ <code class="interfacename">AccessDecisionManager</code> that tallies votes differently.
+ For example, votes from a particular
+ <code class="interfacename">AccessDecisionVoter</code> might receive additional
+ weighting, whilst a deny vote from a particular voter may have a veto effect.</p><div class="section" title="RoleVoter"><div class="titlepage"><div><div><h4 class="title"><a name="authz-role-voter"></a><code class="classname">RoleVoter</code></h4></div></div></div><p> The most commonly used <code class="interfacename">AccessDecisionVoter</code>
+ provided with Spring Security is the simple <code class="classname">RoleVoter</code>,
+ which treats configuration attributes as simple role names and votes to grant
+ access if the user has been assigned that role.</p><p>It will vote if any <code class="interfacename">ConfigAttribute</code> begins with
+ the prefix <code class="literal">ROLE_</code>. It will vote to grant access if there is a
+ <code class="interfacename">GrantedAuthority</code> which returns a
+ <code class="literal">String</code> representation (via the
+ <code class="literal">getAuthority()</code> method) exactly equal to one or more
+ <code class="literal">ConfigAttributes</code> starting with the prefix
+ <code class="literal">ROLE_</code>. If there is no exact match of any
+ <code class="literal">ConfigAttribute</code> starting with <code class="literal">ROLE_</code>, the
+ <code class="literal">RoleVoter</code> will vote to deny access. If no
+ <code class="literal">ConfigAttribute</code> begins with <code class="literal">ROLE_</code>, the
+ voter will abstain.</p></div><div class="section" title="AuthenticatedVoter"><div class="titlepage"><div><div><h4 class="title"><a name="authz-authenticated-voter"></a><code class="classname">AuthenticatedVoter</code></h4></div></div></div><p> Another voter which we've implicitly seen is the
+ <code class="classname">AuthenticatedVoter</code>, which can be used to differentiate
+ between anonymous, fully-authenticated and remember-me authenticated users. Many
+ sites allow certain limited access under remember-me authentication, but require
+ a user to confirm their identity by logging in for full access.</p><p>When we've used the attribute <code class="literal">IS_AUTHENTICATED_ANONYMOUSLY</code>
+ to grant anonymous access, this attribute was being processed by the
+ <code class="classname">AuthenticatedVoter</code>. See the Javadoc for this class for
+ more information. </p></div><div class="section" title="Custom Voters"><div class="titlepage"><div><div><h4 class="title"><a name="authz-custom-voter"></a>Custom Voters</h4></div></div></div><p>Obviously, you can also implement a custom
+ <code class="interfacename">AccessDecisionVoter</code> and you can
+ put just about any access-control logic you want in it. It might
+ be specific to your application (business-logic related) or it
+ might implement some security administration logic. For example, you'll find
+ a <a class="link" href="http://blog.springsource.com/2009/01/02/spring-security-customization-part-2-adjusting-secured-session-in-real-time/" target="_top">
+ blog article</a> on the SpringSource web site which describes how to
+ use a voter to deny access in real-time to users whose accounts have
+ been suspended.
+ </p></div></div></div><div class="section" title="14.3 After Invocation Handling"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="authz-after-invocation-handling"></a>14.3 After Invocation Handling</h2></div></div></div><p>Whilst the <code class="interfacename">AccessDecisionManager</code> is called by the
+ <code class="classname">AbstractSecurityInterceptor</code> before proceeding with the secure
+ object invocation, some applications need a way of modifying the object actually
+ returned by the secure object invocation. Whilst you could easily implement your own AOP
+ concern to achieve this, Spring Security provides a convenient hook that has several
+ concrete implementations that integrate with its ACL capabilities.</p><p><a class="xref" href="#authz-after-invocation" title="Figure 14.2. After Invocation Implementation">Figure 14.2, “After Invocation Implementation”</a> illustrates Spring Security's
+ <code class="literal">AfterInvocationManager</code> and its concrete implementations. </p><div class="figure"><a name="authz-after-invocation"></a><p class="title"><b>Figure 14.2. After Invocation Implementation</b></p><div class="figure-contents"><div class="mediaobject" align="center"><img src="images/after-invocation.png" align="middle" alt="After Invocation Implementation"></div></div></div><p><br class="figure-break"></p><p>Like many other parts of Spring Security, <code class="literal">AfterInvocationManager</code>
+ has a single concrete implementation, <code class="literal">AfterInvocationProviderManager</code>,
+ which polls a list of <code class="literal">AfterInvocationProvider</code>s. Each
+ <code class="literal">AfterInvocationProvider</code> is allowed to modify the return object or
+ throw an <code class="literal">AccessDeniedException</code>. Indeed multiple providers can modify
+ the object, as the result of the previous provider is passed to the next in the
+ list.</p><p>Please be aware that if you're using <code class="literal">AfterInvocationManager</code>, you
+ will still need configuration attributes that allow the
+ <code class="classname">MethodSecurityInterceptor</code>'s
+ <code class="interfacename">AccessDecisionManager</code> to allow an operation. If you're
+ using the typical Spring Security included
+ <code class="interfacename">AccessDecisionManager</code> implementations, having no
+ configuration attributes defined for a particular secure method invocation will cause
+ each <code class="interfacename">AccessDecisionVoter</code> to abstain from voting. In turn,
+ if the <code class="interfacename">AccessDecisionManager</code> property
+ "<code class="literal">allowIfAllAbstainDecisions</code>" is <code class="literal">false</code>, an
+ <code class="literal">AccessDeniedException</code> will be thrown. You may avoid this potential
+ issue by either (i) setting "<code class="literal">allowIfAllAbstainDecisions</code>" to
+ <code class="literal">true</code> (although this is generally not recommended) or (ii) simply
+ ensure that there is at least one configuration attribute that an
+ <code class="interfacename">AccessDecisionVoter</code> will vote to grant access for. This
+ latter (recommended) approach is usually achieved through a <code class="literal">ROLE_USER</code>
+ or <code class="literal">ROLE_AUTHENTICATED</code> configuration attribute.</p></div><div class="section" title="14.4 Hierarchical Roles"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="authz-hierarchical-roles"></a>14.4 Hierarchical Roles</h2></div></div></div><p>
+ It is a common requirement that a particular role in an application should automatically
+ <span class="quote">“<span class="quote">include</span>”</span> other roles. For example, in an application which has the concept of
+ an <span class="quote">“<span class="quote">admin</span>”</span> and a <span class="quote">“<span class="quote">user</span>”</span> role, you may want an admin to be able to
+ do everything a normal user can. To achieve this, you can either make sure that all admin users
+ are also assigned the <span class="quote">“<span class="quote">user</span>”</span> role. Alternatively, you can modify every access constraint
+ which requires the <span class="quote">“<span class="quote">user</span>”</span> role to also include the <span class="quote">“<span class="quote">admin</span>”</span> role.
+ This can get quite complicated if you have a lot of different roles in your application.
+ </p><p>
+ The use of a role-hierarchy allows you to configure which roles (or authorities) should include others.
+ An extended version of Spring Security's <a class="link" href="#authz-role-voter" title="RoleVoter"><code class="classname">RoleVoter</code></a>,
+ <code class="classname">RoleHierarchyVoter</code>, is configured with a <code class="interfacename">RoleHierarchy</code>,
+ from which it obtains all the <span class="quote">“<span class="quote">reachable authorities</span>”</span> which the user is assigned.
+ A typical configuration might look like this:
+</p><pre class="programlisting">
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"roleVoter"</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.access.vote.RoleHierarchyVoter"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"roleHierarchy"</span><span class="hl-tag"> /></span>
+<span class="hl-tag"></class></span>
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"roleHierarchy"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"hierarchy"</span><span class="hl-tag">></span>
+ ROLE_ADMIN > ROLE_STAFF
+ ROLE_STAFF > ROLE_USER
+ ROLE_USER > ROLE_GUEST
+ <span class="hl-tag"></property></span>
+<span class="hl-tag"></bean></span>
+</pre><p>
+ Here we have four roles in a hierarchy <code class="literal">ROLE_ADMIN => ROLE_STAFF => ROLE_USER => ROLE_GUEST</code>.
+ A user who is authenticated with <code class="literal">ROLE_ADMIN</code>, will behave as if they have all four roles when
+ security contraints are evaluated against an <code class="interfacename">AccessDecisionManager</code> cconfigured
+ with the above <code class="classname">RoleHierarchyVoter</code>. The <code class="literal">></code> symbol can be thought of
+ as meaning <span class="quote">“<span class="quote">includes</span>”</span>.
+ </p><p>
+ Role hierarchies offer a convenient means of simplifying the access-control configuration data for your
+ application and/or reducing the number of authorities which you need to assign to a user. For more
+ complex requirements you may wish to define a logical mapping between the specific access-rights your
+ application requires and the roles that are assigned to users, translating between the two when loading
+ the user information.
+
+ </p></div></div><div class="chapter" title="15. Secure Object Implementations"><div class="titlepage"><div><div><h1 class="title"><a name="secure-object-impls"></a>Secure Object Implementations</h1></div></div></div><div class="section" title="15.1 AOP Alliance (MethodInvocation) Security Interceptor"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="aop-alliance"></a>15.1 AOP Alliance (MethodInvocation) Security Interceptor</h2></div></div></div><p> Prior to Spring Security 2.0, securing <code class="classname">MethodInvocation</code>s
+ needed quite a lot of boiler plate configuration. Now the recommended approach for
+ method security is to use <a class="link" href="#ns-method-security" title="3.4 Method Security">namespace
+ configuration</a>. This way the method security infrastructure beans are configured
+ automatically for you so you don't really need to know about the implementation classes.
+ We'll just provide a quick overview of the classes that are involved here. </p><p> Method security in enforced using a <code class="classname">MethodSecurityInterceptor</code>,
+ which secures <code class="classname">MethodInvocation</code>s. Depending on the configuration
+ approach, an interceptor may be specific to a single bean or shared between multiple
+ beans. The interceptor uses a
+ <code class="interfacename">MethodSecurityMetadataSource</code> instance to obtain the
+ configuration attributes that apply to a particular method invocation.
+ <code class="classname">MapBasedMethodSecurityMetadataSource</code> is used to store
+ configuration attributes keyed by method names (which can be wildcarded) and will be
+ used internally when the attributes are defined in the application context using the
+ <code class="literal"><intercept-methods></code> or <code class="literal"><protect-point></code>
+ elements. Other implementations will be used to handle annotation-based configuration. </p><div class="section" title="15.1.1 Explicit MethodSecurityInterceptor Configuration"><div class="titlepage"><div><div><h3 class="title"><a name="d0e5314"></a>15.1.1 Explicit MethodSecurityInterceptor Configuration</h3></div></div></div><p> You can of course configure a <code class="classname">MethodSecurityIterceptor</code>
+ directly in your application context for use with one of Spring AOP's proxying
+ mechanisms: </p><pre class="programlisting">
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"bankManagerSecurity"</span> <span class="hl-attribute">class</span>=
+ <span class="hl-value">"org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"authenticationManager"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"accessDecisionManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"accessDecisionManager"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"afterInvocationManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"afterInvocationManager"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"securityMetadataSource"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><value></span>
com.mycompany.BankManager.delete*=ROLE_SUPERVISOR
com.mycompany.BankManager.getBalance=ROLE_TELLER,ROLE_SUPERVISOR
- </value>
- </property>
-</bean>
-</pre></div></div><div class="section" title="14.2 AspectJ (JoinPoint) Security Interceptor"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="aspectj"></a>14.2 AspectJ (JoinPoint) Security Interceptor</h2></div></div></div><p>The AspectJ security interceptor is very similar to the AOP Alliance security interceptor
- discussed in the previous section. Indeed we will only discuss the differences in this
- section.</p><p>The AspectJ interceptor is named <code class="literal">AspectJSecurityInterceptor</code>. Unlike the
- AOP Alliance security interceptor, which relies on the Spring application context to weave in
- the security interceptor via proxying, the <code class="literal">AspectJSecurityInterceptor</code> is
- weaved in via the AspectJ compiler. It would not be uncommon to use both types of security
- interceptors in the same application, with <code class="literal">AspectJSecurityInterceptor</code> being
- used for domain object instance security and the AOP Alliance
- <code class="classname">MethodSecurityInterceptor</code> being used for services layer
- security.</p><p>Let's first consider how the <code class="literal">AspectJSecurityInterceptor</code> is configured
- in the Spring application context:</p><pre class="programlisting">
-<bean id="bankManagerSecurity"
- class="org.springframework.security.access.intercept.aspectj.AspectJSecurityInterceptor">
- <property name="authenticationManager" ref="authenticationManager"/>
- <property name="accessDecisionManager" ref="accessDecisionManager"/>
- <property name="afterInvocationManager" ref="afterInvocationManager"/>
- <property name="securityMetadataSource">
- <value>
+ <span class="hl-tag"></value></span>
+ <span class="hl-tag"></property></span>
+<span class="hl-tag"></bean></span>
+</pre></div></div><div class="section" title="15.2 AspectJ (JoinPoint) Security Interceptor"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="aspectj"></a>15.2 AspectJ (JoinPoint) Security Interceptor</h2></div></div></div><p>The AspectJ security interceptor is very similar to the AOP Alliance security
+ interceptor discussed in the previous section. Indeed we will only discuss the
+ differences in this section.</p><p>The AspectJ interceptor is named <code class="literal">AspectJSecurityInterceptor</code>. Unlike
+ the AOP Alliance security interceptor, which relies on the Spring application context to
+ weave in the security interceptor via proxying, the
+ <code class="literal">AspectJSecurityInterceptor</code> is weaved in via the AspectJ compiler. It
+ would not be uncommon to use both types of security interceptors in the same
+ application, with <code class="literal">AspectJSecurityInterceptor</code> being used for domain
+ object instance security and the AOP Alliance
+ <code class="classname">MethodSecurityInterceptor</code> being used for services layer
+ security.</p><p>Let's first consider how the <code class="literal">AspectJSecurityInterceptor</code> is
+ configured in the Spring application context:</p><pre class="programlisting">
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"bankManagerSecurity"</span> <span class="hl-attribute">class</span>=
+ <span class="hl-value">"org.springframework.security.access.intercept.aspectj.AspectJSecurityInterceptor"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"authenticationManager"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"accessDecisionManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"accessDecisionManager"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"afterInvocationManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"afterInvocationManager"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"securityMetadataSource"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><value></span>
com.mycompany.BankManager.delete*=ROLE_SUPERVISOR
com.mycompany.BankManager.getBalance=ROLE_TELLER,ROLE_SUPERVISOR
- </value>
-</property>
-</bean> </pre><p>As you can see, aside from the class name, the
- <code class="literal">AspectJSecurityInterceptor</code> is exactly the same as the AOP Alliance
- security interceptor. Indeed the two interceptors can share the same
- <code class="literal">securityMetadataSource</code>, as the
- <code class="interfacename">SecurityMetadataSource</code> works with
- <code class="literal">java.lang.reflect.Method</code>s rather than an AOP library-specific class. Of
- course, your access decisions have access to the relevant AOP library-specific invocation (ie
- <code class="classname">MethodInvocation</code> or <code class="literal">JoinPoint</code>) and as such can
- consider a range of addition criteria when making access decisions (such as method
- arguments).</p><p>Next you'll need to define an AspectJ <code class="literal">aspect</code>. For example:</p><pre class="programlisting">
+ <span class="hl-tag"></value></span>
+<span class="hl-tag"></property></span>
+<span class="hl-tag"></bean></span> </pre><p>As you can see, aside from the class name, the
+ <code class="literal">AspectJSecurityInterceptor</code> is exactly the same as the AOP Alliance
+ security interceptor. Indeed the two interceptors can share the same
+ <code class="literal">securityMetadataSource</code>, as the
+ <code class="interfacename">SecurityMetadataSource</code> works with
+ <code class="literal">java.lang.reflect.Method</code>s rather than an AOP library-specific class.
+ Of course, your access decisions have access to the relevant AOP library-specific
+ invocation (ie <code class="classname">MethodInvocation</code> or <code class="literal">JoinPoint</code>)
+ and as such can consider a range of addition criteria when making access decisions (such
+ as method arguments).</p><p>Next you'll need to define an AspectJ <code class="literal">aspect</code>. For example:</p><pre class="programlisting">
<span class="hl-keyword">package</span> org.springframework.security.samples.aspectj;
<span class="hl-keyword">import</span> org.springframework.security.access.intercept.aspectj.AspectJSecurityInterceptor;
@@ -2707,98 +2987,101 @@ boolean supports(Class clazz);
}
}
</pre><p>In the above example, the security interceptor will be applied to every instance of
- <code class="literal">PersistableEntity</code>, which is an abstract class not shown (you can use any
- other class or <code class="literal">pointcut</code> expression you like). For those curious,
- <code class="literal">AspectJCallback</code> is needed because the <code class="literal">proceed();</code>
- statement has special meaning only within an <code class="literal">around()</code> body. The
- <code class="literal">AspectJSecurityInterceptor</code> calls this anonymous
- <code class="literal">AspectJCallback</code> class when it wants the target object to continue.</p><p>You will need to configure Spring to load the aspect and wire it with the
- <code class="literal">AspectJSecurityInterceptor</code>. A bean declaration which achieves this is
- shown below:</p><pre class="programlisting">
-<bean id="domainObjectInstanceSecurityAspect"
- class="security.samples.aspectj.DomainObjectInstanceSecurityAspect"
- factory-method="aspectOf">
- <property name="securityInterceptor" ref="bankManagerSecurity"/>
-</bean>
+ <code class="literal">PersistableEntity</code>, which is an abstract class not shown (you can use
+ any other class or <code class="literal">pointcut</code> expression you like). For those curious,
+ <code class="literal">AspectJCallback</code> is needed because the <code class="literal">proceed();</code>
+ statement has special meaning only within an <code class="literal">around()</code> body. The
+ <code class="literal">AspectJSecurityInterceptor</code> calls this anonymous
+ <code class="literal">AspectJCallback</code> class when it wants the target object to
+ continue.</p><p>You will need to configure Spring to load the aspect and wire it with the
+ <code class="literal">AspectJSecurityInterceptor</code>. A bean declaration which achieves this is
+ shown below:</p><pre class="programlisting">
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"domainObjectInstanceSecurityAspect"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"security.samples.aspectj.DomainObjectInstanceSecurityAspect"</span>
+ <span class="hl-attribute">factory-method</span>=<span class="hl-value">"aspectOf"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"securityInterceptor"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"bankManagerSecurity"</span><span class="hl-tag">/></span>
+<span class="hl-tag"></bean></span>
</pre><p>That's it! Now you can create your beans from anywhere within your application, using
- whatever means you think fit (eg <code class="literal">new Person();</code>) and they will have the
- security interceptor applied.</p></div></div><div class="chapter" title="15. Expression-Based Access Control"><div class="titlepage"><div><div><h2 class="title"><a name="el-access"></a>15. Expression-Based Access Control</h2></div></div></div><p> Spring Security 3.0 introduced the ability to use Spring EL expressions as an
+ whatever means you think fit (eg <code class="literal">new Person();</code>) and they will have
+ the security interceptor applied.</p></div></div><div class="chapter" title="16. Expression-Based Access Control"><div class="titlepage"><div><div><h2 class="title"><a name="el-access"></a>16. Expression-Based Access Control</h2></div></div></div><p> Spring Security 3.0 introduced the ability to use Spring EL expressions as an
authorization mechanism in addition to the simple use of configuration attributes and
access-decision voters which have seen before. Expression-based access control is built on
the same architecture but allows complicated boolean logic to be encapsulated in a single
- expression.</p><div class="section" title="15.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e4781"></a>15.1 Overview</h2></div></div></div><p>Spring Security uses Spring EL for expression support and you should look at how that
+ expression.</p><div class="section" title="16.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e5418"></a>16.1 Overview</h2></div></div></div><p>Spring Security uses Spring EL for expression support and you should look at how that
works if you are interested in understanding the topic in more depth. Expressions are
evaluated with a <span class="quote">“<span class="quote">root object</span>”</span> as part of the evaluation context. Spring
Security uses specific classes for web and method security as the root object, in order
to provide built-in expressions and access to values such as the current
- principal.</p><div class="section" title="15.1.1 Common Built-In Expressions"><div class="titlepage"><div><div><h3 class="title"><a name="el-common-built-in"></a>15.1.1 Common Built-In Expressions</h3></div></div></div><p>The base class for expression root objects is
- <code class="classname">SecurityExpressionRoot</code>. This provides some common
- expressions which are available in both web and method security.</p><div class="table"><a name="d0e4797"></a><p class="title"><b>Table 15.1. Common built-in expressions</b></p><div class="table-contents"><table summary="Common built-in expressions" style="border: none;"><colgroup><col><col></colgroup><thead><tr><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; ">Expression</th><th style="border-bottom: 0.5pt solid ; ">Description</th></tr></thead><tbody><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">hasRole([role])</code></td><td style="border-bottom: 0.5pt solid ; ">Returns <code class="literal">true</code> if the current principal has the
+ principal.</p><div class="section" title="16.1.1 Common Built-In Expressions"><div class="titlepage"><div><div><h3 class="title"><a name="el-common-built-in"></a>16.1.1 Common Built-In Expressions</h3></div></div></div><p>The base class for expression root objects is
+ <code class="classname">SecurityExpressionRoot</code>. This provides some common expressions
+ which are available in both web and method security.</p><div class="table"><a name="d0e5434"></a><p class="title"><b>Table 16.1. Common built-in expressions</b></p><div class="table-contents"><table summary="Common built-in expressions" style="border: none;"><colgroup><col><col></colgroup><thead><tr><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; ">Expression</th><th style="border-bottom: 0.5pt solid ; ">Description</th></tr></thead><tbody><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">hasRole([role])</code></td><td style="border-bottom: 0.5pt solid ; ">Returns <code class="literal">true</code> if the current principal has the
specified role.</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">hasAnyRole([role1,role2])</code></td><td style="border-bottom: 0.5pt solid ; ">Returns <code class="literal">true</code> if the current principal has any
of the supplied roles (given as a comma-separated list of
strings)</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">principal</code></td><td style="border-bottom: 0.5pt solid ; ">Allows direct access to the principal object representing the
current user</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">authentication</code></td><td style="border-bottom: 0.5pt solid ; ">Allows direct access to the current
- <code class="interfacename">Authentication</code> object obtained
- from the <code class="interfacename">SecurityContext</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">permitAll</code></td><td style="border-bottom: 0.5pt solid ; ">Always evaluates to <code class="literal">true</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">denyAll</code></td><td style="border-bottom: 0.5pt solid ; ">Always evaluates to <code class="literal">false</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">isAnonymous()</code></td><td style="border-bottom: 0.5pt solid ; ">Returns <code class="literal">true</code> if the current principal is an
+ <code class="interfacename">Authentication</code> object obtained from
+ the <code class="interfacename">SecurityContext</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">permitAll</code></td><td style="border-bottom: 0.5pt solid ; ">Always evaluates to <code class="literal">true</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">denyAll</code></td><td style="border-bottom: 0.5pt solid ; ">Always evaluates to <code class="literal">false</code></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">isAnonymous()</code></td><td style="border-bottom: 0.5pt solid ; ">Returns <code class="literal">true</code> if the current principal is an
anonymous user</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">isRememberMe()</code></td><td style="border-bottom: 0.5pt solid ; ">Returns <code class="literal">true</code> if the current principal is a
remember-me user</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">isAuthenticated()</code></td><td style="border-bottom: 0.5pt solid ; ">Returns <code class="literal">true</code> if the user is not
anonymous</td></tr><tr><td style="border-right: 0.5pt solid ; "><code class="literal">isFullyAuthenticated()</code></td><td style="">Returns <code class="literal">true</code> if the user is not an anonymous
- or a remember-me user</td></tr></tbody></table></div></div><br class="table-break"></div></div><div class="section" title="15.2 Web Security Expressions"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="el-access-web"></a>15.2 Web Security Expressions</h2></div></div></div><p> To use expressions to secure individual URLs, you would first need to set the
- <code class="literal">use-expressions</code> attribute in the <code class="literal"><http></code>
- element to <code class="literal">true</code>. Spring Security will then expect the
- <code class="literal">access</code> attributes of the <code class="literal"><intercept-url></code>
+ or a remember-me user</td></tr></tbody></table></div></div><br class="table-break"></div></div><div class="section" title="16.2 Web Security Expressions"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="el-access-web"></a>16.2 Web Security Expressions</h2></div></div></div><p> To use expressions to secure individual URLs, you would first need to set the
+ <code class="literal">use-expressions</code> attribute in the <code class="literal"><http></code> element
+ to <code class="literal">true</code>. Spring Security will then expect the
+ <code class="literal">access</code> attributes of the <code class="literal"><intercept-url></code>
elements to contain Spring EL expressions. The expressions should evaluate to a boolean,
defining whether access should be allowed or not. For example:</p><pre class="programlisting">
- <http use-expressions="true">
- <intercept-url pattern="/admin*"
- access="hasRole('admin') and hasIpAddress('192.168.1.0/24')"/>
+ <span class="hl-tag"><http</span> <span class="hl-attribute">use-expressions</span>=<span class="hl-value">"true"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><intercept-url</span> <span class="hl-attribute">pattern</span>=<span class="hl-value">"/admin*"</span>
+ <span class="hl-attribute">access</span>=<span class="hl-value">"hasRole('admin') and hasIpAddress('192.168.1.0/24')"</span><span class="hl-tag">/></span>
...
- </http>
+ <span class="hl-tag"></http></span>
</pre><p>Here we have defined that the <span class="quote">“<span class="quote">admin</span>”</span> area of an application
(defined by the URL pattern) should only be available to users who have the granted
authority <span class="quote">“<span class="quote">admin</span>”</span> and whose IP address matches a local subnet. We've
already seen the built-in <code class="literal">hasRole</code> expression in the previous section.
The expression <code class="literal">hasIpAddress</code> is an additional built-in expression
which is specific to web security. It is defined by the
- <code class="classname">WebSecurityExpressionRoot</code> class, an instance of which is used
- as the expression root object when evaluation web-access expressions. This object also
+ <code class="classname">WebSecurityExpressionRoot</code> class, an instance of which is used as
+ the expression root object when evaluation web-access expressions. This object also
directly exposed the <code class="interfacename">HttpServletRequest</code> object under the
name <code class="literal">request</code> so you can invoke the request directly in an
expression.</p><p>If expressions are being used, a <code class="classname">WebExpressionVoter</code> will be
added to the <code class="interfacename">AccessDecisionManager</code> which is used by the
namespace. So if you aren't using the namespace and want to use expressions, you will
- have to add one of these to your configuration.</p></div><div class="section" title="15.3 Method Security Expressions"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e4949"></a>15.3 Method Security Expressions</h2></div></div></div><p>Method security is a bit more complicated than a simple allow or deny rule. Spring
+ have to add one of these to your configuration.</p></div><div class="section" title="16.3 Method Security Expressions"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e5586"></a>16.3 Method Security Expressions</h2></div></div></div><p>Method security is a bit more complicated than a simple allow or deny rule. Spring
Security 3.0 introduced some new annotations in order to allow comprehensive support for
- the use of expressions.</p><div class="section" title="15.3.1 @Pre and @Post Annotations"><div class="titlepage"><div><div><h3 class="title"><a name="el-pre-post-annotations"></a>15.3.1 <code class="literal">@Pre</code> and <code class="literal">@Post</code> Annotations</h3></div></div></div><p>There are four annotations which support expression attributes to allow pre and
+ the use of expressions.</p><div class="section" title="16.3.1 @Pre and @Post Annotations"><div class="titlepage"><div><div><h3 class="title"><a name="el-pre-post-annotations"></a>16.3.1 <code class="literal">@Pre</code> and <code class="literal">@Post</code> Annotations</h3></div></div></div><p>There are four annotations which support expression attributes to allow pre and
post-invocation authorization checks and also to support filtering of submitted
collection arguments or return values. They are <code class="literal">@PreAuthorize</code>,
- <code class="literal">@PreFilter</code>, <code class="literal">@PostAuthorize</code> and
- <code class="literal">@PostFilter</code>. Their use is enabled through the
- <code class="literal">global-method-security</code> namespace
- element:</p><pre class="programlisting"><global-method-security pre-post-annotations="enabled"/></pre><div class="section" title="Access Control using @PreAuthorize and @PostAuthorize"><div class="titlepage"><div><div><h4 class="title"><a name="d0e4981"></a>Access Control using <code class="literal">@PreAuthorize</code> and
- <code class="literal">@PostAuthorize</code></h4></div></div></div><p>The most obviously useful annotation is <code class="literal">@PreAuthorize</code> which
+ <code class="literal">@PreFilter</code>, <code class="literal">@PostAuthorize</code> and
+ <code class="literal">@PostFilter</code>. Their use is enabled through the
+ <code class="literal">global-method-security</code> namespace
+ element:</p><pre class="programlisting"><span class="hl-tag"><global-method-security</span> <span class="hl-attribute">pre-post-annotations</span>=<span class="hl-value">"enabled"</span><span class="hl-tag">/></span></pre><div class="section" title="Access Control using @PreAuthorize and @PostAuthorize"><div class="titlepage"><div><div><h4 class="title"><a name="d0e5618"></a>Access Control using <code class="literal">@PreAuthorize</code> and
+ <code class="literal">@PostAuthorize</code></h4></div></div></div><p>The most obviously useful annotation is <code class="literal">@PreAuthorize</code> which
decides whether a method can actually be invoked or not. For example (from the
- <span class="quote">“<span class="quote">Contacts</span>”</span> sample
- application)</p><pre class="programlisting"> @PreAuthorize("hasRole('ROLE_USER')")
- public void create(Contact contact);</pre><p>which
+ <span class="quote">“<span class="quote">Contacts</span>”</span> sample
+ application)</p><pre class="programlisting">
+ <i><span class="hl-annotation" style="color: gray">@PreAuthorize("hasRole('ROLE_USER')")</span></i>
+ <span class="hl-keyword">public</span> <span class="hl-keyword">void</span> create(Contact contact);</pre><p>which
means that access will only be allowed for users with the role "ROLE_USER".
Obviously the same thing could easily be achieved using a traditional
configuration and a simple configuration attribute for the required role. But
what
- about:</p><pre class="programlisting"> @PreAuthorize("hasPermission(#contact, 'admin')")
- public void deletePermission(Contact contact, Sid recipient, Permission permission);</pre><p>Here
+ about:</p><pre class="programlisting">
+ <i><span class="hl-annotation" style="color: gray">@PreAuthorize("hasPermission(#contact, 'admin')")</span></i>
+ <span class="hl-keyword">public</span> <span class="hl-keyword">void</span> deletePermission(Contact contact, Sid recipient, Permission permission);</pre><p>Here
we're actually using a method argument as part of the expression to decide
whether the current user has the <span class="quote">“<span class="quote">admin</span>”</span>permission for the given
contact. The built-in <code class="literal">hasPermission()</code> expression is linked
into the Spring Security ACL module through the application context, as we'll
- <a class="link" href="#el-permission-evaluator" title="The PermissionEvaluator interface">see below</a>. You can access
- any of the method arguments by name as expression variables, provided your code
- has debug information compiled in. Any Spring-EL functionality is available
- within the expression, so you can also access properties on the arguments. For
- example, if you wanted a particular method to only allow access to a user whose
- username matched that of the contact, you could write</p><pre class="programlisting">
- @PreAuthorize("#contact.name == authentication.name")
- public void doSomething(Contact contact);</pre><p>Here we are accessing another built–in expression, <code class="literal">authentication</code>,
+ <a class="link" href="#el-permission-evaluator" title="The PermissionEvaluator interface">see below</a>. You can access any
+ of the method arguments by name as expression variables, provided your code has
+ debug information compiled in. Any Spring-EL functionality is available within
+ the expression, so you can also access properties on the arguments. For example,
+ if you wanted a particular method to only allow access to a user whose username
+ matched that of the contact, you could write</p><pre class="programlisting">
+ <i><span class="hl-annotation" style="color: gray">@PreAuthorize("#contact.name == authentication.name")</span></i>
+ <span class="hl-keyword">public</span> <span class="hl-keyword">void</span> doSomething(Contact contact);</pre><p>Here we are accessing another built–in expression, <code class="literal">authentication</code>,
which is the <code class="interfacename">Authentication</code> stored in the
security context. You can also access its <span class="quote">“<span class="quote">principal</span>”</span> property
directly, using the expression <code class="literal">principal</code>. The value will
@@ -2806,15 +3089,15 @@ boolean supports(Class clazz);
expression like <code class="literal">principal.username</code> or
<code class="literal">principal.enabled</code>.</p><p>Less commonly, you may wish to perform an access-control check after the
method has been invoked. This can be achieved using the
- <code class="literal">@PostAuthorize</code> annotation. To access the return value
- from a method, use the built–in name <code class="literal">returnObject</code> in the
- expression.</p></div><div class="section" title="Filtering using @PreFilter and @PostFilter"><div class="titlepage"><div><div><h4 class="title"><a name="d0e5045"></a>Filtering using <code class="literal">@PreFilter</code> and
- <code class="literal">@PostFilter</code></h4></div></div></div><p>As you may already be aware, Spring Security supports filtering of collections
+ <code class="literal">@PostAuthorize</code> annotation. To access the return value from a
+ method, use the built–in name <code class="literal">returnObject</code> in the
+ expression.</p></div><div class="section" title="Filtering using @PreFilter and @PostFilter"><div class="titlepage"><div><div><h4 class="title"><a name="d0e5682"></a>Filtering using <code class="literal">@PreFilter</code> and
+ <code class="literal">@PostFilter</code></h4></div></div></div><p>As you may already be aware, Spring Security supports filtering of collections
and arrays and this can now be achieved using expressions. This is most commonly
performed on the return value of a method. For
- example:</p><pre class="programlisting"> @PreAuthorize("hasRole('ROLE_USER')")
- @PostFilter("hasPermission(filterObject, 'read') or hasPermission(filterObject, 'admin')")
- public List<Contact> getAll();</pre><p>When
+ example:</p><pre class="programlisting"> <i><span class="hl-annotation" style="color: gray">@PreAuthorize("hasRole('ROLE_USER')")</span></i>
+ <i><span class="hl-annotation" style="color: gray">@PostFilter("hasPermission(filterObject, 'read') or hasPermission(filterObject, 'admin')")</span></i>
+ <span class="hl-keyword">public</span> List<Contact> getAll();</pre><p>When
using the <code class="literal">@PostFilter</code> annotation, Spring Security iterates
through the returned collection and removes any elements for which the supplied
expression is false. The name <code class="literal">filterObject</code> refers to the
@@ -2822,21 +3105,25 @@ boolean supports(Class clazz);
using <code class="literal">@PreFilter</code>, though this is a less common requirement.
The syntax is just the same, but if there is more than one argument which is a
collection type then you have to select one by name using the
- <code class="literal">filterTarget</code> property of this annotation.</p><p>Note that filtering is obviously not a substitute for tuning your data
+ <code class="literal">filterTarget</code> property of this annotation.</p><p>Note that filtering is obviously not a substitute for tuning your data
retrieval queries. If you are filtering large collections and removing many of
- the entries then this is likely to be inefficient.</p></div></div><div class="section" title="15.3.2 Built-In Expressions"><div class="titlepage"><div><div><h3 class="title"><a name="el-method-built-in"></a>15.3.2 Built-In Expressions</h3></div></div></div><p>There are some built-in expressions which are specific to method security, which
+ the entries then this is likely to be inefficient.</p></div></div><div class="section" title="16.3.2 Built-In Expressions"><div class="titlepage"><div><div><h3 class="title"><a name="el-method-built-in"></a>16.3.2 Built-In Expressions</h3></div></div></div><p>There are some built-in expressions which are specific to method security, which
we have already seen in use above. The <code class="literal">filterTarget</code> and
- <code class="literal">returnValue</code> values are simple enough, but the use of the
- <code class="literal">hasPermission()</code> expression warrants a closer look.</p><div class="section" title="The PermissionEvaluator interface"><div class="titlepage"><div><div><h4 class="title"><a name="el-permission-evaluator"></a>The <code class="interfacename">PermissionEvaluator</code> interface</h4></div></div></div><p><code class="literal">hasPermission()</code> expressions are delegated to an instance of
- <code class="interfacename">PermissionEvaluator</code>. It is intended to bridge
+ <code class="literal">returnValue</code> values are simple enough, but the use of the
+ <code class="literal">hasPermission()</code> expression warrants a closer look.</p><div class="section" title="The PermissionEvaluator interface"><div class="titlepage"><div><div><h4 class="title"><a name="el-permission-evaluator"></a>The <code class="interfacename">PermissionEvaluator</code> interface</h4></div></div></div><p><code class="literal">hasPermission()</code> expressions are delegated to an instance of
+ <code class="interfacename">PermissionEvaluator</code>. It is intended to bridge
between the expression system and Spring Security's ACL system, allowing you to
specify authorization constraints on domain objects, based on abstract
permissions. It has no explicit dependencies on the ACL module, so you could
swap that out for an alternative implementation if required. The interface has
two methods:
- </p><pre class="programlisting"> <span class="hl-keyword">boolean</span> hasPermission(Authentication authentication, Object targetDomainObject, Object permission);
+ </p><pre class="programlisting">
+ <span class="hl-keyword">boolean</span> hasPermission(Authentication authentication, Object targetDomainObject,
+ Object permission);
- <span class="hl-keyword">boolean</span> hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission);</pre><p>which
+ <span class="hl-keyword">boolean</span> hasPermission(Authentication authentication, Serializable targetId,
+ String targetType, Object permission);
+</pre><p>which
map directly to the available versions of the expression, with the exception
that the first argument (the <code class="interfacename">Authentication</code>
object) is not supplied. The first is used in situations where the domain
@@ -2848,73 +3135,74 @@ boolean supports(Class clazz);
has traditionally been the Java class of the object, but does not have to be as
long as it is consistent with how the permissions are loaded.</p><p>To use <code class="literal">hasPermission()</code> expressions, you have to explicitly
configure a <code class="interfacename">PermissionEvaluator</code> in your
- application context. This would look something like this:</p><pre class="programlisting"> <span class="hl-tag"><security:global-method-security</span> <span class="hl-attribute">pre-post-annotations</span>=<span class="hl-value">"enabled"</span><span class="hl-tag">></span>
- <span class="hl-tag"><security:expression-handler</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"expressionHandler"</span><span class="hl-tag">/></span>
- <span class="hl-tag"></security:global-method-security></span>
+ application context. This would look something like this: </p><pre class="programlisting">
+<span class="hl-tag"><security:global-method-security</span> <span class="hl-attribute">pre-post-annotations</span>=<span class="hl-value">"enabled"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><security:expression-handler</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"expressionHandler"</span><span class="hl-tag">/></span>
+<span class="hl-tag"></security:global-method-security></span>
- <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"expressionHandler"</span>
- <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler"</span><span class="hl-tag">></span>
- <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"permissionEvaluator"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"myPermissionEvaluator"</span><span class="hl-tag">/></span>
- <span class="hl-tag"></bean></span></pre><p>Where <code class="literal">myPermissionEvaluator</code> is the bean which
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"expressionHandler"</span> <span class="hl-attribute">class</span>=
+ <span class="hl-value">"org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"permissionEvaluator"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"myPermissionEvaluator"</span><span class="hl-tag">/></span>
+<span class="hl-tag"></bean></span></pre><p>Where <code class="literal">myPermissionEvaluator</code> is the bean which
implements <code class="interfacename">PermissionEvaluator</code>. Usually this will
be the implementation from the ACL module which is called
- <code class="classname">AclPermissionEvaluator</code>. See the
- <span class="quote">“<span class="quote">Contacts</span>”</span> sample application configuration for more
- details.</p></div></div></div></div></div><div class="part" title="Part V. Additional Topics"><div class="titlepage"><div><div><h1 class="title"><a name="advanced-topics"></a>Part V. Additional Topics</h1></div></div></div><div class="partintro" title="Additional Topics"><div></div><p> In this part we cover features which require a knowledge of previous chapters as well
- as some of the more advanced and less-commonly used features of the framework.</p></div><div class="chapter" title="16. Domain Object Security (ACLs)"><div class="titlepage"><div><div><h1 class="title"><a name="domain-acls"></a>Domain Object Security (ACLs)</h1></div></div></div><div class="section" title="16.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="domain-acls-overview"></a>16.1 Overview</h2></div></div></div><p>Complex applications often will find the need to define access permissions not simply
+ <code class="classname">AclPermissionEvaluator</code>. See the <span class="quote">“<span class="quote">Contacts</span>”</span>
+ sample application configuration for more details.</p></div></div></div></div></div><div class="part" title="Part V. Additional Topics"><div class="titlepage"><div><div><h1 class="title"><a name="advanced-topics"></a>Part V. Additional Topics</h1></div></div></div><div class="partintro" title="Additional Topics"><div></div><p> In this part we cover features which require a knowledge of previous chapters as
+ well as some of the more advanced and less-commonly used features of the
+ framework.</p></div><div class="chapter" title="17. Domain Object Security (ACLs)"><div class="titlepage"><div><div><h1 class="title"><a name="domain-acls"></a>Domain Object Security (ACLs)</h1></div></div></div><div class="section" title="17.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="domain-acls-overview"></a>17.1 Overview</h2></div></div></div><p>Complex applications often will find the need to define access permissions not simply
at a web request or method invocation level. Instead, security decisions need to
comprise both who (<code class="interfacename">Authentication</code>), where
- (<code class="classname">MethodInvocation</code>) and what (<code class="literal">SomeDomainObject</code>). In
- other words, authorization decisions also need to consider the actual domain object
- instance subject of a method invocation.</p><p>Imagine you're designing an application for a pet clinic. There will be two main
+ (<code class="classname">MethodInvocation</code>) and what
+ (<code class="literal">SomeDomainObject</code>). In other words, authorization decisions also need
+ to consider the actual domain object instance subject of a method invocation.</p><p>Imagine you're designing an application for a pet clinic. There will be two main
groups of users of your Spring-based application: staff of the pet clinic, as well as
the pet clinic's customers. The staff will have access to all of the data, whilst your
customers will only be able to see their own customer records. To make it a little more
interesting, your customers can allow other users to see their customer records, such as
their "puppy preschool" mentor or president of their local "Pony Club". Using Spring
Security as the foundation, you have several approaches that can be used:</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>Write your business methods to enforce the security. You could consult a
- collection within the <code class="literal">Customer</code> domain object instance to
- determine which users have access. By using the
- <code class="literal">SecurityContextHolder.getContext().getAuthentication()</code>,
- you'll be able to access the <code class="interfacename">Authentication</code>
- object.</p></li><li class="listitem"><p>Write an <code class="interfacename">AccessDecisionVoter</code> to enforce the security
- from the <code class="literal">GrantedAuthority[]</code>s stored in the
- <code class="interfacename">Authentication</code> object. This would mean your
- <code class="interfacename">AuthenticationManager</code> would need to populate the
- <code class="interfacename">Authentication</code> with custom
- <code class="interfacename">GrantedAuthority</code>[]s representing each of the
- <code class="literal">Customer</code> domain object instances the principal has
- access to.</p></li><li class="listitem"><p>Write an <code class="interfacename">AccessDecisionVoter</code> to enforce the security
- and open the target <code class="literal">Customer</code> domain object directly. This
- would mean your voter needs access to a DAO that allows it to retrieve the
- <code class="literal">Customer</code> object. It would then access the
- <code class="literal">Customer</code> object's collection of approved users and
- make the appropriate decision.</p></li></ol></div><p>Each one of these approaches is perfectly legitimate. However, the first couples your
+ collection within the <code class="literal">Customer</code> domain object instance to
+ determine which users have access. By using the
+ <code class="literal">SecurityContextHolder.getContext().getAuthentication()</code>,
+ you'll be able to access the <code class="interfacename">Authentication</code>
+ object.</p></li><li class="listitem"><p>Write an <code class="interfacename">AccessDecisionVoter</code> to enforce the
+ security from the <code class="literal">GrantedAuthority[]</code>s stored in the
+ <code class="interfacename">Authentication</code> object. This would mean your
+ <code class="interfacename">AuthenticationManager</code> would need to populate the
+ <code class="interfacename">Authentication</code> with custom
+ <code class="interfacename">GrantedAuthority</code>[]s representing each of the
+ <code class="literal">Customer</code> domain object instances the principal has access
+ to.</p></li><li class="listitem"><p>Write an <code class="interfacename">AccessDecisionVoter</code> to enforce the
+ security and open the target <code class="literal">Customer</code> domain object directly.
+ This would mean your voter needs access to a DAO that allows it to retrieve the
+ <code class="literal">Customer</code> object. It would then access the
+ <code class="literal">Customer</code> object's collection of approved users and make the
+ appropriate decision.</p></li></ol></div><p>Each one of these approaches is perfectly legitimate. However, the first couples your
authorization checking to your business code. The main problems with this include the
enhanced difficulty of unit testing and the fact it would be more difficult to reuse the
- <code class="literal">Customer</code> authorization logic elsewhere. Obtaining the
- <code class="literal">GrantedAuthority[]</code>s from the <code class="interfacename">Authentication</code>
- object is also fine, but will not scale to large numbers of
- <code class="literal">Customer</code>s. If a user might be able to access 5,000
+ <code class="literal">Customer</code> authorization logic elsewhere. Obtaining the
+ <code class="literal">GrantedAuthority[]</code>s from the
+ <code class="interfacename">Authentication</code> object is also fine, but will not scale to
+ large numbers of <code class="literal">Customer</code>s. If a user might be able to access 5,000
<code class="literal">Customer</code>s (unlikely in this case, but imagine if it were a popular
vet for a large Pony Club!) the amount of memory consumed and time required to construct
- the <code class="interfacename">Authentication</code> object would be undesirable. The final method,
- opening the <code class="literal">Customer</code> directly from external code, is probably the
- best of the three. It achieves separation of concerns, and doesn't misuse memory or CPU
- cycles, but it is still inefficient in that both the
- <code class="interfacename">AccessDecisionVoter</code> and the eventual business method itself will
- perform a call to the DAO responsible for retrieving the <code class="literal">Customer</code>
- object. Two accesses per method invocation is clearly undesirable. In addition, with
- every approach listed you'll need to write your own access control list (ACL)
- persistence and business logic from scratch.</p><p>Fortunately, there is another alternative, which we'll talk about below.</p></div><div class="section" title="16.2 Key Concepts"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="domain-acls-key-concepts"></a>16.2 Key Concepts</h2></div></div></div><p>Spring Security's ACL services are shipped in the
+ the <code class="interfacename">Authentication</code> object would be undesirable. The final
+ method, opening the <code class="literal">Customer</code> directly from external code, is probably
+ the best of the three. It achieves separation of concerns, and doesn't misuse memory or
+ CPU cycles, but it is still inefficient in that both the
+ <code class="interfacename">AccessDecisionVoter</code> and the eventual business method
+ itself will perform a call to the DAO responsible for retrieving the
+ <code class="literal">Customer</code> object. Two accesses per method invocation is clearly
+ undesirable. In addition, with every approach listed you'll need to write your own
+ access control list (ACL) persistence and business logic from scratch.</p><p>Fortunately, there is another alternative, which we'll talk about below.</p></div><div class="section" title="17.2 Key Concepts"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="domain-acls-key-concepts"></a>17.2 Key Concepts</h2></div></div></div><p>Spring Security's ACL services are shipped in the
<code class="literal">spring-security-acl-xxx.jar</code>. You will need to add this JAR to your
classpath to use Spring Security's domain object instance security capabilities.</p><p>Spring Security's domain object instance security capabilities centre on the concept
of an access control list (ACL). Every domain object instance in your system has its own
ACL, and the ACL records details of who can and can't work with that domain object. With
this in mind, Spring Security delivers three main ACL-related capabilities to your application:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>A way of efficiently retrieving ACL entries for all of your domain objects
- (and modifying those ACLs)</p></li><li class="listitem"><p>A way of ensuring a given principal is permitted to work with your
- objects, before methods are called</p></li><li class="listitem"><p>A way of ensuring a given principal is permitted to work with your objects
- (or something they return), after methods are called</p></li></ul></div><p>As indicated by the first bullet point, one of the main capabilities of the Spring
+ (and modifying those ACLs)</p></li><li class="listitem"><p>A way of ensuring a given principal is permitted to work with your objects,
+ before methods are called</p></li><li class="listitem"><p>A way of ensuring a given principal is permitted to work with your objects (or
+ something they return), after methods are called</p></li></ul></div><p>As indicated by the first bullet point, one of the main capabilities of the Spring
Security ACL module is providing a high-performance way of retrieving ACLs. This ACL
repository capability is extremely important, because every domain object instance in
your system might have several access control entries, and each ACL might inherit from
@@ -2926,35 +3214,32 @@ boolean supports(Class clazz);
updating.</p><p>Given databases are central to the operation of the ACL module, let's explore the four
main tables used by default in the implementation. The tables are presented below in
order of size in a typical Spring Security ACL deployment, with the table with the most
- rows listed last:</p><p>
- </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>ACL_SID allows us to uniquely identify any principal or authority in the
- system ("SID" stands for "security identity"). The only columns are the ID,
- a textual representation of the SID, and a flag to indicate whether the
- textual representation refers to a principal name or a
- <code class="interfacename">GrantedAuthority</code>. Thus, there is a single row for
- each unique principal or <code class="interfacename">GrantedAuthority</code>. When used in
- the context of receiving a permission, a SID is generally called a
- "recipient".</p></li><li class="listitem"><p>ACL_CLASS allows us to uniquely identify any domain object class in the
- system. The only columns are the ID and the Java class name. Thus, there is
- a single row for each unique Class we wish to store ACL permissions
- for.</p></li><li class="listitem"><p>ACL_OBJECT_IDENTITY stores information for each unique domain object
- instance in the system. Columns include the ID, a foreign key to the
- ACL_CLASS table, a unique identifier so we know which ACL_CLASS instance
- we're providing information for, the parent, a foreign key to the ACL_SID
- table to represent the owner of the domain object instance, and whether we
- allow ACL entries to inherit from any parent ACL. We have a single row for
- every domain object instance we're storing ACL permissions for.</p></li><li class="listitem"><p>Finally, ACL_ENTRY stores the individual permissions assigned to each
- recipient. Columns include a foreign key to the ACL_OBJECT_IDENTITY, the
- recipient (ie a foreign key to ACL_SID), whether we'll be auditing or not,
- and the integer bit mask that represents the actual permission being granted
- or denied. We have a single row for every recipient that receives a
- permission to work with a domain object.</p></li></ul></div><p>
- </p><p>As mentioned in the last paragraph, the ACL system uses integer bit masking. Don't
+ rows listed last:</p><p> </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>ACL_SID allows us to uniquely identify any principal or authority in the
+ system ("SID" stands for "security identity"). The only columns are the ID, a
+ textual representation of the SID, and a flag to indicate whether the textual
+ representation refers to a principal name or a
+ <code class="interfacename">GrantedAuthority</code>. Thus, there is a single row for
+ each unique principal or <code class="interfacename">GrantedAuthority</code>. When
+ used in the context of receiving a permission, a SID is generally called a
+ "recipient".</p></li><li class="listitem"><p>ACL_CLASS allows us to uniquely identify any domain object class in the
+ system. The only columns are the ID and the Java class name. Thus, there is a
+ single row for each unique Class we wish to store ACL permissions for.</p></li><li class="listitem"><p>ACL_OBJECT_IDENTITY stores information for each unique domain object instance
+ in the system. Columns include the ID, a foreign key to the ACL_CLASS table, a
+ unique identifier so we know which ACL_CLASS instance we're providing
+ information for, the parent, a foreign key to the ACL_SID table to represent the
+ owner of the domain object instance, and whether we allow ACL entries to inherit
+ from any parent ACL. We have a single row for every domain object instance we're
+ storing ACL permissions for.</p></li><li class="listitem"><p>Finally, ACL_ENTRY stores the individual permissions assigned to each
+ recipient. Columns include a foreign key to the ACL_OBJECT_IDENTITY, the
+ recipient (ie a foreign key to ACL_SID), whether we'll be auditing or not, and
+ the integer bit mask that represents the actual permission being granted or
+ denied. We have a single row for every recipient that receives a permission to
+ work with a domain object.</p></li></ul></div><p> </p><p>As mentioned in the last paragraph, the ACL system uses integer bit masking. Don't
worry, you need not be aware of the finer points of bit shifting to use the ACL system,
but suffice to say that we have 32 bits we can switch on or off. Each of these bits
represents a permission, and by default the permissions are read (bit 0), write (bit 1),
create (bit 2), delete (bit 3) and administer (bit 4). It's easy to implement your own
- <code class="literal">Permission</code> instance if you wish to use other permissions, and the
+ <code class="literal">Permission</code> instance if you wish to use other permissions, and the
remainder of the ACL framework will operate without knowledge of your extensions.</p><p>It is important to understand that the number of domain objects in your system has
absolutely no bearing on the fact we've chosen to use integer bit masking. Whilst you
have 32 bits available for permissions, you could have billions of domain object
@@ -2964,29 +3249,29 @@ boolean supports(Class clazz);
looks like at a table structure, let's explore the key interfaces. The key interfaces
are:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc" compact><li class="listitem"><p><code class="literal">Acl</code>: Every domain object has one and only one
<code class="literal">Acl</code> object, which internally holds the
- <code class="literal">AccessControlEntry</code>s as well as knows the owner of the
- <code class="literal">Acl</code>. An Acl does not refer directly to the domain object,
- but instead to an <code class="literal">ObjectIdentity</code>. The <code class="literal">Acl</code>
- is stored in the ACL_OBJECT_IDENTITY table.</p></li><li class="listitem"><p><code class="literal">AccessControlEntry</code>: An <code class="literal">Acl</code> holds
+ <code class="literal">AccessControlEntry</code>s as well as knows the owner of the
+ <code class="literal">Acl</code>. An Acl does not refer directly to the domain object, but
+ instead to an <code class="literal">ObjectIdentity</code>. The <code class="literal">Acl</code> is
+ stored in the ACL_OBJECT_IDENTITY table.</p></li><li class="listitem"><p><code class="literal">AccessControlEntry</code>: An <code class="literal">Acl</code> holds
multiple <code class="literal">AccessControlEntry</code>s, which are often abbreviated as
ACEs in the framework. Each ACE refers to a specific tuple of
- <code class="literal">Permission</code>, <code class="literal">Sid</code> and
+ <code class="literal">Permission</code>, <code class="literal">Sid</code> and
<code class="literal">Acl</code>. An ACE can also be granting or non-granting and contain
audit settings. The ACE is stored in the ACL_ENTRY table.</p></li><li class="listitem"><p><code class="literal">Permission</code>: A permission represents a particular immutable
bit mask, and offers convenience functions for bit masking and outputting
information. The basic permissions presented above (bits 0 through 4) are
contained in the <code class="literal">BasePermission</code> class.</p></li><li class="listitem"><p><code class="literal">Sid</code>: The ACL module needs to refer to principals and
- <code class="literal">GrantedAuthority[]</code>s. A level of indirection is provided
- by the <code class="literal">Sid</code> interface, which is an abbreviation of "security
+ <code class="literal">GrantedAuthority[]</code>s. A level of indirection is provided by
+ the <code class="literal">Sid</code> interface, which is an abbreviation of "security
identity". Common classes include <code class="literal">PrincipalSid</code> (to represent
- the principal inside an <code class="interfacename">Authentication</code> object) and
- <code class="literal">GrantedAuthoritySid</code>. The security identity information is
+ the principal inside an <code class="interfacename">Authentication</code> object)
+ and <code class="literal">GrantedAuthoritySid</code>. The security identity information is
stored in the ACL_SID table.</p></li><li class="listitem"><p><code class="literal">ObjectIdentity</code>: Each domain object is represented
internally within the ACL module by an <code class="literal">ObjectIdentity</code>. The
default implementation is called <code class="literal">ObjectIdentityImpl</code>.</p></li><li class="listitem"><p><code class="literal">AclService</code>: Retrieves the <code class="literal">Acl</code> applicable
for a given <code class="literal">ObjectIdentity</code>. In the included implementation
- (<code class="literal">JdbcAclService</code>), retrieval operations are delegated to a
- <code class="literal">LookupStrategy</code>. The <code class="literal">LookupStrategy</code>
+ (<code class="literal">JdbcAclService</code>), retrieval operations are delegated to a
+ <code class="literal">LookupStrategy</code>. The <code class="literal">LookupStrategy</code>
provides a highly optimized strategy for retrieving ACL information, using
batched retrievals <code class="literal">(BasicLookupStrategy</code>) and supporting
custom implementations that leverage materialized views, hierarchical queries
@@ -2997,19 +3282,18 @@ boolean supports(Class clazz);
the system had been successfully tested using Hypersonic SQL, PostgreSQL, Microsoft SQL
Server and Oracle.</p><p>Two samples ship with Spring Security that demonstrate the ACL module. The first is
the Contacts Sample, and the other is the Document Management System (DMS) Sample. We
- suggest taking a look over these for examples.</p></div><div class="section" title="16.3 Getting Started"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="domain-acls-getting-started"></a>16.3 Getting Started</h2></div></div></div><p>To get starting using Spring Security's ACL capability, you will need to store your
+ suggest taking a look over these for examples.</p></div><div class="section" title="17.3 Getting Started"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="domain-acls-getting-started"></a>17.3 Getting Started</h2></div></div></div><p>To get starting using Spring Security's ACL capability, you will need to store your
ACL information somewhere. This necessitates the instantiation of a
<code class="literal">DataSource</code> using Spring. The <code class="literal">DataSource</code> is then
injected into a <code class="literal">JdbcMutableAclService</code> and
- <code class="literal">BasicLookupStrategy</code> instance. The latter provides
- high-performance ACL retrieval capabilities, and the former provides mutator
- capabilities. Refer to one of the samples that ship with Spring Security for an example
- configuration. You'll also need to populate the database with the four ACL-specific
- tables listed in the last section (refer to the ACL samples for the appropriate SQL
- statements).</p><p>Once you've created the required schema and instantiated
- <code class="literal">JdbcMutableAclService</code>, you'll next need to ensure your domain
- model supports interoperability with the Spring Security ACL package. Hopefully
- <code class="literal">ObjectIdentityImpl</code> will prove sufficient, as it provides a large
+ <code class="literal">BasicLookupStrategy</code> instance. The latter provides high-performance
+ ACL retrieval capabilities, and the former provides mutator capabilities. Refer to one
+ of the samples that ship with Spring Security for an example configuration. You'll also
+ need to populate the database with the four ACL-specific tables listed in the last
+ section (refer to the ACL samples for the appropriate SQL statements).</p><p>Once you've created the required schema and instantiated
+ <code class="literal">JdbcMutableAclService</code>, you'll next need to ensure your domain model
+ supports interoperability with the Spring Security ACL package. Hopefully
+ <code class="literal">ObjectIdentityImpl</code> will prove sufficient, as it provides a large
number of ways in which it can be used. Most people will have domain objects that
contain a <code class="literal">public Serializable getId()</code> method. If the return type is
long, or compatible with long (eg an int), you will find you need not give further
@@ -3020,20 +3304,20 @@ boolean supports(Class clazz);
compatible with all database sequences, the most common identifier data type, and are of
sufficient length to accommodate all common usage scenarios.</p><p>The following fragment of code shows how to create an <code class="literal">Acl</code>, or
modify an existing
- <code class="literal">Acl</code>:</p><pre class="programlisting">// Prepare the information we'd like in our access control entry (ACE)
-ObjectIdentity oi = new ObjectIdentityImpl(Foo.class, new Long(44));
-Sid sid = new PrincipalSid("Samantha");
+ <code class="literal">Acl</code>:</p><pre class="programlisting"><span class="hl-comment">// Prepare the information we'd like in our access control entry (ACE)</span>
+ObjectIdentity oi = <span class="hl-keyword">new</span> ObjectIdentityImpl(Foo.<span class="hl-keyword">class</span>, <span class="hl-keyword">new</span> Long(<span class="hl-number">44</span>));
+Sid sid = <span class="hl-keyword">new</span> PrincipalSid(<span class="hl-string">"Samantha"</span>);
Permission p = BasePermission.ADMINISTRATION;
-// Create or update the relevant ACL
+<span class="hl-comment">// Create or update the relevant ACL</span>
MutableAcl acl = null;
-try {
+<span class="hl-keyword">try</span> {
acl = (MutableAcl) aclService.readAclById(oi);
-} catch (NotFoundException nfe) {
+} <span class="hl-keyword">catch</span> (NotFoundException nfe) {
acl = aclService.createAcl(oi);
}
-// Now grant some permissions via an access control entry (ACE)
+<span class="hl-comment">// Now grant some permissions via an access control entry (ACE)</span>
acl.insertAce(acl.getEntries().length, p, sid, true);
aclService.updateAcl(acl);
</pre><p>In the example above, we're retrieving the ACL associated with the "Foo" domain object
@@ -3043,7 +3327,8 @@ aclService.updateAcl(acl);
position in the Acl the new entry will be inserted. In the example above, we're just
putting the new ACE at the end of the existing ACEs. The final argument is a boolean
indicating whether the ACE is granting or denying. Most of the time it will be granting
- (true), but if it is denying (false), the permissions are effectively being blocked.</p><p>Spring Security does not provide any special integration to automatically create,
+ (true), but if it is denying (false), the permissions are effectively being
+ blocked.</p><p>Spring Security does not provide any special integration to automatically create,
update or delete ACLs as part of your DAO or repository operations. Instead, you will
need to write code like shown above for your individual domain objects. It's worth
considering using AOP on your services layer to automatically integrate the ACL
@@ -3051,369 +3336,369 @@ aclService.updateAcl(acl);
approach in the past.</p><p>Once you've used the above techniques to store some ACL information in the database,
the next step is to actually use the ACL information as part of authorization decision
logic. You have a number of choices here. You could write your own
- <code class="interfacename">AccessDecisionVoter</code> or <code class="literal">AfterInvocationProvider</code>
- that respectively fires before or after a method invocation. Such classes would use
- <code class="literal">AclService</code> to retrieve the relevant ACL and then call
- <code class="literal">Acl.isGranted(Permission[] permission, Sid[] sids, boolean
- administrativeMode)</code> to decide whether permission is granted or denied.
+ <code class="interfacename">AccessDecisionVoter</code> or
+ <code class="literal">AfterInvocationProvider</code> that respectively fires before or after a
+ method invocation. Such classes would use <code class="literal">AclService</code> to retrieve the
+ relevant ACL and then call <code class="literal">Acl.isGranted(Permission[] permission, Sid[] sids,
+ boolean administrativeMode)</code> to decide whether permission is granted or denied.
Alternately, you could use our <code class="literal">AclEntryVoter</code>,
- <code class="literal">AclEntryAfterInvocationProvider</code> or
- <code class="literal">AclEntryAfterInvocationCollectionFilteringProvider</code> classes. All
- of these classes provide a declarative-based approach to evaluating ACL information at
+ <code class="literal">AclEntryAfterInvocationProvider</code> or
+ <code class="literal">AclEntryAfterInvocationCollectionFilteringProvider</code> classes. All of
+ these classes provide a declarative-based approach to evaluating ACL information at
runtime, freeing you from needing to write any code. Please refer to the sample
- applications to learn how to use these classes.</p></div></div><div class="chapter" title="17. Pre-Authentication Scenarios"><div class="titlepage"><div><div><h1 class="title"><a name="preauth"></a>Pre-Authentication Scenarios</h1></div></div></div><p> There are situations where you want to use Spring Security for authorization, but the user
- has already been reliably authenticated by some external system prior to accessing the
- application. We refer to these situations as <span class="quote">“<span class="quote">pre-authenticated</span>”</span> scenarios.
- Examples include X.509, Siteminder and authentication by the J2EE container in which the
- application is running. When using pre-authentication, Spring Security has to
- </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>Identify the user making the request.
- </p></li><li class="listitem"><p>Obtain the authorities for the
- user.</p></li></ol></div><p>The details will depend on the external authentication
- mechanism. A user might be identified by their certificate information in the case of X.509, or
- by an HTTP request header in the case of Siteminder. If relying on container authentication, the
- user will be identified by calling the <code class="methodname">getUserPrincipal()</code> method on the
- incoming HTTP request. In some cases, the external mechanism may supply role/authority
- information for the user but in others the authorities must be obtained from a separate source,
- such as a <code class="interfacename">UserDetailsService</code>. </p><div class="section" title="17.1 Pre-Authentication Framework Classes"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e5505"></a>17.1 Pre-Authentication Framework Classes</h2></div></div></div><p> Because most pre-authentication mechanisms follow the same pattern, Spring Security has a
- set of classes which provide an internal framework for implementing pre-authenticated
- authentication providers. This removes duplication and allows new implementations to be added
- in a structured fashion, without having to write everything from scratch. You don't need to
- know about these classes if you want to use something like <a class="link" href="#x509" title="22. X.509 Authentication">X.509
- authentication</a>, as it already has a namespace configuration option which is simpler
- to use and get started with. If you need to use explicit bean configuration or are planning on
- writing your own implementation then an understanding of how the provided implementations work
- will be useful. You will find classes under the
- <span class="package">org.springframework.security.web.authentication.preauth</span>. We just provide
- an outline here so you should consult the Javadoc and source where appropriate. </p><div class="section" title="17.1.1 AbstractPreAuthenticatedProcessingFilter"><div class="titlepage"><div><div><h3 class="title"><a name="d0e5516"></a>17.1.1 AbstractPreAuthenticatedProcessingFilter</h3></div></div></div><p> This class will check the current contents of the security context and, if empty, it
- will attempt to extract user information from the HTTP request and submit it to the
- <code class="interfacename">AuthenticationManager</code>. Subclasses override the following
- methods to obtain this information:
- </p><pre class="programlisting">
+ applications to learn how to use these classes.</p></div></div><div class="chapter" title="18. Pre-Authentication Scenarios"><div class="titlepage"><div><div><h1 class="title"><a name="preauth"></a>Pre-Authentication Scenarios</h1></div></div></div><p> There are situations where you want to use Spring Security for authorization, but the
+ user has already been reliably authenticated by some external system prior to accessing the
+ application. We refer to these situations as <span class="quote">“<span class="quote">pre-authenticated</span>”</span> scenarios.
+ Examples include X.509, Siteminder and authentication by the J2EE container in which the
+ application is running. When using pre-authentication, Spring Security has to </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>Identify the user making the request. </p></li><li class="listitem"><p>Obtain the authorities for the user.</p></li></ol></div><p>The details will depend on the external authentication mechanism. A user might
+ be identified by their certificate information in the case of X.509, or by an HTTP request
+ header in the case of Siteminder. If relying on container authentication, the user will be
+ identified by calling the <code class="methodname">getUserPrincipal()</code> method on the incoming
+ HTTP request. In some cases, the external mechanism may supply role/authority information
+ for the user but in others the authorities must be obtained from a separate source, such as
+ a <code class="interfacename">UserDetailsService</code>. </p><div class="section" title="18.1 Pre-Authentication Framework Classes"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e6142"></a>18.1 Pre-Authentication Framework Classes</h2></div></div></div><p> Because most pre-authentication mechanisms follow the same pattern, Spring Security
+ has a set of classes which provide an internal framework for implementing
+ pre-authenticated authentication providers. This removes duplication and allows new
+ implementations to be added in a structured fashion, without having to write everything
+ from scratch. You don't need to know about these classes if you want to use something
+ like <a class="link" href="#x509" title="23. X.509 Authentication">X.509 authentication</a>, as it already has a namespace
+ configuration option which is simpler to use and get started with. If you need to use
+ explicit bean configuration or are planning on writing your own implementation then an
+ understanding of how the provided implementations work will be useful. You will find
+ classes under the
+ <span class="package">org.springframework.security.web.authentication.preauth</span>. We just
+ provide an outline here so you should consult the Javadoc and source where appropriate. </p><div class="section" title="18.1.1 AbstractPreAuthenticatedProcessingFilter"><div class="titlepage"><div><div><h3 class="title"><a name="d0e6153"></a>18.1.1 AbstractPreAuthenticatedProcessingFilter</h3></div></div></div><p> This class will check the current contents of the security context and, if empty,
+ it will attempt to extract user information from the HTTP request and submit it to
+ the <code class="interfacename">AuthenticationManager</code>. Subclasses override the
+ following methods to obtain this information:
+ </p><pre class="programlisting">
<span class="hl-keyword">protected</span> <span class="hl-keyword">abstract</span> Object getPreAuthenticatedPrincipal(HttpServletRequest request);
<span class="hl-keyword">protected</span> <span class="hl-keyword">abstract</span> Object getPreAuthenticatedCredentials(HttpServletRequest request);
</pre><p>
- After calling these, the filter will create a
- <code class="classname">PreAuthenticatedAuthenticationToken</code> containing the returned data
- and submit it for authentication. By <span class="quote">“<span class="quote">authentication</span>”</span> here, we really just mean
- further processing to perhaps load the user's authorities, but the standard Spring Security
- authentication architecture is followed. </p></div><div class="section" title="17.1.2 AbstractPreAuthenticatedAuthenticationDetailsSource"><div class="titlepage"><div><div><h3 class="title"><a name="d0e5533"></a>17.1.2 AbstractPreAuthenticatedAuthenticationDetailsSource</h3></div></div></div><p> Like other Spring Security authentication filters, the pre-authentication filter has an
- <code class="literal">authenticationDetailsSource</code> property which by default will create a
- <code class="classname">WebAuthenticationDetails</code> object to store additional information
- such as the session-identifier and originating IP address in the <code class="literal">details</code>
- property of the <code class="interfacename">Authentication</code> object. In cases where user
- role information can be obtained from the pre-authentication mechanism, the data is also
- stored in this property. Subclasses of
- <code class="classname">AbstractPreAuthenticatedAuthenticationDetailsSource</code> use an extended
- details object which implements the
- <code class="interfacename">GrantedAuthoritiesContainer</code> interface, thus enabling the
- authentication provider to read the authorities which were externally allocated to the user.
- We'll look at a concrete example next. </p><div class="section" title="J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource"><div class="titlepage"><div><div><h4 class="title"><a name="j2ee-preauth-details"></a>J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource</h4></div></div></div><p> If the filter is configured with an <code class="literal">authenticationDetailsSource</code>
- which is an instance of this class, the authority information is obtained by calling the
- <code class="methodname">isUserInRole(String role)</code> method for each of a pre-determined
- set of <span class="quote">“<span class="quote">mappable roles</span>”</span>. The class gets these from a configured
- <code class="interfacename">MappableAttributesRetriever</code>. Possible implementations
- include hard-coding a list in the application context and reading the role information
- from the <code class="literal"><security-role></code> information in a
- <code class="filename">web.xml</code> file. The pre-authentication sample application uses the
- latter approach. </p><p>There is an additional stage where the roles (or attributes) are mapped to Spring
- Security <code class="interfacename">GrantedAuthority</code> objects using a configured
- <code class="interfacename">Attributes2GrantedAuthoritiesMapper</code>. The default will
- just add the usual <code class="literal">ROLE_</code> prefix to the names, but it gives you full
- control over the behaviour. </p></div></div><div class="section" title="17.1.3 PreAuthenticatedAuthenticationProvider"><div class="titlepage"><div><div><h3 class="title"><a name="d0e5590"></a>17.1.3 PreAuthenticatedAuthenticationProvider</h3></div></div></div><p> The pre-authenticated provider has little more to do than load the
- <code class="interfacename">UserDetails</code> object for the user. It does this by delegating
- to a <code class="interfacename">AuthenticationUserDetailsService</code>. The latter is similar
- to the standard <code class="interfacename">UserDetailsService</code> but takes an
- <code class="interfacename">Authentication</code> object rather than just user name:
- </p><pre class="programlisting">
+ After calling these, the filter will create a
+ <code class="classname">PreAuthenticatedAuthenticationToken</code> containing the returned
+ data and submit it for authentication. By <span class="quote">“<span class="quote">authentication</span>”</span> here, we
+ really just mean further processing to perhaps load the user's authorities, but the
+ standard Spring Security authentication architecture is followed. </p><p> Like other Spring Security authentication filters, the pre-authentication filter
+ has an <code class="literal">authenticationDetailsSource</code> property which by default will
+ create a <code class="classname">WebAuthenticationDetails</code> object to store additional
+ information such as the session-identifier and originating IP address in the
+ <code class="literal">details</code> property of the
+ <code class="interfacename">Authentication</code> object. In cases where user role
+ information can be obtained from the pre-authentication mechanism, the data is also
+ stored in this property, with the details implementing the
+ <code class="interfacename">GrantedAuthoritiesContainer</code> interface. This
+ enables the authentication provider to read the authorities which were externally
+ allocated to the user. We'll look at a concrete example next. </p><div class="section" title="J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource"><div class="titlepage"><div><div><h4 class="title"><a name="j2ee-preauth-details"></a>J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource</h4></div></div></div><p> If the filter is configured with an
+ <code class="literal">authenticationDetailsSource</code> which is an instance of this
+ class, the authority information is obtained by calling the
+ <code class="methodname">isUserInRole(String role)</code> method for each of a
+ pre-determined set of <span class="quote">“<span class="quote">mappable roles</span>”</span>. The class gets these from a
+ configured <code class="interfacename">MappableAttributesRetriever</code>. Possible
+ implementations include hard-coding a list in the application context and
+ reading the role information from the <code class="literal"><security-role></code>
+ information in a <code class="filename">web.xml</code> file. The pre-authentication
+ sample application uses the latter approach.</p><p>There is an additional stage where the roles (or attributes) are mapped to
+ Spring Security <code class="interfacename">GrantedAuthority</code> objects using a
+ configured <code class="interfacename">Attributes2GrantedAuthoritiesMapper</code>.
+ The default will just add the usual <code class="literal">ROLE_</code> prefix to the
+ names, but it gives you full control over the behaviour. </p></div></div><div class="section" title="18.1.2 PreAuthenticatedAuthenticationProvider"><div class="titlepage"><div><div><h3 class="title"><a name="d0e6221"></a>18.1.2 PreAuthenticatedAuthenticationProvider</h3></div></div></div><p> The pre-authenticated provider has little more to do than load the
+ <code class="interfacename">UserDetails</code> object for the user. It does this by
+ delegating to a <code class="interfacename">AuthenticationUserDetailsService</code>. The
+ latter is similar to the standard <code class="interfacename">UserDetailsService</code>
+ but takes an <code class="interfacename">Authentication</code> object rather than just
+ user name:
+ </p><pre class="programlisting">
<span class="hl-keyword">public</span> <span class="hl-keyword">interface</span> AuthenticationUserDetailsService {
UserDetails loadUserDetails(Authentication token) <span class="hl-keyword">throws</span> UsernameNotFoundException;
}
</pre><p>
- This interface may have also other uses but with pre-authentication it allows access to the
- authorities which were packaged in the <code class="interfacename">Authentication</code> object,
- as we saw in the previous section. The
- <code class="classname">PreAuthenticatedGrantedAuthoritiesUserDetailsService</code> class does
- this. Alternatively, it may delegate to a standard
- <code class="interfacename">UserDetailsService</code> via the
- <code class="classname">UserDetailsByNameServiceWrapper</code> implementation. </p></div><div class="section" title="17.1.4 Http403ForbiddenEntryPoint"><div class="titlepage"><div><div><h3 class="title"><a name="d0e5622"></a>17.1.4 Http403ForbiddenEntryPoint</h3></div></div></div><p> The <code class="interfacename">AuthenticationEntryPoint</code> was discussed in the <a class="link" href="#tech-intro-auth-entry-point" title="5.4.2 AuthenticationEntryPoint">technical overview</a> chapter. Normally it
- is responsible for kick-starting the authentication process for an unauthenticated user
- (when they try to access a protected resource), but in the pre-authenticated case this
- doesn't apply. You would only configure the
- <code class="classname">ExceptionTranslationFilter</code> with an instance of this class if you
- aren't using pre-authentication in combination with other authentication mechanisms. It will
- be called if the user is rejected by the
- <code class="classname">AbstractPreAuthenticatedProcessingFilter</code> resulting in a null
- authentication. It always returns a <code class="literal">403</code>-forbidden response code if
- called. </p></div></div><div class="section" title="17.2 Concrete Implementations"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e5642"></a>17.2 Concrete Implementations</h2></div></div></div><p> X.509 authentication is covered in its <a class="link" href="#x509" title="22. X.509 Authentication">own chapter</a>. Here
- we'll look at some classes which provide support for other pre-authenticated scenarios. </p><div class="section" title="17.2.1 Request-Header Authentication (Siteminder)"><div class="titlepage"><div><div><h3 class="title"><a name="d0e5650"></a>17.2.1 Request-Header Authentication (Siteminder)</h3></div></div></div><p> An external authentication system may supply information to the application by setting
- specific headers on the HTTP request. A well known example of this is Siteminder, which
- passes the username in a header called <code class="literal">SM_USER</code>. This mechanism is
- supported by the class <code class="classname">RequestHeaderAuthenticationFilter</code> which simply
- extracts the username from the header. It defaults to using the name
- <code class="literal">SM_USER</code> as the header name. See the Javadoc for more details. </p><div class="tip" title="Tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>Note that when using a system like this, the framework performs no authentication
- checks at all and it is <span class="emphasis"><em>extremely</em></span> important that the external system
- is configured properly and protects all access to the application. If an attacker is able
- to forge the headers in their original request without this being detected then they could
- potentially choose any username they wished. </p></td></tr></table></div><div class="section" title="Siteminder Example Configuration"><div class="titlepage"><div><div><h4 class="title"><a name="d0e5670"></a>Siteminder Example Configuration</h4></div></div></div><p> A typical configuration using this filter would look like this: </p><pre class="programlisting">
- <security:http>
- <!-- Additional http configuration omitted -->
- <security:custom-filter position="PRE_AUTH_FILTER" ref="siteminderFilter" />
- </security:http>
+ This interface may have also other uses but with pre-authentication it allows access
+ to the authorities which were packaged in the
+ <code class="interfacename">Authentication</code> object, as we saw in the previous
+ section. The
+ <code class="classname">PreAuthenticatedGrantedAuthoritiesUserDetailsService</code> class
+ does this. Alternatively, it may delegate to a standard
+ <code class="interfacename">UserDetailsService</code> via the
+ <code class="classname">UserDetailsByNameServiceWrapper</code> implementation. </p></div><div class="section" title="18.1.3 Http403ForbiddenEntryPoint"><div class="titlepage"><div><div><h3 class="title"><a name="d0e6253"></a>18.1.3 Http403ForbiddenEntryPoint</h3></div></div></div><p> The <code class="interfacename">AuthenticationEntryPoint</code> was discussed in the
+ <a class="link" href="#tech-intro-auth-entry-point" title="6.4.2 AuthenticationEntryPoint">technical overview</a> chapter.
+ Normally it is responsible for kick-starting the authentication process for an
+ unauthenticated user (when they try to access a protected resource), but in the
+ pre-authenticated case this doesn't apply. You would only configure the
+ <code class="classname">ExceptionTranslationFilter</code> with an instance of this class if
+ you aren't using pre-authentication in combination with other authentication
+ mechanisms. It will be called if the user is rejected by the
+ <code class="classname">AbstractPreAuthenticatedProcessingFilter</code> resulting in a null
+ authentication. It always returns a <code class="literal">403</code>-forbidden response code
+ if called. </p></div></div><div class="section" title="18.2 Concrete Implementations"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e6273"></a>18.2 Concrete Implementations</h2></div></div></div><p> X.509 authentication is covered in its <a class="link" href="#x509" title="23. X.509 Authentication">own chapter</a>.
+ Here we'll look at some classes which provide support for other pre-authenticated
+ scenarios. </p><div class="section" title="18.2.1 Request-Header Authentication (Siteminder)"><div class="titlepage"><div><div><h3 class="title"><a name="d0e6281"></a>18.2.1 Request-Header Authentication (Siteminder)</h3></div></div></div><p> An external authentication system may supply information to the application by
+ setting specific headers on the HTTP request. A well known example of this is
+ Siteminder, which passes the username in a header called <code class="literal">SM_USER</code>.
+ This mechanism is supported by the class
+ <code class="classname">RequestHeaderAuthenticationFilter</code> which simply extracts the
+ username from the header. It defaults to using the name <code class="literal">SM_USER</code>
+ as the header name. See the Javadoc for more details. </p><div class="tip" title="Tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>Note that when using a system like this, the framework performs no
+ authentication checks at all and it is <span class="emphasis"><em>extremely</em></span> important
+ that the external system is configured properly and protects all access to the
+ application. If an attacker is able to forge the headers in their original
+ request without this being detected then they could potentially choose any
+ username they wished. </p></td></tr></table></div><div class="section" title="Siteminder Example Configuration"><div class="titlepage"><div><div><h4 class="title"><a name="d0e6301"></a>Siteminder Example Configuration</h4></div></div></div><p> A typical configuration using this filter would look like this: </p><pre class="programlisting">
+ <span class="hl-tag"><security:http></span>
+ <span class="hl-comment"><!-- Additional http configuration omitted --></span>
+ <span class="hl-tag"><security:custom-filter</span> <span class="hl-attribute">position</span>=<span class="hl-value">"PRE_AUTH_FILTER"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"siteminderFilter"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"></security:http></span>
- <bean id="siteminderFilter" class=
-"org.springframework.security.web.authentication.preauth.header.RequestHeaderAuthenticationFilter">
- <property name="principalRequestHeader" value="SM_USER"/>
- <property name="authenticationManager" ref="authenticationManager" />
- </bean>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"siteminderFilter"</span> <span class="hl-attribute">class</span>=
+<span class="hl-value">"org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"principalRequestHeader"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"SM_USER"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"authenticationManager"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"></bean></span>
- <bean id="preauthAuthProvider"
-class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
- <property name="preAuthenticatedUserDetailsService">
- <bean id="userDetailsServiceWrapper"
- class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
- <property name="userDetailsService" ref="userDetailsService"/>
- </bean>
- </property>
- </bean>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"preauthAuthProvider"</span>
+<span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"preAuthenticatedUserDetailsService"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"userDetailsServiceWrapper"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"userDetailsService"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"userDetailsService"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></bean></span>
+ <span class="hl-tag"></property></span>
+ <span class="hl-tag"></bean></span>
- <security:authentication-manager alias="authenticationManager">
- <security:authentication-provider ref="preauthAuthProvider" />
- </security-authentication-manager>
+ <span class="hl-tag"><security:authentication-manager</span> <span class="hl-attribute">alias</span>=<span class="hl-value">"authenticationManager"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><security:authentication-provider</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"preauthAuthProvider"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"></security:authentication-manager></span>
-</pre><p> We've assumed here that the security namespace is being used for
- configuration (hence the user of the <code class="literal">custom-filter</code>,
- <code class="literal">authentication-manager</code> and
- <code class="literal">custom-authentication-provider</code> elements (you can read more about them
- in the <a class="link" href="#ns-config" title="2. Security Namespace Configuration">namespace chapter</a>). You would leave these out
- of a traditional bean configuration. It's also assumed that you have added a
- <code class="interfacename">UserDetailsService</code> (called
- <span class="quote">“<span class="quote">userDetailsService</span>”</span>) to your configuration to load the user's roles.
- </p></div></div><div class="section" title="17.2.2 J2EE Container Authentication"><div class="titlepage"><div><div><h3 class="title"><a name="d0e5696"></a>17.2.2 J2EE Container Authentication</h3></div></div></div><p> The class <code class="classname">J2eePreAuthenticatedProcessingFilter</code> will extract the
- username from the <code class="literal">userPrincipal</code> property of the
- <code class="interfacename">HttpServletRequest</code>. Use of this filter would usually be
- combined with the use of J2EE roles as described above in <a class="xref" href="#j2ee-preauth-details" title="J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource">the section called “J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource”</a>. </p><p> There is a sample application in the codebase which uses this approach, so get hold of
- the code from subversion and have a look at the application context file if you are
- interested. The code is in the <code class="filename">samples/preauth</code> directory. </p></div></div></div><div class="chapter" title="18. LDAP Authentication"><div class="titlepage"><div><div><h1 class="title"><a name="ldap"></a>LDAP Authentication</h1></div></div></div><div class="section" title="18.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ldap-overview"></a>18.1 Overview</h2></div></div></div><p>LDAP is often used by organizations as a central repository for user information and
+</pre><p> We've assumed here that the security namespace is being used for configuration
+ (hence the user of the <code class="literal">custom-filter</code>,
+ <code class="literal">authentication-manager</code> and
+ <code class="literal">custom-authentication-provider</code> elements (you can read more
+ about them in the <a class="link" href="#ns-config" title="3. Security Namespace Configuration">namespace chapter</a>). You
+ would leave these out of a traditional bean configuration. It's also assumed
+ that you have added a <code class="interfacename">UserDetailsService</code> (called
+ <span class="quote">“<span class="quote">userDetailsService</span>”</span>) to your configuration to load the user's
+ roles. </p></div></div><div class="section" title="18.2.2 J2EE Container Authentication"><div class="titlepage"><div><div><h3 class="title"><a name="d0e6327"></a>18.2.2 J2EE Container Authentication</h3></div></div></div><p> The class <code class="classname">J2eePreAuthenticatedProcessingFilter</code> will
+ extract the username from the <code class="literal">userPrincipal</code> property of the
+ <code class="interfacename">HttpServletRequest</code>. Use of this filter would usually
+ be combined with the use of J2EE roles as described above in <a class="xref" href="#j2ee-preauth-details" title="J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource">the section called “J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource”</a>. </p><p> There is a sample application in the codebase which uses this approach, so get
+ hold of the code from subversion and have a look at the application context file if
+ you are interested. The code is in the <code class="filename">samples/preauth</code>
+ directory. </p></div></div></div><div class="chapter" title="19. LDAP Authentication"><div class="titlepage"><div><div><h1 class="title"><a name="ldap"></a>LDAP Authentication</h1></div></div></div><div class="section" title="19.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ldap-overview"></a>19.1 Overview</h2></div></div></div><p>LDAP is often used by organizations as a central repository for user information and
as an authentication service. It can also be used to store the role information for
application users.</p><p>There are many different scenarios for how an LDAP server may be configured so Spring
Security's LDAP provider is fully configurable. It uses separate strategy interfaces for
authentication and role retrieval and provides default implementations which can be
configured to handle a wide range of situations.</p><p>You should be familiar with LDAP before trying to use it with Spring Security. The
following link provides a good introduction to the concepts involved and a guide to
- setting up a directory using the free LDAP server OpenLDAP: <code class="uri"><a class="uri" href="http://www.zytrax.com/books/ldap/" target="_top">http://www.zytrax.com/books/ldap/</a></code>. Some familiarity with the JNDI APIs used
- to access LDAP from Java may also be useful. We don't use any third-party LDAP libraries
- (Mozilla, JLDAP etc.) in the LDAP provider, but extensive use is made of Spring LDAP, so
- some familiarity with that project may be useful if you plan on adding your own
- customizations.</p></div><div class="section" title="18.2 Using LDAP with Spring Security"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e5734"></a>18.2 Using LDAP with Spring Security</h2></div></div></div><p> LDAP authentication in Spring Security can be roughly divided into the following
- stages. </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>Obtaining the unique LDAP <span class="quote">“<span class="quote">Distinguished Name</span>”</span>, or DN, from
- the login name. This will often mean performing a search in the directory,
- unless the exact mapping of usernames to DNs is known in advance.</p></li><li class="listitem"><p>Authenticating the user, either by binding as that user or by performing a
- remote <span class="quote">“<span class="quote">compare</span>”</span> operation of the user's password against the
- password attribute in the directory entry for the DN.</p></li><li class="listitem"><p>Loading the list of authorities for the user.</p></li></ol></div><p> The exception is when the LDAP directory is just being used to retrieve
+ setting up a directory using the free LDAP server OpenLDAP: <code class="uri"><a class="uri" href="http://www.zytrax.com/books/ldap/" target="_top">http://www.zytrax.com/books/ldap/</a></code>.
+ Some familiarity with the JNDI APIs used to access LDAP from Java may also be useful. We
+ don't use any third-party LDAP libraries (Mozilla, JLDAP etc.) in the LDAP provider, but
+ extensive use is made of Spring LDAP, so some familiarity with that project may be
+ useful if you plan on adding your own customizations.</p></div><div class="section" title="19.2 Using LDAP with Spring Security"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e6365"></a>19.2 Using LDAP with Spring Security</h2></div></div></div><p> LDAP authentication in Spring Security can be roughly divided into the following
+ stages. </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>Obtaining the unique LDAP <span class="quote">“<span class="quote">Distinguished Name</span>”</span>, or DN, from the
+ login name. This will often mean performing a search in the directory, unless
+ the exact mapping of usernames to DNs is known in advance. So a user might enter
+ the name <span class="quote">“<span class="quote">joe</span>”</span> when logging in, but the actual name used to
+ authenticate to LDAP will be the full DN, such as
+ <code class="literal">uid=joe,ou=users,dc=springsource,dc=com</code>.</p></li><li class="listitem"><p>Authenticating the user, either by <span class="quote">“<span class="quote">binding</span>”</span> as that user or by
+ performing a remote <span class="quote">“<span class="quote">compare</span>”</span> operation of the user's password
+ against the password attribute in the directory entry for the DN.</p></li><li class="listitem"><p>Loading the list of authorities for the user.</p></li></ol></div><p> The exception is when the LDAP directory is just being used to retrieve
user information and authenticate against it locally. This may not be possible as
directories are often set up with limited read access for attributes such as user
passwords. </p><p> We will look at some configuration scenarios below. For full information on available
configuration options, please consult the security namespace schema (information from
- which should be available in your XML editor). </p></div><div class="section" title="18.3 Configuring an LDAP Server"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ldap-server"></a>18.3 Configuring an LDAP Server</h2></div></div></div><p> The first thing you need to do is configure the server against which authentication
+ which should be available in your XML editor). </p></div><div class="section" title="19.3 Configuring an LDAP Server"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ldap-server"></a>19.3 Configuring an LDAP Server</h2></div></div></div><p> The first thing you need to do is configure the server against which authentication
should take place. This is done using the <code class="literal"><ldap-server></code> element
from the security namespace. This can be configured to point at an external LDAP server,
using the <code class="literal">url</code> attribute: </p><pre class="programlisting">
- <ldap-server url="ldap://springframework.org:389/dc=springframework,dc=org" />
+ <span class="hl-tag"><ldap-server</span> <span class="hl-attribute">url</span>=<span class="hl-value">"ldap://springframework.org:389/dc=springframework,dc=org"</span><span class="hl-tag"> /></span>
- </pre><div class="section" title="18.3.1 Using an Embedded Test Server"><div class="titlepage"><div><div><h3 class="title"><a name="d0e5773"></a>18.3.1 Using an Embedded Test Server</h3></div></div></div><p> The <code class="literal"><ldap-server></code> element can also be used to create an
+ </pre><div class="section" title="19.3.1 Using an Embedded Test Server"><div class="titlepage"><div><div><h3 class="title"><a name="d0e6413"></a>19.3.1 Using an Embedded Test Server</h3></div></div></div><p> The <code class="literal"><ldap-server></code> element can also be used to create an
embedded server, which can be very useful for testing and demonstrations. In this
case you use it without the <code class="literal">url</code> attribute: </p><pre class="programlisting">
- <ldap-server root="dc=springframework,dc=org"/>
+ <span class="hl-tag"><ldap-server</span> <span class="hl-attribute">root</span>=<span class="hl-value">"dc=springframework,dc=org"</span><span class="hl-tag">/></span>
</pre><p> Here we've specified that the root DIT of the directory should be
- <span class="quote">“<span class="quote">dc=springframework,dc=org</span>”</span>, which is the default. Used this way,
- the namespace parser will create an embedded Apache Directory server and scan the
+ <span class="quote">“<span class="quote">dc=springframework,dc=org</span>”</span>, which is the default. Used this way, the
+ namespace parser will create an embedded Apache Directory server and scan the
classpath for any LDIF files, which it will attempt to load into the server. You can
customize this behaviour using the <code class="literal">ldif</code> attribute, which defines
an LDIF resource to be loaded: </p><pre class="programlisting">
- <ldap-server ldif="classpath:users.ldif" />
+ <span class="hl-tag"><ldap-server</span> <span class="hl-attribute">ldif</span>=<span class="hl-value">"classpath:users.ldif"</span><span class="hl-tag"> /></span>
</pre><p> This makes it a lot easier to get up and running with LDAP, since it
can be inconvenient to work all the time with an external server. It also insulates
the user from the complex bean configuration needed to wire up an Apache Directory
server. Using plain Spring Beans the configuration would be much more cluttered. You
must have the necessary Apache Directory dependency jars available for your
- application to use. These can be obtained from the LDAP sample application. </p></div><div class="section" title="18.3.2 Using Bind Authentication"><div class="titlepage"><div><div><h3 class="title"><a name="d0e5797"></a>18.3.2 Using Bind Authentication</h3></div></div></div><p> This is the most common LDAP authentication scenario. </p><pre class="programlisting">
- <ldap-authentication-provider user-dn-pattern="uid={0},ou=people"/>
+ application to use. These can be obtained from the LDAP sample application. </p></div><div class="section" title="19.3.2 Using Bind Authentication"><div class="titlepage"><div><div><h3 class="title"><a name="d0e6437"></a>19.3.2 Using Bind Authentication</h3></div></div></div><p> This is the most common LDAP authentication scenario. </p><pre class="programlisting">
+ <span class="hl-tag"><ldap-authentication-provider</span> <span class="hl-attribute">user-dn-pattern</span>=<span class="hl-value">"uid={0},ou=people"</span><span class="hl-tag">/></span>
</pre><p> This simple example would obtain the DN for the user by
substituting the user login name in the supplied pattern and attempting to bind as
that user with the login password. This is OK if all your users are stored under a
single node in the directory. If instead you wished to configure an LDAP search
filter to locate the user, you could use the following: </p><pre class="programlisting">
- <ldap-authentication-provider user-search-filter="(uid={0})"
- user-search-base="ou=people"/>
+ <span class="hl-tag"><ldap-authentication-provider</span> <span class="hl-attribute">user-search-filter</span>=<span class="hl-value">"(uid={0})"</span>
+ <span class="hl-attribute">user-search-base</span>=<span class="hl-value">"ou=people"</span><span class="hl-tag">/></span>
</pre><p> If used with the server definition above, this would
perform a search under the DN <code class="literal">ou=people,dc=springframework,dc=org</code>
using the value of the <code class="literal">user-search-filter</code> attribute as a filter.
- Again the user login name is substituted for the parameter in the filter name. If
- <code class="literal">user-search-base</code> isn't supplied, the search will be performed
- from the root. </p></div><div class="section" title="18.3.3 Loading Authorities"><div class="titlepage"><div><div><h3 class="title"><a name="d0e5818"></a>18.3.3 Loading Authorities</h3></div></div></div><p> How authorities are loaded from groups in the LDAP directory is controlled by the
- following attributes. </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>
- <code class="literal">group-search-base</code>. Defines the part of the directory
- tree under which group searches should be performed.</p></li><li class="listitem"><p>
- <code class="literal">group-role-attribute</code>. The attribute which contains
- the name of the authority defined by the group entry. Defaults to
- <code class="literal">cn</code>
- </p></li><li class="listitem"><p>
- <code class="literal">group-search-filter</code>. The filter which is used to
- search for group membership. The default is
- <code class="literal">uniqueMember={0}</code>, corresponding to the
- <code class="literal">groupOfUniqueMembers</code> LDAP class. In this case,
- the substituted parameter is the full distinguished name of the user.
- The parameter <code class="literal">{1}</code> can be used if you want to filter
- on the login name.</p></li></ul></div><p> So if we used the following configuration </p><pre class="programlisting">
- <ldap-authentication-provider user-dn-pattern="uid={0},ou=people"
- group-search-base="ou=groups" />
+ Again the user login name is substituted for the parameter in the filter name, so it
+ will search for an entry with the <code class="literal">uid</code> attribute equal to the user
+ name. If <code class="literal">user-search-base</code> isn't supplied, the search will be
+ performed from the root. </p></div><div class="section" title="19.3.3 Loading Authorities"><div class="titlepage"><div><div><h3 class="title"><a name="d0e6461"></a>19.3.3 Loading Authorities</h3></div></div></div><p> How authorities are loaded from groups in the LDAP directory is controlled by the
+ following attributes. </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> <code class="literal">group-search-base</code>. Defines the part of the directory
+ tree under which group searches should be performed.</p></li><li class="listitem"><p> <code class="literal">group-role-attribute</code>. The attribute which contains the
+ name of the authority defined by the group entry. Defaults to
+ <code class="literal">cn</code> </p></li><li class="listitem"><p> <code class="literal">group-search-filter</code>. The filter which is used to
+ search for group membership. The default is
+ <code class="literal">uniqueMember={0}</code>, corresponding to the
+ <code class="literal">groupOfUniqueMembers</code> LDAP class. In this case, the
+ substituted parameter is the full distinguished name of the user. The
+ parameter <code class="literal">{1}</code> can be used if you want to filter on the
+ login name.</p></li></ul></div><p> So if we used the following configuration </p><pre class="programlisting">
+ <span class="hl-tag"><ldap-authentication-provider</span> <span class="hl-attribute">user-dn-pattern</span>=<span class="hl-value">"uid={0},ou=people"</span>
+ <span class="hl-attribute">group-search-base</span>=<span class="hl-value">"ou=groups"</span><span class="hl-tag"> /></span>
</pre><p> and authenticated successfully as user <span class="quote">“<span class="quote">ben</span>”</span>, the subsequent
loading of authorities would perform a search under the directory entry
- <code class="literal">ou=groups,dc=springframework,dc=org</code>, looking for entries
- which contain the attribute <code class="literal">uniqueMember</code> with value
- <code class="literal">uid=ben,ou=people,dc=springframework,dc=org</code>. By default the
+ <code class="literal">ou=groups,dc=springframework,dc=org</code>, looking for entries which
+ contain the attribute <code class="literal">uniqueMember</code> with value
+ <code class="literal">uid=ben,ou=people,dc=springframework,dc=org</code>. By default the
authority names will have the prefix <code class="literal">ROLE_</code> prepended. You can
change this using the <code class="literal">role-prefix</code> attribute. If you don't want
any prefix, use <code class="literal">role-prefix="none"</code>. For more information on
loading authorities, see the Javadoc for the
- <code class="classname">DefaultLdapAuthoritiesPopulator</code> class. </p></div></div><div class="section" title="18.4 Implementation Classes"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e5883"></a>18.4 Implementation Classes</h2></div></div></div><p>The namespace configuration options we've used above are simple to use and much more
+ <code class="classname">DefaultLdapAuthoritiesPopulator</code> class. </p></div></div><div class="section" title="19.4 Implementation Classes"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e6526"></a>19.4 Implementation Classes</h2></div></div></div><p>The namespace configuration options we've used above are simple to use and much more
concise than using Spring beans explicitly. There are situations when you may need to
know how to configure Spring Security LDAP directly in your application context. You may
wish to customize the behaviour of some of the classes, for example. If you're happy
using namespace configuration then you can skip this section and the next one. </p><p> The main LDAP provider class, <code class="classname">LdapAuthenticationProvider</code>,
doesn't actually do much itself but delegates the work to two other beans, an
- <code class="interfacename">LdapAuthenticator</code> and an
- <code class="interfacename">LdapAuthoritiesPopulator</code> which are responsible for
+ <code class="interfacename">LdapAuthenticator</code> and an
+ <code class="interfacename">LdapAuthoritiesPopulator</code> which are responsible for
authenticating the user and retrieving the user's set of
- <code class="interfacename">GrantedAuthority</code>s respectively.</p><div class="section" title="18.4.1 LdapAuthenticator Implementations"><div class="titlepage"><div><div><h3 class="title"><a name="ldap-ldap-authenticators"></a>18.4.1 LdapAuthenticator Implementations</h3></div></div></div><p>The authenticator is also responsible for retrieving any required user attributes.
+ <code class="interfacename">GrantedAuthority</code>s respectively.</p><div class="section" title="19.4.1 LdapAuthenticator Implementations"><div class="titlepage"><div><div><h3 class="title"><a name="ldap-ldap-authenticators"></a>19.4.1 LdapAuthenticator Implementations</h3></div></div></div><p>The authenticator is also responsible for retrieving any required user attributes.
This is because the permissions on the attributes may depend on the type of
authentication being used. For example, if binding as the user, it may be necessary
- to read them with the user's own permissions.</p><p>There are currently two authentication strategies supplied with Spring Security: </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>Authentication directly to the LDAP server ("bind"
- authentication).</p></li><li class="listitem"><p>Password comparison, where the password supplied by the user is
- compared with the one stored in the repository. This can either be done
- by retrieving the value of the password attribute and checking it
- locally or by performing an LDAP "compare" operation, where the supplied
- password is passed to the server for comparison and the real password
- value is never retrieved.</p></li></ul></div><div class="section" title="Common Functionality"><div class="titlepage"><div><div><h4 class="title"><a name="ldap-ldap-authenticators-common"></a>Common Functionality</h4></div></div></div><p>Before it is possible to authenticate a user (by either strategy), the
+ to read them with the user's own permissions.</p><p>There are currently two authentication strategies supplied with Spring Security: </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>Authentication directly to the LDAP server ("bind" authentication).</p></li><li class="listitem"><p>Password comparison, where the password supplied by the user is compared
+ with the one stored in the repository. This can either be done by retrieving
+ the value of the password attribute and checking it locally or by performing
+ an LDAP "compare" operation, where the supplied password is passed to the
+ server for comparison and the real password value is never retrieved.</p></li></ul></div><div class="section" title="Common Functionality"><div class="titlepage"><div><div><h4 class="title"><a name="ldap-ldap-authenticators-common"></a>Common Functionality</h4></div></div></div><p>Before it is possible to authenticate a user (by either strategy), the
distinguished name (DN) has to be obtained from the login name supplied to the
application. This can be done either by simple pattern-matching (by setting the
- <span class="property">setUserDnPatterns</span> array property) or by setting the
- <span class="property">userSearch</span> property. For the DN pattern-matching
- approach, a standard Java pattern format is used, and the login name will be
- substituted for the parameter <em class="parameter"><code>{0}</code></em>. The pattern should be
- relative to the DN that the configured
- <code class="interfacename">SpringSecurityContextSource</code> will bind to (see
- the section on <a class="link" href="#ldap-context-source" title="18.4.2 Connecting to the LDAP Server">connecting to the LDAP
- server</a> for more information on this). For example, if you are using
- an LDAP server with the URL
- <code class="literal">ldap://monkeymachine.co.uk/dc=springframework,dc=org</code>, and
+ <span class="property">setUserDnPatterns</span> array property) or by setting the
+ <span class="property">userSearch</span> property. For the DN pattern-matching approach,
+ a standard Java pattern format is used, and the login name will be substituted
+ for the parameter <em class="parameter"><code>{0}</code></em>. The pattern should be relative to
+ the DN that the configured
+ <code class="interfacename">SpringSecurityContextSource</code> will bind to (see the
+ section on <a class="link" href="#ldap-context-source" title="19.4.2 Connecting to the LDAP Server">connecting to the LDAP
+ server</a> for more information on this). For example, if you are using an
+ LDAP server with the URL
+ <code class="literal">ldap://monkeymachine.co.uk/dc=springframework,dc=org</code>, and
have a pattern <code class="literal">uid={0},ou=greatapes</code>, then a login name of
"gorilla" will map to a DN
- <code class="literal">uid=gorilla,ou=greatapes,dc=springframework,dc=org</code>. Each
+ <code class="literal">uid=gorilla,ou=greatapes,dc=springframework,dc=org</code>. Each
configured DN pattern will be tried in turn until a match is found. For
- information on using a search, see the section on <a class="link" href="#ldap-searchobjects" title="18.4.3 LDAP Search Objects">search objects</a> below. A combination of
- the two approaches can also be used - the patterns will be checked first and if
- no matching DN is found, the search will be used.</p></div><div class="section" title="BindAuthenticator"><div class="titlepage"><div><div><h4 class="title"><a name="ldap-ldap-authenticators-bind"></a>BindAuthenticator</h4></div></div></div><p>The class <code class="classname">BindAuthenticator</code> in the package
- <code class="filename">org.springframework.security.ldap.authentication</code>
- implements the bind authentication strategy. It simply attempts to bind as the
- user.</p></div><div class="section" title="PasswordComparisonAuthenticator"><div class="titlepage"><div><div><h4 class="title"><a name="ldap-ldap-authenticators-password"></a>PasswordComparisonAuthenticator</h4></div></div></div><p>The class <code class="classname">PasswordComparisonAuthenticator</code> implements
- the password comparison authentication strategy.</p></div><div class="section" title="Active Directory Authentication"><div class="titlepage"><div><div><h4 class="title"><a name="ldap-ldap-authenticators-active-directory"></a>Active Directory Authentication</h4></div></div></div><p>In addition to standard LDAP authentication (binding with a DN), Active
- Directory has its own non-standard syntax for user authentication.</p></div></div><div class="section" title="18.4.2 Connecting to the LDAP Server"><div class="titlepage"><div><div><h3 class="title"><a name="ldap-context-source"></a>18.4.2 Connecting to the LDAP Server</h3></div></div></div><p>The beans discussed above have to be able to connect to the server. They both have
+ information on using a search, see the section on <a class="link" href="#ldap-searchobjects" title="19.4.3 LDAP Search Objects">search objects</a> below. A combination of the
+ two approaches can also be used - the patterns will be checked first and if no
+ matching DN is found, the search will be used.</p></div><div class="section" title="BindAuthenticator"><div class="titlepage"><div><div><h4 class="title"><a name="ldap-ldap-authenticators-bind"></a>BindAuthenticator</h4></div></div></div><p>The class <code class="classname">BindAuthenticator</code> in the package
+ <code class="filename">org.springframework.security.ldap.authentication</code> implements
+ the bind authentication strategy. It simply attempts to bind as the user.</p></div><div class="section" title="PasswordComparisonAuthenticator"><div class="titlepage"><div><div><h4 class="title"><a name="ldap-ldap-authenticators-password"></a>PasswordComparisonAuthenticator</h4></div></div></div><p>The class <code class="classname">PasswordComparisonAuthenticator</code> implements
+ the password comparison authentication strategy.</p></div></div><div class="section" title="19.4.2 Connecting to the LDAP Server"><div class="titlepage"><div><div><h3 class="title"><a name="ldap-context-source"></a>19.4.2 Connecting to the LDAP Server</h3></div></div></div><p>The beans discussed above have to be able to connect to the server. They both have
to be supplied with a <code class="interfacename">SpringSecurityContextSource</code>
which is an extension of Spring LDAP's <code class="interfacename">ContextSource</code>.
Unless you have special requirements, you will usually configure a
- <code class="classname">DefaultSpringSecurityContextSource</code> bean, which can be
+ <code class="classname">DefaultSpringSecurityContextSource</code> bean, which can be
configured with the URL of your LDAP server and optionally with the username and
password of a "manager" user which will be used by default when binding to the
server (instead of binding anonymously). For more information read the Javadoc for
this class and for Spring LDAP's <code class="classname">AbstractContextSource</code>.
- </p></div><div class="section" title="18.4.3 LDAP Search Objects"><div class="titlepage"><div><div><h3 class="title"><a name="ldap-searchobjects"></a>18.4.3 LDAP Search Objects</h3></div></div></div><p>Often a more complicated strategy than simple DN-matching is required to
- locate a user entry in the directory. This can be encapsulated in an
- <code class="interfacename">LdapUserSearch</code> instance which can be supplied to
- the authenticator implementations, for example, to allow them to locate a user. The
+ </p></div><div class="section" title="19.4.3 LDAP Search Objects"><div class="titlepage"><div><div><h3 class="title"><a name="ldap-searchobjects"></a>19.4.3 LDAP Search Objects</h3></div></div></div><p>Often a more complicated strategy than simple DN-matching is required to locate a
+ user entry in the directory. This can be encapsulated in an
+ <code class="interfacename">LdapUserSearch</code> instance which can be supplied to the
+ authenticator implementations, for example, to allow them to locate a user. The
supplied implementation is <code class="classname">FilterBasedLdapUserSearch</code>.</p><div class="section" title="FilterBasedLdapUserSearch"><div class="titlepage"><div><div><h4 class="title"><a name="ldap-searchobjects-filter"></a>
- <code class="classname">FilterBasedLdapUserSearch</code>
- </h4></div></div></div><p>This bean uses an LDAP filter to match the user object in the directory. The
+ <code class="classname">FilterBasedLdapUserSearch</code> </h4></div></div></div><p>This bean uses an LDAP filter to match the user object in the directory. The
process is explained in the Javadoc for the corresponding search method on the
- <a class="link" href="http://java.sun.com/j2se/1.4.2/docs/api/javax/naming/directory/DirContext.html#search(javax.naming.Name,%20java.lang.String,%20java.lang.Object[],%20javax.naming.directory.SearchControls)" target="_top">JDK DirContext class</a>. As explained there, the search filter can be
+ <a class="link" href="http://java.sun.com/j2se/1.4.2/docs/api/javax/naming/directory/DirContext.html#search(javax.naming.Name,%20java.lang.String,%20java.lang.Object[],%20javax.naming.directory.SearchControls)" target="_top">JDK DirContext class</a>. As explained there, the search filter can be
supplied with parameters. For this class, the only valid parameter is
- <em class="parameter"><code>{0}</code></em> which will be replaced with the user's login
- name.</p></div></div><div class="section" title="18.4.4 LdapAuthoritiesPopulator"><div class="titlepage"><div><div><h3 class="title"><a name="ldap-authorities"></a>18.4.4 LdapAuthoritiesPopulator</h3></div></div></div><p> After authenticating the user successfully, the
- <code class="classname">LdapAuthenticationProvider</code> will attempt to load a set of
+ <em class="parameter"><code>{0}</code></em> which will be replaced with the user's login
+ name.</p></div></div><div class="section" title="19.4.4 LdapAuthoritiesPopulator"><div class="titlepage"><div><div><h3 class="title"><a name="ldap-authorities"></a>19.4.4 LdapAuthoritiesPopulator</h3></div></div></div><p> After authenticating the user successfully, the
+ <code class="classname">LdapAuthenticationProvider</code> will attempt to load a set of
authorities for the user by calling the configured
- <code class="interfacename">LdapAuthoritiesPopulator</code> bean. The
- <code class="classname">DefaultLdapAuthoritiesPopulator</code> is an implementation
- which will load the authorities by searching the directory for groups of which the
- user is a member (typically these will be <code class="literal">groupOfNames</code> or
- <code class="literal">groupOfUniqueNames</code> entries in the directory). Consult the
- Javadoc for this class for more details on how it works. </p><p>If you want to use LDAP only for authentication, but load the authorities from a
+ <code class="interfacename">LdapAuthoritiesPopulator</code> bean. The
+ <code class="classname">DefaultLdapAuthoritiesPopulator</code> is an implementation which
+ will load the authorities by searching the directory for groups of which the user is
+ a member (typically these will be <code class="literal">groupOfNames</code> or
+ <code class="literal">groupOfUniqueNames</code> entries in the directory). Consult the Javadoc
+ for this class for more details on how it works. </p><p>If you want to use LDAP only for authentication, but load the authorities from a
difference source (such as a database) then you can provide your own implementation
- of this interface and inject that instead.</p></div><div class="section" title="18.4.5 Spring Bean Configuration"><div class="titlepage"><div><div><h3 class="title"><a name="ldap-bean-config"></a>18.4.5 Spring Bean Configuration</h3></div></div></div><p>A typical configuration, using some of the beans we've discussed here, might look
+ of this interface and inject that instead.</p></div><div class="section" title="19.4.5 Spring Bean Configuration"><div class="titlepage"><div><div><h3 class="title"><a name="ldap-bean-config"></a>19.4.5 Spring Bean Configuration</h3></div></div></div><p>A typical configuration, using some of the beans we've discussed here, might look
like this: </p><pre class="programlisting">
-<bean id="contextSource"
- class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
- <constructor-arg value="ldap://monkeymachine:389/dc=springframework,dc=org"/>
- <property name="userDn" value="cn=manager,dc=springframework,dc=org"/>
- <property name="password" value="password"/>
-</bean>
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"contextSource"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.ldap.DefaultSpringSecurityContextSource"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">value</span>=<span class="hl-value">"ldap://monkeymachine:389/dc=springframework,dc=org"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"userDn"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"cn=manager,dc=springframework,dc=org"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"password"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"password"</span><span class="hl-tag">/></span>
+<span class="hl-tag"></bean></span>
-<bean id="ldapAuthProvider"
- class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
- <constructor-arg>
- <bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
- <constructor-arg ref="contextSource"/>
- <property name="userDnPatterns">
- <list><value>uid={0},ou=people</value></list>
- </property>
- </bean>
- </constructor-arg>
- <constructor-arg>
- <bean
- class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
- <constructor-arg ref="contextSource"/>
- <constructor-arg value="ou=groups"/>
- <property name="groupRoleAttribute" value="ou"/>
- </bean>
- </constructor-arg>
-</bean>
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"ldapAuthProvider"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.ldap.authentication.LdapAuthenticationProvider"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><constructor-arg></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.ldap.authentication.BindAuthenticator"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"contextSource"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"userDnPatterns"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><list></span><span class="hl-tag"><value></span>uid={0},ou=people<span class="hl-tag"></value></span><span class="hl-tag"></list></span>
+ <span class="hl-tag"></property></span>
+ <span class="hl-tag"></bean></span>
+ <span class="hl-tag"></constructor-arg></span>
+ <span class="hl-tag"><constructor-arg></span>
+ <span class="hl-tag"><bean</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"contextSource"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">value</span>=<span class="hl-value">"ou=groups"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"groupRoleAttribute"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"ou"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></bean></span>
+ <span class="hl-tag"></constructor-arg></span>
+<span class="hl-tag"></bean></span>
</pre><p> This would set up the provider to access an LDAP server
with URL <code class="literal">ldap://monkeymachine:389/dc=springframework,dc=org</code>.
Authentication will be performed by attempting to bind with the DN
- <code class="literal">uid=<user-login-name>,ou=people,dc=springframework,dc=org</code>.
+ <code class="literal">uid=<user-login-name>,ou=people,dc=springframework,dc=org</code>.
After successful authentication, roles will be assigned to the user by searching
under the DN <code class="literal">ou=groups,dc=springframework,dc=org</code> with the default
filter <code class="literal">(member=<user's-DN>)</code>. The role name will be taken
from the <span class="quote">“<span class="quote">ou</span>”</span> attribute of each match.</p><p>To configure a user search object, which uses the filter
- <code class="literal">(uid=<user-login-name>)</code> for use instead of the
- DN-pattern (or in addition to it), you would configure the following bean </p><pre class="programlisting">
-<bean id="userSearch"
- class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
- <constructor-arg index="0" value=""/>
- <constructor-arg index="1" value="(uid={0})"/>
- <constructor-arg index="2" ref="contextSource" />
-</bean>
+ <code class="literal">(uid=<user-login-name>)</code> for use instead of the DN-pattern
+ (or in addition to it), you would configure the following bean </p><pre class="programlisting">
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"userSearch"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.ldap.search.FilterBasedLdapUserSearch"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">index</span>=<span class="hl-value">"0"</span> <span class="hl-attribute">value</span>=<span class="hl-value">""</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">index</span>=<span class="hl-value">"1"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"(uid={0})"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">index</span>=<span class="hl-value">"2"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"contextSource"</span><span class="hl-tag"> /></span>
+<span class="hl-tag"></bean></span>
</pre><p> and use it by setting the
- <code class="classname">BindAuthenticator</code> bean's <span class="property">userSearch</span>
+ <code class="classname">BindAuthenticator</code> bean's <span class="property">userSearch</span>
property. The authenticator would then call the search object to obtain the correct
- user's DN before attempting to bind as this user.</p></div><div class="section" title="18.4.6 LDAP Attributes and Customized UserDetails"><div class="titlepage"><div><div><h3 class="title"><a name="ldap-custom-user-details"></a>18.4.6 LDAP Attributes and Customized UserDetails</h3></div></div></div><p> The net result of an authentication using
- <code class="classname">LdapAuthenticationProvider</code> is the same as a normal Spring
+ user's DN before attempting to bind as this user.</p></div><div class="section" title="19.4.6 LDAP Attributes and Customized UserDetails"><div class="titlepage"><div><div><h3 class="title"><a name="ldap-custom-user-details"></a>19.4.6 LDAP Attributes and Customized UserDetails</h3></div></div></div><p> The net result of an authentication using
+ <code class="classname">LdapAuthenticationProvider</code> is the same as a normal Spring
Security authentication using the standard
- <code class="interfacename">UserDetailsService</code> interface. A
- <code class="interfacename">UserDetails</code> object is created and stored in the
+ <code class="interfacename">UserDetailsService</code> interface. A
+ <code class="interfacename">UserDetails</code> object is created and stored in the
returned <code class="interfacename">Authentication</code> object. As with using a
- <code class="interfacename">UserDetailsService</code>, a common requirement is to be
+ <code class="interfacename">UserDetailsService</code>, a common requirement is to be
able to customize this implementation and add extra properties. When using LDAP,
these will normally be attributes from the user entry. The creation of the
- <code class="interfacename">UserDetails</code> object is controlled by the
- provider's <code class="interfacename">UserDetailsContextMapper</code> strategy, which
- is responsible for mapping user objects to and from LDAP context data: </p><pre class="programlisting">
-public interface UserDetailsContextMapper {
+ <code class="interfacename">UserDetails</code> object is controlled by the provider's
+ <code class="interfacename">UserDetailsContextMapper</code> strategy, which is
+ responsible for mapping user objects to and from LDAP context data: </p><pre class="programlisting">
+<span class="hl-keyword">public</span> <span class="hl-keyword">interface</span> UserDetailsContextMapper {
UserDetails mapUserFromContext(DirContextOperations ctx, String username,
Collection<GrantedAuthority> authorities);
- void mapUserToContext(UserDetails user, DirContextAdapter ctx);
+ <span class="hl-keyword">void</span> mapUserToContext(UserDetails user, DirContextAdapter ctx);
}
</pre><p> Only the first method is relevant for authentication. If you
provide an implementation of this interface and inject it into the
@@ -3428,35 +3713,71 @@ public interface UserDetailsContextMapper {
context returned from the bind operation will be used to read the attributes,
otherwise the data will be read using the standard context obtained from the
configured <code class="interfacename">ContextSource</code> (when a search is configured
- to locate the user, this will be the data returned by the search object). </p></div></div></div><div class="chapter" title="19. JSP Tag Libraries"><div class="titlepage"><div><div><h2 class="title"><a name="taglibs"></a>19. JSP Tag Libraries</h2></div></div></div><p> Spring Security has its own taglib which provides basic support for accessing security
- information and applying security constraints in JSPs. </p><div class="section" title="19.1 Declaring the Taglib"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e6137"></a>19.1 Declaring the Taglib</h2></div></div></div><p>To use any of the tags, you must have the security taglib declared in your JSP:
+ to locate the user, this will be the data returned by the search object). </p></div></div><div class="section" title="19.5 Active Directory Authentication"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ldap-active-directory"></a>19.5 Active Directory Authentication</h2></div></div></div><p>Active Directory supports its own non-standard authentication options, and the normal usage pattern
+ doesn't fit too cleanly with the standard <code class="classname">LdapAuthenticationProvider</code>.
+ Typically authentication is performed using the domain username (in the form <code class="literal">user at domain</code>),
+ rather than using an LDAP distinguished name. To make this easier, Spring Security 3.1 has an
+ authentication provider which is customized for a typical Active Directory setup.
+ </p><div class="section" title="19.5.1 ActiveDirectoryLdapAuthenticationProvider"><div class="titlepage"><div><div><h3 class="title"><a name="d0e6780"></a>19.5.1 <code class="classname">ActiveDirectoryLdapAuthenticationProvider</code></h3></div></div></div><p> Configuring <code class="classname">ActiveDirectoryLdapAuthenticationProvider</code> is
+ quite straightforward. You just need to supply the domain name and an LDAP URL
+ supplying the address of the server <sup>[<a name="d0e6789" href="#ftn.d0e6789" class="footnote">22</a>]</sup>. An example configuration would then look like this: </p><pre class="programlisting">
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"adAuthenticationProvider"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">value</span>=<span class="hl-value">"mydomain.com"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">value</span>=<span class="hl-value">"ldap://adserver.mydomain.com/"</span><span class="hl-tag"> /></span>
+<span class="hl-tag"></bean></span>
+}
+ </pre><p> Note that there is no need to specify a separate
+ <code class="literal">ContextSource</code> in order to define the server location - the bean
+ is completely self-contained. A user named <span class="quote">“<span class="quote">Sharon</span>”</span>, for example, would
+ then be able to authenticate by entering either the username
+ <code class="literal">sharon</code> or the full Active Directory
+ <code class="literal">userPrincipalName</code>, namely <code class="literal">sharon at mydomain.com</code>.
+ The user's directory entry will then be located, and the attributes returned for
+ possible use in customizing the created <code class="interfacename">UserDetails</code>
+ object (a <code class="interfacename">UserDetailsContextMapper</code> can be injected
+ for this purpose, as described above). All interaction with the directory takes
+ place with the identity of the user themselves. There is no concept of a
+ <span class="quote">“<span class="quote">manager</span>”</span> user. </p><p>By default, the user authorities are obtained from the <code class="literal">memberOf</code>
+ attribute values of the user entry. The authorities allocated to the user can again
+ be customized using a <code class="interfacename">UserDetailsContextMapper</code>. You
+ can also inject a <code class="interfacename">GrantedAuthoritiesMaper</code> into the
+ provider instance to control the authorities which end up in the
+ <code class="interfacename">Authentication</code> object.</p><div class="section" title="Active Directory Error Codes"><div class="titlepage"><div><div><h4 class="title"><a name="d0e6834"></a>Active Directory Error Codes</h4></div></div></div><p>By default, a failed result will cause a standard Spring Security
+ <code class="classname">BadCredentialsException</code>. If you set the property
+ <code class="literal">convertSubErrorCodesToExceptions</code> to <code class="literal">true</code>,
+ the exception messages will be parsed to attempt to extract the Active
+ Directory-specific error code and raise a more specific exception. Check the
+ class Javadoc for more information.</p></div></div></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e6789" href="#d0e6789" class="para">22</a>] </sup>It is also possible to obtain the server's IP address using a DNS lookup. This
+ is not currently supported, but hopefully will be in a future version.</p></div></div></div><div class="chapter" title="20. JSP Tag Libraries"><div class="titlepage"><div><div><h2 class="title"><a name="taglibs"></a>20. JSP Tag Libraries</h2></div></div></div><p> Spring Security has its own taglib which provides basic support for accessing security
+ information and applying security constraints in JSPs. </p><div class="section" title="20.1 Declaring the Taglib"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e6853"></a>20.1 Declaring the Taglib</h2></div></div></div><p>To use any of the tags, you must have the security taglib declared in your JSP:
</p><pre class="programlisting">
- <%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
-</pre></div><div class="section" title="19.2 The authorize Tag"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e6144"></a>19.2 The <code class="literal">authorize</code> Tag</h2></div></div></div><p> This tag is used to determine whether its contents should be evaluated or not. In
- Spring Security 3.0, it can be used in two ways <sup>[<a name="d0e6152" href="#ftn.d0e6152" class="footnote">15</a>]</sup>. The first approach uses a <a class="link" href="#el-access-web" title="15.2 Web Security Expressions">web-security
- expression</a>, specified in the <code class="literal">access</code> attribute of the tag.
- The expression evaluation will be delegated to the
- <code class="interfacename">WebSecurityExpressionHandler</code> defined in the
- application context (you should have web expressions enabled in your
- <code class="literal"><http></code> namespace configuration to make sure this service is
- available). So, for example, you might
- have</p><pre class="programlisting"><sec:authorize access="hasRole('supervisor')">
+ <span class="hl-tag"><%@</span> <span class="hl-attribute">taglib</span> <span class="hl-attribute">prefix</span>=<span class="hl-value">"sec"</span> <span class="hl-attribute">uri</span>=<span class="hl-value">"http://www.springframework.org/security/tags"</span> <span class="hl-attribute">%></span>
+</pre></div><div class="section" title="20.2 The authorize Tag"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e6860"></a>20.2 The <code class="literal">authorize</code> Tag</h2></div></div></div><p> This tag is used to determine whether its contents should be evaluated or not. In
+ Spring Security 3.0, it can be used in two ways <sup>[<a name="d0e6868" href="#ftn.d0e6868" class="footnote">23</a>]</sup>. The first approach uses a <a class="link" href="#el-access-web" title="16.2 Web Security Expressions">web-security
+ expression</a>, specified in the <code class="literal">access</code> attribute of the tag. The
+ expression evaluation will be delegated to the
+ <code class="interfacename">WebSecurityExpressionHandler</code> defined in the application
+ context (you should have web expressions enabled in your <code class="literal"><http></code>
+ namespace configuration to make sure this service is available). So, for example, you
+ might
+ have</p><pre class="programlisting"><span class="hl-tag"><sec:authorize</span> <span class="hl-attribute">access</span>=<span class="hl-value">"hasRole('supervisor')"</span><span class="hl-tag">></span>
This content will only be visible to users who have
-the "supervisor" authority in their list of <tt>GrantedAuthority</tt>s.
+the "supervisor" authority in their list of <span class="hl-tag"><tt></span>GrantedAuthority<span class="hl-tag"></tt></span>s.
-</sec:authorize></pre><p>A common requirement is to only show a particular link, if the user is actually
+<span class="hl-tag"></sec:authorize></span></pre><p>A common requirement is to only show a particular link, if the user is actually
allowed to click it. How can we determine in advance whether something will be allowed?
This tag can also operate in an alternative mode which allows you to define a particular
URL as an attribute. If the user is allowed to invoke that URL, then the tag body will
be evaluated, otherwise it will be skipped. So you might have something
- like</p><pre class="programlisting"><sec:authorize url="/admin">
+ like</p><pre class="programlisting"><span class="hl-tag"><sec:authorize</span> <span class="hl-attribute">url</span>=<span class="hl-value">"/admin"</span><span class="hl-tag">></span>
This content will only be visible to users who are authorized to send requests to the "/admin" URL.
-</sec:authorize></pre><p>To
+<span class="hl-tag"></sec:authorize></span></pre><p>To
use this tag there must also be an instance of
- <code class="interfacename">WebInvocationPrivilegeEvaluator</code> in your application
+ <code class="interfacename">WebInvocationPrivilegeEvaluator</code> in your application
context. If you are using the namespace, one will automatically be registered. This is
an instance of <code class="classname">DefaultWebInvocationPrivilegeEvaluator</code>, which
creates a dummy web request for the supplied URL and invokes the security interceptor to
@@ -3465,142 +3786,214 @@ This content will only be visible to users who are authorized to send requests t
within the <code class="literal"><http></code> namespace configuration and saves having to
duplicate the information (such as the required roles) within your JSPs. This approach
can also be combined with a <code class="literal">method</code> attribute, supplying the HTTP
- method, for a more specific match.</p></div><div class="section" title="19.3 The authenticationTag"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e6190"></a>19.3 The <code class="literal">authentication</code>Tag</h2></div></div></div><p>This tag allows access to the current <code class="interfacename">Authentication</code>
+ method, for a more specific match.</p><p>The boolean result of evaluating the tag (whether it grants or denies access) can be
+ stored in a page context scope variable by setting the <code class="literal">var</code> attribute
+ to the variable name, avoiding the need for duplicating and re-evaluating the condition
+ at other points in the page.</p><div class="section" title="20.2.1 Disabling Tag Authorization for Testing"><div class="titlepage"><div><div><h3 class="title"><a name="d0e6911"></a>20.2.1 Disabling Tag Authorization for Testing</h3></div></div></div><p>Hiding a link in a page for unauthorized users doesn't prevent them from accessing
+ the URL. They could just type it into their browser directly, for example. As part
+ of your testing process, you may want to reveal the hidden areas in order to check
+ that links really are secured at the back end. If you set the system property
+ <code class="literal">spring.security.disableUISecurity</code> to <code class="literal">true</code>,
+ the <code class="literal">authorize</code> tag will still run but will not hide its contents.
+ By default it will also surround the content with <code class="literal"><span
+ class="securityHiddenUI">...</span></code> tags. This allows you to
+ display <span class="quote">“<span class="quote">hidden</span>”</span> content with a particular CSS style such as a
+ different background colour. Try running the <span class="quote">“<span class="quote">tutorial</span>”</span> sample
+ application with this property enabled, for example.</p><p>You can also set the properties <code class="literal">spring.security.securedUIPrefix</code>
+ and <code class="literal">spring.security.securedUISuffix</code> if you want to change
+ surrounding text from the default <code class="literal">span</code> tags (or use empty strings
+ to remove it completely).</p></div></div><div class="section" title="20.3 The authenticationTag"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e6945"></a>20.3 The <code class="literal">authentication</code>Tag</h2></div></div></div><p>This tag allows access to the current <code class="interfacename">Authentication</code>
object stored in the security context. It renders a property of the object directly in
the JSP. So, for example, if the <code class="literal">principal</code> property of the
- <code class="interfacename">Authentication</code> is an instance of Spring Security's
- <code class="interfacename">UserDetails</code> object, then using
- <code class="literal"><sec:authentication property="principal.username" /></code> will
- render the name of the current user.</p><p>Of course, it isn't necessary to use JSP tags for this kind of thing and some people
+ <code class="interfacename">Authentication</code> is an instance of Spring Security's
+ <code class="interfacename">UserDetails</code> object, then using
+ <code class="literal"><sec:authentication property="principal.username" /></code> will render
+ the name of the current user.</p><p>Of course, it isn't necessary to use JSP tags for this kind of thing and some people
prefer to keep as little logic as possible in the view. You can access the
- <code class="interfacename">Authentication</code> object in your MVC controller (by
- calling <code class="code">SecurityContextHolder.getContext().getAuthentication()</code>) and add the
- data directly to your model for rendering by the view.</p></div><div class="section" title="19.4 The accesscontrollist Tag"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e6221"></a>19.4 The <code class="literal">accesscontrollist</code> Tag</h2></div></div></div><p>This tag is only valid when used with Spring Security's ACL module. It checks a
+ <code class="interfacename">Authentication</code> object in your MVC controller (by calling
+ <code class="code">SecurityContextHolder.getContext().getAuthentication()</code>) and add the data
+ directly to your model for rendering by the view.</p></div><div class="section" title="20.4 The accesscontrollist Tag"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e6976"></a>20.4 The <code class="literal">accesscontrollist</code> Tag</h2></div></div></div><p>This tag is only valid when used with Spring Security's ACL module. It checks a
comma-separated list of required permissions for a specified domain object. If the
current user has any of those permissions, then the tag body will be evaluated. If they
don't, it will be skipped. An example might
- be</p><pre class="programlisting"><sec:accesscontrollist hasPermission="1,2" domainObject="someObject">
+ be</p><pre class="programlisting"><span class="hl-tag"><sec:accesscontrollist</span> <span class="hl-attribute">hasPermission</span>=<span class="hl-value">"1,2"</span> <span class="hl-attribute">domainObject</span>=<span class="hl-value">"${someObject}"</span><span class="hl-tag">></span>
This will be shown if the user has either of the permissions
represented by the values "1" or "2" on the given object.
-</sec:accesscontrollist></pre><p>The permissions are passed to the <code class="interfacename">PermissionFactory</code>
+<span class="hl-tag"></sec:accesscontrollist></span></pre><p>The permissions are passed to the <code class="interfacename">PermissionFactory</code>
defined in the application context, converting them to ACL
- <code class="interfacename">Permission</code> instances, so they may be any format which
- is supported by the factory - they don't have to be integers, they could be strings like
- <code class="literal">READ</code> or <code class="literal">WRITE</code>. If no
- <code class="interfacename">PermissionFactory</code> is found, an instance of
- <code class="classname">DefaultPermissionFactory</code> will be used. The
- <code class="interfacename">AclService</code>from the application context will be used
- to load the <code class="interfacename">Acl</code> instance for the supplied object. The
- <code class="interfacename">Acl</code> will be invoked with the required permissions to
- check if any of them are granted.</p></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e6152" href="#d0e6152" class="para">15</a>] </sup>The legacy options from Spring Security 2.0 are also supported, but
- discouraged.</p></div></div></div><div class="chapter" title="20. Java Authentication and Authorization Service (JAAS) Provider"><div class="titlepage"><div><div><h1 class="title"><a name="jaas"></a>Java Authentication and Authorization Service (JAAS) Provider</h1></div></div></div><div class="section" title="20.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="jaas-overview"></a>20.1 Overview</h2></div></div></div><p>Spring Security provides a package able to delegate
- authentication requests to the Java Authentication and Authorization
- Service (JAAS). This package is discussed in detail below.</p><p>Central to JAAS operation are login configuration files. To
- learn more about JAAS login configuration files, consult the JAAS
- reference documentation available from Sun Microsystems. We expect you
- to have a basic understanding of JAAS and its login configuration file
- syntax in order to understand this section.</p></div><div class="section" title="20.2 Configuration"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="jaas-config"></a>20.2 Configuration</h2></div></div></div><p>The <code class="literal">JaasAuthenticationProvider</code> attempts to
- authenticate a user’s principal and credentials through JAAS.</p><p>Let’s assume we have a JAAS login configuration file,
- <code class="literal">/WEB-INF/login.conf</code>, with the following
- contents:
-</p><pre class="programlisting">
-JAASTest {
- sample.SampleLoginModule required;
-};</pre><p>Like all Spring Security beans, the
- <code class="classname">JaasAuthenticationProvider</code> is configured via the
- application context. The following definitions would correspond to the
- above JAAS login configuration file:
-</p><pre class="programlisting">
-<bean id="jaasAuthenticationProvider"
- class="org.springframework.security.authentication.jaas.JaasAuthenticationProvider">
- <property name="loginConfig" value="/WEB-INF/login.conf"/>
- <property name="loginContextName" value="JAASTest"/>
- <property name="callbackHandlers">
- <list>
- <bean
- class="org.springframework.security.authentication.jaas.JaasNameCallbackHandler"/>
- <bean
- class="org.springframework.security.authentication.jaas.JaasPasswordCallbackHandler"/>
- </list>
- </property>
- <property name="authorityGranters">
- <list>
- <bean class="org.springframework.security.authentication.jaas.TestAuthorityGranter"/>
- </list>
- </property>
-</bean>
-</pre><p>The <code class="literal">CallbackHandler</code>s and
- <code class="interfacename">AuthorityGranter</code>s are discussed below.</p><div class="section" title="20.2.1 JAAS CallbackHandler"><div class="titlepage"><div><div><h3 class="title"><a name="jaas-callbackhandler"></a>20.2.1 JAAS CallbackHandler</h3></div></div></div><p>Most JAAS <code class="literal">LoginModule</code>s require a callback
- of some sort. These callbacks are usually used to obtain the
- username and password from the user.</p><p>In a Spring Security deployment, Spring Security is
- responsible for this user interaction (via the authentication
- mechanism). Thus, by the time the authentication request is
- delegated through to JAAS, Spring Security's authentication
- mechanism will already have fully-populated an
- <code class="interfacename">Authentication</code> object containing all the
- information required by the JAAS
- <code class="literal">LoginModule</code>.</p><p>Therefore, the JAAS package for Spring Security provides two
- default callback handlers,
- <code class="literal">JaasNameCallbackHandler</code> and
- <code class="literal">JaasPasswordCallbackHandler</code>. Each of these
- callback handlers implement
- <code class="literal">JaasAuthenticationCallbackHandler</code>. In most cases
- these callback handlers can simply be used without understanding the
- internal mechanics.</p><p>For those needing full control over the callback behavior,
- internally <code class="literal">JaasAuthenticationProvider</code> wraps these
+ <code class="interfacename">Permission</code> instances, so they may be any format which is
+ supported by the factory - they don't have to be integers, they could be strings like
+ <code class="literal">READ</code> or <code class="literal">WRITE</code>. If no
+ <code class="interfacename">PermissionFactory</code> is found, an instance of
+ <code class="classname">DefaultPermissionFactory</code> will be used. The
+ <code class="interfacename">AclService</code>from the application context will be used to
+ load the <code class="interfacename">Acl</code> instance for the supplied object. The
+ <code class="interfacename">Acl</code> will be invoked with the required permissions to
+ check if any of them are granted.</p><p>This tag also supports the <code class="literal">var</code> attribute, in the same way as the
+ <code class="literal">authorize</code> tag.</p></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e6868" href="#d0e6868" class="para">23</a>] </sup>The legacy options from Spring Security 2.0 are also supported, but
+ discouraged.</p></div></div></div><div class="chapter" title="21. Java Authentication and Authorization Service (JAAS) Provider"><div class="titlepage"><div><div><h1 class="title"><a name="jaas"></a>Java Authentication and Authorization Service (JAAS) Provider</h1></div></div></div><div class="section" title="21.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e7027"></a>21.1 Overview</h2></div></div></div><p>Spring Security provides a package able to delegate authentication requests to the
+ Java Authentication and Authorization Service (JAAS). This package is discussed in
+ detail below.</p></div><div class="section" title="21.2 AbstractJaasAuthenticationProvider"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="jaas-abstractjaasauthenticationprovider"></a>21.2 AbstractJaasAuthenticationProvider</h2></div></div></div><p>The <code class="classname">AbstractJaasAuthenticationProvider</code> is the basis for the
+ provided JAAS <code class="interfacename">AuthenticationProvider</code> implementations. Subclasses
+ must implement a method that creates the <code class="classname">LoginContext</code>. The
+ <code class="classname">AbstractJaasAuthenticationProvider</code> has a number of dependencies that can
+ be injected into it that are discussed below.</p><div class="section" title="21.2.1 JAAS CallbackHandler"><div class="titlepage"><div><div><h3 class="title"><a name="jaas-callbackhandler"></a>21.2.1 JAAS CallbackHandler</h3></div></div></div><p>Most JAAS <code class="literal">LoginModule</code>s require a callback of some sort. These
+ callbacks are usually used to obtain the username and password from the user.</p><p>In a Spring Security deployment, Spring Security is responsible for this user
+ interaction (via the authentication mechanism). Thus, by the time the authentication
+ request is delegated through to JAAS, Spring Security's authentication mechanism
+ will already have fully-populated an <code class="interfacename">Authentication</code>
+ object containing all the information required by the JAAS
+ <code class="literal">LoginModule</code>.</p><p>Therefore, the JAAS package for Spring Security provides two default callback
+ handlers, <code class="literal">JaasNameCallbackHandler</code> and
+ <code class="literal">JaasPasswordCallbackHandler</code>. Each of these callback handlers
+ implement <code class="literal">JaasAuthenticationCallbackHandler</code>. In most cases these
+ callback handlers can simply be used without understanding the internal
+ mechanics.</p><p>For those needing full control over the callback behavior, internally
+ <code class="classname">AbstractJaasAuthenticationProvider</code> wraps these
<code class="literal">JaasAuthenticationCallbackHandler</code>s with an
<code class="literal">InternalCallbackHandler</code>. The
- <code class="literal">InternalCallbackHandler</code> is the class that
- actually implements JAAS’ normal <code class="literal">CallbackHandler</code>
- interface. Any time that the JAAS <code class="literal">LoginModule</code> is
- used, it is passed a list of application context configured
- <code class="literal">InternalCallbackHandler</code>s. If the
+ <code class="literal">InternalCallbackHandler</code> is the class that actually implements
+ JAAS’ normal <code class="literal">CallbackHandler</code> interface. Any time that the JAAS
+ <code class="literal">LoginModule</code> is used, it is passed a list of application context
+ configured <code class="literal">InternalCallbackHandler</code>s. If the
<code class="literal">LoginModule</code> requests a callback against the
- <code class="literal">InternalCallbackHandler</code>s, the callback is in-turn
- passed to the <code class="literal">JaasAuthenticationCallbackHandler</code>s
- being wrapped.</p></div><div class="section" title="20.2.2 JAAS AuthorityGranter"><div class="titlepage"><div><div><h3 class="title"><a name="jaas-authoritygranter"></a>20.2.2 JAAS AuthorityGranter</h3></div></div></div><p>JAAS works with principals. Even "roles" are represented as
- principals in JAAS. Spring Security, on the other hand, works with
+ <code class="literal">InternalCallbackHandler</code>s, the callback is in-turn passed to the
+ <code class="literal">JaasAuthenticationCallbackHandler</code>s being wrapped.</p></div><div class="section" title="21.2.2 JAAS AuthorityGranter"><div class="titlepage"><div><div><h3 class="title"><a name="jaas-authoritygranter"></a>21.2.2 JAAS AuthorityGranter</h3></div></div></div><p>JAAS works with principals. Even "roles" are represented as principals in JAAS.
+ Spring Security, on the other hand, works with
<code class="interfacename">Authentication</code> objects. Each
- <code class="interfacename">Authentication</code> object contains a single
- principal, and multiple <code class="interfacename">GrantedAuthority</code>[]s. To
- facilitate mapping between these different concepts, Spring
- Security's JAAS package includes an
- <code class="literal">AuthorityGranter</code> interface.</p><p>An <code class="literal">AuthorityGranter</code> is responsible for
- inspecting a JAAS principal and returning a set of
- <code class="literal">String</code>s, representing the authorities assigned to the principal.
- For each returned authority string, the
- <code class="classname">JaasAuthenticationProvider</code> creates a
- <code class="classname">JaasGrantedAuthority</code> (which implements Spring
- Security’s <code class="interfacename">GrantedAuthority</code> interface) containing
- the authority string and the JAAS principal that the
+ <code class="interfacename">Authentication</code> object contains a single principal,
+ and multiple <code class="interfacename">GrantedAuthority</code>s. To facilitate
+ mapping between these different concepts, Spring Security's JAAS package includes an
+ <code class="literal">AuthorityGranter</code> interface.</p><p>An <code class="literal">AuthorityGranter</code> is responsible for inspecting a JAAS
+ principal and returning a set of <code class="literal">String</code>s, representing the
+ authorities assigned to the principal. For each returned authority string, the
+ <code class="classname">AbstractJaasAuthenticationProvider</code> creates a
+ <code class="classname">JaasGrantedAuthority</code> (which implements Spring Security’s
+ <code class="interfacename">GrantedAuthority</code> interface) containing the authority
+ string and the JAAS principal that the
<code class="interfacename">AuthorityGranter</code> was passed. The
- <code class="classname">JaasAuthenticationProvider</code> obtains the JAAS
- principals by firstly successfully authenticating the user’s
- credentials using the JAAS <code class="literal">LoginModule</code>, and then
- accessing the <code class="literal">LoginContext</code> it returns. A call to
- <code class="literal">LoginContext.getSubject().getPrincipals()</code> is
- made, with each resulting principal passed to each
- <code class="interfacename">AuthorityGranter</code> defined against the
- <code class="literal">JaasAuthenticationProvider.setAuthorityGranters(List)</code>
+ <code class="classname">AbstractJaasAuthenticationProvider</code> obtains the JAAS principals by
+ firstly successfully authenticating the user’s credentials using the JAAS
+ <code class="literal">LoginModule</code>, and then accessing the
+ <code class="literal">LoginContext</code> it returns. A call to
+ <code class="literal">LoginContext.getSubject().getPrincipals()</code> is made, with each
+ resulting principal passed to each <code class="interfacename">AuthorityGranter</code>
+ defined against the
+ <code class="literal">AbstractJaasAuthenticationProvider.setAuthorityGranters(List)</code>
property.</p><p>Spring Security does not include any production
- <code class="interfacename">AuthorityGranter</code>s given that every JAAS principal
- has an implementation-specific meaning. However, there is a
- <code class="literal">TestAuthorityGranter</code> in the unit tests that
- demonstrates a simple <code class="literal">AuthorityGranter</code>
- implementation.</p></div></div></div><div class="chapter" title="21. CAS Authentication"><div class="titlepage"><div><div><h2 class="title"><a name="cas"></a>21. CAS Authentication</h2></div></div></div><div class="section" title="21.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="cas-overview"></a>21.1 Overview</h2></div></div></div><p>JA-SIG produces an enterprise-wide single sign on system known as CAS. Unlike other
- initiatives, JA-SIG's Central Authentication Service is open source, widely used, simple to
- understand, platform independent, and supports proxy capabilities. Spring Security fully
- supports CAS, and provides an easy migration path from single-application deployments of
- Spring Security through to multiple-application deployments secured by an enterprise-wide CAS
- server.</p><p>You can learn more about CAS at <code class="literal">http://www.ja-sig.org/cas</code>. You will
- also need to visit this site to download the CAS Server files.</p></div><div class="section" title="21.2 How CAS Works"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="cas-how-it-works"></a>21.2 How CAS Works</h2></div></div></div><p>Whilst the CAS web site contains documents that detail the architecture of CAS, we present
- the general overview again here within the context of Spring Security. Spring Security 3.0
- supports CAS 3. At the time of writing, the CAS server was at version 3.3.</p><p>Somewhere in your enterprise you will need to setup a CAS server. The CAS server is simply
- a standard WAR file, so there isn't anything difficult about setting up your server. Inside
- the WAR file you will customise the login and other single sign on pages displayed to
- users.</p><p>When deploying a CAS 3.3 server, you will also need to specify an
+ <code class="interfacename">AuthorityGranter</code>s given that every JAAS principal has
+ an implementation-specific meaning. However, there is a
+ <code class="literal">TestAuthorityGranter</code> in the unit tests that demonstrates a simple
+ <code class="literal">AuthorityGranter</code> implementation.</p></div></div><div class="section" title="21.3 DefaultJaasAuthenticationProvider"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="jaas-defaultjaasauthenticationprovider"></a>21.3 DefaultJaasAuthenticationProvider</h2></div></div></div><p>The <code class="classname">DefaultJaasAuthenticationProvider</code> allows a JAAS
+ <code class="classname">Configuration</code> object to be injected into it as a dependency. It then
+ creates a <code class="classname">LoginContext</code> using the injected JAAS <code class="classname">Configuration</code>.
+ This means that <code class="classname">DefaultJaasAuthenticationProvider</code> is not bound any particular implementation
+ of <code class="classname">Configuration</code> as <code class="classname">JaasAuthenticationProvider</code> is.</p><div class="section" title="21.3.1 InMemoryConfiguration"><div class="titlepage"><div><div><h3 class="title"><a name="jaas-inmemoryconfiguration"></a>21.3.1 InMemoryConfiguration</h3></div></div></div><p>In order to make it easy to inject a <code class="classname">Configuration</code> into
+ <code class="classname">DefaultJaasAuthenticationProvider</code>, a default in memory
+ implementation named <code class="classname">InMemoryConfiguration</code> is provided. The
+ implementation constructor accepts a <code class="interfacename">Map</code> where each key represents a
+ login configuration name and the value represents an <code class="classname">Array</code> of
+ <code class="classname">AppConfigurationEntry</code>s.
+ <code class="classname">InMemoryConfiguration</code> also supports a default
+ <code class="classname">Array</code> of <code class="classname">AppConfigurationEntry</code> objects that
+ will be used if no mapping is found within the provided <code class="interfacename">Map</code>. For
+ details, refer to the class level javadoc of <code class="classname">InMemoryConfiguration</code>.</p></div><div class="section" title="21.3.2 DefaultJaasAuthenticationProvider Example Configuration"><div class="titlepage"><div><div><h3 class="title"><a name="jaas-djap-config"></a>21.3.2 DefaultJaasAuthenticationProvider Example Configuration</h3></div></div></div><p>While the Spring configuration for <code class="classname">InMemoryConfiguration</code> can be
+ more verbose than the standarad JAAS configuration files, using it in conjuction with
+ <code class="classname">DefaultJaasAuthenticationProvider</code> is more flexible than
+ <code class="classname">JaasAuthenticationProvider</code> since it not dependant on the default
+ <code class="classname">Configuration</code> implementation.</p><p>An example configuration of <code class="classname">DefaultJaasAuthenticationProvider</code> using
+ <code class="classname">InMemoryConfiguration</code> is provided below. Note that custom implementations of
+ <code class="classname">Configuration</code> can easily be injected into
+ <code class="classname">DefaultJaasAuthenticationProvider</code> as well.</p><pre class="programlisting">
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"jaasAuthProvider"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.authentication.jaas.DefaultJaasAuthenticationProvider"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"configuration"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.authentication.jaas.memory.InMemoryConfiguration"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><constructor-arg></span>
+ <span class="hl-tag"><map></span>
+ <span class="hl-comment"><!--
+ SPRINGSECURITY is the default loginContextName
+ for AbstractJaasAuthenticationProvider
+ --></span>
+ <span class="hl-tag"><entry</span> <span class="hl-attribute">key</span>=<span class="hl-value">"SPRINGSECURITY"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><array></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"javax.security.auth.login.AppConfigurationEntry"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">value</span>=<span class="hl-value">"sample.SampleLoginModule"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"><constructor-arg></span>
+ <span class="hl-tag"><util:constant</span> <span class="hl-attribute">static-field</span>=
+ <span class="hl-value">"javax.security.auth.login.AppConfigurationEntry$LoginModuleControlFlag.REQUIRED"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></constructor-arg></span>
+ <span class="hl-tag"><constructor-arg></span>
+ <span class="hl-tag"><map></span><span class="hl-tag"></map></span>
+ <span class="hl-tag"></constructor-arg></span>
+ <span class="hl-tag"></bean></span>
+ <span class="hl-tag"></array></span>
+ <span class="hl-tag"></entry></span>
+ <span class="hl-tag"></map></span>
+ <span class="hl-tag"></constructor-arg></span>
+ <span class="hl-tag"></bean></span>
+ <span class="hl-tag"></property></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authorityGranters"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><list></span>
+ <span class="hl-comment"><!-- You will need to write your own implementation of AuthorityGranter --></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.authentication.jaas.TestAuthorityGranter"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></list></span>
+ <span class="hl-tag"></property></span>
+<span class="hl-tag"></bean></span>
+</pre></div></div><div class="section" title="21.4 JaasAuthenticationProvider"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="jaas-jaasauthenticationprovider"></a>21.4 JaasAuthenticationProvider</h2></div></div></div><p>The <code class="classname">JaasAuthenticationProvider</code> assumes the default <code class="classname">Configuration</code> is an instance of
+ <a class="link" href="http://download.oracle.com/javase/1.4.2/docs/guide/security/jaas/spec/com/sun/security/auth/login/ConfigFile.html" target="_top">
+ ConfigFile</a>. This assumption is made in order to attempt to update the <code class="classname">Configuration</code>. The
+ <code class="classname">JaasAuthenticationProvider</code> then uses the default <code class="classname">Configuration</code> to create the
+ <code class="classname">LoginContext</code>.</p><p>Let’s assume we have a JAAS login configuration file,
+ <code class="literal">/WEB-INF/login.conf</code>, with the following contents:
+ </p><pre class="programlisting">
+JAASTest {
+ sample.SampleLoginModule required;
+};</pre><p>Like all Spring Security beans, the <code class="classname">JaasAuthenticationProvider</code>
+ is configured via the application context. The following definitions would correspond to
+ the above JAAS login configuration file: </p><pre class="programlisting">
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"jaasAuthenticationProvider"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.authentication.jaas.JaasAuthenticationProvider"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"loginConfig"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"/WEB-INF/login.conf"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"loginContextName"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"JAASTest"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"callbackHandlers"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><list></span>
+ <span class="hl-tag"><bean</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.authentication.jaas.JaasNameCallbackHandler"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><bean</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.authentication.jaas.JaasPasswordCallbackHandler"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></list></span>
+ <span class="hl-tag"></property></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authorityGranters"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><list></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.authentication.jaas.TestAuthorityGranter"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></list></span>
+ <span class="hl-tag"></property></span>
+<span class="hl-tag"></bean></span>
+</pre></div><div class="section" title="21.5 Running as a Subject"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="jaas-apiprovision"></a>21.5 Running as a Subject</h2></div></div></div><p>If configured, the <code class="classname">JaasApiIntegrationFilter</code> will attempt to
+ run as the <code class="literal">Subject</code> on the
+ <code class="classname">JaasAuthenticationToken</code>. This means that the
+ <code class="literal">Subject</code> can be accessed using:
+ </p><pre class="programlisting">
+ Subject subject = Subject.getSubject(AccessController.getContext());
+</pre><p>
+ This integration can easily be configured using the
+ <a class="link" href="#nsa-http-jaas-api-provision" title="jaas-api-provision">jaas-api-provision</a> attribute. This
+ feature is useful when integrating with legacy or external API's that rely on the
+ JAAS Subject being populated.</p></div></div><div class="chapter" title="22. CAS Authentication"><div class="titlepage"><div><div><h2 class="title"><a name="cas"></a>22. CAS Authentication</h2></div></div></div><div class="section" title="22.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="cas-overview"></a>22.1 Overview</h2></div></div></div><p>JA-SIG produces an enterprise-wide single sign on system known as CAS. Unlike other
+ initiatives, JA-SIG's Central Authentication Service is open source, widely used, simple
+ to understand, platform independent, and supports proxy capabilities. Spring Security
+ fully supports CAS, and provides an easy migration path from single-application
+ deployments of Spring Security through to multiple-application deployments secured by an
+ enterprise-wide CAS server.</p><p>You can learn more about CAS at <code class="literal">http://www.ja-sig.org/cas</code>. You will
+ also need to visit this site to download the CAS Server files.</p></div><div class="section" title="22.2 How CAS Works"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="cas-how-it-works"></a>22.2 How CAS Works</h2></div></div></div><p>Whilst the CAS web site contains documents that detail the architecture of CAS, we
+ present the general overview again here within the context of Spring Security. Spring Security
+ 3.x supports CAS 3. At the time of writing, the CAS server was at version 3.4.</p><p>Somewhere in your enterprise you will need to setup a CAS server. The CAS server is
+ simply a standard WAR file, so there isn't anything difficult about setting up your
+ server. Inside the WAR file you will customise the login and other single sign on pages
+ displayed to users.</p><p>When deploying a CAS 3.4 server, you will also need to specify an
<code class="literal">AuthenticationHandler</code> in the
<code class="filename">deployerConfigContext.xml</code> included with CAS. The
<code class="literal">AuthenticationHandler</code> has a simple method that returns a boolean as to
@@ -3611,104 +4004,417 @@ JAASTest {
download and deploy the server war file, it is set up to successfully authenticate users who
enter a password matching their username, which is useful for testing.</p><p>Apart from the CAS server itself, the other key players are of course the secure web
applications deployed throughout your enterprise. These web applications are known as
- "services". There are two types of services: standard services and proxy services. A proxy
- service is able to request resources from other services on behalf of the user. This will be
- explained more fully later.</p></div><div class="section" title="21.3 Configuration of CAS Client"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="cas-client"></a>21.3 Configuration of CAS Client</h2></div></div></div><p>The web application side of CAS is made easy due to Spring Security. It is assumed you
- already know the basics of using Spring Security, so these are not covered again below. We'll
- assume a namespace based configuration is being used and add in the CAS beans as required. </p><p>You will need to add a <code class="classname">ServiceProperties</code> bean to your application
- context. This represents your CAS service:</p><p>
- </p><pre class="programlisting">
- <bean id="serviceProperties"
- class="org.springframework.security.cas.ServiceProperties">
- <property name="service"
- value="https://localhost:8443/cas-sample/j_spring_cas_security_check"/>
- <property name="sendRenew" value="false"/>
- </bean>
- </pre><p>
- </p><p>The <code class="literal">service</code> must equal a URL that will be monitored by the
- <code class="literal">CasAuthenticationFilter</code>. The <code class="literal">sendRenew</code> defaults to
- false, but should be set to true if your application is particularly sensitive. What this
- parameter does is tell the CAS login service that a single sign on login is unacceptable.
- Instead, the user will need to re-enter their username and password in order to gain access to
- the service.</p><p>The following beans should be configured to commence the CAS authentication process
- (assuming you're using a namespace configuration):</p><p>
- </p><pre class="programlisting">
-<security:http entry-point-ref="casEntryPoint">
+ "services". There are three types of services. Those that authenticate service tickets, those that
+ can obtain proxy tickets, and those that authenticate proxy tickets. Authenticating a proxy ticket
+ differs because the list of proxies must be validated and often times a proxy ticket can be reused.</p><div class="section" title="22.2.1 Spring Security and CAS Interaction Sequence"><div class="titlepage"><div><div><h3 class="title"><a name="cas-sequence"></a>22.2.1 Spring Security and CAS Interaction Sequence</h3></div></div></div><p>The basic interaction between a web browser, CAS server and a
+ Spring Security-secured service is as follows:</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>The web user is browsing the service's public pages. CAS or
+ Spring Security is not involved.</p></li><li class="listitem"><p>The user eventually requests a page that is either secure or
+ one of the beans it uses is secure. Spring Security's
+ <code class="classname">ExceptionTranslationFilter</code> will detect the
+ <code class="classname">AccessDeniedException</code> or <code class="classname">AuthenticationException</code>.</p></li><li class="listitem"><p>Because the user's <code class="interfacename">Authentication</code> object (or lack
+ thereof) caused an <code class="classname">AuthenticationException</code>, the
+ <code class="classname">ExceptionTranslationFilter</code> will call the configured
+ <code class="interfacename">AuthenticationEntryPoint</code>. If using CAS, this will be
+ the <code class="classname">CasAuthenticationEntryPoint</code> class.</p></li><li class="listitem"><p>The <code class="classname">CasAuthenticationEntryPoint</code> will redirect the user's browser
+ to the CAS server. It will also indicate a <code class="literal">service</code> parameter, which
+ is the callback URL for the Spring Security service (your application). For example, the
+ URL to which the browser is redirected might be
+ <code class="literal">https://my.company.com/cas/login?service=https%3A%2F%2Fserver3.company.com%2Fwebapp%2Fj_spring_cas_security_check</code>.</p></li><li class="listitem"><p>After the user's browser redirects to CAS, they will be
+ prompted for their username and password. If the user presents a
+ session cookie which indicates they've previously logged on, they
+ will not be prompted to login again (there is an exception to this
+ procedure, which we'll cover later). CAS will use the
+ <code class="interfacename">PasswordHandler</code> (or
+ <code class="interfacename">AuthenticationHandler</code> if using CAS 3.0)
+ discussed above to decide whether the username and password is
+ valid.</p></li><li class="listitem"><p>Upon successful login, CAS will redirect the user's browser
+ back to the original service. It will also include a
+ <code class="literal">ticket</code> parameter, which is an opaque string
+ representing the "service ticket". Continuing our earlier example,
+ the URL the browser is redirected to might be
+ <code class="literal">https://server3.company.com/webapp/j_spring_cas_security_check?ticket=ST-0-ER94xMJmn6pha35CQRoZ</code>.</p></li><li class="listitem"><p>Back in the service web application, the <code class="classname">CasAuthenticationFilter</code> is
+ always listening for requests to <code class="literal">/j_spring_cas_security_check</code> (this
+ is configurable, but we'll use the defaults in this introduction). The processing filter
+ will construct a <code class="classname">UsernamePasswordAuthenticationToken</code> representing the
+ service ticket. The principal will be equal to
+ <code class="literal">CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER</code>, whilst the credentials
+ will be the service ticket opaque value. This authentication request will then be handed
+ to the configured <code class="interfacename">AuthenticationManager</code>.</p></li><li class="listitem"><p>The <code class="interfacename">AuthenticationManager</code> implementation
+ will be the <code class="classname">ProviderManager</code>, which is in turn
+ configured with the <code class="classname">CasAuthenticationProvider</code>.
+ The <code class="classname">CasAuthenticationProvider</code> only responds to
+ <code class="classname">UsernamePasswordAuthenticationToken</code>s containing
+ the CAS-specific principal (such as
+ <code class="literal">CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER</code>)
+ and <code class="classname">CasAuthenticationToken</code>s (discussed
+ later).</p></li><li class="listitem"><p><code class="classname">CasAuthenticationProvider</code> will validate the service ticket using a
+ <code class="interfacename">TicketValidator</code> implementation. This will typically be a
+ <code class="classname">Cas20ServiceTicketValidator</code> which is one of the classes
+ included in the CAS client library. In the event the application needs to validate proxy tickets, the
+ <code class="classname">Cas20ProxyTicketValidator</code> is used. The
+ <code class="interfacename">TicketValidator</code> makes an HTTPS request to the CAS server in order to
+ validate the service ticket. It may also include a proxy callback URL, which is included in this example:
+ <code class="literal">https://my.company.com/cas/proxyValidate?service=https%3A%2F%2Fserver3.company.com%2Fwebapp%2Fj_spring_cas_security_check&ticket=ST-0-ER94xMJmn6pha35CQRoZ&pgtUrl=https://server3.company.com/webapp/j_spring_cas_security_proxyreceptor</code>.
+ </p></li><li class="listitem"><p>Back on the CAS server, the validation request will be
+ received. If the presented service ticket matches the service URL
+ the ticket was issued to, CAS will provide an affirmative response
+ in XML indicating the username. If any proxy was involved in the
+ authentication (discussed below), the list of proxies is also
+ included in the XML response.</p></li><li class="listitem"><p>[OPTIONAL] If the request to the CAS validation service included the proxy callback
+ URL (in the <code class="literal">pgtUrl</code> parameter), CAS will include a
+ <code class="literal">pgtIou</code> string in the XML response. This <code class="literal">pgtIou</code>
+ represents a proxy-granting ticket IOU. The CAS server will then create its own HTTPS
+ connection back to the <code class="literal">pgtUrl</code>. This is to mutually authenticate the
+ CAS server and the claimed service URL. The HTTPS connection will be used to send a
+ proxy granting ticket to the original web application. For example,
+ <code class="literal">https://server3.company.com/webapp/j_spring_cas_security_proxyreceptor?pgtIou=PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt&pgtId=PGT-1-si9YkkHLrtACBo64rmsi3v2nf7cpCResXg5MpESZFArbaZiOKH</code>.</p></li><li class="listitem"><p>The <code class="classname">Cas20TicketValidator</code> will parse the XML received from the
+ CAS server. It will return to the <code class="classname">CasAuthenticationProvider</code> a
+ <code class="literal">TicketResponse</code>, which includes the username (mandatory), proxy list
+ (if any were involved), and proxy-granting ticket IOU (if the proxy callback was
+ requested).</p></li><li class="listitem"><p>Next <code class="literal">CasAuthenticationProvider</code> will call
+ a configured <code class="literal">CasProxyDecider</code>. The
+ <code class="literal">CasProxyDecider</code> indicates whether the proxy
+ list in the <code class="literal">TicketResponse</code> is acceptable to the
+ service. Several implementations are provided with Spring
+ Security: <code class="literal">RejectProxyTickets</code>,
+ <code class="literal">AcceptAnyCasProxy</code> and
+ <code class="literal">NamedCasProxyDecider</code>. These names are largely
+ self-explanatory, except <code class="literal">NamedCasProxyDecider</code>
+ which allows a <code class="literal">List</code> of trusted proxies to be
+ provided.</p></li><li class="listitem"><p><code class="classname">CasAuthenticationProvider</code> will next
+ request a <code class="interfacename">AuthenticationUserDetailsService</code> to load the
+ <code class="interfacename">GrantedAuthority</code> objects that apply to the user
+ contained in the <code class="interfacename">Assertion</code>.</p></li><li class="listitem"><p>If there were no problems,
+ <code class="classname">CasAuthenticationProvider</code> constructs a
+ <code class="classname">CasAuthenticationToken</code> including the details
+ contained in the <code class="interfacename">TicketResponse</code> and the
+ <code class="interfacename">GrantedAuthority</code>s.</p></li><li class="listitem"><p>Control then returns to
+ <code class="classname">CasAuthenticationFilter</code>, which places the created
+ <code class="classname">CasAuthenticationToken</code> in the security context.</p></li><li class="listitem"><p>The user's browser is redirected to the original page that
+ caused the <code class="classname">AuthenticationException</code> (or a
+ <a class="link" href="#form-login-flow-handling" title="9.4.1 Application Flow on Authentication Success and Failure">custom destination</a> depending on
+ the configuration).</p></li></ol></div><p>It's good that you're still here! Let's now look at how this is configured</p></div></div><div class="section" title="22.3 Configuration of CAS Client"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="cas-client"></a>22.3 Configuration of CAS Client</h2></div></div></div><p>The web application side of CAS is made easy due to Spring Security. It is assumed you
+ already know the basics of using Spring Security, so these are not covered again below.
+ We'll assume a namespace based configuration is being used and add in the CAS beans as
+ required. Each section builds upon the previous section. A full
+ <a class="link" href="#cas-sample" title="4.5 CAS Sample">CAS sample application</a> can be found in the Spring
+ Security Samples.</p><div class="section" title="22.3.1 Service Ticket Authentication"><div class="titlepage"><div><div><h3 class="title"><a name="cas-st"></a>22.3.1 Service Ticket Authentication</h3></div></div></div><p>This section describes how to setup Spring Security to authenticate Service Tickets. Often times
+ this is all a web application requires. You will need to add a <code class="classname">ServiceProperties</code>
+ bean to your application context. This represents your CAS service:</p><p> </p><pre class="programlisting">
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"serviceProperties"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.cas.ServiceProperties"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"service"</span>
+ <span class="hl-attribute">value</span>=<span class="hl-value">"https://localhost:8443/cas-sample/j_spring_cas_security_check"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"sendRenew"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"false"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></bean></span>
+ </pre><p> </p><p>The <code class="literal">service</code> must equal a URL that will be monitored by the
+ <code class="literal">CasAuthenticationFilter</code>. The <code class="literal">sendRenew</code> defaults to
+ false, but should be set to true if your application is particularly sensitive. What
+ this parameter does is tell the CAS login service that a single sign on login is
+ unacceptable. Instead, the user will need to re-enter their username and password in
+ order to gain access to the service.</p><p>The following beans should be configured to commence the CAS authentication process
+ (assuming you're using a namespace configuration):</p><p> </p><pre class="programlisting">
+ <span class="hl-tag"><security:http</span> <span class="hl-attribute">entry-point-ref</span>=<span class="hl-value">"casEntryPoint"</span><span class="hl-tag">></span>
...
- <custom-filter position="FORM_LOGIN_FILTER" ref="myFilter" />
-</security:http>
+ <span class="hl-tag"><security:custom-filter</span> <span class="hl-attribute">position</span>=<span class="hl-value">"CAS_FILTER"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"casFilter"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"></security:http></span>
-<bean id="casFilter"
- class="org.springframework.security.cas.web.CasAuthenticationFilter">
- <property name="authenticationManager" ref="authenticationManager"/>
-</bean>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"casFilter"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.cas.web.CasAuthenticationFilter"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationManager"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"authenticationManager"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></bean></span>
-<bean id="casEntryPoint"
- class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
- <property name="loginUrl" value="https://localhost:9443/cas/login"/>
- <property name="serviceProperties" ref="serviceProperties"/>
-</bean>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"casEntryPoint"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.cas.web.CasAuthenticationEntryPoint"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"loginUrl"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"https://localhost:9443/cas/login"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"serviceProperties"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"serviceProperties"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></bean></span>
- </pre><p>
- </p><p> The <code class="classname">CasAuthenticationEntryPoint</code> should be selected to drive
- authentication using <a class="link" href="#ns-entry-point-ref" title="Setting a Custom AuthenticationEntryPoint"><code class="literal">entry-point-ref</code></a>. </p><p>The <code class="classname">CasAuthenticationFilter</code> has very similar properties to the
- <code class="classname">UsernamePasswordAuthenticationFilter</code> (used for form-based logins).
- </p><p>For CAS to operate, the <code class="classname">ExceptionTranslationFilter</code> must have its
- <code class="literal">authenticationEntryPoint</code> property set to the
- <code class="classname">CasAuthenticationEntryPoint</code> bean.</p><p>The <code class="classname">CasAuthenticationEntryPoint</code> must refer to the
- <code class="classname">ServiceProperties</code> bean (discussed above), which provides the URL to the
- enterprise's CAS login server. This is where the user's browser will be redirected.</p><p>Next you need to add a <code class="literal">CasAuthenticationProvider</code> and its collaborators: </p><pre class="programlisting">
- <security:authentication-manager alias="authenticationManager">
- <security:authentication-provider ref="casAuthenticationProvider" />
- </security:authentication-manager>
+ </pre><p> </p><p>For CAS to operate, the <code class="classname">ExceptionTranslationFilter</code> must have
+ its <code class="literal">authenticationEntryPoint</code> property set to the
+ <code class="classname">CasAuthenticationEntryPoint</code> bean. This can easily be done using
+ <a class="link" href="#ns-entry-point-ref" title="Setting a Custom AuthenticationEntryPoint"><code class="literal">entry-point-ref</code></a> as is
+ done in the example above. The <code class="classname">CasAuthenticationEntryPoint</code> must refer to the
+ <code class="classname">ServiceProperties</code> bean (discussed above), which provides the URL
+ to the enterprise's CAS login server. This is where the user's browser will be
+ redirected.</p><p>The <code class="classname">CasAuthenticationFilter</code> has very similar properties to the
+ <code class="classname">UsernamePasswordAuthenticationFilter</code> (used for form-based
+ logins). You can use these properties to customize things like behavior for authentication
+ success and failure.</p><p>Next you need to add a <code class="classname">CasAuthenticationProvider</code> and its
+ collaborators: </p><pre class="programlisting">
+ <span class="hl-tag"><security:authentication-manager</span> <span class="hl-attribute">alias</span>=<span class="hl-value">"authenticationManager"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><security:authentication-provider</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"casAuthenticationProvider"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"></security:authentication-manager></span>
+
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"casAuthenticationProvider"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.cas.authentication.CasAuthenticationProvider"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationUserDetailsService"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"userService"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"></bean></span>
+ <span class="hl-tag"></property></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"serviceProperties"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"serviceProperties"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"ticketValidator"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.jasig.cas.client.validation.Cas20ServiceTicketValidator"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">index</span>=<span class="hl-value">"0"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"https://localhost:9443/cas"</span><span class="hl-tag"> /></span>
+ <span class="hl-tag"></bean></span>
+ <span class="hl-tag"></property></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"key"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"an_id_for_this_auth_provider_only"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></bean></span>
+
+ <span class="hl-tag"><security:user-service</span> <span class="hl-attribute">id</span>=<span class="hl-value">"userService"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><security:user</span> <span class="hl-attribute">name</span>=<span class="hl-value">"joe"</span> <span class="hl-attribute">password</span>=<span class="hl-value">"joe"</span> <span class="hl-attribute">authorities</span>=<span class="hl-value">"ROLE_USER"</span><span class="hl-tag"> /></span>
+ ...
+ <span class="hl-tag"></security:user-service></span>
+ </pre><p> The <code class="classname">CasAuthenticationProvider</code> uses a
+ <code class="interfacename">UserDetailsService</code> instance to load the authorities for a
+ user, once they have been authenticated by CAS. We've shown a simple in-memory setup
+ here. Note that the <code class="classname">CasAuthenticationProvider</code> does not actually use
+ the password for authentication, but it does use the authorities.</p><p>The beans are all reasonably self-explanatory if you refer back to the
+ <a class="link" href="#cas-how-it-works" title="22.2 How CAS Works">How CAS Works</a> section.</p><p>This completes the most basic configuration for CAS. If you haven't made any
+ mistakes, your web application should happily work within the
+ framework of CAS single sign on. No other parts of Spring Security
+ need to be concerned about the fact CAS handled authentication. In the following sections
+ we will discuss some (optional) more advanced configurations.</p></div><div class="section" title="22.3.2 Single Logout"><div class="titlepage"><div><div><h3 class="title"><a name="cas-singlelogout"></a>22.3.2 Single Logout</h3></div></div></div><p>The CAS protocol supports Single Logout and can be easily added to your Spring
+ Security configuration. Below are updates to the Spring Security configuration
+ that handle Single Logout </p><pre class="programlisting">
+ <span class="hl-tag"><security:http</span> <span class="hl-attribute">entry-point-ref</span>=<span class="hl-value">"casEntryPoint"</span><span class="hl-tag">></span>
+ ...
+ <span class="hl-tag"><security:logout</span> <span class="hl-attribute">logout-success-url</span>=<span class="hl-value">"/cas-logout.jsp"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><security:custom-filter</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"requestSingleLogoutFilter"</span> <span class="hl-attribute">before</span>=<span class="hl-value">"LOGOUT_FILTER"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><security:custom-filter</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"singleLogoutFilter"</span> <span class="hl-attribute">before</span>=<span class="hl-value">"CAS_FILTER"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></security:http></span>
+
+ <span class="hl-comment"><!-- This filter handles a Single Logout Request from the CAS Server --></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"singleLogoutFilter"</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.jasig.cas.client.session.SingleSignOutFilter"</span><span class="hl-tag">/></span>
+ <span class="hl-comment"><!-- This filter redirects to the CAS Server to signal Single Logout should be performed --></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"requestSingleLogoutFilter"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.web.authentication.logout.LogoutFilter"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">value</span>=<span class="hl-value">"https://localhost:9443/cas/logout"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><constructor-arg></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=
+ <span class="hl-value">"org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></constructor-arg></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"filterProcessesUrl"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"/j_spring_cas_security_logout"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></bean></span>
+ </pre><p> The <code class="literal">logout</code> element logs the user out of the local application, but
+ does not terminate the session with the CAS server or any other applications that have been logged
+ into. The <code class="literal">requestSingleLogoutFilter</code> filter will allow the url of
+ <code class="literal">/spring_security_cas_logout</code> to be requested to redirect the application to the
+ configured CAS Server logout url. Then the CAS Server will send a Single Logout request to all the
+ services that were signed into. The <code class="literal">singleLogoutFilter</code> handles the Single Logout
+ request by looking up the <code class="literal">HttpSession</code> in a static <code class="interfacename">Map</code>
+ and then invalidating it.</p><p>It might be confusing why both the <code class="literal">logout</code> element and the
+ <code class="literal">singleLogoutFilter</code> are needed. It is considered best practice to logout locally
+ first since the <code class="literal">SingleSignOutFilter</code> just stores the
+ <code class="interfacename">HttpSession</code> in a static <code class="interfacename">Map</code> in order to
+ call invalidate on it. With the configuration above, the flow of logout would be:
+ </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem">The user requests <code class="literal">/j_spring_security_logout</code> which would log the user
+ out of the local application and send the user to the logout success page.</li><li class="listitem">The logout success page, <code class="literal">/cas-logout.jsp</code>, should instruct the user
+ to click a link pointing to <code class="literal">/j_spring_cas_security_logout</code> in order to logout
+ out of all applications.</li><li class="listitem">When the user clicks the link, the user is redirected to the CAS single logout URL
+ (<code class="literal">https://localhost:9443/cas/logout</code>).</li><li class="listitem">On the CAS Server side, the CAS single logout URL then submits single logout requests to
+ all the CAS Services. On the CAS Service side, JASIG's
+ <code class="classname">SingleSignOutFilter</code> processes the logout request by invaliditing the
+ original session.</li></ol></div><p>
+ </p><p>The next step is to add the following to your web.xml
+ </p><pre class="programlisting">
+ <span class="hl-tag"><filter></span>
+ <span class="hl-tag"><filter-name></span>characterEncodingFilter<span class="hl-tag"></filter-name></span>
+ <span class="hl-tag"><filter-class></span>org.springframework.web.filter.CharacterEncodingFilter<span class="hl-tag"></filter-class></span>
+ <span class="hl-tag"><init-param></span>
+ <span class="hl-tag"><param-name></span>encoding<span class="hl-tag"></param-name></span>
+ <span class="hl-tag"><param-value></span>UTF-8<span class="hl-tag"></param-value></span>
+ <span class="hl-tag"></init-param></span>
+ <span class="hl-tag"></filter></span>
+ <span class="hl-tag"><filter-mapping></span>
+ <span class="hl-tag"><filter-name></span>characterEncodingFilter<span class="hl-tag"></filter-name></span>
+ <span class="hl-tag"><url-pattern></span>/*<span class="hl-tag"></url-pattern></span>
+ <span class="hl-tag"></filter-mapping></span>
+ <span class="hl-tag"><listener></span>
+ <span class="hl-tag"><listener-class></span>org.jasig.cas.client.session.SingleSignOutHttpSessionListener<span class="hl-tag"></listener-class></span>
+ <span class="hl-tag"></listener></span></pre><p>When using the SingleSignOutFilter you might encounter some encoding issues. Therefore it is
+ recommended to add the <code class="classname">CharacterEncodingFilter</code> to ensure that the character
+ encoding is correct when using the <code class="classname">SingleSignOutFilter</code>. Again, refer to JASIG's
+ documentation for details. The <code class="classname">SingleSignOutHttpSessionListener</code> ensures that
+ when an <code class="interfacename">HttpSession</code> expires, the mapping used for single logout is
+ removed.</p></div><div class="section" title="22.3.3 Authenticating to a Stateless Service with CAS"><div class="titlepage"><div><div><h3 class="title"><a name="cas-pt-client"></a>22.3.3 Authenticating to a Stateless Service with CAS</h3></div></div></div><p>This section describes how to authenticate to a service using CAS. In other words,
+ this section discusses how to setup a client that uses a service that authenticates with
+ CAS. The next section describes how to setup a stateless service to Authenticate
+ using CAS.</p><div class="section" title="Configuring CAS to Obtain Proxy Granting Tickets"><div class="titlepage"><div><div><h4 class="title"><a name="cas-pt-client-config"></a>Configuring CAS to Obtain Proxy Granting Tickets</h4></div></div></div><p>In order to authenticate to a stateless service, the application needs to obtain a proxy granting ticket
+ (PGT). This section describes how to configure Spring Security to obtain a PGT building upon then
+ <a class="link" href="cas-st" target="_top">Service Ticket Authentication</a> configuration.</p><p>The first step is to include a <code class="classname">ProxyGrantingTicketStorage</code> in your Spring Security
+ configuration. This is used to store PGT's that are obtained by the
+ <code class="classname">CasAuthenticationFilter</code> so that they can be used to obtain proxy tickets. An example
+ configuration is shown below </p><pre class="programlisting">
+ <span class="hl-comment"><!--
+ NOTE: In a real application you should not use an in memory implementation. You will also want
+ to ensure to clean up expired tickets by calling ProxyGrantingTicketStorage.cleanup()
+ --></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"pgtStorage"</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl"</span><span class="hl-tag">/></span>
+</pre><p>The next step is to update the <code class="classname">CasAuthenticationProvider</code> to be able to obtain proxy
+ tickets. To do this replace the <code class="classname">Cas20ServiceTicketValidator</code> with a
+ <code class="classname">Cas20ProxyTicketValidator</code>. The <code class="literal">proxyCallbackUrl</code> should be set to
+ a URL that the application will receive PGT's at. Last, the configuration should also reference the
+ <code class="classname">ProxyGrantingTicketStorage</code> so it can use a PGT to obtain proxy tickets.
+ You can find an example of the configuration changes that should be made below.
+</p><pre class="programlisting">
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"casAuthenticationProvider"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.cas.authentication.CasAuthenticationProvider"</span><span class="hl-tag">></span>
+ ...
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"ticketValidator"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.jasig.cas.client.validation.Cas20ProxyTicketValidator"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">value</span>=<span class="hl-value">"https://localhost:9443/cas"</span><span class="hl-tag">/></span>
- <bean id="casAuthenticationProvider"
- class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
- <property name="userDetailsService" ref="userService"/>
- <property name="serviceProperties" ref="serviceProperties" />
- <property name="ticketValidator">
- <bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
- <constructor-arg index="0" value="https://localhost:9443/cas" />
- </bean>
- </property>
- <property name="key" value="an_id_for_this_auth_provider_only"/>
- </bean>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"proxyCallbackUrl"</span>
+ <span class="hl-attribute">value</span>=<span class="hl-value">"https://localhost:8443/cas-sample/j_spring_cas_security_proxyreceptor"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"proxyGrantingTicketStorage"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"pgtStorage"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></bean></span>
+ <span class="hl-tag"></property></span>
+ <span class="hl-tag"></bean></span>
+</pre><p>The last step is to update the <code class="classname">CasAuthenticationFilter</code> to accept PGT and to store them
+ in the <code class="classname">ProxyGrantingTicketStorage</code>. It is important the the <code class="literal">proxyReceptorUrl</code>
+ matches the <code class="literal">proxyCallbackUrl</code> of the <code class="classname">Cas20ProxyTicketValidator</code>. An example
+ configuration is shown below.
+</p><pre class="programlisting">
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"casFilter"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.cas.web.CasAuthenticationFilter"</span><span class="hl-tag">></span>
+ ...
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"proxyGrantingTicketStorage"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"pgtStorage"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"proxyReceptorUrl"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"/j_spring_cas_security_proxyreceptor"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></bean></span>
+</pre></div><div class="section" title="Calling a Stateless Service Using a Proxy Ticket"><div class="titlepage"><div><div><h4 class="title"><a name="cas-pt-client-sample"></a>Calling a Stateless Service Using a Proxy Ticket</h4></div></div></div><p>Now that Spring Security obtains PGTs, you can use them to create proxy tickets which can be used to authenticate
+ to a stateless service. The <a class="link" href="#cas-sample" title="4.5 CAS Sample">CAS sample application</a> contains a working example in
+ the <code class="classname">ProxyTicketSampleServlet</code>. Example code can be found below:
+</p><pre class="programlisting">
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ // NOTE: The CasAuthenticationToken can also be obtained using
+ // SecurityContextHolder.getContext().getAuthentication()
+ final CasAuthenticationToken token = (CasAuthenticationToken) request.getUserPrincipal();
+ // proxyTicket could be reused to make calls to the CAS service even if the
+ // target url differs
+ final String proxyTicket = token.getAssertion().getPrincipal().getProxyTicketFor(targetUrl);
- <security:user-service id="userService">
- <security:user name="joe" password="joe" authorities="ROLE_USER" />
+ // Make a remote call using the proxy ticket
+ final String serviceUrl = targetUrl+"?ticket="+URLEncoder.encode(proxyTicket, "UTF-8");
+ String proxyResponse = CommonUtils.getResponseFromServer(serviceUrl, "UTF-8");
+ ...
+ }
+</pre></div></div><div class="section" title="22.3.4 Proxy Ticket Authentication"><div class="titlepage"><div><div><h3 class="title"><a name="cas-pt"></a>22.3.4 Proxy Ticket Authentication</h3></div></div></div><p>The <code class="classname">CasAuthenticationProvider</code> distinguishes
+ between stateful and stateless clients. A stateful client is
+ considered any that submits to the <code class="literal">filterProcessUrl</code> of the
+ <code class="classname">CasAuthenticationFilter</code>. A stateless client is any that
+ presents an authentication request to <code class="classname">CasAuthenticationFilter</code>
+ on a URL other than the <code class="literal">filterProcessUrl</code>.</p><p>Because remoting protocols have no way of presenting themselves
+ within the context of an <code class="classname">HttpSession</code>, it isn't
+ possible to rely on the default practice of storing the security context in the
+ session between requests. Furthermore, because the CAS server invalidates a
+ ticket after it has been validated by the <code class="literal">TicketValidator</code>,
+ presenting the same proxy ticket on subsequent requests will not
+ work.</p><p>One obvious option is to not use CAS at all for remoting
+ protocol clients. However, this would eliminate many of the desirable
+ features of CAS. As a middle-ground, the
+ <code class="literal">CasAuthenticationProvider</code> uses a
+ <code class="literal">StatelessTicketCache</code>. This is used solely for stateless clients
+ which use a principal equal to
+ <code class="literal">CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER</code>. What
+ happens is the <code class="literal">CasAuthenticationProvider</code> will store
+ the resulting <code class="literal">CasAuthenticationToken</code> in the
+ <code class="literal">StatelessTicketCache</code>, keyed on the proxy ticket.
+ Accordingly, remoting protocol clients can present the same proxy
+ ticket and the <code class="literal">CasAuthenticationProvider</code> will not
+ need to contact the CAS server for validation (aside from the first
+ request). Once authenticated, the proxy ticket could be used for URLs other than the
+ original target service.</p><p>This section builds upon the previous sections to accomodate proxy ticket authentication.
+ The first step is to specify to authenticate all artifacts as shown below.
+</p><pre class="programlisting">
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"serviceProperties"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.cas.ServiceProperties"</span><span class="hl-tag">></span>
...
- </security:user-service>
- </pre><p> The
- <code class="classname">CasAuthenticationProvider</code> uses a
- <code class="interfacename">UserDetailsService</code> instance to load the authorities for a
- user, once they have been authentiated by CAS. We've shown a simple in-memory setup here. </p><p>The beans are all reasonable self-explanatory if you refer back to the "How CAS Works"
- section.</p></div></div><div class="chapter" title="22. X.509 Authentication"><div class="titlepage"><div><div><h1 class="title"><a name="x509"></a>X.509 Authentication</h1></div></div></div><div class="section" title="22.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="x509-overview"></a>22.1 Overview</h2></div></div></div><p>The most common use of X.509 certificate authentication is in verifying the identity
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticateAllArtifacts"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"true"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></bean></span>
+</pre><p>The next step is to specify <code class="literal">serviceProperties</code> and the
+ <code class="literal">authenticationDetailsSource</code> for the <code class="classname">CasAuthenticationFilter</code>.
+ The <code class="literal">serviceProperties</code> property instructs the
+ <code class="classname">CasAuthenticationFilter</code> to attempt to authenticate all artifacts instead of only
+ ones present on the <code class="literal">filterProcessUrl</code>. The
+ <code class="classname">ServiceAuthenticationDetailsSource</code> creates a
+ <code class="interfacename">ServiceAuthenticationDetails</code> that ensures the current URL, based
+ upon the <code class="literal">HttpServletRequest</code>, is used as the service URL when validating the ticket.
+ The method for generating the service URL can be customized by injecting a custom
+ <code class="literal">AuthenticationDetailsSource</code> that returns a custom
+ <code class="interfacename">ServiceAuthenticationDetails</code>.</p><pre class="programlisting">
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"casFilter"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.cas.web.CasAuthenticationFilter"</span><span class="hl-tag">></span>
+ ...
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"serviceProperties"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"serviceProperties"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"authenticationDetailsSource"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=
+ <span class="hl-value">"org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></property></span>
+ <span class="hl-tag"></bean></span>
+</pre><p>You will also need to update the <code class="classname">CasAuthenticationProvider</code> to handle proxy tickets.
+ To do this replace the <code class="classname">Cas20ServiceTicketValidator</code> with a
+ <code class="classname">Cas20ProxyTicketValidator</code>. You will need to configure the
+ <code class="literal">statelessTicketCache</code> and which proxies you want to accept. You can find an example of the updates
+ required to accept all proxies below.
+</p><pre class="programlisting">
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"casAuthenticationProvider"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.cas.authentication.CasAuthenticationProvider"</span><span class="hl-tag">></span>
+ ...
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"ticketValidator"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.jasig.cas.client.validation.Cas20ProxyTicketValidator"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">value</span>=<span class="hl-value">"https://localhost:9443/cas"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"acceptAnyProxy"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"true"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></bean></span>
+ <span class="hl-tag"></property></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"statelessTicketCache"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.cas.authentication.EhCacheBasedTicketCache"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"cache"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"net.sf.ehcache.Cache"</span>
+ <span class="hl-attribute">init-method</span>=<span class="hl-value">"initialise"</span> <span class="hl-attribute">destroy-method</span>=<span class="hl-value">"dispose"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">value</span>=<span class="hl-value">"casTickets"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">value</span>=<span class="hl-value">"50"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">value</span>=<span class="hl-value">"true"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">value</span>=<span class="hl-value">"false"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">value</span>=<span class="hl-value">"3600"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"><constructor-arg</span> <span class="hl-attribute">value</span>=<span class="hl-value">"900"</span><span class="hl-tag">/></span>
+ <span class="hl-tag"></bean></span>
+ <span class="hl-tag"></property></span>
+ <span class="hl-tag"></bean></span>
+ <span class="hl-tag"></property></span>
+ <span class="hl-tag"></bean></span>
+</pre></div></div></div><div class="chapter" title="23. X.509 Authentication"><div class="titlepage"><div><div><h1 class="title"><a name="x509"></a>X.509 Authentication</h1></div></div></div><div class="section" title="23.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="x509-overview"></a>23.1 Overview</h2></div></div></div><p>The most common use of X.509 certificate authentication is in verifying the identity
of a server when using SSL, most commonly when using HTTPS from a browser. The browser
will automatically check that the certificate presented by a server has been issued (ie
digitally signed) by one of a list of trusted certificate authorities which it
maintains.</p><p>You can also use SSL with <span class="quote">“<span class="quote">mutual authentication</span>”</span>; the server will then
request a valid certificate from the client as part of the SSL handshake. The server
- will authenticate the client by checking that its certificate is signed by an
- acceptable authority. If a valid certificate has been provided, it can be obtained
- through the servlet API in an application. Spring Security X.509 module extracts the
- certificate using a filter. It maps the certificate to an application user and loads that
- user's set of granted authorities for use with the standard Spring Security infrastructure.</p><p>You should be familiar with using certificates and setting up client authentication
+ will authenticate the client by checking that its certificate is signed by an acceptable
+ authority. If a valid certificate has been provided, it can be obtained through the
+ servlet API in an application. Spring Security X.509 module extracts the certificate
+ using a filter. It maps the certificate to an application user and loads that user's set
+ of granted authorities for use with the standard Spring Security infrastructure.</p><p>You should be familiar with using certificates and setting up client authentication
for your servlet container before attempting to use it with Spring Security. Most of the
work is in creating and installing suitable certificates and keys. For example, if
- you're using Tomcat then read the instructions here <code class="uri"><a class="uri" href="http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html" target="_top">http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html</a></code>. It's important that
- you get this working before trying it out with Spring Security</p></div><div class="section" title="22.2 Adding X.509 Authentication to Your Web Application"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e6578"></a>22.2 Adding X.509 Authentication to Your Web Application</h2></div></div></div><p> Enabling X.509 client authentication is very straightforward. Just add the <code class="literal"><x509/></code> element to your http security namespace configuration. </p><pre class="programlisting">
-<http>
+ you're using Tomcat then read the instructions here <code class="uri"><a class="uri" href="http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html" target="_top">http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html</a></code>. It's important that you
+ get this working before trying it out with Spring Security</p></div><div class="section" title="23.2 Adding X.509 Authentication to Your Web Application"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e8013"></a>23.2 Adding X.509 Authentication to Your Web Application</h2></div></div></div><p> Enabling X.509 client authentication is very straightforward. Just add the
+ <code class="literal"><x509/></code> element to your http security namespace configuration.
+ </p><pre class="programlisting">
+<span class="hl-tag"><http></span>
...
- <x509 subject-principal-regex="CN=(.*?)," user-service-ref="userService"/>
+ <span class="hl-tag"><x509</span> <span class="hl-attribute">subject-principal-regex</span>=<span class="hl-value">"CN=(.*?),"</span> <span class="hl-attribute">user-service-ref</span>=<span class="hl-value">"userService"</span><span class="hl-tag">/></span>;
...
-</http>
- </pre><p> The element has two optional attributes: </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p><code class="literal">subject-principal-regex</code>. The regular expression used to
- extract a username from the certificate's subject name. The default value is
- shown above. This is the username which will be passed to the <code class="interfacename">UserDetailsService</code> to load the authorities for the
- user.</p></li><li class="listitem"><p><code class="literal">user-service-ref</code>. This is the bean Id of the
- <code class="interfacename">UserDetailsService</code> to be used with X.509.
- It isn't needed if there is only one defined in your application
- context.</p></li></ul></div><p> The <code class="literal">subject-principal-regex</code> should contain a single
+<span class="hl-tag"></http></span>
+ </pre><p>
+ The element has two optional attributes: </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p><code class="literal">subject-principal-regex</code>. The regular expression used to
+ extract a username from the certificate's subject name. The default value is
+ shown above. This is the username which will be passed to the
+ <code class="interfacename">UserDetailsService</code> to load the authorities for
+ the user.</p></li><li class="listitem"><p><code class="literal">user-service-ref</code>. This is the bean Id of the
+ <code class="interfacename">UserDetailsService</code> to be used with X.509. It
+ isn't needed if there is only one defined in your application context.</p></li></ul></div><p> The <code class="literal">subject-principal-regex</code> should contain a single
group. For example the default expression "CN=(.*?)," matches the common name field. So
if the subject name in the certificate is "CN=Jimi Hendrix, OU=...", this will give a
user name of "Jimi Hendrix". The matches are case insensitive. So "emailAddress=(.?),"
@@ -3717,118 +4423,191 @@ JAASTest {
then there should be a valid <code class="classname">Authentication</code> object in the
security context. If no certificate is found, or no corresponding user could be found
then the security context will remain empty. This means that you can easily use X.509
- authentication with other options such as a form-based login. </p></div><div class="section" title="22.3 Setting up SSL in Tomcat"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="x509-ssl-config"></a>22.3 Setting up SSL in Tomcat</h2></div></div></div><p>There are some pre-generated certificates in the
- <code class="filename">samples/certificate</code> directory in the Spring Security project.
- You can use these to enable SSL for testing if you don't want to generate your own. The file
- <code class="filename">server.jks</code> contains the server certificate, private key and the
+ authentication with other options such as a form-based login. </p></div><div class="section" title="23.3 Setting up SSL in Tomcat"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="x509-ssl-config"></a>23.3 Setting up SSL in Tomcat</h2></div></div></div><p>There are some pre-generated certificates in the
+ <code class="filename">samples/certificate</code> directory in the Spring Security project. You
+ can use these to enable SSL for testing if you don't want to generate your own. The file
+ <code class="filename">server.jks</code> contains the server certificate, private key and the
issuing certificate authority certificate. There are also some client certificate files
- for the users from the sample applications. You can install these in your browser to enable
- SSL client authentication.
- </p><p>
- To run tomcat with SSL support, drop the <code class="filename">server.jks</code> file into the
- tomcat <code class="filename">conf</code> directory and add the following connector to the
+ for the users from the sample applications. You can install these in your browser to
+ enable SSL client authentication. </p><p> To run tomcat with SSL support, drop the <code class="filename">server.jks</code> file into
+ the tomcat <code class="filename">conf</code> directory and add the following connector to the
<code class="filename">server.xml</code> file
- </p><pre class="programlisting">
-<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" scheme="https" secure="true"
- clientAuth="true" sslProtocol="TLS"
- keystoreFile="${catalina.home}/conf/server.jks"
- keystoreType="JKS" keystorePass="password"
- truststoreFile="${catalina.home}/conf/server.jks"
- truststoreType="JKS" truststorePass="password"
-/>
+ </p><pre class="programlisting">
+<span class="hl-tag"><Connector</span> <span class="hl-attribute">port</span>=<span class="hl-value">"8443"</span> <span class="hl-attribute">protocol</span>=<span class="hl-value">"HTTP/1.1"</span> <span class="hl-attribute">SSLEnabled</span>=<span class="hl-value">"true"</span> <span class="hl-attribute">scheme</span>=<span class="hl-value">"https"</span> <span class="hl-attribute">secure</span>=<span class="hl-value">"true"</span>
+ <span class="hl-attribute">clientAuth</span>=<span class="hl-value">"true"</span> <span class="hl-attribute">sslProtocol</span>=<span class="hl-value">"TLS"</span>
+ <span class="hl-attribute">keystoreFile</span>=<span class="hl-value">"${catalina.home}/conf/server.jks"</span>
+ <span class="hl-attribute">keystoreType</span>=<span class="hl-value">"JKS"</span> <span class="hl-attribute">keystorePass</span>=<span class="hl-value">"password"</span>
+ <span class="hl-attribute">truststoreFile</span>=<span class="hl-value">"${catalina.home}/conf/server.jks"</span>
+ <span class="hl-attribute">truststoreType</span>=<span class="hl-value">"JKS"</span> <span class="hl-attribute">truststorePass</span>=<span class="hl-value">"password"</span><span class="hl-tag">
+/></span>
</pre><p>
- <em class="parameter"><code>clientAuth</code></em> can also be set to <em class="parameter"><code>want</code></em> if you still
- want SSL connections to succeed even if the client doesn't provide a certificate.
+ <em class="parameter"><code>clientAuth</code></em> can also be set to <em class="parameter"><code>want</code></em> if you
+ still want SSL connections to succeed even if the client doesn't provide a certificate.
Clients which don't present a certificate won't be able to access any objects secured by
- Spring Security unless you use a non-X.509 authentication mechanism, such as form authentication.
- </p></div></div><div class="chapter" title="23. Run-As Authentication Replacement"><div class="titlepage"><div><div><h1 class="title"><a name="runas"></a>Run-As Authentication Replacement</h1></div></div></div><div class="section" title="23.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="runas-overview"></a>23.1 Overview</h2></div></div></div><p>The <code class="classname">AbstractSecurityInterceptor</code> is able to
- temporarily replace the <code class="interfacename">Authentication</code> object in
- the <code class="interfacename">SecurityContext</code> and
- <code class="classname">SecurityContextHolder</code> during the secure object
- callback phase. This only occurs if the original
- <code class="interfacename">Authentication</code> object was successfully processed by
- the <code class="interfacename">AuthenticationManager</code> and
- <code class="interfacename">AccessDecisionManager</code>. The
+ Spring Security unless you use a non-X.509 authentication mechanism, such as form
+ authentication. </p></div></div><div class="chapter" title="24. Run-As Authentication Replacement"><div class="titlepage"><div><div><h1 class="title"><a name="runas"></a>Run-As Authentication Replacement</h1></div></div></div><div class="section" title="24.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="runas-overview"></a>24.1 Overview</h2></div></div></div><p>The <code class="classname">AbstractSecurityInterceptor</code> is able to temporarily replace
+ the <code class="interfacename">Authentication</code> object in the
+ <code class="interfacename">SecurityContext</code> and
+ <code class="classname">SecurityContextHolder</code> during the secure object callback phase.
+ This only occurs if the original <code class="interfacename">Authentication</code> object
+ was successfully processed by the <code class="interfacename">AuthenticationManager</code>
+ and <code class="interfacename">AccessDecisionManager</code>. The
<code class="literal">RunAsManager</code> will indicate the replacement
- <code class="interfacename">Authentication</code> object, if any, that should be used
- during the <code class="literal">SecurityInterceptorCallback</code>.</p><p>By temporarily replacing the <code class="interfacename">Authentication</code>
- object during the secure object callback phase, the secured invocation
- will be able to call other objects which require different
- authentication and authorization credentials. It will also be able to
- perform any internal security checks for specific
+ <code class="interfacename">Authentication</code> object, if any, that should be used during
+ the <code class="literal">SecurityInterceptorCallback</code>.</p><p>By temporarily replacing the <code class="interfacename">Authentication</code> object
+ during the secure object callback phase, the secured invocation will be able to call
+ other objects which require different authentication and authorization credentials. It
+ will also be able to perform any internal security checks for specific
<code class="interfacename">GrantedAuthority</code> objects. Because Spring Security
- provides a number of helper classes that automatically configure
- remoting protocols based on the contents of the
- <code class="classname">SecurityContextHolder</code>, these run-as replacements
- are particularly useful when calling remote web services</p></div><div class="section" title="23.2 Configuration"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="runas-config"></a>23.2 Configuration</h2></div></div></div><p>A <code class="literal">RunAsManager</code> interface is provided by Spring Security:
+ provides a number of helper classes that automatically configure remoting protocols
+ based on the contents of the <code class="classname">SecurityContextHolder</code>, these run-as
+ replacements are particularly useful when calling remote web services</p></div><div class="section" title="24.2 Configuration"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="runas-config"></a>24.2 Configuration</h2></div></div></div><p>A <code class="literal">RunAsManager</code> interface is provided by Spring Security:
</p><pre class="programlisting">
Authentication buildRunAs(Authentication authentication, Object object,
List<ConfigAttribute> config);
- boolean supports(ConfigAttribute attribute);
- boolean supports(Class clazz);
- </pre><p>
- </p><p>The first method returns the <code class="interfacename">Authentication</code>
- object that should replace the existing
- <code class="interfacename">Authentication</code> object for the duration of the
- method invocation. If the method returns <code class="literal">null</code>, it
- indicates no replacement should be made. The second method is used by
- the <code class="classname">AbstractSecurityInterceptor</code> as part of its
- startup validation of configuration attributes. The
- <code class="literal">supports(Class)</code> method is called by a security
- interceptor implementation to ensure the configured
- <code class="literal">RunAsManager</code> supports the type of secure object
- that the security interceptor will present.</p><p>One concrete implementation of a <code class="literal">RunAsManager</code>
- is provided with Spring Security. The
- <code class="literal">RunAsManagerImpl</code> class returns a replacement
- <code class="literal">RunAsUserToken</code> if any
- <code class="literal">ConfigAttribute</code> starts with
- <code class="literal">RUN_AS_</code>. If any such
- <code class="literal">ConfigAttribute</code> is found, the replacement
- <code class="literal">RunAsUserToken</code> will contain the same principal,
+ <span class="hl-keyword">boolean</span> supports(ConfigAttribute attribute);
+ <span class="hl-keyword">boolean</span> supports(Class clazz);
+ </pre><p> </p><p>The first method returns the <code class="interfacename">Authentication</code> object that
+ should replace the existing <code class="interfacename">Authentication</code> object for the
+ duration of the method invocation. If the method returns <code class="literal">null</code>, it
+ indicates no replacement should be made. The second method is used by the
+ <code class="classname">AbstractSecurityInterceptor</code> as part of its startup validation of
+ configuration attributes. The <code class="literal">supports(Class)</code> method is called by a
+ security interceptor implementation to ensure the configured
+ <code class="literal">RunAsManager</code> supports the type of secure object that the security
+ interceptor will present.</p><p>One concrete implementation of a <code class="literal">RunAsManager</code> is provided with
+ Spring Security. The <code class="literal">RunAsManagerImpl</code> class returns a replacement
+ <code class="literal">RunAsUserToken</code> if any <code class="literal">ConfigAttribute</code> starts with
+ <code class="literal">RUN_AS_</code>. If any such <code class="literal">ConfigAttribute</code> is found, the
+ replacement <code class="literal">RunAsUserToken</code> will contain the same principal,
credentials and granted authorities as the original
<code class="interfacename">Authentication</code> object, along with a new
- <code class="literal">GrantedAuthorityImpl</code> for each
- <code class="literal">RUN_AS_</code> <code class="literal">ConfigAttribute</code>. Each
- new <code class="literal">GrantedAuthorityImpl</code> will be prefixed with
- <code class="literal">ROLE_</code>, followed by the <code class="literal">RUN_AS</code>
- <code class="literal">ConfigAttribute</code>. For example, a
+ <code class="literal">GrantedAuthorityImpl</code> for each <code class="literal">RUN_AS_</code>
+ <code class="literal">ConfigAttribute</code>. Each new <code class="literal">GrantedAuthorityImpl</code>
+ will be prefixed with <code class="literal">ROLE_</code>, followed by the
+ <code class="literal">RUN_AS</code> <code class="literal">ConfigAttribute</code>. For example, a
<code class="literal">RUN_AS_SERVER</code> will result in the replacement
- <code class="literal">RunAsUserToken</code> containing a
- <code class="literal">ROLE_RUN_AS_SERVER</code> granted authority.</p><p>The replacement <code class="literal">RunAsUserToken</code> is just like
- any other <code class="interfacename">Authentication</code> object. It needs to be
- authenticated by the <code class="interfacename">AuthenticationManager</code>,
- probably via delegation to a suitable
- <code class="classname">AuthenticationProvider</code>. The
- <code class="literal">RunAsImplAuthenticationProvider</code> performs such
- authentication. It simply accepts as valid any
- <code class="literal">RunAsUserToken</code> presented.</p><p>To ensure malicious code does not create a
- <code class="literal">RunAsUserToken</code> and present it for guaranteed
- acceptance by the <code class="literal">RunAsImplAuthenticationProvider</code>,
- the hash of a key is stored in all generated tokens. The
- <code class="literal">RunAsManagerImpl</code> and
- <code class="literal">RunAsImplAuthenticationProvider</code> is created in the
- bean context with the same key:
- </p><pre class="programlisting">
+ <code class="literal">RunAsUserToken</code> containing a <code class="literal">ROLE_RUN_AS_SERVER</code>
+ granted authority.</p><p>The replacement <code class="literal">RunAsUserToken</code> is just like any other
+ <code class="interfacename">Authentication</code> object. It needs to be authenticated by
+ the <code class="interfacename">AuthenticationManager</code>, probably via delegation to a
+ suitable <code class="classname">AuthenticationProvider</code>. The
+ <code class="literal">RunAsImplAuthenticationProvider</code> performs such authentication. It
+ simply accepts as valid any <code class="literal">RunAsUserToken</code> presented.</p><p>To ensure malicious code does not create a <code class="literal">RunAsUserToken</code> and
+ present it for guaranteed acceptance by the
+ <code class="literal">RunAsImplAuthenticationProvider</code>, the hash of a key is stored in all
+ generated tokens. The <code class="literal">RunAsManagerImpl</code> and
+ <code class="literal">RunAsImplAuthenticationProvider</code> is created in the bean context with
+ the same key: </p><pre class="programlisting">
-<bean id="runAsManager"
- class="org.springframework.security.access.intercept.RunAsManagerImpl">
- <property name="key" value="my_run_as_password"/>
-</bean>
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"runAsManager"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.access.intercept.RunAsManagerImpl"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"key"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"my_run_as_password"</span><span class="hl-tag">/></span>
+<span class="hl-tag"></bean></span>
-<bean id="runAsAuthenticationProvider"
- class="org.springframework.security.access.intercept.RunAsImplAuthenticationProvider">
- <property name="key" value="my_run_as_password"/>
-</bean></pre><p>By using the same key, each <code class="literal">RunAsUserToken</code>
- can be validated it was created by an approved
- <code class="literal">RunAsManagerImpl</code>. The
- <code class="literal">RunAsUserToken</code> is immutable after creation for
- security reasons</p></div></div></div><div class="appendix" title="Appendix A. Security Database Schema"><div class="titlepage"><div><div><h1 class="title"><a name="appendix-schema"></a>Security Database Schema</h1></div></div></div><p> There are various database schema used by the framework and this appendix provides a single
- reference point to them all. You only need to provide the tables for the areas of functonality
- you require. </p><p> DDL statements are given for the HSQLDB database. You can use these as a guideline for
- defining the schema for the database you are using. </p><div class="section" title="A.1 User Schema"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e6840"></a>A.1 User Schema</h2></div></div></div><p> The standard JDBC implementation of the <code class="interfacename">UserDetailsService</code>
- (<code class="classname">JdbcDaoImpl</code>) requires tables to load the password, account status
- (enabled or disabled) and a list of authorities (roles) for the user.
- <a name="db_schema_users_authorities"></a></p><pre class="programlisting">
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"runAsAuthenticationProvider"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.security.access.intercept.RunAsImplAuthenticationProvider"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"key"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"my_run_as_password"</span><span class="hl-tag">/></span>
+<span class="hl-tag"></bean></span></pre><p>By using the same key, each <code class="literal">RunAsUserToken</code> can be validated it was
+ created by an approved <code class="literal">RunAsManagerImpl</code>. The
+ <code class="literal">RunAsUserToken</code> is immutable after creation for security
+ reasons</p></div></div><div class="chapter" title="25. Spring Security Crypto Module"><div class="titlepage"><div><div><h2 class="title"><a name="crypto"></a>25. Spring Security Crypto Module</h2></div></div></div><div class="section" title="25.1 Introduction"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="spring-security-crypto-introduction"></a>25.1 Introduction</h2></div></div></div><p>
+ The Spring Security Crypto module provides support for symmetric encryption, key generation, and password encoding.
+ The code is distributed as part of the core module but has no dependencies on any other Spring Security (or Spring) code.
+ </p></div><div class="section" title="25.2 Encryptors"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="spring-security-crypto-encryption"></a>25.2 Encryptors</h2></div></div></div><p>
+ The Encryptors class provides factory methods for constructing symmetric encryptors.
+ Using this class, you can create ByteEncryptors to encrypt data in raw byte[] form.
+ You can also construct TextEncryptors to encrypt text strings.
+ Encryptors are thread safe.
+ </p><div class="section" title="25.2.1 BytesEncryptor"><div class="titlepage"><div><div><h3 class="title"><a name="spring-security-crypto-encryption-bytes"></a>25.2.1 BytesEncryptor</h3></div></div></div><p>
+ Use the Encryptors.standard factory method to construct a "standard" BytesEncryptor:
+ </p><pre class="programlisting">
+Encryptors.standard(<span class="hl-string">"password"</span>, <span class="hl-string">"salt"</span>);
+ </pre><p>
+ The "standard" encryption method is 256-bit AES using PKCS #5's PBKDF2 (Password-Based Key Derivation Function #2).
+ This method requires Java 6.
+ The password used to generate the SecretKey should be kept in a secure place and not be shared.
+ The salt is used to prevent dictionary attacks against the key in the event your encrypted data is compromised.
+ A 16-byte random initialization vector is also applied so each encrypted message is unique.
+ </p><p>
+ The provided salt should be in hex-encoded String form, be random, and be at least 8 bytes in length.
+ Such a salt may be generated using a KeyGenerator:
+ </p><pre class="programlisting">
+String salt = KeyGenerators.string().generateKey(); <span class="hl-comment">// generates a random 8-byte salt that is then hex-encoded</span>
+ </pre><p>
+ </p></div><div class="section" title="25.2.2 TextEncryptor"><div class="titlepage"><div><div><h3 class="title"><a name="spring-security-crypto-encryption-text"></a>25.2.2 TextEncryptor</h3></div></div></div><p>
+ Use the Encryptors.text factory method to construct a standard TextEncryptor:
+ </p><pre class="programlisting">
+Encryptors.text(<span class="hl-string">"password"</span>, <span class="hl-string">"salt"</span>);
+ </pre><p>
+ A TextEncryptor uses a standard BytesEncryptor to encrypt text data.
+ Encrypted results are returned as hex-encoded strings for easy storage on the filesystem or in the database.
+ </p><p>
+ Use the Encryptors.queryableText factory method to construct a "queryable" TextEncryptor:
+ </p><pre class="programlisting">
+Encryptors.queryableText(<span class="hl-string">"password"</span>, <span class="hl-string">"salt"</span>);
+ </pre><p>
+ The difference between a queryable TextEncryptor and a standard TextEncryptor has to do with initialization vector (iv) handling.
+ The iv used in a queryable TextEncryptor#encrypt operation is shared, or constant, and is not randomly generated.
+ This means the same text encrypted multiple times will always produce the same encryption result.
+ This is less secure, but necessary for encrypted data that needs to be queried against.
+ An example of queryable encrypted text would be an OAuth apiKey.
+ </p></div></div><div class="section" title="25.3 Key Generators"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="spring-security-crypto-keygenerators"></a>25.3 Key Generators</h2></div></div></div><p>
+ The KeyGenerators class provides a number of convenience factory methods for constructing different types of key generators.
+ Using this class, you can create a BytesKeyGenerator to generate byte[] keys.
+ You can also construct a StringKeyGenerator to generate string keys.
+ KeyGenerators are thread safe.
+ </p><div class="section" title="25.3.1 BytesKeyGenerator"><div class="titlepage"><div><div><h3 class="title"><a name="d0e8311"></a>25.3.1 BytesKeyGenerator</h3></div></div></div><p>
+ Use the KeyGenerators.secureRandom factory methods to generate a BytesKeyGenerator backed by a SecureRandom instance:
+ </p><pre class="programlisting">
+KeyGenerator generator = KeyGenerators.secureRandom();
+<span class="hl-keyword">byte</span>[] key = generator.generateKey();
+ </pre><p>
+ </p><p>
+ The default key length is 8 bytes.
+ There is also a KeyGenerators.secureRandom variant that provides control over the key length:
+ </p><pre class="programlisting">
+KeyGenerators.secureRandom(<span class="hl-number">16</span>);
+ </pre><p>
+ </p><p>
+ Use the KeyGenerators.shared factory method to construct a BytesKeyGenerator that always returns the same key on every invocation:
+ </p><pre class="programlisting">
+KeyGenerators.shared(<span class="hl-number">16</span>);
+ </pre><p>
+ </p></div><div class="section" title="25.3.2 StringKeyGenerator"><div class="titlepage"><div><div><h3 class="title"><a name="d0e8329"></a>25.3.2 StringKeyGenerator</h3></div></div></div><p>
+ Use the KeyGenerators.string factory method to construct a 8-byte, SecureRandom KeyGenerator that hex-encodes each key as a String:
+ </p><pre class="programlisting">
+KeyGenerators.string();
+ </pre><p>
+ </p></div></div><div class="section" title="25.4 Password Encoding"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="spring-security-crypto-passwordencoders"></a>25.4 Password Encoding</h2></div></div></div><p>
+ The password package of the spring-security-crypto module provides support for encoding passwords.
+ <code class="interfacename">PasswordEncoder</code> is the central service interface and has the following signature:
+ </p><pre class="programlisting">
+<span class="hl-keyword">public</span> <span class="hl-keyword">interface</span> PasswordEncoder {
+ String encode(String rawPassword);
+ <span class="hl-keyword">boolean</span> matches(String rawPassword, String encodedPassword);
+}
+ </pre><p>
+ The matches method returns true if the rawPassword, once encoded, equals the encodedPassword.
+ This method is designed to support password-based authentication schemes.
+ </p><p>
+ The <code class="classname">StandardPasswordEncoder</code> implementation applies 1024 iterations of the SHA-256 hashing algorithm to the rawPassword combined with a site-wide secret and 8-byte random salt:
+ </p><pre class="programlisting">
+StandardPasswordEncoder encoder = <span class="hl-keyword">new</span> StandardPasswordEncoder(<span class="hl-string">"secret"</span>);
+String result = encoder.encode(<span class="hl-string">"myPassword"</span>);
+assertTrue(encoder.matches(<span class="hl-string">"myPassword"</span>, result));
+ </pre><p>
+ The random salt ensures each hash is unique when the same password is used multiple times.
+ The site-wide secret should be stored in a safe place separate from where passwords are stored, and is used to protect against a bruce force attack in the event the database of passwords is compromised.
+ 1024 iterations of the hashing algorithm strengthens the key and makes it more difficult to compromise using a brute force attack.
+ </p></div></div></div><div class="appendix" title="Appendix A. Security Database Schema"><div class="titlepage"><div><div><h1 class="title"><a name="appendix-schema"></a>Security Database Schema</h1></div></div></div><p> There are various database schema used by the framework and this appendix provides a
+ single reference point to them all. You only need to provide the tables for the areas of
+ functonality you require. </p><p> DDL statements are given for the HSQLDB database. You can use these as a guideline for
+ defining the schema for the database you are using. </p><div class="section" title="A.1 User Schema"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e8365"></a>A.1 User Schema</h2></div></div></div><p> The standard JDBC implementation of the
+ <code class="interfacename">UserDetailsService</code> (<code class="classname">JdbcDaoImpl</code>)
+ requires tables to load the password, account status (enabled or disabled) and a list of
+ authorities (roles) for the
+ user.<a name="db_schema_users_authorities"></a></p><pre class="programlisting">
create table users(
username varchar_ignorecase(50) not null primary key,
password varchar_ignorecase(50) not null,
@@ -3839,9 +4618,9 @@ JAASTest {
authority varchar_ignorecase(50) not null,
constraint fk_authorities_users foreign key(username) references users(username));
create unique index ix_auth_username on authorities (username,authority);
-</pre><div class="section" title="A.1.1 Group Authorities"><div class="titlepage"><div><div><h3 class="title"><a name="d0e6853"></a>A.1.1 Group Authorities</h3></div></div></div><p> Spring Security 2.0 introduced support for group authorities in
- <code class="classname">JdbcDaoImpl</code>. The table structure if groups are enabled is as
- follows:<a name="db-schema-groups"></a></p><pre class="programlisting">
+</pre><div class="section" title="A.1.1 Group Authorities"><div class="titlepage"><div><div><h3 class="title"><a name="d0e8378"></a>A.1.1 Group Authorities</h3></div></div></div><p> Spring Security 2.0 introduced support for group authorities in
+ <code class="classname">JdbcDaoImpl</code>. The table structure if groups are enabled is as
+ follows:<a name="db-schema-groups"></a></p><pre class="programlisting">
create table groups (
id bigint generated by default as identity(start with 0) primary key,
group_name varchar_ignorecase(50) not null);
@@ -3856,28 +4635,35 @@ create table group_members (
username varchar(50) not null,
group_id bigint not null,
constraint fk_group_members_group foreign key(group_id) references groups(id));
- </pre></div></div><div class="section" title="A.2 Persistent Login (Remember-Me) Schema"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e6863"></a>A.2 Persistent Login (Remember-Me) Schema</h2></div></div></div><p> This table is used to store data used by the more secure <a class="link" href="#remember-me-persistent-token" title="10.3 Persistent Token Approach">persistent token</a> remember-me
- implementation. If you are using <code class="classname">JdbcTokenRepositoryImpl</code> either
- directly or through the namespace, then you will need this table.
- <a name="db-schema-remeber-me"></a></p><pre class="programlisting">
+ </pre><p>Remember that these tables are only required if you are using the provided JDBC
+ <code class="interfacename">UserDetailsService</code> implementation. If you write your
+ own or choose to implement <code class="interfacename">AuthenticationProvider</code>
+ without a <code class="interfacename">UserDetailsService</code>, then you have complete
+ freedom over how you store the data, as long as the interface contract is
+ satisfied.</p></div></div><div class="section" title="A.2 Persistent Login (Remember-Me) Schema"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e8399"></a>A.2 Persistent Login (Remember-Me) Schema</h2></div></div></div><p> This table is used to store data used by the more secure <a class="link" href="#remember-me-persistent-token" title="11.3 Persistent Token Approach">persistent token</a> remember-me
+ implementation. If you are using <code class="classname">JdbcTokenRepositoryImpl</code> either
+ directly or through the namespace, then you will need this table.
+ <a name="db-schema-remeber-me"></a></p><pre class="programlisting">
create table persistent_logins (
username varchar(64) not null,
series varchar(64) primary key,
token varchar(64) not null,
last_used timestamp not null);
-</pre></div><div class="section" title="A.3 ACL Schema"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="dbschema-acl"></a>A.3 ACL Schema</h2></div></div></div><p>There are four tables used by the Spring Security <a class="link" href="#domain-acls" title="16. Domain Object Security (ACLs)">ACL</a> implementation. </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p><code class="literal">acl_sid</code> stores the security identities recognised by the ACL
- system. These can be unique principals or authorities which may apply to multiple
- principals.</p></li><li class="listitem"><p><code class="literal">acl_class</code> defines the domain object types to which ACLs apply.
- The <code class="literal">class</code> column stores the Java class name of the object. </p></li><li class="listitem"><p><code class="literal">acl_object_identity</code> stores the object identity definitions of
- specific domai objects.</p></li><li class="listitem"><p><code class="literal">acl_entry</code> stores the ACL permissions which apply to a specific
- object identity and security identity.</p></li></ol></div><p>It is assumed that the database will auto-generate the primary keys for each of the
- identities. The <code class="literal">JdbcMutableAclService</code> has to be able to retrieve these when
- it has created a new row in the <code class="literal">acl_sid</code> or <code class="literal">acl_class</code>
- tables. It has two properties which define the SQL needed to retrieve these values
- <code class="literal">classIdentityQuery</code> and <code class="literal">sidIdentityQuery</code>. Both of these
- default to <code class="literal">call identity()</code></p><div class="section" title="A.3.1 Hypersonic SQL"><div class="titlepage"><div><div><h3 class="title"><a name="d0e6927"></a>A.3.1 Hypersonic SQL</h3></div></div></div><p>The default schema works with the embedded HSQLDB database that is used in unit tests
- within the
- framework.<a name="dbschema-acl-hsql"></a></p><pre class="programlisting">
+</pre></div><div class="section" title="A.3 ACL Schema"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="dbschema-acl"></a>A.3 ACL Schema</h2></div></div></div><p>There are four tables used by the Spring Security <a class="link" href="#domain-acls" title="17. Domain Object Security (ACLs)">ACL</a> implementation. </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p><code class="literal">acl_sid</code> stores the security identities recognised by the
+ ACL system. These can be unique principals or authorities which may apply to
+ multiple principals.</p></li><li class="listitem"><p><code class="literal">acl_class</code> defines the domain object types to which ACLs
+ apply. The <code class="literal">class</code> column stores the Java class name of the
+ object. </p></li><li class="listitem"><p><code class="literal">acl_object_identity</code> stores the object identity definitions
+ of specific domai objects.</p></li><li class="listitem"><p><code class="literal">acl_entry</code> stores the ACL permissions which apply to a
+ specific object identity and security identity.</p></li></ol></div><p>It is assumed that the database will auto-generate the primary keys for each of the
+ identities. The <code class="literal">JdbcMutableAclService</code> has to be able to retrieve
+ these when it has created a new row in the <code class="literal">acl_sid</code> or
+ <code class="literal">acl_class</code> tables. It has two properties which define the SQL needed
+ to retrieve these values <code class="literal">classIdentityQuery</code> and
+ <code class="literal">sidIdentityQuery</code>. Both of these default to <code class="literal">call
+ identity()</code></p><div class="section" title="A.3.1 Hypersonic SQL"><div class="titlepage"><div><div><h3 class="title"><a name="d0e8463"></a>A.3.1 Hypersonic SQL</h3></div></div></div><p>The default schema works with the embedded HSQLDB database that is used in unit
+ tests within the
+ framework.<a name="dbschema-acl-hsql"></a></p><pre class="programlisting">
create table acl_sid (
id bigint generated by default as identity(start with 100) not null primary key,
principal boolean not null,
@@ -3911,8 +4697,8 @@ create table acl_entry (
references acl_object_identity(id),
constraint foreign_fk_5 foreign key(sid) references acl_sid(id) );
-</pre><div class="section" title="PostgreSQL"><div class="titlepage"><div><div><h4 class="title"><a name="d0e6934"></a>PostgreSQL</h4></div></div></div><p>
- </p><pre class="programlisting">create table acl_sid(
+ </pre></div><div class="section" title="A.3.2 PostgreSQL"><div class="titlepage"><div><div><h3 class="title"><a name="d0e8470"></a>A.3.2 PostgreSQL</h3></div></div></div><p>
+ </p><pre class="programlisting">create table acl_sid(
id bigserial not null primary key,
principal boolean not null,
sid varchar(100) not null,
@@ -3948,99 +4734,177 @@ create table acl_entry(
constraint foreign_fk_4 foreign key(acl_object_identity)
references acl_object_identity(id),
constraint foreign_fk_5 foreign key(sid) references acl_sid(id));
-</pre><p>
- </p><p>You will have to set the <code class="literal">classIdentityQuery</code> and
- <code class="literal">sidIdentityQuery</code> properties of
- <code class="classname">JdbcMutableAclService</code> to the following values, respectively: </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p><code class="literal">select currval(pg_get_serial_sequence('acl_class',
- 'id'))</code></p></li><li class="listitem"><p><code class="literal">select currval(pg_get_serial_sequence('acl_sid',
- 'id'))</code></p></li></ul></div></div></div></div></div><div class="appendix" title="Appendix B. The Security Namespace"><div class="titlepage"><div><div><h1 class="title"><a name="appendix-namespace"></a>The Security Namespace</h1></div></div></div><p> This appendix provides a reference to the elements available in the security namespace
+</pre><p> </p><p>You will have to set the <code class="literal">classIdentityQuery</code> and
+ <code class="literal">sidIdentityQuery</code> properties of
+ <code class="classname">JdbcMutableAclService</code> to the following values,
+ respectively: </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p><code class="literal">select currval(pg_get_serial_sequence('acl_class',
+ 'id'))</code></p></li><li class="listitem"><p><code class="literal">select currval(pg_get_serial_sequence('acl_sid',
+ 'id'))</code></p></li></ul></div></div></div></div><div class="appendix" title="Appendix B. The Security Namespace"><div class="titlepage"><div><div><h1 class="title"><a name="appendix-namespace"></a>The Security Namespace</h1></div></div></div><p> This appendix provides a reference to the elements available in the security namespace
and information on the underlying beans they create (a knowledge of the individual classes
and how they work together is assumed - you can find more information in the project Javadoc
and elsewhere in this document). If you haven't used the namespace before, please read the
- <a class="link" href="#ns-config" title="2. Security Namespace Configuration">introductory chapter</a> on namespace configuration, as
+ <a class="link" href="#ns-config" title="3. Security Namespace Configuration">introductory chapter</a> on namespace configuration, as
this is intended as a supplement to the information there. Using a good quality XML editor
while editing a configuration based on the schema is recommended as this will provide
contextual information on which elements and attributes are available as well as comments
explaining their purpose. The namespace is written in <a class="link" href="http://www.relaxng.org/" target="_top">RELAX NG</a> Compact format and later converted into
- an XSD schema. If you are familiar with this format, you may wish to examine the <a class="link" href="https://fisheye.springsource.org/browse/spring-security/config/src/main/resources/org/springframework/security/config/spring-security-3.1.rnc" target="_top">schema file</a> directly.</p><div class="section" title="B.1 Web Application Security - the <http> Element"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="nsa-http"></a>B.1 Web Application Security - the <code class="literal"><http></code> Element</h2></div></div></div><p> If you use an <code class="literal"><http></code> element within your application, a
- <code class="classname">FilterChainProxy</code> bean named "springSecurityFilterChain" is
- created and the configuration within the element is used to build a filter chain within
- <code class="classname">FilterChainProxy</code>. As of Spring Security 3.1, additional
- <code class="literal">http</code> elements can be used to add extra filter chains <sup>[<a name="d0e6997" href="#ftn.d0e6997" class="footnote">16</a>]</sup>. Some core filters are always created in a filter chain and others will be
- added to the stack depending on the attributes and child elements which are present. The
- positions of the standard filters are fixed (see <a class="link" href="#filter-stack" title="Table 2.1. Standard Filter Aliases and Ordering">the
- filter order table</a> in the namespace introduction), removing a common source of
- errors with previous versions of the framework when users had to configure the filter
- chain explicitly in the<code class="classname">FilterChainProxy</code> bean. You can, of course,
- still do this if you need full control of the configuration. </p><p> All filters which require a reference to the
- <code class="interfacename">AuthenticationManager</code> will be automatically injected with
- the internal instance created by the namespace configuration (see the <a class="link" href="#ns-auth-manager" title="2.6 The Authentication Manager and the Namespace"> introductory chapter</a> for more on the
- <code class="interfacename">AuthenticationManager</code>). </p><p> Each <code class="literal"><http></code> namespace block always creates an
- <code class="classname">SecurityContextPersistenceFilter</code>, an
- <code class="classname">ExceptionTranslationFilter</code> and a
- <code class="classname">FilterSecurityInterceptor</code>. These are fixed and cannot be replaced
- with alternatives. </p><div class="section" title="B.1.1 <http> Attributes"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-http-attributes"></a>B.1.1 <code class="literal"><http></code> Attributes</h3></div></div></div><p> The attributes on the <code class="literal"><http></code> element control some of the
- properties on the core filters. </p><div class="section" title="pattern"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-http-pattern"></a><code class="literal">pattern</code></h4></div></div></div><p>Defining a pattern for the <code class="literal">http</code> element controls the
- requests which will be filtered through the list of filters which it defines.
- The interpretation is dependent on the configured <a class="link" href="#nsa-path-type" title="request-matcher">request-matcher</a>. If no pattern is defined,
- all requests will be matched, so the most specific patterns should be declared
- first. </p></div><div class="section" title="security"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-http-secured"></a><code class="literal">security</code></h4></div></div></div><p>A request pattern can be mapped to an empty filter chain, by setting this
- attribute to <code class="literal">none</code>. No security will be applied and none of
- Spring Security's features will be available. </p></div><div class="section" title="servlet-api-provision"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-servlet-api-provision"></a><code class="literal">servlet-api-provision</code></h4></div></div></div><p> Provides versions of <code class="literal">HttpServletRequest</code> security methods
- such as <code class="literal">isUserInRole()</code> and <code class="literal">getPrincipal()</code>
- which are implemented by adding a
- <code class="classname">SecurityContextHolderAwareRequestFilter</code> bean to the
- stack. Defaults to "true".</p></div><div class="section" title="jaas-api-provision"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-jaas-api-provision"></a><code class="literal">jaas-api-provision</code></h4></div></div></div><p>If available, runs the request as the <code class="literal">Subject</code> acquired from
- the <code class="classname">JaasAuthenticationToken</code> which is implemented by
- adding a <code class="classname">JaasApiIntegrationFilter</code> bean to the stack.
- Defaults to "false".</p></div><div class="section" title="request-matcher"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-path-type"></a><code class="literal">request-matcher</code></h4></div></div></div><p> Defines the <code class="interfacename">RequestMatcher</code> strategy used in
- the <code class="classname">FilterChainProxy</code> and the beans created by the
- <code class="literal">intercept-url</code> to match incoming requests. Options are
- currently <code class="literal">ant</code>, <code class="literal">regex</code> and
- <code class="literal">ciRegex</code>, for ant, regular-expression and case-insensitive
- regular-expression repsectively. A separate instance is created for each
- <code class="literal">intercept-url</code> element using its <code class="literal">pattern</code>
- and <code class="literal">method</code> attributes (see below). Ant paths are matched
- using an <code class="classname">AntPathRequestMatcher</code> and regular expressions
- are matched using a <code class="classname">RegexRequestMatcher</code>. See the Javadoc
- for these classes for more details on exactly how the matching is preformed. Ant
- paths are the default strategy.</p></div><div class="section" title="realm"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-realm"></a><code class="literal">realm</code></h4></div></div></div><p> Sets the realm name used for basic authentication (if enabled). Corresponds
- to the <code class="literal">realmName</code> property on
- <code class="classname">BasicAuthenticationEntryPoint</code>. </p></div><div class="section" title="entry-point-ref"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-entry-point-ref"></a><code class="literal">entry-point-ref</code></h4></div></div></div><p> Normally the <code class="interfacename">AuthenticationEntryPoint</code> used
- will be set depending on which authentication mechanisms have been configured.
- This attribute allows this behaviour to be overridden by defining a customized
- <code class="interfacename">AuthenticationEntryPoint</code> bean which will start
- the authentication process. </p></div><div class="section" title="security-context-repository-ref"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-security-context-repo-ref"></a><code class="literal">security-context-repository-ref</code></h4></div></div></div><p> Allows injection of a custom
- <code class="interfacename">SecurityContextRepository</code> into the
- <code class="classname">SecurityContextPersistenceFilter</code>. </p></div><div class="section" title="access-decision-manager-ref"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-access-decision-manager-ref"></a><code class="literal">access-decision-manager-ref</code></h4></div></div></div><p> Optional attribute specifying the ID of the
- <code class="interfacename">AccessDecisionManager</code> implementation which should
- be used for authorizing HTTP requests. By default an
- <code class="classname">AffirmativeBased</code> implementation is used for with a
- <code class="classname">RoleVoter</code> and an
- <code class="classname">AuthenticatedVoter</code>. </p></div><div class="section" title="access-denied-page"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-access-denied-page"></a><code class="literal">access-denied-page</code></h4></div></div></div><p> Deprecated in favour of the <code class="literal">access-denied-handler</code> child
- element. </p></div><div class="section" title="once-per-request"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-once-per-request"></a><code class="literal">once-per-request</code></h4></div></div></div><p> Corresponds to the <code class="literal">observeOncePerRequest</code> property of
- <code class="classname">FilterSecurityInterceptor</code>. Defaults to "true". </p></div><div class="section" title="create-session"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-create-session"></a><code class="literal">create-session</code></h4></div></div></div><p> Controls the eagerness with which an HTTP session is created. If not set,
- defaults to "ifRequired". Other options are "always" and "never". The setting of
- this attribute affect the <code class="literal">allowSessionCreation</code> and
- <code class="literal">forceEagerSessionCreation</code> properties of
- <code class="classname">HttpSessionContextIntegrationFilter</code>.
- <code class="literal">allowSessionCreation</code> will always be true unless this
- attribute is set to "never". <code class="literal">forceEagerSessionCreation</code> is
- "false" unless it is set to "always". So the default configuration allows
- session creation but does not force it. The exception is if concurrent session
- control is enabled, when <code class="literal">forceEagerSessionCreation</code> will be
- set to true, regardless of what the setting is here. Using "never" would then
- cause an exception during the initialization of
- <code class="classname">HttpSessionContextIntegrationFilter</code>. </p></div><div class="section" title="use-expressions"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-use-expressions"></a><code class="literal">use-expressions</code></h4></div></div></div><p>Enables EL-expressions in the <code class="literal">access</code> attribute, as
- described in the chapter on <a class="link" href="#el-access-web" title="15.2 Web Security Expressions">expression-based
- access-control</a>. </p></div><div class="section" title="disable-url-rewriting"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-disable-url-rewriting"></a><code class="literal">disable-url-rewriting</code></h4></div></div></div><p>Prevents session IDs from being appended to URLs in the application. Clients
- must use cookies if this attribute is set to <code class="literal">true</code>. </p></div></div><div class="section" title="B.1.2 <access-denied-handler>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-access-denied-handler"></a>B.1.2 <code class="literal"><access-denied-handler></code></h3></div></div></div><p> This element allows you to set the <code class="literal">errorPage</code> property for the
+ an XSD schema. If you are familiar with this format, you may wish to examine the <a class="link" href="https://fisheye.springsource.org/browse/spring-security/config/src/main/resources/org/springframework/security/config/spring-security-3.1.rnc" target="_top">schema file</a> directly.</p><div class="section" title="B.1 Web Application Security"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="nsa-web"></a>B.1 Web Application Security</h2></div></div></div><div class="section" title="B.1.1 <debug>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-debug"></a>B.1.1 <code class="literal"><debug></code></h3></div></div></div><p>Enables Spring Security debugging infrastructure. This will provide human-readable (multi-line)
+ debugging information to monitor requests coming into the security filters. This may include sensitive
+ information, such as request parameters or headers, and should only be used in a development
+ environment.</p></div><div class="section" title="B.1.2 <http>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-http"></a>B.1.2 <code class="literal"><http></code></h3></div></div></div><p> If you use an <code class="literal"><http></code> element within your application, a
+ <code class="classname">FilterChainProxy</code> bean named "springSecurityFilterChain" is
+ created and the configuration within the element is used to build a filter chain within
+ <code class="classname">FilterChainProxy</code>. As of Spring Security 3.1, additional
+ <code class="literal">http</code> elements can be used to add extra filter chains <sup>[<a name="d0e8540" href="#ftn.d0e8540" class="footnote">24</a>]</sup>. Some core filters are always created in a filter chain and others will be
+ added to the stack depending on the attributes and child elements which are present. The
+ positions of the standard filters are fixed (see <a class="link" href="#filter-stack" title="Table 3.1. Standard Filter Aliases and Ordering">the
+ filter order table</a> in the namespace introduction), removing a common source of
+ errors with previous versions of the framework when users had to configure the filter
+ chain explicitly in the <code class="classname">FilterChainProxy</code> bean. You can, of course,
+ still do this if you need full control of the configuration. </p><p> All filters which require a reference to the
+ <code class="interfacename">AuthenticationManager</code> will be automatically injected with
+ the internal instance created by the namespace configuration (see the <a class="link" href="#ns-auth-manager" title="3.6 The Authentication Manager and the Namespace">introductory chapter</a> for more on the
+ <code class="interfacename">AuthenticationManager</code>). </p><p> Each <code class="literal"><http></code> namespace block always creates an
+ <code class="classname">SecurityContextPersistenceFilter</code>, an
+ <code class="classname">ExceptionTranslationFilter</code> and a
+ <code class="classname">FilterSecurityInterceptor</code>. These are fixed and cannot be replaced
+ with alternatives. </p><div class="section" title="<http> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-http-attributes"></a><code class="literal"><http></code> Attributes</h4></div></div></div><p> The attributes on the <code class="literal"><http></code> element control some of the
+ properties on the core filters. </p><div class="section" title="access-decision-manager-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-access-decision-manager-ref"></a><code class="literal">access-decision-manager-ref</code></h5></div></div></div><p> Optional attribute specifying the ID of the
+ <code class="interfacename">AccessDecisionManager</code> implementation which should
+ be used for authorizing HTTP requests. By default an
+ <code class="classname">AffirmativeBased</code> implementation is used for with a
+ <code class="classname">RoleVoter</code> and an
+ <code class="classname">AuthenticatedVoter</code>. </p></div><div class="section" title="access-denied-page"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-access-denied-page"></a><code class="literal">access-denied-page</code></h5></div></div></div><p> Deprecated in favour of the <a class="link" href="#nsa-access-denied-handler" title="B.1.3 <access-denied-handler>">access-denied-handler</a>
+ child element.</p></div><div class="section" title="authentication-manager-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-authentication-manager-ref"></a><code class="literal">authentication-manager-ref</code></h5></div></div></div><p>A reference to the <code class="interfacename">AuthenticationManager</code> used for the
+ <code class="classname">FilterChain</code> created by this http element.</p></div><div class="section" title="auto-config"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-auto-config"></a><code class="literal">auto-config</code></h5></div></div></div><p>Automatically registers a login form, BASIC authentication, anonymous authentication, logout
+ services, remember-me and servlet-api-integration. If set to "true", all of these capabilities are added
+ (although you can still customize the configuration of each by providing the respective element). If
+ unspecified, defaults to "false".</p></div><div class="section" title="create-session"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-create-session"></a><code class="literal">create-session</code></h5></div></div></div><p>Controls the eagerness with which an HTTP session is created by Spring Security classes.
+ Options include:
+ </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><code class="literal">always</code> - Spring Security will proactively create a session if one
+ does not exist.
+ </li><li class="listitem"><code class="literal">ifRequired</code> - Spring Security will only create a session only if one
+ is required (default value).
+ </li><li class="listitem"><code class="literal">never</code> - Spring Security will never create a session, but will
+ make use of one if the application does.</li><li class="listitem"><code class="literal">stateless</code> - Spring Security will not create a session and ignore the
+ session for obtaining a Spring <code class="interfacename">Authentication</code>.
+ </li></ul></div><p>
+ </p></div><div class="section" title="disable-url-rewriting"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-disable-url-rewriting"></a><code class="literal">disable-url-rewriting</code></h5></div></div></div><p>Prevents session IDs from being appended to URLs in the application. Clients
+ must use cookies if this attribute is set to <code class="literal">true</code>. The default is
+ <code class="literal">false</code>.</p></div><div class="section" title="entry-point-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-entry-point-ref"></a><code class="literal">entry-point-ref</code></h5></div></div></div><p> Normally the <code class="interfacename">AuthenticationEntryPoint</code> used
+ will be set depending on which authentication mechanisms have been configured.
+ This attribute allows this behaviour to be overridden by defining a customized
+ <code class="interfacename">AuthenticationEntryPoint</code> bean which will start
+ the authentication process.</p></div><div class="section" title="jaas-api-provision"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-jaas-api-provision"></a><code class="literal">jaas-api-provision</code></h5></div></div></div><p>If available, runs the request as the <code class="literal">Subject</code> acquired from
+ the <code class="classname">JaasAuthenticationToken</code> which is implemented by
+ adding a <code class="classname">JaasApiIntegrationFilter</code> bean to the stack.
+ Defaults to <code class="literal">false</code>.</p></div><div class="section" title="name"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-name"></a><code class="literal">name</code></h5></div></div></div><p>A bean identifier, used for referring to the bean elsewhere in the context.</p></div><div class="section" title="once-per-request"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-once-per-request"></a><code class="literal">once-per-request</code></h5></div></div></div><p>Corresponds to the <code class="literal">observeOncePerRequest</code> property of
+ <code class="classname">FilterSecurityInterceptor</code>. Defaults to <code class="literal">true</code>.</p></div><div class="section" title="path-type"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-path-type"></a><code class="literal">path-type</code></h5></div></div></div><p>Deprecated in favor of <a class="link" href="#nsa-http-request-matcher" title="request-matcher">request-matcher</a>.
+ </p></div><div class="section" title="pattern"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-pattern"></a><code class="literal">pattern</code></h5></div></div></div><p>Defining a pattern for the <a class="link" href="#nsa-http" title="B.1.2 <http>">http</a> element controls the
+ requests which will be filtered through the list of filters which it defines.
+ The interpretation is dependent on the configured <a class="link" href="#nsa-http-request-matcher" title="request-matcher">request-matcher</a>. If no pattern is defined,
+ all requests will be matched, so the most specific patterns should be declared
+ first.</p></div><div class="section" title="realm"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-realm"></a><code class="literal">realm</code></h5></div></div></div><p>Sets the realm name used for basic authentication (if enabled). Corresponds
+ to the <code class="literal">realmName</code> property on
+ <code class="classname">BasicAuthenticationEntryPoint</code>.</p></div><div class="section" title="request-matcher"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-request-matcher"></a><code class="literal">request-matcher</code></h5></div></div></div><p>Defines the <code class="interfacename">RequestMatcher</code> strategy used in
+ the <code class="classname">FilterChainProxy</code> and the beans created by the
+ <code class="literal">intercept-url</code> to match incoming requests. Options are
+ currently <code class="literal">ant</code>, <code class="literal">regex</code> and
+ <code class="literal">ciRegex</code>, for ant, regular-expression and case-insensitive
+ regular-expression repsectively. A separate instance is created for each
+ <a class="link" href="#nsa-intercept-url" title="B.1.10 <intercept-url>">intercept-url</a> element using its
+ <a class="link" href="#nsa-intercept-url-pattern" title="pattern">pattern</a> and
+ <a class="link" href="#nsa-intercept-url-method" title="method">method</a> attributes. Ant paths
+ are matched using an <code class="classname">AntPathRequestMatcher</code> and regular expressions
+ are matched using a <code class="classname">RegexRequestMatcher</code>. See the Javadoc
+ for these classes for more details on exactly how the matching is preformed. Ant
+ paths are the default strategy.</p></div><div class="section" title="request-matcher-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-request-matcher-ref"></a><code class="literal">request-matcher-ref</code></h5></div></div></div><p>A referenece to a bean that implements <code class="interfacename">RequestMatcher</code> that
+ will determine if this <code class="classname">FilterChain</code> should be used. This is a more
+ powerful alternative to <a class="link" href="#nsa-http-pattern" title="pattern">pattern</a>.</p></div><div class="section" title="security"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-security"></a><code class="literal">security</code></h5></div></div></div><p>A request pattern can be mapped to an empty filter chain, by setting this
+ attribute to <code class="literal">none</code>. No security will be applied and none of
+ Spring Security's features will be available.</p></div><div class="section" title="security-context-repository-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-security-context-repository-ref"></a><code class="literal">security-context-repository-ref</code></h5></div></div></div><p>Allows injection of a custom
+ <code class="interfacename">SecurityContextRepository</code> into the
+ <code class="classname">SecurityContextPersistenceFilter</code>.</p></div><div class="section" title="servlet-api-provision"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-servlet-api-provision"></a><code class="literal">servlet-api-provision</code></h5></div></div></div><p>Provides versions of <code class="literal">HttpServletRequest</code> security methods
+ such as <code class="literal">isUserInRole()</code> and <code class="literal">getPrincipal()</code>
+ which are implemented by adding a
+ <code class="classname">SecurityContextHolderAwareRequestFilter</code> bean to the
+ stack. Defaults to <code class="literal">true</code>.</p></div><div class="section" title="use-expressions"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-use-expressions"></a><code class="literal">use-expressions</code></h5></div></div></div><p>Enables EL-expressions in the <code class="literal">access</code> attribute, as
+ described in the chapter on <a class="link" href="#el-access-web" title="16.2 Web Security Expressions">expression-based
+ access-control</a>.</p></div></div><div class="section" title="Child Elements of <http>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-http-children"></a>Child Elements of <http></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-access-denied-handler" title="B.1.3 <access-denied-handler>">access-denied-handler</a></li><li class="listitem"><a class="link" href="#nsa-anonymous" title="B.1.4 <anonymous>">anonymous</a></li><li class="listitem"><a class="link" href="#nsa-custom-filter" title="B.1.5 <custom-filter>">custom-filter</a></li><li class="listitem"><a class="link" href="#nsa-expression-handler" title="B.1.6 <expression-handler>">expression-handler</a></li><li class="listitem"><a class="link" href="#nsa-form-login" title="B.1.7 <form-login>">form-login</a></li><li class="listitem"><a class="link" href="#nsa-http-basic" title="B.1.8 <http-basic>">http-basic</a></li><li class="listitem"><a class="link" href="#nsa-intercept-url" title="B.1.10 <intercept-url>">intercept-url</a></li><li class="listitem"><a class="link" href="#nsa-jee" title="B.1.11 <jee>">jee</a></li><li class="listitem"><a class="link" href="#nsa-logout" title="B.1.12 <logout>">logout</a></li><li class="listitem"><a class="link" href="#nsa-openid-login" title="B.1.13 <openid-login>">openid-login</a></li><li class="listitem"><a class="link" href="#nsa-port-mappings" title="B.1.16 <port-mappings>">port-mappings</a></li><li class="listitem"><a class="link" href="#nsa-remember-me" title="B.1.18 <remember-me>">remember-me</a></li><li class="listitem"><a class="link" href="#nsa-request-cache" title="B.1.19 <request-cache> Element">request-cache</a></li><li class="listitem"><a class="link" href="#nsa-session-management" title="B.1.20 <session-management>">session-management</a></li><li class="listitem"><a class="link" href="#nsa-x509" title="B.1.22 <x509>">x509</a></li></ul></div></div></div><div class="section" title="B.1.3 <access-denied-handler>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-access-denied-handler"></a>B.1.3 <code class="literal"><access-denied-handler></code></h3></div></div></div><p>This element allows you to set the <code class="literal">errorPage</code> property for the
default <code class="interfacename">AccessDeniedHandler</code> used by the
- <code class="classname">ExceptionTranslationFilter</code>, (using the
- <code class="literal">error-page</code> attribute, or to supply your own implementation using
- the <code class="literal">ref</code> attribute. This is discussed in more detail in the
- section on <a class="link" href="#access-denied-handler" title="8.2.2 AccessDeniedHandler">the
- <code class="classname">ExceptionTranslationFilter</code></a>.</p></div><div class="section" title="B.1.3 The <intercept-url> Element"><div class="titlepage"><div><div><h3 class="title"><a name="d0e7289"></a>B.1.3 The <code class="literal"><intercept-url></code> Element</h3></div></div></div><p> This element is used to define the set of URL patterns that the application is
+ <code class="classname">ExceptionTranslationFilter</code>, using the
+ <a class="link" href="#nsa-access-denied-handler-error-page" title="error-page">error-page</a> attribute, or
+ to supply your own implementation using the
+ <a class="link" href="#nsa-access-denied-handler-ref" title="ref">ref</a> attribute. This is discussed
+ in more detail in the section on the <a class="link" href="#access-denied-handler" title="9.2.2 AccessDeniedHandler">
+ <code class="classname">ExceptionTranslationFilter</code></a>.</p><div class="section" title="Parent Elements of <access-denied-handler>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-access-denied-handler-parents"></a>Parent Elements of <code class="literal"><access-denied-handler></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-http" title="B.1.2 <http>">http</a></li></ul></div></div><div class="section" title="<access-denied-handler> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-access-denied-handler-attributes"></a><code class="literal"><access-denied-handler></code> Attributes</h4></div></div></div><div class="section" title="error-page"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-access-denied-handler-error-page"></a><code class="literal">error-page</code></h5></div></div></div><p>The access denied page that an authenticated user will be redirected to if they request a
+ page which they don't have the authority to access.</p></div><div class="section" title="ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-access-denied-handler-ref"></a><code class="literal">ref</code></h5></div></div></div><p>Defines a reference to a Spring bean of type <code class="interfacename">AccessDeniedHandler
+ </code>.</p></div></div></div><div class="section" title="B.1.4 <anonymous>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-anonymous"></a>B.1.4 <code class="literal"><anonymous></code></h3></div></div></div><p>Adds an <code class="classname">AnonymousAuthenticationFilter</code> to the stack and an
+ <code class="classname">AnonymousAuthenticationProvider</code>. Required if you are using
+ the <code class="literal">IS_AUTHENTICATED_ANONYMOUSLY</code> attribute.</p><div class="section" title="Parent Elements of <anonymous>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-anonymous-parents"></a>Parent Elements of <code class="literal"><anonymous></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-http" title="B.1.2 <http>">http</a></li></ul></div></div><div class="section" title="<anonymous> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-anonymous-attributes"></a><code class="literal"><anonymous></code> Attributes</h4></div></div></div><div class="section" title="enabled"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-anonymous-enabled"></a><code class="literal">enabled</code></h5></div></div></div><p>With the default namespace setup, the anonymous "authentication" facility is automatically
+ enabled. You can disable it using this property.</p></div><div class="section" title="granted-authority"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-anonymous-granted-authority"></a><code class="literal">granted-authority</code></h5></div></div></div><p>The granted authority that should be assigned to the anonymous request. Commonly this is used
+ to assign the anonymous request particular roles, which can subsequently be used in authorization
+ decisions. If unset, defaults to <code class="literal">ROLE_ANONYMOUS</code>.</p></div><div class="section" title="key"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-anonymous-key"></a><code class="literal">key</code></h5></div></div></div><p>The key shared between the provider and filter. This generally does not need to be set. If
+ unset, it will default to a secure randomly generated value. This means setting this value can
+ improve startup time when using the anonymous functionality since secure random values can take
+ a while to be generated.</p></div><div class="section" title="username"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-anonymous-username"></a><code class="literal">username</code></h5></div></div></div><p>The username that should be assigned to the anonymous request. This allows the principal to
+ be identified, which may be important for logging and auditing. if unset, defaults to
+ <code class="literal">anonymousUser</code>.</p></div></div></div><div class="section" title="B.1.5 <custom-filter>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-custom-filter"></a>B.1.5 <code class="literal"><custom-filter></code></h3></div></div></div><p>This element is used to add a filter to the filter chain. It doesn't create any
+ additional beans but is used to select a bean of type
+ <code class="interfacename">javax.servlet.Filter</code> which is already defined in the
+ application context and add that at a particular position in the filter chain
+ maintained by Spring Security. Full details can be found in the <a class="link" href="#ns-custom-filters" title="3.3.5 Adding in Your Own Filters">
+ namespace chapter</a>.</p><div class="section" title="Parent Elements of <custom-filter>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-custom-filter-parents"></a>Parent Elements of <code class="literal"><custom-filter></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-http" title="B.1.2 <http>">http</a></li></ul></div></div><div class="section" title="<custom-filter> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-custom-filter-attributes"></a><code class="literal"><custom-filter></code> Attributes</h4></div></div></div><div class="section" title="after"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-custom-filter-after"></a><code class="literal">after</code></h5></div></div></div><p>The filter immediately after which the custom-filter should be placed in the chain. This
+ feature will only be needed by advanced users who wish to mix their own filters into the
+ security filter chain and have some knowledge of the standard Spring Security filters. The
+ filter names map to specific Spring Security implementation filters.</p></div><div class="section" title="before"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-custom-filter-before"></a><code class="literal">before</code></h5></div></div></div><p>The filter immediately before which the custom-filter should be placed in the chain</p></div><div class="section" title="position"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-custom-filter-position"></a><code class="literal">position</code></h5></div></div></div><p>The explicit position at which the custom-filter should be placed in the chain. Use if you
+ are replacing a standard filter.</p></div><div class="section" title="ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-custom-filter-ref"></a><code class="literal">ref</code></h5></div></div></div><p>Defines a reference to a Spring bean that implements <code class="interfacename">Filter</code>.</p></div></div></div><div class="section" title="B.1.6 <expression-handler>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-expression-handler"></a>B.1.6 <code class="literal"><expression-handler></code></h3></div></div></div><p>Defines the <code class="interfacename">SecurityExpressionHandler</code> instance which will be used if
+ expression-based access-control is enabled. A default implementation (with no ACL support) will be used
+ if not supplied.</p><div class="section" title="Parent Elements of <expression-handler>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-expression-handler-parents"></a>Parent Elements of <code class="literal"><expression-handler></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-global-method-security" title="B.3.1 <global-method-security>">global-method-security</a></li><li class="listitem"><a class="link" href="#nsa-http" title="B.1.2 <http>">http</a></li></ul></div></div><div class="section" title="<expression-handler> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-expression-handler-attributes"></a><code class="literal"><expression-handler></code> Attributes</h4></div></div></div><div class="section" title="ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-expression-handler-ref"></a><code class="literal">ref</code></h5></div></div></div><p>Defines a reference to a Spring bean that implements <code class="interfacename">SecurityExpressionHandler</code>.</p></div></div></div><div class="section" title="B.1.7 <form-login>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-form-login"></a>B.1.7 <code class="literal"><form-login></code></h3></div></div></div><p>Used to add an <code class="classname">UsernamePasswordAuthenticationFilter</code> to the
+ filter stack and an <code class="classname">LoginUrlAuthenticationEntryPoint</code> to the
+ application context to provide authentication on demand. This will always take
+ precedence over other namespace-created entry points. If no attributes are supplied,
+ a login page will be generated automatically at the URL "/spring_security_login" <sup>[<a name="d0e9129" href="#ftn.d0e9129" class="footnote">25</a>]</sup> The behaviour can be customized using the <a class="link" href="#nsa-form-login-attributes" title="<form-login> Attributes">
+ <code class="literal"><form-login></code> Attributes</a>.</p><div class="section" title="Parent Elements of <form-login>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-form-login-parents"></a>Parent Elements of <code class="literal"><form-login></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-http" title="B.1.2 <http>">http</a></li></ul></div></div><div class="section" title="<form-login> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-form-login-attributes"></a><code class="literal"><form-login></code> Attributes</h4></div></div></div><div class="section" title="always-use-default-target"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-form-login-always-use-default-target"></a><code class="literal">always-use-default-target</code></h5></div></div></div><p>If set to <code class="literal">true</code>, the user will always start at the value given by
+ <a class="link" href="#nsa-form-login-default-target-url" title="default-target-url">default-target-url</a>, regardless
+ of how they arrived at the login page. Maps to the <code class="literal">alwaysUseDefaultTargetUrl</code>
+ property of <code class="classname">UsernamePasswordAuthenticationFilter</code>. Default value is
+ <code class="literal">false</code>.</p></div><div class="section" title="authentication-details-source-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-form-login-authentication-details-source-ref"></a><code class="literal">authentication-details-source-ref</code></h5></div></div></div><p>Reference to an <code class="interfacename">AuthenticationDetailsSource</code> which will be used
+ by the authentication filter</p></div><div class="section" title="authentication-failure-handler-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-form-login-authentication-failure-handler-ref"></a><code class="literal">authentication-failure-handler-ref</code></h5></div></div></div><p>Can be used as an alternative to
+ <a class="link" href="#nsa-form-login-authentication-failure-url" title="authentication-failure-url">authentication-failure-url</a>,
+ giving you full control over the navigation flow after an authentication failure. The value
+ should be he name of an <code class="interfacename">AuthenticationFailureHandler</code> bean in the
+ application context.</p></div><div class="section" title="authentication-failure-url"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-form-login-authentication-failure-url"></a><code class="literal">authentication-failure-url</code></h5></div></div></div><p>Maps to the <code class="literal">authenticationFailureUrl</code> property of
+ <code class="classname">UsernamePasswordAuthenticationFilter</code>. Defines the URL the
+ browser will be redirected to on login failure. Defaults to
+ <code class="literal">/spring_security_login?login_error</code>, which will be automatically handled by
+ the automatic login page generator, re-rendering the login page with an error message.</p></div><div class="section" title="authentication-success-handler-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-form-login-authentication-success-handler-ref"></a><code class="literal">authentication-success-handler-ref</code></h5></div></div></div><p>This can be used as an alternative to
+ <a class="link" href="#nsa-form-login-default-target-url" title="default-target-url">default-target-url</a>
+ and <a class="link" href="#nsa-form-login-always-use-default-target" title="always-use-default-target">always-use-default-target</a>,
+ giving you full control over the navigation flow after a successful authentication. The value
+ should be the name of an <code class="interfacename">AuthenticationSuccessHandler</code> bean in
+ the application context. By default, an implementation of
+ <code class="classname">SavedRequestAwareAuthenticationSuccessHandler</code> is used and
+ injected with the <a class="link" href="#nsa-form-login-default-target-url" title="default-target-url">default-target-url
+ </a>.</p></div><div class="section" title="default-target-url"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-form-login-default-target-url"></a><code class="literal">default-target-url</code></h5></div></div></div><p>Maps to the <code class="literal">defaultTargetUrl</code> property of
+ <code class="classname">UsernamePasswordAuthenticationFilter</code>. If not set, the
+ default value is "/" (the application root). A user will be taken to this URL
+ after logging in, provided they were not asked to login while attempting to
+ access a secured resource, when they will be taken to the originally requested
+ URL.</p></div><div class="section" title="login-page"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-form-login-login-page"></a><code class="literal">login-page</code></h5></div></div></div><p> The URL that should be used to render the login page. Maps to the
+ <code class="literal">loginFormUrl</code> property of the
+ <code class="classname">LoginUrlAuthenticationEntryPoint</code>. Defaults to
+ "/spring_security_login".</p></div><div class="section" title="login-processing-url"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-form-login-login-processing-url"></a><code class="literal">login-processing-url</code></h5></div></div></div><p> Maps to the <code class="literal">filterProcessesUrl</code> property of
+ <code class="classname">UsernamePasswordAuthenticationFilter</code>. The default value
+ is "/j_spring_security_check".</p></div><div class="section" title="password-parameter"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-form-login-password-parameter"></a><code class="literal">password-parameter</code></h5></div></div></div><p>The name of the request parameter which contains the password. Defaults to "j_password".</p></div><div class="section" title="username-parameter"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-form-login-username-parameter"></a><code class="literal">username-parameter</code></h5></div></div></div><p>The name of the request parameter which contains the username. Defaults to "j_username".</p></div></div></div><div class="section" title="B.1.8 <http-basic>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-http-basic"></a>B.1.8 <code class="literal"><http-basic></code></h3></div></div></div><p>Adds a <code class="classname">BasicAuthenticationFilter</code> and
+ <code class="classname">BasicAuthenticationEntryPoint</code> to the configuration. The
+ latter will only be used as the configuration entry point if form-based login is not
+ enabled.</p><div class="section" title="Parent Elements of <http-basic>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-http-basic-parents"></a>Parent Elements of <code class="literal"><http-basic></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-http" title="B.1.2 <http>">http</a></li></ul></div></div><div class="section" title="<http-basic> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-http-basic-attributes"></a><code class="literal"><http-basic></code> Attributes</h4></div></div></div><div class="section" title="authentication-details-source-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-basic-authentication-details-source-ref"></a><code class="literal">authentication-details-source-ref</code></h5></div></div></div><p>Reference to an <code class="interfacename">AuthenticationDetailsSource</code> which will be used
+ by the authentication filter</p></div><div class="section" title="entry-point-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-basic-entry-point-ref"></a><code class="literal">entry-point-ref</code></h5></div></div></div><p>Sets the <code class="interfacename">AuthenticationEntryPoint</code> which is used by the
+ <code class="classname">BasicAuthenticationFilter</code>.</p></div></div></div><div class="section" title="B.1.9 <http-firewall> Element"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-http-firewall"></a>B.1.9 <code class="literal"><http-firewall></code> Element</h3></div></div></div><p>This is a top-level element which can be used to inject a custom implementation of
+ <code class="interfacename">HttpFirewall</code> into the
+ <code class="classname">FilterChainProxy</code> created by the namespace. The default
+ implementation should be suitable for most applications.</p><div class="section" title="<http-firewall> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-http-firewall-attributes"></a><code class="literal"><http-firewall></code> Attributes</h4></div></div></div><div class="section" title="ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-http-firewall-ref"></a><code class="literal">ref</code></h5></div></div></div><p>Defines a reference to a Spring bean that implements <code class="interfacename">HttpFirewall</code>.</p></div></div></div><div class="section" title="B.1.10 <intercept-url>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-intercept-url"></a>B.1.10 <code class="literal"><intercept-url></code></h3></div></div></div><p>This element is used to define the set of URL patterns that the application is
interested in and to configure how they should be handled. It is used to construct
the <code class="interfacename">FilterInvocationSecurityMetadataSource</code> used by
the <code class="classname">FilterSecurityInterceptor</code>. It is also responsible for
@@ -4048,101 +4912,133 @@ create table acl_entry(
need to be accessed by HTTPS, for example. When matching the specified patterns
against an incoming request, the matching is done in the order in which the elements
are declared. So the most specific matches patterns should come first and the most
- general should come last.</p><div class="section" title="pattern"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-pattern"></a><code class="literal">pattern</code></h4></div></div></div><p> The pattern which defines the URL path. The content will depend on the
- <code class="literal">request-matcher</code> attribute from the containing http element,
- so will default to ant path syntax. </p></div><div class="section" title="method"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-method"></a><code class="literal">method</code></h4></div></div></div><p> The HTTP Method which will be used in combination with the pattern to match
- an incoming request. If omitted, any method will match. If an identical pattern
- is specified with and without a method, the method-specific match will take
- precedence.</p></div><div class="section" title="access"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-access"></a><code class="literal">access</code></h4></div></div></div><p> Lists the access attributes which will be stored in the
- <code class="interfacename">FilterInvocationSecurityMetadataSource</code> for the
- defined URL pattern/method combination. This should be a comma-separated list of
- the security configuration attributes (such as role names). </p></div><div class="section" title="requires-channel"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-requires-channel"></a><code class="literal">requires-channel</code></h4></div></div></div><p> Can be <span class="quote">“<span class="quote">http</span>”</span> or <span class="quote">“<span class="quote">https</span>”</span> depending on whether a
- particular URL pattern should be accessed over HTTP or HTTPS respectively.
- Alternatively the value <span class="quote">“<span class="quote">any</span>”</span> can be used when there is no
- preference. If this attribute is present on any
- <code class="literal"><intercept-url></code> element, then a
- <code class="classname">ChannelAuthenticationFilter</code> will be added to the filter
- stack and its additional dependencies added to the application
- context.</p><p> If a <code class="literal"><port-mappings></code> configuration is added, this
- will be used to by the <code class="classname">SecureChannelProcessor</code> and
- <code class="classname">InsecureChannelProcessor</code> beans to determine the ports
- used for redirecting to HTTP/HTTPS. </p></div><div class="section" title="filters"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7363"></a><code class="literal">filters</code></h4></div></div></div><p>Can only take the value <span class="quote">“<span class="quote">none</span>”</span>. This will cause any matching
- request to bypass the Spring Security filter chain entirely. None of the rest of
- the <code class="literal"><http></code> configuration will have any effect on the
- request and there will be no security context available for its duration. Access
- to secured methods during the request will fail.</p></div></div><div class="section" title="B.1.4 The <port-mappings> Element"><div class="titlepage"><div><div><h3 class="title"><a name="d0e7375"></a>B.1.4 The <code class="literal"><port-mappings></code> Element</h3></div></div></div><p> By default, an instance of <code class="classname">PortMapperImpl</code> will be added to
+ general should come last.</p><div class="section" title="Parent Elements of <intercept-url>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-intercept-url-parents"></a>Parent Elements of <code class="literal"><intercept-url></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-filter-invocation-definition-source" title="B.1.25 <filter-invocation-definition-source>">filter-invocation-definition-source</a></li><li class="listitem"><a class="link" href="#nsa-filter-security-metadata-source" title="B.1.26 <filter-security-metadata-source>">filter-security-metadata-source</a></li><li class="listitem"><a class="link" href="#nsa-http" title="B.1.2 <http>">http</a></li></ul></div></div><div class="section" title="<intercept-url> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-intercept-url-attributes"></a><code class="literal"><intercept-url></code> Attributes</h4></div></div></div><div class="section" title="access"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-intercept-url-access"></a><code class="literal">access</code></h5></div></div></div><p>Lists the access attributes which will be stored in the
+ <code class="interfacename">FilterInvocationSecurityMetadataSource</code> for the
+ defined URL pattern/method combination. This should be a comma-separated list of
+ the security configuration attributes (such as role names).</p></div><div class="section" title="filters"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-intercept-url-filters"></a><code class="literal">filters</code></h5></div></div></div><p>Can only take the value <span class="quote">“<span class="quote">none</span>”</span>. This will cause any matching
+ request to bypass the Spring Security filter chain entirely. None of the rest of
+ the <code class="literal"><http></code> configuration will have any effect on the
+ request and there will be no security context available for its duration. Access
+ to secured methods during the request will fail.</p></div><div class="section" title="method"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-intercept-url-method"></a><code class="literal">method</code></h5></div></div></div><p>The HTTP Method which will be used in combination with the pattern to match
+ an incoming request. If omitted, any method will match. If an identical pattern
+ is specified with and without a method, the method-specific match will take
+ precedence.</p></div><div class="section" title="pattern"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-intercept-url-pattern"></a><code class="literal">pattern</code></h5></div></div></div><p>The pattern which defines the URL path. The content will depend on the
+ <code class="literal">request-matcher</code> attribute from the containing http element,
+ so will default to ant path syntax.</p></div><div class="section" title="requires-channel"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-intercept-url-requires-channel"></a><code class="literal">requires-channel</code></h5></div></div></div><p>Can be <span class="quote">“<span class="quote">http</span>”</span> or <span class="quote">“<span class="quote">https</span>”</span> depending on whether a
+ particular URL pattern should be accessed over HTTP or HTTPS respectively.
+ Alternatively the value <span class="quote">“<span class="quote">any</span>”</span> can be used when there is no
+ preference. If this attribute is present on any
+ <code class="literal"><intercept-url></code> element, then a
+ <code class="classname">ChannelAuthenticationFilter</code> will be added to the filter
+ stack and its additional dependencies added to the application
+ context.</p><p>If a <code class="literal"><port-mappings></code> configuration is added, this
+ will be used to by the <code class="classname">SecureChannelProcessor</code> and
+ <code class="classname">InsecureChannelProcessor</code> beans to determine the ports
+ used for redirecting to HTTP/HTTPS. </p></div></div></div><div class="section" title="B.1.11 <jee>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-jee"></a>B.1.11 <code class="literal"><jee></code></h3></div></div></div><p>Adds a J2eePreAuthenticatedProcessingFilter to the filter chain to provide integration with container
+ authentication.</p><div class="section" title="Parent Elements of <jee>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-jee-parents"></a>Parent Elements of <code class="literal"><jee></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-http" title="B.1.2 <http>">http</a></li></ul></div></div><div class="section" title="<jee> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-jee-attributes"></a><code class="literal"><jee></code> Attributes</h4></div></div></div><div class="section" title="mappable-roles"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-jee-mappable-roles"></a><code class="literal">mappable-roles</code></h5></div></div></div><p>A comma-separate list of roles to look for in the incoming HttpServletRequest.</p></div><div class="section" title="user-service-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-jee-user-service-ref"></a><code class="literal">user-service-ref</code></h5></div></div></div><p>A reference to a user-service (or UserDetailsService bean) Id</p></div></div></div><div class="section" title="B.1.12 <logout>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-logout"></a>B.1.12 <code class="literal"><logout></code></h3></div></div></div><p>Adds a <code class="classname">LogoutFilter</code> to the filter stack. This is
+ configured with a <code class="classname">SecurityContextLogoutHandler</code>.</p><div class="section" title="Parent Elements of <logout>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-logout-parents"></a>Parent Elements of <code class="literal"><logout></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-http" title="B.1.2 <http>">http</a></li></ul></div></div><div class="section" title="<logout> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-logout-attributes"></a><code class="literal"><logout></code> Attributes</h4></div></div></div><div class="section" title="The delete-cookies attribute"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-logout-delete-cookies"></a>The <code class="literal">delete-cookies</code> attribute</h5></div></div></div><p>A comma-separated list of the names of cookies which should be deleted when the user logs out.
+ </p></div><div class="section" title="The invalidate-session attribute"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-logout-invalidate-session"></a>The <code class="literal">invalidate-session</code> attribute</h5></div></div></div><p> Maps to the <code class="literal">invalidateHttpSession</code> of the
+ <code class="classname">SecurityContextLogoutHandler</code>. Defaults to "true", so the
+ session will be invalidated on logout.</p></div><div class="section" title="The logout-success-url attribute"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-logout-logout-success-url"></a>The <code class="literal">logout-success-url</code> attribute</h5></div></div></div><p>The destination URL which the user will be taken to after logging out.
+ Defaults to "/". </p><p>Setting this attribute will inject the <code class="classname">SessionManagementFilter</code>
+ with a <code class="classname">SimpleRedirectInvalidSessionStrategy</code> configured with
+ the attribute value. When an invalid session ID is submitted, the strategy will be invoked,
+ redirecting to the configured URL.</p></div><div class="section" title="The logout-url attribute"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-logout-logout-url"></a>The <code class="literal">logout-url</code> attribute</h5></div></div></div><p> The URL which will cause a logout (i.e. which will be processed by the
+ filter). Defaults to "/j_spring_security_logout". </p></div><div class="section" title="The success-handler-ref attribute"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-logout-success-handler-ref"></a>The <code class="literal">success-handler-ref</code> attribute</h5></div></div></div><p>May be used to supply an instance of <code class="interfacename">LogoutSuccessHandler</code>
+ which will be invoked to control the navigation after logging out.
+ </p></div></div></div><div class="section" title="B.1.13 <openid-login>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-openid-login"></a>B.1.13 <code class="literal"><openid-login></code></h3></div></div></div><p> Similar to <code class="literal"><form-login></code> and has the same attributes. The
+ default value for <code class="literal">login-processing-url</code> is
+ "/j_spring_openid_security_check". An
+ <code class="classname">OpenIDAuthenticationFilter</code> and
+ <code class="classname">OpenIDAuthenticationProvider</code> will be registered. The latter
+ requires a reference to a <code class="interfacename">UserDetailsService</code>. Again,
+ this can be specified by <code class="literal">id</code>, using the <code class="literal">user-service-ref</code>
+ attribute, or will be located automatically in the application context. </p><div class="section" title="Parent Elements of <openid-login>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-openid-login-parents"></a>Parent Elements of <code class="literal"><openid-login></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-http" title="B.1.2 <http>">http</a></li></ul></div></div><div class="section" title="<openid-login> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-openid-login-attributes"></a><code class="literal"><openid-login></code> Attributes</h4></div></div></div><div class="section" title="always-use-default-target"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-openid-login-always-use-default-target"></a><code class="literal">always-use-default-target</code></h5></div></div></div><p>Whether the user should always be redirected to the default-target-url after login.</p></div><div class="section" title="authentication-details-source-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-openid-login-authentication-details-source-ref"></a><code class="literal">authentication-details-source-ref</code></h5></div></div></div><p>Reference to an AuthenticationDetailsSource which will be used by the authentication filter</p></div><div class="section" title="authentication-failure-handler-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-openid-login-authentication-failure-handler-ref"></a><code class="literal">authentication-failure-handler-ref</code></h5></div></div></div><p>Reference to an AuthenticationFailureHandler bean which should be used to handle a failed
+ authentication request. Should not be used in combination with authentication-failure-url as the
+ implementation should always deal with navigation to the subsequent destination</p></div><div class="section" title="authentication-failure-url"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-openid-login-authentication-failure-url"></a><code class="literal">authentication-failure-url</code></h5></div></div></div><p>The URL for the login failure page. If no login failure URL is specified, Spring Security will
+ automatically create a failure login URL at /spring_security_login?login_error and a corresponding
+ filter to render that login failure URL when requested.</p></div><div class="section" title="authentication-success-handler-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-openid-login-authentication-success-handler-ref"></a><code class="literal">authentication-success-handler-ref</code></h5></div></div></div><p>Reference to an AuthenticationSuccessHandler bean which should be used to handle a successful
+ authentication request. Should not be used in combination with
+ <a class="link" href="#nsa-openid-login-default-target-url" title="default-target-url">default-target-url</a> (or
+ <a class="link" href="#nsa-openid-login-always-use-default-target" title="always-use-default-target">
+ always-use-default-target</a>) as the implementation should always deal with navigation
+ to the subsequent destination</p></div><div class="section" title="default-target-url"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-openid-login-default-target-url"></a><code class="literal">default-target-url</code></h5></div></div></div><p>The URL that will be redirected to after successful authentication, if the user's previous action
+ could not be resumed. This generally happens if the user visits a login page without having first requested a
+ secured operation that triggers authentication. If unspecified, defaults to the root of the application.</p></div><div class="section" title="login-page"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-openid-login-login-page"></a><code class="literal">login-page</code></h5></div></div></div><p>The URL for the login page. If no login URL is specified, Spring Security will automatically
+ create a login URL at /spring_security_login and a corresponding filter to render that login URL when requested.
+ </p></div><div class="section" title="login-processing-url"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-openid-login-login-processing-url"></a><code class="literal">login-processing-url</code></h5></div></div></div><p>The URL that the login form is posted to. If unspecified, it defaults to /j_spring_security_check.</p></div><div class="section" title="password-parameter"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-openid-login-password-parameter"></a><code class="literal">password-parameter</code></h5></div></div></div><p>The name of the request parameter which contains the password. Defaults to "j_password".</p></div><div class="section" title="user-service-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-openid-login-user-service-ref"></a><code class="literal">user-service-ref</code></h5></div></div></div><p>A reference to a user-service (or UserDetailsService bean) Id</p></div><div class="section" title="username-parameter"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-openid-login-username-parameter"></a><code class="literal">username-parameter</code></h5></div></div></div><p>The name of the request parameter which contains the username. Defaults to "j_username".</p></div></div><div class="section" title="Child Elements of <openid-login>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-openid-login-children"></a>Child Elements of <openid-login></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-attribute-exchange" title="B.1.14 <attribute-exchange>">attribute-exchange</a></li></ul></div></div></div><div class="section" title="B.1.14 <attribute-exchange>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-attribute-exchange"></a>B.1.14 <code class="literal"><attribute-exchange></code></h3></div></div></div><p>The <code class="literal">attribute-exchange</code> element defines the list of
+ attributes which should be requested from the identity provider. An example can be found
+ in the <a class="link" href="#ns-openid" title="3.3.4 OpenID Support">OpenID Support</a> section of the namespace configuration
+ chapter. More than one can be used, in which case each must have an <code class="literal">identifier-match</code>
+ attribute, containing a regular expression which is matched against the supplied
+ OpenID identifier. This allows different attribute lists to be fetched from
+ different providers (Google, Yahoo etc).</p><div class="section" title="Parent Elements of <attribute-exchange>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-attribute-exchange-parents"></a>Parent Elements of <code class="literal"><attribute-exchange></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-openid-login" title="B.1.13 <openid-login>">openid-login</a></li></ul></div></div><div class="section" title="<attribute-exchange> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-attribute-exchange-attributes"></a><code class="literal"><attribute-exchange></code> Attributes</h4></div></div></div><div class="section" title="identifier-match"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-attribute-exchange-identifier-match"></a><code class="literal">identifier-match</code></h5></div></div></div><p>A regular expression which will be compared against the claimed identity, when deciding which
+ attribute-exchange configuration to use during authentication.</p></div></div><div class="section" title="Child Elements of <attribute-exchange>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-attribute-exchange-children"></a>Child Elements of <code class="literal"><attribute-exchange></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-openid-attribute" title="B.1.15 <openid-attribute>">openid-attribute</a></li></ul></div></div></div><div class="section" title="B.1.15 <openid-attribute>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-openid-attribute"></a>B.1.15 <code class="literal"><openid-attribute></code></h3></div></div></div><p>Attributes used when making an OpenID AX
+ <a class="link" href="http://openid.net/specs/openid-attribute-exchange-1_0.html#fetch_request" target="_top">
+ Fetch Request</a></p><div class="section" title="Parent Elements of <openid-attribute>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-openid-attribute-parents"></a>Parent Elements of <code class="literal"><openid-attribute></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-attribute-exchange" title="B.1.14 <attribute-exchange>">attribute-exchange</a></li></ul></div></div><div class="section" title="<openid-attribute> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-openid-attribute-attributes"></a><code class="literal"><openid-attribute></code> Attributes</h4></div></div></div><div class="section" title="count"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-openid-attribute-count"></a><code class="literal">count</code></h5></div></div></div><p>Specifies the number of attributes that you wish to get back. For example, return 3 emails.
+ The default value is 1.</p></div><div class="section" title="name"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-openid-attribute-name"></a><code class="literal">name</code></h5></div></div></div><p>Specifies the name of the attribute that you wish to get back. For example, email.</p></div><div class="section" title="required"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-openid-attribute-required"></a><code class="literal">required</code></h5></div></div></div><p>Specifies if this attribute is required to the OP, but does not error out if the OP does not
+ return the attribute. Default is false.</p></div><div class="section" title="type"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-openid-attribute-type"></a><code class="literal">type</code></h5></div></div></div><p>Specifies the attribute type. For example, http://axschema.org/contact/email. See your OP's
+ documentation for valid attribute types.</p></div></div></div><div class="section" title="B.1.16 <port-mappings>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-port-mappings"></a>B.1.16 <code class="literal"><port-mappings></code></h3></div></div></div><p> By default, an instance of <code class="classname">PortMapperImpl</code> will be added to
the configuration for use in redirecting to secure and insecure URLs. This element
can optionally be used to override the default mappings which that class defines.
Each child <code class="literal"><port-mapping></code> element defines a pair of
HTTP:HTTPS ports. The default mappings are 80:443 and 8080:8443. An example of
- overriding these can be found in the <a class="link" href="#ns-requires-channel" title="2.3.2 Adding HTTP/HTTPS Channel Security">namespace introduction</a>. </p></div><div class="section" title="B.1.5 The <form-login> Element"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-form-login"></a>B.1.5 The <code class="literal"><form-login></code> Element</h3></div></div></div><p> Used to add an <code class="classname">UsernamePasswordAuthenticationFilter</code> to the
- filter stack and an <code class="classname">LoginUrlAuthenticationEntryPoint</code> to the
- application context to provide authentication on demand. This will always take
- precedence over other namespace-created entry points. If no attributes are supplied,
- a login page will be generated automatically at the URL "/spring_security_login" <sup>[<a name="d0e7406" href="#ftn.d0e7406" class="footnote">17</a>]</sup> The behaviour can be customized using the following attributes. </p><div class="section" title="login-page"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7413"></a><code class="literal">login-page</code></h4></div></div></div><p> The URL that should be used to render the login page. Maps to the
- <code class="literal">loginFormUrl</code> property of the
- <code class="classname">LoginUrlAuthenticationEntryPoint</code>. Defaults to
- "/spring_security_login". </p></div><div class="section" title="login-processing-url"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7425"></a><code class="literal">login-processing-url</code></h4></div></div></div><p> Maps to the <code class="literal">filterProcessesUrl</code> property of
- <code class="classname">UsernamePasswordAuthenticationFilter</code>. The default value
- is "/j_spring_security_check". </p></div><div class="section" title="default-target-url"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7437"></a><code class="literal">default-target-url</code></h4></div></div></div><p>Maps to the <code class="literal">defaultTargetUrl</code> property of
- <code class="classname">UsernamePasswordAuthenticationFilter</code>. If not set, the
- default value is "/" (the application root). A user will be taken to this URL
- after logging in, provided they were not asked to login while attempting to
- access a secured resource, when they will be taken to the originally requested
- URL. </p></div><div class="section" title="always-use-default-target"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7449"></a><code class="literal">always-use-default-target</code></h4></div></div></div><p> If set to "true", the user will always start at the value given by
- <code class="literal">default-target-url</code>, regardless of how they arrived at the
- login page. Maps to the <code class="literal">alwaysUseDefaultTargetUrl</code> property of
- <code class="classname">UsernamePasswordAuthenticationFilter</code>. Default value is
- "false". </p></div><div class="section" title="authentication-failure-url"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7464"></a><code class="literal">authentication-failure-url</code></h4></div></div></div><p> Maps to the <code class="literal">authenticationFailureUrl</code> property of
- <code class="classname">UsernamePasswordAuthenticationFilter</code>. Defines the URL the
- browser will be redirected to on login failure. Defaults to
- "/spring_security_login?login_error", which will be automatically handled by the
- automatic login page generator, re-rendering the login page with an error
- message. </p></div><div class="section" title="authentication-success-handler-ref"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7476"></a><code class="literal">authentication-success-handler-ref</code></h4></div></div></div><p>This can be used as an alternative to <code class="literal">default-target-url</code>
- and <code class="literal">always-use-default-target</code>, giving you full control over
- the navigation flow after a successful authentication. The value should be the
- name of an <code class="interfacename">AuthenticationSuccessHandler</code> bean in
- the application context. By default, an imlementation of
- <code class="classname">SavedRequestAwareAuthenticationSuccessHandler</code> is used and
- injected with the <code class="literal">default-target-url</code>.</p></div><div class="section" title="authentication-failure-handler-ref"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7497"></a><code class="literal">authentication-failure-handler-ref</code></h4></div></div></div><p>Can be used as an alternative to
- <code class="literal">authentication-failure-url</code>, giving you full control over the
- navigation flow after an authentication failure. The value should be he name of
- an <code class="interfacename">AuthenticationFailureHandler</code> bean in the
- application context. </p></div></div><div class="section" title="B.1.6 The <http-basic> Element"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-http-basic"></a>B.1.6 The <code class="literal"><http-basic></code> Element</h3></div></div></div><p> Adds a <code class="classname">BasicAuthenticationFilter</code> and
- <code class="classname">BasicAuthenticationEntryPoint</code> to the configuration. The
- latter will only be used as the configuration entry point if form-based login is not
- enabled. </p></div><div class="section" title="B.1.7 The <remember-me> Element"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-remember-me"></a>B.1.7 The <code class="literal"><remember-me></code> Element</h3></div></div></div><p> Adds the <code class="classname">RememberMeAuthenticationFilter</code> to the stack. This
+ overriding these can be found in the <a class="link" href="#ns-requires-channel" title="3.3.2 Adding HTTP/HTTPS Channel Security">namespace introduction</a>. </p><div class="section" title="Parent Elements of <port-mappings>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-port-mappings-parents"></a>Parent Elements of <code class="literal"><port-mappings></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-http" title="B.1.2 <http>">http</a></li></ul></div></div><div class="section" title="Child Elements of <port-mappings>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-port-mappings-children"></a>Child Elements of <code class="literal"><port-mappings></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-port-mapping" title="B.1.17 <port-mapping>">port-mapping</a></li></ul></div></div></div><div class="section" title="B.1.17 <port-mapping>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-port-mapping"></a>B.1.17 <code class="literal"><port-mapping></code></h3></div></div></div><p>Provides a method to map http ports to https ports when forcing a redirect.</p><div class="section" title="Parent Elements of <port-mapping>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-port-mapping-parents"></a>Parent Elements of <code class="literal"><port-mapping></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-port-mappings" title="B.1.16 <port-mappings>">port-mappings</a></li></ul></div></div><div class="section" title="<port-mapping> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-port-mapping-attributes"></a><code class="literal"><port-mapping></code> Attributes</h4></div></div></div><div class="section" title="http"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-port-mapping-http"></a><code class="literal">http</code></h5></div></div></div><p>The http port to use.</p></div><div class="section" title="https"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-port-mapping-https"></a><code class="literal">https</code></h5></div></div></div><p>The https port to use.</p></div></div></div><div class="section" title="B.1.18 <remember-me>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-remember-me"></a>B.1.18 <code class="literal"><remember-me></code></h3></div></div></div><p> Adds the <code class="classname">RememberMeAuthenticationFilter</code> to the stack. This
in turn will be configured with either a
<code class="classname">TokenBasedRememberMeServices</code>, a
<code class="classname">PersistentTokenBasedRememberMeServices</code> or a user-specified
bean implementing <code class="interfacename">RememberMeServices</code> depending on the
- attribute settings. </p><div class="section" title="data-source-ref"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7543"></a><code class="literal">data-source-ref</code></h4></div></div></div><p> If this is set, <code class="classname">PersistentTokenBasedRememberMeServices</code>
- will be used and configured with a
- <code class="classname">JdbcTokenRepositoryImpl</code> instance. </p></div><div class="section" title="services-ref"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7555"></a><code class="literal">services-ref</code></h4></div></div></div><p> Allows complete control of the
- <code class="interfacename">RememberMeServices</code> implementation that will be
- used by the filter. The value should be the <code class="literal">id</code> of a bean in the application
- context which implements this interface. Should also implement
- <code class="interfacename">LogoutHandler</code> if a logout filter is in use.</p></div><div class="section" title="token-repository-ref"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7570"></a><code class="literal">token-repository-ref</code></h4></div></div></div><p> Configures a <code class="classname">PersistentTokenBasedRememberMeServices</code>
- but allows the use of a custom
- <code class="interfacename">PersistentTokenRepository</code> bean. </p></div><div class="section" title="The key Attribute"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7582"></a>The <code class="literal">key</code> Attribute</h4></div></div></div><p>Maps to the "key" property of
- <code class="classname">AbstractRememberMeServices</code>. Should be set to a unique
- value to ensure that remember-me cookies are only valid within the one
- application <sup>[<a name="d0e7593" href="#ftn.d0e7593" class="footnote">18</a>]</sup>. </p></div><div class="section" title="token-validity-seconds"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7600"></a><code class="literal">token-validity-seconds</code></h4></div></div></div><p> Maps to the <code class="literal">tokenValiditySeconds</code> property of
- <code class="classname">AbstractRememberMeServices</code>. Specifies the period in
- seconds for which the remember-me cookie should be valid. By default it will be
- valid for 14 days. </p></div><div class="section" title="user-service-ref"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7612"></a><code class="literal">user-service-ref</code></h4></div></div></div><p> The remember-me services implementations require access to a
- <code class="interfacename">UserDetailsService</code>, so there has to be one
- defined in the application context. If there is only one, it will be selected
- and used automatically by the namespace configuration. If there are multiple
- instances, you can specify a bean <code class="literal">id</code> explicitly using this attribute. </p></div></div><div class="section" title="B.1.8 The <session-management> Element"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-session-mgmt"></a>B.1.8 The <code class="literal"><session-management></code> Element</h3></div></div></div><p>Session-management related functionality is implemented by the addition of a
- <code class="classname">SessionManagementFilter</code> to the filter stack.</p><div class="section" title="session-fixation-protection"><div class="titlepage"><div><div><h4 class="title"><a name="session-fixation-protection"></a><code class="literal">session-fixation-protection</code></h4></div></div></div><p> Indicates whether an existing session should be invalidated when a user
- authenticates and a new session started. If set to "none" no change will be
- made. "newSession" will create a new empty session. "migrateSession" will create
- a new session and copy the session attributes to the new session. Defaults to
- "migrateSession".</p><p> If session fixation protection is enabled, the
- <code class="classname">SessionManagementFilter</code> is inected with a appropriately
- configured <code class="classname">DefaultSessionAuthenticationStrategy</code>. See the
- Javadoc for this class for more details. </p></div></div><div class="section" title="B.1.9 The <concurrency-control> Element"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-concurrent-session-control"></a>B.1.9 The <code class="literal"><concurrency-control></code> Element</h3></div></div></div><p> Adds support for concurrent session control, allowing limits to be placed on the
+ attribute settings. </p><div class="section" title="Parent Elements of <remember-me>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-remember-me-parents"></a>Parent Elements of <code class="literal"><remember-me></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-http" title="B.1.2 <http>">http</a></li></ul></div></div><div class="section" title="<remember-me> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-remember-me-attributes"></a><code class="literal"><remember-me></code> Attributes</h4></div></div></div><div class="section" title="authentication-success-handler-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-remember-me-authentication-success-handler-ref"></a><code class="literal">authentication-success-handler-ref</code></h5></div></div></div><p>Sets the <code class="code">authenticationSuccessHandler</code> property on the
+ <code class="classname">RememberMeAuthenticationFilter</code> if custom navigation is required.
+ The value should be the name of a <code class="interfacename">AuthenticationSuccessHandler</code>
+ bean in the application context. </p></div><div class="section" title="data-source-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-remember-me-data-source-ref"></a><code class="literal">data-source-ref</code></h5></div></div></div><p>A reference to a <code class="interfacename">DataSource</code> bean. If this is set,
+ <code class="classname">PersistentTokenBasedRememberMeServices</code> will be used and configured with a
+ <code class="classname">JdbcTokenRepositoryImpl</code> instance. </p></div><div class="section" title="key"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-remember-me-key"></a><code class="literal">key</code></h5></div></div></div><p>Maps to the "key" property of
+ <code class="classname">AbstractRememberMeServices</code>. Should be set to a unique
+ value to ensure that remember-me cookies are only valid within the one
+ application <sup>[<a name="d0e9921" href="#ftn.d0e9921" class="footnote">26</a>]</sup>. If this is not set a secure random value will be generated. Since generating secure
+ random values can take a while, setting this value explicitly can help improve startup times when
+ using the remember me functionality.</p></div><div class="section" title="services-alias"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-remember-me-services-alias"></a><code class="literal">services-alias</code></h5></div></div></div><p>Exports the internally defined <code class="interfacename">RememberMeServices</code> as a bean alias,
+ allowing it to be used by other beans in the application context.</p></div><div class="section" title="services-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-remember-me-services-ref"></a><code class="literal">services-ref</code></h5></div></div></div><p> Allows complete control of the
+ <code class="interfacename">RememberMeServices</code> implementation that will be
+ used by the filter. The value should be the <code class="literal">id</code> of a bean in the application
+ context which implements this interface. Should also implement
+ <code class="interfacename">LogoutHandler</code> if a logout filter is in use.</p></div><div class="section" title="token-repository-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-remember-me-token-repository-ref"></a><code class="literal">token-repository-ref</code></h5></div></div></div><p> Configures a <code class="classname">PersistentTokenBasedRememberMeServices</code>
+ but allows the use of a custom
+ <code class="interfacename">PersistentTokenRepository</code> bean. </p></div><div class="section" title="token-validity-seconds"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-remember-me-token-validity-seconds"></a><code class="literal">token-validity-seconds</code></h5></div></div></div><p> Maps to the <code class="literal">tokenValiditySeconds</code> property of
+ <code class="classname">AbstractRememberMeServices</code>. Specifies the period in
+ seconds for which the remember-me cookie should be valid. By default it will be
+ valid for 14 days. </p></div><div class="section" title="use-secure-cookie"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-remember-me-use-secure-cookie"></a><code class="literal">use-secure-cookie</code></h5></div></div></div><p>It is recommended that remember-me cookies are only submitted over HTTPS and thus should
+ be flagged as <span class="quote">“<span class="quote">secure</span>”</span>. By default, a secure cookie will be used if the
+ connection over which the login request is made is secure (as it should be).
+ If you set this property to <code class="literal">false</code>, secure cookies will not be used.
+ Setting it to <code class="literal">true</code> will always set the secure flag on the cookie.
+ This attribute maps to the <code class="literal">useSecureCookie</code> property of
+ <code class="classname">AbstractRememberMeServices</code>.
+ </p></div><div class="section" title="user-service-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-remember-me-user-service-ref"></a><code class="literal">user-service-ref</code></h5></div></div></div><p> The remember-me services implementations require access to a
+ <code class="interfacename">UserDetailsService</code>, so there has to be one
+ defined in the application context. If there is only one, it will be selected
+ and used automatically by the namespace configuration. If there are multiple
+ instances, you can specify a bean <code class="literal">id</code> explicitly using this attribute. </p></div></div></div><div class="section" title="B.1.19 <request-cache> Element"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-request-cache"></a>B.1.19 <code class="literal"><request-cache></code> Element</h3></div></div></div><p>Sets the <code class="interfacename">RequestCache</code> instance which will be used
+ by the <code class="classname">ExceptionTranslationFilter</code> to store request
+ information before invoking an
+ <code class="interfacename">AuthenticationEntryPoint</code>. </p><div class="section" title="Parent Elements of <request-cache>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-request-cache-parents"></a>Parent Elements of <code class="literal"><request-cache></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-http" title="B.1.2 <http>">http</a></li></ul></div></div><div class="section" title="<request-cache> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-request-cache-attributes"></a><code class="literal"><request-cache></code> Attributes</h4></div></div></div><div class="section" title="ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-request-cache-ref"></a><code class="literal">ref</code></h5></div></div></div><p>Defines a reference to a Spring bean that is a <code class="interfacename">RequestCache</code>.</p></div></div></div><div class="section" title="B.1.20 <session-management>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-session-management"></a>B.1.20 <code class="literal"><session-management></code></h3></div></div></div><p> Session-management related functionality is implemented by the addition of a
+ <code class="classname">SessionManagementFilter</code> to the filter stack.</p><div class="section" title="Parent Elements of <session-management>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-session-management-parents"></a>Parent Elements of <code class="literal"><session-management></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-http" title="B.1.2 <http>">http</a></li></ul></div></div><div class="section" title="<session-management> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-session-management-attributes"></a><code class="literal"><session-management></code> Attributes</h4></div></div></div><div class="section" title="invalid-session-url"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-session-management-invalid-session-url"></a><code class="literal">invalid-session-url</code></h5></div></div></div><p>Setting this attribute will inject the <code class="classname">SessionManagementFilter</code>
+ with a <code class="classname">SimpleRedirectInvalidSessionStrategy</code> configured with
+ the attribute value. When an invalid session ID is submitted, the strategy will be invoked,
+ redirecting to the configured URL.
+ </p></div><div class="section" title="session-authentication-error-url"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-session-management-session-authentication-error-url"></a><code class="literal">session-authentication-error-url</code></h5></div></div></div><p>Defines the URL of the error page which should be shown when the SessionAuthenticationStrategy
+ raises an exception. If not set, an unauthorized (402) error code will be returned to the client.
+ Note that this attribute doesn't apply if the error occurs during a form-based login, where the URL
+ for authentication failure will take precedence.</p></div><div class="section" title="session-authentication-strategy-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-session-management-session-authentication-strategy-ref"></a><code class="literal">session-authentication-strategy-ref</code></h5></div></div></div><p>Allows injection of the SessionAuthenticationStrategy instance used by the
+ SessionManagementFilter</p></div><div class="section" title="session-fixation-protection"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-session-management-session-fixation-protection"></a><code class="literal">session-fixation-protection</code></h5></div></div></div><p> Indicates whether an existing session should be invalidated when a user
+ authenticates and a new session started. If set to "none" no change will be
+ made. "newSession" will create a new empty session. "migrateSession" will create
+ a new session and copy the session attributes to the new session. Defaults to
+ "migrateSession".</p><p> If session fixation protection is enabled, the
+ <code class="classname">SessionManagementFilter</code> is injected with an appropriately
+ configured <code class="classname">DefaultSessionAuthenticationStrategy</code>. See the
+ Javadoc for this class for more details. </p></div></div><div class="section" title="Child elements of <session-management>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-session-management-children"></a>Child elements of <code class="literal"><session-management></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-concurrency-control" title="B.1.21 <concurrency-control>">concurrency-control</a></li></ul></div></div></div><div class="section" title="B.1.21 <concurrency-control>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-concurrency-control"></a>B.1.21 <code class="literal"><concurrency-control></code></h3></div></div></div><p> Adds support for concurrent session control, allowing limits to be placed on the
number of active sessions a user can have. A
<code class="classname">ConcurrentSessionFilter</code> will be created, and a
<code class="classname">ConcurrentSessionControlStrategy</code> will be used with the
@@ -4151,67 +5047,59 @@ create table acl_entry(
created authentication filter. An instance of
<code class="interfacename">SessionRegistry</code> (a
<code class="classname">SessionRegistryImpl</code> instance unless the user wishes to use a
- custom bean) will be created for use by the strategy.</p><div class="section" title="The max-sessions attribute"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7675"></a>The <code class="literal">max-sessions</code> attribute</h4></div></div></div><p>Maps to the <code class="literal">maximumSessions</code> property of
- <code class="classname">ConcurrentSessionControlStrategy</code>.</p></div><div class="section" title="The expired-url attribute"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7689"></a>The <code class="literal">expired-url</code> attribute</h4></div></div></div><p> The URL a user will be redirected to if they attempt to use a session which
- has been "expired" by the concurrent session controller because the user has
- exceeded the number of allowed sessions and has logged in again elsewhere.
- Should be set unless <code class="literal">exception-if-maximum-exceeded</code> is set. If
- no value is supplied, an expiry message will just be written directly back to
- the response. </p></div><div class="section" title="The error-if-maximum-exceeded attribute"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7700"></a>The <code class="literal">error-if-maximum-exceeded</code> attribute</h4></div></div></div><p>If set to "true" a
- <code class="exceptionname">SessionAuthenticationException</code> will be raised
- when a user attempts to exceed the maximum allowed number of sessions. The
- default behaviour is to expire the original session. </p></div><div class="section" title="The session-registry-alias and session-registry-ref attributes"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7711"></a>The <code class="literal">session-registry-alias</code> and
- <code class="literal">session-registry-ref</code> attributes</h4></div></div></div><p> The user can supply their own <code class="interfacename">SessionRegistry</code>
- implementation using the <code class="literal">session-registry-ref</code> attribute. The
- other concurrent session control beans will be wired up to use it. </p><p> It can also be useful to have a reference to the internal session registry
- for use in your own beans or an admin interface. You can expose the interal bean
- using the <code class="literal">session-registry-alias</code> attribute, giving it a name
- that you can use elsewhere in your configuration. </p></div></div><div class="section" title="B.1.10 The <anonymous> Element"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-anonymous"></a>B.1.10 The <code class="literal"><anonymous></code> Element</h3></div></div></div><p> Adds an <code class="classname">AnonymousAuthenticationFilter</code> to the stack and an
- <code class="classname">AnonymousAuthenticationProvider</code>. Required if you are using
- the <code class="literal">IS_AUTHENTICATED_ANONYMOUSLY</code> attribute. </p></div><div class="section" title="B.1.11 The <x509> Element"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-x509"></a>B.1.11 The <code class="literal"><x509></code> Element</h3></div></div></div><p> Adds support for X.509 authentication. An
+ custom bean) will be created for use by the strategy.</p><div class="section" title="Parent Elements of <concurrency-control>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-concurrency-control-parents"></a>Parent Elements of <code class="literal"><concurrency-control></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-session-management" title="B.1.20 <session-management>">session-management</a></li></ul></div></div><div class="section" title="<concurrency-control> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-concurrency-control-attributes"></a><code class="literal"><concurrency-control></code> Attributes</h4></div></div></div><div class="section" title="error-if-maximum-exceeded"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-concurrency-control-error-if-maximum-exceeded"></a><code class="literal">error-if-maximum-exceeded</code></h5></div></div></div><p>If set to "true" a
+ <code class="exceptionname">SessionAuthenticationException</code> will be raised
+ when a user attempts to exceed the maximum allowed number of sessions. The
+ default behaviour is to expire the original session. </p></div><div class="section" title="expired-url"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-concurrency-control-expired-url"></a><code class="literal">expired-url</code></h5></div></div></div><p> The URL a user will be redirected to if they attempt to use a session which
+ has been "expired" by the concurrent session controller because the user has
+ exceeded the number of allowed sessions and has logged in again elsewhere.
+ Should be set unless <code class="literal">exception-if-maximum-exceeded</code> is set. If
+ no value is supplied, an expiry message will just be written directly back to
+ the response. </p></div><div class="section" title="max-sessions"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-concurrency-control-max-sessions"></a><code class="literal">max-sessions</code></h5></div></div></div><p>Maps to the <code class="literal">maximumSessions</code> property of
+ <code class="classname">ConcurrentSessionControlStrategy</code>.</p></div><div class="section" title="session-registry-alias"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-concurrency-control-session-registry-alias"></a><code class="literal">session-registry-alias</code></h5></div></div></div><p> It can also be useful to have a reference to the internal session registry
+ for use in your own beans or an admin interface. You can expose the internal bean
+ using the <code class="literal">session-registry-alias</code> attribute, giving it a name
+ that you can use elsewhere in your configuration. </p></div><div class="section" title="session-registry-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-concurrency-control-session-registry-ref"></a><code class="literal">session-registry-ref</code></h5></div></div></div><p> The user can supply their own <code class="interfacename">SessionRegistry</code>
+ implementation using the <code class="literal">session-registry-ref</code> attribute. The
+ other concurrent session control beans will be wired up to use it. </p></div></div></div><div class="section" title="B.1.22 <x509>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-x509"></a>B.1.22 <code class="literal"><x509></code></h3></div></div></div><p> Adds support for X.509 authentication. An
<code class="classname">X509AuthenticationFilter</code> will be added to the stack and an
<code class="classname">Http403ForbiddenEntryPoint</code> bean will be created. The latter
- will only be used if no other authentication mechanisms are in use (it's only
+ will only be used if no other authentication mechanisms are in use (its only
functionality is to return an HTTP 403 error code). A
<code class="classname">PreAuthenticatedAuthenticationProvider</code> will also be created
which delegates the loading of user authorities to a
- <code class="interfacename">UserDetailsService</code>. </p><div class="section" title="The subject-principal-regex attribute"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7770"></a>The <code class="literal">subject-principal-regex</code> attribute</h4></div></div></div><p> Defines a regular expression which will be used to extract the username from
- the certificate (for use with the
- <code class="interfacename">UserDetailsService</code>). </p></div><div class="section" title="The user-service-ref attribute"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7781"></a>The <code class="literal">user-service-ref</code> attribute</h4></div></div></div><p> Allows a specific <code class="interfacename">UserDetailsService</code> to be
- used with X.509 in the case where multiple instances are configured. If not set,
- an attempt will be made to locate a suitable instance automatically and use
- that. </p></div></div><div class="section" title="B.1.12 The <openid-login> Element"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-openid-login"></a>B.1.12 The <code class="literal"><openid-login></code> Element</h3></div></div></div><p> Similar to <code class="literal"><form-login></code> and has the same attributes. The
- default value for <code class="literal">login-processing-url</code> is
- "/j_spring_openid_security_check". An
- <code class="classname">OpenIDAuthenticationFilter</code> and
- <code class="classname">OpenIDAuthenticationProvider</code> will be registered. The latter
- requires a reference to a <code class="interfacename">UserDetailsService</code>. Again,
- this can be specified by <code class="literal">id</code>, using the <code class="literal">user-service-ref</code>
- attribute, or will be located automatically in the application context. </p><div class="section" title="The <attribute-exchange> Element"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7821"></a>The <code class="literal"><attribute-exchange></code> Element</h4></div></div></div><p>The <code class="literal">attribute-exchange</code> element defines the list of
- attributes which should be requested from the identity provider. More than one
- can be used, in which case each must have an <code class="literal">identifier-match</code>
- attribute, containing a regular expression which is matched against the supplied
- OpenID identifer. This allows different attribute lists to be fetched from
- different providers (Google, Yahoo etc).</p></div></div><div class="section" title="B.1.13 The <logout> Element"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-logout"></a>B.1.13 The <code class="literal"><logout></code> Element</h3></div></div></div><p> Adds a <code class="classname">LogoutFilter</code> to the filter stack. This is
- configured with a <code class="classname">SecurityContextLogoutHandler</code>. </p><div class="section" title="The logout-url attribute"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7849"></a>The <code class="literal">logout-url</code> attribute</h4></div></div></div><p> The URL which will cause a logout (i.e. which will be processed by the
- filter). Defaults to "/j_spring_security_logout". </p></div><div class="section" title="The logout-success-url attribute"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7857"></a>The <code class="literal">logout-success-url</code> attribute</h4></div></div></div><p> The destination URL which the user will be taken to after logging out.
- Defaults to "/". </p></div><div class="section" title="The success-handler-ref attribute"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7865"></a>The <code class="literal">success-handler-ref</code> attribute</h4></div></div></div><p>May be used to supply an instance of <code class="interfacename">LogoutSuccessHandler</code>
- which will be invoked to control the navigation after logging out.
- </p></div><div class="section" title="The invalidate-session attribute"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7876"></a>The <code class="literal">invalidate-session</code> attribute</h4></div></div></div><p> Maps to the <code class="literal">invalidateHttpSession</code> of the
- <code class="classname">SecurityContextLogoutHandler</code>. Defaults to "true", so the
- session will be invalidated on logout.</p></div><div class="section" title="The delete-cookies attribute"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7890"></a>The <code class="literal">delete-cookies</code> attribute</h4></div></div></div><p>A comma-separated list of the names of cookies which should be deleted when the user logs out.
- </p></div></div><div class="section" title="B.1.14 The <custom-filter> Element"><div class="titlepage"><div><div><h3 class="title"><a name="d0e7898"></a>B.1.14 The <code class="literal"><custom-filter></code> Element</h3></div></div></div><p>This element is used to add a filter to the filter chain. It doesn't create any
- additional beans but is used to select a bean of type
- <code class="interfacename">javax.servlet.Filter</code> which is already defined in the
- appllication context and add that at a particular position in the filter chain
- maintained by Spring Security. Full details can be found in the namespace
- chapter.</p></div><div class="section" title="B.1.15 The request-cache Element"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-request-cache"></a>B.1.15 The <code class="literal">request-cache</code> Element</h3></div></div></div><p>Sets the <code class="interfacename">RequestCache</code> instance which will be used
- by the <code class="classname">ExceptionTranslationFilter</code> to store request
- information before invoking an
- <code class="interfacename">AuthenticationEntryPoint</code>. </p></div><div class="section" title="B.1.16 The <http-firewall> Element"><div class="titlepage"><div><div><h3 class="title"><a name="d0e7926"></a>B.1.16 The <code class="literal"><http-firewall></code> Element</h3></div></div></div><p>This is a top-level element which can be used to inject a custom implementation of
- <code class="interfacename">HttpFirewall</code> into the
- <code class="classname">FilterChainProxy</code> created by the namespace. The default
- implementation should be suitable for most applications.</p></div></div><div class="section" title="B.2 Authentication Services"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="nsa-authentication"></a>B.2 Authentication Services</h2></div></div></div><p> Before Spring Security 3.0, an <code class="interfacename">AuthenticationManager</code>
+ <code class="interfacename">UserDetailsService</code>. </p><div class="section" title="Parent Elements of <x509>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-x509-parents"></a>Parent Elements of <code class="literal"><x509></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-http" title="B.1.2 <http>">http</a></li></ul></div></div><div class="section" title="<x509> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-x509-attributes"></a><code class="literal"><x509></code> Attributes</h4></div></div></div><div class="section" title="authentication-details-source-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-x509-authentication-details-source-ref"></a><code class="literal">authentication-details-source-ref</code></h5></div></div></div><p>A reference to an <code class="interfacename">AuthenticationDetailsSource</code></p></div><div class="section" title="subject-principal-regex"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-x509-subject-principal-regex"></a><code class="literal">subject-principal-regex</code></h5></div></div></div><p> Defines a regular expression which will be used to extract the username from
+ the certificate (for use with the
+ <code class="interfacename">UserDetailsService</code>). </p></div><div class="section" title="user-service-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-x509-user-service-ref"></a><code class="literal">user-service-ref</code></h5></div></div></div><p> Allows a specific <code class="interfacename">UserDetailsService</code> to be
+ used with X.509 in the case where multiple instances are configured. If not set,
+ an attempt will be made to locate a suitable instance automatically and use
+ that. </p></div></div></div><div class="section" title="B.1.23 <filter-chain-map>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-filter-chain-map"></a>B.1.23 <code class="literal"><filter-chain-map></code></h3></div></div></div><p>Used to explicitly configure a FilterChainProxy instance with a FilterChainMap</p><div class="section" title="<filter-chain-map> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-filter-chain-map-attributes"></a><code class="literal"><filter-chain-map></code> Attributes</h4></div></div></div><div class="section" title="path-type"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-filter-chain-map-path-type"></a><code class="literal">path-type</code></h5></div></div></div><p>Superseded by the
+ <a class="link" href="#nsa-filter-chain-map-request-matcher" title="request-matcher">request-matcher</a> attribute</p></div><div class="section" title="request-matcher"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-filter-chain-map-request-matcher"></a><code class="literal">request-matcher</code></h5></div></div></div><p>Supersedes the 'path-type' attribute. Defines the strategy use for matching incoming requests.
+ Currently the options are 'ant' (for ant path patterns), 'regex' for regular expressions and 'ciRegex' for
+ case-insensitive regular expressions.</p></div></div><div class="section" title="Child Elements of <filter-chain-map>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-filter-chain-map-children"></a>Child Elements of <code class="literal"><filter-chain-map></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-filter-chain" title="B.1.24 <filter-chain>">filter-chain</a></li></ul></div></div></div><div class="section" title="B.1.24 <filter-chain>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-filter-chain"></a>B.1.24 <code class="literal"><filter-chain></code></h3></div></div></div><p>Used within to define a specific URL pattern and the list of filters which apply to the URLs matching
+ that pattern. When multiple filter-chain elements are assembled in a list in order to configure a FilterChainProxy,
+ the most specific patterns must be placed at the top of the list, with most general ones at the bottom.</p><div class="section" title="Parent Elements of <filter-chain>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-filter-chain-parents"></a>Parent Elements of <code class="literal"><filter-chain></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-filter-chain-map" title="B.1.23 <filter-chain-map>">filter-chain-map</a></li></ul></div></div><div class="section" title="<filter-chain> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-filter-chain-attributes"></a><code class="literal"><filter-chain></code> Attributes</h4></div></div></div><div class="section" title="filters"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-filter-chain-filters"></a><code class="literal">filters</code></h5></div></div></div><p>A comma separated list of references to Spring beans that implement
+ <code class="interfacename">Filter</code>. The value "none" means that no
+ <code class="interfacename">Filter</code>'s should be used for this
+ <code class="classname">FilterChain</code>.</p></div><div class="section" title="pattern"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-filter-chain-pattern"></a><code class="literal">pattern</code></h5></div></div></div><p>A-pattern that creates RequestMatcher in combination with the
+ <a class="link" href="#nsa-filter-chain-map-request-matcher" title="request-matcher">request-matcher</a></p></div><div class="section" title="request-matcher-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-filter-chain-request-matcher-ref"></a><code class="literal">request-matcher-ref</code></h5></div></div></div><p>A reference to a <code class="interfacename">RequestMatcher</code> that will be used to determine if the
+ <code class="interfacename">Filter</code>'s from the <code class="literal">filters</code> attribute should be invoked.</p></div></div></div><div class="section" title="B.1.25 <filter-invocation-definition-source>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-filter-invocation-definition-source"></a>B.1.25 <code class="literal"><filter-invocation-definition-source></code></h3></div></div></div><p>Deprecated synonym for filter-security-metadata-source</p><div class="section" title="<filter-invocation-definition-source> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-filter-invocation-definition-source-attributes"></a><code class="literal"><filter-invocation-definition-source></code> Attributes</h4></div></div></div><div class="section" title="id"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-filter-invocation-definition-source-id"></a><code class="literal">id</code></h5></div></div></div><p>A bean identifier, used for referring to the bean elsewhere in the context.</p></div><div class="section" title="lowercase-comparisons"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-filter-invocation-definition-source-lowercase-comparisons"></a><code class="literal">lowercase-comparisons</code></h5></div></div></div><p>Compare after forcing to lowercase</p></div><div class="section" title="path-type"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-filter-invocation-definition-source-path-type"></a><code class="literal">path-type</code></h5></div></div></div><p>Superseded by
+ <a class="link" href="#nsa-filter-invocation-definition-source-request-matcher" title="request-matcher">request-matcher</a></p></div><div class="section" title="request-matcher"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-filter-invocation-definition-source-request-matcher"></a><code class="literal">request-matcher</code></h5></div></div></div><p>Supersedes the 'path-type' attribute. Defines the strategy use for matching incoming requests.
+ Currently the options are 'ant' (for ant path patterns), 'regex' for regular expressions and 'ciRegex' for
+ case-insensitive regular expressions.</p></div><div class="section" title="use-expressions"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-filter-invocation-definition-source-use-expressions"></a><code class="literal">use-expressions</code></h5></div></div></div><p>Enables the use of expressions in the 'access' attributes in <intercept-url> elements
+ rather than the traditional list of configuration attributes. Defaults to 'false'. If
+ enabled, each attribute should contain a single boolean expression. If the expression evaluates to 'true', access will be
+ granted.</p></div></div><div class="section" title="Child Elements of <filter-invocation-definition-source>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-filter-invocation-definition-source-children"></a>Child Elements of <code class="literal"><filter-invocation-definition-source></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-intercept-url" title="B.1.10 <intercept-url>">intercept-url</a></li></ul></div></div></div><div class="section" title="B.1.26 <filter-security-metadata-source>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-filter-security-metadata-source"></a>B.1.26 <code class="literal"><filter-security-metadata-source></code></h3></div></div></div><p>Used to explicitly configure a FilterSecurityMetadataSource bean for use with a FilterSecurityInterceptor. Usually
+ only needed if you are configuring a FilterChainProxy explicitly, rather than using the
+ <http> element. The intercept-url elements used should only contain pattern, method and access attributes. Any
+ others will result in a configuration error.</p><div class="section" title="<filter-security-metadata-source> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-filter-security-metadata-source-attributes"></a><code class="literal"><filter-security-metadata-source></code> Attributes</h4></div></div></div><div class="section" title="id"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-filter-security-metadata-source-id"></a><code class="literal">id</code></h5></div></div></div><p>A bean identifier, used for referring to the bean elsewhere in the context.</p></div><div class="section" title="lowercase-comparisons"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-filter-security-metadata-source-lowercase-comparisons"></a><code class="literal">lowercase-comparisons</code></h5></div></div></div><p>Compare after forcing to lower case</p></div><div class="section" title="path-type"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-filter-security-metadata-source-path-type"></a><code class="literal">path-type</code></h5></div></div></div><p>Superseded by
+ <a class="link" href="#nsa-filter-security-metadata-source-request-matcher" title="request-matcher">request-matcher</a>
+ </p></div><div class="section" title="request-matcher"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-filter-security-metadata-source-request-matcher"></a><code class="literal">request-matcher</code></h5></div></div></div><p>Supersedes the 'path-type' attribute. Defines the strategy use for matching incoming requests.
+ Currently the options are 'ant' (for ant path patterns), 'regex' for regular expressions and 'ciRegex' for
+ case-insensitive regular expressions.</p></div><div class="section" title="use-expressions"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-filter-security-metadata-source-use-expressions"></a><code class="literal">use-expressions</code></h5></div></div></div><p>Enables the use of expressions in the 'access' attributes in
+ <intercept-url> elements rather than the traditional list of configuration attributes. Defaults to 'false'. If
+ enabled, each attribute should contain a single boolean expression. If the expression evaluates to 'true',
+ access will be granted.</p></div></div><div class="section" title="Child Elements of <filter-security-metadata-source>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-filter-security-metadata-source-children"></a>Child Elements of <code class="literal"><filter-security-metadata-source></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-intercept-url" title="B.1.10 <intercept-url>">intercept-url</a></li></ul></div></div></div></div><div class="section" title="B.2 Authentication Services"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="nsa-authentication"></a>B.2 Authentication Services</h2></div></div></div><p> Before Spring Security 3.0, an <code class="interfacename">AuthenticationManager</code>
was automatically registered internally. Now you must register one explicitly using the
<code class="literal"><authentication-manager></code> element. This creates an instance of
Spring Security's <code class="classname">ProviderManager</code> class, which needs to be
@@ -4219,97 +5107,172 @@ create table acl_entry(
<code class="interfacename">AuthenticationProvider</code> instances. These can either be
created using syntax elements provided by the namespace, or they can be standard bean
definitions, marked for addition to the list using the
- <code class="literal">authentication-provider</code> element. </p><div class="section" title="B.2.1 The <authentication-manager> Element"><div class="titlepage"><div><div><h3 class="title"><a name="d0e7960"></a>B.2.1 The <code class="literal"><authentication-manager></code> Element</h3></div></div></div><p> Every Spring Security application which uses the namespace must have include this
+ <code class="literal">authentication-provider</code> element. </p><div class="section" title="B.2.1 <authentication-manager>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-authentication-manager"></a>B.2.1 <code class="literal"><authentication-manager></code></h3></div></div></div><p> Every Spring Security application which uses the namespace must have include this
element somewhere. It is responsible for registering the
<code class="interfacename">AuthenticationManager</code> which provides authentication
- services to the application. It also allows you to define an alias name for the
- internal instance for use in your own configuration. Its use is described in the
- <a class="link" href="#ns-auth-manager" title="2.6 The Authentication Manager and the Namespace">namespace introduction</a>. All elements
+ services to the application. All elements
which create <code class="interfacename">AuthenticationProvider</code> instances should
- be children of this element.</p><p> The element also exposes an <code class="literal">erase-credentials</code> attribute which
- maps to the <code class="literal">eraseCredentialsAfterAuthentication</code> property of the
- <code class="classname">ProviderManager</code>. This is discussed in the <a class="link" href="#core-services-erasing-credentials" title="6.1.2 Erasing Credentials on Successful Authentication">Core Services</a> chapter.</p><div class="section" title="The <authentication-provider> Element"><div class="titlepage"><div><div><h4 class="title"><a name="d0e7991"></a>The <code class="literal"><authentication-provider></code> Element</h4></div></div></div><p> Unless used with a <code class="literal">ref</code> attribute, this element is
- shorthand for configuring a <a class="link" href="#core-services-dao-provider" title="6.1.1 DaoAuthenticationProvider"><code class="classname">DaoAuthenticationProvider</code></a>.
- <code class="classname">DaoAuthenticationProvider</code> loads user information from a
- <code class="interfacename">UserDetailsService</code> and compares the
- username/password combination with the values supplied at login. The
- <code class="interfacename">UserDetailsService</code> instance can be defined either
- by using an available namespace element (<code class="literal">jdbc-user-service</code> or
- by using the <code class="literal">user-service-ref</code> attribute to point to a bean
- defined elsewhere in the application context). You can find examples of these
- variations in the <a class="link" href="#ns-auth-providers" title="2.2.3 Using other Authentication Providers">namespace
- introduction</a>. </p><div class="section" title="The <password-encoder> Element"><div class="titlepage"><div><div><h5 class="title"><a name="d0e8024"></a>The <code class="literal"><password-encoder></code> Element</h5></div></div></div><p>Authentication providers can optionally be configured to use a password
- encoder as described in the <a class="link" href="#ns-password-encoder" title="Adding a Password Encoder">namespace introduction</a>. This will result in the bean being injected
- with the appropriate <code class="interfacename">PasswordEncoder</code>
- instance, potentially with an accompanying
- <code class="interfacename">SaltSource</code> bean to provide salt values for
- hashing. </p></div></div><div class="section" title="Using <authentication-provider> to refer to an AuthenticationProvider Bean"><div class="titlepage"><div><div><h4 class="title"><a name="d0e8041"></a>Using <code class="literal"><authentication-provider></code> to refer to an
- <code class="interfacename">AuthenticationProvider</code> Bean</h4></div></div></div><p> If you have written your own
- <code class="interfacename">AuthenticationProvider</code> implementation (or want to
- configure one of Spring Security's own implementations as a traditional bean for
- some reason, then you can use the following syntax to add it to the internal
- <code class="classname">ProviderManager</code>'s list: </p><pre class="programlisting">
- <security:authentication-manager>
- <security:authentication-provider ref="myAuthenticationProvider" />
- </security:authentication-manager>
- <bean id="myAuthenticationProvider" class="com.something.MyAuthenticationProvider"/>
- </pre></div></div></div><div class="section" title="B.3 Method Security"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="nsa-method-security"></a>B.3 Method Security</h2></div></div></div><div class="section" title="B.3.1 The <global-method-security> Element"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-gms"></a>B.3.1 The <code class="literal"><global-method-security></code> Element</h3></div></div></div><p> This element is the primary means of adding support for securing methods on
+ be children of this element.</p><div class="section" title="<authentication-manager> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-authentication-manager-attributes"></a><code class="literal"><authentication-manager></code> Attributes</h4></div></div></div><div class="section" title="alias"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-authentication-manager-alias"></a><code class="literal">alias</code></h5></div></div></div><p>This attribute allows you to define an alias name for the
+ internal instance for use in your own configuration. Its use is described in the
+ <a class="link" href="#ns-auth-manager" title="3.6 The Authentication Manager and the Namespace">namespace introduction</a>.</p></div><div class="section" title="erase-credentials"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-authentication-manager-erase-credentials"></a><code class="literal">erase-credentials</code></h5></div></div></div><p>If set to true, the AuthenticationManger will attempt to clear any credentials data in the
+ returned Authentication object, once the user has been authenticated. Literally it maps to
+ the <code class="literal">eraseCredentialsAfterAuthentication</code> property of the
+ <code class="classname">ProviderManager</code>. This is discussed in the <a class="link" href="#core-services-erasing-credentials" title="7.1.1 Erasing Credentials on Successful Authentication">Core Services</a> chapter.</p></div><div class="section" title="id"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-authentication-manager-id"></a><code class="literal">id</code></h5></div></div></div><p>This attribute allows you to define an id for the internal instance for use in your own
+ configuration. It is the same a the alias element, but provides a more consistent experience
+ with elements that use the id attribute.</p></div></div><div class="section" title="Child Elements of <authentication-manager>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-authentication-manager-children"></a>Child Elements of <code class="literal"><authentication-manager></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-authentication-provider" title="B.2.2 <authentication-provider>">authentication-provider</a></li><li class="listitem"><a class="link" href="#nsa-ldap-authentication-provider" title="B.4.2 <ldap-authentication-provider>">ldap-authentication-provider</a></li></ul></div></div></div><div class="section" title="B.2.2 <authentication-provider>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-authentication-provider"></a>B.2.2 <code class="literal"><authentication-provider></code></h3></div></div></div><p> Unless used with a <code class="literal">ref</code> attribute, this element is
+ shorthand for configuring a <a class="link" href="#core-services-dao-provider" title="7.1.2 DaoAuthenticationProvider"><code class="classname">DaoAuthenticationProvider</code></a>.
+ <code class="classname">DaoAuthenticationProvider</code> loads user information from a
+ <code class="interfacename">UserDetailsService</code> and compares the
+ username/password combination with the values supplied at login. The
+ <code class="interfacename">UserDetailsService</code> instance can be defined either
+ by using an available namespace element (<code class="literal">jdbc-user-service</code> or
+ by using the <code class="literal">user-service-ref</code> attribute to point to a bean
+ defined elsewhere in the application context). You can find examples of these
+ variations in the <a class="link" href="#ns-auth-providers" title="3.2.5 Using other Authentication Providers">namespace
+ introduction</a>. </p><div class="section" title="Parent Elements of <authentication-provider>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-authentication-provider-parents"></a>Parent Elements of <code class="literal"><authentication-provider></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-authentication-manager" title="B.2.1 <authentication-manager>">authentication-manager</a></li></ul></div></div><div class="section" title="<authentication-provider> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-authentication-provider-attributes"></a><code class="literal"><authentication-provider></code> Attributes</h4></div></div></div><div class="section" title="ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-authentication-provider-ref"></a><code class="literal">ref</code></h5></div></div></div><p>Defines a reference to a Spring bean that implements <code class="interfacename">AuthenticationProvider
+ </code>.</p><p> If you have written your own
+ <code class="interfacename">AuthenticationProvider</code> implementation (or want to
+ configure one of Spring Security's own implementations as a traditional bean for
+ some reason, then you can use the following syntax to add it to the internal
+ <code class="classname">ProviderManager</code>'s list: </p><pre class="programlisting">
+<span class="hl-tag"><security:authentication-manager></span>
+ <span class="hl-tag"><security:authentication-provider</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"myAuthenticationProvider"</span><span class="hl-tag"> /></span>
+<span class="hl-tag"></security:authentication-manager></span>
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"myAuthenticationProvider"</span> <span class="hl-attribute">class</span>=<span class="hl-value">"com.something.MyAuthenticationProvider"</span><span class="hl-tag">/></span>
+ </pre></div><div class="section" title="user-service-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-authentication-provider-user-service-ref"></a><code class="literal">user-service-ref</code></h5></div></div></div><p>A reference to a bean that implements UserDetailsService that may be created using the standard bean
+ element or the custom user-service element.</p></div></div><div class="section" title="Child Elements of <authentication-provider>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-authentication-provider-children"></a>Child Elements of <code class="literal"><authentication-provider></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-jdbc-user-service" title="B.2.3 <jdbc-user-service>">jdbc-user-service</a></li><li class="listitem"><a class="link" href="#nsa-ldap-user-service" title="B.4.4 <ldap-user-service>">ldap-user-service</a></li><li class="listitem"><a class="link" href="#nsa-password-encoder" title="B.2.4 <password-encoder>">password-encoder</a></li><li class="listitem"><a class="link" href="#nsa-user-service" title="B.2.6 <user-service>">user-service</a></li></ul></div></div></div><div class="section" title="B.2.3 <jdbc-user-service>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-jdbc-user-service"></a>B.2.3 <code class="literal"><jdbc-user-service></code></h3></div></div></div><p>Causes creation of a JDBC-based UserDetailsService.</p><div class="section" title="<jdbc-user-service> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-jdbc-user-service-attributes"></a><code class="literal"><jdbc-user-service></code> Attributes</h4></div></div></div><div class="section" title="authorities-by-username-query"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-jdbc-user-service-authorities-by-username-query"></a><code class="literal">authorities-by-username-query</code></h5></div></div></div><p>An SQL statement to query for a user's granted authorities given a username.</p><p>The default is
+ </p><pre class="programlisting">select username, authority from authorities where username = ?</pre></div><div class="section" title="cache-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-jdbc-user-service-cache-ref"></a><code class="literal">cache-ref</code></h5></div></div></div><p>Defines a reference to a cache for use with a UserDetailsService.</p></div><div class="section" title="data-source-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-jdbc-user-service-data-source-ref"></a><code class="literal">data-source-ref</code></h5></div></div></div><p>The bean ID of the DataSource which provides the required tables.</p></div><div class="section" title="group-authorities-by-username-query"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-jdbc-user-service-group-authorities-by-username-query"></a><code class="literal">group-authorities-by-username-query</code></h5></div></div></div><p>An SQL statement to query user's group authorities given a username.</p><p>The default is
+ </p><pre class="programlisting">select
+ g.id, g.group_name, ga.authority
+from
+ groups g, group_members gm, group_authorities ga
+where
+ gm.username = ? and g.id = ga.group_id and g.id = gm.group_id</pre></div><div class="section" title="id"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-jdbc-user-service-id"></a><code class="literal">id</code></h5></div></div></div><p>A bean identifier, used for referring to the bean elsewhere in the context.</p></div><div class="section" title="role-prefix"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-jdbc-user-service-role-prefix"></a><code class="literal">role-prefix</code></h5></div></div></div><p>A non-empty string prefix that will be added to role strings loaded from persistent
+ storage (default is "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty.</p></div><div class="section" title="users-by-username-query"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-jdbc-user-service-users-by-username-query"></a><code class="literal">users-by-username-query</code></h5></div></div></div><p>An SQL statement to query a username, password, and enabled status given a username.</p><p>The default is
+ </p><pre class="programlisting">select username, password, enabled from users where username = ?</pre></div></div></div><div class="section" title="B.2.4 <password-encoder>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-password-encoder"></a>B.2.4 <code class="literal"><password-encoder></code></h3></div></div></div><p>Authentication providers can optionally be configured to use a password
+ encoder as described in the <a class="link" href="#ns-password-encoder" title="Adding a Password Encoder">namespace introduction</a>. This will result in the bean being injected
+ with the appropriate <code class="interfacename">PasswordEncoder</code>
+ instance, potentially with an accompanying
+ <code class="interfacename">SaltSource</code> bean to provide salt values for
+ hashing. </p><div class="section" title="Parent Elements of <password-encoder>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-password-encoder-parents"></a>Parent Elements of <code class="literal"><password-encoder></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-authentication-provider" title="B.2.2 <authentication-provider>">authentication-provider</a></li><li class="listitem"><a class="link" href="#nsa-password-compare" title="B.4.3 <password-compare>">password-compare</a></li></ul></div></div><div class="section" title="<password-encoder> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-password-encoder-attributes"></a><code class="literal"><password-encoder></code> Attributes</h4></div></div></div><div class="section" title="base64"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-password-encoder-base64"></a><code class="literal">base64</code></h5></div></div></div><p>Whether a string should be base64 encoded</p></div><div class="section" title="hash"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-password-encoder-hash"></a><code class="literal">hash</code></h5></div></div></div><p>Defines the hashing algorithm used on user passwords. We recommend strongly against using
+ MD4, as it is a very weak hashing algorithm.</p></div><div class="section" title="ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-password-encoder-ref"></a><code class="literal">ref</code></h5></div></div></div><p>Defines a reference to a Spring bean that implements <code class="interfacename">PasswordEncoder
+ </code>.</p></div></div><div class="section" title="Child Elements of <password-encoder>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-password-encoder-children"></a>Child Elements of <code class="literal"><password-encoder></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-salt-source" title="B.2.5 <salt-source>">salt-source</a></li></ul></div></div></div><div class="section" title="B.2.5 <salt-source>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-salt-source"></a>B.2.5 <code class="literal"><salt-source></code></h3></div></div></div><p>Password salting strategy. A system-wide constant or a property from the UserDetails object
+ can be used.</p><div class="section" title="Parent Elements of <salt-source>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-salt-source-parents"></a>Parent Elements of <code class="literal"><salt-source></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-password-encoder" title="B.2.4 <password-encoder>">password-encoder</a></li></ul></div></div><div class="section" title="<salt-source> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-salt-source-attributes"></a><code class="literal"><salt-source></code> Attributes</h4></div></div></div><div class="section" title="ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-salt-source-ref"></a><code class="literal">ref</code></h5></div></div></div><p>Defines a reference to a Spring bean Id.</p></div><div class="section" title="system-wide"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-salt-source-system-wide"></a><code class="literal">system-wide</code></h5></div></div></div><p>A single value that will be used as the salt for a password encoder.</p></div><div class="section" title="user-property"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-salt-source-user-property"></a><code class="literal">user-property</code></h5></div></div></div><p>A property of the UserDetails object which will be used as salt by a password encoder.
+ Typically something like "username" might be used.</p></div></div></div><div class="section" title="B.2.6 <user-service>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-user-service"></a>B.2.6 <code class="literal"><user-service></code></h3></div></div></div><p>Creates an in-memory UserDetailsService from a properties file or a list of "user" child
+ elements. Usernames are converted to lower-case internally to allow for case-insensitive lookups, so
+ this should not be used if case-sensitivity is required.</p><div class="section" title="<user-service> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-user-service-attributes"></a><code class="literal"><user-service></code> Attributes</h4></div></div></div><div class="section" title="id"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-user-service-id"></a><code class="literal">id</code></h5></div></div></div><p>A bean identifier, used for referring to the bean elsewhere in the context.</p></div><div class="section" title="properties"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-user-service-properties"></a><code class="literal">properties</code></h5></div></div></div><p>The location of a Properties file where each line is in the format of
+ </p><pre class="programlisting">username=password,grantedAuthority[,grantedAuthority][,enabled|disabled]</pre></div></div><div class="section" title="Child Elements of <user-service>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-user-service-children"></a>Child Elements of <code class="literal"><user-service></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-user" title="B.2.7 <user>">user</a></li></ul></div></div></div><div class="section" title="B.2.7 <user>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-user"></a>B.2.7 <code class="literal"><user></code></h3></div></div></div><p>Represents a user in the application.</p><div class="section" title="Parent Elements of <user>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-user-parents"></a>Parent Elements of <code class="literal"><user></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-user-service" title="B.2.6 <user-service>">user-service</a></li></ul></div></div><div class="section" title="<user> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-user-attributes"></a><code class="literal"><user></code> Attributes</h4></div></div></div><div class="section" title="authorities"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-user-authorities"></a><code class="literal">authorities</code></h5></div></div></div><p>One of more authorities granted to the user. Separate authorities with a comma
+ (but no space). For example, "ROLE_USER,ROLE_ADMINISTRATOR"</p></div><div class="section" title="disabled"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-user-disabled"></a><code class="literal">disabled</code></h5></div></div></div><p>Can be set to "true" to mark an account as disabled and unusable.</p></div><div class="section" title="locked"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-user-locked"></a><code class="literal">locked</code></h5></div></div></div><p>Can be set to "true" to mark an account as locked and unusable.</p></div><div class="section" title="name"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-user-name"></a><code class="literal">name</code></h5></div></div></div><p>The username assigned to the user.</p></div><div class="section" title="password"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-user-password"></a><code class="literal">password</code></h5></div></div></div><p>The password assigned to the user. This may be hashed if the corresponding
+ authentication provider supports hashing (remember to set the "hash" attribute of the
+ "user-service" element). This attribute be omitted in the case where the data will
+ not be used for authentication, but only for accessing authorities. If omitted, the
+ namespace will generate a random value, preventing its accidental use for
+ authentication. Cannot be empty.</p></div></div></div></div><div class="section" title="B.3 Method Security"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="nsa-method-security"></a>B.3 Method Security</h2></div></div></div><div class="section" title="B.3.1 <global-method-security>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-global-method-security"></a>B.3.1 <code class="literal"><global-method-security></code></h3></div></div></div><p> This element is the primary means of adding support for securing methods on
Spring Security beans. Methods can be secured by the use of annotations (defined at
the interface or class level) or by defining a set of pointcuts as child elements,
- using AspectJ syntax. </p><p> Method security uses the same
- <code class="interfacename">AccessDecisionManager</code> configuration as web security,
- but this can be overridden as explained above <a class="xref" href="#nsa-access-decision-manager-ref" title="access-decision-manager-ref">the section called “<code class="literal">access-decision-manager-ref</code>”</a>, using the same attribute. </p><div class="section" title="The secured-annotations and jsr250-annotations Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="d0e8078"></a>The <code class="literal">secured-annotations</code> and
- <code class="literal">jsr250-annotations</code> Attributes</h4></div></div></div><p> Setting these to "true" will enable support for Spring Security's own
- <code class="literal">@Secured</code> annotations and JSR-250 annotations, respectively.
- They are both disabled by default. Use of JSR-250 annotations also adds a
- <code class="classname">Jsr250Voter</code> to the
- <code class="interfacename">AccessDecisionManager</code>, so you need to make sure
- you do this if you are using a custom implementation and want to use these
- annotations. </p></div><div class="section" title="The mode Attribute"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-gms-mode"></a>The <code class="literal">mode</code> Attribute</h4></div></div></div><p>This attribute can be set to <span class="quote">“<span class="quote">aspectj</span>”</span> to specify that AspectJ
- should be used instead of the default Spring AOP. Secured methods must be woven
- with the <code class="classname">AnnotationSecurityAspect</code> from the
- <code class="literal">spring-security-aspects</code> module. </p></div><div class="section" title="Securing Methods using <protect-pointcut>"><div class="titlepage"><div><div><h4 class="title"><a name="d0e8115"></a>Securing Methods using <code class="literal"><protect-pointcut></code></h4></div></div></div><p> Rather than defining security attributes on an individual method or class
- basis using the <code class="literal">@Secured</code> annotation, you can define
- cross-cutting security constraints across whole sets of methods and interfaces
- in your service layer using the <code class="literal"><protect-pointcut></code>
- element. This has two attributes: </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p><code class="literal">expression</code> - the pointcut expression</p></li><li class="listitem"><p><code class="literal">access</code> - the security attributes which apply</p></li></ul></div><p> You can find an example in the <a class="link" href="#ns-protect-pointcut" title="Adding Security Pointcuts using protect-pointcut">namespace introduction</a>. </p></div><div class="section" title="The <after-invocation-provider> Element"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-custom-after-invocation"></a>The <code class="literal"><after-invocation-provider></code> Element</h4></div></div></div><p> This element can be used to decorate an
- <code class="interfacename">AfterInvocationProvider</code> for use by the security
- interceptor maintained by the <code class="literal"><global-method-security></code>
- namespace. You can define zero or more of these within the
- <code class="literal">global-method-security</code> element, each with a
- <code class="literal">ref</code> attribute pointing to an
- <code class="interfacename">AfterInvocationProvider</code> bean instance within your
- application context. </p></div></div><div class="section" title="B.3.2 LDAP Namespace Options"><div class="titlepage"><div><div><h3 class="title"><a name="d0e8166"></a>B.3.2 LDAP Namespace Options</h3></div></div></div><p> LDAP is covered in some details in <a class="link" href="#ldap" title="18. LDAP Authentication">its own
- chapter</a>. We will expand on that here with some explanation of how the
- namespace options map to Spring beans. The LDAP implementation uses Spring LDAP
- extensively, so some familiarity with that project's API may be useful. </p><div class="section" title="Defining the LDAP Server using the <ldap-server> Element"><div class="titlepage"><div><div><h4 class="title"><a name="d0e8174"></a>Defining the LDAP Server using the <code class="literal"><ldap-server></code>
- Element</h4></div></div></div><p> This element sets up a Spring LDAP
- <code class="interfacename">ContextSource</code> for use by the other LDAP beans,
- defining the location of the LDAP server and other information (such as a
- username and password, if it doesn't allow anonymous access) for connecting to
- it. It can also be used to create an embedded server for testing. Details of the
- syntax for both options are covered in the <a class="link" href="#ldap-server" title="18.3 Configuring an LDAP Server">LDAP
- chapter</a>. The actual <code class="interfacename">ContextSource</code>
- implementation is <code class="classname">DefaultSpringSecurityContextSource</code>
- which extends Spring LDAP's <code class="classname">LdapContextSource</code> class. The
- <code class="literal">manager-dn</code> and <code class="literal">manager-password</code> attributes
- map to the latter's <code class="literal">userDn</code> and <code class="literal">password</code>
- properties respectively. </p><p> If you only have one server defined in your application context, the other
- LDAP namespace-defined beans will use it automatically. Otherwise, you can give
- the element an "id" attribute and refer to it from other namespace beans using
- the <code class="literal">server-ref</code> attribute. This is actually the bean <code class="literal">id</code> of the
- <code class="literal">ContextSource</code> instance, if you want to use it in other
- traditional Spring beans. </p></div><div class="section" title="The <ldap-provider> Element"><div class="titlepage"><div><div><h4 class="title"><a name="d0e8220"></a>The <code class="literal"><ldap-provider></code> Element</h4></div></div></div><p> This element is shorthand for the creation of an
- <code class="classname">LdapAuthenticationProvider</code> instance. By default this will
- be configured with a <code class="classname">BindAuthenticator</code> instance and a
- <code class="classname">DefaultAuthoritiesPopulator</code>. As with all namespace
- authentication providers, it must be included as a child of the
- <code class="literal">authentication-provider</code> element.</p><div class="section" title="The user-dn-pattern Attribute"><div class="titlepage"><div><div><h5 class="title"><a name="d0e8240"></a>The <code class="literal">user-dn-pattern</code> Attribute</h5></div></div></div><p> If your users are at a fixed location in the directory (i.e. you can work
+ using AspectJ syntax. </p><div class="section" title="<global-method-security> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-global-method-security-attributes"></a><code class="literal"><global-method-security></code> Attributes</h4></div></div></div><div class="section" title="access-decision-manager-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-global-method-security-access-decision-manager-ref"></a><code class="literal">access-decision-manager-ref</code></h5></div></div></div><p>Method security uses the same <code class="interfacename">AccessDecisionManager</code>
+ configuration as web security, but this can be overridden using this attribute. By default
+ an AffirmativeBased implementation is used for with a RoleVoter and an AuthenticatedVoter. </p></div><div class="section" title="authentication-manager-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-global-method-security-authentication-manager-ref"></a><code class="literal">authentication-manager-ref</code></h5></div></div></div><p>A reference to an <code class="interfacename">AuthenticationManager</code>
+ that should be used for method security.</p></div><div class="section" title="jsr250-annotations"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-global-method-security-jsr250-annotations"></a><code class="literal">jsr250-annotations</code></h5></div></div></div><p>Specifies whether JSR-250 style attributes are to be used (for example "RolesAllowed"). This
+ will require the javax.annotation.security classes on the classpath. Setting this to true also
+ adds a <code class="classname">Jsr250Voter</code> to the
+ <code class="interfacename">AccessDecisionManager</code>, so you need to make sure you do this if
+ you are using a custom implementation and want to use these annotations.</p></div><div class="section" title="<metadata-source-ref> Attribute"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-global-method-security-metadata-source-ref"></a><code class="literal"><metadata-source-ref></code> Attribute</h5></div></div></div><p> An external <code class="interfacename">MethodSecurityMetadataSource</code>
+ instance can be supplied which will take priority over other sources
+ (such as the default annotations).
+ </p></div><div class="section" title="The mode Attribute"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-global-method-security-mode"></a>The <code class="literal">mode</code> Attribute</h5></div></div></div><p>This attribute can be set to <span class="quote">“<span class="quote">aspectj</span>”</span> to specify that AspectJ
+ should be used instead of the default Spring AOP. Secured methods must be woven
+ with the <code class="classname">AnnotationSecurityAspect</code> from the
+ <code class="literal">spring-security-aspects</code> module. </p></div><div class="section" title="order"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-global-method-security-order"></a><code class="literal">order</code></h5></div></div></div><p>Allows the advice "order" to be set for the method security interceptor.</p></div><div class="section" title="pre-post-annotations"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-global-method-security-pre-post-annotations"></a><code class="literal">pre-post-annotations</code></h5></div></div></div><p>Specifies whether the use of Spring Security's pre and post invocation annotations (@PreFilter,
+ @PreAuthorize, @PostFilter, @PostAuthorize) should be enabled for this application context.
+ Defaults to "disabled".</p></div><div class="section" title="proxy-target-class"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-global-method-security-proxy-target-class"></a><code class="literal">proxy-target-class</code></h5></div></div></div><p>If true, class based proxying will be used instead of interface based proxying.</p></div><div class="section" title="run-as-manager-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-global-method-security-run-as-manager-ref"></a><code class="literal">run-as-manager-ref</code></h5></div></div></div><p>A reference to an optional <code class="interfacename">RunAsManager</code> implementation which
+ will be used by the configured <code class="classname">MethodSecurityInterceptor</code></p></div><div class="section" title="secured-annotations"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-global-method-security-secured-annotations"></a><code class="literal">secured-annotations</code></h5></div></div></div><p>Specifies whether the use of Spring Security's @Secured annotations should be enabled for this
+ application context. Defaults to "disabled".</p></div></div><div class="section" title="Child Elements of <global-method-security>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-global-method-security-children"></a>Child Elements of <code class="literal"><global-method-security></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-after-invocation-provider" title="B.3.2 <after-invocation-provider>">after-invocation-provider</a></li><li class="listitem"><a class="link" href="#nsa-expression-handler" title="B.1.6 <expression-handler>">expression-handler</a></li><li class="listitem"><a class="link" href="#nsa-pre-post-annotation-handling" title="B.3.3 <pre-post-annotation-handling>">pre-post-annotation-handling</a></li><li class="listitem"><a class="link" href="#nsa-protect-pointcut" title="B.3.7 Securing Methods using <protect-pointcut>">protect-pointcut</a></li></ul></div></div></div><div class="section" title="B.3.2 <after-invocation-provider>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-after-invocation-provider"></a>B.3.2 <code class="literal"><after-invocation-provider></code></h3></div></div></div><p> This element can be used to decorate an
+ <code class="interfacename">AfterInvocationProvider</code> for use by the security
+ interceptor maintained by the <code class="literal"><global-method-security></code>
+ namespace. You can define zero or more of these within the
+ <code class="literal">global-method-security</code> element, each with a
+ <code class="literal">ref</code> attribute pointing to an
+ <code class="interfacename">AfterInvocationProvider</code> bean instance within your
+ application context. </p><div class="section" title="Parent Elements of <after-invocation-provider>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-after-invocation-provider-parents"></a>Parent Elements of <code class="literal"><after-invocation-provider></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-global-method-security" title="B.3.1 <global-method-security>">global-method-security</a></li></ul></div></div><div class="section" title="<after-invocation-provider> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-after-invocation-provider-attributes"></a><code class="literal"><after-invocation-provider></code> Attributes</h4></div></div></div><div class="section" title="ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-after-invocation-provider-ref"></a><code class="literal">ref</code></h5></div></div></div><p>Defines a reference to a Spring bean that implements <code class="interfacename">
+ AfterInvocationProvider</code>.</p></div></div></div><div class="section" title="B.3.3 <pre-post-annotation-handling>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-pre-post-annotation-handling"></a>B.3.3 <code class="literal"><pre-post-annotation-handling></code></h3></div></div></div><p>Allows the default expression-based mechanism for handling Spring Security's pre and post invocation
+ annotations (@PreFilter, @PreAuthorize, @PostFilter, @PostAuthorize) to be replace entirely. Only
+ applies if these annotations are enabled.</p><div class="section" title="Parent Elements of <pre-post-annotation-handling>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-pre-post-annotation-handling-parents"></a>Parent Elements of <code class="literal"><pre-post-annotation-handling></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-global-method-security" title="B.3.1 <global-method-security>">global-method-security</a></li></ul></div></div><div class="section" title="Child Elements of <pre-post-annotation-handling>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-pre-post-annotation-handling-children"></a>Child Elements of <code class="literal"><pre-post-annotation-handling></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-invocation-attribute-factory" title="B.3.4 <invocation-attribute-factory>">invocation-attribute-factory</a></li><li class="listitem"><a class="link" href="#nsa-post-invocation-advice" title="B.3.5 <post-invocation-advice>">post-invocation-advice</a></li><li class="listitem"><a class="link" href="#nsa-pre-invocation-advice" title="B.3.6 <pre-invocation-advice>">pre-invocation-advice</a></li></ul></div></div></div><div class="section" title="B.3.4 <invocation-attribute-factory>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-invocation-attribute-factory"></a>B.3.4 <code class="literal"><invocation-attribute-factory></code></h3></div></div></div><p>Defines the PrePostInvocationAttributeFactory instance which is used to generate pre and post
+ invocation metadata from the annotated methods.</p><div class="section" title="Parent Elements of <invocation-attribute-factory>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-invocation-attribute-factory-parents"></a>Parent Elements of <code class="literal"><invocation-attribute-factory></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-pre-post-annotation-handling" title="B.3.3 <pre-post-annotation-handling>">pre-post-annotation-handling</a></li></ul></div></div><div class="section" title="<invocation-attribute-factory> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-invocation-attribute-factory-attributes"></a><code class="literal"><invocation-attribute-factory></code> Attributes</h4></div></div></div><div class="section" title="ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-invocation-attribute-factory-ref"></a><code class="literal">ref</code></h5></div></div></div><p>Defines a reference to a Spring bean Id.</p></div></div></div><div class="section" title="B.3.5 <post-invocation-advice>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-post-invocation-advice"></a>B.3.5 <code class="literal"><post-invocation-advice></code></h3></div></div></div><p>Customizes the <code class="classname">PostInvocationAdviceProvider</code> with the ref as the
+ <code class="classname">PostInvocationAuthorizationAdvice</code> for the <pre-post-annotation-handling>
+ element.</p><div class="section" title="Parent Elements of <post-invocation-advice>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-post-invocation-advice-parents"></a>Parent Elements of <code class="literal"><post-invocation-advice></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-pre-post-annotation-handling" title="B.3.3 <pre-post-annotation-handling>">pre-post-annotation-handling</a></li></ul></div></div><div class="section" title="<post-invocation-advice> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-post-invocation-advice-attributes"></a><code class="literal"><post-invocation-advice></code> Attributes</h4></div></div></div><div class="section" title="ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-post-invocation-advice-ref"></a><code class="literal">ref</code></h5></div></div></div><p>Defines a reference to a Spring bean Id.</p></div></div></div><div class="section" title="B.3.6 <pre-invocation-advice>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-pre-invocation-advice"></a>B.3.6 <code class="literal"><pre-invocation-advice></code></h3></div></div></div><p>Customizes the <code class="classname">PreInvocationAuthorizationAdviceVoter</code> with the ref as the
+ <code class="classname">PreInvocationAuthorizationAdviceVoter</code> for the
+ <pre-post-annotation-handling> element.</p><div class="section" title="Parent Elements of <pre-invocation-advice>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-pre-invocation-advice-parents"></a>Parent Elements of <code class="literal"><pre-invocation-advice></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-pre-post-annotation-handling" title="B.3.3 <pre-post-annotation-handling>">pre-post-annotation-handling</a></li></ul></div></div><div class="section" title="<pre-invocation-advice> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-pre-invocation-advice-attributes"></a><code class="literal"><pre-invocation-advice></code> Attributes</h4></div></div></div><div class="section" title="ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-pre-invocation-advice-ref"></a><code class="literal">ref</code></h5></div></div></div><p>Defines a reference to a Spring bean Id.</p></div></div></div><div class="section" title="B.3.7 Securing Methods using <protect-pointcut>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-protect-pointcut"></a>B.3.7 Securing Methods using <code class="literal"><protect-pointcut></code></h3></div></div></div><p> Rather than defining security attributes on an individual method or class
+ basis using the <code class="literal">@Secured</code> annotation, you can define
+ cross-cutting security constraints across whole sets of methods and interfaces
+ in your service layer using the <code class="literal"><protect-pointcut></code>
+ element. You can find an example in the <a class="link" href="#ns-protect-pointcut" title="Adding Security Pointcuts using protect-pointcut">namespace introduction</a>.</p><div class="section" title="Parent Elements of <protect-pointcut>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-protect-pointcut-parents"></a>Parent Elements of <code class="literal"><protect-pointcut></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-global-method-security" title="B.3.1 <global-method-security>">global-method-security</a></li></ul></div></div><div class="section" title="<protect-pointcut> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-protect-pointcut-attributes"></a><code class="literal"><protect-pointcut></code> Attributes</h4></div></div></div><div class="section" title="access"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-protect-pointcut-access"></a><code class="literal">access</code></h5></div></div></div><p>Access configuration attributes list that applies to all methods matching the pointcut,
+ e.g. "ROLE_A,ROLE_B"</p></div><div class="section" title="expression"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-protect-pointcut-expression"></a><code class="literal">expression</code></h5></div></div></div><p>An AspectJ expression, including the 'execution' keyword. For example, 'execution(int
+ com.foo.TargetObject.countLength(String))' (without the quotes).</p></div></div></div><div class="section" title="B.3.8 <intercept-methods>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-intercept-methods"></a>B.3.8 <code class="literal"><intercept-methods></code></h3></div></div></div><p>Can be used inside a bean definition to add a security interceptor to the bean and set up access
+ configuration attributes for the bean's methods</p><div class="section" title="<intercept-methods> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-intercept-methods-attributes"></a><code class="literal"><intercept-methods></code> Attributes</h4></div></div></div><div class="section" title="access-decision-manager-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-intercept-methods-access-decision-manager-ref"></a><code class="literal">access-decision-manager-ref</code></h5></div></div></div><p>Optional AccessDecisionManager bean ID to be used by the created method security interceptor.</p></div></div><div class="section" title="Child Elements of <intercept-methods>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-intercept-methods-children"></a>Child Elements of <code class="literal"><intercept-methods></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-protect" title="B.3.10 <protect>">protect</a></li></ul></div></div></div><div class="section" title="B.3.9 <method-security-metadata-source>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-method-security-metadata-source"></a>B.3.9 <code class="literal"><method-security-metadata-source></code></h3></div></div></div><p>Creates a MethodSecurityMetadataSource instance</p><div class="section" title="<method-security-metadata-source> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-method-security-metadata-source-attributes"></a><code class="literal"><method-security-metadata-source></code> Attributes</h4></div></div></div><div class="section" title="id"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-method-security-metadata-source-id"></a><code class="literal">id</code></h5></div></div></div><p>A bean identifier, used for referring to the bean elsewhere in the context.</p></div><div class="section" title="use-expressions"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-method-security-metadata-source-use-expressions"></a><code class="literal">use-expressions</code></h5></div></div></div><p>Enables the use of expressions in the 'access' attributes in
+ <intercept-url> elements rather than the traditional list of configuration attributes.
+ Defaults to 'false'. If enabled, each attribute should contain a single boolean expression.
+ If the expression evaluates to 'true', access will be granted.</p></div></div><div class="section" title="Child Elements of <method-security-metadata-source>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-method-security-metadata-source-children"></a>Child Elements of <code class="literal"><method-security-metadata-source></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-protect" title="B.3.10 <protect>">protect</a></li></ul></div></div></div><div class="section" title="B.3.10 <protect>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-protect"></a>B.3.10 <code class="literal"><protect></code></h3></div></div></div><p>Defines a protected method and the access control configuration attributes that apply to it. We
+ strongly advise you NOT to mix "protect" declarations with any services provided "global-method-security".</p><div class="section" title="Parent Elements of <protect>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-protect-parents"></a>Parent Elements of <code class="literal"><protect></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-intercept-methods" title="B.3.8 <intercept-methods>">intercept-methods</a></li><li class="listitem"><a class="link" href="#nsa-method-security-metadata-source" title="B.3.9 <method-security-metadata-source>">method-security-metadata-source</a></li></ul></div></div><div class="section" title="<protect> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-protect-attributes"></a><code class="literal"><protect></code> Attributes</h4></div></div></div><div class="section" title="access"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-protect-access"></a><code class="literal">access</code></h5></div></div></div><p>Access configuration attributes list that applies to the method, e.g. "ROLE_A,ROLE_B".</p></div><div class="section" title="method"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-protect-method"></a><code class="literal">method</code></h5></div></div></div><p>A method name</p></div></div></div></div><div class="section" title="B.4 LDAP Namespace Options"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="nsa-ldap"></a>B.4 LDAP Namespace Options</h2></div></div></div><p> LDAP is covered in some details in <a class="link" href="#ldap" title="19. LDAP Authentication">its own
+ chapter</a>. We will expand on that here with some explanation of how the
+ namespace options map to Spring beans. The LDAP implementation uses Spring LDAP
+ extensively, so some familiarity with that project's API may be useful. </p><div class="section" title="B.4.1 Defining the LDAP Server using the <ldap-server> Element"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-ldap-server"></a>B.4.1 Defining the LDAP Server using the <code class="literal"><ldap-server></code>
+ Element</h3></div></div></div><p> This element sets up a Spring LDAP
+ <code class="interfacename">ContextSource</code> for use by the other LDAP beans,
+ defining the location of the LDAP server and other information (such as a
+ username and password, if it doesn't allow anonymous access) for connecting to
+ it. It can also be used to create an embedded server for testing. Details of the
+ syntax for both options are covered in the <a class="link" href="#ldap-server" title="19.3 Configuring an LDAP Server">LDAP
+ chapter</a>. The actual <code class="interfacename">ContextSource</code>
+ implementation is <code class="classname">DefaultSpringSecurityContextSource</code>
+ which extends Spring LDAP's <code class="classname">LdapContextSource</code> class. The
+ <code class="literal">manager-dn</code> and <code class="literal">manager-password</code> attributes
+ map to the latter's <code class="literal">userDn</code> and <code class="literal">password</code>
+ properties respectively. </p><p> If you only have one server defined in your application context, the other
+ LDAP namespace-defined beans will use it automatically. Otherwise, you can give
+ the element an "id" attribute and refer to it from other namespace beans using
+ the <code class="literal">server-ref</code> attribute. This is actually the bean <code class="literal">id</code> of the
+ <code class="literal">ContextSource</code> instance, if you want to use it in other
+ traditional Spring beans. </p><div class="section" title="<ldap-server> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-ldap-server-attributes"></a><code class="literal"><ldap-server></code> Attributes</h4></div></div></div><div class="section" title="id"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-server-id"></a><code class="literal">id</code></h5></div></div></div><p>A bean identifier, used for referring to the bean elsewhere in the context.</p></div><div class="section" title="ldif"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-server-ldif"></a><code class="literal">ldif</code></h5></div></div></div><p>Explicitly specifies an ldif file resource to load into an embedded LDAP server. The ldiff
+ is should be a Spring resource pattern (i.e. classpath:init.ldiff). The default is
+ classpath*:*.ldiff</p></div><div class="section" title="manager-dn"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-server-manager-dn"></a><code class="literal">manager-dn</code></h5></div></div></div><p>Username (DN) of the "manager" user identity which will be used to authenticate to a
+ (non-embedded) LDAP server. If omitted, anonymous access will be used.</p></div><div class="section" title="manager-password"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-server-manager-password"></a><code class="literal">manager-password</code></h5></div></div></div><p>The password for the manager DN. This is required if the manager-dn is specified.</p></div><div class="section" title="port"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-server-port"></a><code class="literal">port</code></h5></div></div></div><p>Specifies an IP port number. Used to configure an embedded LDAP server, for example. The
+ default value is 33389.</p></div><div class="section" title="root"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-server-root"></a><code class="literal">root</code></h5></div></div></div><p>Optional root suffix for the embedded LDAP server. Default is "dc=springframework,dc=org"
+ </p></div><div class="section" title="url"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-server-url"></a><code class="literal">url</code></h5></div></div></div><p>Specifies the ldap server URL when not using the embedded LDAP server.</p></div></div></div><div class="section" title="B.4.2 <ldap-authentication-provider>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-ldap-authentication-provider"></a>B.4.2 <code class="literal"><ldap-authentication-provider></code></h3></div></div></div><p> This element is shorthand for the creation of an
+ <code class="classname">LdapAuthenticationProvider</code> instance. By default this will
+ be configured with a <code class="classname">BindAuthenticator</code> instance and a
+ <code class="classname">DefaultAuthoritiesPopulator</code>. As with all namespace
+ authentication providers, it must be included as a child of the
+ <code class="literal">authentication-provider</code> element.</p><div class="section" title="Parent Elements of <ldap-authentication-provider>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-ldap-authentication-provider-parents"></a>Parent Elements of <code class="literal"><ldap-authentication-provider></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-authentication-manager" title="B.2.1 <authentication-manager>">authentication-manager</a></li></ul></div></div><div class="section" title="<ldap-authentication-provider> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-ldap-authentication-provider-attributes"></a><code class="literal"><ldap-authentication-provider></code> Attributes</h4></div></div></div><div class="section" title="group-role-attribute"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-authentication-provider-group-role-attribute"></a><code class="literal">group-role-attribute</code></h5></div></div></div><p>The LDAP attribute name which contains the role name which will be used within Spring
+ Security. Maps to the <code class="classname">DefaultLdapAuthoritiesPopulator</code>'s
+ <code class="literal">groupRoleAttribute</code> property. Defaults to "cn".</p></div><div class="section" title="group-search-base"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-authentication-provider-group-search-base"></a><code class="literal">group-search-base</code></h5></div></div></div><p>Search base for group membership searches. Maps to the
+ <code class="classname">DefaultLdapAuthoritiesPopulator</code>'s <code class="literal">groupSearchBase</code>
+ constructor argument. Defaults to "" (searching from the root).</p></div><div class="section" title="group-search-filter"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-authentication-provider-group-search-filter"></a><code class="literal">group-search-filter</code></h5></div></div></div><p>Group search filter. Maps to the <code class="classname">DefaultLdapAuthoritiesPopulator</code>'s
+ <code class="literal">groupSearchFilter</code> property. Defaults to (uniqueMember={0}).
+ The substituted parameter is the DN of the user.</p></div><div class="section" title="role-prefix"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-authentication-provider-role-prefix"></a><code class="literal">role-prefix</code></h5></div></div></div><p>A non-empty string prefix that will be added to role strings loaded from persistent.
+ Maps to the <code class="classname">DefaultLdapAuthoritiesPopulator</code>'s
+ <code class="literal">rolePrefix</code> property. Defaults to "ROLE_". Use the value "none" for
+ no prefix in cases where the default is non-empty.</p></div><div class="section" title="server-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-authentication-provider-server-ref"></a><code class="literal">server-ref</code></h5></div></div></div><p>The optional server to use. If omitted, and a default LDAP server is registered (using
+ <ldap-server> with no Id), that server will be used.</p></div><div class="section" title="user-context-mapper-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-authentication-provider-user-context-mapper-ref"></a><code class="literal">user-context-mapper-ref</code></h5></div></div></div><p>Allows explicit customization of the loaded user object by specifying a
+ UserDetailsContextMapper bean which will be called with the context information
+ from the user's directory entry</p></div><div class="section" title="user-details-class"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-authentication-provider-user-details-class"></a><code class="literal">user-details-class</code></h5></div></div></div><p>Allows the objectClass of the user entry to be specified. If set, the framework will
+ attempt to load standard attributes for the defined class into the returned UserDetails
+ object</p></div><div class="section" title="user-dn-pattern"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-authentication-provider-user-dn-pattern"></a><code class="literal">user-dn-pattern</code></h5></div></div></div><p>If your users are at a fixed location in the directory (i.e. you can work
out the DN directly from the username without doing a directory search), you
can use this attribute to map directly to the DN. It maps directly to the
<code class="literal">userDnPatterns</code> property of
- <code class="classname">AbstractLdapAuthenticator</code>. </p></div><div class="section" title="The user-search-base and user-search-filter Attributes"><div class="titlepage"><div><div><h5 class="title"><a name="d0e8254"></a>The <code class="literal">user-search-base</code> and
- <code class="literal">user-search-filter</code> Attributes</h5></div></div></div><p> If you need to perform a search to locate the user in the directory, then
+ <code class="classname">AbstractLdapAuthenticator</code>. The value is a specific pattern
+ used to build the user's DN, for example "uid={0},ou=people". The key
+ "{0}" must be present and will be substituted with the username.</p></div><div class="section" title="user-search-base"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-authentication-provider-user-search-base"></a><code class="literal">user-search-base</code></h5></div></div></div><p>Search base for user searches. Defaults to "". Only used with a 'user-search-filter'.</p><p>If you need to perform a search to locate the user in the directory, then
+ you can set these attributes to control the search. The
+ <code class="classname">BindAuthenticator</code> will be configured with a
+ <code class="classname">FilterBasedLdapUserSearch</code> and the attribute values
+ map directly to the first two arguments of that bean's constructor. If these
+ attributes aren't set and no <code class="literal">user-dn-pattern</code> has been
+ supplied as an alternative, then the default search values of
+ <code class="literal">user-search-filter="(uid={0})"</code> and
+ <code class="literal">user-search-base=""</code> will be used. </p></div><div class="section" title="user-search-filter"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-authentication-provider-user-search-filter"></a><code class="literal">user-search-filter</code></h5></div></div></div><p>The LDAP filter used to search for users (optional). For example "(uid={0})". The
+ substituted parameter is the user's login name.</p><p>If you need to perform a search to locate the user in the directory, then
you can set these attributes to control the search. The
<code class="classname">BindAuthenticator</code> will be configured with a
<code class="classname">FilterBasedLdapUserSearch</code> and the attribute values
@@ -4317,37 +5280,76 @@ create table acl_entry(
attributes aren't set and no <code class="literal">user-dn-pattern</code> has been
supplied as an alternative, then the default search values of
<code class="literal">user-search-filter="(uid={0})"</code> and
- <code class="literal">user-search-base=""</code> will be used. </p></div><div class="section" title="group-search-filter, group-search-base, group-role-attribute and role-prefix Attributes"><div class="titlepage"><div><div><h5 class="title"><a name="d0e8280"></a><code class="literal">group-search-filter</code>,
- <code class="literal">group-search-base</code>,
- <code class="literal">group-role-attribute</code> and <code class="literal">role-prefix</code>
- Attributes</h5></div></div></div><p> The value of <code class="literal">group-search-base</code> is mapped to the
- <code class="literal">groupSearchBase</code> constructor argument of
- <code class="classname">DefaultAuthoritiesPopulator</code> and defaults to
- "ou=groups". The default filter value is "(uniqueMember={0})", which assumes
- that the entry is of type "groupOfUniqueNames".
- <code class="literal">group-role-attribute</code> maps to the
- <code class="literal">groupRoleAttribute</code> attribute and defaults to "cn".
- Similarly <code class="literal">role-prefix</code> maps to
- <code class="literal">rolePrefix</code> and defaults to "ROLE_". </p></div><div class="section" title="The <password-compare> Element"><div class="titlepage"><div><div><h5 class="title"><a name="d0e8317"></a>The <code class="literal"><password-compare></code> Element</h5></div></div></div><p> This is used as child element to <code class="literal"><ldap-provider></code>
- and switches the authentication strategy from
- <code class="classname">BindAuthenticator</code> to
- <code class="classname">PasswordComparisonAuthenticator</code>. This can optionally
- be supplied with a <code class="literal">hash</code> attribute or with a child
- <code class="literal"><password-encoder></code> element to hash the password
- before submitting it to the directory for comparison. </p></div></div><div class="section" title="The <ldap-user-service> Element"><div class="titlepage"><div><div><h4 class="title"><a name="d0e8340"></a>The <code class="literal"><ldap-user-service></code> Element</h4></div></div></div><p> This element configures an LDAP
- <code class="interfacename">UserDetailsService</code>. The class used is
- <code class="classname">LdapUserDetailsService</code> which is a combination of a
- <code class="classname">FilterBasedLdapUserSearch</code> and a
- <code class="classname">DefaultAuthoritiesPopulator</code>. The attributes it supports
- have the same usage as in <code class="literal"><ldap-provider></code>. </p></div></div></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e6997" href="#d0e6997" class="para">16</a>] </sup>See the <a class="link" href="#ns-web-xml" title="2.2.1 web.xml Configuration"> introductory chapter</a> for how to set
- up the mapping from your <code class="literal">web.xml</code></p></div><div class="footnote"><p><sup>[<a name="ftn.d0e7406" href="#d0e7406" class="para">17</a>] </sup>This feature is really just provided for convenience and is not intended for
+ <code class="literal">user-search-base=""</code> will be used. </p></div></div><div class="section" title="Child Elements of <ldap-authentication-provider>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-ldap-authentication-provider-children"></a>Child Elements of <code class="literal"><ldap-authentication-provider></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-password-compare" title="B.4.3 <password-compare>">password-compare</a></li></ul></div></div></div><div class="section" title="B.4.3 <password-compare>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-password-compare"></a>B.4.3 <code class="literal"><password-compare></code></h3></div></div></div><p> This is used as child element to <code class="literal"><ldap-provider></code>
+ and switches the authentication strategy from
+ <code class="classname">BindAuthenticator</code> to
+ <code class="classname">PasswordComparisonAuthenticator</code>.</p><div class="section" title="Parent Elements of <password-compare>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-password-compare-parents"></a>Parent Elements of <code class="literal"><password-compare></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-ldap-authentication-provider" title="B.4.2 <ldap-authentication-provider>">ldap-authentication-provider</a></li></ul></div></div><div class="section" title="<password-compare> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-password-compare-attributes"></a><code class="literal"><password-compare></code> Attributes</h4></div></div></div><div class="section" title="hash"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-password-compare-hash"></a><code class="literal">hash</code></h5></div></div></div><p>Defines the hashing algorithm used on user passwords. We recommend strongly against
+ using MD4, as it is a very weak hashing algorithm.</p></div><div class="section" title="password-attribute"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-password-compare-password-attribute"></a><code class="literal">password-attribute</code></h5></div></div></div><p>The attribute in the directory which contains the user password. Defaults to "userPassword".
+ </p></div></div><div class="section" title="Child Elements of <password-compare>"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-password-compare-children"></a>Child Elements of <code class="literal"><password-compare></code></h4></div></div></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><a class="link" href="#nsa-password-encoder" title="B.2.4 <password-encoder>">password-encoder</a></li></ul></div></div></div><div class="section" title="B.4.4 <ldap-user-service>"><div class="titlepage"><div><div><h3 class="title"><a name="nsa-ldap-user-service"></a>B.4.4 <code class="literal"><ldap-user-service></code></h3></div></div></div><p> This element configures an LDAP
+ <code class="interfacename">UserDetailsService</code>. The class used is
+ <code class="classname">LdapUserDetailsService</code> which is a combination of a
+ <code class="classname">FilterBasedLdapUserSearch</code> and a
+ <code class="classname">DefaultLdapAuthoritiesPopulator</code>. The attributes it supports
+ have the same usage as in <code class="literal"><ldap-provider></code>. </p><div class="section" title="<ldap-user-service> Attributes"><div class="titlepage"><div><div><h4 class="title"><a name="nsa-ldap-user-service-attributes"></a><code class="literal"><ldap-user-service></code> Attributes</h4></div></div></div><div class="section" title="cache-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-user-service-cache-ref"></a><code class="literal">cache-ref</code></h5></div></div></div><p>Defines a reference to a cache for use with a UserDetailsService.</p></div><div class="section" title="group-role-attribute"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-user-service-group-role-attribute"></a><code class="literal">group-role-attribute</code></h5></div></div></div><p>The LDAP attribute name which contains the role name which will be used within Spring
+ Security. Defaults to "cn".</p></div><div class="section" title="group-search-base"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-user-service-group-search-base"></a><code class="literal">group-search-base</code></h5></div></div></div><p>Search base for group membership searches. Defaults to "" (searching from the root).</p></div><div class="section" title="group-search-filter"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-user-service-group-search-filter"></a><code class="literal">group-search-filter</code></h5></div></div></div><p>Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of
+ the user.</p></div><div class="section" title="id"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-user-service-id"></a><code class="literal">id</code></h5></div></div></div><p>A bean identifier, used for referring to the bean elsewhere in the context.</p></div><div class="section" title="role-prefix"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-user-service-role-prefix"></a><code class="literal">role-prefix</code></h5></div></div></div><p>A non-empty string prefix that will be added to role strings loaded from persistent
+ storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is
+ non-empty.</p></div><div class="section" title="server-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-user-service-server-ref"></a><code class="literal">server-ref</code></h5></div></div></div><p>The optional server to use. If omitted, and a default LDAP server is registered (using
+ <ldap-server> with no Id), that server will be used.</p></div><div class="section" title="user-context-mapper-ref"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-user-service-user-context-mapper-ref"></a><code class="literal">user-context-mapper-ref</code></h5></div></div></div><p>Allows explicit customization of the loaded user object by specifying a
+ UserDetailsContextMapper bean which will be called with the context information from the
+ user's directory entry</p></div><div class="section" title="user-details-class"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-user-service-user-details-class"></a><code class="literal">user-details-class</code></h5></div></div></div><p>Allows the objectClass of the user entry to be specified. If set, the framework will
+ attempt to load standard attributes for the defined class into the returned UserDetails object
+ </p></div><div class="section" title="user-search-base"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-user-service-user-search-base"></a><code class="literal">user-search-base</code></h5></div></div></div><p>Search base for user searches. Defaults to "". Only used with a 'user-search-filter'.</p></div><div class="section" title="user-search-filter"><div class="titlepage"><div><div><h5 class="title"><a name="nsa-ldap-user-service-user-search-filter"></a><code class="literal">user-search-filter</code></h5></div></div></div><p>The LDAP filter used to search for users (optional). For example "(uid={0})". The
+ substituted parameter is the user's login name.</p></div></div></div></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e8540" href="#d0e8540" class="para">24</a>] </sup>See the <a class="link" href="#ns-web-xml" title="3.2.1 web.xml Configuration">introductory chapter</a> for how to set
+ up the mapping from your <code class="literal">web.xml</code></p></div><div class="footnote"><p><sup>[<a name="ftn.d0e9129" href="#d0e9129" class="para">25</a>] </sup>This feature is really just provided for convenience and is not intended for
production (where a view technology will have been chosen and can be used to
render a customized login page). The class
<code class="classname">DefaultLoginPageGeneratingFilter</code> is responsible for
rendering the login page and will provide login forms for both normal form login
- and/or OpenID if required.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e7593" href="#d0e7593" class="para">18</a>] </sup>This doesn't affect the use of
- <code class="classname">PersistentTokenBasedRememberMeServices</code>, where the
- tokens are stored on the server side.</p></div></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
+ and/or OpenID if required.</p></div><div class="footnote"><p><sup>[<a name="ftn.d0e9921" href="#d0e9921" class="para">26</a>] </sup>This doesn't affect the use of
+ <code class="classname">PersistentTokenBasedRememberMeServices</code>, where the
+ tokens are stored on the server side.</p></div></div></div><div class="appendix" title="Appendix C. Spring Security Dependencies"><div class="titlepage"><div><div><h1 class="title"><a name="appendix-dependencies"></a>Spring Security Dependencies</h1></div></div></div><p>
+ This appendix provides a reference of the modules in Spring Security and the additional
+ dependencies that they require in order to function in a running application. We don't include
+ dependenices that are only used when building or testing Spring Security itself. Nor do we include
+ transitive dependencies which are required by external dependencies.
+ </p><p>The version of Spring required is listed on the project website, so the specific versions
+ are omitted for Spring dependencies below. Note that some of the dependencies listed as
+ <span class="quote">“<span class="quote">optional</span>”</span> below may still be required for other non-security functionality in
+ a Spring application. Also dependencies listed as <span class="quote">“<span class="quote">optional</span>”</span> may not actually be marked
+ as such in the project's Maven pom files if they are used in most applications. They are
+ <span class="quote">“<span class="quote">optional</span>”</span> only in the sense that you don't need them unless you are using the
+ specified functionality.</p><p>Where a module depends on another Spring Security module, the non-optional dependencies of the
+ module it depends on are also assumed to be required and are not listed separately.
+ </p><div class="section" title="C.1 spring-security-core"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e11729"></a>C.1 <code class="literal">spring-security-core</code></h2></div></div></div><p>The core module must be included in any project using Spring Security.
+ </p><div class="table"><a name="deps-core"></a><p class="title"><b>Table C.1. Core Depenendencies</b></p><div class="table-contents"><table summary="Core Depenendencies" style="border-collapse: collapse;border-top: 0.5pt solid ; border-bottom: 0.5pt solid ; border-left: 0.5pt solid ; border-right: 0.5pt solid ; "><colgroup><col align="left"><col align="left"><col align="left"></colgroup><thead><tr><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="center">Dependency</th><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="center">Version</th><th style="border-bottom: 0.5pt solid ; " align="center">Description</th></tr></thead><tbody><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">aopalliance</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">1.0</td><td style="border-bottom: 0.5pt solid ; " align="left"><p>Required for method security implementation.</p></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">ehcache</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">1.6.2</td><td style="border-bottom: 0.5pt solid ; " align="left"><p>Required if the ehcache-based user cache implementation is used (optional).</p></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">spring-aop</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> </td><td style="border-bottom: 0.5pt solid ; " align="left"><p>Method security is based on Spring AOP</p></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">spring-beans</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> </td><td style="border-bottom: 0.5pt solid ; " align="left"><p>Required for Spring configuration</p></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">spring-expression</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> </td><td style="border-bottom: 0.5pt solid ; " align="left"><p>Required for expression-based method security (optional)</p></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">spring-jdbc</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> </td><td style="border-bottom: 0.5pt solid ; " align="left"><p>Required if using a database to store user data (optional).</p></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">spring-tx</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> </td><td style="border-bottom: 0.5pt solid ; " align="left"><p>Required if using a database to store user data (optional).</p></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">aspectjrt</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">1.6.10</td><td style="border-bottom: 0.5pt solid ; " align="left"><p>Required if using AspectJ support (optional).</p></td></tr><tr><td style="border-right: 0.5pt solid ; " align="left">jsr250-api</td><td style="border-right: 0.5pt solid ; " align="left">1.0</td><td style="" align="left"><p>Required if you are using JSR-250 method-security annotations (optional).</p></td></tr></tbody></table></div></div><p><br class="table-break">
+ </p></div><div class="section" title="C.2 spring-security-remoting"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e11819"></a>C.2 <code class="literal">spring-security-remoting</code></h2></div></div></div><p>This module is typically required in web applications which use the Servlet API.
+ </p><div class="table"><a name="deps-remoting"></a><p class="title"><b>Table C.2. Remoting Dependencies</b></p><div class="table-contents"><table summary="Remoting Dependencies" style="border-collapse: collapse;border-top: 0.5pt solid ; border-bottom: 0.5pt solid ; border-left: 0.5pt solid ; border-right: 0.5pt solid ; "><colgroup><col align="left"><col align="left"><col align="left"></colgroup><thead><tr><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="center">Dependency</th><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="center">Version</th><th style="border-bottom: 0.5pt solid ; " align="center">Description</th></tr></thead><tbody><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">spring-security-core</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> </td><td style="border-bottom: 0.5pt solid ; " align="left"> </td></tr><tr><td style="border-right: 0.5pt solid ; " align="left">spring-web</td><td style="border-right: 0.5pt solid ; " align="left"> </td><td style="" align="left"><p>Required for clients which use HTTP remoting support.</p></td></tr></tbody></table></div></div><p><br class="table-break">
+ </p></div><div class="section" title="C.3 spring-security-web"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e11854"></a>C.3 <code class="literal">spring-security-web</code></h2></div></div></div><p>This module is typically required in web applications which use the Servlet API.
+ </p><div class="table"><a name="deps-web"></a><p class="title"><b>Table C.3. Web Dependencies</b></p><div class="table-contents"><table summary="Web Dependencies" style="border-collapse: collapse;border-top: 0.5pt solid ; border-bottom: 0.5pt solid ; border-left: 0.5pt solid ; border-right: 0.5pt solid ; "><colgroup><col align="left"><col align="left"><col align="left"></colgroup><thead><tr><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="center">Dependency</th><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="center">Version</th><th style="border-bottom: 0.5pt solid ; " align="center">Description</th></tr></thead><tbody><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">spring-security-core</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> </td><td style="border-bottom: 0.5pt solid ; " align="left"> </td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">spring-web</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> </td><td style="border-bottom: 0.5pt solid ; " align="left"><p>Spring web support classes are used extensively.</p></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">spring-jdbc</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> </td><td style="border-bottom: 0.5pt solid ; " align="left"><p>Required for JDBC-based persistent remember-me token repository (optional).</p></td></tr><tr><td style="border-right: 0.5pt solid ; " align="left">spring-tx</td><td style="border-right: 0.5pt solid ; " align="left"> </td><td style="" align="left"><p>Required by remember-me persistent token repository implementations (optional).</p></td></tr></tbody></table></div></div><p><br class="table-break">
+ </p></div><div class="section" title="C.4 spring-security-ldap"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e11903"></a>C.4 <code class="literal">spring-security-ldap</code></h2></div></div></div><p>This module is only required if you are using LDAP authentication.
+ </p><div class="table"><a name="deps-ldap"></a><p class="title"><b>Table C.4. LDAP Dependencies</b></p><div class="table-contents"><table summary="LDAP Dependencies" style="border-collapse: collapse;border-top: 0.5pt solid ; border-bottom: 0.5pt solid ; border-left: 0.5pt solid ; border-right: 0.5pt solid ; "><colgroup><col align="left"><col align="left"><col align="left"></colgroup><thead><tr><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="center">Dependency</th><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="center">Version</th><th style="border-bottom: 0.5pt solid ; " align="center">Description</th></tr></thead><tbody><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">spring-security-core</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> </td><td style="border-bottom: 0.5pt solid ; " align="left"> </td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">spring-ldap-core</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">1.3.0</td><td style="border-bottom: 0.5pt solid ; " align="left"><p>LDAP support is based on Spring LDAP.</p></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">spring-tx</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> </td><td style="border-bottom: 0.5pt solid ; " align="left"><p>Data exception classes are required.</p></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">apache-ds <sup>[<a name="d0e11948" href="#ftn.d0e11948" class="footnote">1</a>]</sup></td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">1.5.5</td><td style="border-bottom: 0.5pt solid ; " align="left"><p>Required if you are using an embedded LDAP server (optional).</p></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">shared-ldap</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">0.9.15</td><td style="border-bottom: 0.5pt solid ; " align="left"><p>Required if you are using an embedded LDAP server (optional).</p></td></tr><tr><td style="border-right: 0.5pt solid ; " align="left">ldapsdk</td><td style="border-right: 0.5pt solid ; " align="left">4.1</td><td style="" align="left">
+ <p>Mozilla LdapSDK. Used for decoding LDAP password policy controls if you are
+ using password-policy functionality with OpenLDAP, for example.
+ </p>
+ </td></tr></tbody><tbody class="footnotes"><tr><td colspan="3"><div class="footnote"><p><sup>[<a name="ftn.d0e11948" href="#d0e11948" class="para">1</a>] </sup>The modules <code class="literal">apacheds-core</code>,
+ <code class="literal">apacheds-core-entry</code>, <code class="literal">apacheds-protocol-shared</code>,
+ <code class="literal">apacheds-protocol-ldap</code> and <code class="literal">apacheds-server-jndi</code> are required.
+ </p></div></td></tr></tbody></table></div></div><p><br class="table-break">
+ </p></div><div class="section" title="C.5 spring-security-config"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e11990"></a>C.5 <code class="literal">spring-security-config</code></h2></div></div></div><p>This module is required if you are using Spring Security namespace configuration.
+ </p><div class="table"><a name="deps-config"></a><p class="title"><b>Table C.5. Config Dependencies</b></p><div class="table-contents"><table summary="Config Dependencies" style="border-collapse: collapse;border-top: 0.5pt solid ; border-bottom: 0.5pt solid ; border-left: 0.5pt solid ; border-right: 0.5pt solid ; "><colgroup><col align="left"><col align="left"><col align="left"></colgroup><thead><tr><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="center">Dependency</th><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="center">Version</th><th style="border-bottom: 0.5pt solid ; " align="center">Description</th></tr></thead><tbody><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">spring-security-core</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> </td><td style="border-bottom: 0.5pt solid ; " align="left"> </td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">spring-security-web</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> </td><td style="border-bottom: 0.5pt solid ; " align="left">Required if you are using any web-related namespace configuration (optional).</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">spring-security-ldap</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> </td><td style="border-bottom: 0.5pt solid ; " align="left">Required if you are using the LDAP namespace options (optional).</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">spring-security-openid</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> </td><td style="border-bottom: 0.5pt solid ; " align="left">Required if you are using OpenID authentication (optional).</td></tr><tr><td style="border-right: 0.5pt solid ; " align="left">aspectjweaver</td><td style="border-right: 0.5pt solid ; " align="left">1.6.10</td><td style="" align="left"><p>Required if using the protect-pointcut namespace syntax (optional).</p></td></tr></tbody></table></div></div><p><br class="table-break">
+ </p></div><div class="section" title="C.6 spring-security-acl"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e12044"></a>C.6 <code class="literal">spring-security-acl</code></h2></div></div></div><p>The ACL module.
+ </p><div class="table"><a name="deps-acl"></a><p class="title"><b>Table C.6. ACL Dependencies</b></p><div class="table-contents"><table summary="ACL Dependencies" style="border-collapse: collapse;border-top: 0.5pt solid ; border-bottom: 0.5pt solid ; border-left: 0.5pt solid ; border-right: 0.5pt solid ; "><colgroup><col align="left"><col align="left"><col align="left"></colgroup><thead><tr><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="center">Dependency</th><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="center">Version</th><th style="border-bottom: 0.5pt solid ; " align="center">Description</th></tr></thead><tbody><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">spring-security-core</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> </td><td style="border-bottom: 0.5pt solid ; " align="left"> </td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">ehcache</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">1.6.2</td><td style="border-bottom: 0.5pt solid ; " align="left"><p>Required if the ehcache-based ACL cache implementation is used (optional if you are using your own implementation).</p></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">spring-jdbc</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> </td><td style="border-bottom: 0.5pt solid ; " align="left"><p>Required if you are using the default JDBC-based AclService (optional if you implement your own).</p></td></tr><tr><td style="border-right: 0.5pt solid ; " align="left">spring-tx</td><td style="border-right: 0.5pt solid ; " align="left"> </td><td style="" align="left"><p>Required if you are using the default JDBC-based AclService (optional if you implement your own).</p></td></tr></tbody></table></div></div><p><br class="table-break">
+ </p></div><div class="section" title="C.7 spring-security-cas"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e12094"></a>C.7 <code class="literal">spring-security-cas</code></h2></div></div></div><p>The CAS module provides integration with JA-SIG CAS.
+ </p><div class="table"><a name="deps-cas"></a><p class="title"><b>Table C.7. CAS Dependencies</b></p><div class="table-contents"><table summary="CAS Dependencies" style="border-collapse: collapse;border-top: 0.5pt solid ; border-bottom: 0.5pt solid ; border-left: 0.5pt solid ; border-right: 0.5pt solid ; "><colgroup><col align="left"><col align="left"><col align="left"></colgroup><thead><tr><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="center">Dependency</th><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="center">Version</th><th style="border-bottom: 0.5pt solid ; " align="center">Description</th></tr></thead><tbody><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">spring-security-core</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> </td><td style="border-bottom: 0.5pt solid ; " align="left"> </td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">spring-security-web</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> </td><td style="border-bottom: 0.5pt solid ; " align="left"> </td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">cas-client-core</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">3.1.12</td><td style="border-bottom: 0.5pt solid ; " align="left">The JA-SIG CAS Client. This is the basis of the Spring Security integration.</td></tr><tr><td style="border-right: 0.5pt solid ; " align="left">ehcache</td><td style="border-right: 0.5pt solid ; " align="left">1.6.2</td><td style="" align="left"><p>Required if you are using the ehcache-based ticket cache (optional).</p></td></tr></tbody></table></div></div><p><br class="table-break">
+ </p></div><div class="section" title="C.8 spring-security-openid"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e12142"></a>C.8 <code class="literal">spring-security-openid</code></h2></div></div></div><p>The OpenID module.
+ </p><div class="table"><a name="deps-openid"></a><p class="title"><b>Table C.8. OpenID Dependencies</b></p><div class="table-contents"><table summary="OpenID Dependencies" style="border-collapse: collapse;border-top: 0.5pt solid ; border-bottom: 0.5pt solid ; border-left: 0.5pt solid ; border-right: 0.5pt solid ; "><colgroup><col align="left"><col align="left"><col align="left"></colgroup><thead><tr><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="center">Dependency</th><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="center">Version</th><th style="border-bottom: 0.5pt solid ; " align="center">Description</th></tr></thead><tbody><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">spring-security-core</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> </td><td style="border-bottom: 0.5pt solid ; " align="left"> </td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">spring-security-web</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> </td><td style="border-bottom: 0.5pt solid ; " align="left"> </td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">openid4java-nodeps</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">0.9.6</td><td style="border-bottom: 0.5pt solid ; " align="left">Spring Security's OpenID integration uses OpenID4Java.</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">httpclient</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">4.1.1</td><td style="border-bottom: 0.5pt solid ; " align="left">openid4java-nodeps depends on HttpClient 4.</td></tr><tr><td style="border-right: 0.5pt solid ; " align="left">guice</td><td style="border-right: 0.5pt solid ; " align="left">2.0</td><td style="" align="left">openid4java-nodeps depends on Guice 2.</td></tr></tbody></table></div></div><p><br class="table-break">
+ </p></div><div class="section" title="C.9 spring-security-taglibs"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e12196"></a>C.9 <code class="literal">spring-security-taglibs</code></h2></div></div></div><p>Provides Spring Security's JSP tag implementations.
+ </p><div class="table"><a name="deps-taglibs"></a><p class="title"><b>Table C.9. Taglib Dependencies</b></p><div class="table-contents"><table summary="Taglib Dependencies" style="border-collapse: collapse;border-top: 0.5pt solid ; border-bottom: 0.5pt solid ; border-left: 0.5pt solid ; border-right: 0.5pt solid ; "><colgroup><col align="left"><col align="left"><col align="left"></colgroup><thead><tr><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="center">Dependency</th><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="center">Version</th><th style="border-bottom: 0.5pt solid ; " align="center">Description</th></tr></thead><tbody><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">spring-security-core</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> </td><td style="border-bottom: 0.5pt solid ; " align="left"> </td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">spring-security-web</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> </td><td style="border-bottom: 0.5pt solid ; " align="left"> </td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left">spring-security-acl</td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left"> </td><td style="border-bottom: 0.5pt solid ; " align="left">
+ Required if you are using the <code class="literal">accesscontrollist</code> tag or
+ <code class="literal">hasPermission()</code> expressions with ACLs (optional).
+ </td></tr><tr><td style="border-right: 0.5pt solid ; " align="left">spring-expression</td><td style="border-right: 0.5pt solid ; " align="left"> </td><td style="" align="left">Required if you are using SPEL expressions in your tag access constraints.</td></tr></tbody></table></div></div><p><br class="table-break">
+ </p></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
</script><!--End LoopFuse code--></body></html>
\ No newline at end of file
diff --git a/docs/reference/springsecurity.html b/docs/reference/springsecurity.html
index e20fe4a..70a3a4c 100644
--- a/docs/reference/springsecurity.html
+++ b/docs/reference/springsecurity.html
@@ -8,10 +8,16 @@
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
- </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Spring Security</th></tr><tr><td width="20%" align="left"> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="preface.html">Next</a></td></tr></table><hr></div><div class="book" title="Spring Security"><div class="titlepage"><div><div><h1 class="title"><a name="spring-security-reference-guide"></a>Spring Security</h1></div><div><h2 class="subtitle">Reference Documentation</h2></div><div><div class="authorgroup"><div class="author"><h3 class="author">Ben Alex</h3></div><div class="author"><h3 class="author">Luke Taylor</h3></div></div></div><div><p class="releaseinfo">3.0.5.RELEASE</p></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="preface"><a href="preface.html">Preface</a></span></dt><dt><span class="part"><a href="getting-started.html">I. Getting Started</a></span></dt><dd><dl><dt><span class="chapter"><a href="introduction.html">1. Introduction</a></span></dt><dd><dl><dt><span class="section"><a href="introduction.html#what-is-acegi-security">1.1. What is Spring Security?</a></span></dt><dt><span class="section"><a href="introduction.html#history">1.2. History</a></span></dt><dt><span class="section"><a href="introduction.html#release-numbering">1.3. Release Numbering</a></span></dt><dt><span class="section"><a href="introduction.html#get-spring-security">1.4. Getting Spring Security</a></span></dt><dd><dl><dt><span class="section"><a href="introduction.html#modules">1.4.1. Project Modules</a></span></dt><dt><span class="section"><a href="introduction.html#get-source">1.4.2. Checking out the Source</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="ns-config.html">2. Security Namespace Configuration</a></span></dt><dd><dl><dt><span class="section"><a href="ns-config.html#d0e344">2.1. Introduction</a></span></dt><dd><dl><dt><span class="section"><a href="ns-config.html#d0e382">2.1.1. Design of the Namespace</a></span></dt></dl></dd><dt><span class="section"><a href="ns-config.html#ns-getting-started">2.2. Getting Started with Security Namespace Configuration</a></span></dt><dd><dl><dt><span class="section"><a href="ns-config.html#ns-web-xml">2.2.1. <code class="literal">web.xml</code> Configuration</a></span></dt><dt><span class="section"><a href="ns-config.html#ns-minimal">2.2.2. A Minimal <code class="literal"><http></code> Configuration</a></span></dt><dt><span class="section"><a href="ns-config.html#ns-auth-providers">2.2.3. Using other Authentication Providers</a></span></dt></dl></dd><dt><span class="section"><a href="ns-config.html#ns-web-advanced">2.3. Advanced Web Features</a></span></dt><dd><dl><dt><span class="section"><a href="ns-config.html#ns-remember-me">2.3.1. Remember-Me Authentication</a></span></dt><dt><span class="section"><a href="ns-config.html#ns-requires-channel">2.3.2. Adding HTTP/HTTPS Channel Security</a></span></dt><dt><span class="section"><a href="ns-config.html#ns-session-mgmt">2.3.3. Session Management</a></span></dt><dt><span class="section"><a href="ns-config.html#ns-openid">2.3.4. OpenID Support</a></span></dt><dt><span class="section"><a href="ns-config.html#ns-custom-filters">2.3.5. Adding in Your Own Filters</a></span></dt></dl></dd><dt><span class="section"><a href="ns-config.html#ns-method-security">2.4. Method Security</a></span></dt><dd><dl><dt><span class="section"><a href="ns-config.html#ns-global-method">2.4.1. The <code class="literal"><global-method-security></code> Element</a></span></dt></dl></dd><dt><span class="section"><a href="ns-config.html#ns-access-manager">2.5. The Default AccessDecisionManager</a></span></dt><dd><dl><dt><span class="section"><a href="ns-config.html#ns-custom-access-mgr">2.5.1. Customizing the AccessDecisionManager</a></span></dt></dl></dd><dt><span class="section"><a href="ns-config.html#ns-auth-manager">2.6. The Authentication Manager and the Namespace</a></span></dt></dl></dd><dt><span class="chapter"><a href="sample-apps.html">3. Sample Applications</a></span></dt><dd><dl><dt><span class="section"><a href="sample-apps.html#tutorial-sample">3.1. Tutorial Sample</a></span></dt><dt><span class="section"><a href="sample-apps.html#contacts-sample">3.2. Contacts</a></span></dt><dt><span class="section"><a href="sample-apps.html#ldap-sample">3.3. LDAP Sample</a></span></dt><dt><span class="section"><a href="sample-apps.html#cas-sample">3.4. CAS Sample</a></span></dt><dt><span class="section"><a href="sample-apps.html#preauth-sample">3.5. Pre-Authentication Sample</a></span></dt></dl></dd><dt><span class="chapter"><a href="community.html">4. Spring Security Community</a></span></dt><dd><dl><dt><span class="section"><a href="community.html#jira">4.1. Issue Tracking</a></span></dt><dt><span class="section"><a href="community.html#becoming-involved">4.2. Becoming Involved</a></span></dt><dt><span class="section"><a href="community.html#further-info">4.3. Further Information</a></span></dt></dl></dd></dl></dd><dt><span class="part"><a href="overall-architecture.html">II. Architecture and Implementation</a></span></dt><dd><dl><dt><span class="chapter"><a href="technical-overview.html">5. Technical Overview</a></span></dt><dd><dl><dt><span class="section"><a href="technical-overview.html#runtime-environment">5.1. Runtime Environment</a></span></dt><dt><span class="section"><a href="technical-overview.html#core-components">5.2. Core Components</a></span></dt><dd><dl><dt><span class="section"><a href="technical-overview.html#d0e1518">5.2.1. SecurityContextHolder, SecurityContext and Authentication Objects </a></span></dt><dt><span class="section"><a href="technical-overview.html#d0e1588">5.2.2. The UserDetailsService</a></span></dt><dt><span class="section"><a href="technical-overview.html#tech-granted-authority">5.2.3. GrantedAuthority</a></span></dt><dt><span class="section"><a href="technical-overview.html#d0e1709">5.2.4. Summary</a></span></dt></dl></dd><dt><span class="section"><a href="technical-overview.html#tech-intro-authentication">5.3. Authentication</a></span></dt><dd><dl><dt><span class="section"><a href="technical-overview.html#d0e1765">5.3.1. What is authentication in Spring Security?</a></span></dt><dt><span class="section"><a href="technical-overview.html#d0e1835">5.3.2. Setting the SecurityContextHolder Contents Directly</a></span></dt></dl></dd><dt><span class="section"><a href="technical-overview.html#tech-intro-web-authentication">5.4. Authentication in a Web Application</a></span></dt><dd><dl><dt><span class="section"><a href="technical-overview.html#d0e1917">5.4.1. ExceptionTranslationFilter</a></span></dt><dt><span class="section"><a href="technical-overview.html#tech-intro-auth-entry-point">5.4.2. AuthenticationEntryPoint</a></span></dt><dt><span class="section"><a href="technical-overview.html#d0e1947">5.4.3. Authentication Mechanism</a></span></dt><dt><span class="section"><a href="technical-overview.html#tech-intro-sec-context-persistence">5.4.4. Storing the <code class="interfacename">SecurityContext</code> between requests</a></span></dt></dl></dd><dt><span class="section"><a href="technical-overview.html#tech-intro-access-control">5.5. Access-Control (Authorization) in Spring Security</a></span></dt><dd><dl><dt><span class="section"><a href="technical-overview.html#d0e2068">5.5.1. Security and AOP Advice</a></span></dt><dt><span class="section"><a href="technical-overview.html#secure-objects">5.5.2. Secure Objects and the <code class="classname">AbstractSecurityInterceptor</code></a></span></dt></dl></dd><dt><span class="section"><a href="technical-overview.html#localization">5.6. Localization</a></span></dt></dl></dd><dt><span class="chapter"><a href="core-services.html">6. Core Services</a></span></dt><dd><dl><dt><span class="section"><a href="core-services.html#core-services-authentication-manager">6.1. The <code class="interfacename">AuthenticationManager</code>,
- <code class="classname">ProviderManager</code> and
- <code class="classname">AuthenticationProvider</code>s</a></span></dt><dd><dl><dt><span class="section"><a href="core-services.html#core-services-dao-provider">6.1.1. <code class="literal">DaoAuthenticationProvider</code></a></span></dt><dt><span class="section"><a href="core-services.html#core-services-erasing-credentials">6.1.2. Erasing Credentials on Successful Authentication</a></span></dt></dl></dd><dt><span class="section"><a href="core-services.html#d0e2530">6.2. <code class="interfacename">UserDetailsService</code> Implementations</a></span></dt><dd><dl><dt><span class="section"><a href="core-services.html#core-services-in-memory-service">6.2.1. In-Memory Authentication</a></span></dt><dt><span class="section"><a href="core-services.html#core-services-jdbc-user-service">6.2.2. <code class="literal">JdbcDaoImpl</code></a></span></dt></dl></dd><dt><span class="section"><a href="core-services.html#core-services-password-encoding">6.3. Password Encoding</a></span></dt><dd><dl><dt><span class="section"><a href="core-services.html#d0e2649">6.3.1. What is a hash?</a></span></dt><dt><span class="section"><a href="core-services.html#d0e2663">6.3.2. Adding Salt to a Hash</a></span></dt><dt><span class="section"><a href="core-services.html#d0e2680">6.3.3. Hashing and Authentication</a></span></dt></dl></dd></dl></dd></dl></dd><dt><span class="part"><a href="web-app-security.html">III. Web Application Security</a></span></dt><dd><dl><dt><span class="chapter"><a href="security-filter-chain.html">7. The Security Filter Chain</a></span></dt><dd><dl><dt><span class="section"><a href="security-filter-chain.html#delegating-filter-proxy">7.1. <code class="classname">DelegatingFilterProxy</code></a></span></dt><dt><span class="section"><a href="security-filter-chain.html#filter-chain-proxy">7.2. <code class="classname">FilterChainProxy</code></a></span></dt><dd><dl><dt><span class="section"><a href="security-filter-chain.html#d0e2910">7.2.1. Bypassing the Filter Chain</a></span></dt></dl></dd><dt><span class="section"><a href="security-filter-chain.html#d0e2924">7.3. Filter Ordering</a></span></dt><dt><span class="section"><a href="security-filter-chain.html#d0e3025">7.4. Use with other Filter-Based Frameworks</a></span></dt></dl></dd><dt><span class="chapter"><a href="core-web-filters.html">8. Core Security Filters</a></span></dt><dd><dl><dt><span class="section"><a href="core-web-filters.html#filter-security-interceptor">8.1. <code class="classname">FilterSecurityInterceptor</code></a></span></dt><dt><span class="section"><a href="core-web-filters.html#exception-translation-filter">8.2.
- <code class="classname">ExceptionTranslationFilter</code></a></span></dt><dd><dl><dt><span class="section"><a href="core-web-filters.html#auth-entry-point">8.2.1. <code class="interfacename">AuthenticationEntryPoint</code></a></span></dt><dt><span class="section"><a href="core-web-filters.html#access-denied-handler">8.2.2. <code class="interfacename">AccessDeniedHandler</code></a></span></dt></dl></dd><dt><span class="section"><a href="core-web-filters.html#security-context-persistence-filter">8.3. <code class="classname">SecurityContextPersistenceFilter</code></a></span></dt><dd><dl><dt><span class="section"><a href="core-web-filters.html#security-context-repository">8.3.1. <code class="interfacename">SecurityContextRepository</code></a></span></dt></dl></dd><dt><span class="section"><a href="core-web-filters.html#form-login-filter">8.4. <code class="classname">UsernamePasswordAuthenticationFilter</code></a></span></dt><dd><dl><dt><span class="section"><a href="core-web-filters.html#form-login-flow-handling">8.4.1. Application Flow on Authentication Success and Failure</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="basic.html">9. Basic and Digest Authentication</a></span></dt><dd><dl><dt><span class="section"><a href="basic.html#basic-processing-filter">9.1. <code class="classname">BasicAuthenticationFilter</code></a></span></dt><dd><dl><dt><span class="section"><a href="basic.html#basic-config">9.1.1. Configuration</a></span></dt></dl></dd><dt><span class="section"><a href="basic.html#digest-processing-filter">9.2. <code class="classname">DigestAuthenticationFilter</code></a></span></dt><dd><dl><dt><span class="section"><a href="basic.html#digest-config">9.2.1. Configuration</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="remember-me.html">10. Remember-Me Authentication</a></span></dt><dd><dl><dt><span class="section"><a href="remember-me.html#remember-me-overview">10.1. Overview</a></span></dt><dt><span class="section"><a href="remember-me.html#remember-me-hash-token">10.2. Simple Hash-Based Token Approach</a></span></dt><dt><span class="section"><a href="remember-me.html#remember-me-persistent-token">10.3. Persistent Token Approach</a></span></dt><dt><span class="section"><a href="remember-me.html#remember-me-impls">10.4. Remember-Me Interfaces and Implementations</a></span></dt><dd><dl><dt><span class="section"><a href="remember-me.html#d0e3706">10.4.1. TokenBasedRememberMeServices</a></span></dt><dt><span class="section"><a href="remember-me.html#d0e3772">10.4.2. PersistentTokenBasedRememberMeServices</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="session-mgmt.html">11. Session Management</a></span></dt><dd><dl><dt><span class="section"><a href="session-mgmt.html#d0e3809">11.1. SessionManagementFilter</a></span></dt><dt><span class="section"><a href="session-mgmt.html#d0e3847">11.2. <code class="interfacename">SessionAuthenticationStrategy</code></a></span></dt><dt><span class="section"><a href="session-mgmt.html#concurrent-sessions">11.3. Concurrency Control</a></span></dt></dl></dd><dt><span class="chapter"><a href="anonymous.html">12. Anonymous Authentication</a></span></dt><dd><dl><dt><span class="section"><a href="anonymous.html#anonymous-overview">12.1. Overview</a></span></dt><dt><span class="section"><a href="anonymous.html#anonymous-config">12.2. Configuration</a></span></dt><dt><span class="section"><a href="anonymous.html#anonymous-auth-trust-resolver">12.3. <code class="interfacename">AuthenticationTrustResolver</code></a></span></dt></dl></dd></dl></dd><dt><span class="part"><a href="authorization.html">IV. Authorization</a></span></dt><dd><dl><dt><span class="chapter"><a href="authz-arch.html">13. Authorization Architecture</a></span></dt><dd><dl><dt><span class="section"><a href="authz-arch.html#authz-authorities">13.1. Authorities</a></span></dt><dt><span class="section"><a href="authz-arch.html#authz-pre-invocation">13.2. Pre-Invocation Handling</a></span></dt><dd><dl><dt><span class="section"><a href="authz-arch.html#authz-access-decision-manager">13.2.1. The AccessDecisionManager</a></span></dt><dt><span class="section"><a href="authz-arch.html#authz-voting-based">13.2.2. Voting-Based AccessDecisionManager Implementations</a></span></dt></dl></dd><dt><span class="section"><a href="authz-arch.html#authz-after-invocation-handling">13.3. After Invocation Handling</a></span></dt></dl></dd><dt><span class="chapter"><a href="secure-object-impls.html">14. Secure Object Implementations</a></span></dt><dd><dl><dt><span class="section"><a href="secure-object-impls.html#aop-alliance">14.1. AOP Alliance (MethodInvocation) Security Interceptor</a></span></dt><dd><dl><dt><span class="section"><a href="secure-object-impls.html#d0e4677">14.1.1. Explicit MethodSecurityInterceptor Configuration</a></span></dt></dl></dd><dt><span class="section"><a href="secure-object-impls.html#aspectj">14.2. AspectJ (JoinPoint) Security Interceptor</a></span></dt></dl></dd><dt><span class="chapter"><a href="el-access.html">15. Expression-Based Access Control</a></span></dt><dd><dl><dt><span class="section"><a href="el-access.html#d0e4781">15.1. Overview</a></span></dt><dd><dl><dt><span class="section"><a href="el-access.html#el-common-built-in">15.1.1. Common Built-In Expressions</a></span></dt></dl></dd><dt><span class="section"><a href="el-access.html#el-access-web">15.2. Web Security Expressions</a></span></dt><dt><span class="section"><a href="el-access.html#d0e4949">15.3. Method Security Expressions</a></span></dt><dd><dl><dt><span class="section"><a href="el-access.html#el-pre-post-annotations">15.3.1. <code class="literal">@Pre</code> and <code class="literal">@Post</code> Annotations</a></span></dt><dt><span class="section"><a href="el-access.html#el-method-built-in">15.3.2. Built-In Expressions</a></span></dt></dl></dd></dl></dd></dl></dd><dt><span class="part"><a href="advanced-topics.html">V. Additional Topics</a></span></dt><dd><dl><dt><span class="chapter"><a href="domain-acls.html">16. Domain Object Security (ACLs)</a></span></dt><dd><dl><dt><span class="section"><a href="domain-acls.html#domain-acls-overview">16.1. Overview</a></span></dt><dt><span class="section"><a href="domain-acls.html#domain-acls-key-concepts">16.2. Key Concepts</a></span></dt><dt><span class="section"><a href="domain-acls.html#domain-acls-getting-started">16.3. Getting Started</a></span></dt></dl></dd><dt><span class="chapter"><a href="preauth.html">17. Pre-Authentication Scenarios</a></span></dt><dd><dl><dt><span class="section"><a href="preauth.html#d0e5505">17.1. Pre-Authentication Framework Classes</a></span></dt><dd><dl><dt><span class="section"><a href="preauth.html#d0e5516">17.1.1. AbstractPreAuthenticatedProcessingFilter</a></span></dt><dt><span class="section"><a href="preauth.html#d0e5533">17.1.2. AbstractPreAuthenticatedAuthenticationDetailsSource</a></span></dt><dt><span class="section"><a href="preauth.html#d0e5590">17.1.3. PreAuthenticatedAuthenticationProvider</a></span></dt><dt><span class="section"><a href="preauth.html#d0e5622">17.1.4. Http403ForbiddenEntryPoint</a></span></dt></dl></dd><dt><span class="section"><a href="preauth.html#d0e5642">17.2. Concrete Implementations</a></span></dt><dd><dl><dt><span class="section"><a href="preauth.html#d0e5650">17.2.1. Request-Header Authentication (Siteminder)</a></span></dt><dt><span class="section"><a href="preauth.html#d0e5696">17.2.2. J2EE Container Authentication</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="ldap.html">18. LDAP Authentication</a></span></dt><dd><dl><dt><span class="section"><a href="ldap.html#ldap-overview">18.1. Overview</a></span></dt><dt><span class="section"><a href="ldap.html#d0e5734">18.2. Using LDAP with Spring Security</a></span></dt><dt><span class="section"><a href="ldap.html#ldap-server">18.3. Configuring an LDAP Server</a></span></dt><dd><dl><dt><span class="section"><a href="ldap.html#d0e5773">18.3.1. Using an Embedded Test Server</a></span></dt><dt><span class="section"><a href="ldap.html#d0e5797">18.3.2. Using Bind Authentication</a></span></dt><dt><span class="section"><a href="ldap.html#d0e5818">18.3.3. Loading Authorities</a></span></dt></dl></dd><dt><span class="section"><a href="ldap.html#d0e5883">18.4. Implementation Classes</a></span></dt><dd><dl><dt><span class="section"><a href="ldap.html#ldap-ldap-authenticators">18.4.1. LdapAuthenticator Implementations</a></span></dt><dt><span class="section"><a href="ldap.html#ldap-context-source">18.4.2. Connecting to the LDAP Server</a></span></dt><dt><span class="section"><a href="ldap.html#ldap-searchobjects">18.4.3. LDAP Search Objects</a></span></dt><dt><span class="section"><a href="ldap.html#ldap-authorities">18.4.4. LdapAuthoritiesPopulator</a></span></dt><dt><span class="section"><a href="ldap.html#ldap-bean-config">18.4.5. Spring Bean Configuration</a></span></dt><dt><span class="section"><a href="ldap.html#ldap-custom-user-details">18.4.6. LDAP Attributes and Customized UserDetails</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="taglibs.html">19. JSP Tag Libraries</a></span></dt><dd><dl><dt><span class="section"><a href="taglibs.html#d0e6137">19.1. Declaring the Taglib</a></span></dt><dt><span class="section"><a href="taglibs.html#d0e6144">19.2. The <code class="literal">authorize</code> Tag</a></span></dt><dt><span class="section"><a href="taglibs.html#d0e6190">19.3. The <code class="literal">authentication</code>Tag</a></span></dt><dt><span class="section"><a href="taglibs.html#d0e6221">19.4. The <code class="literal">accesscontrollist</code> Tag</a></span></dt></dl></dd><dt><span class="chapter"><a href="jaas.html">20. Java Authentication and Authorization Service (JAAS) Provider</a></span></dt><dd><dl><dt><span class="section"><a href="jaas.html#jaas-overview">20.1. Overview</a></span></dt><dt><span class="section"><a href="jaas.html#jaas-config">20.2. Configuration</a></span></dt><dd><dl><dt><span class="section"><a href="jaas.html#jaas-callbackhandler">20.2.1. JAAS CallbackHandler</a></span></dt><dt><span class="section"><a href="jaas.html#jaas-authoritygranter">20.2.2. JAAS AuthorityGranter</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="cas.html">21. CAS Authentication</a></span></dt><dd><dl><dt><span class="section"><a href="cas.html#cas-overview">21.1. Overview</a></span></dt><dt><span class="section"><a href="cas.html#cas-how-it-works">21.2. How CAS Works</a></span></dt><dt><span class="section"><a href="cas.html#cas-client">21.3. Configuration of CAS Client</a></span></dt></dl></dd><dt><span class="chapter"><a href="x509.html">22. X.509 Authentication</a></span></dt><dd><dl><dt><span class="section"><a href="x509.html#x509-overview">22.1. Overview</a></span></dt><dt><span class="section"><a href="x509.html#d0e6578">22.2. Adding X.509 Authentication to Your Web Application</a></span></dt><dt><span class="section"><a href="x509.html#x509-ssl-config">22.3. Setting up SSL in Tomcat</a></span></dt></dl></dd><dt><span class="chapter"><a href="runas.html">23. Run-As Authentication Replacement</a></span></dt><dd><dl><dt><span class="section"><a href="runas.html#runas-overview">23.1. Overview</a></span></dt><dt><span class="section"><a href="runas.html#runas-config">23.2. Configuration</a></span></dt></dl></dd></dl></dd><dt><span class="appendix"><a href="appendix-schema.html">A. Security Database Schema</a></span></dt><dd><dl><dt><span class="section"><a href="appendix-schema.html#d0e6840">A.1. User Schema</a></span></dt><dd><dl><dt><span class="section"><a href="appendix-schema.html#d0e6853">A.1.1. Group Authorities</a></span></dt></dl></dd><dt><span class="section"><a href="appendix-schema.html#d0e6863">A.2. Persistent Login (Remember-Me) Schema</a></span></dt><dt><span class="section"><a href="appendix-schema.html#dbschema-acl">A.3. ACL Schema</a></span></dt><dd><dl><dt><span class="section"><a href="appendix-schema.html#d0e6927">A.3.1. Hypersonic SQL</a></span></dt></dl></dd></dl></dd><dt><span class="appendix"><a href="appendix-namespace.html">B. The Security Namespace</a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-http">B.1. Web Application Security - the <code class="literal"><http></code> Element</a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-http-attributes">B.1.1. <code class="literal"><http></code> Attributes</a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-access-denied-handler">B.1.2. <code class="literal"><access-denied-handler></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#d0e7289">B.1.3. The <code class="literal"><intercept-url></code> Element</a></span></dt><dt><span class="section"><a href="appendix-namespace.html#d0e7375">B.1.4. The <code class="literal"><port-mappings></code> Element</a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-form-login">B.1.5. The <code class="literal"><form-login></code> Element</a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-http-basic">B.1.6. The <code class="literal"><http-basic></code> Element</a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-remember-me">B.1.7. The <code class="literal"><remember-me></code> Element</a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-session-mgmt">B.1.8. The <code class="literal"><session-management></code> Element</a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-concurrent-session-control">B.1.9. The <code class="literal"><concurrency-control></code> Element</a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-anonymous">B.1.10. The <code class="literal"><anonymous></code> Element</a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-x509">B.1.11. The <code class="literal"><x509></code> Element</a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-openid-login">B.1.12. The <code class="literal"><openid-login></code> Element</a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-logout">B.1.13. The <code class="literal"><logout></code> Element</a></span></dt><dt><span class="section"><a href="appendix-namespace.html#d0e7898">B.1.14. The <code class="literal"><custom-filter></code> Element</a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-request-cache">B.1.15. The <code class="literal">request-cache</code> Element</a></span></dt><dt><span class="section"><a href="appendix-namespace.html#d0e7926">B.1.16. The <code class="literal"><http-firewall></code> Element</a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-authentication">B.2. Authentication Services</a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#d0e7960">B.2.1. The <code class="literal"><authentication-manager></code> Element</a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-method-security">B.3. Method Security</a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-gms">B.3.1. The <code class="literal"><global-method-security></code> Element</a></span></dt><dt><span class="section"><a href="appendix-namespace.html#d0e8166">B.3.2. LDAP Namespace Options</a></span></dt></dl></dd></dl></dd></dl></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
+ </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Spring Security</th></tr><tr><td width="20%" align="left"> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="preface.html">Next</a></td></tr></table><hr></div><div class="book" title="Spring Security"><div class="titlepage"><div><div><h1 class="title"><a name="spring-security-reference-guide"></a>Spring Security</h1></div><div><h2 class="subtitle">Reference Documentation</h2></div><div><div class="authorgroup"><div class="author"><h3 class="author">Ben Alex</h3></div><div class="author"><h3 class="author">Luke Taylor</h3></div></div></div><div><p class="releaseinfo">3.1.0</p></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="preface"><a href="preface.html">Preface</a></span></dt><dt><span class="part"><a href="getting-started.html">I. Getting Started</a></span></dt><dd><dl><dt><span class="chapter"><a href="introduction.html">1. Introduction</a></span></dt><dd><dl><dt><span class="section"><a href="introduction.html#what-is-acegi-security">1.1. What is Spring Security?</a></span></dt><dt><span class="section"><a href="introduction.html#history">1.2. History</a></span></dt><dt><span class="section"><a href="introduction.html#release-numbering">1.3. Release Numbering</a></span></dt><dt><span class="section"><a href="introduction.html#get-spring-security">1.4. Getting Spring Security</a></span></dt><dd><dl><dt><span class="section"><a href="introduction.html#modules">1.4.1. Project Modules</a></span></dt><dd><dl><dt><span class="section"><a href="introduction.html#spring-security-core">Core - <code class="literal">spring-security-core.jar</code></a></span></dt><dt><span class="section"><a href="introduction.html#spring-security-remoting">Remoting - <code class="literal">spring-security-remoting.jar</code></a></span></dt><dt><span class="section"><a href="introduction.html#spring-security-web">Web - <code class="literal">spring-security-web.jar</code></a></span></dt><dt><span class="section"><a href="introduction.html#spring-security-config">Config - <code class="literal">spring-security-config.jar</code></a></span></dt><dt><span class="section"><a href="introduction.html#spring-security-ldap">LDAP - <code class="literal">spring-security-ldap.jar</code></a></span></dt><dt><span class="section"><a href="introduction.html#spring-security-acl">ACL - <code class="literal">spring-security-acl.jar</code></a></span></dt><dt><span class="section"><a href="introduction.html#spring-security-cas">CAS - <code class="literal">spring-security-cas.jar</code></a></span></dt><dt><span class="section"><a href="introduction.html#spring-security-openid">OpenID - <code class="literal">spring-security-openid.jar</code></a></span></dt></dl></dd><dt><span class="section"><a href="introduction.html#get-source">1.4.2. Checking out the Source</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="new-3.1.html">2. What's new in Spring Security 3.1</a></span></dt><dd><dl><dt><span class="section"><a href="new-3.1.html#new-3.1-highlevel">2.1. High level updates found Spring Security 3.1</a></span></dt><dt><span class="section"><a href="new-3.1.html#new-3.1-ns">2.2. Spring Security 3.1 namespace updates</a></span></dt></dl></dd><dt><span class="chapter"><a href="ns-config.html">3. Security Namespace Configuration</a></span></dt><dd><dl><dt><span class="section"><a href="ns-config.html#d0e507">3.1. Introduction</a></span></dt><dd><dl><dt><span class="section"><a href="ns-config.html#d0e545">3.1.1. Design of the Namespace</a></span></dt></dl></dd><dt><span class="section"><a href="ns-config.html#ns-getting-started">3.2. Getting Started with Security Namespace Configuration</a></span></dt><dd><dl><dt><span class="section"><a href="ns-config.html#ns-web-xml">3.2.1. <code class="literal">web.xml</code> Configuration</a></span></dt><dt><span class="section"><a href="ns-config.html#ns-minimal">3.2.2. A Minimal <code class="literal"><http></code> Configuration</a></span></dt><dd><dl><dt><span class="section"><a href="ns-config.html#ns-auto-config">What does <code class="literal">auto-config</code> Include?</a></span></dt></dl></dd><dt><span class="section"><a href="ns-config.html#ns-form-and-basic">3.2.3. Form and Basic Login Options</a></span></dt><dd><dl><dt><span class="section"><a href="ns-config.html#ns-form-target">Setting a Default Post-Login Destination</a></span></dt></dl></dd><dt><span class="section"><a href="ns-config.html#ns-logout">3.2.4. Logout Handling</a></span></dt><dt><span class="section"><a href="ns-config.html#ns-auth-providers">3.2.5. Using other Authentication Providers</a></span></dt><dd><dl><dt><span class="section"><a href="ns-config.html#ns-password-encoder">Adding a Password Encoder</a></span></dt></dl></dd></dl></dd><dt><span class="section"><a href="ns-config.html#ns-web-advanced">3.3. Advanced Web Features</a></span></dt><dd><dl><dt><span class="section"><a href="ns-config.html#ns-remember-me">3.3.1. Remember-Me Authentication</a></span></dt><dt><span class="section"><a href="ns-config.html#ns-requires-channel">3.3.2. Adding HTTP/HTTPS Channel Security</a></span></dt><dt><span class="section"><a href="ns-config.html#ns-session-mgmt">3.3.3. Session Management</a></span></dt><dd><dl><dt><span class="section"><a href="ns-config.html#d0e1033">Detecting Timeouts</a></span></dt><dt><span class="section"><a href="ns-config.html#ns-concurrent-sessions">Concurrent Session Control</a></span></dt><dt><span class="section"><a href="ns-config.html#ns-session-fixation">Session Fixation Attack Protection</a></span></dt></dl></dd><dt><span class="section"><a href="ns-config.html#ns-openid">3.3.4. OpenID Support</a></span></dt><dd><dl><dt><span class="section"><a href="ns-config.html#d0e1165">Attribute Exchange</a></span></dt></dl></dd><dt><span class="section"><a href="ns-config.html#ns-custom-filters">3.3.5. Adding in Your Own Filters</a></span></dt><dd><dl><dt><span class="section"><a href="ns-config.html#ns-entry-point-ref">Setting a Custom
+ <code class="interfacename">AuthenticationEntryPoint</code></a></span></dt></dl></dd></dl></dd><dt><span class="section"><a href="ns-config.html#ns-method-security">3.4. Method Security</a></span></dt><dd><dl><dt><span class="section"><a href="ns-config.html#ns-global-method">3.4.1. The <code class="literal"><global-method-security></code> Element</a></span></dt><dd><dl><dt><span class="section"><a href="ns-config.html#ns-protect-pointcut">Adding Security Pointcuts using <code class="literal">protect-pointcut</code></a></span></dt></dl></dd></dl></dd><dt><span class="section"><a href="ns-config.html#ns-access-manager">3.5. The Default AccessDecisionManager</a></span></dt><dd><dl><dt><span class="section"><a href="ns-config.html#ns-custom-access-mgr">3.5.1. Customizing the AccessDecisionManager</a></span></dt></dl></dd><dt><span class="section"><a href="ns-config.html#ns-auth-manager">3.6. The Authentication Manager and the Namespace</a></span></dt></dl></dd><dt><span class="chapter"><a href="sample-apps.html">4. Sample Applications</a></span></dt><dd><dl><dt><span class="section"><a href="sample-apps.html#tutorial-sample">4.1. Tutorial Sample</a></span></dt><dt><span class="section"><a href="sample-apps.html#contacts-sample">4.2. Contacts</a></span></dt><dt><span class="section"><a href="sample-apps.html#ldap-sample">4.3. LDAP Sample</a></span></dt><dt><span class="section"><a href="sample-apps.html#openid-sample">4.4. OpenID Sample</a></span></dt><dt><span class="section"><a href="sample-apps.html#cas-sample">4.5. CAS Sample</a></span></dt><dt><span class="section"><a href="sample-apps.html#jaas-sample">4.6. JAAS Sample</a></span></dt><dt><span class="section"><a href="sample-apps.html#preauth-sample">4.7. Pre-Authentication Sample</a></span></dt></dl></dd><dt><span class="chapter"><a href="community.html">5. Spring Security Community</a></span></dt><dd><dl><dt><span class="section"><a href="community.html#jira">5.1. Issue Tracking</a></span></dt><dt><span class="section"><a href="community.html#becoming-involved">5.2. Becoming Involved</a></span></dt><dt><span class="section"><a href="community.html#further-info">5.3. Further Information</a></span></dt></dl></dd></dl></dd><dt><span class="part"><a href="overall-architecture.html">II. Architecture and Implementation</a></span></dt><dd><dl><dt><span class="chapter"><a href="technical-overview.html">6. Technical Overview</a></span></dt><dd><dl><dt><span class="section"><a href="technical-overview.html#runtime-environment">6.1. Runtime Environment</a></span></dt><dt><span class="section"><a href="technical-overview.html#core-components">6.2. Core Components</a></span></dt><dd><dl><dt><span class="section"><a href="technical-overview.html#d0e1833">6.2.1. SecurityContextHolder, SecurityContext and Authentication Objects </a></span></dt><dd><dl><dt><span class="section"><a href="technical-overview.html#d0e1873">Obtaining information about the current user</a></span></dt></dl></dd><dt><span class="section"><a href="technical-overview.html#tech-userdetailsservice">6.2.2. The UserDetailsService</a></span></dt><dt><span class="section"><a href="technical-overview.html#tech-granted-authority">6.2.3. GrantedAuthority</a></span></dt><dt><span class="section"><a href="technical-overview.html#d0e2041">6.2.4. Summary</a></span></dt></dl></dd><dt><span class="section"><a href="technical-overview.html#tech-intro-authentication">6.3. Authentication</a></span></dt><dd><dl><dt><span class="section"><a href="technical-overview.html#d0e2097">6.3.1. What is authentication in Spring Security?</a></span></dt><dt><span class="section"><a href="technical-overview.html#d0e2167">6.3.2. Setting the SecurityContextHolder Contents Directly</a></span></dt></dl></dd><dt><span class="section"><a href="technical-overview.html#tech-intro-web-authentication">6.4. Authentication in a Web Application</a></span></dt><dd><dl><dt><span class="section"><a href="technical-overview.html#d0e2256">6.4.1. ExceptionTranslationFilter</a></span></dt><dt><span class="section"><a href="technical-overview.html#tech-intro-auth-entry-point">6.4.2. AuthenticationEntryPoint</a></span></dt><dt><span class="section"><a href="technical-overview.html#d0e2286">6.4.3. Authentication Mechanism</a></span></dt><dt><span class="section"><a href="technical-overview.html#tech-intro-sec-context-persistence">6.4.4. Storing the <code class="interfacename">SecurityContext</code> between
+ requests</a></span></dt></dl></dd><dt><span class="section"><a href="technical-overview.html#tech-intro-access-control">6.5. Access-Control (Authorization) in Spring Security</a></span></dt><dd><dl><dt><span class="section"><a href="technical-overview.html#d0e2410">6.5.1. Security and AOP Advice</a></span></dt><dt><span class="section"><a href="technical-overview.html#secure-objects">6.5.2. Secure Objects and the <code class="classname">AbstractSecurityInterceptor</code></a></span></dt><dd><dl><dt><span class="section"><a href="technical-overview.html#tech-intro-config-attributes">What are Configuration Attributes?</a></span></dt><dt><span class="section"><a href="technical-overview.html#d0e2540">RunAsManager</a></span></dt><dt><span class="section"><a href="technical-overview.html#d0e2566">AfterInvocationManager</a></span></dt><dt><span class="section"><a href="technical-overview.html#d0e2601">Extending the Secure Object Model</a></span></dt></dl></dd></dl></dd><dt><span class="section"><a href="technical-overview.html#localization">6.6. Localization</a></span></dt></dl></dd><dt><span class="chapter"><a href="core-services.html">7. Core Services</a></span></dt><dd><dl><dt><span class="section"><a href="core-services.html#core-services-authentication-manager">7.1. The <code class="interfacename">AuthenticationManager</code>,
+ <code class="classname">ProviderManager</code> and
+ <code class="classname">AuthenticationProvider</code>s</a></span></dt><dd><dl><dt><span class="section"><a href="core-services.html#core-services-erasing-credentials">7.1.1. Erasing Credentials on Successful Authentication</a></span></dt><dt><span class="section"><a href="core-services.html#core-services-dao-provider">7.1.2. <code class="literal">DaoAuthenticationProvider</code></a></span></dt></dl></dd><dt><span class="section"><a href="core-services.html#d0e2871">7.2. <code class="interfacename">UserDetailsService</code> Implementations</a></span></dt><dd><dl><dt><span class="section"><a href="core-services.html#core-services-in-memory-service">7.2.1. In-Memory Authentication</a></span></dt><dt><span class="section"><a href="core-services.html#core-services-jdbc-user-service">7.2.2. <code class="literal">JdbcDaoImpl</code></a></span></dt><dd><dl><dt><span class="section"><a href="core-services.html#d0e2964">Authority Groups</a></span></dt></dl></dd></dl></dd><dt><span class="section"><a href="core-services.html#core-services-password-encoding">7.3. Password Encoding</a></span></dt><dd><dl><dt><span class="section"><a href="core-services.html#d0e3003">7.3.1. What is a hash?</a></span></dt><dt><span class="section"><a href="core-services.html#d0e3017">7.3.2. Adding Salt to a Hash</a></span></dt><dt><span class="section"><a href="core-services.html#d0e3052">7.3.3. Hashing and Authentication</a></span></dt></dl></dd></dl></dd></dl></dd><dt><span class="part"><a href="web-app-security.html">III. Web Application Security</a></span></dt><dd><dl><dt><span class="chapter"><a href="security-filter-chain.html">8. The Security Filter Chain</a></span></dt><dd><dl><dt><span class="section"><a href="security-filter-chain.html#delegating-filter-proxy">8.1. <code class="classname">DelegatingFilterProxy</code></a></span></dt><dt><span class="section"><a href="security-filter-chain.html#filter-chain-proxy">8.2. <code class="classname">FilterChainProxy</code></a></span></dt><dd><dl><dt><span class="section"><a href="security-filter-chain.html#d0e3260">8.2.1. Bypassing the Filter Chain</a></span></dt></dl></dd><dt><span class="section"><a href="security-filter-chain.html#d0e3274">8.3. Filter Ordering</a></span></dt><dt><span class="section"><a href="security-filter-chain.html#request-matching">8.4. Request Matching and <code class="interfacename">HttpFirewall</code></a></span></dt><dt><span class="section"><a href="security-filter-chain.html#d0e3522">8.5. Use with other Filter-Based Frameworks</a></span></dt><dt><span class="section"><a href="security-filter-chain.html#filter-chains-with-ns">8.6. Advanced Namespace Configuration</a></span></dt></dl></dd><dt><span class="chapter"><a href="core-web-filters.html">9. Core Security Filters</a></span></dt><dd><dl><dt><span class="section"><a href="core-web-filters.html#filter-security-interceptor">9.1. <code class="classname">FilterSecurityInterceptor</code></a></span></dt><dt><span class="section"><a href="core-web-filters.html#exception-translation-filter">9.2. <code class="classname">ExceptionTranslationFilter</code></a></span></dt><dd><dl><dt><span class="section"><a href="core-web-filters.html#auth-entry-point">9.2.1. <code class="interfacename">AuthenticationEntryPoint</code></a></span></dt><dt><span class="section"><a href="core-web-filters.html#access-denied-handler">9.2.2. <code class="interfacename">AccessDeniedHandler</code></a></span></dt><dt><span class="section"><a href="core-web-filters.html#request-caching">9.2.3. <code class="interfacename">SavedRequest</code>s and the <code class="interfacename">RequestCache</code> Interface</a></span></dt></dl></dd><dt><span class="section"><a href="core-web-filters.html#security-context-persistence-filter">9.3. <code class="classname">SecurityContextPersistenceFilter</code></a></span></dt><dd><dl><dt><span class="section"><a href="core-web-filters.html#security-context-repository">9.3.1. <code class="interfacename">SecurityContextRepository</code></a></span></dt></dl></dd><dt><span class="section"><a href="core-web-filters.html#form-login-filter">9.4. <code class="classname">UsernamePasswordAuthenticationFilter</code></a></span></dt><dd><dl><dt><span class="section"><a href="core-web-filters.html#form-login-flow-handling">9.4.1. Application Flow on Authentication Success and Failure</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="basic.html">10. Basic and Digest Authentication</a></span></dt><dd><dl><dt><span class="section"><a href="basic.html#basic-processing-filter">10.1. <code class="classname">BasicAuthenticationFilter</code></a></span></dt><dd><dl><dt><span class="section"><a href="basic.html#basic-config">10.1.1. Configuration</a></span></dt></dl></dd><dt><span class="section"><a href="basic.html#digest-processing-filter">10.2. <code class="classname">DigestAuthenticationFilter</code></a></span></dt><dd><dl><dt><span class="section"><a href="basic.html#digest-config">10.2.1. Configuration</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="remember-me.html">11. Remember-Me Authentication</a></span></dt><dd><dl><dt><span class="section"><a href="remember-me.html#remember-me-overview">11.1. Overview</a></span></dt><dt><span class="section"><a href="remember-me.html#remember-me-hash-token">11.2. Simple Hash-Based Token Approach</a></span></dt><dt><span class="section"><a href="remember-me.html#remember-me-persistent-token">11.3. Persistent Token Approach</a></span></dt><dt><span class="section"><a href="remember-me.html#remember-me-impls">11.4. Remember-Me Interfaces and Implementations</a></span></dt><dd><dl><dt><span class="section"><a href="remember-me.html#d0e4268">11.4.1. TokenBasedRememberMeServices</a></span></dt><dt><span class="section"><a href="remember-me.html#d0e4334">11.4.2. PersistentTokenBasedRememberMeServices</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="session-mgmt.html">12. Session Management</a></span></dt><dd><dl><dt><span class="section"><a href="session-mgmt.html#d0e4371">12.1. SessionManagementFilter</a></span></dt><dt><span class="section"><a href="session-mgmt.html#d0e4412">12.2. <code class="interfacename">SessionAuthenticationStrategy</code></a></span></dt><dt><span class="section"><a href="session-mgmt.html#concurrent-sessions">12.3. Concurrency Control</a></span></dt><dd><dl><dt><span class="section"><a href="session-mgmt.html#list-authenticated-principals">12.3.1. Querying the <code class="interfacename">SessionRegistry</code> for currently authenticated
+ users and their sessions</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="anonymous.html">13. Anonymous Authentication</a></span></dt><dd><dl><dt><span class="section"><a href="anonymous.html#anonymous-overview">13.1. Overview</a></span></dt><dt><span class="section"><a href="anonymous.html#anonymous-config">13.2. Configuration</a></span></dt><dt><span class="section"><a href="anonymous.html#anonymous-auth-trust-resolver">13.3. <code class="interfacename">AuthenticationTrustResolver</code></a></span></dt></dl></dd></dl></dd><dt><span class="part"><a href="authorization.html">IV. Authorization</a></span></dt><dd><dl><dt><span class="chapter"><a href="authz-arch.html">14. Authorization Architecture</a></span></dt><dd><dl><dt><span class="section"><a href="authz-arch.html#authz-authorities">14.1. Authorities</a></span></dt><dt><span class="section"><a href="authz-arch.html#authz-pre-invocation">14.2. Pre-Invocation Handling</a></span></dt><dd><dl><dt><span class="section"><a href="authz-arch.html#authz-access-decision-manager">14.2.1. The AccessDecisionManager</a></span></dt><dt><span class="section"><a href="authz-arch.html#authz-voting-based">14.2.2. Voting-Based AccessDecisionManager Implementations</a></span></dt><dd><dl><dt><span class="section"><a href="authz-arch.html#authz-role-voter"><code class="classname">RoleVoter</code></a></span></dt><dt><span class="section"><a href="authz-arch.html#authz-authenticated-voter"><code class="classname">AuthenticatedVoter</code></a></span></dt><dt><span class="section"><a href="authz-arch.html#authz-custom-voter">Custom Voters</a></span></dt></dl></dd></dl></dd><dt><span class="section"><a href="authz-arch.html#authz-after-invocation-handling">14.3. After Invocation Handling</a></span></dt><dt><span class="section"><a href="authz-arch.html#authz-hierarchical-roles">14.4. Hierarchical Roles</a></span></dt></dl></dd><dt><span class="chapter"><a href="secure-object-impls.html">15. Secure Object Implementations</a></span></dt><dd><dl><dt><span class="section"><a href="secure-object-impls.html#aop-alliance">15.1. AOP Alliance (MethodInvocation) Security Interceptor</a></span></dt><dd><dl><dt><span class="section"><a href="secure-object-impls.html#d0e5314">15.1.1. Explicit MethodSecurityInterceptor Configuration</a></span></dt></dl></dd><dt><span class="section"><a href="secure-object-impls.html#aspectj">15.2. AspectJ (JoinPoint) Security Interceptor</a></span></dt></dl></dd><dt><span class="chapter"><a href="el-access.html">16. Expression-Based Access Control</a></span></dt><dd><dl><dt><span class="section"><a href="el-access.html#d0e5418">16.1. Overview</a></span></dt><dd><dl><dt><span class="section"><a href="el-access.html#el-common-built-in">16.1.1. Common Built-In Expressions</a></span></dt></dl></dd><dt><span class="section"><a href="el-access.html#el-access-web">16.2. Web Security Expressions</a></span></dt><dt><span class="section"><a href="el-access.html#d0e5586">16.3. Method Security Expressions</a></span></dt><dd><dl><dt><span class="section"><a href="el-access.html#el-pre-post-annotations">16.3.1. <code class="literal">@Pre</code> and <code class="literal">@Post</code> Annotations</a></span></dt><dd><dl><dt><span class="section"><a href="el-access.html#d0e5618">Access Control using <code class="literal">@PreAuthorize</code> and
+ <code class="literal">@PostAuthorize</code></a></span></dt><dt><span class="section"><a href="el-access.html#d0e5682">Filtering using <code class="literal">@PreFilter</code> and
+ <code class="literal">@PostFilter</code></a></span></dt></dl></dd><dt><span class="section"><a href="el-access.html#el-method-built-in">16.3.2. Built-In Expressions</a></span></dt><dd><dl><dt><span class="section"><a href="el-access.html#el-permission-evaluator">The <code class="interfacename">PermissionEvaluator</code> interface</a></span></dt></dl></dd></dl></dd></dl></dd></dl></dd><dt><span class="part"><a href="advanced-topics.html">V. Additional Topics</a></span></dt><dd><dl><dt><span class="chapter"><a href="domain-acls.html">17. Domain Object Security (ACLs)</a></span></dt><dd><dl><dt><span class="section"><a href="domain-acls.html#domain-acls-overview">17.1. Overview</a></span></dt><dt><span class="section"><a href="domain-acls.html#domain-acls-key-concepts">17.2. Key Concepts</a></span></dt><dt><span class="section"><a href="domain-acls.html#domain-acls-getting-started">17.3. Getting Started</a></span></dt></dl></dd><dt><span class="chapter"><a href="preauth.html">18. Pre-Authentication Scenarios</a></span></dt><dd><dl><dt><span class="section"><a href="preauth.html#d0e6142">18.1. Pre-Authentication Framework Classes</a></span></dt><dd><dl><dt><span class="section"><a href="preauth.html#d0e6153">18.1.1. AbstractPreAuthenticatedProcessingFilter</a></span></dt><dd><dl><dt><span class="section"><a href="preauth.html#j2ee-preauth-details">J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource</a></span></dt></dl></dd><dt><span class="section"><a href="preauth.html#d0e6221">18.1.2. PreAuthenticatedAuthenticationProvider</a></span></dt><dt><span class="section"><a href="preauth.html#d0e6253">18.1.3. Http403ForbiddenEntryPoint</a></span></dt></dl></dd><dt><span class="section"><a href="preauth.html#d0e6273">18.2. Concrete Implementations</a></span></dt><dd><dl><dt><span class="section"><a href="preauth.html#d0e6281">18.2.1. Request-Header Authentication (Siteminder)</a></span></dt><dd><dl><dt><span class="section"><a href="preauth.html#d0e6301">Siteminder Example Configuration</a></span></dt></dl></dd><dt><span class="section"><a href="preauth.html#d0e6327">18.2.2. J2EE Container Authentication</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="ldap.html">19. LDAP Authentication</a></span></dt><dd><dl><dt><span class="section"><a href="ldap.html#ldap-overview">19.1. Overview</a></span></dt><dt><span class="section"><a href="ldap.html#d0e6365">19.2. Using LDAP with Spring Security</a></span></dt><dt><span class="section"><a href="ldap.html#ldap-server">19.3. Configuring an LDAP Server</a></span></dt><dd><dl><dt><span class="section"><a href="ldap.html#d0e6413">19.3.1. Using an Embedded Test Server</a></span></dt><dt><span class="section"><a href="ldap.html#d0e6437">19.3.2. Using Bind Authentication</a></span></dt><dt><span class="section"><a href="ldap.html#d0e6461">19.3.3. Loading Authorities</a></span></dt></dl></dd><dt><span class="section"><a href="ldap.html#d0e6526">19.4. Implementation Classes</a></span></dt><dd><dl><dt><span class="section"><a href="ldap.html#ldap-ldap-authenticators">19.4.1. LdapAuthenticator Implementations</a></span></dt><dd><dl><dt><span class="section"><a href="ldap.html#ldap-ldap-authenticators-common">Common Functionality</a></span></dt><dt><span class="section"><a href="ldap.html#ldap-ldap-authenticators-bind">BindAuthenticator</a></span></dt><dt><span class="section"><a href="ldap.html#ldap-ldap-authenticators-password">PasswordComparisonAuthenticator</a></span></dt></dl></dd><dt><span class="section"><a href="ldap.html#ldap-context-source">19.4.2. Connecting to the LDAP Server</a></span></dt><dt><span class="section"><a href="ldap.html#ldap-searchobjects">19.4.3. LDAP Search Objects</a></span></dt><dd><dl><dt><span class="section"><a href="ldap.html#ldap-searchobjects-filter">
+ <code class="classname">FilterBasedLdapUserSearch</code> </a></span></dt></dl></dd><dt><span class="section"><a href="ldap.html#ldap-authorities">19.4.4. LdapAuthoritiesPopulator</a></span></dt><dt><span class="section"><a href="ldap.html#ldap-bean-config">19.4.5. Spring Bean Configuration</a></span></dt><dt><span class="section"><a href="ldap.html#ldap-custom-user-details">19.4.6. LDAP Attributes and Customized UserDetails</a></span></dt></dl></dd><dt><span class="section"><a href="ldap.html#ldap-active-directory">19.5. Active Directory Authentication</a></span></dt><dd><dl><dt><span class="section"><a href="ldap.html#d0e6780">19.5.1. <code class="classname">ActiveDirectoryLdapAuthenticationProvider</code></a></span></dt><dd><dl><dt><span class="section"><a href="ldap.html#d0e6834">Active Directory Error Codes</a></span></dt></dl></dd></dl></dd></dl></dd><dt><span class="chapter"><a href="taglibs.html">20. JSP Tag Libraries</a></span></dt><dd><dl><dt><span class="section"><a href="taglibs.html#d0e6853">20.1. Declaring the Taglib</a></span></dt><dt><span class="section"><a href="taglibs.html#d0e6860">20.2. The <code class="literal">authorize</code> Tag</a></span></dt><dd><dl><dt><span class="section"><a href="taglibs.html#d0e6911">20.2.1. Disabling Tag Authorization for Testing</a></span></dt></dl></dd><dt><span class="section"><a href="taglibs.html#d0e6945">20.3. The <code class="literal">authentication</code>Tag</a></span></dt><dt><span class="section"><a href="taglibs.html#d0e6976">20.4. The <code class="literal">accesscontrollist</code> Tag</a></span></dt></dl></dd><dt><span class="chapter"><a href="jaas.html">21. Java Authentication and Authorization Service (JAAS) Provider</a></span></dt><dd><dl><dt><span class="section"><a href="jaas.html#d0e7027">21.1. Overview</a></span></dt><dt><span class="section"><a href="jaas.html#jaas-abstractjaasauthenticationprovider">21.2. AbstractJaasAuthenticationProvider</a></span></dt><dd><dl><dt><span class="section"><a href="jaas.html#jaas-callbackhandler">21.2.1. JAAS CallbackHandler</a></span></dt><dt><span class="section"><a href="jaas.html#jaas-authoritygranter">21.2.2. JAAS AuthorityGranter</a></span></dt></dl></dd><dt><span class="section"><a href="jaas.html#jaas-defaultjaasauthenticationprovider">21.3. DefaultJaasAuthenticationProvider</a></span></dt><dd><dl><dt><span class="section"><a href="jaas.html#jaas-inmemoryconfiguration">21.3.1. InMemoryConfiguration</a></span></dt><dt><span class="section"><a href="jaas.html#jaas-djap-config">21.3.2. DefaultJaasAuthenticationProvider Example Configuration</a></span></dt></dl></dd><dt><span class="section"><a href="jaas.html#jaas-jaasauthenticationprovider">21.4. JaasAuthenticationProvider</a></span></dt><dt><span class="section"><a href="jaas.html#jaas-apiprovision">21.5. Running as a Subject</a></span></dt></dl></dd><dt><span class="chapter"><a href="cas.html">22. CAS Authentication</a></span></dt><dd><dl><dt><span class="section"><a href="cas.html#cas-overview">22.1. Overview</a></span></dt><dt><span class="section"><a href="cas.html#cas-how-it-works">22.2. How CAS Works</a></span></dt><dd><dl><dt><span class="section"><a href="cas.html#cas-sequence">22.2.1. Spring Security and CAS Interaction Sequence</a></span></dt></dl></dd><dt><span class="section"><a href="cas.html#cas-client">22.3. Configuration of CAS Client</a></span></dt><dd><dl><dt><span class="section"><a href="cas.html#cas-st">22.3.1. Service Ticket Authentication</a></span></dt><dt><span class="section"><a href="cas.html#cas-singlelogout">22.3.2. Single Logout</a></span></dt><dt><span class="section"><a href="cas.html#cas-pt-client">22.3.3. Authenticating to a Stateless Service with CAS</a></span></dt><dd><dl><dt><span class="section"><a href="cas.html#cas-pt-client-config">Configuring CAS to Obtain Proxy Granting Tickets</a></span></dt><dt><span class="section"><a href="cas.html#cas-pt-client-sample">Calling a Stateless Service Using a Proxy Ticket</a></span></dt></dl></dd><dt><span class="section"><a href="cas.html#cas-pt">22.3.4. Proxy Ticket Authentication</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="x509.html">23. X.509 Authentication</a></span></dt><dd><dl><dt><span class="section"><a href="x509.html#x509-overview">23.1. Overview</a></span></dt><dt><span class="section"><a href="x509.html#d0e8013">23.2. Adding X.509 Authentication to Your Web Application</a></span></dt><dt><span class="section"><a href="x509.html#x509-ssl-config">23.3. Setting up SSL in Tomcat</a></span></dt></dl></dd><dt><span class="chapter"><a href="runas.html">24. Run-As Authentication Replacement</a></span></dt><dd><dl><dt><span class="section"><a href="runas.html#runas-overview">24.1. Overview</a></span></dt><dt><span class="section"><a href="runas.html#runas-config">24.2. Configuration</a></span></dt></dl></dd><dt><span class="chapter"><a href="crypto.html">25. Spring Security Crypto Module</a></span></dt><dd><dl><dt><span class="section"><a href="crypto.html#spring-security-crypto-introduction">25.1. Introduction</a></span></dt><dt><span class="section"><a href="crypto.html#spring-security-crypto-encryption">25.2. Encryptors</a></span></dt><dd><dl><dt><span class="section"><a href="crypto.html#spring-security-crypto-encryption-bytes">25.2.1. BytesEncryptor</a></span></dt><dt><span class="section"><a href="crypto.html#spring-security-crypto-encryption-text">25.2.2. TextEncryptor</a></span></dt></dl></dd><dt><span class="section"><a href="crypto.html#spring-security-crypto-keygenerators">25.3. Key Generators</a></span></dt><dd><dl><dt><span class="section"><a href="crypto.html#d0e8311">25.3.1. BytesKeyGenerator</a></span></dt><dt><span class="section"><a href="crypto.html#d0e8329">25.3.2. StringKeyGenerator</a></span></dt></dl></dd><dt><span class="section"><a href="crypto.html#spring-security-crypto-passwordencoders">25.4. Password Encoding</a></span></dt></dl></dd></dl></dd><dt><span class="appendix"><a href="appendix-schema.html">A. Security Database Schema</a></span></dt><dd><dl><dt><span class="section"><a href="appendix-schema.html#d0e8365">A.1. User Schema</a></span></dt><dd><dl><dt><span class="section"><a href="appendix-schema.html#d0e8378">A.1.1. Group Authorities</a></span></dt></dl></dd><dt><span class="section"><a href="appendix-schema.html#d0e8399">A.2. Persistent Login (Remember-Me) Schema</a></span></dt><dt><span class="section"><a href="appendix-schema.html#dbschema-acl">A.3. ACL Schema</a></span></dt><dd><dl><dt><span class="section"><a href="appendix-schema.html#d0e8463">A.3.1. Hypersonic SQL</a></span></dt><dt><span class="section"><a href="appendix-schema.html#d0e8470">A.3.2. PostgreSQL</a></span></dt></dl></dd></dl></dd><dt><span class="appendix"><a href="appendix-namespace.html">B. The Security Namespace</a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-web">B.1. Web Application Security</a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-debug">B.1.1. <code class="literal"><debug></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-http">B.1.2. <code class="literal"><http></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-http-attributes"><code class="literal"><http></code> Attributes</a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-http-children">Child Elements of <http></a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-access-denied-handler">B.1.3. <code class="literal"><access-denied-handler></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-access-denied-handler-parents">Parent Elements of <code class="literal"><access-denied-handler></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-access-denied-handler-attributes"><code class="literal"><access-denied-handler></code> Attributes</a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-anonymous">B.1.4. <code class="literal"><anonymous></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-anonymous-parents">Parent Elements of <code class="literal"><anonymous></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-anonymous-attributes"><code class="literal"><anonymous></code> Attributes</a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-custom-filter">B.1.5. <code class="literal"><custom-filter></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-custom-filter-parents">Parent Elements of <code class="literal"><custom-filter></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-custom-filter-attributes"><code class="literal"><custom-filter></code> Attributes</a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-expression-handler">B.1.6. <code class="literal"><expression-handler></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-expression-handler-parents">Parent Elements of <code class="literal"><expression-handler></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-expression-handler-attributes"><code class="literal"><expression-handler></code> Attributes</a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-form-login">B.1.7. <code class="literal"><form-login></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-form-login-parents">Parent Elements of <code class="literal"><form-login></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-form-login-attributes"><code class="literal"><form-login></code> Attributes</a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-http-basic">B.1.8. <code class="literal"><http-basic></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-http-basic-parents">Parent Elements of <code class="literal"><http-basic></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-http-basic-attributes"><code class="literal"><http-basic></code> Attributes</a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-http-firewall">B.1.9. <code class="literal"><http-firewall></code> Element</a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-http-firewall-attributes"><code class="literal"><http-firewall></code> Attributes</a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-intercept-url">B.1.10. <code class="literal"><intercept-url></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-intercept-url-parents">Parent Elements of <code class="literal"><intercept-url></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-intercept-url-attributes"><code class="literal"><intercept-url></code> Attributes</a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-jee">B.1.11. <code class="literal"><jee></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-jee-parents">Parent Elements of <code class="literal"><jee></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-jee-attributes"><code class="literal"><jee></code> Attributes</a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-logout">B.1.12. <code class="literal"><logout></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-logout-parents">Parent Elements of <code class="literal"><logout></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-logout-attributes"><code class="literal"><logout></code> Attributes</a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-openid-login">B.1.13. <code class="literal"><openid-login></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-openid-login-parents">Parent Elements of <code class="literal"><openid-login></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-openid-login-attributes"><code class="literal"><openid-login></code> Attributes</a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-openid-login-children">Child Elements of <openid-login></a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-attribute-exchange">B.1.14. <code class="literal"><attribute-exchange></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-attribute-exchange-parents">Parent Elements of <code class="literal"><attribute-exchange></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-attribute-exchange-attributes"><code class="literal"><attribute-exchange></code> Attributes</a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-attribute-exchange-children">Child Elements of <code class="literal"><attribute-exchange></code></a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-openid-attribute">B.1.15. <code class="literal"><openid-attribute></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-openid-attribute-parents">Parent Elements of <code class="literal"><openid-attribute></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-openid-attribute-attributes"><code class="literal"><openid-attribute></code> Attributes</a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-port-mappings">B.1.16. <code class="literal"><port-mappings></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-port-mappings-parents">Parent Elements of <code class="literal"><port-mappings></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-port-mappings-children">Child Elements of <code class="literal"><port-mappings></code></a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-port-mapping">B.1.17. <code class="literal"><port-mapping></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-port-mapping-parents">Parent Elements of <code class="literal"><port-mapping></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-port-mapping-attributes"><code class="literal"><port-mapping></code> Attributes</a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-remember-me">B.1.18. <code class="literal"><remember-me></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-remember-me-parents">Parent Elements of <code class="literal"><remember-me></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-remember-me-attributes"><code class="literal"><remember-me></code> Attributes</a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-request-cache">B.1.19. <code class="literal"><request-cache></code> Element</a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-request-cache-parents">Parent Elements of <code class="literal"><request-cache></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-request-cache-attributes"><code class="literal"><request-cache></code> Attributes</a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-session-management">B.1.20. <code class="literal"><session-management></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-session-management-parents">Parent Elements of <code class="literal"><session-management></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-session-management-attributes"><code class="literal"><session-management></code> Attributes</a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-session-management-children">Child elements of <code class="literal"><session-management></code></a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-concurrency-control">B.1.21. <code class="literal"><concurrency-control></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-concurrency-control-parents">Parent Elements of <code class="literal"><concurrency-control></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-concurrency-control-attributes"><code class="literal"><concurrency-control></code> Attributes</a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-x509">B.1.22. <code class="literal"><x509></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-x509-parents">Parent Elements of <code class="literal"><x509></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-x509-attributes"><code class="literal"><x509></code> Attributes</a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-filter-chain-map">B.1.23. <code class="literal"><filter-chain-map></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-filter-chain-map-attributes"><code class="literal"><filter-chain-map></code> Attributes</a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-filter-chain-map-children">Child Elements of <code class="literal"><filter-chain-map></code></a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-filter-chain">B.1.24. <code class="literal"><filter-chain></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-filter-chain-parents">Parent Elements of <code class="literal"><filter-chain></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-filter-chain-attributes"><code class="literal"><filter-chain></code> Attributes</a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-filter-invocation-definition-source">B.1.25. <code class="literal"><filter-invocation-definition-source></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-filter-invocation-definition-source-attributes"><code class="literal"><filter-invocation-definition-source></code> Attributes</a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-filter-invocation-definition-source-children">Child Elements of <code class="literal"><filter-invocation-definition-source></code></a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-filter-security-metadata-source">B.1.26. <code class="literal"><filter-security-metadata-source></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-filter-security-metadata-source-attributes"><code class="literal"><filter-security-metadata-source></code> Attributes</a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-filter-security-metadata-source-children">Child Elements of <code class="literal"><filter-security-metadata-source></code></a></span></dt></dl></dd></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-authentication">B.2. Authentication Services</a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-authentication-manager">B.2.1. <code class="literal"><authentication-manager></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-authentication-manager-attributes"><code class="literal"><authentication-manager></code> Attributes</a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-authentication-manager-children">Child Elements of <code class="literal"><authentication-manager></code></a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-authentication-provider">B.2.2. <code class="literal"><authentication-provider></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-authentication-provider-parents">Parent Elements of <code class="literal"><authentication-provider></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-authentication-provider-attributes"><code class="literal"><authentication-provider></code> Attributes</a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-authentication-provider-children">Child Elements of <code class="literal"><authentication-provider></code></a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-jdbc-user-service">B.2.3. <code class="literal"><jdbc-user-service></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-jdbc-user-service-attributes"><code class="literal"><jdbc-user-service></code> Attributes</a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-password-encoder">B.2.4. <code class="literal"><password-encoder></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-password-encoder-parents">Parent Elements of <code class="literal"><password-encoder></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-password-encoder-attributes"><code class="literal"><password-encoder></code> Attributes</a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-password-encoder-children">Child Elements of <code class="literal"><password-encoder></code></a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-salt-source">B.2.5. <code class="literal"><salt-source></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-salt-source-parents">Parent Elements of <code class="literal"><salt-source></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-salt-source-attributes"><code class="literal"><salt-source></code> Attributes</a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-user-service">B.2.6. <code class="literal"><user-service></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-user-service-attributes"><code class="literal"><user-service></code> Attributes</a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-user-service-children">Child Elements of <code class="literal"><user-service></code></a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-user">B.2.7. <code class="literal"><user></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-user-parents">Parent Elements of <code class="literal"><user></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-user-attributes"><code class="literal"><user></code> Attributes</a></span></dt></dl></dd></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-method-security">B.3. Method Security</a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-global-method-security">B.3.1. <code class="literal"><global-method-security></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-global-method-security-attributes"><code class="literal"><global-method-security></code> Attributes</a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-global-method-security-children">Child Elements of <code class="literal"><global-method-security></code></a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-after-invocation-provider">B.3.2. <code class="literal"><after-invocation-provider></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-after-invocation-provider-parents">Parent Elements of <code class="literal"><after-invocation-provider></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-after-invocation-provider-attributes"><code class="literal"><after-invocation-provider></code> Attributes</a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-pre-post-annotation-handling">B.3.3. <code class="literal"><pre-post-annotation-handling></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-pre-post-annotation-handling-parents">Parent Elements of <code class="literal"><pre-post-annotation-handling></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-pre-post-annotation-handling-children">Child Elements of <code class="literal"><pre-post-annotation-handling></code></a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-invocation-attribute-factory">B.3.4. <code class="literal"><invocation-attribute-factory></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-invocation-attribute-factory-parents">Parent Elements of <code class="literal"><invocation-attribute-factory></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-invocation-attribute-factory-attributes"><code class="literal"><invocation-attribute-factory></code> Attributes</a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-post-invocation-advice">B.3.5. <code class="literal"><post-invocation-advice></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-post-invocation-advice-parents">Parent Elements of <code class="literal"><post-invocation-advice></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-post-invocation-advice-attributes"><code class="literal"><post-invocation-advice></code> Attributes</a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-pre-invocation-advice">B.3.6. <code class="literal"><pre-invocation-advice></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-pre-invocation-advice-parents">Parent Elements of <code class="literal"><pre-invocation-advice></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-pre-invocation-advice-attributes"><code class="literal"><pre-invocation-advice></code> Attributes</a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-protect-pointcut">B.3.7. Securing Methods using <code class="literal"><protect-pointcut></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-protect-pointcut-parents">Parent Elements of <code class="literal"><protect-pointcut></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-protect-pointcut-attributes"><code class="literal"><protect-pointcut></code> Attributes</a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-intercept-methods">B.3.8. <code class="literal"><intercept-methods></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-intercept-methods-attributes"><code class="literal"><intercept-methods></code> Attributes</a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-intercept-methods-children">Child Elements of <code class="literal"><intercept-methods></code></a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-method-security-metadata-source">B.3.9. <code class="literal"><method-security-metadata-source></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-method-security-metadata-source-attributes"><code class="literal"><method-security-metadata-source></code> Attributes</a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-method-security-metadata-source-children">Child Elements of <code class="literal"><method-security-metadata-source></code></a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-protect">B.3.10. <code class="literal"><protect></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-protect-parents">Parent Elements of <code class="literal"><protect></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-protect-attributes"><code class="literal"><protect></code> Attributes</a></span></dt></dl></dd></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-ldap">B.4. LDAP Namespace Options</a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-ldap-server">B.4.1. Defining the LDAP Server using the <code class="literal"><ldap-server></code>
+ Element</a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-ldap-server-attributes"><code class="literal"><ldap-server></code> Attributes</a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-ldap-authentication-provider">B.4.2. <code class="literal"><ldap-authentication-provider></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-ldap-authentication-provider-parents">Parent Elements of <code class="literal"><ldap-authentication-provider></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-ldap-authentication-provider-attributes"><code class="literal"><ldap-authentication-provider></code> Attributes</a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-ldap-authentication-provider-children">Child Elements of <code class="literal"><ldap-authentication-provider></code></a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-password-compare">B.4.3. <code class="literal"><password-compare></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-password-compare-parents">Parent Elements of <code class="literal"><password-compare></code></a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-password-compare-attributes"><code class="literal"><password-compare></code> Attributes</a></span></dt><dt><span class="section"><a href="appendix-namespace.html#nsa-password-compare-children">Child Elements of <code class="literal"><password-compare></code></a></span></dt></dl></dd><dt><span class="section"><a href="appendix-namespace.html#nsa-ldap-user-service">B.4.4. <code class="literal"><ldap-user-service></code></a></span></dt><dd><dl><dt><span class="section"><a href="appendix-namespace.html#nsa-ldap-user-service-attributes"><code class="literal"><ldap-user-service></code> Attributes</a></span></dt></dl></dd></dl></dd></dl></dd><dt><span class="appendix"><a href="appendix-dependencies.html">C. Spring Security Dependencies</a></span></dt><dd><dl><dt><span class="section"><a href="appendix-dependencies.html#d0e11729">C.1. <code class="literal">spring-security-core</code></a></span></dt><dt><span class="section"><a href="appendix-dependencies.html#d0e11819">C.2. <code class="literal">spring-security-remoting</code></a></span></dt><dt><span class="section"><a href="appendix-dependencies.html#d0e11854">C.3. <code class="literal">spring-security-web</code></a></span></dt><dt><span class="section"><a href="appendix-dependencies.html#d0e11903">C.4. <code class="literal">spring-security-ldap</code></a></span></dt><dt><span class="section"><a href="appendix-dependencies.html#d0e11990">C.5. <code class="literal">spring-security-config</code></a></span></dt><dt><span class="section"><a href="appendix-dependencies.html#d0e12044">C.6. <code class="literal">spring-security-acl</code></a></span></dt><dt><span class="section"><a href="appendix-dependencies.html#d0e12094">C.7. <code class="literal">spring-security-cas</code></a></span></dt><dt><span class="section"><a href="appendix-dependencies.html#d0e12142">C.8. <code class="literal">spring-security-openid</code></a></span></dt><dt><span class="section"><a href="appendix-dependencies.html#d0e12196">C.9. <code class="literal">spring-security-taglibs</code></a></span></dt></dl></dd></dl></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
</script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="preface.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top"> </td><td width="20%" align="center"> </td><td width="40%" align="right" valign="top"> Preface</td></tr></table></div></body></html>
\ No newline at end of file
diff --git a/docs/reference/taglibs.html b/docs/reference/taglibs.html
index 984f0d3..2685cd2 100644
--- a/docs/reference/taglibs.html
+++ b/docs/reference/taglibs.html
@@ -1,6 +1,6 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>19. JSP Tag Libraries</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="advanced-topics.html" title="Part V. Additional Topics"><link rel="prev" href="ldap.html" title="18. LDAP Authentication"><link rel="next" href="jaas.html" title="20. Java Authentication and Authorization Service (JAAS) Provider"><!--Begin Google Analytics code--><script type="text/javascript">
+ <title>20. JSP Tag Libraries</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="advanced-topics.html" title="Part V. Additional Topics"><link rel="prev" href="ldap.html" title="19. LDAP Authentication"><link rel="next" href="jaas.html" title="21. Java Authentication and Authorization Service (JAAS) Provider"><!--Begin Google Analytics code--><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
@@ -8,35 +8,35 @@
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
- </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">19. JSP Tag Libraries</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ldap.html">Prev</a> </td><th width="60%" align="center">Part V. Additional Topics</th><td width="20%" align="right"> <a accesskey="n" href="jaas.html">Next</a></td></tr></table><hr></div><div class="chapter" title="19. JSP Tag Libraries"><div class="titlepage"><div><div><h2 class="title"><a name="taglibs"></a>19. JSP Tag Libraries</h2></div></div></div><p> Spring Security has its own taglib which provides basic support for accessing security
- information and applying security constraints in JSPs. </p><div class="section" title="19.1 Declaring the Taglib"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e6137"></a>19.1 Declaring the Taglib</h2></div></div></div><p>To use any of the tags, you must have the security taglib declared in your JSP:
+ </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">20. JSP Tag Libraries</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ldap.html">Prev</a> </td><th width="60%" align="center">Part V. Additional Topics</th><td width="20%" align="right"> <a accesskey="n" href="jaas.html">Next</a></td></tr></table><hr></div><div class="chapter" title="20. JSP Tag Libraries"><div class="titlepage"><div><div><h2 class="title"><a name="taglibs"></a>20. JSP Tag Libraries</h2></div></div></div><p> Spring Security has its own taglib which provides basic support for accessing security
+ information and applying security constraints in JSPs. </p><div class="section" title="20.1 Declaring the Taglib"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e6853"></a>20.1 Declaring the Taglib</h2></div></div></div><p>To use any of the tags, you must have the security taglib declared in your JSP:
</p><pre class="programlisting">
- <%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
-</pre></div><div class="section" title="19.2 The authorize Tag"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e6144"></a>19.2 The <code class="literal">authorize</code> Tag</h2></div></div></div><p> This tag is used to determine whether its contents should be evaluated or not. In
- Spring Security 3.0, it can be used in two ways <sup>[<a name="d0e6152" href="#ftn.d0e6152" class="footnote">15</a>]</sup>. The first approach uses a <a class="link" href="el-access.html#el-access-web" title="15.2 Web Security Expressions">web-security
- expression</a>, specified in the <code class="literal">access</code> attribute of the tag.
- The expression evaluation will be delegated to the
- <code class="interfacename">WebSecurityExpressionHandler</code> defined in the
- application context (you should have web expressions enabled in your
- <code class="literal"><http></code> namespace configuration to make sure this service is
- available). So, for example, you might
- have</p><pre class="programlisting"><sec:authorize access="hasRole('supervisor')">
+ <span class="hl-tag"><%@</span> <span class="hl-attribute">taglib</span> <span class="hl-attribute">prefix</span>=<span class="hl-value">"sec"</span> <span class="hl-attribute">uri</span>=<span class="hl-value">"http://www.springframework.org/security/tags"</span> <span class="hl-attribute">%></span>
+</pre></div><div class="section" title="20.2 The authorize Tag"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e6860"></a>20.2 The <code class="literal">authorize</code> Tag</h2></div></div></div><p> This tag is used to determine whether its contents should be evaluated or not. In
+ Spring Security 3.0, it can be used in two ways <sup>[<a name="d0e6868" href="#ftn.d0e6868" class="footnote">23</a>]</sup>. The first approach uses a <a class="link" href="el-access.html#el-access-web" title="16.2 Web Security Expressions">web-security
+ expression</a>, specified in the <code class="literal">access</code> attribute of the tag. The
+ expression evaluation will be delegated to the
+ <code class="interfacename">WebSecurityExpressionHandler</code> defined in the application
+ context (you should have web expressions enabled in your <code class="literal"><http></code>
+ namespace configuration to make sure this service is available). So, for example, you
+ might
+ have</p><pre class="programlisting"><span class="hl-tag"><sec:authorize</span> <span class="hl-attribute">access</span>=<span class="hl-value">"hasRole('supervisor')"</span><span class="hl-tag">></span>
This content will only be visible to users who have
-the "supervisor" authority in their list of <tt>GrantedAuthority</tt>s.
+the "supervisor" authority in their list of <span class="hl-tag"><tt></span>GrantedAuthority<span class="hl-tag"></tt></span>s.
-</sec:authorize></pre><p>A common requirement is to only show a particular link, if the user is actually
+<span class="hl-tag"></sec:authorize></span></pre><p>A common requirement is to only show a particular link, if the user is actually
allowed to click it. How can we determine in advance whether something will be allowed?
This tag can also operate in an alternative mode which allows you to define a particular
URL as an attribute. If the user is allowed to invoke that URL, then the tag body will
be evaluated, otherwise it will be skipped. So you might have something
- like</p><pre class="programlisting"><sec:authorize url="/admin">
+ like</p><pre class="programlisting"><span class="hl-tag"><sec:authorize</span> <span class="hl-attribute">url</span>=<span class="hl-value">"/admin"</span><span class="hl-tag">></span>
This content will only be visible to users who are authorized to send requests to the "/admin" URL.
-</sec:authorize></pre><p>To
+<span class="hl-tag"></sec:authorize></span></pre><p>To
use this tag there must also be an instance of
- <code class="interfacename">WebInvocationPrivilegeEvaluator</code> in your application
+ <code class="interfacename">WebInvocationPrivilegeEvaluator</code> in your application
context. If you are using the namespace, one will automatically be registered. This is
an instance of <code class="classname">DefaultWebInvocationPrivilegeEvaluator</code>, which
creates a dummy web request for the supplied URL and invokes the security interceptor to
@@ -45,37 +45,54 @@ This content will only be visible to users who are authorized to send requests t
within the <code class="literal"><http></code> namespace configuration and saves having to
duplicate the information (such as the required roles) within your JSPs. This approach
can also be combined with a <code class="literal">method</code> attribute, supplying the HTTP
- method, for a more specific match.</p></div><div class="section" title="19.3 The authenticationTag"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e6190"></a>19.3 The <code class="literal">authentication</code>Tag</h2></div></div></div><p>This tag allows access to the current <code class="interfacename">Authentication</code>
+ method, for a more specific match.</p><p>The boolean result of evaluating the tag (whether it grants or denies access) can be
+ stored in a page context scope variable by setting the <code class="literal">var</code> attribute
+ to the variable name, avoiding the need for duplicating and re-evaluating the condition
+ at other points in the page.</p><div class="section" title="20.2.1 Disabling Tag Authorization for Testing"><div class="titlepage"><div><div><h3 class="title"><a name="d0e6911"></a>20.2.1 Disabling Tag Authorization for Testing</h3></div></div></div><p>Hiding a link in a page for unauthorized users doesn't prevent them from accessing
+ the URL. They could just type it into their browser directly, for example. As part
+ of your testing process, you may want to reveal the hidden areas in order to check
+ that links really are secured at the back end. If you set the system property
+ <code class="literal">spring.security.disableUISecurity</code> to <code class="literal">true</code>,
+ the <code class="literal">authorize</code> tag will still run but will not hide its contents.
+ By default it will also surround the content with <code class="literal"><span
+ class="securityHiddenUI">...</span></code> tags. This allows you to
+ display <span class="quote">“<span class="quote">hidden</span>”</span> content with a particular CSS style such as a
+ different background colour. Try running the <span class="quote">“<span class="quote">tutorial</span>”</span> sample
+ application with this property enabled, for example.</p><p>You can also set the properties <code class="literal">spring.security.securedUIPrefix</code>
+ and <code class="literal">spring.security.securedUISuffix</code> if you want to change
+ surrounding text from the default <code class="literal">span</code> tags (or use empty strings
+ to remove it completely).</p></div></div><div class="section" title="20.3 The authenticationTag"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e6945"></a>20.3 The <code class="literal">authentication</code>Tag</h2></div></div></div><p>This tag allows access to the current <code class="interfacename">Authentication</code>
object stored in the security context. It renders a property of the object directly in
the JSP. So, for example, if the <code class="literal">principal</code> property of the
- <code class="interfacename">Authentication</code> is an instance of Spring Security's
- <code class="interfacename">UserDetails</code> object, then using
- <code class="literal"><sec:authentication property="principal.username" /></code> will
- render the name of the current user.</p><p>Of course, it isn't necessary to use JSP tags for this kind of thing and some people
+ <code class="interfacename">Authentication</code> is an instance of Spring Security's
+ <code class="interfacename">UserDetails</code> object, then using
+ <code class="literal"><sec:authentication property="principal.username" /></code> will render
+ the name of the current user.</p><p>Of course, it isn't necessary to use JSP tags for this kind of thing and some people
prefer to keep as little logic as possible in the view. You can access the
- <code class="interfacename">Authentication</code> object in your MVC controller (by
- calling <code class="code">SecurityContextHolder.getContext().getAuthentication()</code>) and add the
- data directly to your model for rendering by the view.</p></div><div class="section" title="19.4 The accesscontrollist Tag"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e6221"></a>19.4 The <code class="literal">accesscontrollist</code> Tag</h2></div></div></div><p>This tag is only valid when used with Spring Security's ACL module. It checks a
+ <code class="interfacename">Authentication</code> object in your MVC controller (by calling
+ <code class="code">SecurityContextHolder.getContext().getAuthentication()</code>) and add the data
+ directly to your model for rendering by the view.</p></div><div class="section" title="20.4 The accesscontrollist Tag"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e6976"></a>20.4 The <code class="literal">accesscontrollist</code> Tag</h2></div></div></div><p>This tag is only valid when used with Spring Security's ACL module. It checks a
comma-separated list of required permissions for a specified domain object. If the
current user has any of those permissions, then the tag body will be evaluated. If they
don't, it will be skipped. An example might
- be</p><pre class="programlisting"><sec:accesscontrollist hasPermission="1,2" domainObject="someObject">
+ be</p><pre class="programlisting"><span class="hl-tag"><sec:accesscontrollist</span> <span class="hl-attribute">hasPermission</span>=<span class="hl-value">"1,2"</span> <span class="hl-attribute">domainObject</span>=<span class="hl-value">"${someObject}"</span><span class="hl-tag">></span>
This will be shown if the user has either of the permissions
represented by the values "1" or "2" on the given object.
-</sec:accesscontrollist></pre><p>The permissions are passed to the <code class="interfacename">PermissionFactory</code>
+<span class="hl-tag"></sec:accesscontrollist></span></pre><p>The permissions are passed to the <code class="interfacename">PermissionFactory</code>
defined in the application context, converting them to ACL
- <code class="interfacename">Permission</code> instances, so they may be any format which
- is supported by the factory - they don't have to be integers, they could be strings like
- <code class="literal">READ</code> or <code class="literal">WRITE</code>. If no
- <code class="interfacename">PermissionFactory</code> is found, an instance of
- <code class="classname">DefaultPermissionFactory</code> will be used. The
- <code class="interfacename">AclService</code>from the application context will be used
- to load the <code class="interfacename">Acl</code> instance for the supplied object. The
- <code class="interfacename">Acl</code> will be invoked with the required permissions to
- check if any of them are granted.</p></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e6152" href="#d0e6152" class="para">15</a>] </sup>The legacy options from Spring Security 2.0 are also supported, but
- discouraged.</p></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
+ <code class="interfacename">Permission</code> instances, so they may be any format which is
+ supported by the factory - they don't have to be integers, they could be strings like
+ <code class="literal">READ</code> or <code class="literal">WRITE</code>. If no
+ <code class="interfacename">PermissionFactory</code> is found, an instance of
+ <code class="classname">DefaultPermissionFactory</code> will be used. The
+ <code class="interfacename">AclService</code>from the application context will be used to
+ load the <code class="interfacename">Acl</code> instance for the supplied object. The
+ <code class="interfacename">Acl</code> will be invoked with the required permissions to
+ check if any of them are granted.</p><p>This tag also supports the <code class="literal">var</code> attribute, in the same way as the
+ <code class="literal">authorize</code> tag.</p></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e6868" href="#d0e6868" class="para">23</a>] </sup>The legacy options from Spring Security 2.0 are also supported, but
+ discouraged.</p></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
- </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ldap.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="advanced-topics.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="jaas.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">18. LDAP Authentication </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 20. Java Authentication and Authorization Service (JAAS) Provider</td></tr></table></div></body></html>
\ No newline at end of file
+ </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ldap.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="advanced-topics.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="jaas.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">19. LDAP Authentication </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 21. Java Authentication and Authorization Service (JAAS) Provider</td></tr></table></div></body></html>
\ No newline at end of file
diff --git a/docs/reference/technical-overview.html b/docs/reference/technical-overview.html
index 2f038cb..2d05f9f 100644
--- a/docs/reference/technical-overview.html
+++ b/docs/reference/technical-overview.html
@@ -1,6 +1,6 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>5. Technical Overview</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="overall-architecture.html" title="Part II. Architecture and Implementation"><link rel="prev" href="overall-architecture.html" title="Part II. Architecture and Implementation"><link rel="next" href="core-services.html" title="6. Core Services"><!--Begin Google Analytics code--><script type="text/javascript">
+ <title>6. Technical Overview</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="overall-architecture.html" title="Part II. Architecture and Implementation"><link rel="prev" href="overall-architecture.html" title="Part II. Architecture and Implementation"><link rel="next" href="core-services.html" title="7. Core Services"><!--Begin Google Analytics code--><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
@@ -8,50 +8,52 @@
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
- </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">5. Technical Overview</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="overall-architecture.html">Prev</a> </td><th width="60%" align="center">Part II. Architecture and Implementation</th><td width="20%" align="right"> <a accesskey="n" href="core-services.html">Next</a></td></tr></table><hr></div><div class="chapter" title="5. Technical Overview"><div class="titlepage"><div><div><h1 class="title"><a name="technical-overview"></a>Technical Overview</h1></div></div></div><div class="section" title="5.1 Runtime Environment"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="runtime-environment"></a>5.1 Runtime Environment</h2></div></div></div><p>Spring Security 3.0 requires a Java 5.0 Runtime Environment or higher. As Spring Security
- aims to operate in a self-contained manner, there is no need to place any special
- configuration files into your Java Runtime Environment. In particular, there is no need to
- configure a special Java Authentication and Authorization Service (JAAS) policy file or place
- Spring Security into common classpath locations.</p><p>Similarly, if you are using an EJB Container or Servlet Container there is no need to put
- any special configuration files anywhere, nor include Spring Security in a server classloader.
- All the required files will be contained within your application.</p><p>This design offers maximum deployment time flexibility, as you can simply copy your target
- artifact (be it a JAR, WAR or EAR) from one system to another and it will immediately
- work.</p></div><div class="section" title="5.2 Core Components"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="core-components"></a>5.2 Core Components</h2></div></div></div><p>In Spring Security 3.0, the contents of the <code class="filename">spring-security-core</code> jar
- were stripped down to the bare minimum. It no longer contains any code related to
- web-application security, LDAP or namespace configuration. We'll take a look here at some of
- the Java types that you'll find in the core module. They represent the building blocks of the
- the framework, so if you ever need to go beyond a simple namespace configuration then it's
- important that you understand what they are, even if you don't actually need to interact with
- them directly.</p><div class="section" title="5.2.1 SecurityContextHolder, SecurityContext and Authentication Objects"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1518"></a>5.2.1 SecurityContextHolder, SecurityContext and Authentication Objects </h3></div></div></div><p>The most fundamental object is <code class="classname">SecurityContextHolder</code>. This is
- where we store details of the present security context of the application, which includes
- details of the principal currently using the application. By default the
- <code class="classname">SecurityContextHolder</code> uses a <code class="literal">ThreadLocal</code> to
- store these details, which means that the security context is always available to methods in
- the same thread of execution, even if the security context is not explicitly passed around
- as an argument to those methods. Using a <code class="literal">ThreadLocal</code> in this way is quite
- safe if care is taken to clear the thread after the present principal's request is
- processed. Of course, Spring Security takes care of this for you automatically so there is
- no need to worry about it.</p><p>Some applications aren't entirely suitable for using a <code class="literal">ThreadLocal</code>,
- because of the specific way they work with threads. For example, a Swing client might want
- all threads in a Java Virtual Machine to use the same security context.
- <code class="classname">SecurityContextHolder</code> can be configured with a strategy on startup
- to specify how you would like the context to be stored. For a standalone application you
- would use the <code class="literal">SecurityContextHolder.MODE_GLOBAL</code> strategy. Other
- applications might want to have threads spawned by the secure thread also assume the same
- security identity. This is achieved by using
- <code class="literal">SecurityContextHolder.MODE_INHERITABLETHREADLOCAL</code>. You can change the
- mode from the default <code class="literal">SecurityContextHolder.MODE_THREADLOCAL</code> in two ways.
- The first is to set a system property, the second is to call a static method on
- <code class="classname">SecurityContextHolder</code>. Most applications won't need to change from
- the default, but if you do, take a look at the JavaDocs for
- <code class="classname">SecurityContextHolder</code> to learn more.</p><div class="section" title="Obtaining information about the current user"><div class="titlepage"><div><div><h4 class="title"><a name="d0e1558"></a>Obtaining information about the current user</h4></div></div></div><p>Inside the <code class="classname">SecurityContextHolder</code> we store details of the
- principal currently interacting with the application. Spring Security uses an
- <code class="interfacename">Authentication</code> object to represent this information. You
- won't normally need to create an <code class="interfacename">Authentication</code> object
- yourself, but it is fairly common for users to query the
- <code class="interfacename">Authentication</code> object. You can use the following code
- block - from anywhere in your application - to obtain the name of the currently
- authenticated user, for example:</p><pre class="programlisting">
+ </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">6. Technical Overview</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="overall-architecture.html">Prev</a> </td><th width="60%" align="center">Part II. Architecture and Implementation</th><td width="20%" align="right"> <a accesskey="n" href="core-services.html">Next</a></td></tr></table><hr></div><div class="chapter" title="6. Technical Overview"><div class="titlepage"><div><div><h1 class="title"><a name="technical-overview"></a>Technical Overview</h1></div></div></div><div class="section" title="6.1 Runtime Environment"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="runtime-environment"></a>6.1 Runtime Environment</h2></div></div></div><p>Spring Security 3.0 requires a Java 5.0 Runtime Environment or higher. As Spring
+ Security aims to operate in a self-contained manner, there is no need to place any
+ special configuration files into your Java Runtime Environment. In particular, there is
+ no need to configure a special Java Authentication and Authorization Service (JAAS)
+ policy file or place Spring Security into common classpath locations.</p><p>Similarly, if you are using an EJB Container or Servlet Container there is no need to
+ put any special configuration files anywhere, nor include Spring Security in a server
+ classloader. All the required files will be contained within your application.</p><p>This design offers maximum deployment time flexibility, as you can simply copy your
+ target artifact (be it a JAR, WAR or EAR) from one system to another and it will
+ immediately work.</p></div><div class="section" title="6.2 Core Components"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="core-components"></a>6.2 Core Components</h2></div></div></div><p>In Spring Security 3.0, the contents of the <code class="filename">spring-security-core</code>
+ jar were stripped down to the bare minimum. It no longer contains any code related to
+ web-application security, LDAP or namespace configuration. We'll take a look here at
+ some of the Java types that you'll find in the core module. They represent the building
+ blocks of the the framework, so if you ever need to go beyond a simple namespace
+ configuration then it's important that you understand what they are, even if you don't
+ actually need to interact with them directly.</p><div class="section" title="6.2.1 SecurityContextHolder, SecurityContext and Authentication Objects"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1833"></a>6.2.1 SecurityContextHolder, SecurityContext and Authentication Objects </h3></div></div></div><p>The most fundamental object is <code class="classname">SecurityContextHolder</code>. This
+ is where we store details of the present security context of the application, which
+ includes details of the principal currently using the application. By default the
+ <code class="classname">SecurityContextHolder</code> uses a <code class="literal">ThreadLocal</code>
+ to store these details, which means that the security context is always available to
+ methods in the same thread of execution, even if the security context is not
+ explicitly passed around as an argument to those methods. Using a
+ <code class="literal">ThreadLocal</code> in this way is quite safe if care is taken to clear
+ the thread after the present principal's request is processed. Of course, Spring
+ Security takes care of this for you automatically so there is no need to worry about
+ it.</p><p>Some applications aren't entirely suitable for using a
+ <code class="literal">ThreadLocal</code>, because of the specific way they work with threads.
+ For example, a Swing client might want all threads in a Java Virtual Machine to use
+ the same security context. <code class="classname">SecurityContextHolder</code> can be
+ configured with a strategy on startup to specify how you would like the context to
+ be stored. For a standalone application you would use the
+ <code class="literal">SecurityContextHolder.MODE_GLOBAL</code> strategy. Other applications
+ might want to have threads spawned by the secure thread also assume the same
+ security identity. This is achieved by using
+ <code class="literal">SecurityContextHolder.MODE_INHERITABLETHREADLOCAL</code>. You can change
+ the mode from the default <code class="literal">SecurityContextHolder.MODE_THREADLOCAL</code>
+ in two ways. The first is to set a system property, the second is to call a static
+ method on <code class="classname">SecurityContextHolder</code>. Most applications won't need
+ to change from the default, but if you do, take a look at the JavaDocs for
+ <code class="classname">SecurityContextHolder</code> to learn more.</p><div class="section" title="Obtaining information about the current user"><div class="titlepage"><div><div><h4 class="title"><a name="d0e1873"></a>Obtaining information about the current user</h4></div></div></div><p>Inside the <code class="classname">SecurityContextHolder</code> we store details of
+ the principal currently interacting with the application. Spring Security uses
+ an <code class="interfacename">Authentication</code> object to represent this
+ information. You won't normally need to create an
+ <code class="interfacename">Authentication</code> object yourself, but it is fairly
+ common for users to query the <code class="interfacename">Authentication</code>
+ object. You can use the following code block - from anywhere in your application
+ - to obtain the name of the currently authenticated user, for example:</p><pre class="programlisting">
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
<span class="hl-keyword">if</span> (principal <span class="hl-keyword">instanceof</span> UserDetails) {
@@ -59,100 +61,106 @@ Object principal = SecurityContextHolder.getContext().getAuthentication().getPri
} <span class="hl-keyword">else</span> {
String username = principal.toString();
}</pre><p>The object returned by the call to <code class="methodname">getContext()</code> is an
- instance of the <code class="interfacename">SecurityContext</code> interface. This is the
- object that is kept in thread-local storage. As we'll see below, most authentication
- mechanisms withing Spring Security return an instance of
- <code class="interfacename">UserDetails</code> as the principal. </p></div></div><div class="section" title="5.2.2 The UserDetailsService"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1588"></a>5.2.2 The UserDetailsService</h3></div></div></div><p>Another item to note from the above code fragment is that you can obtain a principal
- from the <code class="interfacename">Authentication</code> object. The principal is just an
- <code class="literal">Object</code>. Most of the time this can be cast into a
- <code class="interfacename">UserDetails</code> object.
- <code class="interfacename">UserDetails</code> is a central interface in Spring Security. It
- represents a principal, but in an extensible and application-specific way. Think of
- <code class="interfacename">UserDetails</code> as the adapter between your own user database
- and what Spring Security needs inside the <code class="classname">SecurityContextHolder</code>.
- Being a representation of something from your own user database, quite often you will cast
- the <code class="interfacename">UserDetails</code> to the original object that your application
- provided, so you can call business-specific methods (like <code class="literal">getEmail()</code>,
- <code class="literal">getEmployeeNumber()</code> and so on).</p><p>By now you're probably wondering, so when do I provide a
- <code class="interfacename">UserDetails</code> object? How do I do that? I thought you said
- this thing was declarative and I didn't need to write any Java code - what gives? The short
- answer is that there is a special interface called
- <code class="interfacename">UserDetailsService</code>. The only method on this interface
- accepts a <code class="literal">String</code>-based username argument and returns a
- <code class="interfacename">UserDetails</code>:
- </p><pre class="programlisting">
+ instance of the <code class="interfacename">SecurityContext</code> interface. This
+ is the object that is kept in thread-local storage. As we'll see below, most
+ authentication mechanisms withing Spring Security return an instance of
+ <code class="interfacename">UserDetails</code> as the principal. </p></div></div><div class="section" title="6.2.2 The UserDetailsService"><div class="titlepage"><div><div><h3 class="title"><a name="tech-userdetailsservice"></a>6.2.2 The UserDetailsService</h3></div></div></div><p>Another item to note from the above code fragment is that you can obtain a
+ principal from the <code class="interfacename">Authentication</code> object. The
+ principal is just an <code class="literal">Object</code>. Most of the time this can be cast
+ into a <code class="interfacename">UserDetails</code> object.
+ <code class="interfacename">UserDetails</code> is a core interface in Spring
+ Security. It represents a principal, but in an extensible and application-specific
+ way. Think of <code class="interfacename">UserDetails</code> as the adapter between your
+ own user database and what Spring Security needs inside the
+ <code class="classname">SecurityContextHolder</code>. Being a representation of something
+ from your own user database, quite often you will cast the
+ <code class="interfacename">UserDetails</code> to the original object that your
+ application provided, so you can call business-specific methods (like
+ <code class="literal">getEmail()</code>, <code class="literal">getEmployeeNumber()</code> and so
+ on).</p><p>By now you're probably wondering, so when do I provide a
+ <code class="interfacename">UserDetails</code> object? How do I do that? I thought you
+ said this thing was declarative and I didn't need to write any Java code - what
+ gives? The short answer is that there is a special interface called
+ <code class="interfacename">UserDetailsService</code>. The only method on this interface
+ accepts a <code class="literal">String</code>-based username argument and returns a
+ <code class="interfacename">UserDetails</code>:
+ </p><pre class="programlisting">
UserDetails loadUserByUsername(String username) <span class="hl-keyword">throws</span> UsernameNotFoundException;
</pre><p>
- This is the most common approach to loading information for a user within Spring Security
- and you will see it used throughout the framework whenever information on a user is
- required.</p><p> On successful authentication, <code class="interfacename">UserDetails</code> is used to
- build the <code class="interfacename">Authentication</code> object that is stored in the
- <code class="classname">SecurityContextHolder</code> (more on this <a class="link" href="technical-overview.html#tech-intro-authentication" title="5.3 Authentication">below</a>). The good news is that we provide a
- number of <code class="interfacename">UserDetailsService</code> implementations, including one
- that uses an in-memory map (<code class="classname">InMemoryDaoImpl</code>) and another that uses
- JDBC (<code class="classname">JdbcDaoImpl</code>). Most users tend to write their own, though, with
- their implementations often simply sitting on top of an existing Data Access Object (DAO)
- that represents their employees, customers, or other users of the application. Remember the
- advantage that whatever your <code class="interfacename">UserDetailsService</code> returns can
- always be obtained from the <code class="classname">SecurityContextHolder</code> using the above
- code fragment. </p></div><div class="section" title="5.2.3 GrantedAuthority"><div class="titlepage"><div><div><h3 class="title"><a name="tech-granted-authority"></a>5.2.3 GrantedAuthority</h3></div></div></div><p>Besides the principal, another important method provided by
- <code class="interfacename">Authentication</code> is <code class="literal">getAuthorities(</code>). This
- method provides an array of <code class="interfacename">GrantedAuthority</code> objects. A
- <code class="interfacename">GrantedAuthority</code> is, not surprisingly, an authority that is
- granted to the principal. Such authorities are usually <span class="quote">“<span class="quote">roles</span>”</span>, such as
- <code class="literal">ROLE_ADMINISTRATOR</code> or <code class="literal">ROLE_HR_SUPERVISOR</code>. These
- roles are later on configured for web authorization, method authorization and domain object
- authorization. Other parts of Spring Security are capable of interpreting these authorities,
- and expect them to be present. <code class="interfacename">GrantedAuthority</code> objects are
- usually loaded by the <code class="interfacename">UserDetailsService</code>.</p><p>Usually the <code class="interfacename">GrantedAuthority</code> objects are application-wide
- permissions. They are not specific to a given domain object. Thus, you wouldn't likely have
- a <code class="interfacename">GrantedAuthority</code> to represent a permission to
- <code class="literal">Employee</code> object number 54, because if there are thousands of such
- authorities you would quickly run out of memory (or, at the very least, cause the
- application to take a long time to authenticate a user). Of course, Spring Security is
- expressly designed to handle this common requirement, but you'd instead use the project's
- domain object security capabilities for this purpose.</p></div><div class="section" title="5.2.4 Summary"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1709"></a>5.2.4 Summary</h3></div></div></div><p>Just to recap, the major building blocks of Spring Security that we've seen so far
- are:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc" compact><li class="listitem"><p><code class="classname">SecurityContextHolder</code>, to provide access to the
- <code class="interfacename">SecurityContext</code>.</p></li><li class="listitem"><p><code class="interfacename">SecurityContext</code>, to hold the
- <code class="interfacename">Authentication</code> and possibly request-specific security
- information.</p></li><li class="listitem"><p><code class="interfacename">Authentication</code>, to represent the principal in a
- Spring Security-specific manner.</p></li><li class="listitem"><p><code class="interfacename">GrantedAuthority</code>, to reflect the application-wide
- permissions granted to a principal.</p></li><li class="listitem"><p><code class="interfacename">UserDetails</code>, to provide the necessary information to
- build an Authentication object from your application's DAOs or other source source of
- security data.</p></li><li class="listitem"><p><code class="interfacename">UserDetailsService</code>, to create a
- <code class="interfacename">UserDetails</code> when passed in a
- <code class="literal">String</code>-based username (or certificate ID or the like).</p></li></ul></div><p>Now that you've gained an understanding of these repeatedly-used components, let's take
- a closer look at the process of authentication.</p></div></div><div class="section" title="5.3 Authentication"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="tech-intro-authentication"></a>5.3 Authentication</h2></div></div></div><p>Spring Security can participate in many different authentication environments. While we
- recommend people use Spring Security for authentication and not integrate with existing
- Container Managed Authentication, it is nevertheless supported - as is integrating with your
- own proprietary authentication system. </p><div class="section" title="5.3.1 What is authentication in Spring Security?"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1765"></a>5.3.1 What is authentication in Spring Security?</h3></div></div></div><p> Let's consider a standard authentication scenario that everyone is familiar with.
- </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>A user is prompted to log in with a username and
- password.</p></li><li class="listitem"><p>The system (successfully) verifies that the
- password is correct for the username.</p></li><li class="listitem"><p>The context
- information for that user is obtained (their list of roles and so
- on).</p></li><li class="listitem"><p>A security context is established for the
- user</p></li><li class="listitem"><p>The user proceeds, potentially to perform some
- operation which is potentially protected by an access control mechanism which checks
- the required permissions for the operation against the current security context
- information. </p></li></ol></div><p> The first three items constitute the
- authentication process so we'll take a look at how these take place within Spring
- Security.</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>The username and password are obtained and
- combined into an instance of
- <code class="classname">UsernamePasswordAuthenticationToken</code> (an instance of the
- <code class="interfacename">Authentication</code> interface, which we saw
- earlier).</p></li><li class="listitem"><p>The token is passed to an instance of
- <code class="interfacename">AuthenticationManager</code> for
- validation.</p></li><li class="listitem"><p>The
- <code class="interfacename">AuthenticationManager</code> returns a fully populated
- <code class="interfacename">Authentication</code> instance on successful
- authentication.</p></li><li class="listitem"><p>The security context is established
- by calling <code class="code">SecurityContextHolder.getContext().setAuthentication(...)</code>,
- passing in the returned authentication object.</p></li></ol></div><p>From
- that point on, the user is considered to be authenticated. Let's look at some code as an
- example.
- </p><pre class="programlisting"><span class="hl-keyword">import</span> org.springframework.security.authentication.*;
+ This is the most common approach to loading information for a user within Spring
+ Security and you will see it used throughout the framework whenever information on a
+ user is required.</p><p> On successful authentication, <code class="interfacename">UserDetails</code> is used
+ to build the <code class="interfacename">Authentication</code> object that is stored in
+ the <code class="classname">SecurityContextHolder</code> (more on this <a class="link" href="technical-overview.html#tech-intro-authentication" title="6.3 Authentication">below</a>). The good news is that we
+ provide a number of <code class="interfacename">UserDetailsService</code>
+ implementations, including one that uses an in-memory map
+ (<code class="classname">InMemoryDaoImpl</code>) and another that uses JDBC
+ (<code class="classname">JdbcDaoImpl</code>). Most users tend to write their own, though,
+ with their implementations often simply sitting on top of an existing Data Access
+ Object (DAO) that represents their employees, customers, or other users of the
+ application. Remember the advantage that whatever your
+ <code class="interfacename">UserDetailsService</code> returns can always be obtained
+ from the <code class="classname">SecurityContextHolder</code> using the above code fragment.
+ </p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>There is often some confusion about <code class="interfacename">UserDetailsService</code>.
+ It is purely a DAO for user data and performs no other function other than to supply that data
+ to other components within the framework. In particular, it <span class="emphasis"><em>does not</em></span>
+ authenticate the user, which is done by the <code class="interfacename">AuthenticationManager</code>.
+ In many cases it makes more sense to
+ <a class="link" href="core-services.html#core-services-authentication-manager" title="7.1 The AuthenticationManager, ProviderManager and AuthenticationProviders">implement <code class="interfacename">AuthenticationProvider</code></a>
+ directly if you require a custom authentication process.
+ </p></td></tr></table></div></div><div class="section" title="6.2.3 GrantedAuthority"><div class="titlepage"><div><div><h3 class="title"><a name="tech-granted-authority"></a>6.2.3 GrantedAuthority</h3></div></div></div><p>Besides the principal, another important method provided by
+ <code class="interfacename">Authentication</code> is
+ <code class="literal">getAuthorities(</code>). This method provides an array of
+ <code class="interfacename">GrantedAuthority</code> objects. A
+ <code class="interfacename">GrantedAuthority</code> is, not surprisingly, an authority
+ that is granted to the principal. Such authorities are usually <span class="quote">“<span class="quote">roles</span>”</span>,
+ such as <code class="literal">ROLE_ADMINISTRATOR</code> or
+ <code class="literal">ROLE_HR_SUPERVISOR</code>. These roles are later on configured for web
+ authorization, method authorization and domain object authorization. Other parts of
+ Spring Security are capable of interpreting these authorities, and expect them to be
+ present. <code class="interfacename">GrantedAuthority</code> objects are usually loaded
+ by the <code class="interfacename">UserDetailsService</code>.</p><p>Usually the <code class="interfacename">GrantedAuthority</code> objects are
+ application-wide permissions. They are not specific to a given domain object. Thus,
+ you wouldn't likely have a <code class="interfacename">GrantedAuthority</code> to
+ represent a permission to <code class="literal">Employee</code> object number 54, because if
+ there are thousands of such authorities you would quickly run out of memory (or, at
+ the very least, cause the application to take a long time to authenticate a user).
+ Of course, Spring Security is expressly designed to handle this common requirement,
+ but you'd instead use the project's domain object security capabilities for this
+ purpose.</p></div><div class="section" title="6.2.4 Summary"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2041"></a>6.2.4 Summary</h3></div></div></div><p>Just to recap, the major building blocks of Spring Security that we've seen so far
+ are:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc" compact><li class="listitem"><p><code class="classname">SecurityContextHolder</code>, to provide access to the
+ <code class="interfacename">SecurityContext</code>.</p></li><li class="listitem"><p><code class="interfacename">SecurityContext</code>, to hold the
+ <code class="interfacename">Authentication</code> and possibly request-specific
+ security information.</p></li><li class="listitem"><p><code class="interfacename">Authentication</code>, to represent the principal
+ in a Spring Security-specific manner.</p></li><li class="listitem"><p><code class="interfacename">GrantedAuthority</code>, to reflect the
+ application-wide permissions granted to a principal.</p></li><li class="listitem"><p><code class="interfacename">UserDetails</code>, to provide the necessary
+ information to build an Authentication object from your application's DAOs
+ or other source source of security data.</p></li><li class="listitem"><p><code class="interfacename">UserDetailsService</code>, to create a
+ <code class="interfacename">UserDetails</code> when passed in a
+ <code class="literal">String</code>-based username (or certificate ID or the
+ like).</p></li></ul></div><p>Now that you've gained an understanding of these repeatedly-used components, let's
+ take a closer look at the process of authentication.</p></div></div><div class="section" title="6.3 Authentication"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="tech-intro-authentication"></a>6.3 Authentication</h2></div></div></div><p>Spring Security can participate in many different authentication environments. While
+ we recommend people use Spring Security for authentication and not integrate with
+ existing Container Managed Authentication, it is nevertheless supported - as is
+ integrating with your own proprietary authentication system. </p><div class="section" title="6.3.1 What is authentication in Spring Security?"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2097"></a>6.3.1 What is authentication in Spring Security?</h3></div></div></div><p> Let's consider a standard authentication scenario that everyone is familiar with. </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>A user is prompted to log in with a username and password.</p></li><li class="listitem"><p>The system (successfully) verifies that the password is correct for the
+ username.</p></li><li class="listitem"><p>The context information for that user is obtained (their list of roles and
+ so on).</p></li><li class="listitem"><p>A security context is established for the user</p></li><li class="listitem"><p>The user proceeds, potentially to perform some operation which is
+ potentially protected by an access control mechanism which checks the
+ required permissions for the operation against the current security context
+ information. </p></li></ol></div><p> The first three items constitute the authentication process so we'll
+ take a look at how these take place within Spring Security.</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>The username and password are obtained and combined into an instance of
+ <code class="classname">UsernamePasswordAuthenticationToken</code> (an instance of
+ the <code class="interfacename">Authentication</code> interface, which we saw
+ earlier).</p></li><li class="listitem"><p>The token is passed to an instance of
+ <code class="interfacename">AuthenticationManager</code> for validation.</p></li><li class="listitem"><p>The <code class="interfacename">AuthenticationManager</code> returns a fully
+ populated <code class="interfacename">Authentication</code> instance on
+ successful authentication.</p></li><li class="listitem"><p>The security context is established by calling
+ <code class="code">SecurityContextHolder.getContext().setAuthentication(...)</code>,
+ passing in the returned authentication object.</p></li></ol></div><p>From that point on, the user is considered to be authenticated. Let's
+ look at some code as an example.
+ </p><pre class="programlisting"><span class="hl-keyword">import</span> org.springframework.security.authentication.*;
<span class="hl-keyword">import</span> org.springframework.security.core.*;
-<span class="hl-keyword">import</span> org.springframework.security.core.authority.GrantedAuthorityImpl;
+<span class="hl-keyword">import</span> org.springframework.security.core.authority.SimpleGrantedAuthority;
<span class="hl-keyword">import</span> org.springframework.security.core.context.SecurityContextHolder;
<span class="hl-keyword">public</span> <span class="hl-keyword">class</span> AuthenticationExample {
@@ -184,7 +192,7 @@ Object principal = SecurityContextHolder.getContext().getAuthentication().getPri
<span class="hl-keyword">static</span> <span class="hl-keyword">final</span> List<GrantedAuthority> AUTHORITIES = <span class="hl-keyword">new</span> ArrayList<GrantedAuthority>();
<span class="hl-keyword">static</span> {
- AUTHORITIES.add(<span class="hl-keyword">new</span> GrantedAuthorityImpl(<span class="hl-string">"ROLE_USER"</span>));
+ AUTHORITIES.add(<span class="hl-keyword">new</span> SimpleGrantedAuthority(<span class="hl-string">"ROLE_USER"</span>));
}
<span class="hl-keyword">public</span> Authentication authenticate(Authentication auth) <span class="hl-keyword">throws</span> AuthenticationException {
@@ -195,11 +203,12 @@ Object principal = SecurityContextHolder.getContext().getAuthentication().getPri
<span class="hl-keyword">throw</span> <span class="hl-keyword">new</span> BadCredentialsException(<span class="hl-string">"Bad Credentials"</span>);
}
}</pre><p>Here
- we have written a little program that asks the user to enter a username and password and
- performs the above sequence. The <code class="interfacename">AuthenticationManager</code> which
- we've implemented here will authenticate any user whose username and password are the same.
- It assigns a single role to every user. The output from the above will be something
- like:</p><pre class="programlisting">
+ we have written a little program that asks the user to enter a username and password
+ and performs the above sequence. The
+ <code class="interfacename">AuthenticationManager</code> which we've implemented here
+ will authenticate any user whose username and password are the same. It assigns a
+ single role to every user. The output from the above will be something
+ like:</p><pre class="programlisting">
Please enter your username:
bob
Please enter your password:
@@ -214,240 +223,274 @@ Successfully authenticated. Security context contains: \
Principal: bob; Password: [PROTECTED]; \
Authenticated: true; Details: null; \
Granted Authorities: ROLE_USER
- </pre><p>Note that you don't normally need to write any code like this. The process will normally
- occur internally, in a web authentication filter for example. We've just included the code
- here to show that the question of what actually constitutes authentication in Spring
- Security has quite a simple answer. A user is authenticated when the
- <code class="classname">SecurityContextHolder</code> contains a fully populated
- <code class="interfacename">Authentication</code> object.</p></div><div class="section" title="5.3.2 Setting the SecurityContextHolder Contents Directly"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1835"></a>5.3.2 Setting the SecurityContextHolder Contents Directly</h3></div></div></div><p>In fact, Spring Security doesn't mind how you put the
- <code class="interfacename">Authentication</code> object inside the
- <code class="classname">SecurityContextHolder</code>. The only critical requirement is that the
- <code class="classname">SecurityContextHolder</code> contains an
- <code class="interfacename">Authentication</code> which represents a principal before the
- <code class="classname">AbstractSecurityInterceptor</code> (which we'll see more about later)
- needs to authorize a user operation.</p><p>You can (and many users do) write their own filters or MVC controllers to provide
- interoperability with authentication systems that are not based on Spring Security. For
- example, you might be using Container-Managed Authentication which makes the current user
- available from a ThreadLocal or JNDI location. Or you might work for a company that has a
- legacy proprietary authentication system, which is a corporate "standard" over which you
- have little control. In situations like this it's quite easy to get Spring Security to work,
- and still provide authorization capabilities. All you need to do is write a filter (or
- equivalent) that reads the third-party user information from a location, build a Spring
- Security-specific <code class="interfacename">Authentication</code> object, and put it into the
- <code class="classname">SecurityContextHolder</code>.</p><p> If you're wondering how the <code class="interfacename">AuthenticationManager</code>
- manager is implemented in a real world example, we'll look at that in the <a class="link" href="core-services.html#core-services-authentication-manager" title="6.1 The AuthenticationManager, ProviderManager and AuthenticationProviders">core services chapter</a>.</p></div></div><div class="section" title="5.4 Authentication in a Web Application"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="tech-intro-web-authentication"></a>5.4 Authentication in a Web Application</h2></div></div></div><p> Now let's explore the situation where you are using Spring Security in a web application
- (without <code class="filename">web.xml</code> security enabled). How is a user authenticated and the
- security context established?</p><p>Consider a typical web application's authentication process:</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>You visit the home page, and click on a link.</p></li><li class="listitem"><p>A request goes to the server, and the server decides that you've asked for a protected
- resource.</p></li><li class="listitem"><p>As you're not presently authenticated, the server sends back a response indicating
- that you must authenticate. The response will either be an HTTP response code, or a
- redirect to a particular web page.</p></li><li class="listitem"><p>Depending on the authentication mechanism, your browser will either redirect to the
- specific web page so that you can fill out the form, or the browser will somehow retrieve
- your identity (via a BASIC authentication dialogue box, a cookie, a X.509 certificate
- etc.).</p></li><li class="listitem"><p>The browser will send back a response to the server. This will either be an HTTP POST
- containing the contents of the form that you filled out, or an HTTP header containing your
- authentication details.</p></li><li class="listitem"><p>Next the server will decide whether or not the presented credentials are valid. If
- they're valid, the next step will happen. If they're invalid, usually your browser will be
- asked to try again (so you return to step two above).</p></li><li class="listitem"><p>The original request that you made to cause the authentication process will be
- retried. Hopefully you've authenticated with sufficient granted authorities to access the
- protected resource. If you have sufficient access, the request will be successful.
- Otherwise, you'll receive back an HTTP error code 403, which means "forbidden".</p></li></ol></div><p>Spring Security has distinct classes responsible for most of the steps described above.
- The main participants (in the order that they are used) are the
- <code class="classname">ExceptionTranslationFilter</code>, an
- <code class="interfacename">AuthenticationEntryPoint</code> and an <span class="quote">“<span class="quote">authentication
- mechanism</span>”</span>, which is responsible for calling the
- <code class="classname">AuthenticationManager</code> which we saw in the previous section.</p><div class="section" title="5.4.1 ExceptionTranslationFilter"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1917"></a>5.4.1 ExceptionTranslationFilter</h3></div></div></div><p><code class="classname">ExceptionTranslationFilter</code> is a Spring Security filter that has
- responsibility for detecting any Spring Security exceptions that are thrown. Such exceptions
- will generally be thrown by an <code class="classname">AbstractSecurityInterceptor</code>, which is
- the main provider of authorization services. We will discuss
- <code class="classname">AbstractSecurityInterceptor</code> in the next section, but for now we
- just need to know that it produces Java exceptions and knows nothing about HTTP or how to go
- about authenticating a principal. Instead the
- <code class="classname">ExceptionTranslationFilter</code> offers this service, with specific
- responsibility for either returning error code 403 (if the principal has been authenticated
- and therefore simply lacks sufficient access - as per step seven above), or launching an
- <code class="interfacename">AuthenticationEntryPoint</code> (if the principal has not been
- authenticated and therefore we need to go commence step three).</p></div><div class="section" title="5.4.2 AuthenticationEntryPoint"><div class="titlepage"><div><div><h3 class="title"><a name="tech-intro-auth-entry-point"></a>5.4.2 AuthenticationEntryPoint</h3></div></div></div><p>The <code class="interfacename">AuthenticationEntryPoint</code> is responsible for step
- three in the above list. As you can imagine, each web application will have a default
- authentication strategy (well, this can be configured like nearly everything else in Spring
- Security, but let's keep it simple for now). Each major authentication system will have its
- own <code class="interfacename">AuthenticationEntryPoint</code> implementation, which typically
- performs one of the actions described in step 3.</p></div><div class="section" title="5.4.3 Authentication Mechanism"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1947"></a>5.4.3 Authentication Mechanism</h3></div></div></div><p>Once your browser submits your authentication credentials (either as an HTTP form post
- or HTTP header) there needs to be something on the server that <span class="quote">“<span class="quote">collects</span>”</span> these
- authentication details. By now we're at step six in the above list. In Spring Security we
- have a special name for the function of collecting authentication details from a user agent
- (usually a web browser), referring to it as the <span class="quote">“<span class="quote">authentication mechanism</span>”</span>.
- Examples are form-base login and Basic authentication. Once the authentication details have
- been collected from the user agent, an <code class="interfacename">Authentication</code>
- <span class="quote">“<span class="quote">request</span>”</span> object is built and then presented to the
- <code class="interfacename">AuthenticationManager</code>.</p><p>After the authentication mechanism receives back the fully-populated
- <code class="interfacename">Authentication</code> object, it will deem the request valid, put
- the <code class="interfacename">Authentication</code> into the
- <code class="classname">SecurityContextHolder</code>, and cause the original request to be retried
- (step seven above). If, on the other hand, the <code class="classname">AuthenticationManager</code>
- rejected the request, the authentication mechanism will ask the user agent to retry (step
- two above).</p></div><div class="section" title="5.4.4 Storing the SecurityContext between requests"><div class="titlepage"><div><div><h3 class="title"><a name="tech-intro-sec-context-persistence"></a>5.4.4 Storing the <code class="interfacename">SecurityContext</code> between requests</h3></div></div></div><p>Depending on the type of application, there may need to be a strategy in place to store
- the security context between user operations. In a typical web application, a user logs in
- once and is subsequently identified by their session Id. The server caches the principal
- information for the duration session. In Spring Security, the responsibility for storing the
- <code class="interfacename">SecurityContext</code> between requests falls to the
- <code class="classname">SecurityContextPersistenceFilter</code>, which by default stores the
- context as an <code class="literal">HttpSession</code> attribute between HTTP requests. It restores
- the context to the <code class="classname">SecurityContextHolder</code> for each request and,
- crucially, clears the <code class="classname">SecurityContextHolder</code> when the request
- completes. You shouldn't interact directly with the <code class="literal">HttpSession</code> for
- security purposes. There is simply no justification for doing so - always use the
- <code class="classname">SecurityContextHolder</code> instead. </p><p> Many other types of application (for example, a stateless RESTful web service) do not
- use HTTP sessions and will re-authenticate on every request. However, it is still important
- that the <code class="classname">SecurityContextPersistenceFilter</code> is included in the chain to
- make sure that the <code class="classname">SecurityContextHolder</code> is cleared after each
- request.</p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>In an application which receives concurrent requests in a single session, the same
- <code class="interfacename">SecurityContext</code> instance will be shared between threads.
- Even though a <code class="classname">ThreadLocal</code> is being used, it is the same instance
- that is retrieved from the <code class="interfacename">HttpSession</code> for each thread.
- This has implications if you wish to temporarily change the context under which a thread
- is running. If you just use
- <code class="code">SecurityContextHolder.getContext().setAuthentication(anAuthentication)</code>,
- then the <code class="interfacename">Authentication</code> object will change in
- <span class="emphasis"><em>all</em></span> concurrent threads which share the same
- <code class="interfacename">SecurityContext</code> instance. You can customize the behaviour
- of <code class="classname">SecurityContextPersistenceFilter</code> to create a completely new
- <code class="interfacename">SecurityContext</code> for each request, preventing changes in
- one thread from affecting another. Alternatively you can create a new instance just at the
- point where you temporarily change the context. The method
- <code class="code">SecurityContextHolder.createEmptyContext()</code> always returns a new context
- instance.</p></td></tr></table></div></div></div><div class="section" title="5.5 Access-Control (Authorization) in Spring Security"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="tech-intro-access-control"></a>5.5 Access-Control (Authorization) in Spring Security</h2></div></div></div><p> The main interface responsible for making access-control decisions in Spring Security is
- the <code class="interfacename">AccessDecisionManager</code>. It has a
- <code class="methodname">decide</code> method which takes an
- <code class="interfacename">Authentication</code> object representing the principal requesting
- access, a <span class="quote">“<span class="quote">secure object</span>”</span> (see below) and a list of security metadata attributes
- which apply for the object (such as a list of roles which are required for access to be
- granted). </p><div class="section" title="5.5.1 Security and AOP Advice"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2068"></a>5.5.1 Security and AOP Advice</h3></div></div></div><p>If you're familiar with AOP, you'd be aware there are different types of advice
- available: before, after, throws and around. An around advice is very useful, because an
- advisor can elect whether or not to proceed with a method invocation, whether or not to
- modify the response, and whether or not to throw an exception. Spring Security provides an
- around advice for method invocations as well as web requests. We achieve an around advice
- for method invocations using Spring's standard AOP support and we achieve an around advice
- for web requests using a standard Filter.</p><p>For those not familiar with AOP, the key point to understand is that Spring Security can
- help you protect method invocations as well as web requests. Most people are interested in
- securing method invocations on their services layer. This is because the services layer is
- where most business logic resides in current-generation J2EE applications. If you just need
- to secure method invocations in the services layer, Spring's standard AOP will be adequate.
- If you need to secure domain objects directly, you will likely find that AspectJ is worth
- considering.</p><p>You can elect to perform method authorization using AspectJ or Spring AOP, or you can
- elect to perform web request authorization using filters. You can use zero, one, two or
- three of these approaches together. The mainstream usage pattern is to perform some web
- request authorization, coupled with some Spring AOP method invocation authorization on the
- services layer.</p></div><div class="section" title="5.5.2 Secure Objects and the AbstractSecurityInterceptor"><div class="titlepage"><div><div><h3 class="title"><a name="secure-objects"></a>5.5.2 Secure Objects and the <code class="classname">AbstractSecurityInterceptor</code></h3></div></div></div><p>So what <span class="emphasis"><em>is</em></span> a <span class="quote">“<span class="quote">secure object</span>”</span> anyway? Spring Security
- uses the term to refer to any object that can have security (such as an authorization
- decision) applied to it. The most common examples are method invocations and web
- requests.</p><p>Each supported secure object type has its own interceptor class, which is a subclass of
- <code class="classname">AbstractSecurityInterceptor</code>. Importantly, by the time the
- <code class="classname">AbstractSecurityInterceptor</code> is called, the
- <code class="classname">SecurityContextHolder</code> will contain a valid
- <code class="interfacename">Authentication</code> if the principal has been
- authenticated.</p><p><code class="classname">AbstractSecurityInterceptor</code> provides a consistent workflow for
- handling secure object requests, typically: </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>Look up the
- <span class="quote">“<span class="quote">configuration attributes</span>”</span> associated with the present
- request</p></li><li class="listitem"><p>Submitting the secure object, current
- <code class="interfacename">Authentication</code> and configuration attributes to the
- <code class="interfacename">AccessDecisionManager</code> for an authorization
- decision</p></li><li class="listitem"><p>Optionally change the
- <code class="interfacename">Authentication</code> under which the invocation takes
- place</p></li><li class="listitem"><p>Allow the secure object invocation to proceed
- (assuming access was granted)</p></li><li class="listitem"><p>Call the
- <code class="interfacename">AfterInvocationManager</code> if configured, once the
- invocation has returned.</p></li></ol></div><div class="section" title="What are Configuration Attributes?"><div class="titlepage"><div><div><h4 class="title"><a name="tech-intro-config-attributes"></a>What are Configuration Attributes?</h4></div></div></div><p> A <span class="quote">“<span class="quote">configuration attribute</span>”</span> can be thought of as a String that has
- special meaning to the classes used by <code class="classname">AbstractSecurityInterceptor</code>.
- They are represented by the interface <code class="interfacename">ConfigAttribute</code>
- within the framework. They may be simple role names or have more complex meaning,
- depending on the how sophisticated the
- <code class="interfacename">AccessDecisionManager</code> implementation is. The
- <code class="classname">AbstractSecurityInterceptor</code> is configured with a
- <code class="interfacename">SecurityMetadataSource</code> which it uses to look up the
- attributes for a secure object. Usually this configuration will be hidden from the user.
- Configuration attributes will be entered as annotations on secured methods or as access
- attributes on secured URLs. For example, when we saw something like
- <code class="literal"><intercept-url pattern='/secure/**' access='ROLE_A,ROLE_B'/></code> in
- the namespace introduction, this is saying that the configuration attributes
- <code class="literal">ROLE_A</code> and <code class="literal">ROLE_B</code> apply to web requests matching
- the given pattern. In practice, with the default
- <code class="interfacename">AccessDecisionManager</code> configuration, this means that
- anyone who has a <code class="interfacename">GrantedAuthority</code> matching either of these
- two attributes will be allowed access. Strictly speaking though, they are just attributes
- and the interpretation is dependent on the
- <code class="interfacename">AccessDecisionManager</code> implementation. The use of the
- prefix <code class="literal">ROLE_</code> is a marker to indicate that these attributes are roles
- and should be consumed by Spring Security's <code class="classname">RoleVoter</code>. This is only
- relevant when a voter-based <code class="interfacename">AccessDecisionManager</code> is in
- use. We'll see how the <code class="interfacename">AccessDecisionManager</code> is implemented
- in the <a class="link" href="authz-arch.html" title="13. Authorization Architecture">authorization chapter</a>.</p></div><div class="section" title="RunAsManager"><div class="titlepage"><div><div><h4 class="title"><a name="d0e2195"></a>RunAsManager</h4></div></div></div><p>Assuming <code class="interfacename">AccessDecisionManager</code> decides to allow the
- request, the <code class="classname">AbstractSecurityInterceptor</code> will normally just proceed
- with the request. Having said that, on rare occasions users may want to replace the
- <code class="interfacename">Authentication</code> inside the
- <code class="interfacename">SecurityContext</code> with a different
- <code class="interfacename">Authentication</code>, which is handled by the
- <code class="interfacename">AccessDecisionManager</code> calling a
- <code class="literal">RunAsManager</code>. This might be useful in reasonably unusual situations,
- such as if a services layer method needs to call a remote system and present a different
- identity. Because Spring Security automatically propagates security identity from one
- server to another (assuming you're using a properly-configured RMI or HttpInvoker remoting
- protocol client), this may be useful.</p></div><div class="section" title="AfterInvocationManager"><div class="titlepage"><div><div><h4 class="title"><a name="d0e2221"></a>AfterInvocationManager</h4></div></div></div><p>Following the secure object proceeding and then returning - which may mean a method
- invocation completing or a filter chain proceeding - the
- <code class="classname">AbstractSecurityInterceptor</code> gets one final chance to handle the
- invocation. At this stage the <code class="classname">AbstractSecurityInterceptor</code> is
- interested in possibly modifying the return object. We might want this to happen because
- an authorization decision couldn't be made <span class="quote">“<span class="quote">on the way in</span>”</span> to a secure object
- invocation. Being highly pluggable, <code class="classname">AbstractSecurityInterceptor</code>
- will pass control to an <code class="literal">AfterInvocationManager</code> to actually modify the
- object if needed. This class can even entirely replace the object, or throw an exception,
- or not change it in any way as it chooses.</p><p><code class="classname">AbstractSecurityInterceptor</code> and its related objects are shown
- in <a class="xref" href="technical-overview.html#abstract-security-interceptor" title="Figure 5.1. Security interceptors and the “secure object” model">Figure 5.1, “Security interceptors and the
- <span class="quote">“<span class="quote">secure object</span>”</span> model”</a>. </p><div class="figure"><a name="abstract-security-interceptor"></a><p class="title"><b>Figure 5.1. Security interceptors and the
- <span class="quote">“<span class="quote">secure object</span>”</span> model</b></p><div class="figure-contents"><div class="mediaobject" align="center"><img src="images/security-interception.png" align="middle" alt="Security interceptors and the secure object model"></div></div></div><p><br class="figure-break"></p></div><div class="section" title="Extending the Secure Object Model"><div class="titlepage"><div><div><h4 class="title"><a name="d0e2256"></a>Extending the Secure Object Model</h4></div></div></div><p>Only developers contemplating an entirely new way of intercepting and authorizing
- requests would need to use secure objects directly. For example, it would be possible to
- build a new secure object to secure calls to a messaging system. Anything that requires
- security and also provides a way of intercepting a call (like the AOP around advice
- semantics) is capable of being made into a secure object. Having said that, most Spring
- applications will simply use the three currently supported secure object types (AOP
- Alliance <code class="classname">MethodInvocation</code>, AspectJ <code class="classname">JoinPoint</code>
- and web request <code class="classname">FilterInvocation</code>) with complete
- transparency.</p></div></div></div><div class="section" title="5.6 Localization"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="localization"></a>5.6 Localization</h2></div></div></div><p>Spring Security supports localization of exception messages that end users are likely to
- see. If your application is designed for English-speaking users, you don't need to do anything
- as by default all Security Security messages are in English. If you need to support other
- locales, everything you need to know is contained in this section.</p><p>All exception messages can be localized, including messages related to authentication
- failures and access being denied (authorization failures). Exceptions and logging that is
- focused on developers or system deployers (including incorrect attributes, interface contract
- violations, using incorrect constructors, startup time validation, debug-level logging) etc
- are not localized and instead are hard-coded in English within Spring Security's code.</p><p>Shipping in the <code class="literal">spring-security-core-xx.jar</code> you will find an
- <code class="literal">org.springframework.security</code> package that in turn contains a
- <code class="literal">messages.properties</code> file. This should be referred to by your
- <code class="literal">ApplicationContext</code>, as Spring Security classes implement Spring's
- <code class="literal">MessageSourceAware</code> interface and expect the message resolver to be
- dependency injected at application context startup time. Usually all you need to do is
- register a bean inside your application context to refer to the messages. An example is shown
- below:</p><p>
- </p><pre class="programlisting">
-<bean id="messageSource"
- class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
- <property name="basename" value="org/springframework/security/messages"/>
-</bean>
+ </pre><p>Note that you don't normally need to write any code like this. The process will
+ normally occur internally, in a web authentication filter for example. We've just
+ included the code here to show that the question of what actually constitutes
+ authentication in Spring Security has quite a simple answer. A user is authenticated
+ when the <code class="classname">SecurityContextHolder</code> contains a fully populated
+ <code class="interfacename">Authentication</code> object.</p></div><div class="section" title="6.3.2 Setting the SecurityContextHolder Contents Directly"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2167"></a>6.3.2 Setting the SecurityContextHolder Contents Directly</h3></div></div></div><p>In fact, Spring Security doesn't mind how you put the
+ <code class="interfacename">Authentication</code> object inside the
+ <code class="classname">SecurityContextHolder</code>. The only critical requirement is that
+ the <code class="classname">SecurityContextHolder</code> contains an
+ <code class="interfacename">Authentication</code> which represents a principal before
+ the <code class="classname">AbstractSecurityInterceptor</code> (which we'll see more about
+ later) needs to authorize a user operation.</p><p>You can (and many users do) write their own filters or MVC controllers to provide
+ interoperability with authentication systems that are not based on Spring Security.
+ For example, you might be using Container-Managed Authentication which makes the
+ current user available from a ThreadLocal or JNDI location. Or you might work for a
+ company that has a legacy proprietary authentication system, which is a corporate
+ "standard" over which you have little control. In situations like this it's quite
+ easy to get Spring Security to work, and still provide authorization capabilities.
+ All you need to do is write a filter (or equivalent) that reads the third-party user
+ information from a location, build a Spring Security-specific
+ <code class="interfacename">Authentication</code> object, and put it into the
+ <code class="classname">SecurityContextHolder</code>. In this case you also need to think
+ about things which are normally taken care of automatically by the built-in authentication
+ infrastructure. For example, you might need to pre-emptively create an HTTP session to
+ <a class="link" href="tech-intro-sec-context-persistence" target="_top">cache the context between requests</a>,
+ before you write the response to the client<sup>[<a name="d0e2198" href="#ftn.d0e2198" class="footnote">9</a>]</sup>.
+ </p><p> If you're wondering how the <code class="interfacename">AuthenticationManager</code>
+ is implemented in a real world example, we'll look at that in the <a class="link" href="core-services.html#core-services-authentication-manager" title="7.1 The AuthenticationManager, ProviderManager and AuthenticationProviders">core services
+ chapter</a>.</p></div></div><div class="section" title="6.4 Authentication in a Web Application"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="tech-intro-web-authentication"></a>6.4 Authentication in a Web Application</h2></div></div></div><p> Now let's explore the situation where you are using Spring Security in a web
+ application (without <code class="filename">web.xml</code> security enabled). How is a user
+ authenticated and the security context established?</p><p>Consider a typical web application's authentication process:</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>You visit the home page, and click on a link.</p></li><li class="listitem"><p>A request goes to the server, and the server decides that you've asked for a
+ protected resource.</p></li><li class="listitem"><p>As you're not presently authenticated, the server sends back a response
+ indicating that you must authenticate. The response will either be an HTTP
+ response code, or a redirect to a particular web page.</p></li><li class="listitem"><p>Depending on the authentication mechanism, your browser will either redirect
+ to the specific web page so that you can fill out the form, or the browser will
+ somehow retrieve your identity (via a BASIC authentication dialogue box, a
+ cookie, a X.509 certificate etc.).</p></li><li class="listitem"><p>The browser will send back a response to the server. This will either be an
+ HTTP POST containing the contents of the form that you filled out, or an HTTP
+ header containing your authentication details.</p></li><li class="listitem"><p>Next the server will decide whether or not the presented credentials are
+ valid. If they're valid, the next step will happen. If they're invalid, usually
+ your browser will be asked to try again (so you return to step two
+ above).</p></li><li class="listitem"><p>The original request that you made to cause the authentication process will be
+ retried. Hopefully you've authenticated with sufficient granted authorities to
+ access the protected resource. If you have sufficient access, the request will
+ be successful. Otherwise, you'll receive back an HTTP error code 403, which
+ means "forbidden".</p></li></ol></div><p>Spring Security has distinct classes responsible for most of the steps described
+ above. The main participants (in the order that they are used) are the
+ <code class="classname">ExceptionTranslationFilter</code>, an
+ <code class="interfacename">AuthenticationEntryPoint</code> and an <span class="quote">“<span class="quote">authentication
+ mechanism</span>”</span>, which is responsible for calling the
+ <code class="classname">AuthenticationManager</code> which we saw in the previous
+ section.</p><div class="section" title="6.4.1 ExceptionTranslationFilter"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2256"></a>6.4.1 ExceptionTranslationFilter</h3></div></div></div><p><code class="classname">ExceptionTranslationFilter</code> is a Spring Security filter that
+ has responsibility for detecting any Spring Security exceptions that are thrown.
+ Such exceptions will generally be thrown by an
+ <code class="classname">AbstractSecurityInterceptor</code>, which is the main provider of
+ authorization services. We will discuss
+ <code class="classname">AbstractSecurityInterceptor</code> in the next section, but for now
+ we just need to know that it produces Java exceptions and knows nothing about HTTP
+ or how to go about authenticating a principal. Instead the
+ <code class="classname">ExceptionTranslationFilter</code> offers this service, with specific
+ responsibility for either returning error code 403 (if the principal has been
+ authenticated and therefore simply lacks sufficient access - as per step seven
+ above), or launching an <code class="interfacename">AuthenticationEntryPoint</code> (if
+ the principal has not been authenticated and therefore we need to go commence step
+ three).</p></div><div class="section" title="6.4.2 AuthenticationEntryPoint"><div class="titlepage"><div><div><h3 class="title"><a name="tech-intro-auth-entry-point"></a>6.4.2 AuthenticationEntryPoint</h3></div></div></div><p>The <code class="interfacename">AuthenticationEntryPoint</code> is responsible for
+ step three in the above list. As you can imagine, each web application will have a
+ default authentication strategy (well, this can be configured like nearly everything
+ else in Spring Security, but let's keep it simple for now). Each major
+ authentication system will have its own
+ <code class="interfacename">AuthenticationEntryPoint</code> implementation, which
+ typically performs one of the actions described in step 3.</p></div><div class="section" title="6.4.3 Authentication Mechanism"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2286"></a>6.4.3 Authentication Mechanism</h3></div></div></div><p>Once your browser submits your authentication credentials (either as an HTTP form
+ post or HTTP header) there needs to be something on the server that
+ <span class="quote">“<span class="quote">collects</span>”</span> these authentication details. By now we're at step six in
+ the above list. In Spring Security we have a special name for the function of
+ collecting authentication details from a user agent (usually a web browser),
+ referring to it as the <span class="quote">“<span class="quote">authentication mechanism</span>”</span>. Examples are
+ form-base login and Basic authentication. Once the authentication details have been
+ collected from the user agent, an <code class="interfacename">Authentication</code>
+ <span class="quote">“<span class="quote">request</span>”</span> object is built and then presented to the
+ <code class="interfacename">AuthenticationManager</code>.</p><p>After the authentication mechanism receives back the fully-populated
+ <code class="interfacename">Authentication</code> object, it will deem the request
+ valid, put the <code class="interfacename">Authentication</code> into the
+ <code class="classname">SecurityContextHolder</code>, and cause the original request to be
+ retried (step seven above). If, on the other hand, the
+ <code class="classname">AuthenticationManager</code> rejected the request, the
+ authentication mechanism will ask the user agent to retry (step two above).</p></div><div class="section" title="6.4.4 Storing the SecurityContext between requests"><div class="titlepage"><div><div><h3 class="title"><a name="tech-intro-sec-context-persistence"></a>6.4.4 Storing the <code class="interfacename">SecurityContext</code> between
+ requests</h3></div></div></div><p>Depending on the type of application, there may need to be a strategy in place to
+ store the security context between user operations. In a typical web application, a
+ user logs in once and is subsequently identified by their session Id. The server
+ caches the principal information for the duration session. In Spring Security, the
+ responsibility for storing the <code class="interfacename">SecurityContext</code>
+ between requests falls to the
+ <code class="classname">SecurityContextPersistenceFilter</code>, which by default stores the
+ context as an <code class="literal">HttpSession</code> attribute between HTTP requests. It
+ restores the context to the <code class="classname">SecurityContextHolder</code> for each
+ request and, crucially, clears the <code class="classname">SecurityContextHolder</code> when
+ the request completes. You shouldn't interact directly with the
+ <code class="literal">HttpSession</code> for security purposes. There is simply no
+ justification for doing so - always use the
+ <code class="classname">SecurityContextHolder</code> instead. </p><p> Many other types of application (for example, a stateless RESTful web service) do
+ not use HTTP sessions and will re-authenticate on every request. However, it is
+ still important that the <code class="classname">SecurityContextPersistenceFilter</code> is
+ included in the chain to make sure that the
+ <code class="classname">SecurityContextHolder</code> is cleared after each request.</p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>In an application which receives concurrent requests in a single session, the
+ same <code class="interfacename">SecurityContext</code> instance will be shared
+ between threads. Even though a <code class="classname">ThreadLocal</code> is being used,
+ it is the same instance that is retrieved from the
+ <code class="interfacename">HttpSession</code> for each thread. This has
+ implications if you wish to temporarily change the context under which a thread
+ is running. If you just use <code class="code">SecurityContextHolder.getContext()</code>, and
+ call <code class="code">setAuthentication(anAuthentication)</code> on the returned context
+ object, then the <code class="interfacename">Authentication</code> object will
+ change in <span class="emphasis"><em>all</em></span> concurrent threads which share the same
+ <code class="interfacename">SecurityContext</code> instance. You can customize the
+ behaviour of <code class="classname">SecurityContextPersistenceFilter</code> to create a
+ completely new <code class="interfacename">SecurityContext</code> for each request,
+ preventing changes in one thread from affecting another. Alternatively you can
+ create a new instance just at the point where you temporarily change the
+ context. The method <code class="code">SecurityContextHolder.createEmptyContext()</code>
+ always returns a new context instance.</p></td></tr></table></div></div></div><div class="section" title="6.5 Access-Control (Authorization) in Spring Security"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="tech-intro-access-control"></a>6.5 Access-Control (Authorization) in Spring Security</h2></div></div></div><p> The main interface responsible for making access-control decisions in Spring Security
+ is the <code class="interfacename">AccessDecisionManager</code>. It has a
+ <code class="methodname">decide</code> method which takes an
+ <code class="interfacename">Authentication</code> object representing the principal
+ requesting access, a <span class="quote">“<span class="quote">secure object</span>”</span> (see below) and a list of security
+ metadata attributes which apply for the object (such as a list of roles which are
+ required for access to be granted). </p><div class="section" title="6.5.1 Security and AOP Advice"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2410"></a>6.5.1 Security and AOP Advice</h3></div></div></div><p>If you're familiar with AOP, you'd be aware there are different types of advice
+ available: before, after, throws and around. An around advice is very useful,
+ because an advisor can elect whether or not to proceed with a method invocation,
+ whether or not to modify the response, and whether or not to throw an exception.
+ Spring Security provides an around advice for method invocations as well as web
+ requests. We achieve an around advice for method invocations using Spring's standard
+ AOP support and we achieve an around advice for web requests using a standard
+ Filter.</p><p>For those not familiar with AOP, the key point to understand is that Spring
+ Security can help you protect method invocations as well as web requests. Most
+ people are interested in securing method invocations on their services layer. This
+ is because the services layer is where most business logic resides in
+ current-generation J2EE applications. If you just need to secure method invocations
+ in the services layer, Spring's standard AOP will be adequate. If you need to secure
+ domain objects directly, you will likely find that AspectJ is worth
+ considering.</p><p>You can elect to perform method authorization using AspectJ or Spring AOP, or you
+ can elect to perform web request authorization using filters. You can use zero, one,
+ two or three of these approaches together. The mainstream usage pattern is to
+ perform some web request authorization, coupled with some Spring AOP method
+ invocation authorization on the services layer.</p></div><div class="section" title="6.5.2 Secure Objects and the AbstractSecurityInterceptor"><div class="titlepage"><div><div><h3 class="title"><a name="secure-objects"></a>6.5.2 Secure Objects and the <code class="classname">AbstractSecurityInterceptor</code></h3></div></div></div><p>So what <span class="emphasis"><em>is</em></span> a <span class="quote">“<span class="quote">secure object</span>”</span> anyway? Spring
+ Security uses the term to refer to any object that can have security (such as an
+ authorization decision) applied to it. The most common examples are method
+ invocations and web requests.</p><p>Each supported secure object type has its own interceptor class, which is a
+ subclass of <code class="classname">AbstractSecurityInterceptor</code>. Importantly, by the
+ time the <code class="classname">AbstractSecurityInterceptor</code> is called, the
+ <code class="classname">SecurityContextHolder</code> will contain a valid
+ <code class="interfacename">Authentication</code> if the principal has been
+ authenticated.</p><p><code class="classname">AbstractSecurityInterceptor</code> provides a consistent workflow
+ for handling secure object requests, typically: </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>Look up the <span class="quote">“<span class="quote">configuration attributes</span>”</span> associated with the
+ present request</p></li><li class="listitem"><p>Submitting the secure object, current
+ <code class="interfacename">Authentication</code> and configuration attributes
+ to the <code class="interfacename">AccessDecisionManager</code> for an
+ authorization decision</p></li><li class="listitem"><p>Optionally change the <code class="interfacename">Authentication</code> under
+ which the invocation takes place</p></li><li class="listitem"><p>Allow the secure object invocation to proceed (assuming access was
+ granted)</p></li><li class="listitem"><p>Call the <code class="interfacename">AfterInvocationManager</code> if
+ configured, once the invocation has returned. If the invocation raised an
+ exception, the <code class="interfacename">AfterInvocationManager</code>
+ will not be invoked.</p></li></ol></div><div class="section" title="What are Configuration Attributes?"><div class="titlepage"><div><div><h4 class="title"><a name="tech-intro-config-attributes"></a>What are Configuration Attributes?</h4></div></div></div><p> A <span class="quote">“<span class="quote">configuration attribute</span>”</span> can be thought of as a String that
+ has special meaning to the classes used by
+ <code class="classname">AbstractSecurityInterceptor</code>. They are represented by the
+ interface <code class="interfacename">ConfigAttribute</code> within the framework.
+ They may be simple role names or have more complex meaning, depending on the how
+ sophisticated the <code class="interfacename">AccessDecisionManager</code>
+ implementation is. The <code class="classname">AbstractSecurityInterceptor</code> is
+ configured with a <code class="interfacename">SecurityMetadataSource</code> which it
+ uses to look up the attributes for a secure object. Usually this configuration
+ will be hidden from the user. Configuration attributes will be entered as
+ annotations on secured methods or as access attributes on secured URLs. For
+ example, when we saw something like <code class="literal"><intercept-url
+ pattern='/secure/**' access='ROLE_A,ROLE_B'/></code> in the namespace
+ introduction, this is saying that the configuration attributes
+ <code class="literal">ROLE_A</code> and <code class="literal">ROLE_B</code> apply to web requests
+ matching the given pattern. In practice, with the default
+ <code class="interfacename">AccessDecisionManager</code> configuration, this means
+ that anyone who has a <code class="interfacename">GrantedAuthority</code> matching
+ either of these two attributes will be allowed access. Strictly speaking though,
+ they are just attributes and the interpretation is dependent on the
+ <code class="interfacename">AccessDecisionManager</code> implementation. The use of
+ the prefix <code class="literal">ROLE_</code> is a marker to indicate that these
+ attributes are roles and should be consumed by Spring Security's
+ <code class="classname">RoleVoter</code>. This is only relevant when a voter-based
+ <code class="interfacename">AccessDecisionManager</code> is in use. We'll see how
+ the <code class="interfacename">AccessDecisionManager</code> is implemented in the
+ <a class="link" href="authz-arch.html" title="14. Authorization Architecture">authorization chapter</a>.</p></div><div class="section" title="RunAsManager"><div class="titlepage"><div><div><h4 class="title"><a name="d0e2540"></a>RunAsManager</h4></div></div></div><p>Assuming <code class="interfacename">AccessDecisionManager</code> decides to allow
+ the request, the <code class="classname">AbstractSecurityInterceptor</code> will
+ normally just proceed with the request. Having said that, on rare occasions
+ users may want to replace the <code class="interfacename">Authentication</code>
+ inside the <code class="interfacename">SecurityContext</code> with a different
+ <code class="interfacename">Authentication</code>, which is handled by the
+ <code class="interfacename">AccessDecisionManager</code> calling a
+ <code class="literal">RunAsManager</code>. This might be useful in reasonably unusual
+ situations, such as if a services layer method needs to call a remote system and
+ present a different identity. Because Spring Security automatically propagates
+ security identity from one server to another (assuming you're using a
+ properly-configured RMI or HttpInvoker remoting protocol client), this may be
+ useful.</p></div><div class="section" title="AfterInvocationManager"><div class="titlepage"><div><div><h4 class="title"><a name="d0e2566"></a>AfterInvocationManager</h4></div></div></div><p>Following the secure object invocation proceeding and then returning - which may mean a
+ method invocation completing or a filter chain proceeding - the
+ <code class="classname">AbstractSecurityInterceptor</code> gets one final chance to
+ handle the invocation. At this stage the
+ <code class="classname">AbstractSecurityInterceptor</code> is interested in possibly
+ modifying the return object. We might want this to happen because an
+ authorization decision couldn't be made <span class="quote">“<span class="quote">on the way in</span>”</span> to a secure
+ object invocation. Being highly pluggable,
+ <code class="classname">AbstractSecurityInterceptor</code> will pass control to an
+ <code class="literal">AfterInvocationManager</code> to actually modify the object if
+ needed. This class can even entirely replace the object, or throw an exception,
+ or not change it in any way as it chooses. The after-invocation checks will only
+ be executed if the invocation is successful. If an exception occurs, the additional
+ checks will be skipped.
+ </p><p><code class="classname">AbstractSecurityInterceptor</code> and its related objects are
+ shown in <a class="xref" href="technical-overview.html#abstract-security-interceptor" title="Figure 6.1. Security interceptors and the “secure object” model">Figure 6.1, “Security interceptors and the <span class="quote">“<span class="quote">secure object</span>”</span> model”</a>. </p><div class="figure"><a name="abstract-security-interceptor"></a><p class="title"><b>Figure 6.1. Security interceptors and the <span class="quote">“<span class="quote">secure object</span>”</span> model</b></p><div class="figure-contents"><div class="mediaobject" align="center"><img src="images/security-interception.png" align="middle" alt="Security interceptors and the secure object model"></div></div></div><p><br class="figure-break"></p></div><div class="section" title="Extending the Secure Object Model"><div class="titlepage"><div><div><h4 class="title"><a name="d0e2601"></a>Extending the Secure Object Model</h4></div></div></div><p>Only developers contemplating an entirely new way of intercepting and
+ authorizing requests would need to use secure objects directly. For example, it
+ would be possible to build a new secure object to secure calls to a messaging
+ system. Anything that requires security and also provides a way of intercepting
+ a call (like the AOP around advice semantics) is capable of being made into a
+ secure object. Having said that, most Spring applications will simply use the
+ three currently supported secure object types (AOP Alliance
+ <code class="classname">MethodInvocation</code>, AspectJ
+ <code class="classname">JoinPoint</code> and web request
+ <code class="classname">FilterInvocation</code>) with complete transparency.</p></div></div></div><div class="section" title="6.6 Localization"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="localization"></a>6.6 Localization</h2></div></div></div><p>Spring Security supports localization of exception messages that end users are likely
+ to see. If your application is designed for English-speaking users, you don't need to do
+ anything as by default all Security Security messages are in English. If you need to
+ support other locales, everything you need to know is contained in this section.</p><p>All exception messages can be localized, including messages related to authentication
+ failures and access being denied (authorization failures). Exceptions and logging
+ messages that are focused on developers or system deployers (including incorrect
+ attributes, interface contract violations, using incorrect constructors, startup time
+ validation, debug-level logging) are not localized and instead are hard-coded in English
+ within Spring Security's code.</p><p>Shipping in the <code class="literal">spring-security-core-xx.jar</code> you will find an
+ <code class="literal">org.springframework.security</code> package that in turn contains a
+ <code class="literal">messages.properties</code> file, as well as localized versions for some
+ common languages. This should be referred to by your
+ <code class="literal">ApplicationContext</code>, as Spring Security classes implement Spring's
+ <code class="literal">MessageSourceAware</code> interface and expect the message resolver to be
+ dependency injected at application context startup time. Usually all you need to do is
+ register a bean inside your application context to refer to the messages. An example is
+ shown below:</p><p>
+ </p><pre class="programlisting">
+<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"messageSource"</span>
+ <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.context.support.ReloadableResourceBundleMessageSource"</span><span class="hl-tag">></span>
+ <span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"basename"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"classpath:org/springframework/security/messages"</span><span class="hl-tag">/></span>
+<span class="hl-tag"></bean></span>
</pre><p>
- </p><p>The <code class="literal">messages.properties</code> is named in accordance with standard resource
- bundles and represents the default language supported by Spring Security messages. This
- default file is in English. If you do not register a message source, Spring Security will
- still work correctly and fallback to hard-coded English versions of the messages.</p><p>If you wish to customize the <code class="literal">messages.properties</code> file, or support other
- languages, you should copy the file, rename it accordingly, and register it inside the above
- bean definition. There are not a large number of message keys inside this file, so
- localization should not be considered a major initiative. If you do perform localization of
- this file, please consider sharing your work with the community by logging a JIRA task and
- attaching your appropriately-named localized version of
- <code class="literal">messages.properties</code>.</p><p>Rounding out the discussion on localization is the Spring <code class="literal">ThreadLocal</code>
- known as <code class="classname">org.springframework.context.i18n.LocaleContextHolder</code>. You
- should set the <code class="classname">LocaleContextHolder</code> to represent the preferred
- <code class="literal">Locale</code> of each user. Spring Security will attempt to locate a message
- from the message source using the <code class="literal">Locale</code> obtained from this
- <code class="literal">ThreadLocal</code>. Please refer to the Spring Framework documentation for
- further details on using <code class="literal">LocaleContextHolder</code>.</p></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
+ </p><p>The <code class="literal">messages.properties</code> is named in accordance with standard
+ resource bundles and represents the default language supported by Spring Security
+ messages. This default file is in English. </p><p>If you wish to customize the <code class="literal">messages.properties</code> file, or support
+ other languages, you should copy the file, rename it accordingly, and register it inside
+ the above bean definition. There are not a large number of message keys inside this
+ file, so localization should not be considered a major initiative. If you do perform
+ localization of this file, please consider sharing your work with the community by
+ logging a JIRA task and attaching your appropriately-named localized version of
+ <code class="literal">messages.properties</code>.</p><p>Spring Security relies on Spring's localization support in order to actually lookup
+ the appropriate message. In order for this to work, you have to make sure that the
+ locale from the incoming request is stored in Spring's
+ <code class="classname">org.springframework.context.i18n.LocaleContextHolder</code>. Spring
+ MVC's <code class="classname">DispatcherServlet</code> does this for your application
+ automatically, but since Spring Security's filters are invoked before this, the
+ <code class="classname">LocaleContextHolder</code> needs to be set up to contain the correct
+ <code class="literal">Locale</code> before the filters are called. You can either do this in a
+ filter yourself (which must come before the Spring Security filters in
+ <code class="filename">web.xml</code>) or you can use Spring's
+ <code class="classname">RequestContextFilter</code>. Please refer to the Spring Framework
+ documentation for further details on using localization with Spring. </p><p>The <span class="quote">“<span class="quote">contacts</span>”</span> sample application is set up to use localized messages.
+ </p></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.d0e2198" href="#d0e2198" class="para">9</a>] </sup>It isn't possible to create a session once the
+ response has been committed.</p></div></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
- </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="overall-architecture.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="overall-architecture.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="core-services.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Part II. Architecture and Implementation </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 6. Core Services</td></tr></table></div></body></html>
\ No newline at end of file
+ </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="overall-architecture.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="overall-architecture.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="core-services.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Part II. Architecture and Implementation </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 7. Core Services</td></tr></table></div></body></html>
\ No newline at end of file
diff --git a/docs/reference/web-app-security.html b/docs/reference/web-app-security.html
index 8b75f3e..e374dba 100644
--- a/docs/reference/web-app-security.html
+++ b/docs/reference/web-app-security.html
@@ -1,6 +1,6 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>Part III. Web Application Security</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="springsecurity.html" title="Spring Security"><link rel="prev" href="core-services.html" title="6. Core Services"><link rel="next" href="security-filter-chain.html" title="7. The Security Filter Chain"><!--Begin Google Analytics code--><script type="text/javascript">
+ <title>Part III. Web Application Security</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="springsecurity.html" title="Spring Security"><link rel="prev" href="core-services.html" title="7. Core Services"><link rel="next" href="security-filter-chain.html" title="8. The Security Filter Chain"><!--Begin Google Analytics code--><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
@@ -8,13 +8,14 @@
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
- </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Part III. Web Application Security</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="core-services.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="security-filter-chain.html">Next</a></td></tr></table><hr></div><div class="part" title="Part III. Web Application Security"><div class="titlepage"><div><div><h1 class="title"><a name="web-app-security"></a>Part III. Web Application Security</h1></div></div></div><div class="partintro" title="Web Application Security"><div></div><p> Most Spring Security users will be using the framework in applications which make user
- of HTTP and the Servlet API. In this part, we'll take a look at how Spring Security provides
- authentication and access-control features for the web layer of an application. We'll look
- behind the facade of the namespace and see which classes and interfaces are actually
- assembled to provide web-layer security. In some situations it is necessary to use
- traditional bean configuration to provide full control over the configuration, so we'll also
- see how to configure these classes directly without the namespace.</p></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
+ </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Part III. Web Application Security</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="core-services.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="security-filter-chain.html">Next</a></td></tr></table><hr></div><div class="part" title="Part III. Web Application Security"><div class="titlepage"><div><div><h1 class="title"><a name="web-app-security"></a>Part III. Web Application Security</h1></div></div></div><div class="partintro" title="Web Application Security"><div></div><p> Most Spring Security users will be using the framework in applications which make
+ user of HTTP and the Servlet API. In this part, we'll take a look at how Spring
+ Security provides authentication and access-control features for the web layer of an
+ application. We'll look behind the facade of the namespace and see which classes and
+ interfaces are actually assembled to provide web-layer security. In some situations
+ it is necessary to use traditional bean configuration to provide full control over
+ the configuration, so we'll also see how to configure these classes directly without
+ the namespace.</p></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
- </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="core-services.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="security-filter-chain.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">6. Core Services </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 7. The Security Filter Chain</td></tr></table></div></body></html>
\ No newline at end of file
+ </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="core-services.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="security-filter-chain.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">7. Core Services </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 8. The Security Filter Chain</td></tr></table></div></body></html>
\ No newline at end of file
diff --git a/docs/reference/x509.html b/docs/reference/x509.html
index 19e725f..b6bfb89 100644
--- a/docs/reference/x509.html
+++ b/docs/reference/x509.html
@@ -1,6 +1,6 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>22. X.509 Authentication</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="advanced-topics.html" title="Part V. Additional Topics"><link rel="prev" href="cas.html" title="21. CAS Authentication"><link rel="next" href="runas.html" title="23. Run-As Authentication Replacement"><!--Begin Google Analytics code--><script type="text/javascript">
+ <title>23. X.509 Authentication</title><link rel="stylesheet" href="css/manual.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="springsecurity.html" title="Spring Security"><link rel="up" href="advanced-topics.html" title="Part V. Additional Topics"><link rel="prev" href="cas.html" title="22. CAS Authentication"><link rel="next" href="runas.html" title="24. Run-As Authentication Replacement"><!--Begin Google Analytics code--><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
@@ -8,33 +8,36 @@
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
- </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">22. X.509 Authentication</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="cas.html">Prev</a> </td><th width="60%" align="center">Part V. Additional Topics</th><td width="20%" align="right"> <a accesskey="n" href="runas.html">Next</a></td></tr></table><hr></div><div class="chapter" title="22. X.509 Authentication"><div class="titlepage"><div><div><h1 class="title"><a name="x509"></a>X.509 Authentication</h1></div></div></div><div class="section" title="22.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="x509-overview"></a>22.1 Overview</h2></div></div></div><p>The most common use of X.509 certificate authentication is in verifying the identity
+ </script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">23. X.509 Authentication</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="cas.html">Prev</a> </td><th width="60%" align="center">Part V. Additional Topics</th><td width="20%" align="right"> <a accesskey="n" href="runas.html">Next</a></td></tr></table><hr></div><div class="chapter" title="23. X.509 Authentication"><div class="titlepage"><div><div><h1 class="title"><a name="x509"></a>X.509 Authentication</h1></div></div></div><div class="section" title="23.1 Overview"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="x509-overview"></a>23.1 Overview</h2></div></div></div><p>The most common use of X.509 certificate authentication is in verifying the identity
of a server when using SSL, most commonly when using HTTPS from a browser. The browser
will automatically check that the certificate presented by a server has been issued (ie
digitally signed) by one of a list of trusted certificate authorities which it
maintains.</p><p>You can also use SSL with <span class="quote">“<span class="quote">mutual authentication</span>”</span>; the server will then
request a valid certificate from the client as part of the SSL handshake. The server
- will authenticate the client by checking that its certificate is signed by an
- acceptable authority. If a valid certificate has been provided, it can be obtained
- through the servlet API in an application. Spring Security X.509 module extracts the
- certificate using a filter. It maps the certificate to an application user and loads that
- user's set of granted authorities for use with the standard Spring Security infrastructure.</p><p>You should be familiar with using certificates and setting up client authentication
+ will authenticate the client by checking that its certificate is signed by an acceptable
+ authority. If a valid certificate has been provided, it can be obtained through the
+ servlet API in an application. Spring Security X.509 module extracts the certificate
+ using a filter. It maps the certificate to an application user and loads that user's set
+ of granted authorities for use with the standard Spring Security infrastructure.</p><p>You should be familiar with using certificates and setting up client authentication
for your servlet container before attempting to use it with Spring Security. Most of the
work is in creating and installing suitable certificates and keys. For example, if
- you're using Tomcat then read the instructions here <code class="uri"><a class="uri" href="http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html" target="_top">http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html</a></code>. It's important that
- you get this working before trying it out with Spring Security</p></div><div class="section" title="22.2 Adding X.509 Authentication to Your Web Application"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e6578"></a>22.2 Adding X.509 Authentication to Your Web Application</h2></div></div></div><p> Enabling X.509 client authentication is very straightforward. Just add the <code class="literal"><x509/></code> element to your http security namespace configuration. </p><pre class="programlisting">
-<http>
+ you're using Tomcat then read the instructions here <code class="uri"><a class="uri" href="http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html" target="_top">http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html</a></code>. It's important that you
+ get this working before trying it out with Spring Security</p></div><div class="section" title="23.2 Adding X.509 Authentication to Your Web Application"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e8013"></a>23.2 Adding X.509 Authentication to Your Web Application</h2></div></div></div><p> Enabling X.509 client authentication is very straightforward. Just add the
+ <code class="literal"><x509/></code> element to your http security namespace configuration.
+ </p><pre class="programlisting">
+<span class="hl-tag"><http></span>
...
- <x509 subject-principal-regex="CN=(.*?)," user-service-ref="userService"/>
+ <span class="hl-tag"><x509</span> <span class="hl-attribute">subject-principal-regex</span>=<span class="hl-value">"CN=(.*?),"</span> <span class="hl-attribute">user-service-ref</span>=<span class="hl-value">"userService"</span><span class="hl-tag">/></span>;
...
-</http>
- </pre><p> The element has two optional attributes: </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p><code class="literal">subject-principal-regex</code>. The regular expression used to
- extract a username from the certificate's subject name. The default value is
- shown above. This is the username which will be passed to the <code class="interfacename">UserDetailsService</code> to load the authorities for the
- user.</p></li><li class="listitem"><p><code class="literal">user-service-ref</code>. This is the bean Id of the
- <code class="interfacename">UserDetailsService</code> to be used with X.509.
- It isn't needed if there is only one defined in your application
- context.</p></li></ul></div><p> The <code class="literal">subject-principal-regex</code> should contain a single
+<span class="hl-tag"></http></span>
+ </pre><p>
+ The element has two optional attributes: </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p><code class="literal">subject-principal-regex</code>. The regular expression used to
+ extract a username from the certificate's subject name. The default value is
+ shown above. This is the username which will be passed to the
+ <code class="interfacename">UserDetailsService</code> to load the authorities for
+ the user.</p></li><li class="listitem"><p><code class="literal">user-service-ref</code>. This is the bean Id of the
+ <code class="interfacename">UserDetailsService</code> to be used with X.509. It
+ isn't needed if there is only one defined in your application context.</p></li></ul></div><p> The <code class="literal">subject-principal-regex</code> should contain a single
group. For example the default expression "CN=(.*?)," matches the common name field. So
if the subject name in the certificate is "CN=Jimi Hendrix, OU=...", this will give a
user name of "Jimi Hendrix". The matches are case insensitive. So "emailAddress=(.?),"
@@ -43,31 +46,29 @@
then there should be a valid <code class="classname">Authentication</code> object in the
security context. If no certificate is found, or no corresponding user could be found
then the security context will remain empty. This means that you can easily use X.509
- authentication with other options such as a form-based login. </p></div><div class="section" title="22.3 Setting up SSL in Tomcat"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="x509-ssl-config"></a>22.3 Setting up SSL in Tomcat</h2></div></div></div><p>There are some pre-generated certificates in the
- <code class="filename">samples/certificate</code> directory in the Spring Security project.
- You can use these to enable SSL for testing if you don't want to generate your own. The file
- <code class="filename">server.jks</code> contains the server certificate, private key and the
+ authentication with other options such as a form-based login. </p></div><div class="section" title="23.3 Setting up SSL in Tomcat"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="x509-ssl-config"></a>23.3 Setting up SSL in Tomcat</h2></div></div></div><p>There are some pre-generated certificates in the
+ <code class="filename">samples/certificate</code> directory in the Spring Security project. You
+ can use these to enable SSL for testing if you don't want to generate your own. The file
+ <code class="filename">server.jks</code> contains the server certificate, private key and the
issuing certificate authority certificate. There are also some client certificate files
- for the users from the sample applications. You can install these in your browser to enable
- SSL client authentication.
- </p><p>
- To run tomcat with SSL support, drop the <code class="filename">server.jks</code> file into the
- tomcat <code class="filename">conf</code> directory and add the following connector to the
+ for the users from the sample applications. You can install these in your browser to
+ enable SSL client authentication. </p><p> To run tomcat with SSL support, drop the <code class="filename">server.jks</code> file into
+ the tomcat <code class="filename">conf</code> directory and add the following connector to the
<code class="filename">server.xml</code> file
- </p><pre class="programlisting">
-<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" scheme="https" secure="true"
- clientAuth="true" sslProtocol="TLS"
- keystoreFile="${catalina.home}/conf/server.jks"
- keystoreType="JKS" keystorePass="password"
- truststoreFile="${catalina.home}/conf/server.jks"
- truststoreType="JKS" truststorePass="password"
-/>
+ </p><pre class="programlisting">
+<span class="hl-tag"><Connector</span> <span class="hl-attribute">port</span>=<span class="hl-value">"8443"</span> <span class="hl-attribute">protocol</span>=<span class="hl-value">"HTTP/1.1"</span> <span class="hl-attribute">SSLEnabled</span>=<span class="hl-value">"true"</span> <span class="hl-attribute">scheme</span>=<span class="hl-value">"https"</span> <span class="hl-attribute">secure</span>=<span class="hl-value">"true"</span>
+ <span class="hl-attribute">clientAuth</span>=<span class="hl-value">"true"</span> <span class="hl-attribute">sslProtocol</span>=<span class="hl-value">"TLS"</span>
+ <span class="hl-attribute">keystoreFile</span>=<span class="hl-value">"${catalina.home}/conf/server.jks"</span>
+ <span class="hl-attribute">keystoreType</span>=<span class="hl-value">"JKS"</span> <span class="hl-attribute">keystorePass</span>=<span class="hl-value">"password"</span>
+ <span class="hl-attribute">truststoreFile</span>=<span class="hl-value">"${catalina.home}/conf/server.jks"</span>
+ <span class="hl-attribute">truststoreType</span>=<span class="hl-value">"JKS"</span> <span class="hl-attribute">truststorePass</span>=<span class="hl-value">"password"</span><span class="hl-tag">
+/></span>
</pre><p>
- <em class="parameter"><code>clientAuth</code></em> can also be set to <em class="parameter"><code>want</code></em> if you still
- want SSL connections to succeed even if the client doesn't provide a certificate.
+ <em class="parameter"><code>clientAuth</code></em> can also be set to <em class="parameter"><code>want</code></em> if you
+ still want SSL connections to succeed even if the client doesn't provide a certificate.
Clients which don't present a certificate won't be able to access any objects secured by
- Spring Security unless you use a non-X.509 authentication mechanism, such as form authentication.
- </p></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
+ Spring Security unless you use a non-X.509 authentication mechanism, such as form
+ authentication. </p></div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
- </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="cas.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="advanced-topics.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="runas.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">21. CAS Authentication </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 23. Run-As Authentication Replacement</td></tr></table></div></body></html>
\ No newline at end of file
+ </script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="cas.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="advanced-topics.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="runas.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">22. CAS Authentication </td><td width="20%" align="center"><a accesskey="h" href="springsecurity.html">Home</a></td><td width="40%" align="right" valign="top"> 24. Run-As Authentication Replacement</td></tr></table></div></body></html>
\ No newline at end of file
--
Spring Security: Java libraries that provide security services for the Spring Framework
More information about the pkg-java-commits
mailing list