Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 45253ca148 | |||
| 807ae835b8 |
+2
-8
@@ -3,12 +3,13 @@
|
||||
<parent>
|
||||
<artifactId>spring-security-parent</artifactId>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<version>2.0.4</version>
|
||||
<version>2.0.2</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-acl</artifactId>
|
||||
<name>Spring Security - ACL module</name>
|
||||
<version>2.0.2</version>
|
||||
<packaging>bundle</packaging>
|
||||
|
||||
<dependencies>
|
||||
@@ -24,13 +25,6 @@
|
||||
<classifier>tests</classifier>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<classifier>tests</classifier>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
package org.springframework.security.acls.domain;
|
||||
|
||||
import org.springframework.security.acls.AclFormattingUtils;
|
||||
import org.springframework.security.acls.Permission;
|
||||
|
||||
/**
|
||||
* Provides an abstract superclass for {@link Permission} implementations.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @since 2.0.3
|
||||
* @see AbstractRegisteredPermission
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractPermission implements Permission {
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
protected char code;
|
||||
protected int mask;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
protected AbstractPermission(int mask, char code) {
|
||||
this.mask = mask;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public final boolean equals(Object arg0) {
|
||||
if (arg0 == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(arg0 instanceof Permission)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Permission rhs = (Permission) arg0;
|
||||
|
||||
return (this.mask == rhs.getMask());
|
||||
}
|
||||
|
||||
public final int getMask() {
|
||||
return mask;
|
||||
}
|
||||
|
||||
public String getPattern() {
|
||||
return AclFormattingUtils.printBinary(mask, code);
|
||||
}
|
||||
|
||||
public final String toString() {
|
||||
return this.getClass().getSimpleName() + "[" + getPattern() + "=" + mask + "]";
|
||||
}
|
||||
|
||||
public final int hashCode() {
|
||||
return this.mask;
|
||||
}
|
||||
}
|
||||
@@ -14,59 +14,157 @@
|
||||
*/
|
||||
package org.springframework.security.acls.domain;
|
||||
|
||||
import org.springframework.security.acls.AclFormattingUtils;
|
||||
import org.springframework.security.acls.Permission;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* A set of standard permissions.
|
||||
*
|
||||
* <p>
|
||||
* You may subclass this class to add additional permissions, or use this class as a guide
|
||||
* for creating your own permission classes.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class BasePermission extends AbstractPermission {
|
||||
public final class BasePermission implements Permission {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
public static final Permission READ = new BasePermission(1 << 0, 'R'); // 1
|
||||
public static final Permission WRITE = new BasePermission(1 << 1, 'W'); // 2
|
||||
public static final Permission CREATE = new BasePermission(1 << 2, 'C'); // 4
|
||||
public static final Permission DELETE = new BasePermission(1 << 3, 'D'); // 8
|
||||
public static final Permission ADMINISTRATION = new BasePermission(1 << 4, 'A'); // 16
|
||||
|
||||
protected static DefaultPermissionFactory defaultPermissionFactory = new DefaultPermissionFactory();
|
||||
private static Map locallyDeclaredPermissionsByInteger = new HashMap();
|
||||
private static Map locallyDeclaredPermissionsByName = new HashMap();
|
||||
|
||||
/**
|
||||
* Registers the public static permissions defined on this class. This is mandatory so
|
||||
* that the static methods will operate correctly.
|
||||
*/
|
||||
static {
|
||||
registerPermissionsFor(BasePermission.class);
|
||||
Field[] fields = BasePermission.class.getDeclaredFields();
|
||||
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
try {
|
||||
Object fieldValue = fields[i].get(null);
|
||||
|
||||
if (BasePermission.class.isAssignableFrom(fieldValue.getClass())) {
|
||||
// Found a BasePermission static field
|
||||
BasePermission perm = (BasePermission) fieldValue;
|
||||
locallyDeclaredPermissionsByInteger.put(new Integer(perm.getMask()), perm);
|
||||
locallyDeclaredPermissionsByName.put(fields[i].getName(), perm);
|
||||
}
|
||||
} catch (Exception ignore) {}
|
||||
}
|
||||
}
|
||||
|
||||
protected BasePermission(int mask, char code) {
|
||||
super(mask, code);
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private char code;
|
||||
private int mask;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
private BasePermission(int mask, char code) {
|
||||
this.mask = mask;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
protected final static void registerPermissionsFor(Class subClass) {
|
||||
defaultPermissionFactory.registerPublicPermissions(subClass);
|
||||
}
|
||||
|
||||
public final static Permission buildFromMask(int mask) {
|
||||
return defaultPermissionFactory.buildFromMask(mask);
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Dynamically creates a <code>CumulativePermission</code> or <code>BasePermission</code> representing the
|
||||
* active bits in the passed mask.
|
||||
*
|
||||
* @param mask to build
|
||||
*
|
||||
* @return a Permission representing the requested object
|
||||
*/
|
||||
public static Permission buildFromMask(int mask) {
|
||||
if (locallyDeclaredPermissionsByInteger.containsKey(new Integer(mask))) {
|
||||
// The requested mask has an exactly match against a statically-defined BasePermission, so return it
|
||||
return (Permission) locallyDeclaredPermissionsByInteger.get(new Integer(mask));
|
||||
}
|
||||
|
||||
// To get this far, we have to use a CumulativePermission
|
||||
CumulativePermission permission = new CumulativePermission();
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
int permissionToCheck = 1 << i;
|
||||
|
||||
if ((mask & permissionToCheck) == permissionToCheck) {
|
||||
Permission p = (Permission) locallyDeclaredPermissionsByInteger.get(new Integer(permissionToCheck));
|
||||
Assert.state(p != null,
|
||||
"Mask " + permissionToCheck + " does not have a corresponding static BasePermission");
|
||||
permission.set(p);
|
||||
}
|
||||
}
|
||||
|
||||
return permission;
|
||||
}
|
||||
|
||||
public final static Permission[] buildFromMask(int[] masks) {
|
||||
return defaultPermissionFactory.buildFromMask(masks);
|
||||
public static Permission[] buildFromMask(int[] masks) {
|
||||
if ((masks == null) || (masks.length == 0)) {
|
||||
return new Permission[0];
|
||||
}
|
||||
|
||||
Permission[] permissions = new Permission[masks.length];
|
||||
|
||||
for (int i = 0; i < masks.length; i++) {
|
||||
permissions[i] = buildFromMask(masks[i]);
|
||||
}
|
||||
|
||||
return permissions;
|
||||
}
|
||||
|
||||
public final static Permission buildFromName(String name) {
|
||||
return defaultPermissionFactory.buildFromName(name);
|
||||
public static Permission buildFromName(String name) {
|
||||
Assert.isTrue(locallyDeclaredPermissionsByName.containsKey(name), "Unknown permission '" + name + "'");
|
||||
|
||||
return (Permission) locallyDeclaredPermissionsByName.get(name);
|
||||
}
|
||||
|
||||
public final static Permission[] buildFromName(String[] names) {
|
||||
return defaultPermissionFactory.buildFromName(names);
|
||||
public static Permission[] buildFromName(String[] names) {
|
||||
if ((names == null) || (names.length == 0)) {
|
||||
return new Permission[0];
|
||||
}
|
||||
|
||||
Permission[] permissions = new Permission[names.length];
|
||||
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
permissions[i] = buildFromName(names[i]);
|
||||
}
|
||||
|
||||
return permissions;
|
||||
}
|
||||
|
||||
}
|
||||
public boolean equals(Object arg0) {
|
||||
if (arg0 == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(arg0 instanceof Permission)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Permission rhs = (Permission) arg0;
|
||||
|
||||
return (this.mask == rhs.getMask());
|
||||
}
|
||||
|
||||
public int getMask() {
|
||||
return mask;
|
||||
}
|
||||
|
||||
public String getPattern() {
|
||||
return AclFormattingUtils.printBinary(mask, code);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "BasePermission[" + getPattern() + "=" + mask + "]";
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.mask;
|
||||
}
|
||||
}
|
||||
|
||||
+38
-12
@@ -19,21 +19,20 @@ import org.springframework.security.acls.Permission;
|
||||
|
||||
|
||||
/**
|
||||
* Represents a <code>Permission</code> that is constructed at runtime from other permissions.
|
||||
*
|
||||
* <p>Methods return <code>this</code>, in order to facilitate method chaining.</p>
|
||||
* Represents a <code>Permission</code> that is constructed at runtime from other permissions.<p>Methods return
|
||||
* <code>this</code>, in order to facilitate method chaining.</p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class CumulativePermission extends AbstractPermission {
|
||||
public class CumulativePermission implements Permission {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private String pattern = THIRTY_TWO_RESERVED_OFF;
|
||||
private int mask = 0;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public CumulativePermission() {
|
||||
super(0, ' ');
|
||||
}
|
||||
|
||||
public CumulativePermission clear(Permission permission) {
|
||||
this.mask &= ~permission.getMask();
|
||||
this.pattern = AclFormattingUtils.demergePatterns(this.pattern, permission.getPattern());
|
||||
@@ -47,16 +46,43 @@ public class CumulativePermission extends AbstractPermission {
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public boolean equals(Object arg0) {
|
||||
if (arg0 == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(arg0 instanceof Permission)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Permission rhs = (Permission) arg0;
|
||||
|
||||
return (this.mask == rhs.getMask());
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.mask;
|
||||
}
|
||||
|
||||
public int getMask() {
|
||||
return this.mask;
|
||||
}
|
||||
|
||||
public String getPattern() {
|
||||
return this.pattern;
|
||||
}
|
||||
|
||||
public CumulativePermission set(Permission permission) {
|
||||
this.mask |= permission.getMask();
|
||||
this.pattern = AclFormattingUtils.mergePatterns(this.pattern, permission.getPattern());
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getPattern() {
|
||||
return this.pattern;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "CumulativePermission[" + pattern + "=" + this.mask + "]";
|
||||
}
|
||||
}
|
||||
|
||||
-127
@@ -1,127 +0,0 @@
|
||||
package org.springframework.security.acls.domain;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.security.acls.Permission;
|
||||
import org.springframework.security.acls.jdbc.LookupStrategy;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link PermissionFactory}.
|
||||
*
|
||||
* <p>
|
||||
* Generally this class will be used by a {@link Permission} instance, as opposed to being dependency
|
||||
* injected into a {@link LookupStrategy} or similar. Nevertheless, the latter mode of operation is
|
||||
* fully supported (in which case your {@link Permission} implementations probably should extend
|
||||
* {@link AbstractPermission} instead of {@link AbstractRegisteredPermission}).
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @since 2.0.3
|
||||
*
|
||||
*/
|
||||
public class DefaultPermissionFactory implements PermissionFactory {
|
||||
private Map registeredPermissionsByInteger = new HashMap();
|
||||
private Map registeredPermissionsByName = new HashMap();
|
||||
|
||||
/**
|
||||
* Permit registration of a {@link DefaultPermissionFactory} class. The class must provide
|
||||
* public static fields of type {@link Permission} to represent the possible permissions.
|
||||
*
|
||||
* @param clazz a {@link Permission} class with public static fields to register
|
||||
*/
|
||||
public void registerPublicPermissions(Class clazz) {
|
||||
Assert.notNull(clazz, "Class required");
|
||||
Assert.isAssignable(Permission.class, clazz);
|
||||
|
||||
Field[] fields = clazz.getFields();
|
||||
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
try {
|
||||
Object fieldValue = fields[i].get(null);
|
||||
|
||||
if (Permission.class.isAssignableFrom(fieldValue.getClass())) {
|
||||
// Found a Permission static field
|
||||
Permission perm = (Permission) fieldValue;
|
||||
String permissionName = fields[i].getName();
|
||||
|
||||
registerPermission(perm, permissionName);
|
||||
}
|
||||
} catch (Exception ignore) {}
|
||||
}
|
||||
}
|
||||
|
||||
public void registerPermission(Permission perm, String permissionName) {
|
||||
Assert.notNull(perm, "Permission required");
|
||||
Assert.hasText(permissionName, "Permission name required");
|
||||
|
||||
Integer mask = new Integer(perm.getMask());
|
||||
|
||||
// Ensure no existing Permission uses this integer or code
|
||||
Assert.isTrue(!registeredPermissionsByInteger.containsKey(mask), "An existing Permission already provides mask " + mask);
|
||||
Assert.isTrue(!registeredPermissionsByName.containsKey(permissionName), "An existing Permission already provides name '" + permissionName + "'");
|
||||
|
||||
// Register the new Permission
|
||||
registeredPermissionsByInteger.put(mask, perm);
|
||||
registeredPermissionsByName.put(permissionName, perm);
|
||||
}
|
||||
|
||||
public Permission buildFromMask(int mask) {
|
||||
if (registeredPermissionsByInteger.containsKey(new Integer(mask))) {
|
||||
// The requested mask has an exactly match against a statically-defined Permission, so return it
|
||||
return (Permission) registeredPermissionsByInteger.get(new Integer(mask));
|
||||
}
|
||||
|
||||
// To get this far, we have to use a CumulativePermission
|
||||
CumulativePermission permission = new CumulativePermission();
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
int permissionToCheck = 1 << i;
|
||||
|
||||
if ((mask & permissionToCheck) == permissionToCheck) {
|
||||
Permission p = (Permission) registeredPermissionsByInteger.get(new Integer(permissionToCheck));
|
||||
Assert.state(p != null, "Mask " + permissionToCheck + " does not have a corresponding static Permission");
|
||||
permission.set(p);
|
||||
}
|
||||
}
|
||||
|
||||
return permission;
|
||||
}
|
||||
|
||||
public Permission[] buildFromMask(int[] masks) {
|
||||
if ((masks == null) || (masks.length == 0)) {
|
||||
return new Permission[0];
|
||||
}
|
||||
|
||||
Permission[] permissions = new Permission[masks.length];
|
||||
|
||||
for (int i = 0; i < masks.length; i++) {
|
||||
permissions[i] = buildFromMask(masks[i]);
|
||||
}
|
||||
|
||||
return permissions;
|
||||
}
|
||||
|
||||
public Permission buildFromName(String name) {
|
||||
Assert.isTrue(registeredPermissionsByName.containsKey(name), "Unknown permission '" + name + "'");
|
||||
|
||||
return (Permission) registeredPermissionsByName.get(name);
|
||||
}
|
||||
|
||||
public Permission[] buildFromName(String[] names) {
|
||||
if ((names == null) || (names.length == 0)) {
|
||||
return new Permission[0];
|
||||
}
|
||||
|
||||
Permission[] permissions = new Permission[names.length];
|
||||
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
permissions[i] = buildFromName(names[i]);
|
||||
}
|
||||
|
||||
return permissions;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package org.springframework.security.acls.domain;
|
||||
|
||||
import org.springframework.security.acls.Permission;
|
||||
|
||||
/**
|
||||
* Provides a simple mechanism to retrieve {@link Permission} instances from integer masks.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @since 2.0.3
|
||||
*
|
||||
*/
|
||||
public interface PermissionFactory {
|
||||
|
||||
/**
|
||||
* Dynamically creates a <code>CumulativePermission</code> or <code>BasePermission</code> representing the
|
||||
* active bits in the passed mask.
|
||||
*
|
||||
* @param mask to build
|
||||
*
|
||||
* @return a Permission representing the requested object
|
||||
*/
|
||||
public abstract Permission buildFromMask(int mask);
|
||||
|
||||
}
|
||||
@@ -18,14 +18,12 @@ import java.lang.reflect.Field;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
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.Vector;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
@@ -51,7 +49,6 @@ import org.springframework.security.acls.sid.PrincipalSid;
|
||||
import org.springframework.security.acls.sid.Sid;
|
||||
import org.springframework.security.util.FieldUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
||||
/**
|
||||
@@ -175,33 +172,14 @@ public final class BasicLookupStrategy implements LookupStrategy {
|
||||
auditLogger, parent, null, inputAcl.isEntriesInheriting(), inputAcl.getOwner());
|
||||
|
||||
// Copy the "aces" from the input to the destination
|
||||
Field fieldAces = FieldUtils.getField(AclImpl.class, "aces");
|
||||
Field fieldAcl = FieldUtils.getField(AccessControlEntryImpl.class, "acl");
|
||||
|
||||
Field field = FieldUtils.getField(AclImpl.class, "aces");
|
||||
|
||||
try {
|
||||
fieldAces.setAccessible(true);
|
||||
fieldAcl.setAccessible(true);
|
||||
|
||||
// Obtain the "aces" from the input ACL
|
||||
Iterator i = ((List) fieldAces.get(inputAcl)).iterator();
|
||||
|
||||
// Create a list in which to store the "aces" for the "result" AclImpl instance
|
||||
List acesNew = new ArrayList();
|
||||
|
||||
// Iterate over the "aces" input and replace each nested AccessControlEntryImpl.getAcl() with the new "result" AclImpl instance
|
||||
// This ensures StubAclParent instances are removed, as per SEC-951
|
||||
while(i.hasNext()) {
|
||||
AccessControlEntryImpl ace = (AccessControlEntryImpl) i.next();
|
||||
fieldAcl.set(ace, result);
|
||||
acesNew.add(ace);
|
||||
}
|
||||
|
||||
// Finally, now that the "aces" have been converted to have the "result" AclImpl instance, modify the "result" AclImpl instance
|
||||
fieldAces.set(result, acesNew);
|
||||
field.setAccessible(true);
|
||||
field.set(result, field.get(inputAcl));
|
||||
} catch (IllegalAccessException ex) {
|
||||
throw new IllegalStateException("Could not obtain or set AclImpl or AccessControlEntryImpl fields");
|
||||
throw new IllegalStateException("Could not obtain or set AclImpl.ace field");
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -261,8 +239,7 @@ public final class BasicLookupStrategy implements LookupStrategy {
|
||||
recipient = new GrantedAuthoritySid(rs.getString("ace_sid"));
|
||||
}
|
||||
|
||||
int mask = rs.getInt("mask");
|
||||
Permission permission = convertMaskIntoPermission(mask);
|
||||
Permission permission = BasePermission.buildFromMask(rs.getInt("mask"));
|
||||
boolean granting = rs.getBoolean("granting");
|
||||
boolean auditSuccess = rs.getBoolean("audit_success");
|
||||
boolean auditFailure = rs.getBoolean("audit_failure");
|
||||
@@ -287,10 +264,6 @@ public final class BasicLookupStrategy implements LookupStrategy {
|
||||
}
|
||||
}
|
||||
|
||||
protected Permission convertMaskIntoPermission(int mask) {
|
||||
return BasePermission.buildFromMask(mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up a batch of <code>ObjectIdentity</code>s directly from the database.<p>The caller is responsible
|
||||
* for optimization issues, such as selecting the identities to lookup, ensuring the cache doesn't contain them
|
||||
@@ -320,10 +293,10 @@ public final class BasicLookupStrategy implements LookupStrategy {
|
||||
for (int i = 0; i < objectIdentities.length; i++) {
|
||||
// Determine prepared statement values for this iteration
|
||||
String javaType = objectIdentities[i].getJavaType().getName();
|
||||
Assert.isInstanceOf(Long.class, objectIdentities[i].getIdentifier(),
|
||||
"This class requires ObjectIdentity.getIdentifier() to be a Long");
|
||||
|
||||
// No need to check for nulls, as guaranteed non-null by ObjectIdentity.getIdentifier() interface contract
|
||||
String identifier = objectIdentities[i].getIdentifier().toString();
|
||||
long id = (Long.valueOf(identifier)).longValue();
|
||||
long id = ((Long) objectIdentities[i].getIdentifier()).longValue();
|
||||
|
||||
// Inject values
|
||||
ps.setLong((2 * i) + 1, id);
|
||||
|
||||
@@ -53,7 +53,7 @@ public class JdbcAclService implements AclService {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
protected static final Log log = LogFactory.getLog(JdbcAclService.class);
|
||||
private static final String selectAclObjectWithParent = "select obj.object_id_identity as obj_id, class.class as class "
|
||||
private static final String selectAclObjectWithParent = "select obj.object_id_identity obj_id, class.class class "
|
||||
+ "from acl_object_identity obj, acl_object_identity parent, acl_class class "
|
||||
+ "where obj.parent_object = parent.id and obj.object_id_class = class.id "
|
||||
+ "and parent.object_id_identity = ? and parent.object_id_class = ("
|
||||
|
||||
+5
-10
@@ -64,8 +64,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
||||
private 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()"; // should be overridden for postgres : select currval('acl_class_seq')
|
||||
private String sidIdentityQuery = "call identity()"; // should be overridden for postgres : select currval('acl_siq_seq')
|
||||
private String identityQuery = "call identity()";
|
||||
private String insertClass = "insert into acl_class (class) values (?)";
|
||||
private String insertEntry = "insert into acl_entry "
|
||||
+ "(acl_object_identity, ace_order, sid, mask, granting, audit_success, audit_failure)"
|
||||
@@ -177,7 +176,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
||||
jdbcTemplate.update(insertClass, new Object[] {clazz.getName()});
|
||||
Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(),
|
||||
"Transaction must be running");
|
||||
classId = new Long(jdbcTemplate.queryForLong(classIdentityQuery));
|
||||
classId = new Long(jdbcTemplate.queryForLong(identityQuery));
|
||||
}
|
||||
} else {
|
||||
classId = (Long) classIds.iterator().next();
|
||||
@@ -222,7 +221,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
||||
jdbcTemplate.update(insertSid, new Object[] {new Boolean(principal), sidName});
|
||||
Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(),
|
||||
"Transaction must be running");
|
||||
sidId = new Long(jdbcTemplate.queryForLong(sidIdentityQuery));
|
||||
sidId = new Long(jdbcTemplate.queryForLong(identityQuery));
|
||||
}
|
||||
} else {
|
||||
sidId = (Long) sidIds.iterator().next();
|
||||
@@ -381,15 +380,11 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
||||
}
|
||||
}
|
||||
|
||||
public void setClassIdentityQuery(String identityQuery) {
|
||||
public void setIdentityQuery(String identityQuery) {
|
||||
Assert.hasText(identityQuery, "New identity query is required");
|
||||
this.classIdentityQuery = identityQuery;
|
||||
this.identityQuery = identityQuery;
|
||||
}
|
||||
|
||||
public void setSidIdentityQuery(String identityQuery) {
|
||||
Assert.hasText(identityQuery, "New identity query is required");
|
||||
this.sidIdentityQuery = identityQuery;
|
||||
}
|
||||
/**
|
||||
* @param foreignKeysInDatabase if false this class will perform additional FK constrain checking, which may
|
||||
* cause deadlocks (the default is true, so deadlocks are avoided but the database is expected to enforce FKs)
|
||||
|
||||
+1
-8
@@ -15,7 +15,6 @@
|
||||
package org.springframework.security.acls.objectidentity;
|
||||
|
||||
import org.springframework.security.acls.IdentityUnavailableException;
|
||||
import org.springframework.security.acls.jdbc.LookupStrategy;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
@@ -98,12 +97,6 @@ public class ObjectIdentityImpl implements ObjectIdentity {
|
||||
/**
|
||||
* Important so caching operates properly.<P>Considers an object of the same class equal if it has the same
|
||||
* <code>classname</code> and <code>id</code> properties.</p>
|
||||
*
|
||||
* <p>
|
||||
* Note that this class uses string equality for the identifier field, which ensures it better supports
|
||||
* differences between {@link LookupStrategy} requirements and the domain object represented by this
|
||||
* <code>ObjectIdentityImpl</code>.
|
||||
* </p>
|
||||
*
|
||||
* @param arg0 object to compare
|
||||
*
|
||||
@@ -120,7 +113,7 @@ public class ObjectIdentityImpl implements ObjectIdentity {
|
||||
|
||||
ObjectIdentityImpl other = (ObjectIdentityImpl) arg0;
|
||||
|
||||
if (this.getIdentifier().toString().equals(other.getIdentifier().toString()) && this.getJavaType().equals(other.getJavaType())) {
|
||||
if (this.getIdentifier().equals(other.getIdentifier()) && this.getJavaType().equals(other.getJavaType())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+9
-9
@@ -34,20 +34,20 @@ import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* Abstract {@link AfterInvocationProvider} which provides commonly-used ACL-related services.
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
* @author $author$
|
||||
* @version $Revision$
|
||||
*/
|
||||
public abstract class AbstractAclProvider implements AfterInvocationProvider {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
protected AclService aclService;
|
||||
protected Class processDomainObjectClass = Object.class;
|
||||
protected ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl();
|
||||
protected SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();
|
||||
protected String processConfigAttribute;
|
||||
protected Permission[] requirePermission = {BasePermission.READ};
|
||||
private AclService aclService;
|
||||
private Class processDomainObjectClass = Object.class;
|
||||
private ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl();
|
||||
private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();
|
||||
private String processConfigAttribute;
|
||||
private Permission[] requirePermission = {BasePermission.READ};
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ import org.springframework.security.acls.Permission;
|
||||
|
||||
|
||||
/**
|
||||
* Tests classes associated with Permission.
|
||||
* Tests BasePermission and CumulativePermission.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id${date}
|
||||
@@ -32,12 +32,6 @@ public class PermissionTests {
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
@Test
|
||||
public void basePermissionTest() {
|
||||
Permission p = BasePermission.buildFromName("WRITE");
|
||||
assertNotNull(p);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void expectedIntegerValues() {
|
||||
assertEquals(1, BasePermission.READ.getMask());
|
||||
@@ -69,9 +63,9 @@ public class PermissionTests {
|
||||
assertEquals("CumulativePermission[...............................R=1]",
|
||||
new CumulativePermission().set(BasePermission.READ).toString());
|
||||
|
||||
System.out.println("A = " + new CumulativePermission().set(SpecialPermission.ENTER).set(BasePermission.ADMINISTRATION).toString());
|
||||
assertEquals("CumulativePermission[..........................EA....=48]",
|
||||
new CumulativePermission().set(SpecialPermission.ENTER).set(BasePermission.ADMINISTRATION).toString());
|
||||
System.out.println("A = " + new CumulativePermission().set(BasePermission.ADMINISTRATION).toString());
|
||||
assertEquals("CumulativePermission[...........................A....=16]",
|
||||
new CumulativePermission().set(BasePermission.ADMINISTRATION).toString());
|
||||
|
||||
System.out.println("RA = "
|
||||
+ new CumulativePermission().set(BasePermission.ADMINISTRATION).set(BasePermission.READ).toString());
|
||||
|
||||
@@ -1,40 +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.acls.domain;
|
||||
|
||||
import org.springframework.security.acls.Permission;
|
||||
|
||||
|
||||
/**
|
||||
* A test permission.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class SpecialPermission extends BasePermission {
|
||||
public static final Permission ENTER = new SpecialPermission(1 << 5, 'E'); // 32
|
||||
|
||||
/**
|
||||
* Registers the public static permissions defined on this class. This is mandatory so
|
||||
* that the static methods will operate correctly.
|
||||
*/
|
||||
static {
|
||||
registerPermissionsFor(SpecialPermission.class);
|
||||
}
|
||||
|
||||
protected SpecialPermission(int mask, char code) {
|
||||
super(mask, code);
|
||||
}
|
||||
}
|
||||
+23
-7
@@ -120,8 +120,7 @@ public class BasicLookupStrategyTests {
|
||||
public void testAclsRetrievalWithDefaultBatchSize() throws Exception {
|
||||
ObjectIdentity topParentOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Long(100));
|
||||
ObjectIdentity middleParentOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Long(101));
|
||||
// Deliberately use an integer for the child, to reproduce bug report in SEC-819
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Integer(102));
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Long(102));
|
||||
|
||||
Map map = this.strategy.readAclsById(new ObjectIdentity[] { topParentOid, middleParentOid, childOid }, null);
|
||||
checkEntries(topParentOid, middleParentOid, childOid, map);
|
||||
@@ -129,7 +128,7 @@ public class BasicLookupStrategyTests {
|
||||
|
||||
@Test
|
||||
public void testAclsRetrievalFromCacheOnly() throws Exception {
|
||||
ObjectIdentity topParentOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Integer(100));
|
||||
ObjectIdentity topParentOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Long(100));
|
||||
ObjectIdentity middleParentOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Long(101));
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Long(102));
|
||||
|
||||
@@ -146,7 +145,7 @@ public class BasicLookupStrategyTests {
|
||||
@Test
|
||||
public void testAclsRetrievalWithCustomBatchSize() throws Exception {
|
||||
ObjectIdentity topParentOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Long(100));
|
||||
ObjectIdentity middleParentOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Integer(101));
|
||||
ObjectIdentity middleParentOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Long(101));
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Long(102));
|
||||
|
||||
// Set a batch size to allow multiple database queries in order to retrieve all acls
|
||||
@@ -228,7 +227,7 @@ public class BasicLookupStrategyTests {
|
||||
jdbcTemplate.execute(query);
|
||||
|
||||
ObjectIdentity topParentOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Long(100));
|
||||
ObjectIdentity middleParentOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Integer(101));
|
||||
ObjectIdentity middleParentOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Long(101));
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Long(102));
|
||||
ObjectIdentity middleParent2Oid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Long(103));
|
||||
|
||||
@@ -261,8 +260,8 @@ public class BasicLookupStrategyTests {
|
||||
|
||||
ObjectIdentity grandParentOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Long(104));
|
||||
ObjectIdentity parent1Oid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Long(105));
|
||||
ObjectIdentity parent2Oid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Integer(106));
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Integer(107));
|
||||
ObjectIdentity parent2Oid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Long(106));
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Long(107));
|
||||
|
||||
// First lookup only child, thus populating the cache with grandParent, parent1 and child
|
||||
Permission[] checkPermission = new Permission[] { BasePermission.READ };
|
||||
@@ -291,4 +290,21 @@ public class BasicLookupStrategyTests {
|
||||
Assert.assertTrue(foundParent2Acl.isGranted(checkPermission, sids, false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAclsWithDifferentSerializableTypesAsObjectIdentities() throws Exception {
|
||||
String query = "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (4,2,104,null,1,1);"
|
||||
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (5,4,0,1,1,1,0,0)";
|
||||
jdbcTemplate.execute(query);
|
||||
|
||||
ObjectIdentity oid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Integer(104));
|
||||
Sid[] sids = new Sid[] { new PrincipalSid("ben") };
|
||||
ObjectIdentity[] childOids = new ObjectIdentity[] { oid };
|
||||
|
||||
try {
|
||||
Map foundAcls = strategy.readAclsById(childOids, sids);
|
||||
Assert.fail("It should have thrown IllegalArgumentException");
|
||||
} catch(IllegalArgumentException expected) {
|
||||
Assert.assertTrue(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -97,7 +97,7 @@ public class JdbcAclServiceTests extends AbstractTransactionalDataSourceSpringCo
|
||||
|
||||
ObjectIdentity topParentOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Long(100));
|
||||
ObjectIdentity middleParentOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Long(101));
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Integer(102));
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Long(102));
|
||||
|
||||
MutableAcl topParent = jdbcMutableAclService.createAcl(topParentOid);
|
||||
MutableAcl middleParent = jdbcMutableAclService.createAcl(middleParentOid);
|
||||
@@ -337,7 +337,7 @@ public class JdbcAclServiceTests extends AbstractTransactionalDataSourceSpringCo
|
||||
|
||||
ObjectIdentity topParentOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Long(100));
|
||||
ObjectIdentity middleParentOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Long(101));
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Integer(102));
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl("org.springframework.security.TargetObject", new Long(102));
|
||||
|
||||
// Remove the child and check all related database rows were removed accordingly
|
||||
jdbcMutableAclService.deleteAcl(childOid, false);
|
||||
|
||||
@@ -53,7 +53,7 @@ public class SidTests extends TestCase {
|
||||
}
|
||||
|
||||
try {
|
||||
Authentication authentication = new TestingAuthenticationToken(null, "password");
|
||||
Authentication authentication = new TestingAuthenticationToken(null, "password", null);
|
||||
Sid principalSid = new PrincipalSid(authentication);
|
||||
Assert.fail("It should have thrown IllegalArgumentException");
|
||||
}
|
||||
@@ -62,7 +62,7 @@ public class SidTests extends TestCase {
|
||||
}
|
||||
|
||||
try {
|
||||
Authentication authentication = new TestingAuthenticationToken("johndoe", "password");
|
||||
Authentication authentication = new TestingAuthenticationToken("johndoe", "password", null);
|
||||
Sid principalSid = new PrincipalSid(authentication);
|
||||
Assert.assertTrue(true);
|
||||
}
|
||||
@@ -128,15 +128,15 @@ public class SidTests extends TestCase {
|
||||
}
|
||||
|
||||
public void testPrincipalSidEquals() throws Exception {
|
||||
Authentication authentication = new TestingAuthenticationToken("johndoe", "password");
|
||||
Authentication authentication = new TestingAuthenticationToken("johndoe", "password", null);
|
||||
Sid principalSid = new PrincipalSid(authentication);
|
||||
|
||||
Assert.assertFalse(principalSid.equals(null));
|
||||
Assert.assertFalse(principalSid.equals("DIFFERENT_TYPE_OBJECT"));
|
||||
Assert.assertTrue(principalSid.equals(principalSid));
|
||||
Assert.assertTrue(principalSid.equals(new PrincipalSid(authentication)));
|
||||
Assert.assertTrue(principalSid.equals(new PrincipalSid(new TestingAuthenticationToken("johndoe", null))));
|
||||
Assert.assertFalse(principalSid.equals(new PrincipalSid(new TestingAuthenticationToken("scott", null))));
|
||||
Assert.assertTrue(principalSid.equals(new PrincipalSid(new TestingAuthenticationToken("johndoe", null, null))));
|
||||
Assert.assertFalse(principalSid.equals(new PrincipalSid(new TestingAuthenticationToken("scott", null, null))));
|
||||
Assert.assertTrue(principalSid.equals(new PrincipalSid("johndoe")));
|
||||
Assert.assertFalse(principalSid.equals(new PrincipalSid("scott")));
|
||||
}
|
||||
@@ -156,13 +156,14 @@ public class SidTests extends TestCase {
|
||||
}
|
||||
|
||||
public void testPrincipalSidHashCode() throws Exception {
|
||||
Authentication authentication = new TestingAuthenticationToken("johndoe", "password");
|
||||
Authentication authentication = new TestingAuthenticationToken("johndoe", "password", null);
|
||||
Sid principalSid = new PrincipalSid(authentication);
|
||||
|
||||
Assert.assertTrue(principalSid.hashCode() == new String("johndoe").hashCode());
|
||||
Assert.assertTrue(principalSid.hashCode() == new PrincipalSid("johndoe").hashCode());
|
||||
Assert.assertTrue(principalSid.hashCode() != new PrincipalSid("scott").hashCode());
|
||||
Assert.assertTrue(principalSid.hashCode() != new PrincipalSid(new TestingAuthenticationToken("scott", "password")).hashCode());
|
||||
Assert.assertTrue(principalSid.hashCode() != new PrincipalSid(new TestingAuthenticationToken("scott", "password",
|
||||
null)).hashCode());
|
||||
}
|
||||
|
||||
public void testGrantedAuthoritySidHashCode() throws Exception {
|
||||
@@ -176,7 +177,7 @@ public class SidTests extends TestCase {
|
||||
}
|
||||
|
||||
public void testGetters() throws Exception {
|
||||
Authentication authentication = new TestingAuthenticationToken("johndoe", "password");
|
||||
Authentication authentication = new TestingAuthenticationToken("johndoe", "password", null);
|
||||
PrincipalSid principalSid = new PrincipalSid(authentication);
|
||||
GrantedAuthority ga = new GrantedAuthorityImpl("ROLE_TEST");
|
||||
GrantedAuthoritySid gaSid = new GrantedAuthoritySid(ga);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-adapters</artifactId>
|
||||
<version>2.0.4</version>
|
||||
<version>2.0.2</version>
|
||||
</parent>
|
||||
<artifactId>spring-security-catalina</artifactId>
|
||||
<name>Spring Security - Catalina adapter</name>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-adapters</artifactId>
|
||||
<version>2.0.4</version>
|
||||
<version>2.0.2</version>
|
||||
</parent>
|
||||
<artifactId>spring-security-jboss</artifactId>
|
||||
<name>Spring Security - JBoss adapter</name>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-adapters</artifactId>
|
||||
<version>2.0.4</version>
|
||||
<version>2.0.2</version>
|
||||
</parent>
|
||||
<artifactId>spring-security-jetty</artifactId>
|
||||
<name>Spring Security - Jetty adapter</name>
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-parent</artifactId>
|
||||
<version>2.0.4</version>
|
||||
<version>2.0.2</version>
|
||||
</parent>
|
||||
<artifactId>spring-security-adapters</artifactId>
|
||||
<name>Spring Security - Adapters</name>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-adapters</artifactId>
|
||||
<version>2.0.4</version>
|
||||
<version>2.0.2</version>
|
||||
</parent>
|
||||
<artifactId>spring-security-resin</artifactId>
|
||||
<name>Spring Security - Resin adapter</name>
|
||||
|
||||
+3
-10
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-parent</artifactId>
|
||||
<version>2.0.4</version>
|
||||
<version>2.0.2</version>
|
||||
</parent>
|
||||
<artifactId>spring-security-cas-client</artifactId>
|
||||
<name>Spring Security - CAS support</name>
|
||||
@@ -15,13 +15,6 @@
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<classifier>tests</classifier>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-dao</artifactId>
|
||||
@@ -38,7 +31,7 @@
|
||||
<dependency>
|
||||
<groupId>org.jasig.cas</groupId>
|
||||
<artifactId>cas-client-core</artifactId>
|
||||
<version>3.1.3</version>
|
||||
<version>3.1.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.sf.ehcache</groupId>
|
||||
@@ -61,7 +54,7 @@
|
||||
javax.servlet.*;version="[2.4.0, 3.0.0)";resolution:=optional,
|
||||
net.sf.ehcache.*;version="[1.4.1, 2.0.0)";resolution:=optional,
|
||||
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
|
||||
org.jasig.cas.client.*;version="[3.1.3, 4.0.0)"
|
||||
org.jasig.cas.client.*;version="[3.1.1, 4.0.0)"
|
||||
</spring.osgi.import>
|
||||
|
||||
<spring.osgi.private.pkg>
|
||||
|
||||
@@ -15,11 +15,6 @@
|
||||
|
||||
package org.springframework.security.ui.cas;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
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;
|
||||
import org.springframework.security.AuthenticationException;
|
||||
|
||||
@@ -29,7 +24,6 @@ import org.springframework.security.ui.AbstractProcessingFilter;
|
||||
import org.springframework.security.ui.FilterChainOrder;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
||||
/**
|
||||
@@ -44,11 +38,7 @@ import javax.servlet.http.HttpServletResponse;
|
||||
* <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>
|
||||
* <p>By configuring a shared {@link ProxyGrantingTicketStorage} between the {@link TicketValidator} and the CasProcessingFilter
|
||||
* one can have the CasProcessingFilter 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><b>Do not use this class directly.</b> Instead configure <code>web.xml</code> to use the {@link
|
||||
* <p><b>Do not use this class directly.</b> Instead configure <code>web.xml</code> to use the {@link
|
||||
* org.springframework.security.util.FilterToBeanProxy}.</p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
@@ -67,17 +57,8 @@ public class CasProcessingFilter extends AbstractProcessingFilter {
|
||||
*/
|
||||
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;
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
public Authentication attemptAuthentication(final HttpServletRequest request)
|
||||
throws AuthenticationException {
|
||||
final String username = CAS_STATEFUL_IDENTIFIER;
|
||||
@@ -106,35 +87,4 @@ public class CasProcessingFilter extends AbstractProcessingFilter {
|
||||
public int getOrder() {
|
||||
return FilterChainOrder.CAS_PROCESSING_FILTER;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+16
-7
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-parent</artifactId>
|
||||
<version>2.0.4</version>
|
||||
<version>2.0.2</version>
|
||||
</parent>
|
||||
<packaging>bundle</packaging>
|
||||
<artifactId>spring-security-core-tiger</artifactId>
|
||||
@@ -21,12 +21,7 @@
|
||||
<version>${project.version}</version>
|
||||
<classifier>tests</classifier>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-remoting</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjrt</artifactId>
|
||||
@@ -37,6 +32,20 @@
|
||||
<artifactId>aspectjweaver</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-support</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
|
||||
+2
-4
@@ -39,10 +39,8 @@ public interface BusinessService {
|
||||
public void someUserMethod1();
|
||||
|
||||
@Secured({"ROLE_USER"})
|
||||
@RolesAllowed({"ROLE_USER"})
|
||||
@RolesAllowed({"ROLE_USER"})
|
||||
public void someUserMethod2();
|
||||
|
||||
public int someOther(String s);
|
||||
|
||||
|
||||
public int someOther(int input);
|
||||
}
|
||||
|
||||
+3
-7
@@ -26,11 +26,7 @@ public class BusinessServiceImpl<E extends Entity> implements BusinessService {
|
||||
return entity;
|
||||
}
|
||||
|
||||
public int someOther(String s) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int someOther(int input) {
|
||||
return input;
|
||||
}
|
||||
public int someOther(int input) {
|
||||
return input;
|
||||
}
|
||||
}
|
||||
|
||||
+3
-7
@@ -27,11 +27,7 @@ public class Jsr250BusinessServiceImpl implements BusinessService {
|
||||
public void someAdminMethod() {
|
||||
}
|
||||
|
||||
public int someOther(String input) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int someOther(int input) {
|
||||
return input;
|
||||
}
|
||||
}
|
||||
return input;
|
||||
}
|
||||
}
|
||||
+14
-108
@@ -1,12 +1,13 @@
|
||||
package org.springframework.security.config;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.security.config.ConfigTestUtils.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
|
||||
import org.springframework.context.support.AbstractXmlApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.security.AccessDeniedException;
|
||||
import org.springframework.security.AuthenticationCredentialsNotFoundException;
|
||||
import org.springframework.security.GrantedAuthority;
|
||||
@@ -14,12 +15,10 @@ import org.springframework.security.GrantedAuthorityImpl;
|
||||
import org.springframework.security.annotation.BusinessService;
|
||||
import org.springframework.security.context.SecurityContextHolder;
|
||||
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.userdetails.UserDetailsService;
|
||||
import org.springframework.security.util.InMemoryXmlApplicationContext;
|
||||
|
||||
/**
|
||||
* @author Ben Alex
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
*/
|
||||
public class GlobalMethodSecurityBeanDefinitionParserTests {
|
||||
@@ -28,36 +27,29 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
||||
private BusinessService target;
|
||||
|
||||
public void loadContext() {
|
||||
setContext(
|
||||
"<b:bean id='target' class='org.springframework.security.annotation.BusinessServiceImpl'/>" +
|
||||
"<global-method-security>" +
|
||||
" <protect-pointcut expression='execution(* *.someUser*(..))' access='ROLE_USER'/>" +
|
||||
" <protect-pointcut expression='execution(* *.someAdmin*(..))' access='ROLE_ADMIN'/>" +
|
||||
"</global-method-security>" + ConfigTestUtils.AUTH_PROVIDER_XML
|
||||
);
|
||||
appContext = new ClassPathXmlApplicationContext("org/springframework/security/config/global-method-security.xml");
|
||||
target = (BusinessService) appContext.getBean("target");
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
public void closeAppContext() {
|
||||
if (appContext != null) {
|
||||
appContext.close();
|
||||
appContext = null;
|
||||
}
|
||||
SecurityContextHolder.clearContext();
|
||||
target = null;
|
||||
}
|
||||
|
||||
@Test(expected=AuthenticationCredentialsNotFoundException.class)
|
||||
public void targetShouldPreventProtectedMethodInvocationWithNoContext() {
|
||||
loadContext();
|
||||
loadContext();
|
||||
target.someUserMethod1();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void targetShouldAllowProtectedMethodInvocationWithCorrectRole() {
|
||||
loadContext();
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user", "password");
|
||||
loadContext();
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_USER")});
|
||||
SecurityContextHolder.getContext().setAuthentication(token);
|
||||
|
||||
target.someUserMethod1();
|
||||
@@ -65,19 +57,20 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
||||
|
||||
@Test(expected=AccessDeniedException.class)
|
||||
public void targetShouldPreventProtectedMethodInvocationWithIncorrectRole() {
|
||||
loadContext();
|
||||
loadContext();
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_SOMEOTHERROLE")});
|
||||
SecurityContextHolder.getContext().setAuthentication(token);
|
||||
|
||||
target.someAdminMethod();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void doesntInterfereWithBeanPostProcessing() {
|
||||
setContext(
|
||||
"<b:bean id='myUserService' class='org.springframework.security.config.PostProcessedMockUserDetailsService'/>" +
|
||||
"<global-method-security />" +
|
||||
// "<http auto-config='true'/>" +
|
||||
"<authentication-provider user-service-ref='myUserService'/>" +
|
||||
"<b:bean id='beanPostProcessor' class='org.springframework.security.config.MockUserServiceBeanPostProcessor'/>"
|
||||
);
|
||||
@@ -86,75 +79,7 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
||||
|
||||
assertEquals("Hello from the post processor!", service.getPostProcessorWasHere());
|
||||
}
|
||||
|
||||
@Test(expected=AccessDeniedException.class)
|
||||
public void worksWithAspectJAutoproxy() {
|
||||
setContext(
|
||||
"<global-method-security>" +
|
||||
" <protect-pointcut expression='execution(* org.springframework.security.config.*Service.*(..))'" +
|
||||
" access='ROLE_SOMETHING' />" +
|
||||
"</global-method-security>" +
|
||||
"<b:bean id='myUserService' class='org.springframework.security.config.PostProcessedMockUserDetailsService'/>" +
|
||||
"<aop:aspectj-autoproxy />" +
|
||||
"<authentication-provider user-service-ref='myUserService'/>"
|
||||
);
|
||||
|
||||
UserDetailsService service = (UserDetailsService) appContext.getBean("myUserService");
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_SOMEOTHERROLE")});
|
||||
SecurityContextHolder.getContext().setAuthentication(token);
|
||||
|
||||
service.loadUserByUsername("notused");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supportsMethodArgumentsInPointcut() {
|
||||
setContext(
|
||||
"<b:bean id='target' class='org.springframework.security.annotation.BusinessServiceImpl'/>" +
|
||||
"<global-method-security>" +
|
||||
" <protect-pointcut expression='execution(* org.springframework.security.annotation.BusinessService.someOther(String))' access='ROLE_ADMIN'/>" +
|
||||
" <protect-pointcut expression='execution(* org.springframework.security.annotation.BusinessService.*(..))' access='ROLE_USER'/>" +
|
||||
"</global-method-security>" + ConfigTestUtils.AUTH_PROVIDER_XML
|
||||
);
|
||||
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("user", "password"));
|
||||
target = (BusinessService) appContext.getBean("target");
|
||||
// someOther(int) should not be matched by someOther(String), but should require ROLE_USER
|
||||
target.someOther(0);
|
||||
|
||||
try {
|
||||
// String version should required admin role
|
||||
target.someOther("somestring");
|
||||
fail("Expected AccessDeniedException");
|
||||
} catch (AccessDeniedException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supportsBooleanPointcutExpressions() {
|
||||
setContext(
|
||||
"<b:bean id='target' class='org.springframework.security.annotation.BusinessServiceImpl'/>" +
|
||||
"<global-method-security>" +
|
||||
" <protect-pointcut expression=" +
|
||||
" 'execution(* org.springframework.security.annotation.BusinessService.*(..)) " +
|
||||
" and not execution(* org.springframework.security.annotation.BusinessService.someOther(String)))' " +
|
||||
" access='ROLE_USER'/>" +
|
||||
"</global-method-security>" + ConfigTestUtils.AUTH_PROVIDER_XML
|
||||
);
|
||||
target = (BusinessService) appContext.getBean("target");
|
||||
// String method should not be protected
|
||||
target.someOther("somestring");
|
||||
|
||||
// All others should require ROLE_USER
|
||||
try {
|
||||
target.someOther(0);
|
||||
fail("Expected AuthenticationCredentialsNotFoundException");
|
||||
} catch (AuthenticationCredentialsNotFoundException expected) {
|
||||
}
|
||||
|
||||
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("user", "password"));
|
||||
target.someOther(0);
|
||||
}
|
||||
|
||||
|
||||
@Test(expected=BeanDefinitionParsingException.class)
|
||||
public void duplicateElementCausesError() {
|
||||
setContext(
|
||||
@@ -162,27 +87,8 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
||||
"<global-method-security />"
|
||||
);
|
||||
}
|
||||
|
||||
@Test(expected=AccessDeniedException.class)
|
||||
public void worksWithoutTargetOrClass() {
|
||||
setContext(
|
||||
"<global-method-security secured-annotations='enabled'/>" +
|
||||
"<b:bean id='businessService' class='org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean'>" +
|
||||
" <b:property name='serviceUrl' value='http://localhost:8080/SomeService'/>" +
|
||||
" <b:property name='serviceInterface' value='org.springframework.security.annotation.BusinessService'/>" +
|
||||
"</b:bean>" + AUTH_PROVIDER_XML
|
||||
);
|
||||
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_SOMEOTHERROLE")});
|
||||
SecurityContextHolder.getContext().setAuthentication(token);
|
||||
target = (BusinessService) appContext.getBean("businessService");
|
||||
target.someUserMethod1();
|
||||
}
|
||||
|
||||
|
||||
private void setContext(String context) {
|
||||
appContext = new InMemoryXmlApplicationContext(context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+5
-8
@@ -3,6 +3,7 @@ package org.springframework.security.config;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.security.AccessDeniedException;
|
||||
import org.springframework.security.AuthenticationCredentialsNotFoundException;
|
||||
import org.springframework.security.GrantedAuthority;
|
||||
@@ -10,23 +11,19 @@ import org.springframework.security.GrantedAuthorityImpl;
|
||||
import org.springframework.security.annotation.BusinessService;
|
||||
import org.springframework.security.context.SecurityContextHolder;
|
||||
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.util.InMemoryXmlApplicationContext;
|
||||
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
*/
|
||||
public class Jsr250AnnotationDrivenBeanDefinitionParserTests {
|
||||
private InMemoryXmlApplicationContext appContext;
|
||||
private ClassPathXmlApplicationContext appContext;
|
||||
|
||||
private BusinessService target;
|
||||
|
||||
@Before
|
||||
public void loadContext() {
|
||||
appContext = new InMemoryXmlApplicationContext(
|
||||
"<b:bean id='target' class='org.springframework.security.annotation.Jsr250BusinessServiceImpl'/>" +
|
||||
"<global-method-security jsr250-annotations='enabled'/>" + ConfigTestUtils.AUTH_PROVIDER_XML
|
||||
);
|
||||
appContext = new ClassPathXmlApplicationContext("/org/springframework/security/config/jsr250-annotated-method-security.xml");
|
||||
target = (BusinessService) appContext.getBean("target");
|
||||
}
|
||||
|
||||
@@ -51,7 +48,7 @@ public class Jsr250AnnotationDrivenBeanDefinitionParserTests {
|
||||
|
||||
target.someOther(0);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void targetShouldAllowProtectedMethodInvocationWithCorrectRole() {
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
|
||||
@@ -69,4 +66,4 @@ public class Jsr250AnnotationDrivenBeanDefinitionParserTests {
|
||||
|
||||
target.someAdminMethod();
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-6
@@ -3,6 +3,7 @@ package org.springframework.security.config;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.security.AccessDeniedException;
|
||||
import org.springframework.security.AuthenticationCredentialsNotFoundException;
|
||||
import org.springframework.security.GrantedAuthority;
|
||||
@@ -10,23 +11,19 @@ import org.springframework.security.GrantedAuthorityImpl;
|
||||
import org.springframework.security.annotation.BusinessService;
|
||||
import org.springframework.security.context.SecurityContextHolder;
|
||||
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.util.InMemoryXmlApplicationContext;
|
||||
|
||||
/**
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class SecuredAnnotationDrivenBeanDefinitionParserTests {
|
||||
private InMemoryXmlApplicationContext appContext;
|
||||
private ClassPathXmlApplicationContext appContext;
|
||||
|
||||
private BusinessService target;
|
||||
|
||||
@Before
|
||||
public void loadContext() {
|
||||
appContext = new InMemoryXmlApplicationContext(
|
||||
"<b:bean id='target' class='org.springframework.security.annotation.Jsr250BusinessServiceImpl'/>" +
|
||||
"<global-method-security secured-annotations='enabled'/>" + ConfigTestUtils.AUTH_PROVIDER_XML
|
||||
);
|
||||
appContext = new ClassPathXmlApplicationContext("org/springframework/security/config/secured-annotated-method-security.xml");
|
||||
target = (BusinessService) appContext.getBean("target");
|
||||
}
|
||||
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<b:beans xmlns="http://www.springframework.org/schema/security"
|
||||
xmlns:b="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
|
||||
|
||||
<b:bean id="target" class="org.springframework.security.annotation.BusinessServiceImpl"/>
|
||||
|
||||
<global-method-security>
|
||||
<protect-pointcut expression="execution(* *.someUser*(..))" access="ROLE_USER"/>
|
||||
<protect-pointcut expression="execution(* *.someAdmin*(..))" access="ROLE_ADMIN"/>
|
||||
</global-method-security>
|
||||
|
||||
<authentication-provider>
|
||||
<user-service>
|
||||
<user name="bob" password="bobspassword" authorities="ROLE_A,ROLE_B" />
|
||||
<user name="bill" password="billspassword" authorities="ROLE_A,ROLE_B,AUTH_OTHER" />
|
||||
</user-service>
|
||||
</authentication-provider>
|
||||
|
||||
</b:beans>
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<b:beans xmlns="http://www.springframework.org/schema/security"
|
||||
xmlns:b="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
|
||||
|
||||
<b:bean id="target" class="org.springframework.security.annotation.Jsr250BusinessServiceImpl"/>
|
||||
|
||||
<global-method-security jsr250-annotations="enabled"/>
|
||||
|
||||
<authentication-provider>
|
||||
<user-service>
|
||||
<user name="bob" password="bobspassword" authorities="ROLE_A,ROLE_B" />
|
||||
<user name="bill" password="billspassword" authorities="ROLE_A,ROLE_B,AUTH_OTHER" />
|
||||
</user-service>
|
||||
</authentication-provider>
|
||||
|
||||
</b:beans>
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<b:beans xmlns="http://www.springframework.org/schema/security"
|
||||
xmlns:b="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
|
||||
|
||||
<b:bean id="target" class="org.springframework.security.annotation.Jsr250BusinessServiceImpl"/>
|
||||
|
||||
<global-method-security secured-annotations="enabled"/>
|
||||
|
||||
<authentication-provider>
|
||||
<user-service>
|
||||
<user name="bob" password="bobspassword" authorities="ROLE_A,ROLE_B" />
|
||||
<user name="bill" password="billspassword" authorities="ROLE_A,ROLE_B,AUTH_OTHER" />
|
||||
</user-service>
|
||||
</authentication-provider>
|
||||
|
||||
</b:beans>
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-parent</artifactId>
|
||||
<version>2.0.4</version>
|
||||
<version>2.0.2</version>
|
||||
</parent>
|
||||
<packaging>bundle</packaging>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
|
||||
@@ -21,13 +21,8 @@ import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* Basic concrete implementation of a {@link GrantedAuthority}.
|
||||
*
|
||||
* <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.
|
||||
* Basic concrete implementation of a {@link GrantedAuthority}.<p>Stores a <code>String</code> representation of an
|
||||
* authority granted to the {@link Authentication} object.</p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
@@ -41,6 +36,7 @@ public class GrantedAuthorityImpl implements GrantedAuthority, Serializable {
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public GrantedAuthorityImpl(String role) {
|
||||
super();
|
||||
Assert.hasText(role, "A granted authority textual representation is required");
|
||||
this.role = role;
|
||||
}
|
||||
@@ -75,13 +71,8 @@ public class GrantedAuthorityImpl implements GrantedAuthority, Serializable {
|
||||
|
||||
public int compareTo(Object o) {
|
||||
if (o != null && o instanceof GrantedAuthority) {
|
||||
String rhsRole = ((GrantedAuthority) o).getAuthority();
|
||||
|
||||
if (rhsRole == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return role.compareTo(rhsRole);
|
||||
GrantedAuthority rhs = (GrantedAuthority) o;
|
||||
return this.role.compareTo(rhs.getAuthority());
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
-167
@@ -1,167 +0,0 @@
|
||||
package org.springframework.security.authoritymapping;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.security.GrantedAuthority;
|
||||
import org.springframework.security.GrantedAuthorityImpl;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This class implements the Attributes2GrantedAuthoritiesMapper and
|
||||
* MappableAttributesRetriever interfaces based on the supplied Map.
|
||||
* It supports both one-to-one and one-to-many mappings. The granted
|
||||
* authorities to map to can be supplied either as a String or as a
|
||||
* GrantedAuthority object.
|
||||
* </p>
|
||||
* @author Ruud Senden
|
||||
*/
|
||||
public class MapBasedAttributes2GrantedAuthoritiesMapper implements Attributes2GrantedAuthoritiesMapper, MappableAttributesRetriever, InitializingBean {
|
||||
private Map attributes2grantedAuthoritiesMap = null;
|
||||
private String stringSeparator = ",";
|
||||
private String[] mappableAttributes = null;
|
||||
|
||||
/**
|
||||
* Check whether all properties have been set to correct values, and do some preprocessing.
|
||||
*/
|
||||
public void afterPropertiesSet() {
|
||||
Assert.notEmpty(attributes2grantedAuthoritiesMap,"A non-empty attributes2grantedAuthoritiesMap must be supplied");
|
||||
attributes2grantedAuthoritiesMap = preProcessMap(attributes2grantedAuthoritiesMap);
|
||||
try {
|
||||
mappableAttributes = (String[])attributes2grantedAuthoritiesMap.keySet().toArray(new String[]{});
|
||||
} catch ( ArrayStoreException ase ) {
|
||||
throw new IllegalArgumentException("attributes2grantedAuthoritiesMap contains non-String objects as keys");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Preprocess the given map
|
||||
* @param orgMap The map to process
|
||||
* @return the processed Map
|
||||
*/
|
||||
private Map preProcessMap(Map orgMap) {
|
||||
Map result = new HashMap(orgMap.size());
|
||||
Iterator it = orgMap.entrySet().iterator();
|
||||
while ( it.hasNext() ) {
|
||||
Map.Entry entry = (Map.Entry)it.next();
|
||||
result.put(entry.getKey(),getGrantedAuthorityCollection(entry.getValue()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given value to a collection of Granted Authorities
|
||||
*
|
||||
* @param value
|
||||
* The value to convert to a GrantedAuthority Collection
|
||||
* @return Collection containing the GrantedAuthority Collection
|
||||
*/
|
||||
private Collection getGrantedAuthorityCollection(Object value) {
|
||||
Collection result = new ArrayList();
|
||||
addGrantedAuthorityCollection(result,value);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given value to a collection of Granted Authorities,
|
||||
* adding the result to the given result collection.
|
||||
*
|
||||
* @param value
|
||||
* The value to convert to a GrantedAuthority Collection
|
||||
* @return Collection containing the GrantedAuthority Collection
|
||||
*/
|
||||
private void addGrantedAuthorityCollection(Collection result, Object value) {
|
||||
if ( value != null ) {
|
||||
if ( value instanceof Collection ) {
|
||||
addGrantedAuthorityCollection(result,(Collection)value);
|
||||
} else if ( value instanceof Object[] ) {
|
||||
addGrantedAuthorityCollection(result,(Object[])value);
|
||||
} else if ( value instanceof String ) {
|
||||
addGrantedAuthorityCollection(result,(String)value);
|
||||
} else if ( value instanceof GrantedAuthority ) {
|
||||
result.add(value);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Invalid object type: "+value.getClass().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addGrantedAuthorityCollection(Collection result, Collection value) {
|
||||
Iterator it = value.iterator();
|
||||
while ( it.hasNext() ) {
|
||||
addGrantedAuthorityCollection(result,it.next());
|
||||
}
|
||||
}
|
||||
|
||||
private void addGrantedAuthorityCollection(Collection result, Object[] value) {
|
||||
for ( int i = 0 ; i < value.length ; i++ ) {
|
||||
addGrantedAuthorityCollection(result,value[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private void addGrantedAuthorityCollection(Collection result, String value) {
|
||||
StringTokenizer st = new StringTokenizer(value,stringSeparator,false);
|
||||
while ( st.hasMoreTokens() ) {
|
||||
String nextToken = st.nextToken();
|
||||
if ( StringUtils.hasText(nextToken) ) {
|
||||
result.add(new GrantedAuthorityImpl(nextToken));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Map the given array of attributes to Spring Security GrantedAuthorities.
|
||||
*/
|
||||
public GrantedAuthority[] getGrantedAuthorities(String[] attributes) {
|
||||
List gaList = new ArrayList();
|
||||
for (int i = 0; i < attributes.length; i++) {
|
||||
Collection c = (Collection)attributes2grantedAuthoritiesMap.get(attributes[i]);
|
||||
if ( c != null ) { gaList.addAll(c); }
|
||||
}
|
||||
GrantedAuthority[] result = new GrantedAuthority[gaList.size()];
|
||||
result = (GrantedAuthority[])gaList.toArray(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the attributes2grantedAuthoritiesMap.
|
||||
*/
|
||||
public Map getAttributes2grantedAuthoritiesMap() {
|
||||
return attributes2grantedAuthoritiesMap;
|
||||
}
|
||||
/**
|
||||
* @param attributes2grantedAuthoritiesMap The attributes2grantedAuthoritiesMap to set.
|
||||
*/
|
||||
public void setAttributes2grantedAuthoritiesMap(Map attributes2grantedAuthoritiesMap) {
|
||||
this.attributes2grantedAuthoritiesMap = attributes2grantedAuthoritiesMap;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see org.springframework.security.authoritymapping.MappableAttributesRetriever#getMappableAttributes()
|
||||
*/
|
||||
public String[] getMappableAttributes() {
|
||||
return mappableAttributes;
|
||||
}
|
||||
/**
|
||||
* @return Returns the stringSeparator.
|
||||
*/
|
||||
public String getStringSeparator() {
|
||||
return stringSeparator;
|
||||
}
|
||||
/**
|
||||
* @param stringSeparator The stringSeparator to set.
|
||||
*/
|
||||
public void setStringSeparator(String stringSeparator) {
|
||||
this.stringSeparator = stringSeparator;
|
||||
}
|
||||
}
|
||||
-4
@@ -158,8 +158,4 @@ public class ConcurrentSessionControllerImpl implements ConcurrentSessionControl
|
||||
public void setSessionRegistry(SessionRegistry sessionRegistry) {
|
||||
this.sessionRegistry = sessionRegistry;
|
||||
}
|
||||
|
||||
public SessionRegistry getSessionRegistry() {
|
||||
return sessionRegistry;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-3
@@ -61,13 +61,14 @@ public class AnonymousBeanDefinitionParser implements BeanDefinitionParser {
|
||||
filter.getPropertyValues().addPropertyValue("userAttribute", username + "," + grantedAuthority);
|
||||
filter.getPropertyValues().addPropertyValue(ATT_KEY, key);
|
||||
|
||||
BeanDefinition authManager = ConfigUtils.registerProviderManagerIfNecessary(parserContext);
|
||||
RootBeanDefinition provider = new RootBeanDefinition(AnonymousAuthenticationProvider.class);
|
||||
provider.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
provider.setSource(source);
|
||||
provider.getPropertyValues().addPropertyValue(ATT_KEY, key);
|
||||
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.ANONYMOUS_AUTHENTICATION_PROVIDER, provider);
|
||||
ConfigUtils.addAuthenticationProvider(parserContext, BeanIds.ANONYMOUS_AUTHENTICATION_PROVIDER);
|
||||
|
||||
ManagedList authMgrProviderList = (ManagedList) authManager.getPropertyValues().getPropertyValue("providers").getValue();
|
||||
authMgrProviderList.add(provider);
|
||||
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.ANONYMOUS_PROCESSING_FILTER, filter);
|
||||
ConfigUtils.addHttpFilter(parserContext, new RuntimeBeanReference(BeanIds.ANONYMOUS_PROCESSING_FILTER));
|
||||
|
||||
+2
-9
@@ -1,6 +1,5 @@
|
||||
package org.springframework.security.config;
|
||||
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
@@ -22,7 +21,7 @@ public class AuthenticationManagerBeanDefinitionParser implements BeanDefinition
|
||||
private static final String ATT_ALIAS = "alias";
|
||||
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
ConfigUtils.registerProviderManagerIfNecessary(parserContext);
|
||||
BeanDefinition authManager = ConfigUtils.registerProviderManagerIfNecessary(parserContext);
|
||||
|
||||
String alias = element.getAttribute(ATT_ALIAS);
|
||||
|
||||
@@ -33,20 +32,14 @@ public class AuthenticationManagerBeanDefinitionParser implements BeanDefinition
|
||||
String sessionControllerRef = element.getAttribute(ATT_SESSION_CONTROLLER_REF);
|
||||
|
||||
if (StringUtils.hasText(sessionControllerRef)) {
|
||||
BeanDefinition authManager = parserContext.getRegistry().getBeanDefinition(BeanIds.AUTHENTICATION_MANAGER);
|
||||
ConfigUtils.setSessionControllerOnAuthenticationManager(parserContext,
|
||||
BeanIds.CONCURRENT_SESSION_CONTROLLER, element);
|
||||
authManager.getPropertyValues().addPropertyValue("sessionController",
|
||||
new RuntimeBeanReference(sessionControllerRef));
|
||||
RootBeanDefinition sessionRegistryInjector = new RootBeanDefinition(SessionRegistryInjectionBeanPostProcessor.class);
|
||||
sessionRegistryInjector.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
sessionRegistryInjector.getConstructorArgumentValues().addGenericArgumentValue(sessionControllerRef);
|
||||
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.SESSION_REGISTRY_INJECTION_POST_PROCESSOR, sessionRegistryInjector);
|
||||
}
|
||||
|
||||
parserContext.getRegistry().registerAlias(BeanIds.AUTHENTICATION_MANAGER, alias);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -94,7 +94,7 @@ class AuthenticationProviderBeanDefinitionParser implements BeanDefinitionParser
|
||||
parserContext.getRegistry().registerBeanDefinition(name , cacheResolver);
|
||||
parserContext.registerComponent(new BeanComponentDefinition(cacheResolver, name));
|
||||
|
||||
ConfigUtils.addAuthenticationProvider(parserContext, id);
|
||||
ConfigUtils.getRegisteredProviders(parserContext).add(new RuntimeBeanReference(id));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ public abstract class BeanIds {
|
||||
static final String CONTEXT_SOURCE_SETTING_POST_PROCESSOR = "_contextSettingPostProcessor";
|
||||
static final String ENTRY_POINT_INJECTION_POST_PROCESSOR = "_entryPointInjectionBeanPostProcessor";
|
||||
static final String USER_DETAILS_SERVICE_INJECTION_POST_PROCESSOR = "_userServiceInjectionPostProcessor";
|
||||
static final String SESSION_REGISTRY_INJECTION_POST_PROCESSOR = "_sessionRegistryInjectionPostProcessor";
|
||||
static final String FILTER_CHAIN_POST_PROCESSOR = "_filterChainProxyPostProcessor";
|
||||
static final String FILTER_LIST = "_filterChainList";
|
||||
|
||||
@@ -42,7 +41,6 @@ public abstract class BeanIds {
|
||||
public static final String MAIN_ENTRY_POINT = "_mainEntryPoint";
|
||||
public static final String FILTER_CHAIN_PROXY = "_filterChainProxy";
|
||||
public static final String HTTP_SESSION_CONTEXT_INTEGRATION_FILTER = "_httpSessionContextIntegrationFilter";
|
||||
public static final String LDAP_AUTHENTICATION_PROVIDER = "_ldapAuthenticationProvider";
|
||||
public static final String LOGOUT_FILTER = "_logoutFilter";
|
||||
public static final String EXCEPTION_TRANSLATION_FILTER = "_exceptionTranslationFilter";
|
||||
public static final String FILTER_SECURITY_INTERCEPTOR = "_filterSecurityInterceptor";
|
||||
@@ -50,7 +48,6 @@ public abstract class BeanIds {
|
||||
public static final String CHANNEL_DECISION_MANAGER = "_channelDecisionManager";
|
||||
public static final String REMEMBER_ME_FILTER = "_rememberMeFilter";
|
||||
public static final String REMEMBER_ME_SERVICES = "_rememberMeServices";
|
||||
public static final String REMEMBER_ME_AUTHENTICATION_PROVIDER = "_rememberMeAuthenticationProvider";
|
||||
public static final String DEFAULT_LOGIN_PAGE_GENERATING_FILTER = "_defaultLoginPageFilter";
|
||||
public static final String SECURITY_CONTEXT_HOLDER_AWARE_REQUEST_FILTER = "_securityContextHolderAwareRequestFilter";
|
||||
public static final String SESSION_FIXATION_PROTECTION_FILTER = "_sessionFixationProtectionFilter";
|
||||
@@ -68,4 +65,5 @@ public abstract class BeanIds {
|
||||
public static final String X509_AUTH_PROVIDER = "_x509AuthenticationProvider";
|
||||
public static final String PRE_AUTH_ENTRY_POINT = "_preAuthenticatedProcessingFilterEntryPoint";
|
||||
public static final String REMEMBER_ME_SERVICES_INJECTION_POST_PROCESSOR = "_rememberMeServicesInjectionBeanPostProcessor";
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.springframework.security.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -9,12 +9,15 @@ import org.springframework.beans.BeanMetadataElement;
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.PropertyValue;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
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.ParserContext;
|
||||
import org.springframework.security.afterinvocation.AfterInvocationProviderManager;
|
||||
import org.springframework.security.providers.ProviderManager;
|
||||
import org.springframework.security.userdetails.UserDetailsService;
|
||||
import org.springframework.security.util.UrlUtils;
|
||||
import org.springframework.security.vote.AffirmativeBased;
|
||||
import org.springframework.security.vote.AuthenticatedVoter;
|
||||
@@ -77,20 +80,21 @@ public abstract class ConfigUtils {
|
||||
* using the <security:provider /> tag or by other beans which have a dependency on the
|
||||
* authentication manager.
|
||||
*/
|
||||
static void registerProviderManagerIfNecessary(ParserContext parserContext) {
|
||||
static BeanDefinition registerProviderManagerIfNecessary(ParserContext parserContext) {
|
||||
if(parserContext.getRegistry().containsBeanDefinition(BeanIds.AUTHENTICATION_MANAGER)) {
|
||||
return;
|
||||
return parserContext.getRegistry().getBeanDefinition(BeanIds.AUTHENTICATION_MANAGER);
|
||||
}
|
||||
|
||||
BeanDefinition authManager = new RootBeanDefinition(NamespaceAuthenticationManager.class);
|
||||
authManager.getPropertyValues().addPropertyValue("providerBeanNames", new ArrayList());
|
||||
BeanDefinition authManager = new RootBeanDefinition(ProviderManager.class);
|
||||
authManager.getPropertyValues().addPropertyValue("providers", new ManagedList());
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.AUTHENTICATION_MANAGER, authManager);
|
||||
|
||||
return authManager;
|
||||
}
|
||||
|
||||
static void addAuthenticationProvider(ParserContext parserContext, String beanName) {
|
||||
registerProviderManagerIfNecessary(parserContext);
|
||||
BeanDefinition authManager = parserContext.getRegistry().getBeanDefinition(BeanIds.AUTHENTICATION_MANAGER);
|
||||
((ArrayList) authManager.getPropertyValues().getPropertyValue("providerBeanNames").getValue()).add(beanName);
|
||||
static ManagedList getRegisteredProviders(ParserContext parserContext) {
|
||||
BeanDefinition authManager = registerProviderManagerIfNecessary(parserContext);
|
||||
return (ManagedList) authManager.getPropertyValues().getPropertyValue("providers").getValue();
|
||||
}
|
||||
|
||||
static ManagedList getRegisteredAfterInvocationProviders(ParserContext parserContext) {
|
||||
@@ -168,8 +172,7 @@ public abstract class ConfigUtils {
|
||||
}
|
||||
|
||||
static void setSessionControllerOnAuthenticationManager(ParserContext pc, String beanName, Element sourceElt) {
|
||||
registerProviderManagerIfNecessary(pc);
|
||||
BeanDefinition authManager = pc.getRegistry().getBeanDefinition(BeanIds.AUTHENTICATION_MANAGER);
|
||||
BeanDefinition authManager = registerProviderManagerIfNecessary(pc);
|
||||
PropertyValue pv = authManager.getPropertyValues().getPropertyValue("sessionController");
|
||||
|
||||
if (pv != null && pv.getValue() != null) {
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ import org.w3c.dom.Node;
|
||||
*/
|
||||
public class CustomAuthenticationProviderBeanDefinitionDecorator implements BeanDefinitionDecorator {
|
||||
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder holder, ParserContext parserContext) {
|
||||
ConfigUtils.addAuthenticationProvider(parserContext, holder.getBeanName());
|
||||
ConfigUtils.getRegisteredProviders(parserContext).add(new RuntimeBeanReference(holder.getBeanName()));
|
||||
|
||||
return holder;
|
||||
}
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ public class FilterChainProxyPostProcessor implements BeanPostProcessor, BeanFac
|
||||
unwrapFilter(previous) + "' have the same 'order' value. When using custom filters, " +
|
||||
"please make sure the positions do not conflict with default filters. " +
|
||||
"Alternatively you can disable the default filters by removing the corresponding " +
|
||||
"child elements from <http> and avoiding the use of <http auto-config='true'>.");
|
||||
"child elements from <http> and not avoiding the use of <http auto-config='true'>.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+128
-150
@@ -50,16 +50,16 @@ import org.w3c.dom.Element;
|
||||
* @version $Id$
|
||||
*/
|
||||
public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
static final Log logger = LogFactory.getLog(HttpSecurityBeanDefinitionParser.class);
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
static final String ATT_REALM = "realm";
|
||||
static final String DEF_REALM = "Spring Security Application";
|
||||
|
||||
static final String ATT_PATH_PATTERN = "pattern";
|
||||
|
||||
|
||||
static final String ATT_SESSION_FIXATION_PROTECTION = "session-fixation-protection";
|
||||
static final String OPT_SESSION_FIXATION_NO_PROTECTION = "none";
|
||||
static final String OPT_SESSION_FIXATION_CLEAN_SESSION = "newSession";
|
||||
static final String OPT_SESSION_FIXATION_CLEAN_SESSION = "newSession";
|
||||
static final String OPT_SESSION_FIXATION_MIGRATE_SESSION = "migrateSession";
|
||||
|
||||
static final String ATT_PATH_TYPE = "path-type";
|
||||
@@ -91,9 +91,9 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
static final String ATT_SERVLET_API_PROVISION = "servlet-api-provision";
|
||||
static final String DEF_SERVLET_API_PROVISION = "true";
|
||||
|
||||
static final String ATT_ACCESS_MGR = "access-decision-manager-ref";
|
||||
static final String ATT_ACCESS_MGR = "access-decision-manager-ref";
|
||||
static final String ATT_USER_SERVICE_REF = "user-service-ref";
|
||||
|
||||
|
||||
static final String ATT_ENTRY_POINT_REF = "entry-point-ref";
|
||||
static final String ATT_ONCE_PER_REQUEST = "once-per-request";
|
||||
static final String ATT_ACCESS_DENIED_PAGE = "access-denied-page";
|
||||
@@ -106,20 +106,20 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
// SEC-501 - should paths stored in request maps be converted to lower case
|
||||
// true if Ant path and using lower case
|
||||
final boolean convertPathsToLowerCase = (matcher instanceof AntUrlPathMatcher) && matcher.requiresLowerCaseUrl();
|
||||
|
||||
|
||||
final List interceptUrlElts = DomUtils.getChildElementsByTagName(element, Elements.INTERCEPT_URL);
|
||||
final Map filterChainMap = new LinkedHashMap();
|
||||
final LinkedHashMap channelRequestMap = new LinkedHashMap();
|
||||
|
||||
registerFilterChainProxy(parserContext, filterChainMap, matcher, source);
|
||||
|
||||
parseInterceptUrlsForChannelSecurityAndFilterChain(interceptUrlElts, filterChainMap, channelRequestMap,
|
||||
|
||||
parseInterceptUrlsForChannelSecurityAndFilterChain(interceptUrlElts, filterChainMap, channelRequestMap,
|
||||
convertPathsToLowerCase, parserContext);
|
||||
|
||||
boolean allowSessionCreation = registerHttpSessionIntegrationFilter(element, parserContext);
|
||||
|
||||
registerHttpSessionIntegrationFilter(element, parserContext);
|
||||
|
||||
registerServletApiFilter(element, parserContext);
|
||||
|
||||
|
||||
// Set up the access manager reference for http
|
||||
String accessManagerId = element.getAttribute(ATT_ACCESS_MGR);
|
||||
|
||||
@@ -127,31 +127,31 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
ConfigUtils.registerDefaultAccessManagerIfNecessary(parserContext);
|
||||
accessManagerId = BeanIds.ACCESS_MANAGER;
|
||||
}
|
||||
|
||||
|
||||
// Register the portMapper. A default will always be created, even if no element exists.
|
||||
BeanDefinition portMapper = new PortMappingsBeanDefinitionParser().parse(
|
||||
DomUtils.getChildElementByTagName(element, Elements.PORT_MAPPINGS), parserContext);
|
||||
registry.registerBeanDefinition(BeanIds.PORT_MAPPER, portMapper);
|
||||
|
||||
registerExceptionTranslationFilter(element, parserContext, allowSessionCreation);
|
||||
registerExceptionTranslationFilter(element, parserContext);
|
||||
|
||||
|
||||
if (channelRequestMap.size() > 0) {
|
||||
// At least one channel requirement has been specified
|
||||
registerChannelProcessingBeans(parserContext, matcher, channelRequestMap);
|
||||
}
|
||||
|
||||
registerFilterSecurityInterceptor(element, parserContext, matcher, accessManagerId,
|
||||
}
|
||||
|
||||
registerFilterSecurityInterceptor(element, parserContext, matcher, accessManagerId,
|
||||
parseInterceptUrlsForFilterInvocationRequestMap(interceptUrlElts, convertPathsToLowerCase, parserContext));
|
||||
|
||||
boolean sessionControlEnabled = registerConcurrentSessionControlBeansIfRequired(element, parserContext);
|
||||
|
||||
registerSessionFixationProtectionFilter(parserContext, element.getAttribute(ATT_SESSION_FIXATION_PROTECTION),
|
||||
|
||||
registerSessionFixationProtectionFilter(parserContext, element.getAttribute(ATT_SESSION_FIXATION_PROTECTION),
|
||||
sessionControlEnabled);
|
||||
|
||||
boolean autoConfig = false;
|
||||
if ("true".equals(element.getAttribute(ATT_AUTO_CONFIG))) {
|
||||
autoConfig = true;
|
||||
autoConfig = true;
|
||||
}
|
||||
|
||||
Element anonymousElt = DomUtils.getChildElementByTagName(element, Elements.ANONYMOUS);
|
||||
@@ -159,9 +159,22 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
new AnonymousBeanDefinitionParser().parse(anonymousElt, parserContext);
|
||||
}
|
||||
|
||||
parseRememberMeAndLogout(element, autoConfig, parserContext);
|
||||
|
||||
parseBasicFormLoginAndOpenID(element, parserContext, autoConfig, allowSessionCreation);
|
||||
// Parse remember me before logout as RememberMeServices is also a LogoutHandler implementation.
|
||||
Element rememberMeElt = DomUtils.getChildElementByTagName(element, Elements.REMEMBER_ME);
|
||||
if (rememberMeElt != null || autoConfig) {
|
||||
new RememberMeBeanDefinitionParser().parse(rememberMeElt, parserContext);
|
||||
// Post processor to inject RememberMeServices into filters which need it
|
||||
RootBeanDefinition rememberMeInjectionPostProcessor = new RootBeanDefinition(RememberMeServicesInjectionBeanPostProcessor.class);
|
||||
rememberMeInjectionPostProcessor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
registry.registerBeanDefinition(BeanIds.REMEMBER_ME_SERVICES_INJECTION_POST_PROCESSOR, rememberMeInjectionPostProcessor);
|
||||
}
|
||||
|
||||
Element logoutElt = DomUtils.getChildElementByTagName(element, Elements.LOGOUT);
|
||||
if (logoutElt != null || autoConfig) {
|
||||
new LogoutBeanDefinitionParser().parse(logoutElt, parserContext);
|
||||
}
|
||||
|
||||
parseBasicFormLoginAndOpenID(element, parserContext, autoConfig);
|
||||
|
||||
Element x509Elt = DomUtils.getChildElementByTagName(element, Elements.X509);
|
||||
if (x509Elt != null) {
|
||||
@@ -175,49 +188,26 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
RootBeanDefinition postProcessor2 = new RootBeanDefinition(UserDetailsServiceInjectionBeanPostProcessor.class);
|
||||
postProcessor2.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
registry.registerBeanDefinition(BeanIds.USER_DETAILS_SERVICE_INJECTION_POST_PROCESSOR, postProcessor2);
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void parseRememberMeAndLogout(Element elt, boolean autoConfig, ParserContext pc) {
|
||||
// Parse remember me before logout as RememberMeServices is also a LogoutHandler implementation.
|
||||
Element rememberMeElt = DomUtils.getChildElementByTagName(elt, Elements.REMEMBER_ME);
|
||||
String rememberMeServices = null;
|
||||
|
||||
if (rememberMeElt != null || autoConfig) {
|
||||
RememberMeBeanDefinitionParser rmbdp = new RememberMeBeanDefinitionParser();
|
||||
rmbdp.parse(rememberMeElt, pc);
|
||||
rememberMeServices = rmbdp.getServicesName();
|
||||
// Post processor to inject RememberMeServices into filters which need it
|
||||
RootBeanDefinition rememberMeInjectionPostProcessor = new RootBeanDefinition(RememberMeServicesInjectionBeanPostProcessor.class);
|
||||
rememberMeInjectionPostProcessor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
pc.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_SERVICES_INJECTION_POST_PROCESSOR, rememberMeInjectionPostProcessor);
|
||||
}
|
||||
|
||||
Element logoutElt = DomUtils.getChildElementByTagName(elt, Elements.LOGOUT);
|
||||
if (logoutElt != null || autoConfig) {
|
||||
new LogoutBeanDefinitionParser(rememberMeServices).parse(logoutElt, pc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void registerFilterChainProxy(ParserContext pc, Map filterChainMap, UrlMatcher matcher, Object source) {
|
||||
if (pc.getRegistry().containsBeanDefinition(BeanIds.FILTER_CHAIN_PROXY)) {
|
||||
pc.getReaderContext().error("Duplicate <http> element detected", source);
|
||||
}
|
||||
|
||||
|
||||
RootBeanDefinition filterChainProxy = new RootBeanDefinition(FilterChainProxy.class);
|
||||
filterChainProxy.setSource(source);
|
||||
filterChainProxy.getPropertyValues().addPropertyValue("matcher", matcher);
|
||||
filterChainProxy.getPropertyValues().addPropertyValue("stripQueryStringFromUrls", Boolean.valueOf(matcher instanceof AntUrlPathMatcher));
|
||||
filterChainProxy.getPropertyValues().addPropertyValue("filterChainMap", filterChainMap);
|
||||
pc.getRegistry().registerBeanDefinition(BeanIds.FILTER_CHAIN_PROXY, filterChainProxy);
|
||||
pc.getRegistry().registerAlias(BeanIds.FILTER_CHAIN_PROXY, BeanIds.SPRING_SECURITY_FILTER_CHAIN);
|
||||
pc.getRegistry().registerAlias(BeanIds.FILTER_CHAIN_PROXY, BeanIds.SPRING_SECURITY_FILTER_CHAIN);
|
||||
}
|
||||
|
||||
private boolean registerHttpSessionIntegrationFilter(Element element, ParserContext pc) {
|
||||
private void registerHttpSessionIntegrationFilter(Element element, ParserContext pc) {
|
||||
RootBeanDefinition httpScif = new RootBeanDefinition(HttpSessionContextIntegrationFilter.class);
|
||||
boolean sessionCreationAllowed = true;
|
||||
|
||||
|
||||
String createSession = element.getAttribute(ATT_CREATE_SESSION);
|
||||
if (OPT_CREATE_SESSION_ALWAYS.equals(createSession)) {
|
||||
httpScif.getPropertyValues().addPropertyValue("allowSessionCreation", Boolean.TRUE);
|
||||
@@ -225,7 +215,6 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
} else if (OPT_CREATE_SESSION_NEVER.equals(createSession)) {
|
||||
httpScif.getPropertyValues().addPropertyValue("allowSessionCreation", Boolean.FALSE);
|
||||
httpScif.getPropertyValues().addPropertyValue("forceEagerSessionCreation", Boolean.FALSE);
|
||||
sessionCreationAllowed = false;
|
||||
} else {
|
||||
createSession = DEF_CREATE_SESSION_IF_REQUIRED;
|
||||
httpScif.getPropertyValues().addPropertyValue("allowSessionCreation", Boolean.TRUE);
|
||||
@@ -234,11 +223,9 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
pc.getRegistry().registerBeanDefinition(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER, httpScif);
|
||||
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER));
|
||||
|
||||
return sessionCreationAllowed;
|
||||
}
|
||||
|
||||
// Adds the servlet-api integration filter if required
|
||||
// Adds the servlet-api integration filter if required
|
||||
private void registerServletApiFilter(Element element, ParserContext pc) {
|
||||
String provideServletApi = element.getAttribute(ATT_SERVLET_API_PROVISION);
|
||||
if (!StringUtils.hasText(provideServletApi)) {
|
||||
@@ -251,27 +238,26 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.SECURITY_CONTEXT_HOLDER_AWARE_REQUEST_FILTER));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean registerConcurrentSessionControlBeansIfRequired(Element element, ParserContext parserContext) {
|
||||
Element sessionControlElt = DomUtils.getChildElementByTagName(element, Elements.CONCURRENT_SESSIONS);
|
||||
if (sessionControlElt == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
new ConcurrentSessionsBeanDefinitionParser().parse(sessionControlElt, parserContext);
|
||||
logger.info("Concurrent session filter in use, setting 'forceEagerSessionCreation' to true");
|
||||
BeanDefinition sessionIntegrationFilter = parserContext.getRegistry().getBeanDefinition(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER);
|
||||
BeanDefinition sessionIntegrationFilter = parserContext.getRegistry().getBeanDefinition(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER);
|
||||
sessionIntegrationFilter.getPropertyValues().addPropertyValue("forceEagerSessionCreation", Boolean.TRUE);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void registerExceptionTranslationFilter(Element element, ParserContext pc, boolean allowSessionCreation) {
|
||||
String accessDeniedPage = element.getAttribute(ATT_ACCESS_DENIED_PAGE);
|
||||
ConfigUtils.validateHttpRedirect(accessDeniedPage, pc, pc.extractSource(element));
|
||||
|
||||
private void registerExceptionTranslationFilter(Element element, ParserContext pc) {
|
||||
String accessDeniedPage = element.getAttribute(ATT_ACCESS_DENIED_PAGE);
|
||||
ConfigUtils.validateHttpRedirect(accessDeniedPage, pc, pc.extractSource(element));
|
||||
BeanDefinitionBuilder exceptionTranslationFilterBuilder
|
||||
= BeanDefinitionBuilder.rootBeanDefinition(ExceptionTranslationFilter.class);
|
||||
exceptionTranslationFilterBuilder.addPropertyValue("createSessionAllowed", new Boolean(allowSessionCreation));
|
||||
|
||||
|
||||
if (StringUtils.hasText(accessDeniedPage)) {
|
||||
AccessDeniedHandlerImpl accessDeniedHandler = new AccessDeniedHandlerImpl();
|
||||
accessDeniedHandler.setErrorPage(accessDeniedPage);
|
||||
@@ -281,27 +267,27 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
pc.getRegistry().registerBeanDefinition(BeanIds.EXCEPTION_TRANSLATION_FILTER, exceptionTranslationFilterBuilder.getBeanDefinition());
|
||||
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.EXCEPTION_TRANSLATION_FILTER));
|
||||
}
|
||||
|
||||
|
||||
private void registerFilterSecurityInterceptor(Element element, ParserContext pc, UrlMatcher matcher,
|
||||
String accessManagerId, LinkedHashMap filterInvocationDefinitionMap) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(FilterSecurityInterceptor.class);
|
||||
|
||||
builder.addPropertyReference("accessDecisionManager", accessManagerId);
|
||||
builder.addPropertyReference("authenticationManager", BeanIds.AUTHENTICATION_MANAGER);
|
||||
|
||||
|
||||
if ("false".equals(element.getAttribute(ATT_ONCE_PER_REQUEST))) {
|
||||
builder.addPropertyValue("observeOncePerRequest", Boolean.FALSE);
|
||||
}
|
||||
|
||||
DefaultFilterInvocationDefinitionSource fids =
|
||||
|
||||
DefaultFilterInvocationDefinitionSource fids =
|
||||
new DefaultFilterInvocationDefinitionSource(matcher, filterInvocationDefinitionMap);
|
||||
fids.setStripQueryStringFromUrls(matcher instanceof AntUrlPathMatcher);
|
||||
|
||||
|
||||
builder.addPropertyValue("objectDefinitionSource", fids);
|
||||
pc.getRegistry().registerBeanDefinition(BeanIds.FILTER_SECURITY_INTERCEPTOR, builder.getBeanDefinition());
|
||||
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.FILTER_SECURITY_INTERCEPTOR));
|
||||
}
|
||||
|
||||
|
||||
private void registerChannelProcessingBeans(ParserContext pc, UrlMatcher matcher, LinkedHashMap channelRequestMap) {
|
||||
RootBeanDefinition channelFilter = new RootBeanDefinition(ChannelProcessingFilter.class);
|
||||
channelFilter.getPropertyValues().addPropertyValue("channelDecisionManager",
|
||||
@@ -309,7 +295,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
DefaultFilterInvocationDefinitionSource channelFilterInvDefSource =
|
||||
new DefaultFilterInvocationDefinitionSource(matcher, channelRequestMap);
|
||||
channelFilterInvDefSource.setStripQueryStringFromUrls(matcher instanceof AntUrlPathMatcher);
|
||||
|
||||
|
||||
channelFilter.getPropertyValues().addPropertyValue("filterInvocationDefinitionSource",
|
||||
channelFilterInvDefSource);
|
||||
RootBeanDefinition channelDecisionManager = new RootBeanDefinition(ChannelDecisionManagerImpl.class);
|
||||
@@ -330,161 +316,159 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
pc.getRegistry().registerBeanDefinition(BeanIds.CHANNEL_PROCESSING_FILTER, channelFilter);
|
||||
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.CHANNEL_PROCESSING_FILTER));
|
||||
pc.getRegistry().registerBeanDefinition(BeanIds.CHANNEL_DECISION_MANAGER, channelDecisionManager);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void registerSessionFixationProtectionFilter(ParserContext pc, String sessionFixationAttribute, boolean sessionControlEnabled) {
|
||||
if(!StringUtils.hasText(sessionFixationAttribute)) {
|
||||
sessionFixationAttribute = OPT_SESSION_FIXATION_MIGRATE_SESSION;
|
||||
}
|
||||
|
||||
|
||||
if (!sessionFixationAttribute.equals(OPT_SESSION_FIXATION_NO_PROTECTION)) {
|
||||
BeanDefinitionBuilder sessionFixationFilter =
|
||||
BeanDefinitionBuilder sessionFixationFilter =
|
||||
BeanDefinitionBuilder.rootBeanDefinition(SessionFixationProtectionFilter.class);
|
||||
sessionFixationFilter.addPropertyValue("migrateSessionAttributes",
|
||||
sessionFixationFilter.addPropertyValue("migrateSessionAttributes",
|
||||
Boolean.valueOf(sessionFixationAttribute.equals(OPT_SESSION_FIXATION_MIGRATE_SESSION)));
|
||||
if (sessionControlEnabled) {
|
||||
sessionFixationFilter.addPropertyReference("sessionRegistry", BeanIds.SESSION_REGISTRY);
|
||||
}
|
||||
pc.getRegistry().registerBeanDefinition(BeanIds.SESSION_FIXATION_PROTECTION_FILTER,
|
||||
pc.getRegistry().registerBeanDefinition(BeanIds.SESSION_FIXATION_PROTECTION_FILTER,
|
||||
sessionFixationFilter.getBeanDefinition());
|
||||
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.SESSION_FIXATION_PROTECTION_FILTER));
|
||||
}
|
||||
}
|
||||
|
||||
private void parseBasicFormLoginAndOpenID(Element element, ParserContext pc, boolean autoConfig, boolean allowSessionCreation) {
|
||||
|
||||
private void parseBasicFormLoginAndOpenID(Element element, ParserContext pc, boolean autoConfig) {
|
||||
RootBeanDefinition formLoginFilter = null;
|
||||
RootBeanDefinition formLoginEntryPoint = null;
|
||||
String formLoginPage = null;
|
||||
String formLoginPage = null;
|
||||
RootBeanDefinition openIDFilter = null;
|
||||
RootBeanDefinition openIDEntryPoint = null;
|
||||
String openIDLoginPage = null;
|
||||
|
||||
|
||||
String realm = element.getAttribute(ATT_REALM);
|
||||
if (!StringUtils.hasText(realm)) {
|
||||
realm = DEF_REALM;
|
||||
realm = DEF_REALM;
|
||||
}
|
||||
|
||||
|
||||
Element basicAuthElt = DomUtils.getChildElementByTagName(element, Elements.BASIC_AUTH);
|
||||
if (basicAuthElt != null || autoConfig) {
|
||||
new BasicAuthenticationBeanDefinitionParser(realm).parse(basicAuthElt, pc);
|
||||
}
|
||||
|
||||
Element formLoginElt = DomUtils.getChildElementByTagName(element, Elements.FORM_LOGIN);
|
||||
|
||||
|
||||
Element formLoginElt = DomUtils.getChildElementByTagName(element, Elements.FORM_LOGIN);
|
||||
|
||||
if (formLoginElt != null || autoConfig) {
|
||||
FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_security_check",
|
||||
"org.springframework.security.ui.webapp.AuthenticationProcessingFilter");
|
||||
|
||||
FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_security_check",
|
||||
"org.springframework.security.ui.webapp.AuthenticationProcessingFilter");
|
||||
|
||||
parser.parse(formLoginElt, pc);
|
||||
formLoginFilter = parser.getFilterBean();
|
||||
formLoginEntryPoint = parser.getEntryPointBean();
|
||||
formLoginPage = parser.getLoginPage();
|
||||
}
|
||||
|
||||
|
||||
Element openIDLoginElt = DomUtils.getChildElementByTagName(element, Elements.OPENID_LOGIN);
|
||||
|
||||
if (openIDLoginElt != null) {
|
||||
FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_openid_security_check",
|
||||
"org.springframework.security.ui.openid.OpenIDAuthenticationProcessingFilter");
|
||||
|
||||
FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_openid_security_check",
|
||||
"org.springframework.security.ui.openid.OpenIDAuthenticationProcessingFilter");
|
||||
|
||||
parser.parse(openIDLoginElt, pc);
|
||||
openIDFilter = parser.getFilterBean();
|
||||
openIDEntryPoint = parser.getEntryPointBean();
|
||||
openIDLoginPage = parser.getLoginPage();
|
||||
|
||||
BeanDefinitionBuilder openIDProviderBuilder =
|
||||
|
||||
BeanDefinitionBuilder openIDProviderBuilder =
|
||||
BeanDefinitionBuilder.rootBeanDefinition("org.springframework.security.providers.openid.OpenIDAuthenticationProvider");
|
||||
|
||||
|
||||
String userService = openIDLoginElt.getAttribute(ATT_USER_SERVICE_REF);
|
||||
|
||||
|
||||
if (StringUtils.hasText(userService)) {
|
||||
openIDProviderBuilder.addPropertyReference("userDetailsService", userService);
|
||||
}
|
||||
|
||||
|
||||
BeanDefinition openIDProvider = openIDProviderBuilder.getBeanDefinition();
|
||||
pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_PROVIDER, openIDProvider);
|
||||
ConfigUtils.addAuthenticationProvider(pc, BeanIds.OPEN_ID_PROVIDER);
|
||||
ConfigUtils.getRegisteredProviders(pc).add(new RuntimeBeanReference(BeanIds.OPEN_ID_PROVIDER));
|
||||
}
|
||||
|
||||
|
||||
boolean needLoginPage = false;
|
||||
|
||||
|
||||
if (formLoginFilter != null) {
|
||||
needLoginPage = true;
|
||||
formLoginFilter.getPropertyValues().addPropertyValue("allowSessionCreation", new Boolean(allowSessionCreation));
|
||||
pc.getRegistry().registerBeanDefinition(BeanIds.FORM_LOGIN_FILTER, formLoginFilter);
|
||||
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.FORM_LOGIN_FILTER));
|
||||
pc.getRegistry().registerBeanDefinition(BeanIds.FORM_LOGIN_ENTRY_POINT, formLoginEntryPoint);
|
||||
}
|
||||
needLoginPage = true;
|
||||
pc.getRegistry().registerBeanDefinition(BeanIds.FORM_LOGIN_FILTER, formLoginFilter);
|
||||
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.FORM_LOGIN_FILTER));
|
||||
pc.getRegistry().registerBeanDefinition(BeanIds.FORM_LOGIN_ENTRY_POINT, formLoginEntryPoint);
|
||||
}
|
||||
|
||||
if (openIDFilter != null) {
|
||||
needLoginPage = true;
|
||||
openIDFilter.getPropertyValues().addPropertyValue("allowSessionCreation", new Boolean(allowSessionCreation));
|
||||
pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_FILTER, openIDFilter);
|
||||
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.OPEN_ID_FILTER));
|
||||
pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_ENTRY_POINT, openIDEntryPoint);
|
||||
needLoginPage = true;
|
||||
pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_FILTER, openIDFilter);
|
||||
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.OPEN_ID_FILTER));
|
||||
pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_ENTRY_POINT, openIDEntryPoint);
|
||||
}
|
||||
|
||||
// If no login page has been defined, add in the default page generator.
|
||||
if (needLoginPage && formLoginPage == null && openIDLoginPage == null) {
|
||||
logger.info("No login page configured. The default internal one will be used. Use the '"
|
||||
+ FormLoginBeanDefinitionParser.ATT_LOGIN_PAGE + "' attribute to set the URL of the login page.");
|
||||
BeanDefinitionBuilder loginPageFilter =
|
||||
BeanDefinitionBuilder.rootBeanDefinition(DefaultLoginPageGeneratingFilter.class);
|
||||
|
||||
BeanDefinitionBuilder loginPageFilter =
|
||||
BeanDefinitionBuilder.rootBeanDefinition(DefaultLoginPageGeneratingFilter.class);
|
||||
|
||||
if (formLoginFilter != null) {
|
||||
loginPageFilter.addConstructorArg(new RuntimeBeanReference(BeanIds.FORM_LOGIN_FILTER));
|
||||
loginPageFilter.addConstructorArg(new RuntimeBeanReference(BeanIds.FORM_LOGIN_FILTER));
|
||||
}
|
||||
|
||||
|
||||
if (openIDFilter != null) {
|
||||
loginPageFilter.addConstructorArg(new RuntimeBeanReference(BeanIds.OPEN_ID_FILTER));
|
||||
loginPageFilter.addConstructorArg(new RuntimeBeanReference(BeanIds.OPEN_ID_FILTER));
|
||||
}
|
||||
|
||||
pc.getRegistry().registerBeanDefinition(BeanIds.DEFAULT_LOGIN_PAGE_GENERATING_FILTER,
|
||||
loginPageFilter.getBeanDefinition());
|
||||
pc.getRegistry().registerBeanDefinition(BeanIds.DEFAULT_LOGIN_PAGE_GENERATING_FILTER,
|
||||
loginPageFilter.getBeanDefinition());
|
||||
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.DEFAULT_LOGIN_PAGE_GENERATING_FILTER));
|
||||
}
|
||||
|
||||
|
||||
// We need to establish the main entry point.
|
||||
// First check if a custom entry point bean is set
|
||||
String customEntryPoint = element.getAttribute(ATT_ENTRY_POINT_REF);
|
||||
|
||||
|
||||
if (StringUtils.hasText(customEntryPoint)) {
|
||||
pc.getRegistry().registerAlias(customEntryPoint, BeanIds.MAIN_ENTRY_POINT);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Basic takes precedence if explicit element is used and no others are configured
|
||||
if (basicAuthElt != null && formLoginElt == null && openIDLoginElt == null) {
|
||||
pc.getRegistry().registerAlias(BeanIds.BASIC_AUTHENTICATION_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
|
||||
return;
|
||||
pc.getRegistry().registerAlias(BeanIds.BASIC_AUTHENTICATION_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// If formLogin has been enabled either through an element or auto-config, then it is used if no openID login page
|
||||
// has been set
|
||||
if (formLoginFilter != null && openIDLoginPage == null) {
|
||||
pc.getRegistry().registerAlias(BeanIds.FORM_LOGIN_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
|
||||
return;
|
||||
pc.getRegistry().registerAlias(BeanIds.FORM_LOGIN_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Otherwise use OpenID if enabled
|
||||
if (openIDFilter != null && formLoginFilter == null) {
|
||||
pc.getRegistry().registerAlias(BeanIds.OPEN_ID_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
|
||||
return;
|
||||
pc.getRegistry().registerAlias(BeanIds.OPEN_ID_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// If X.509 has been enabled, use the preauth entry point.
|
||||
if (DomUtils.getChildElementByTagName(element, Elements.X509) != null) {
|
||||
pc.getRegistry().registerAlias(BeanIds.PRE_AUTH_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
pc.getReaderContext().error("No AuthenticationEntryPoint could be established. Please " +
|
||||
"make sure you have a login mechanism configured through the namespace (such as form-login) or " +
|
||||
"specify a custom AuthenticationEntryPoint with the custom-entry-point-ref attribute ",
|
||||
"make sure you have a login mechanism configured through the namespace (such as form-login) or " +
|
||||
"specify a custom AuthenticationEntryPoint with the custom-entry-point-ref attribute ",
|
||||
pc.extractSource(element));
|
||||
}
|
||||
|
||||
|
||||
static UrlMatcher createUrlMatcher(Element element) {
|
||||
String patternType = element.getAttribute(ATT_PATH_TYPE);
|
||||
if (!StringUtils.hasText(patternType)) {
|
||||
@@ -518,8 +502,8 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
}
|
||||
// Default for regex is no change
|
||||
}
|
||||
|
||||
return matcher;
|
||||
|
||||
return matcher;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -563,7 +547,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
editor.setAsText(channelConfigAttribute);
|
||||
channelRequestMap.put(new RequestKey(path), (ConfigAttributeDefinition) editor.getValue());
|
||||
}
|
||||
|
||||
|
||||
String filters = urlElt.getAttribute(ATT_FILTERS);
|
||||
|
||||
if (StringUtils.hasText(filters)) {
|
||||
@@ -576,10 +560,10 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static LinkedHashMap parseInterceptUrlsForFilterInvocationRequestMap(List urlElts, boolean useLowerCasePaths, ParserContext parserContext) {
|
||||
LinkedHashMap filterInvocationDefinitionMap = new LinkedHashMap();
|
||||
|
||||
|
||||
Iterator urlEltsIterator = urlElts.iterator();
|
||||
ConfigAttributeEditor editor = new ConfigAttributeEditor();
|
||||
|
||||
@@ -606,17 +590,11 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
// Convert the comma-separated list of access attributes to a ConfigAttributeDefinition
|
||||
if (StringUtils.hasText(access)) {
|
||||
editor.setAsText(access);
|
||||
Object key = new RequestKey(path, method);
|
||||
|
||||
if (filterInvocationDefinitionMap.containsKey(key)) {
|
||||
logger.warn("Duplicate URL defined: " + key + ". The original attribute values will be overwritten");
|
||||
}
|
||||
|
||||
filterInvocationDefinitionMap.put(key, editor.getValue());
|
||||
filterInvocationDefinitionMap.put(new RequestKey(path, method), editor.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return filterInvocationDefinitionMap;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ public class JdbcUserServiceBeanDefinitionParser extends AbstractUserDetailsServ
|
||||
|
||||
if (StringUtils.hasText(groupAuthoritiesQuery)) {
|
||||
builder.addPropertyValue("enableGroups", Boolean.TRUE);
|
||||
builder.addPropertyValue("groupAuthoritiesByUsernameQuery", groupAuthoritiesQuery);
|
||||
builder.addPropertyValue("authoritiesByUsernameQuery", groupAuthoritiesQuery);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -100,9 +100,8 @@ public class LdapProviderBeanDefinitionParser implements BeanDefinitionParser {
|
||||
ldapProvider.addConstructorArg(LdapUserServiceBeanDefinitionParser.parseAuthoritiesPopulator(elt, parserContext));
|
||||
ldapProvider.addPropertyValue("userDetailsContextMapper",
|
||||
LdapUserServiceBeanDefinitionParser.parseUserDetailsClass(elt, parserContext));
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.LDAP_AUTHENTICATION_PROVIDER, ldapProvider.getBeanDefinition());
|
||||
|
||||
ConfigUtils.addAuthenticationProvider(parserContext, BeanIds.LDAP_AUTHENTICATION_PROVIDER);
|
||||
ConfigUtils.getRegisteredProviders(parserContext).add(ldapProvider.getBeanDefinition());
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
+30
-30
@@ -14,22 +14,22 @@ import org.w3c.dom.Element;
|
||||
* @since 2.0
|
||||
*/
|
||||
public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServiceBeanDefinitionParser {
|
||||
public static final String ATT_SERVER = "server-ref";
|
||||
public static final String ATT_SERVER = "server-ref";
|
||||
public static final String ATT_USER_SEARCH_FILTER = "user-search-filter";
|
||||
public static final String ATT_USER_SEARCH_BASE = "user-search-base";
|
||||
public static final String DEF_USER_SEARCH_BASE = "";
|
||||
|
||||
public static final String ATT_GROUP_SEARCH_FILTER = "group-search-filter";
|
||||
public static final String ATT_GROUP_SEARCH_BASE = "group-search-base";
|
||||
public static final String ATT_GROUP_ROLE_ATTRIBUTE = "group-role-attribute";
|
||||
public static final String ATT_GROUP_ROLE_ATTRIBUTE = "group-role-attribute";
|
||||
public static final String DEF_GROUP_SEARCH_FILTER = "(uniqueMember={0})";
|
||||
public static final String DEF_GROUP_SEARCH_BASE = "";
|
||||
|
||||
public static final String DEF_GROUP_SEARCH_BASE = "ou=groups";
|
||||
|
||||
static final String ATT_ROLE_PREFIX = "role-prefix";
|
||||
static final String ATT_USER_CLASS = "user-details-class";
|
||||
static final String OPT_PERSON = "person";
|
||||
static final String OPT_INETORGPERSON = "inetOrgPerson";
|
||||
|
||||
|
||||
public static final String LDAP_SEARCH_CLASS = "org.springframework.security.ldap.search.FilterBasedLdapUserSearch";
|
||||
public static final String PERSON_MAPPER_CLASS = "org.springframework.security.userdetails.ldap.PersonContextMapper";
|
||||
public static final String INET_ORG_PERSON_MAPPER_CLASS = "org.springframework.security.userdetails.ldap.InetOrgPersonContextMapper";
|
||||
@@ -45,42 +45,42 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ
|
||||
if (!StringUtils.hasText(elt.getAttribute(ATT_USER_SEARCH_FILTER))) {
|
||||
parserContext.getReaderContext().error("User search filter must be supplied", elt);
|
||||
}
|
||||
|
||||
|
||||
builder.addConstructorArg(parseSearchBean(elt, parserContext));
|
||||
builder.addConstructorArg(parseAuthoritiesPopulator(elt, parserContext));
|
||||
builder.addPropertyValue("userDetailsMapper", parseUserDetailsClass(elt, parserContext));
|
||||
}
|
||||
|
||||
|
||||
static RootBeanDefinition parseSearchBean(Element elt, ParserContext parserContext) {
|
||||
String userSearchFilter = elt.getAttribute(ATT_USER_SEARCH_FILTER);
|
||||
String userSearchBase = elt.getAttribute(ATT_USER_SEARCH_BASE);
|
||||
Object source = parserContext.extractSource(elt);
|
||||
|
||||
|
||||
if (StringUtils.hasText(userSearchBase)) {
|
||||
if(!StringUtils.hasText(userSearchFilter)) {
|
||||
parserContext.getReaderContext().error(ATT_USER_SEARCH_BASE + " cannot be used without a " + ATT_USER_SEARCH_FILTER, source);
|
||||
}
|
||||
} else {
|
||||
userSearchBase = DEF_USER_SEARCH_BASE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!StringUtils.hasText(userSearchFilter)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
BeanDefinitionBuilder searchBuilder = BeanDefinitionBuilder.rootBeanDefinition(LDAP_SEARCH_CLASS);
|
||||
searchBuilder.setSource(source);
|
||||
searchBuilder.addConstructorArg(userSearchBase);
|
||||
searchBuilder.addConstructorArg(userSearchFilter);
|
||||
searchBuilder.addConstructorArg(parseServerReference(elt, parserContext));
|
||||
|
||||
|
||||
return (RootBeanDefinition) searchBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
|
||||
static RuntimeBeanReference parseServerReference(Element elt, ParserContext parserContext) {
|
||||
String server = elt.getAttribute(ATT_SERVER);
|
||||
boolean requiresDefaultName = false;
|
||||
|
||||
|
||||
if (!StringUtils.hasText(server)) {
|
||||
server = BeanIds.CONTEXT_SOURCE;
|
||||
requiresDefaultName = true;
|
||||
@@ -89,27 +89,27 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ
|
||||
RuntimeBeanReference contextSource = new RuntimeBeanReference(server);
|
||||
contextSource.setSource(parserContext.extractSource(elt));
|
||||
LdapConfigUtils.registerPostProcessorIfNecessary(parserContext.getRegistry(), requiresDefaultName);
|
||||
|
||||
|
||||
return contextSource;
|
||||
}
|
||||
|
||||
|
||||
static RootBeanDefinition parseUserDetailsClass(Element elt, ParserContext parserContext) {
|
||||
String userDetailsClass = elt.getAttribute(ATT_USER_CLASS);
|
||||
|
||||
if (OPT_PERSON.equals(userDetailsClass)) {
|
||||
return new RootBeanDefinition(PERSON_MAPPER_CLASS, null, null);
|
||||
} else if (OPT_INETORGPERSON.equals(userDetailsClass)) {
|
||||
return new RootBeanDefinition(INET_ORG_PERSON_MAPPER_CLASS, null, null);
|
||||
}
|
||||
return new RootBeanDefinition(LDAP_USER_MAPPER_CLASS, null, null);
|
||||
String userDetailsClass = elt.getAttribute(ATT_USER_CLASS);
|
||||
|
||||
if (OPT_PERSON.equals(userDetailsClass)) {
|
||||
return new RootBeanDefinition(PERSON_MAPPER_CLASS, null, null);
|
||||
} else if (OPT_INETORGPERSON.equals(userDetailsClass)) {
|
||||
return new RootBeanDefinition(INET_ORG_PERSON_MAPPER_CLASS, null, null);
|
||||
}
|
||||
return new RootBeanDefinition(LDAP_USER_MAPPER_CLASS, null, null);
|
||||
}
|
||||
|
||||
|
||||
static RootBeanDefinition parseAuthoritiesPopulator(Element elt, ParserContext parserContext) {
|
||||
String groupSearchFilter = elt.getAttribute(ATT_GROUP_SEARCH_FILTER);
|
||||
String groupSearchBase = elt.getAttribute(ATT_GROUP_SEARCH_BASE);
|
||||
String groupRoleAttribute = elt.getAttribute(ATT_GROUP_ROLE_ATTRIBUTE);
|
||||
String rolePrefix = elt.getAttribute(ATT_ROLE_PREFIX);
|
||||
|
||||
|
||||
if (!StringUtils.hasText(groupSearchFilter)) {
|
||||
groupSearchFilter = DEF_GROUP_SEARCH_FILTER;
|
||||
}
|
||||
@@ -117,25 +117,25 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ
|
||||
if (!StringUtils.hasText(groupSearchBase)) {
|
||||
groupSearchBase = DEF_GROUP_SEARCH_BASE;
|
||||
}
|
||||
|
||||
|
||||
BeanDefinitionBuilder populator = BeanDefinitionBuilder.rootBeanDefinition(LDAP_AUTHORITIES_POPULATOR_CLASS);
|
||||
populator.setSource(parserContext.extractSource(elt));
|
||||
populator.addConstructorArg(parseServerReference(elt, parserContext));
|
||||
populator.addConstructorArg(groupSearchBase);
|
||||
populator.addPropertyValue("groupSearchFilter", groupSearchFilter);
|
||||
populator.addPropertyValue("searchSubtree", Boolean.TRUE);
|
||||
|
||||
|
||||
if (StringUtils.hasText(rolePrefix)) {
|
||||
if ("none".equals(rolePrefix)) {
|
||||
rolePrefix = "";
|
||||
}
|
||||
populator.addPropertyValue("rolePrefix", rolePrefix);
|
||||
}
|
||||
|
||||
|
||||
if (StringUtils.hasLength(groupRoleAttribute)) {
|
||||
populator.addPropertyValue("groupRoleAttribute", groupRoleAttribute);
|
||||
}
|
||||
|
||||
|
||||
return (RootBeanDefinition) populator.getBeanDefinition();
|
||||
}
|
||||
}
|
||||
|
||||
+2
-8
@@ -25,12 +25,6 @@ public class LogoutBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
static final String ATT_LOGOUT_URL = "logout-url";
|
||||
static final String DEF_LOGOUT_URL = "/j_spring_security_logout";
|
||||
|
||||
String rememberMeServices;
|
||||
|
||||
public LogoutBeanDefinitionParser(String rememberMeServices) {
|
||||
this.rememberMeServices = rememberMeServices;
|
||||
}
|
||||
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
String logoutUrl = null;
|
||||
@@ -72,8 +66,8 @@ public class LogoutBeanDefinitionParser implements BeanDefinitionParser {
|
||||
}
|
||||
handlers.add(sclh);
|
||||
|
||||
if (rememberMeServices != null) {
|
||||
handlers.add(new RuntimeBeanReference(rememberMeServices));
|
||||
if (parserContext.getRegistry().containsBeanDefinition(BeanIds.REMEMBER_ME_SERVICES)) {
|
||||
handlers.add(new RuntimeBeanReference(BeanIds.REMEMBER_ME_SERVICES));
|
||||
}
|
||||
|
||||
builder.addConstructorArg(handlers);
|
||||
|
||||
-59
@@ -1,59 +0,0 @@
|
||||
package org.springframework.security.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.security.providers.ProviderManager;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Extended version of {@link ProviderManager the default authentication manager} which lazily initializes
|
||||
* the list of {@link AuthenticationProvider}s. This prevents some of the issues that have occurred with
|
||||
* namespace configuration where early instantiation of a security interceptor has caused the AuthenticationManager
|
||||
* and thus dependent beans (typically UserDetailsService implementations or DAOs) to be initialized too early.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @since 2.0.4
|
||||
*/
|
||||
public class NamespaceAuthenticationManager extends ProviderManager implements BeanFactoryAware {
|
||||
BeanFactory beanFactory;
|
||||
List providerBeanNames;
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(providerBeanNames, "provideBeanNames has not been set");
|
||||
Assert.notEmpty(providerBeanNames, "No authentication providers were found in the application context");
|
||||
|
||||
super.afterPropertiesSet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Overridden to lazily-initialize the list of providers on first use.
|
||||
*/
|
||||
public List getProviders() {
|
||||
// We use the names array to determine whether the list has been set yet.
|
||||
if (providerBeanNames != null) {
|
||||
List providers = new ArrayList();
|
||||
Iterator beanNames = providerBeanNames.iterator();
|
||||
|
||||
while (beanNames.hasNext()) {
|
||||
providers.add(beanFactory.getBean((String) beanNames.next()));
|
||||
}
|
||||
providerBeanNames = null;
|
||||
|
||||
setProviders(providers);
|
||||
}
|
||||
|
||||
return super.getProviders();
|
||||
}
|
||||
|
||||
public void setProviderBeanNames(List provideBeanNames) {
|
||||
this.providerBeanNames = provideBeanNames;
|
||||
}
|
||||
}
|
||||
+18
-22
@@ -22,7 +22,7 @@ import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* Adds the decorated "Filter" bean into the standard filter chain maintained by the FilterChainProxy.
|
||||
* Adds the decorated "Filter" bean into the standard filter chain maintained by the FilterChainProxy.
|
||||
* This allows user to add their own custom filters to the security chain. If the user's filter
|
||||
* already implements Ordered, and no "order" attribute is specified, the filter's default order will be used.
|
||||
*
|
||||
@@ -33,7 +33,7 @@ public class OrderedFilterBeanDefinitionDecorator implements BeanDefinitionDecor
|
||||
|
||||
public static final String ATT_AFTER = "after";
|
||||
public static final String ATT_BEFORE = "before";
|
||||
public static final String ATT_POSITION = "position";
|
||||
public static final String ATT_POSITION = "position";
|
||||
|
||||
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder holder, ParserContext parserContext) {
|
||||
Element elt = (Element)node;
|
||||
@@ -48,7 +48,7 @@ public class OrderedFilterBeanDefinitionDecorator implements BeanDefinitionDecor
|
||||
}
|
||||
|
||||
ConfigUtils.addHttpFilter(parserContext, wrapper.getBeanDefinition());
|
||||
|
||||
|
||||
return holder;
|
||||
}
|
||||
|
||||
@@ -59,26 +59,22 @@ public class OrderedFilterBeanDefinitionDecorator implements BeanDefinitionDecor
|
||||
String after = elt.getAttribute(ATT_AFTER);
|
||||
String before = elt.getAttribute(ATT_BEFORE);
|
||||
String position = elt.getAttribute(ATT_POSITION);
|
||||
|
||||
|
||||
if(ConfigUtils.countNonEmpty(new String[] {after, before, position}) != 1) {
|
||||
pc.getReaderContext().error("A single '" + ATT_AFTER + "', '" + ATT_BEFORE + "', or '" +
|
||||
ATT_POSITION + "' attribute must be supplied", pc.extractSource(elt));
|
||||
pc.getReaderContext().error("A single '" + ATT_AFTER + "', '" + ATT_BEFORE + "', or '" +
|
||||
ATT_POSITION + "' attribute must be supplied", pc.extractSource(elt));
|
||||
}
|
||||
|
||||
|
||||
if (StringUtils.hasText(position)) {
|
||||
return Integer.toString(FilterChainOrder.getOrder(position));
|
||||
return Integer.toString(FilterChainOrder.getOrder(position));
|
||||
}
|
||||
|
||||
|
||||
if (StringUtils.hasText(after)) {
|
||||
int order = FilterChainOrder.getOrder(after);
|
||||
|
||||
return Integer.toString(order == Integer.MAX_VALUE ? order : order + 1);
|
||||
return Integer.toString(FilterChainOrder.getOrder(after) + 1);
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(before)) {
|
||||
int order = FilterChainOrder.getOrder(before);
|
||||
|
||||
return Integer.toString(order == Integer.MIN_VALUE ? order : order - 1);
|
||||
return Integer.toString(FilterChainOrder.getOrder(before) - 1);
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -125,12 +121,12 @@ public class OrderedFilterBeanDefinitionDecorator implements BeanDefinitionDecor
|
||||
return beanName;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "OrderedFilterDecorator[ delegate=" + delegate + "; order=" + getOrder() + "]";
|
||||
}
|
||||
|
||||
Filter getDelegate() {
|
||||
return delegate;
|
||||
}
|
||||
public String toString() {
|
||||
return "OrderedFilterDecorator[ delegate=" + delegate + "; order=" + getOrder() + "]";
|
||||
}
|
||||
|
||||
Filter getDelegate() {
|
||||
return delegate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-13
@@ -32,7 +32,6 @@ public class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
|
||||
static final String ATT_TOKEN_VALIDITY = "token-validity-seconds";
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
private String servicesName;
|
||||
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
String tokenRepository = null;
|
||||
@@ -85,7 +84,7 @@ public class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
|
||||
tokenRepo = new RuntimeBeanReference(tokenRepository);
|
||||
} else {
|
||||
tokenRepo = new RootBeanDefinition(JdbcTokenRepositoryImpl.class);
|
||||
((BeanDefinition)tokenRepo).getPropertyValues().addPropertyValue("dataSource",
|
||||
((BeanDefinition)tokenRepo).getPropertyValues().addPropertyValue(ATT_DATA_SOURCE,
|
||||
new RuntimeBeanReference(dataSource));
|
||||
}
|
||||
services.getPropertyValues().addPropertyValue("tokenRepository", tokenRepo);
|
||||
@@ -103,10 +102,8 @@ public class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
|
||||
}
|
||||
services.setSource(source);
|
||||
services.getPropertyValues().addPropertyValue(ATT_KEY, key);
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_SERVICES, services);
|
||||
servicesName = BeanIds.REMEMBER_ME_SERVICES;
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_SERVICES, services);
|
||||
} else {
|
||||
servicesName = rememberMeServicesRef;
|
||||
parserContext.getRegistry().registerAlias(rememberMeServicesRef, BeanIds.REMEMBER_ME_SERVICES);
|
||||
}
|
||||
|
||||
@@ -117,17 +114,13 @@ public class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
|
||||
return null;
|
||||
}
|
||||
|
||||
String getServicesName() {
|
||||
return servicesName;
|
||||
}
|
||||
|
||||
private void registerProvider(ParserContext pc, Object source, String key) {
|
||||
//BeanDefinition authManager = ConfigUtils.registerProviderManagerIfNecessary(pc);
|
||||
private void registerProvider(ParserContext pc, Object source, String key) {
|
||||
BeanDefinition authManager = ConfigUtils.registerProviderManagerIfNecessary(pc);
|
||||
RootBeanDefinition provider = new RootBeanDefinition(RememberMeAuthenticationProvider.class);
|
||||
provider.setSource(source);
|
||||
provider.getPropertyValues().addPropertyValue(ATT_KEY, key);
|
||||
pc.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_AUTHENTICATION_PROVIDER, provider);
|
||||
ConfigUtils.addAuthenticationProvider(pc, BeanIds.REMEMBER_ME_AUTHENTICATION_PROVIDER);
|
||||
ManagedList providers = (ManagedList) authManager.getPropertyValues().getPropertyValue("providers").getValue();
|
||||
providers.add(provider);
|
||||
}
|
||||
|
||||
private void registerFilter(ParserContext pc, Object source) {
|
||||
|
||||
+1
-2
@@ -51,8 +51,7 @@ public class RememberMeServicesInjectionBeanPostProcessor implements BeanPostPro
|
||||
Map beans = beanFactory.getBeansOfType(RememberMeServices.class);
|
||||
|
||||
Assert.isTrue(beans.size() > 0, "No RememberMeServices configured");
|
||||
Assert.isTrue(beans.size() == 1, "Use of '<remember-me />' requires a single instance of RememberMeServices " +
|
||||
"in the application context, but more than one was found.");
|
||||
Assert.isTrue(beans.size() == 1, "More than one RememberMeServices bean found.");
|
||||
|
||||
return (RememberMeServices) beans.values().toArray()[0];
|
||||
}
|
||||
|
||||
-94
@@ -1,94 +0,0 @@
|
||||
package org.springframework.security.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.security.concurrent.ConcurrentSessionController;
|
||||
import org.springframework.security.concurrent.ConcurrentSessionControllerImpl;
|
||||
import org.springframework.security.concurrent.SessionRegistry;
|
||||
import org.springframework.security.ui.AbstractProcessingFilter;
|
||||
import org.springframework.security.ui.SessionFixationProtectionFilter;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Registered by the <tt>AuthenticationManagerBeanDefinitionParser</tt> if an external
|
||||
* ConcurrentSessionController is set (and hence an external SessionRegistry).
|
||||
* Its responsibility is to set the SessionRegistry on namespace-registered beans which require access
|
||||
* to it.
|
||||
* <p>
|
||||
* It will attempt to read the registry directly from the registered controller. If that fails, it will look in
|
||||
* the application context for a registered SessionRegistry bean.
|
||||
*
|
||||
* See SEC-879.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @since 2.0.3
|
||||
*/
|
||||
class SessionRegistryInjectionBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
private ListableBeanFactory beanFactory;
|
||||
private SessionRegistry sessionRegistry;
|
||||
private final String controllerBeanName;
|
||||
|
||||
SessionRegistryInjectionBeanPostProcessor(String controllerBeanName) {
|
||||
this.controllerBeanName = controllerBeanName;
|
||||
}
|
||||
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
if (BeanIds.FORM_LOGIN_FILTER.equals(beanName) ||
|
||||
BeanIds.OPEN_ID_FILTER.equals(beanName)) {
|
||||
((AbstractProcessingFilter) bean).setSessionRegistry(getSessionRegistry());
|
||||
} else if (BeanIds.SESSION_FIXATION_PROTECTION_FILTER.equals(beanName)) {
|
||||
((SessionFixationProtectionFilter)bean).setSessionRegistry(getSessionRegistry());
|
||||
}
|
||||
|
||||
return bean;
|
||||
}
|
||||
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
return bean;
|
||||
}
|
||||
|
||||
private SessionRegistry getSessionRegistry() {
|
||||
if (sessionRegistry != null) {
|
||||
return sessionRegistry;
|
||||
}
|
||||
|
||||
logger.info("Attempting to read SessionRegistry from registered ConcurrentSessionController bean");
|
||||
|
||||
ConcurrentSessionController controller = (ConcurrentSessionController) beanFactory.getBean(controllerBeanName);
|
||||
|
||||
if (controller instanceof ConcurrentSessionControllerImpl) {
|
||||
sessionRegistry = ((ConcurrentSessionControllerImpl)controller).getSessionRegistry();
|
||||
|
||||
return sessionRegistry;
|
||||
}
|
||||
|
||||
logger.info("ConcurrentSessionController is not a standard implementation. SessionRegistry could not be read from it. Looking for it in the context.");
|
||||
|
||||
List sessionRegs = new ArrayList(beanFactory.getBeansOfType(SessionRegistry.class).values());
|
||||
|
||||
if (sessionRegs.size() == 0) {
|
||||
throw new SecurityConfigurationException("concurrent-session-controller-ref was set but no SessionRegistry could be obtained from the application context.");
|
||||
}
|
||||
|
||||
if (sessionRegs.size() > 1) {
|
||||
logger.warn("More than one SessionRegistry instance in application context. Possible configuration errors may result.");
|
||||
}
|
||||
|
||||
sessionRegistry = (SessionRegistry) sessionRegs.get(0);
|
||||
|
||||
return sessionRegistry;
|
||||
}
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = (ListableBeanFactory) beanFactory;
|
||||
}
|
||||
}
|
||||
+72
-70
@@ -2,6 +2,8 @@ package org.springframework.security.config;
|
||||
|
||||
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;
|
||||
@@ -19,91 +21,91 @@ import org.springframework.security.userdetails.UserDetailsService;
|
||||
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 ConfigurableListableBeanFactory beanFactory;
|
||||
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
if (BeanIds.X509_AUTH_PROVIDER.equals(beanName)) {
|
||||
injectUserDetailsServiceIntoX509Provider((PreAuthenticatedAuthenticationProvider) bean);
|
||||
} else if (BeanIds.REMEMBER_ME_SERVICES.equals(beanName)) {
|
||||
injectUserDetailsServiceIntoRememberMeServices((AbstractRememberMeServices)bean);
|
||||
} else if (BeanIds.OPEN_ID_PROVIDER.equals(beanName)) {
|
||||
injectUserDetailsServiceIntoOpenIDProvider(bean);
|
||||
}
|
||||
|
||||
return bean;
|
||||
}
|
||||
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
return bean;
|
||||
}
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
private ConfigurableListableBeanFactory beanFactory;
|
||||
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
if (BeanIds.X509_AUTH_PROVIDER.equals(beanName)) {
|
||||
injectUserDetailsServiceIntoX509Provider((PreAuthenticatedAuthenticationProvider) bean);
|
||||
} else if (BeanIds.REMEMBER_ME_SERVICES.equals(beanName)) {
|
||||
injectUserDetailsServiceIntoRememberMeServices((AbstractRememberMeServices)bean);
|
||||
} else if (BeanIds.OPEN_ID_PROVIDER.equals(beanName)) {
|
||||
injectUserDetailsServiceIntoOpenIDProvider(bean);
|
||||
}
|
||||
|
||||
return bean;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
return bean;
|
||||
}
|
||||
|
||||
private void injectUserDetailsServiceIntoRememberMeServices(AbstractRememberMeServices services) {
|
||||
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(BeanIds.REMEMBER_ME_SERVICES);
|
||||
PropertyValue pv = beanDefinition.getPropertyValues().getPropertyValue("userDetailsService");
|
||||
|
||||
if (pv == null) {
|
||||
services.setUserDetailsService(getUserDetailsService());
|
||||
services.setUserDetailsService(getUserDetailsService());
|
||||
} else {
|
||||
UserDetailsService cachingUserService = getCachingUserService(pv.getValue());
|
||||
|
||||
if (cachingUserService != null) {
|
||||
services.setUserDetailsService(cachingUserService);
|
||||
}
|
||||
UserDetailsService cachingUserService = getCachingUserService(pv.getValue());
|
||||
|
||||
if (cachingUserService != null) {
|
||||
services.setUserDetailsService(cachingUserService);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void injectUserDetailsServiceIntoX509Provider(PreAuthenticatedAuthenticationProvider provider) {
|
||||
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(BeanIds.X509_AUTH_PROVIDER);
|
||||
PropertyValue pv = beanDefinition.getPropertyValues().getPropertyValue("preAuthenticatedUserDetailsService");
|
||||
UserDetailsByNameServiceWrapper wrapper = new UserDetailsByNameServiceWrapper();
|
||||
|
||||
|
||||
if (pv == null) {
|
||||
wrapper.setUserDetailsService(getUserDetailsService());
|
||||
provider.setPreAuthenticatedUserDetailsService(wrapper);
|
||||
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);
|
||||
}
|
||||
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(BeanIds.OPEN_ID_PROVIDER);
|
||||
PropertyValue pv = beanDefinition.getPropertyValues().getPropertyValue("userDetailsService");
|
||||
|
||||
if (pv == null) {
|
||||
BeanWrapperImpl beanWrapper = new BeanWrapperImpl(bean);
|
||||
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.
|
||||
* if available so should not be used for beans which need to separate the two.
|
||||
*/
|
||||
UserDetailsService getUserDetailsService() {
|
||||
Map beans = beanFactory.getBeansOfType(CachingUserDetailsService.class);
|
||||
|
||||
if (beans.size() == 0) {
|
||||
beans = beanFactory.getBeansOfType(UserDetailsService.class);
|
||||
}
|
||||
|
||||
Map beans = beanFactory.getBeansOfType(CachingUserDetailsService.class);
|
||||
|
||||
if (beans.size() == 0) {
|
||||
beans = beanFactory.getBeansOfType(UserDetailsService.class);
|
||||
}
|
||||
|
||||
if (beans.size() == 0) {
|
||||
throw new SecurityConfigurationException("No UserDetailsService registered.");
|
||||
|
||||
@@ -114,24 +116,24 @@ public class UserDetailsServiceInjectionBeanPostProcessor implements BeanPostPro
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
|
||||
}
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ public class X509BeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
BeanDefinition provider = new RootBeanDefinition(PreAuthenticatedAuthenticationProvider.class);
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.X509_AUTH_PROVIDER, provider);
|
||||
ConfigUtils.addAuthenticationProvider(parserContext, BeanIds.X509_AUTH_PROVIDER);
|
||||
ConfigUtils.getRegisteredProviders(parserContext).add(new RuntimeBeanReference(BeanIds.X509_AUTH_PROVIDER));
|
||||
|
||||
String userServiceRef = element.getAttribute(ATT_USER_SERVICE_REF);
|
||||
|
||||
|
||||
+100
-101
@@ -18,11 +18,11 @@ import org.springframework.util.ObjectUtils;
|
||||
* Abstract implementation of {@link MethodDefinitionSource} that supports both Spring AOP and AspectJ and
|
||||
* caches configuration attribute resolution from: 1. specific target method; 2. target class; 3. declaring method;
|
||||
* 4. declaring class/interface.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* This class mimics the behaviour of Spring's AbstractFallbackTransactionAttributeSource class.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Note that this class cannot extract security metadata where that metadata is expressed by way of
|
||||
* a target method/class (ie #1 and #2 above) AND the target method/class is encapsulated in another
|
||||
@@ -31,7 +31,7 @@ import org.springframework.util.ObjectUtils;
|
||||
* another proxy), move the metadata to declared methods or interfaces the proxy implements, or provide
|
||||
* your own replacement <tt>MethodDefinitionSource</tt>.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
* @since 2.0
|
||||
@@ -39,16 +39,15 @@ import org.springframework.util.ObjectUtils;
|
||||
public abstract class AbstractFallbackMethodDefinitionSource implements MethodDefinitionSource {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(AbstractFallbackMethodDefinitionSource.class);
|
||||
private final static Object NULL_CONFIG_ATTRIBUTE = new Object();
|
||||
private final static Object NULL_CONFIG_ATTRIBUTE = new Object();
|
||||
private final Map attributeCache = new HashMap();
|
||||
|
||||
public ConfigAttributeDefinition getAttributes(Object object) throws IllegalArgumentException {
|
||||
Assert.notNull(object, "Object cannot be null");
|
||||
|
||||
if (object instanceof MethodInvocation) {
|
||||
MethodInvocation mi = (MethodInvocation) object;
|
||||
Object target = mi.getThis();
|
||||
return getAttributes(mi.getMethod(), target == null ? null : target.getClass());
|
||||
MethodInvocation mi = (MethodInvocation) object;
|
||||
return getAttributes(mi.getMethod(), mi.getThis().getClass());
|
||||
}
|
||||
|
||||
if (object instanceof JoinPoint) {
|
||||
@@ -60,143 +59,143 @@ public abstract class AbstractFallbackMethodDefinitionSource implements MethodDe
|
||||
|
||||
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 MethodInvocation or JoinPoint");
|
||||
}
|
||||
|
||||
|
||||
public final boolean supports(Class clazz) {
|
||||
return (MethodInvocation.class.isAssignableFrom(clazz) || JoinPoint.class.isAssignableFrom(clazz));
|
||||
}
|
||||
|
||||
|
||||
public ConfigAttributeDefinition getAttributes(Method method, Class targetClass) {
|
||||
// First, see if we have a cached value.
|
||||
Object cacheKey = new DefaultCacheKey(method, targetClass);
|
||||
synchronized (this.attributeCache) {
|
||||
Object cached = this.attributeCache.get(cacheKey);
|
||||
if (cached != null) {
|
||||
// Value will either be canonical value indicating there is no config attribute,
|
||||
// or an actual config attribute.
|
||||
if (cached == NULL_CONFIG_ATTRIBUTE) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return (ConfigAttributeDefinition) cached;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// We need to work it out.
|
||||
ConfigAttributeDefinition cfgAtt = computeAttributes(method, targetClass);
|
||||
// Put it in the cache.
|
||||
if (cfgAtt == null) {
|
||||
this.attributeCache.put(cacheKey, NULL_CONFIG_ATTRIBUTE);
|
||||
}
|
||||
else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Adding security method [" + cacheKey + "] with attribute [" + cfgAtt + "]");
|
||||
}
|
||||
this.attributeCache.put(cacheKey, cfgAtt);
|
||||
}
|
||||
return cfgAtt;
|
||||
}
|
||||
}
|
||||
// First, see if we have a cached value.
|
||||
Object cacheKey = new DefaultCacheKey(method, targetClass);
|
||||
synchronized (this.attributeCache) {
|
||||
Object cached = this.attributeCache.get(cacheKey);
|
||||
if (cached != null) {
|
||||
// Value will either be canonical value indicating there is no config attribute,
|
||||
// or an actual config attribute.
|
||||
if (cached == NULL_CONFIG_ATTRIBUTE) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return (ConfigAttributeDefinition) cached;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// We need to work it out.
|
||||
ConfigAttributeDefinition cfgAtt = computeAttributes(method, targetClass);
|
||||
// Put it in the cache.
|
||||
if (cfgAtt == null) {
|
||||
this.attributeCache.put(cacheKey, NULL_CONFIG_ATTRIBUTE);
|
||||
}
|
||||
else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Adding security method [" + cacheKey + "] with attribute [" + cfgAtt + "]");
|
||||
}
|
||||
this.attributeCache.put(cacheKey, cfgAtt);
|
||||
}
|
||||
return cfgAtt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param method the method for the current invocation (never <code>null</code>)
|
||||
* @param targetClass the target class for this invocation (may be <code>null</code>)
|
||||
*
|
||||
* @param method the method for the current invocation (never <code>null</code>)
|
||||
* @param targetClass the target class for this invocation (may be <code>null</code>)
|
||||
* @return
|
||||
*/
|
||||
private ConfigAttributeDefinition computeAttributes(Method method, Class targetClass) {
|
||||
// The method may be on an interface, but we need attributes from the target class.
|
||||
// If the target class is null, the method will be unchanged.
|
||||
Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
|
||||
// First try is the method in the target class.
|
||||
ConfigAttributeDefinition attr = findAttributes(specificMethod, targetClass);
|
||||
if (attr != null) {
|
||||
return attr;
|
||||
}
|
||||
// The method may be on an interface, but we need attributes from the target class.
|
||||
// If the target class is null, the method will be unchanged.
|
||||
Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
|
||||
// First try is the method in the target class.
|
||||
ConfigAttributeDefinition attr = findAttributes(specificMethod, targetClass);
|
||||
if (attr != null) {
|
||||
return attr;
|
||||
}
|
||||
|
||||
// Second try is the config attribute on the target class.
|
||||
attr = findAttributes(specificMethod.getDeclaringClass());
|
||||
if (attr != null) {
|
||||
return attr;
|
||||
}
|
||||
// Second try is the config attribute on the target class.
|
||||
attr = findAttributes(specificMethod.getDeclaringClass());
|
||||
if (attr != null) {
|
||||
return attr;
|
||||
}
|
||||
|
||||
if (specificMethod != method || targetClass == null) {
|
||||
// Fallback is to look at the original method.
|
||||
attr = findAttributes(method, method.getDeclaringClass());
|
||||
if (attr != null) {
|
||||
return attr;
|
||||
}
|
||||
// Last fallback is the class of the original method.
|
||||
return findAttributes(method.getDeclaringClass());
|
||||
}
|
||||
return null;
|
||||
if (specificMethod != method) {
|
||||
// Fallback is to look at the original method.
|
||||
attr = findAttributes(method, method.getDeclaringClass());
|
||||
if (attr != null) {
|
||||
return attr;
|
||||
}
|
||||
// Last fallback is the class of the original method.
|
||||
return findAttributes(method.getDeclaringClass());
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtains the security metadata applicable to the specified method invocation.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Note that the {@link Method#getDeclaringClass()} may not equal the <code>targetClass</code>.
|
||||
* Both parameters are provided to assist subclasses which may wish to provide advanced
|
||||
* capabilities related to method metadata being "registered" against a method even if the
|
||||
* target class does not declare the method (i.e. the subclass may only inherit the method).
|
||||
*
|
||||
*
|
||||
* @param method the method for the current invocation (never <code>null</code>)
|
||||
* @param targetClass the target class for the invocation (may be <code>null</code>)
|
||||
* @return the security metadata (or null if no metadata applies)
|
||||
*/
|
||||
protected abstract ConfigAttributeDefinition findAttributes(Method method, Class targetClass);
|
||||
|
||||
|
||||
/**
|
||||
* Obtains the security metadata registered against the specified class.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Subclasses should only return metadata expressed at a class level. Subclasses should NOT
|
||||
* aggregate metadata for each method registered against a class, as the abstract superclass
|
||||
* will separate invoke {@link #findAttributes(Method, Class)} for individual methods as
|
||||
* appropriate.
|
||||
*
|
||||
* appropriate.
|
||||
*
|
||||
* @param clazz the target class for the invocation (never <code>null</code>)
|
||||
* @return the security metadata (or null if no metadata applies)
|
||||
*/
|
||||
protected abstract ConfigAttributeDefinition findAttributes(Class clazz);
|
||||
|
||||
private static class DefaultCacheKey {
|
||||
|
||||
private static class DefaultCacheKey {
|
||||
private final Method method;
|
||||
private final Class targetClass;
|
||||
|
||||
private final Method method;
|
||||
private final Class targetClass;
|
||||
public DefaultCacheKey(Method method, Class targetClass) {
|
||||
this.method = method;
|
||||
this.targetClass = targetClass;
|
||||
}
|
||||
|
||||
public DefaultCacheKey(Method method, Class targetClass) {
|
||||
this.method = method;
|
||||
this.targetClass = targetClass;
|
||||
}
|
||||
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));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.method.hashCode() * 21 + (this.targetClass != null ? this.targetClass.hashCode() : 0);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "CacheKey[" + (targetClass == null ? "-" : targetClass.getName()) + "; " + method + "]";
|
||||
}
|
||||
}
|
||||
public int hashCode() {
|
||||
return this.method.hashCode() * 21 + (this.targetClass != null ? this.targetClass.hashCode() : 0);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "CacheKey[" + (targetClass == null ? "-" : targetClass.getName()) + "; " + method + "]";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+124
-106
@@ -34,13 +34,13 @@ import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Stores a {@link ConfigAttributeDefinition} for a method or class signature.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* This class is the preferred implementation of {@link MethodDefinitionSource} for XML-based
|
||||
* definition of method security metadata. To assist in XML-based definition, wildcard support
|
||||
* is provided.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
* @since 2.0
|
||||
@@ -51,9 +51,9 @@ public class MapBasedMethodDefinitionSource extends AbstractFallbackMethodDefini
|
||||
private static final Log logger = LogFactory.getLog(MapBasedMethodDefinitionSource.class);
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
|
||||
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
|
||||
|
||||
/** Map from RegisteredMethod to ConfigAttributeDefinition */
|
||||
/** Map from RegisteredMethod to ConfigAttributeDefinition */
|
||||
protected Map methodMap = new HashMap();
|
||||
|
||||
/** Map from RegisteredMethod to name pattern used for registration */
|
||||
@@ -74,37 +74,48 @@ public class MapBasedMethodDefinitionSource extends AbstractFallbackMethodDefini
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry entry = (Map.Entry) iterator.next();
|
||||
addSecureMethod((String)entry.getKey(), (ConfigAttributeDefinition)entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation does not support class-level attributes.
|
||||
*/
|
||||
protected ConfigAttributeDefinition findAttributes(Class clazz) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will walk the method inheritance tree to find the most specific declaration applicable.
|
||||
*/
|
||||
protected ConfigAttributeDefinition findAttributes(Method method, Class targetClass) {
|
||||
return findAttributesSpecifiedAgainst(method, targetClass);
|
||||
}
|
||||
|
||||
private ConfigAttributeDefinition findAttributesSpecifiedAgainst(Method method, Class clazz) {
|
||||
RegisteredMethod registeredMethod = new RegisteredMethod(method, clazz);
|
||||
if (methodMap.containsKey(registeredMethod)) {
|
||||
return (ConfigAttributeDefinition) methodMap.get(registeredMethod);
|
||||
}
|
||||
// Search superclass
|
||||
if (clazz.getSuperclass() != null) {
|
||||
return findAttributesSpecifiedAgainst(method, clazz.getSuperclass());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation does not support class-level attributes.
|
||||
* Add configuration attributes for a secure method.
|
||||
*
|
||||
* @param method the method to be secured
|
||||
* @param attr required authorities associated with the method
|
||||
*/
|
||||
protected ConfigAttributeDefinition findAttributes(Class clazz) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will walk the method inheritance tree to find the most specific declaration applicable.
|
||||
*/
|
||||
protected ConfigAttributeDefinition findAttributes(Method method, Class targetClass) {
|
||||
if (targetClass == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return findAttributesSpecifiedAgainst(method, targetClass);
|
||||
}
|
||||
|
||||
private ConfigAttributeDefinition findAttributesSpecifiedAgainst(Method method, Class clazz) {
|
||||
RegisteredMethod registeredMethod = new RegisteredMethod(method, clazz);
|
||||
if (methodMap.containsKey(registeredMethod)) {
|
||||
return (ConfigAttributeDefinition) methodMap.get(registeredMethod);
|
||||
}
|
||||
// Search superclass
|
||||
if (clazz.getSuperclass() != null) {
|
||||
return findAttributesSpecifiedAgainst(method, clazz.getSuperclass());
|
||||
}
|
||||
return null;
|
||||
private void addSecureMethod(RegisteredMethod method, ConfigAttributeDefinition attr) {
|
||||
Assert.notNull(method, "RegisteredMethod required");
|
||||
Assert.notNull(attr, "Configuration attribute required");
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Adding secure method [" + method + "] with attributes [" + attr + "]");
|
||||
}
|
||||
this.methodMap.put(method, attr);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -115,7 +126,7 @@ public class MapBasedMethodDefinitionSource extends AbstractFallbackMethodDefini
|
||||
* @param attr required authorities associated with the method
|
||||
*/
|
||||
public void addSecureMethod(String name, ConfigAttributeDefinition attr) {
|
||||
int lastDotIndex = name.lastIndexOf(".");
|
||||
int lastDotIndex = name.lastIndexOf(".");
|
||||
|
||||
if (lastDotIndex == -1) {
|
||||
throw new IllegalArgumentException("'" + name + "' is not a valid method name: format is FQN.methodName");
|
||||
@@ -123,17 +134,17 @@ public class MapBasedMethodDefinitionSource extends AbstractFallbackMethodDefini
|
||||
|
||||
String methodName = name.substring(lastDotIndex + 1);
|
||||
Assert.hasText(methodName, "Method not found for '" + name + "'");
|
||||
|
||||
|
||||
String typeName = name.substring(0, lastDotIndex);
|
||||
Class type = ClassUtils.resolveClassName(typeName, this.beanClassLoader);
|
||||
|
||||
|
||||
addSecureMethod(type, methodName, attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add configuration attributes for a secure method. Mapped method names can end or start with <code>*</code>
|
||||
* for matching multiple methods.
|
||||
*
|
||||
*
|
||||
* @param javaType target interface or class the security configuration attribute applies to
|
||||
* @param mappedName mapped method name, which the javaType has declared or inherited
|
||||
* @param attr required authorities associated with the method
|
||||
@@ -181,38 +192,6 @@ public class MapBasedMethodDefinitionSource extends AbstractFallbackMethodDefini
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds configuration attributes for a specific method, for example where the method has been
|
||||
* matched using a pointcut expression. If a match already exists in the map for the method, then
|
||||
* the existing match will be retained, so that if this method is called for a more general pointcut
|
||||
* it will not override a more specific one which has already been added. This
|
||||
*/
|
||||
public void addSecureMethod(Class javaType, Method method, ConfigAttributeDefinition attr) {
|
||||
RegisteredMethod key = new RegisteredMethod(method, javaType);
|
||||
|
||||
if (methodMap.containsKey(key)) {
|
||||
logger.debug("Method [" + method + "] is already registered with attributes [" + methodMap.get(key) + "]");
|
||||
return;
|
||||
}
|
||||
|
||||
methodMap.put(key, attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add configuration attributes for a secure method.
|
||||
*
|
||||
* @param method the method to be secured
|
||||
* @param attr required authorities associated with the method
|
||||
*/
|
||||
private void addSecureMethod(RegisteredMethod method, ConfigAttributeDefinition attr) {
|
||||
Assert.notNull(method, "RegisteredMethod required");
|
||||
Assert.notNull(attr, "Configuration attribute required");
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Adding secure method [" + method + "] with attributes [" + attr + "]");
|
||||
}
|
||||
this.methodMap.put(method, attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the configuration attributes explicitly defined against this bean.
|
||||
*
|
||||
@@ -236,54 +215,93 @@ public class MapBasedMethodDefinitionSource extends AbstractFallbackMethodDefini
|
||||
|| (mappedName.startsWith("*") && methodName.endsWith(mappedName.substring(1, mappedName.length())));
|
||||
}
|
||||
|
||||
public void setBeanClassLoader(ClassLoader beanClassLoader) {
|
||||
Assert.notNull(beanClassLoader, "Bean class loader required");
|
||||
this.beanClassLoader = beanClassLoader;
|
||||
}
|
||||
protected ConfigAttributeDefinition lookupAttributes(Method method) {
|
||||
List attributesToReturn = new ArrayList();
|
||||
|
||||
/**
|
||||
* @return map size (for unit tests and diagnostics)
|
||||
*/
|
||||
public int getMethodMapSize() {
|
||||
return methodMap.size();
|
||||
}
|
||||
// Add attributes explicitly defined for this method invocation
|
||||
merge(attributesToReturn, (ConfigAttributeDefinition) this.methodMap.get(method));
|
||||
|
||||
/**
|
||||
* Stores both the Java Method as well as the Class we obtained the Method from. This is necessary because Method only
|
||||
* provides us access to the declaring class. It doesn't provide a way for us to introspect which Class the Method
|
||||
* was registered against. If a given Class inherits and redeclares a method (i.e. calls super();) the registered Class
|
||||
* and declaring Class are the same. If a given class merely inherits but does not redeclare a method, the registered
|
||||
* 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;
|
||||
// Add attributes explicitly defined for this method invocation's interfaces
|
||||
Class[] interfaces = method.getDeclaringClass().getInterfaces();
|
||||
|
||||
public RegisteredMethod(Method method, Class registeredJavaType) {
|
||||
Assert.notNull(method, "Method required");
|
||||
Assert.notNull(registeredJavaType, "Registered Java Type required");
|
||||
this.method = method;
|
||||
this.registeredJavaType = registeredJavaType;
|
||||
}
|
||||
for (int i = 0; i < interfaces.length; i++) {
|
||||
Class clazz = interfaces[i];
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
try {
|
||||
// Look for the method on the current interface
|
||||
Method interfaceMethod = clazz.getDeclaredMethod(method.getName(), (Class[]) method.getParameterTypes());
|
||||
ConfigAttributeDefinition interfaceAssigned =
|
||||
(ConfigAttributeDefinition) this.methodMap.get(interfaceMethod);
|
||||
merge(attributesToReturn, interfaceAssigned);
|
||||
} catch (Exception e) {
|
||||
// skip this interface
|
||||
}
|
||||
if (obj != null && obj instanceof RegisteredMethod) {
|
||||
RegisteredMethod rhs = (RegisteredMethod) obj;
|
||||
return method.equals(rhs.method) && registeredJavaType.equals(rhs.registeredJavaType);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return method.hashCode() * registeredJavaType.hashCode();
|
||||
// Return null if empty, as per abstract superclass contract
|
||||
if (attributesToReturn.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "RegisteredMethod[" + registeredJavaType.getName() + "; " + method + "]";
|
||||
}
|
||||
return new ConfigAttributeDefinition(attributesToReturn);
|
||||
}
|
||||
|
||||
private void merge(List attributes, ConfigAttributeDefinition toMerge) {
|
||||
if (toMerge == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
attributes.addAll(toMerge.getConfigAttributes());
|
||||
}
|
||||
|
||||
public void setBeanClassLoader(ClassLoader beanClassLoader) {
|
||||
Assert.notNull(beanClassLoader, "Bean class loader required");
|
||||
this.beanClassLoader = beanClassLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return map size (for unit tests and diagnostics)
|
||||
*/
|
||||
public int getMethodMapSize() {
|
||||
return methodMap.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores both the Java Method as well as the Class we obtained the Method from. This is necessary because Method only
|
||||
* provides us access to the declaring class. It doesn't provide a way for us to introspect which Class the Method
|
||||
* was registered against. If a given Class inherits and redeclares a method (i.e. calls super();) the registered Class
|
||||
* and declaring Class are the same. If a given class merely inherits but does not redeclare a method, the registered
|
||||
* 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;
|
||||
|
||||
public RegisteredMethod(Method method, Class registeredJavaType) {
|
||||
Assert.notNull(method, "Method required");
|
||||
Assert.notNull(registeredJavaType, "Registered Java Type required");
|
||||
this.method = method;
|
||||
this.registeredJavaType = registeredJavaType;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj != null && obj instanceof RegisteredMethod) {
|
||||
RegisteredMethod rhs = (RegisteredMethod) obj;
|
||||
return method.equals(rhs.method) && registeredJavaType.equals(rhs.registeredJavaType);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return method.hashCode() * registeredJavaType.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "RegisteredMethod[" + registeredJavaType.getName() + "; " + method + "]";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+88
-100
@@ -17,30 +17,29 @@ import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.security.ConfigAttributeDefinition;
|
||||
import org.springframework.security.intercept.method.aopalliance.MethodDefinitionSourceAdvisor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Parses AspectJ pointcut expressions, registering methods that match the pointcut with a
|
||||
* traditional {@link MapBasedMethodDefinitionSource}.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* This class provides a convenient way of declaring a list of pointcuts, and then
|
||||
* having every method of every bean defined in the Spring application context compared with
|
||||
* those pointcuts. Where a match is found, the matching method will be registered with the
|
||||
* {@link MapBasedMethodDefinitionSource}.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* It is very important to understand that only the <b>first</b> pointcut that matches a given
|
||||
* method will be taken as authoritative for that method. This is why pointcuts should be provided
|
||||
* as a <tt>LinkedHashMap</tt>, because their order is very important.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Note also that only beans defined in the Spring application context will be examined by this
|
||||
* class.
|
||||
* class.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Because this class registers method security metadata with {@link MapBasedMethodDefinitionSource},
|
||||
* normal Spring Security capabilities such as {@link MethodDefinitionSourceAdvisor} can be used.
|
||||
@@ -58,18 +57,18 @@ public final class ProtectPointcutPostProcessor implements BeanPostProcessor {
|
||||
private static final Log logger = LogFactory.getLog(ProtectPointcutPostProcessor.class);
|
||||
|
||||
private Map pointcutMap = new LinkedHashMap(); /** Key: string-based pointcut, value: ConfigAttributeDefinition */
|
||||
private MapBasedMethodDefinitionSource mapBasedMethodDefinitionSource;
|
||||
private PointcutParser parser;
|
||||
|
||||
public ProtectPointcutPostProcessor(MapBasedMethodDefinitionSource mapBasedMethodDefinitionSource) {
|
||||
Assert.notNull(mapBasedMethodDefinitionSource, "MapBasedMethodDefinitionSource to populate is required");
|
||||
this.mapBasedMethodDefinitionSource = mapBasedMethodDefinitionSource;
|
||||
|
||||
// Setup AspectJ pointcut expression parser
|
||||
Set supportedPrimitives = new HashSet();
|
||||
supportedPrimitives.add(PointcutPrimitive.EXECUTION);
|
||||
supportedPrimitives.add(PointcutPrimitive.ARGS);
|
||||
supportedPrimitives.add(PointcutPrimitive.REFERENCE);
|
||||
private MapBasedMethodDefinitionSource mapBasedMethodDefinitionSource;
|
||||
private PointcutParser parser;
|
||||
|
||||
public ProtectPointcutPostProcessor(MapBasedMethodDefinitionSource mapBasedMethodDefinitionSource) {
|
||||
Assert.notNull(mapBasedMethodDefinitionSource, "MapBasedMethodDefinitionSource to populate is required");
|
||||
this.mapBasedMethodDefinitionSource = mapBasedMethodDefinitionSource;
|
||||
|
||||
// Setup AspectJ pointcut expression parser
|
||||
Set supportedPrimitives = new HashSet();
|
||||
supportedPrimitives.add(PointcutPrimitive.EXECUTION);
|
||||
supportedPrimitives.add(PointcutPrimitive.ARGS);
|
||||
supportedPrimitives.add(PointcutPrimitive.REFERENCE);
|
||||
// supportedPrimitives.add(PointcutPrimitive.THIS);
|
||||
// supportedPrimitives.add(PointcutPrimitive.TARGET);
|
||||
// supportedPrimitives.add(PointcutPrimitive.WITHIN);
|
||||
@@ -77,90 +76,79 @@ public final class ProtectPointcutPostProcessor implements BeanPostProcessor {
|
||||
// supportedPrimitives.add(PointcutPrimitive.AT_WITHIN);
|
||||
// supportedPrimitives.add(PointcutPrimitive.AT_ARGS);
|
||||
// supportedPrimitives.add(PointcutPrimitive.AT_TARGET);
|
||||
parser = PointcutParser.getPointcutParserSupportingSpecifiedPrimitivesAndUsingContextClassloaderForResolution(supportedPrimitives);
|
||||
}
|
||||
parser = PointcutParser.getPointcutParserSupportingSpecifiedPrimitivesAndUsingContextClassloaderForResolution(supportedPrimitives);
|
||||
}
|
||||
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
return bean;
|
||||
}
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
return bean;
|
||||
}
|
||||
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
// Obtain methods for the present bean
|
||||
Method[] methods;
|
||||
try {
|
||||
methods = bean.getClass().getMethods();
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException(e.getMessage());
|
||||
}
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
// Obtain methods for the present bean
|
||||
Method[] methods;
|
||||
try {
|
||||
methods = bean.getClass().getMethods();
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException(e.getMessage());
|
||||
}
|
||||
|
||||
// Check to see if any of those methods are compatible with our pointcut expressions
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
Iterator iter = pointcutMap.keySet().iterator();
|
||||
while (iter.hasNext()) {
|
||||
String ex = iter.next().toString();
|
||||
|
||||
// Parse the presented AspectJ pointcut expression
|
||||
PointcutExpression expression = parser.parsePointcutExpression(ex);
|
||||
|
||||
// Check to see if any of those methods are compatible with our pointcut expressions
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
Iterator iter = pointcutMap.keySet().iterator();
|
||||
while (iter.hasNext()) {
|
||||
String ex = iter.next().toString();
|
||||
|
||||
// Parse the presented AspectJ pointcut expression
|
||||
PointcutExpression expression = parser.parsePointcutExpression(ex);
|
||||
|
||||
// Try for the bean class directly
|
||||
if (attemptMatch(bean.getClass(), methods[i], 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bean;
|
||||
}
|
||||
|
||||
private boolean attemptMatch(Class targetClass, Method method, PointcutExpression expression, String beanName) {
|
||||
// Determine if the presented AspectJ pointcut expression matches this method
|
||||
boolean matches = expression.matchesMethodExecution(method).alwaysMatches();
|
||||
|
||||
// Handle accordingly
|
||||
if (matches) {
|
||||
ConfigAttributeDefinition attr = (ConfigAttributeDefinition) pointcutMap.get(expression.getPointcutExpression());
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("AspectJ pointcut expression '" + expression.getPointcutExpression() + "' matches target class '" + targetClass.getName() + "' (bean ID '" + beanName + "') for method '" + method + "'; registering security configuration attribute '" + attr + "'");
|
||||
}
|
||||
|
||||
mapBasedMethodDefinitionSource.addSecureMethod(targetClass, method, attr);
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
public void setPointcutMap(Map map) {
|
||||
Assert.notEmpty(map);
|
||||
Iterator i = map.keySet().iterator();
|
||||
while (i.hasNext()) {
|
||||
String expression = i.next().toString();
|
||||
Object value = map.get(expression);
|
||||
Assert.isInstanceOf(ConfigAttributeDefinition.class, value, "Map keys must be instances of ConfigAttributeDefinition");
|
||||
addPointcut(expression, (ConfigAttributeDefinition) value);
|
||||
}
|
||||
}
|
||||
|
||||
private void addPointcut(String pointcutExpression, ConfigAttributeDefinition definition) {
|
||||
Assert.hasText(pointcutExpression, "An AspectJ pointcut expression is required");
|
||||
Assert.notNull(definition, "ConfigAttributeDefinition required");
|
||||
pointcutExpression = replaceBooleanOperators(pointcutExpression);
|
||||
pointcutMap.put(pointcutExpression, definition);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("AspectJ pointcut expression '" + pointcutExpression + "' registered for security configuration attribute '" + definition + "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.springframework.aop.aspectj.AspectJExpressionPointcut#replaceBooleanOperators
|
||||
*/
|
||||
private String replaceBooleanOperators(String pcExpr) {
|
||||
pcExpr = StringUtils.replace(pcExpr," and "," && ");
|
||||
pcExpr = StringUtils.replace(pcExpr, " or ", " || ");
|
||||
pcExpr = StringUtils.replace(pcExpr, " not ", " ! ");
|
||||
return pcExpr;
|
||||
}
|
||||
// Try for the bean class directly
|
||||
if (attemptMatch(bean.getClass(), methods[i], 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bean;
|
||||
}
|
||||
|
||||
private boolean attemptMatch(Class targetClass, Method method, PointcutExpression expression, String beanName) {
|
||||
// Determine if the presented AspectJ pointcut expression matches this method
|
||||
boolean matches = expression.matchesMethodExecution(method).alwaysMatches();
|
||||
|
||||
// Handle accordingly
|
||||
if (matches) {
|
||||
ConfigAttributeDefinition attr = (ConfigAttributeDefinition) pointcutMap.get(expression.getPointcutExpression());
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("AspectJ pointcut expression '" + expression.getPointcutExpression() + "' matches target class '" + targetClass.getName() + "' (bean ID '" + beanName + "') for method '" + method + "'; registering security configuration attribute '" + attr + "'");
|
||||
}
|
||||
|
||||
mapBasedMethodDefinitionSource.addSecureMethod(targetClass, method.getName(), attr);
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
public void setPointcutMap(Map map) {
|
||||
Assert.notEmpty(map);
|
||||
Iterator i = map.keySet().iterator();
|
||||
while (i.hasNext()) {
|
||||
String expression = i.next().toString();
|
||||
Object value = map.get(expression);
|
||||
Assert.isInstanceOf(ConfigAttributeDefinition.class, value, "Map keys must be instances of ConfigAttributeDefinition");
|
||||
addPointcut(expression, (ConfigAttributeDefinition) value);
|
||||
}
|
||||
}
|
||||
|
||||
public void addPointcut(String pointcutExpression, ConfigAttributeDefinition definition) {
|
||||
Assert.hasText(pointcutExpression, "An AspectJ pointcut expression is required");
|
||||
Assert.notNull(definition, "ConfigAttributeDefinition required");
|
||||
pointcutMap.put(pointcutExpression, definition);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("AspectJ pointcut expression '" + pointcutExpression + "' registered for security configuration attribute '" + definition + "'");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+36
-35
@@ -33,7 +33,7 @@ import org.springframework.util.Assert;
|
||||
* Advisor driven by a {@link MethodDefinitionSource}, used to exclude a {@link MethodSecurityInterceptor} from
|
||||
* public (ie non-secure) methods.
|
||||
* <p>
|
||||
* Because the AOP framework caches advice calculations, this is normally faster than just letting the
|
||||
* Because the AOP framework caches advice calculations, this is normally faster than just letting the
|
||||
* <code>MethodSecurityInterceptor</code> run and find out itself that it has no work to do.
|
||||
* <p>
|
||||
* This class also allows the use of Spring's
|
||||
@@ -63,63 +63,64 @@ public class MethodDefinitionSourceAdvisor extends AbstractPointcutAdvisor imple
|
||||
* @deprecated use the decoupled approach instead
|
||||
*/
|
||||
public MethodDefinitionSourceAdvisor(MethodSecurityInterceptor advice) {
|
||||
Assert.notNull(advice.getObjectDefinitionSource(), "Cannot construct a MethodDefinitionSourceAdvisor using a " +
|
||||
"MethodSecurityInterceptor that has no ObjectDefinitionSource configured");
|
||||
Assert.notNull(advice.getObjectDefinitionSource(), "Cannot construct a MethodDefinitionSourceAdvisor using a " +
|
||||
"MethodSecurityInterceptor that has no ObjectDefinitionSource configured");
|
||||
|
||||
this.interceptor = advice;
|
||||
this.interceptor = advice;
|
||||
this.attributeSource = advice.getObjectDefinitionSource();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
* bean name should be set. This prevents eager instantiation of the interceptor
|
||||
* (and hence the AuthenticationManager). See SEC-773, for example.
|
||||
* <p>
|
||||
* This is essentially the approach taken by subclasses of {@link AbstractBeanFactoryPointcutAdvisor}, which this
|
||||
* class should extend in future. The original hierarchy and constructor have been retained for backwards
|
||||
* compatibility.
|
||||
*
|
||||
* class should extend in future. The original hierarchy and constructor have been retained for backwards
|
||||
* compatibilty.
|
||||
*
|
||||
* @param adviceBeanName name of the MethodSecurityInterceptor bean
|
||||
* @param attributeSource the attribute source (should be the same as the one used on the interceptor)
|
||||
*/
|
||||
public MethodDefinitionSourceAdvisor(String adviceBeanName, MethodDefinitionSource attributeSource) {
|
||||
Assert.notNull(adviceBeanName, "The adviceBeanName cannot be null");
|
||||
Assert.notNull(attributeSource, "The attributeSource cannot be null");
|
||||
|
||||
this.adviceBeanName = adviceBeanName;
|
||||
this.attributeSource = attributeSource;
|
||||
Assert.notNull(adviceBeanName, "The adviceBeanName cannot be null");
|
||||
Assert.notNull(attributeSource, "The attributeSource cannot be null");
|
||||
|
||||
this.adviceBeanName = adviceBeanName;
|
||||
this.attributeSource = attributeSource;
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public Pointcut getPointcut() {
|
||||
return pointcut;
|
||||
}
|
||||
public Pointcut getPointcut() {
|
||||
return pointcut;
|
||||
}
|
||||
|
||||
public Advice getAdvice() {
|
||||
synchronized (this.adviceMonitor) {
|
||||
if (interceptor == null) {
|
||||
Assert.notNull(adviceBeanName, "'adviceBeanName' must be set for use with bean factory lookup.");
|
||||
Assert.state(beanFactory != null, "BeanFactory must be set to resolve 'adviceBeanName'");
|
||||
interceptor = (MethodSecurityInterceptor)
|
||||
beanFactory.getBean(this.adviceBeanName, MethodSecurityInterceptor.class);
|
||||
}
|
||||
return interceptor;
|
||||
}
|
||||
}
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
public Advice getAdvice() {
|
||||
synchronized (this.adviceMonitor) {
|
||||
if (interceptor == null) {
|
||||
Assert.notNull(adviceBeanName, "'adviceBeanName' must be set for use with bean factory lookup.");
|
||||
Assert.state(beanFactory != null, "BeanFactory must be set to resolve 'adviceBeanName'");
|
||||
interceptor = (MethodSecurityInterceptor)
|
||||
beanFactory.getBean(this.adviceBeanName, MethodSecurityInterceptor.class);
|
||||
attributeSource = interceptor.getObjectDefinitionSource();
|
||||
}
|
||||
return interceptor;
|
||||
}
|
||||
}
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
|
||||
class MethodDefinitionSourcePointcut extends StaticMethodMatcherPointcut {
|
||||
public boolean matches(Method m, Class targetClass) {
|
||||
return attributeSource.getAttributes(m, targetClass) != null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Represents a <code>MethodInvocation</code>.
|
||||
* <p>
|
||||
@@ -152,7 +153,7 @@ public class MethodDefinitionSourceAdvisor extends AbstractPointcutAdvisor imple
|
||||
}
|
||||
|
||||
public Object getThis() {
|
||||
return this.targetClass;
|
||||
return this.targetClass;
|
||||
}
|
||||
|
||||
public Object proceed() throws Throwable {
|
||||
|
||||
+1
-1
@@ -12,5 +12,5 @@ package org.springframework.security.intercept.method.aspectj;
|
||||
public interface AspectJAnnotationCallback {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
Object proceedWithObject() throws Throwable;
|
||||
Object proceedWithObject();
|
||||
}
|
||||
|
||||
@@ -54,16 +54,4 @@ public class RequestKey {
|
||||
|
||||
return method.equals(key.method);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer(url.length() + 7);
|
||||
sb.append("[");
|
||||
if (method != null) {
|
||||
sb.append(method).append(",");
|
||||
}
|
||||
sb.append(url);
|
||||
sb.append("]");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ public final class LdapUtils {
|
||||
|
||||
if (url.startsWith("ldap:") || url.startsWith("ldaps:")) {
|
||||
URI uri = parseLdapUrl(url);
|
||||
urlRootDn = uri.getRawPath();
|
||||
urlRootDn = uri.getPath();
|
||||
} else {
|
||||
// Assume it's an embedded server
|
||||
urlRootDn = url;
|
||||
|
||||
+50
-59
@@ -15,21 +15,6 @@
|
||||
|
||||
package org.springframework.security.ldap;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.naming.NamingEnumeration;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.PartialResultException;
|
||||
import javax.naming.directory.Attributes;
|
||||
import javax.naming.directory.DirContext;
|
||||
import javax.naming.directory.SearchControls;
|
||||
import javax.naming.directory.SearchResult;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||
import org.springframework.ldap.core.ContextExecutor;
|
||||
import org.springframework.ldap.core.ContextMapper;
|
||||
@@ -38,18 +23,33 @@ import org.springframework.ldap.core.DirContextAdapter;
|
||||
import org.springframework.ldap.core.DirContextOperations;
|
||||
import org.springframework.ldap.core.DistinguishedName;
|
||||
import org.springframework.ldap.core.LdapEncoder;
|
||||
import org.springframework.ldap.core.LdapTemplate;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import javax.naming.NamingEnumeration;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.directory.Attributes;
|
||||
import javax.naming.directory.DirContext;
|
||||
import javax.naming.directory.SearchControls;
|
||||
import javax.naming.directory.SearchResult;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.Arrays;
|
||||
|
||||
|
||||
/**
|
||||
* Extension of Spring LDAP's LdapTemplate class which adds extra functionality required by Spring Security.
|
||||
* LDAP equivalent of the Spring JdbcTemplate class.
|
||||
* <p>
|
||||
* This is mainly intended to simplify Ldap access within Spring Security's LDAP-related services.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author Luke Taylor
|
||||
* @since 2.0
|
||||
*/
|
||||
public class SpringSecurityLdapTemplate extends LdapTemplate {
|
||||
public class SpringSecurityLdapTemplate extends org.springframework.ldap.core.LdapTemplate {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
private static final Log logger = LogFactory.getLog(SpringSecurityLdapTemplate.class);
|
||||
|
||||
@@ -136,14 +136,14 @@ public class SpringSecurityLdapTemplate extends LdapTemplate {
|
||||
* @return the set of String values for the attribute as a union of the values found in all the matching entries.
|
||||
*/
|
||||
public Set searchForSingleAttributeValues(final String base, final String filter, final Object[] params,
|
||||
final String attributeName) {
|
||||
// Escape the params acording to RFC2254
|
||||
Object[] encodedParams = new String[params.length];
|
||||
|
||||
for (int i=0; i < params.length; i++) {
|
||||
encodedParams[i] = LdapEncoder.filterEncode(params[i].toString());
|
||||
}
|
||||
|
||||
final String attributeName) {
|
||||
// Escape the params acording to RFC2254
|
||||
Object[] encodedParams = new String[params.length];
|
||||
|
||||
for (int i=0; i < params.length; i++) {
|
||||
encodedParams[i] = LdapEncoder.filterEncode(params[i].toString());
|
||||
}
|
||||
|
||||
String formattedFilter = MessageFormat.format(filter, encodedParams);
|
||||
logger.debug("Using filter: " + formattedFilter);
|
||||
|
||||
@@ -175,15 +175,12 @@ public class SpringSecurityLdapTemplate extends LdapTemplate {
|
||||
/**
|
||||
* Performs a search, with the requirement that the search shall return a single directory entry, and uses
|
||||
* the supplied mapper to create the object from that entry.
|
||||
* <p>
|
||||
* Ignores <tt>PartialResultException</tt> if thrown, for compatibility with Active Directory
|
||||
* (see {@link LdapTemplate#setIgnorePartialResultException(boolean)}).
|
||||
*
|
||||
* @param base the search base, relative to the base context supplied by the context source.
|
||||
* @param filter the LDAP search filter
|
||||
* @param params parameters to be substituted in the search.
|
||||
* @param base
|
||||
* @param filter
|
||||
* @param params
|
||||
*
|
||||
* @return a DirContextOperations instance created from the matching entry.
|
||||
* @return the object created by the mapper from the matching entry
|
||||
*
|
||||
* @throws IncorrectResultSizeDataAccessException if no results are found or the search returns more than one
|
||||
* result.
|
||||
@@ -191,38 +188,32 @@ public class SpringSecurityLdapTemplate extends LdapTemplate {
|
||||
public DirContextOperations searchForSingleEntry(final String base, final String filter, final Object[] params) {
|
||||
|
||||
return (DirContextOperations) executeReadOnly(new ContextExecutor() {
|
||||
public Object executeWithContext(DirContext ctx) throws NamingException {
|
||||
DistinguishedName ctxBaseDn = new DistinguishedName(ctx.getNameInNamespace());
|
||||
NamingEnumeration resultsEnum = ctx.search(base, filter, params, searchControls);
|
||||
Set results = new HashSet();
|
||||
try {
|
||||
while (resultsEnum.hasMore()) {
|
||||
public Object executeWithContext(DirContext ctx)
|
||||
throws NamingException {
|
||||
|
||||
SearchResult searchResult = (SearchResult) resultsEnum.next();
|
||||
// Work out the DN of the matched entry
|
||||
StringBuffer dn = new StringBuffer(searchResult.getName());
|
||||
NamingEnumeration results = ctx.search(base, filter, params, searchControls);
|
||||
|
||||
if (base.length() > 0) {
|
||||
dn.append(",");
|
||||
dn.append(base);
|
||||
}
|
||||
|
||||
results.add(new DirContextAdapter(searchResult.getAttributes(),
|
||||
new DistinguishedName(dn.toString()), ctxBaseDn));
|
||||
}
|
||||
} catch (PartialResultException e) {
|
||||
logger.info("Ignoring PartialResultException");
|
||||
}
|
||||
|
||||
if (results.size() == 0) {
|
||||
if (!results.hasMore()) {
|
||||
throw new IncorrectResultSizeDataAccessException(1, 0);
|
||||
}
|
||||
|
||||
if (results.size() > 1) {
|
||||
throw new IncorrectResultSizeDataAccessException(1, results.size());
|
||||
SearchResult searchResult = (SearchResult) results.next();
|
||||
|
||||
if (results.hasMore()) {
|
||||
// We don't know how many results but set to 2 which is good enough
|
||||
throw new IncorrectResultSizeDataAccessException(1, 2);
|
||||
}
|
||||
|
||||
return results.toArray()[0];
|
||||
// Work out the DN of the matched entry
|
||||
StringBuffer dn = new StringBuffer(searchResult.getName());
|
||||
|
||||
if (base.length() > 0) {
|
||||
dn.append(",");
|
||||
dn.append(base);
|
||||
}
|
||||
|
||||
return new DirContextAdapter(searchResult.getAttributes(),
|
||||
new DistinguishedName(dn.toString()), new DistinguishedName(ctx.getNameInNamespace()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+18
-5
@@ -99,6 +99,8 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
|
||||
*/
|
||||
private GrantedAuthority defaultRole;
|
||||
|
||||
private ContextSource contextSource;
|
||||
|
||||
private SpringSecurityLdapTemplate ldapTemplate;
|
||||
|
||||
/**
|
||||
@@ -141,10 +143,8 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
|
||||
* context factory.
|
||||
*/
|
||||
public DefaultLdapAuthoritiesPopulator(ContextSource contextSource, String groupSearchBase) {
|
||||
Assert.notNull(contextSource, "contextSource must not be null");
|
||||
ldapTemplate = new SpringSecurityLdapTemplate(contextSource);
|
||||
ldapTemplate.setSearchControls(searchControls);
|
||||
setGroupSearchBase(groupSearchBase);
|
||||
this.setContextSource(contextSource);
|
||||
this.setGroupSearchBase(groupSearchBase);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
@@ -226,7 +226,20 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
|
||||
}
|
||||
|
||||
protected ContextSource getContextSource() {
|
||||
return ldapTemplate.getContextSource();
|
||||
return contextSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link ContextSource}
|
||||
*
|
||||
* @param contextSource supplies the contexts used to search for user roles.
|
||||
*/
|
||||
private void setContextSource(ContextSource contextSource) {
|
||||
Assert.notNull(contextSource, "contextSource must not be null");
|
||||
this.contextSource = contextSource;
|
||||
|
||||
ldapTemplate = new SpringSecurityLdapTemplate(contextSource);
|
||||
ldapTemplate.setSearchControls(searchControls);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -144,10 +144,17 @@ public class ProviderManager extends AbstractAuthenticationManager implements In
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
checkIfValidList(this.providers);
|
||||
Assert.notNull(this.messages, "A message source must be set");
|
||||
exceptionMappings.putAll(additionalExceptionMappings);
|
||||
}
|
||||
|
||||
private void checkIfValidList(List listToCheck) {
|
||||
if ((listToCheck == null) || (listToCheck.size() == 0)) {
|
||||
throw new IllegalArgumentException("A list of AuthenticationProviders is required");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to authenticate the passed {@link Authentication} object.
|
||||
* <p>
|
||||
@@ -167,7 +174,7 @@ public class ProviderManager extends AbstractAuthenticationManager implements In
|
||||
* @throws AuthenticationException if authentication fails.
|
||||
*/
|
||||
public Authentication doAuthentication(Authentication authentication) throws AuthenticationException {
|
||||
Iterator iter = getProviders().iterator();
|
||||
Iterator iter = providers.iterator();
|
||||
|
||||
Class toTest = authentication.getClass();
|
||||
|
||||
@@ -266,11 +273,7 @@ public class ProviderManager extends AbstractAuthenticationManager implements In
|
||||
}
|
||||
|
||||
public List getProviders() {
|
||||
if (providers == null || providers.size() == 0) {
|
||||
throw new IllegalArgumentException("A list of AuthenticationProviders is required");
|
||||
}
|
||||
|
||||
return providers;
|
||||
return this.providers;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -300,7 +303,8 @@ public class ProviderManager extends AbstractAuthenticationManager implements In
|
||||
* AuthenticationProvider instance.
|
||||
*/
|
||||
public void setProviders(List providers) {
|
||||
Assert.notEmpty(providers, "A list of AuthenticationProviders is required");
|
||||
checkIfValidList(providers);
|
||||
|
||||
Iterator iter = providers.iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
|
||||
-12
@@ -16,7 +16,6 @@
|
||||
package org.springframework.security.providers;
|
||||
|
||||
import org.springframework.security.GrantedAuthority;
|
||||
import org.springframework.security.util.AuthorityUtils;
|
||||
|
||||
|
||||
/**
|
||||
@@ -35,17 +34,6 @@ public class TestingAuthenticationToken extends AbstractAuthenticationToken {
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public TestingAuthenticationToken(Object principal, Object credentials) {
|
||||
super(null);
|
||||
this.principal = principal;
|
||||
this.credentials = credentials;
|
||||
}
|
||||
|
||||
|
||||
public TestingAuthenticationToken(Object principal, Object credentials, String... authorities) {
|
||||
this(principal, credentials, AuthorityUtils.stringArrayToAuthorityArray(authorities));
|
||||
}
|
||||
|
||||
public TestingAuthenticationToken(Object principal, Object credentials, GrantedAuthority[] authorities) {
|
||||
super(authorities);
|
||||
this.principal = principal;
|
||||
+15
-13
@@ -15,28 +15,30 @@
|
||||
|
||||
package org.springframework.security.providers.anonymous;
|
||||
|
||||
import org.springframework.security.SpringSecurityMessageSource;
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.AuthenticationException;
|
||||
import org.springframework.security.BadCredentialsException;
|
||||
import org.springframework.security.providers.AuthenticationProvider;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.MessageSourceAware;
|
||||
import org.springframework.context.support.MessageSourceAccessor;
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.AuthenticationException;
|
||||
import org.springframework.security.BadCredentialsException;
|
||||
import org.springframework.security.SpringSecurityMessageSource;
|
||||
import org.springframework.security.providers.AuthenticationProvider;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* An {@link AuthenticationProvider} implementation that validates {@link AnonymousAuthenticationToken}s.
|
||||
* <p>
|
||||
* To be successfully validated, the {@link AnonymousAuthenticationToken#getKeyHash()} must match this class'
|
||||
* {@link #getKey()}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
* An {@link AuthenticationProvider} implementation that validates {@link
|
||||
* org.springframework.security.providers.anonymous.AnonymousAuthenticationToken}s.<p>To be successfully validated, the
|
||||
* {@link org.springframework.security.providers.anonymous.AnonymousAuthenticationToken#getKeyHash()} must match this class'
|
||||
* {@link #getKey()}.</p>
|
||||
*/
|
||||
public class AnonymousAuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
private static final Log logger = LogFactory.getLog(AnonymousAuthenticationProvider.class);
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
@@ -45,7 +47,7 @@ public class AnonymousAuthenticationProvider implements AuthenticationProvider,
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.hasLength(key, "A Key is required");
|
||||
Assert.notNull(this.messages, "A message source must be set");
|
||||
}
|
||||
|
||||
+2
-7
@@ -158,7 +158,7 @@ public class JaasAuthenticationProvider implements AuthenticationProvider, Appli
|
||||
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 "
|
||||
@@ -246,9 +246,6 @@ public class JaasAuthenticationProvider implements AuthenticationProvider, Appli
|
||||
*/
|
||||
protected void configureJaas(Resource loginConfig) throws IOException {
|
||||
configureJaasUsingLoop();
|
||||
|
||||
// Overcome issue in SEC-760
|
||||
Configuration.getConfiguration().refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -378,9 +375,7 @@ public class JaasAuthenticationProvider implements AuthenticationProvider, Appli
|
||||
* @param token The {@link UsernamePasswordAuthenticationToken} being processed
|
||||
*/
|
||||
protected void publishSuccessEvent(UsernamePasswordAuthenticationToken token) {
|
||||
if (applicationEventPublisher != null) {
|
||||
applicationEventPublisher.publishEvent(new JaasAuthenticationSuccessEvent(token));
|
||||
}
|
||||
applicationEventPublisher.publishEvent(new JaasAuthenticationSuccessEvent(token));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-10
@@ -88,6 +88,7 @@ public class PreAuthenticatedAuthenticationProvider implements AuthenticationPro
|
||||
result.setDetails(authentication.getDetails());
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,14 +123,4 @@ public class PreAuthenticatedAuthenticationProvider implements AuthenticationPro
|
||||
public void setThrowExceptionWhenTokenRejected(boolean throwExceptionWhenTokenRejected) {
|
||||
this.throwExceptionWhenTokenRejected = throwExceptionWhenTokenRejected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the strategy which will be used to validate the loaded <tt>UserDetails</tt> object
|
||||
* for the user. Defaults to an {@link AccountStatusUserDetailsChecker}.
|
||||
* @param userDetailsChecker
|
||||
*/
|
||||
public void setUserDetailsChecker(UserDetailsChecker userDetailsChecker) {
|
||||
Assert.notNull(userDetailsChecker, "userDetailsChacker cannot be null");
|
||||
this.userDetailsChecker = userDetailsChecker;
|
||||
}
|
||||
}
|
||||
|
||||
+3
-5
@@ -45,7 +45,7 @@ import java.security.cert.X509Certificate;
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @deprecated superceded by the preauth provider. Use the X.509 authentication support in org.springframework.security.ui.preauth.x509 instead
|
||||
* or namespace support via the <x509 /> element.
|
||||
* or namespace support via the <x509 /> element.
|
||||
* @version $Id$
|
||||
*/
|
||||
public class X509AuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware {
|
||||
@@ -61,7 +61,7 @@ public class X509AuthenticationProvider implements AuthenticationProvider, Initi
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(userCache, "An x509UserCache must be set");
|
||||
Assert.notNull(x509AuthoritiesPopulator, "An X509AuthoritiesPopulator must be set");
|
||||
Assert.notNull(this.messages, "A message source must be set");
|
||||
@@ -101,9 +101,7 @@ public class X509AuthenticationProvider implements AuthenticationProvider, Initi
|
||||
UserDetails user = userCache.getUserFromCache(clientCertificate);
|
||||
|
||||
if (user == null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Authenticating with certificate " + clientCertificate);
|
||||
}
|
||||
logger.debug("Authenticating with certificate " + clientCertificate);
|
||||
user = x509AuthoritiesPopulator.getUserDetails(clientCertificate);
|
||||
userCache.putUserInCache(clientCertificate, user);
|
||||
}
|
||||
|
||||
@@ -147,11 +147,7 @@ public abstract class AbstractProcessingFilter extends SpringSecurityFilter impl
|
||||
|
||||
private Properties exceptionMappings = new Properties();
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
private TargetUrlResolver targetUrlResolver = new TargetUrlResolverImpl();
|
||||
|
||||
@@ -222,13 +218,11 @@ public abstract class AbstractProcessingFilter extends SpringSecurityFilter impl
|
||||
Assert.isTrue(UrlUtils.isValidRedirectUrl(filterProcessesUrl), filterProcessesUrl + " isn't a valid redirect URL");
|
||||
Assert.hasLength(defaultTargetUrl, "defaultTargetUrl must be specified");
|
||||
Assert.isTrue(UrlUtils.isValidRedirectUrl(defaultTargetUrl), defaultTargetUrl + " isn't a valid redirect URL");
|
||||
// Assert.hasLength(authenticationFailureUrl, "authenticationFailureUrl must be specified");
|
||||
Assert.isTrue(UrlUtils.isValidRedirectUrl(authenticationFailureUrl), authenticationFailureUrl + " isn't a valid redirect URL");
|
||||
Assert.notNull(authenticationManager, "authenticationManager must be specified");
|
||||
Assert.notNull(rememberMeServices, "rememberMeServices cannot be null");
|
||||
Assert.notNull(targetUrlResolver, "targetUrlResolver cannot be null");
|
||||
|
||||
if (rememberMeServices == null) {
|
||||
rememberMeServices = new NullRememberMeServices();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@ public class AuthenticationDetailsSourceImpl implements AuthenticationDetailsSou
|
||||
Constructor constructor = null;
|
||||
for (int i = 0; i < constructors.length; i++) {
|
||||
Class[] parameterTypes = constructors[i].getParameterTypes();
|
||||
if (parameterTypes.length == 1 && (object == null || parameterTypes[0].isInstance(object))) {
|
||||
if (parameterTypes.length == 1 && (object == null || parameterTypes[i].isInstance(object))) {
|
||||
constructor = constructors[i];
|
||||
break;
|
||||
}
|
||||
|
||||
+14
-24
@@ -35,7 +35,6 @@ import org.springframework.security.ui.WebAuthenticationDetailsSource;
|
||||
import org.springframework.security.ui.AuthenticationEntryPoint;
|
||||
import org.springframework.security.ui.FilterChainOrder;
|
||||
import org.springframework.security.ui.SpringSecurityFilter;
|
||||
import org.springframework.security.ui.rememberme.NullRememberMeServices;
|
||||
import org.springframework.security.ui.rememberme.RememberMeServices;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -92,7 +91,7 @@ public class BasicProcessingFilter extends SpringSecurityFilter implements Initi
|
||||
private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource();
|
||||
private AuthenticationEntryPoint authenticationEntryPoint;
|
||||
private AuthenticationManager authenticationManager;
|
||||
private RememberMeServices rememberMeServices = new NullRememberMeServices();
|
||||
private RememberMeServices rememberMeServices;
|
||||
private boolean ignoreFailure = false;
|
||||
private String credentialsCharset = "UTF-8";
|
||||
|
||||
@@ -106,10 +105,10 @@ public class BasicProcessingFilter extends SpringSecurityFilter implements Initi
|
||||
}
|
||||
}
|
||||
|
||||
public void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
|
||||
public void doFilterHttp(HttpServletRequest httpRequest, HttpServletResponse httpResponse, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
|
||||
String header = request.getHeader("Authorization");
|
||||
String header = httpRequest.getHeader("Authorization");
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Authorization header: " + header);
|
||||
@@ -117,7 +116,7 @@ public class BasicProcessingFilter extends SpringSecurityFilter implements Initi
|
||||
|
||||
if ((header != null) && header.startsWith("Basic ")) {
|
||||
byte[] base64Token = header.substring(6).getBytes("UTF-8");
|
||||
String token = new String(Base64.decodeBase64(base64Token), getCredentialsCharset(request));
|
||||
String token = new String(Base64.decodeBase64(base64Token), getCredentialsCharset(httpRequest));
|
||||
|
||||
String username = "";
|
||||
String password = "";
|
||||
@@ -131,7 +130,7 @@ public class BasicProcessingFilter extends SpringSecurityFilter implements Initi
|
||||
if (authenticationIsRequired(username)) {
|
||||
UsernamePasswordAuthenticationToken authRequest =
|
||||
new UsernamePasswordAuthenticationToken(username, password);
|
||||
authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
|
||||
authRequest.setDetails(authenticationDetailsSource.buildDetails(httpRequest));
|
||||
|
||||
Authentication authResult;
|
||||
|
||||
@@ -145,14 +144,14 @@ public class BasicProcessingFilter extends SpringSecurityFilter implements Initi
|
||||
|
||||
SecurityContextHolder.getContext().setAuthentication(null);
|
||||
|
||||
rememberMeServices.loginFail(request, response);
|
||||
if (rememberMeServices != null) {
|
||||
rememberMeServices.loginFail(httpRequest, httpResponse);
|
||||
}
|
||||
|
||||
onUnsuccessfulAuthentication(request, response, failed);
|
||||
|
||||
if (ignoreFailure) {
|
||||
chain.doFilter(request, response);
|
||||
chain.doFilter(httpRequest, httpResponse);
|
||||
} else {
|
||||
authenticationEntryPoint.commence(request, response, failed);
|
||||
authenticationEntryPoint.commence(httpRequest, httpResponse, failed);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -165,13 +164,13 @@ public class BasicProcessingFilter extends SpringSecurityFilter implements Initi
|
||||
|
||||
SecurityContextHolder.getContext().setAuthentication(authResult);
|
||||
|
||||
rememberMeServices.loginSuccess(request, response, authResult);
|
||||
|
||||
onSuccessfulAuthentication(request, response, authResult);
|
||||
if (rememberMeServices != null) {
|
||||
rememberMeServices.loginSuccess(httpRequest, httpResponse, authResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
chain.doFilter(request, response);
|
||||
chain.doFilter(httpRequest, httpResponse);
|
||||
}
|
||||
|
||||
private boolean authenticationIsRequired(String username) {
|
||||
@@ -203,14 +202,6 @@ public class BasicProcessingFilter extends SpringSecurityFilter implements Initi
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void onSuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication authResult) throws IOException {
|
||||
}
|
||||
|
||||
protected void onUnsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
|
||||
AuthenticationException failed) throws IOException {
|
||||
}
|
||||
|
||||
protected AuthenticationEntryPoint getAuthenticationEntryPoint() {
|
||||
return authenticationEntryPoint;
|
||||
@@ -242,7 +233,6 @@ public class BasicProcessingFilter extends SpringSecurityFilter implements Initi
|
||||
}
|
||||
|
||||
public void setRememberMeServices(RememberMeServices rememberMeServices) {
|
||||
Assert.notNull(rememberMeServices, "rememberMeServices cannot be null");
|
||||
this.rememberMeServices = rememberMeServices;
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -34,10 +34,10 @@ import javax.servlet.http.HttpSession;
|
||||
* @version $Id$
|
||||
*/
|
||||
public class SecurityContextLogoutHandler implements LogoutHandler {
|
||||
private boolean invalidateHttpSession = true;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
private boolean invalidateHttpSession = true;
|
||||
|
||||
/**
|
||||
* Requires the request to be passed in.
|
||||
*
|
||||
@@ -69,6 +69,6 @@ public class SecurityContextLogoutHandler implements LogoutHandler {
|
||||
*/
|
||||
public void setInvalidateHttpSession(boolean invalidateHttpSession) {
|
||||
this.invalidateHttpSession = invalidateHttpSession;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-24
@@ -25,13 +25,6 @@ import org.springframework.util.Assert;
|
||||
/**
|
||||
* Base class for processing filters that handle pre-authenticated authentication requests. Subclasses must implement
|
||||
* the getPreAuthenticatedPrincipal() and getPreAuthenticatedCredentials() methods.
|
||||
* <p>
|
||||
* By default, the filter chain will proceed when an authentication attempt fails in order to allow other
|
||||
* authentication mechanisms to process the request. To reject the credentials immediately, set the
|
||||
* <tt>continueFilterChainOnUnsuccessfulAuthentication</tt> flag to false. The exception raised by the
|
||||
* <tt>AuthenticationManager</tt> will the be re-thrown. Note that this will not affect cases where the principal
|
||||
* returned by {@link #getPreAuthenticatedPrincipal} is null, when the chain will still proceed as normal.
|
||||
*
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @author Ruud Senden
|
||||
@@ -45,8 +38,6 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends SpringSec
|
||||
private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource();
|
||||
|
||||
private AuthenticationManager authenticationManager = null;
|
||||
|
||||
private boolean continueFilterChainOnUnsuccessfulAuthentication = true;
|
||||
|
||||
/**
|
||||
* Check whether all required properties have been set.
|
||||
@@ -97,10 +88,6 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends SpringSec
|
||||
successfulAuthentication(request, response, authResult);
|
||||
} catch (AuthenticationException failed) {
|
||||
unsuccessfulAuthentication(request, response, failed);
|
||||
|
||||
if (!continueFilterChainOnUnsuccessfulAuthentication) {
|
||||
throw failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,19 +143,8 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends SpringSec
|
||||
public void setAuthenticationManager(AuthenticationManager authenticationManager) {
|
||||
this.authenticationManager = authenticationManager;
|
||||
}
|
||||
|
||||
public void setContinueFilterChainOnUnsuccessfulAuthentication(boolean shouldContinue) {
|
||||
continueFilterChainOnUnsuccessfulAuthentication = shouldContinue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override to extract the principal information from the current request
|
||||
*/
|
||||
protected abstract Object getPreAuthenticatedPrincipal(HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* Override to extract the credentials (if applicable) from the current request. Some implementations
|
||||
* may return a dummy value.
|
||||
*/
|
||||
protected abstract Object getPreAuthenticatedCredentials(HttpServletRequest request);
|
||||
}
|
||||
|
||||
+17
-21
@@ -32,14 +32,14 @@ import javax.servlet.http.HttpServletResponse;
|
||||
* @since 2.0
|
||||
*/
|
||||
public abstract class AbstractRememberMeServices implements RememberMeServices, InitializingBean, LogoutHandler {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
public static final String SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY = "SPRING_SECURITY_REMEMBER_ME_COOKIE";
|
||||
public static final String DEFAULT_PARAMETER = "_spring_security_remember_me";
|
||||
|
||||
private static final String DELIMITER = ":";
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
//~ Instance fields ================================================================================================
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
|
||||
@@ -49,7 +49,7 @@ public abstract class AbstractRememberMeServices implements RememberMeServices,
|
||||
private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource();
|
||||
|
||||
private String cookieName = SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY;
|
||||
private String parameter = DEFAULT_PARAMETER;
|
||||
private String parameter = DEFAULT_PARAMETER;
|
||||
private boolean alwaysRemember;
|
||||
private String key;
|
||||
private int tokenValiditySeconds = 1209600; // 14 days
|
||||
@@ -232,14 +232,14 @@ public abstract class AbstractRememberMeServices implements RememberMeServices,
|
||||
}
|
||||
|
||||
String paramValue = request.getParameter(parameter);
|
||||
|
||||
|
||||
if (paramValue != null) {
|
||||
if (paramValue.equalsIgnoreCase("true") || paramValue.equalsIgnoreCase("on") ||
|
||||
paramValue.equalsIgnoreCase("yes") || paramValue.equals("1")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (paramValue.equalsIgnoreCase("true") || paramValue.equalsIgnoreCase("on") ||
|
||||
paramValue.equalsIgnoreCase("yes") || paramValue.equals("1")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Did not send remember-me cookie (principal did not set parameter '" + parameter + "')");
|
||||
}
|
||||
@@ -309,10 +309,6 @@ public abstract class AbstractRememberMeServices implements RememberMeServices,
|
||||
this.cookieName = cookieName;
|
||||
}
|
||||
|
||||
protected String getCookieName() {
|
||||
return cookieName;
|
||||
}
|
||||
|
||||
public void setAlwaysRemember(boolean alwaysRemember) {
|
||||
this.alwaysRemember = alwaysRemember;
|
||||
}
|
||||
@@ -320,11 +316,11 @@ public abstract class AbstractRememberMeServices implements RememberMeServices,
|
||||
/**
|
||||
* Sets the name of the parameter which should be checked for to see if a remember-me has been requested
|
||||
* during a login request. This should be the same name you assign to the checkbox in your login form.
|
||||
*
|
||||
*
|
||||
* @param parameter the HTTP request parameter
|
||||
*/
|
||||
public void setParameter(String parameter) {
|
||||
Assert.hasText(parameter, "Parameter name cannot be null");
|
||||
Assert.hasText(parameter, "Parameter name cannot be null");
|
||||
this.parameter = parameter;
|
||||
}
|
||||
|
||||
@@ -337,7 +333,7 @@ public abstract class AbstractRememberMeServices implements RememberMeServices,
|
||||
}
|
||||
|
||||
public void setUserDetailsService(UserDetailsService userDetailsService) {
|
||||
Assert.notNull(userDetailsService, "UserDetailsService canot be null");
|
||||
Assert.notNull(userDetailsService, "UserDetailsService canot be null");
|
||||
this.userDetailsService = userDetailsService;
|
||||
}
|
||||
|
||||
@@ -361,8 +357,8 @@ public abstract class AbstractRememberMeServices implements RememberMeServices,
|
||||
return authenticationDetailsSource;
|
||||
}
|
||||
|
||||
public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) {
|
||||
Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource cannot be null");
|
||||
this.authenticationDetailsSource = authenticationDetailsSource;
|
||||
}
|
||||
public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) {
|
||||
Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource cannot be null");
|
||||
this.authenticationDetailsSource = authenticationDetailsSource;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -304,7 +304,8 @@ public class SwitchUserProcessingFilter extends SpringSecurityFilter implements
|
||||
logger.debug("Switch User failed", failed);
|
||||
|
||||
if (switchFailureUrl != null) {
|
||||
sendRedirect(request, response, switchFailureUrl);
|
||||
switchFailureUrl = request.getContextPath() + switchFailureUrl;
|
||||
response.sendRedirect(response.encodeRedirectURL(switchFailureUrl));
|
||||
} else {
|
||||
response.getWriter().print("Switch user failed: " + failed.getMessage());
|
||||
response.flushBuffer();
|
||||
|
||||
-2
@@ -25,8 +25,6 @@ import org.springframework.dao.DataAccessException;
|
||||
* instead of only the directly assigned authorities.
|
||||
*
|
||||
* @author Michael Mayr
|
||||
* @deprecated use a {@link RoleHierarchyVoter} instead of populating the user Authentication object
|
||||
* with the additional authorities.
|
||||
*/
|
||||
public class UserDetailsServiceWrapper implements UserDetailsService {
|
||||
|
||||
|
||||
-1
@@ -23,7 +23,6 @@ import org.springframework.security.userdetails.UserDetails;
|
||||
* delegated to the <tt>UserDetails</tt> implementation.
|
||||
*
|
||||
* @author Michael Mayr
|
||||
* @deprecated use a {@link RoleHierarchyVoter} instead.
|
||||
*/
|
||||
public class UserDetailsWrapper implements UserDetails {
|
||||
|
||||
|
||||
@@ -47,53 +47,23 @@ import javax.sql.DataSource;
|
||||
|
||||
|
||||
/**
|
||||
* <tt>UserDetailsServiceRetrieves</tt> implementation which retrieves the user details
|
||||
* (username, password, enabled flag, and authorities) from a database using JDBC queries.
|
||||
*
|
||||
* <h3>Default Schema</h3>
|
||||
* A default database schema is assumed, with two tables "users" and "authorities".
|
||||
*
|
||||
* <h4>The Users table</h4>
|
||||
*
|
||||
* This table contains the login name, password and enabled status of the user.
|
||||
*
|
||||
* <table>
|
||||
* <tr><th>Column</th></tr>
|
||||
* <tr><td>username</td></tr>
|
||||
* <tr><td>password</td></tr>
|
||||
* <tr><td>enabled</td></tr>
|
||||
* </table>
|
||||
*
|
||||
* <h4>The Authorities Table</h4>
|
||||
*
|
||||
* <table>
|
||||
* <tr><th>Column</th></tr>
|
||||
* <tr><td>username</td></tr>
|
||||
* <tr><td>authority</td></tr>
|
||||
* </table>
|
||||
*
|
||||
* If you are using an existing schema you will have to set the queries <tt>usersByUsernameQuery</tt> and
|
||||
* <tt>authoritiesByUsernameQuery</tt> to match your database setup
|
||||
* (see {@link #DEF_USERS_BY_USERNAME_QUERY} and {@link #DEF_AUTHORITIES_BY_USERNAME_QUERY}).
|
||||
*
|
||||
* Retrieves user details (username, password, enabled flag, and authorities) from a JDBC location.
|
||||
* <p>
|
||||
* In order to minimise backward compatibility issues, this implementation doesn't recognise the expiration of user
|
||||
* A default database structure is assumed, (see {@link #DEF_USERS_BY_USERNAME_QUERY} and {@link
|
||||
* #DEF_AUTHORITIES_BY_USERNAME_QUERY}, which most users of this class will need to override, if using an existing
|
||||
* scheme. This may be done by setting the default query strings used.
|
||||
* <p>
|
||||
* In order to minimise backward compatibility issues, this DAO does not recognise the expiration of user
|
||||
* accounts or the expiration of user credentials. However, it does recognise and honour the user enabled/disabled
|
||||
* column. This should map to a <tt>boolean</tt> type in the result set (the SQL type will depend on the
|
||||
* database you are using). All the other columns map to <tt>String</tt>s.
|
||||
*
|
||||
* <h3>Group Support</h3>
|
||||
* column.
|
||||
* <p>
|
||||
* Support for group-based authorities can be enabled by setting the <tt>enableGroups</tt> property to <tt>true</tt>
|
||||
* (you may also then wish to set <tt>enableAuthorities</tt> to <tt>false</tt> to disable loading of authorities
|
||||
* directly). With this approach, authorities are allocated to groups and a user's authorities are determined based
|
||||
* on the groups they are a member of. The net result is the same (a UserDetails containing a set of
|
||||
* <tt>GrantedAuthority</tt>s is loaded), but the different persistence strategy may be more suitable for the
|
||||
* administration of some applications.
|
||||
* <p>
|
||||
* When groups are being used, the tables "groups", "group_members" and "group_authorities" are used. See
|
||||
* {@link #DEF_GROUP_AUTHORITIES_BY_USERNAME_QUERY} for the default query which is used to load the group authorities.
|
||||
* Again you can customize this by setting the <tt>groupAuthoritiesByUsernameQuery</tt> property, but the format of
|
||||
* the rows returned should match the default.
|
||||
*
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author colin sampaleanu
|
||||
|
||||
+1
-1
@@ -184,7 +184,7 @@ public class LdapUserDetailsManager implements UserDetailsManager {
|
||||
public Object executeWithContext(DirContext dirCtx) throws NamingException {
|
||||
LdapContext ctx = (LdapContext) dirCtx;
|
||||
ctx.removeFromEnvironment("com.sun.jndi.ldap.connect.pool");
|
||||
ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, LdapUtils.getFullDn(dn, ctx).toString());
|
||||
ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, LdapUtils.getFullDn(dn, ctx).toUrl());
|
||||
ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, oldPassword);
|
||||
// TODO: reconnect doesn't appear to actually change the credentials
|
||||
try {
|
||||
|
||||
@@ -107,7 +107,6 @@ public class FilterChainProxy implements Filter, InitializingBean, ApplicationCo
|
||||
/** Compiled pattern version of the filter chain map */
|
||||
private Map filterChainMap;
|
||||
private UrlMatcher matcher = new AntUrlPathMatcher();
|
||||
private boolean stripQueryStringFromUrls = true;
|
||||
private DefaultFilterInvocationDefinitionSource fids;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
@@ -117,8 +116,8 @@ public class FilterChainProxy implements Filter, InitializingBean, ApplicationCo
|
||||
if (fids != null) {
|
||||
Assert.isNull(uncompiledFilterChainMap, "Set the filterChainMap or FilterInvocationDefinitionSource but not both");
|
||||
FIDSToFilterChainMapConverter converter = new FIDSToFilterChainMapConverter(fids, applicationContext);
|
||||
setMatcher(converter.getMatcher());
|
||||
setFilterChainMap(converter.getFilterChainMap());
|
||||
setMatcher(converter.getMatcher());
|
||||
setFilterChainMap(converter.getFilterChainMap());
|
||||
fids = null;
|
||||
}
|
||||
|
||||
@@ -182,16 +181,6 @@ public class FilterChainProxy implements Filter, InitializingBean, ApplicationCo
|
||||
* @return an ordered array of Filters defining the filter chain
|
||||
*/
|
||||
public List getFilters(String url) {
|
||||
if (stripQueryStringFromUrls) {
|
||||
// String query string - see SEC-953
|
||||
int firstQuestionMarkIndex = url.indexOf("?");
|
||||
|
||||
if (firstQuestionMarkIndex != -1) {
|
||||
url = url.substring(0, firstQuestionMarkIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Iterator filterChains = filterChainMap.entrySet().iterator();
|
||||
|
||||
while (filterChains.hasNext()) {
|
||||
@@ -330,14 +319,6 @@ public class FilterChainProxy implements Filter, InitializingBean, ApplicationCo
|
||||
return matcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public void setStripQueryStringFromUrls(boolean stripQueryStringFromUrls) {
|
||||
this.stripQueryStringFromUrls = stripQueryStringFromUrls;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append("FilterChainProxy[");
|
||||
|
||||
@@ -2,22 +2,18 @@ package org.springframework.security.util;
|
||||
|
||||
/**
|
||||
* Utilities for working with Strings and text.
|
||||
*
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
*/
|
||||
public abstract class TextUtils {
|
||||
|
||||
public static String escapeEntities(String s) {
|
||||
if (s == null || s.length() == 0) {
|
||||
return s;
|
||||
}
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
|
||||
for (int i=0; i < s.length(); i++) {
|
||||
char c = s.charAt(i);
|
||||
|
||||
|
||||
if(c == '<') {
|
||||
sb.append("<");
|
||||
} else if (c == '>') {
|
||||
@@ -26,14 +22,12 @@ public abstract class TextUtils {
|
||||
sb.append(""");
|
||||
} else if (c == '\'') {
|
||||
sb.append("'");
|
||||
} else if (c == '&') {
|
||||
sb.append("&");
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
package org.springframework.security.vote;
|
||||
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.GrantedAuthority;
|
||||
import org.springframework.security.userdetails.hierarchicalroles.RoleHierarchy;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Extended RoleVoter which uses a {@link RoleHierarchy} definition to determine the
|
||||
* roles allocated to the current user before voting.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @since 2.0.4
|
||||
*/
|
||||
public class RoleHierarchyVoter extends RoleVoter {
|
||||
private RoleHierarchy roleHierarchy = null;
|
||||
|
||||
public RoleHierarchyVoter(RoleHierarchy roleHierarchy) {
|
||||
Assert.notNull(roleHierarchy, "RoleHierarchy must not be null");
|
||||
this.roleHierarchy = roleHierarchy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the <tt>RoleHierarchy</tt> to obtain the complete set of user authorities.
|
||||
*/
|
||||
GrantedAuthority[] extractAuthorities(Authentication authentication) {
|
||||
return roleHierarchy.getReachableGrantedAuthorities(authentication.getAuthorities());
|
||||
}
|
||||
}
|
||||
@@ -95,7 +95,6 @@ public class RoleVoter implements AccessDecisionVoter {
|
||||
public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) {
|
||||
int result = ACCESS_ABSTAIN;
|
||||
Iterator iter = config.getConfigAttributes().iterator();
|
||||
GrantedAuthority[] authorities = extractAuthorities(authentication);
|
||||
|
||||
while (iter.hasNext()) {
|
||||
ConfigAttribute attribute = (ConfigAttribute) iter.next();
|
||||
@@ -103,6 +102,7 @@ public class RoleVoter implements AccessDecisionVoter {
|
||||
if (this.supports(attribute)) {
|
||||
result = ACCESS_DENIED;
|
||||
|
||||
GrantedAuthority[] authorities = authentication.getAuthorities();
|
||||
// Attempt to find a matching granted authority
|
||||
for (int i = 0; i < authorities.length; i++) {
|
||||
if (attribute.getAttribute().equals(authorities[i].getAuthority())) {
|
||||
@@ -114,8 +114,4 @@ public class RoleVoter implements AccessDecisionVoter {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
GrantedAuthority[] extractAuthorities(Authentication authentication) {
|
||||
return authentication.getAuthorities();
|
||||
}
|
||||
}
|
||||
|
||||
+36
-42
@@ -31,12 +31,10 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
@@ -276,62 +274,58 @@ public class SavedRequestAwareWrapper extends SecurityContextHolderAwareRequestW
|
||||
}
|
||||
|
||||
public Map getParameterMap() {
|
||||
Map parameters = super.getParameterMap();
|
||||
|
||||
if (savedRequest == null) {
|
||||
return super.getParameterMap();
|
||||
return parameters;
|
||||
}
|
||||
|
||||
Set names = getCombinedParameterNames();
|
||||
Iterator nameIter = names.iterator();
|
||||
Map parameterMap = new HashMap(names.size());
|
||||
// We have a saved request so merge the values, with the wrapped request taking precedence (see getParameter())
|
||||
Map newParameters = new HashMap(savedRequest.getParameterMap().size() + parameters.size());
|
||||
newParameters.putAll(parameters);
|
||||
|
||||
while (nameIter.hasNext()) {
|
||||
String name = (String) nameIter.next();
|
||||
parameterMap.put(name, getParameterValues(name));
|
||||
Iterator savedParams = savedRequest.getParameterMap().entrySet().iterator();
|
||||
|
||||
while (savedParams.hasNext()) {
|
||||
Map.Entry entry = (Entry) savedParams.next();
|
||||
String name = (String) entry.getKey();
|
||||
String[] savedParamValues = (String[]) entry.getValue();
|
||||
|
||||
if (newParameters.containsKey(name)) {
|
||||
// merge values
|
||||
String[] existingValues = (String[]) newParameters.get(name);
|
||||
String[] mergedValues = new String[savedParamValues.length + existingValues.length];
|
||||
System.arraycopy(existingValues, 0, mergedValues, 0, existingValues.length);
|
||||
System.arraycopy(savedParamValues, 0, mergedValues, existingValues.length, savedParamValues.length);
|
||||
newParameters.put(name, mergedValues);
|
||||
} else {
|
||||
newParameters.put(name, savedParamValues);
|
||||
}
|
||||
}
|
||||
|
||||
return parameterMap;
|
||||
}
|
||||
|
||||
private Set getCombinedParameterNames() {
|
||||
Set names = new HashSet();
|
||||
names.addAll(super.getParameterMap().keySet());
|
||||
|
||||
if (savedRequest != null) {
|
||||
names.addAll(savedRequest.getParameterMap().keySet());
|
||||
}
|
||||
|
||||
return names;
|
||||
|
||||
return newParameters;
|
||||
}
|
||||
|
||||
public Enumeration getParameterNames() {
|
||||
return new Enumerator(getCombinedParameterNames());
|
||||
return new Enumerator(getParameterMap().keySet());
|
||||
}
|
||||
|
||||
public String[] getParameterValues(String name) {
|
||||
if (savedRequest == null) {
|
||||
return super.getParameterValues(name);
|
||||
}
|
||||
|
||||
String[] savedRequestParams = savedRequest.getParameterValues(name);
|
||||
String[] savedRequestParams = savedRequest == null ? null : savedRequest.getParameterValues(name);
|
||||
String[] wrappedRequestParams = super.getParameterValues(name);
|
||||
|
||||
if (savedRequestParams == null) {
|
||||
return wrappedRequestParams;
|
||||
}
|
||||
|
||||
if (wrappedRequestParams == null) {
|
||||
return savedRequestParams;
|
||||
if (savedRequestParams == null && wrappedRequestParams == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// We have params in both saved and wrapped requests so have to merge them
|
||||
List wrappedParamsList = Arrays.asList(wrappedRequestParams);
|
||||
List combinedParams = new ArrayList(wrappedParamsList);
|
||||
List combinedParams = new ArrayList();
|
||||
|
||||
// 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]);
|
||||
}
|
||||
if (wrappedRequestParams != null) {
|
||||
combinedParams.addAll(Arrays.asList(wrappedRequestParams));
|
||||
}
|
||||
|
||||
if (savedRequestParams != null) {
|
||||
combinedParams.addAll(Arrays.asList(savedRequestParams));
|
||||
}
|
||||
|
||||
return (String[]) combinedParams.toArray(new String[combinedParams.size()]);
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
http\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-2.0.4.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
|
||||
|
||||
+10
-15
@@ -46,7 +46,6 @@ 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}
|
||||
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.
|
||||
@@ -70,8 +69,8 @@ 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.
|
||||
ldap-server.attlist &=
|
||||
attribute manager-password {xsd:string}?
|
||||
ldap-server.attlist &=
|
||||
## Explicitly specifies an ldif file resource to load into an embedded LDAP server
|
||||
@@ -89,13 +88,12 @@ 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:string}
|
||||
group-search-base-attribute =
|
||||
## Search base for group membership searches. Defaults to "" (searching from the root).
|
||||
## Search base for group membership searches. Defaults to "ou=groups".
|
||||
attribute group-search-base {xsd:string}
|
||||
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:string}
|
||||
user-search-base-attribute =
|
||||
## Search base for user searches. Defaults to "". Only used with a 'user-search-filter'.
|
||||
## Search base for user searches. Defaults to "".
|
||||
attribute user-search-base {xsd:string}
|
||||
group-role-attribute-attribute =
|
||||
## The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn".
|
||||
@@ -193,7 +191,6 @@ global-method-security.attlist &=
|
||||
attribute access-decision-manager-ref {xsd:string}?
|
||||
|
||||
custom-after-invocation-provider =
|
||||
## Used to decorate an AfterInvocationProvider to specify that it should be used with method security.
|
||||
element custom-after-invocation-provider {empty}
|
||||
|
||||
protect-pointcut =
|
||||
@@ -261,7 +258,7 @@ 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.
|
||||
## Used to specify that a URL must be accessed over http or https
|
||||
attribute requires-channel {"http" | "https" | "any"}?
|
||||
|
||||
logout =
|
||||
@@ -336,13 +333,12 @@ concurrent-session-control =
|
||||
## Adds support for concurrent session control, allowing limits to be placed on the number of sessions a user can have.
|
||||
element concurrent-session-control {concurrent-sessions.attlist, empty}
|
||||
concurrent-sessions.attlist &=
|
||||
## The maximum number of sessions a single user can have open at the same time. Defaults to "1".
|
||||
attribute max-sessions {xsd:positiveInteger}?
|
||||
concurrent-sessions.attlist &=
|
||||
## 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.
|
||||
## The URL a user will be redirected to if they attempt to use a session which has been "expired" by the concurrent session controller.
|
||||
attribute expired-url {xsd:string}?
|
||||
concurrent-sessions.attlist &=
|
||||
## 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.
|
||||
## Specifies that an exception should be raised when a user attempts to login twice. The default behaviour is to expire the original session.
|
||||
attribute exception-if-maximum-exceeded {boolean}?
|
||||
concurrent-sessions.attlist &=
|
||||
## Allows you to define an alias for the SessionRegistry bean in order to access it in your own configuration
|
||||
@@ -375,7 +371,7 @@ 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:string}?
|
||||
remember-me-data-source-ref =
|
||||
## DataSource bean for the database that contains the token repository schema.
|
||||
## DataSource bean for the database that contains the token
|
||||
data-source-ref
|
||||
|
||||
anonymous =
|
||||
@@ -400,9 +396,9 @@ port-mappings.attlist &= empty
|
||||
port-mapping =
|
||||
element port-mapping {http-port, https-port}
|
||||
|
||||
http-port = attribute http {xsd:string}
|
||||
http-port = attribute http {xsd:integer}
|
||||
|
||||
https-port = attribute https {xsd:string}
|
||||
https-port = attribute https {xsd:integer}
|
||||
|
||||
|
||||
x509 =
|
||||
@@ -434,7 +430,6 @@ ap.attlist &=
|
||||
user-service-ref?
|
||||
|
||||
custom-authentication-provider =
|
||||
## Element used to decorate an AuthenticationProvider bean to add it to the internal AuthenticationManager maintained by the namespace.
|
||||
element custom-authentication-provider {cap.attlist}
|
||||
cap.attlist &= empty
|
||||
|
||||
@@ -501,6 +496,6 @@ position =
|
||||
|
||||
|
||||
|
||||
named-security-filter = "FIRST" | "CHANNEL_FILTER" | "CONCURRENT_SESSION_FILTER" | "SESSION_CONTEXT_INTEGRATION_FILTER" | "LOGOUT_FILTER" | "X509_FILTER" | "PRE_AUTH_FILTER" | "CAS_PROCESSING_FILTER" | "AUTHENTICATION_PROCESSING_FILTER" | "OPENID_PROCESSING_FILTER" |"BASIC_PROCESSING_FILTER" | "SERVLET_API_SUPPORT_FILTER" | "REMEMBER_ME_FILTER" | "ANONYMOUS_FILTER" | "EXCEPTION_TRANSLATION_FILTER" | "NTLM_FILTER" | "FILTER_SECURITY_INTERCEPTOR" | "SWITCH_USER_FILTER" | "LAST"
|
||||
named-security-filter = "FIRST" | "CHANNEL_FILTER" | "CONCURRENT_SESSION_FILTER" | "SESSION_CONTEXT_INTEGRATION_FILTER" | "LOGOUT_FILTER" | "X509_FILTER" | "PRE_AUTH_FILTER" | "CAS_PROCESSING_FILTER" | "AUTHENTICATION_PROCESSING_FILTER" | "BASIC_PROCESSING_FILTER" | "SERVLET_API_SUPPORT_FILTER" | "REMEMBER_ME_FILTER" | "ANONYMOUS_FILTER" | "EXCEPTION_TRANSLATION_FILTER" | "NTLM_FILTER" | "FILTER_SECURITY_INTERCEPTOR" | "SWITCH_USER_FILTER" | "LAST"
|
||||
|
||||
|
||||
-1468
File diff suppressed because it is too large
Load Diff
@@ -222,7 +222,7 @@
|
||||
<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>
|
||||
"ou=groups".</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:attributeGroup>
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -6,12 +6,12 @@ ProviderManager.providerNotFound=\u672a\u67e5\u627e\u5230\u9488\u5bf9{0}\u7684Au
|
||||
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
|
||||
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.disabled=\u7528\u6237\u5df2\u88ab\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
|
||||
@@ -29,13 +29,11 @@ DigestProcessingFilter.nonceNotNumeric=Nonce\u4ee4\u724c\u7684\u7b2c1\u90e8\u520
|
||||
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.disabled=\u7528\u6237\u5df2\u88ab\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
|
||||
@@ -47,8 +45,4 @@ DefaultIntitalDirContextFactory.unexpectedException=\u7531\u4e8e\u672a\u9884\u67
|
||||
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
|
||||
|
||||
|
||||
@@ -15,9 +15,7 @@
|
||||
|
||||
package org.springframework.security;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
|
||||
/**
|
||||
@@ -26,10 +24,28 @@ import org.junit.Test;
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class GrantedAuthorityImplTests {
|
||||
|
||||
@Test
|
||||
public void equalsBehavesAsExpected() throws Exception {
|
||||
public class GrantedAuthorityImplTests extends TestCase {
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public GrantedAuthorityImplTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
public GrantedAuthorityImplTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(GrantedAuthorityImplTests.class);
|
||||
}
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public void testObjectEquals() throws Exception {
|
||||
GrantedAuthorityImpl auth1 = new GrantedAuthorityImpl("TEST");
|
||||
GrantedAuthorityImpl auth2 = new GrantedAuthorityImpl("TEST");
|
||||
assertEquals(auth1, auth2);
|
||||
@@ -43,52 +59,32 @@ public class GrantedAuthorityImplTests {
|
||||
GrantedAuthorityImpl auth3 = new GrantedAuthorityImpl("NOT_EQUAL");
|
||||
assertTrue(!auth1.equals(auth3));
|
||||
|
||||
MockGrantedAuthority mock1 = new MockGrantedAuthority("TEST");
|
||||
MockGrantedAuthorityImpl mock1 = new MockGrantedAuthorityImpl("TEST");
|
||||
assertEquals(auth1, mock1);
|
||||
|
||||
MockGrantedAuthority mock2 = new MockGrantedAuthority("NOT_EQUAL");
|
||||
MockGrantedAuthorityImpl mock2 = new MockGrantedAuthorityImpl("NOT_EQUAL");
|
||||
assertTrue(!auth1.equals(mock2));
|
||||
|
||||
Integer int1 = new Integer(222);
|
||||
assertTrue(!auth1.equals(int1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toStringReturnsAuthorityValue() {
|
||||
public void testToString() {
|
||||
GrantedAuthorityImpl auth = new GrantedAuthorityImpl("TEST");
|
||||
assertEquals("TEST", auth.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareToGrantedAuthorityWithSameValueReturns0() {
|
||||
assertEquals(0, new GrantedAuthorityImpl("TEST").compareTo(new MockGrantedAuthority("TEST")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareToNullReturnsNegativeOne() {
|
||||
assertEquals(-1, new GrantedAuthorityImpl("TEST").compareTo(null));
|
||||
}
|
||||
|
||||
/* SEC-899 */
|
||||
@Test
|
||||
public void compareToHandlesCustomAuthorityWhichReturnsNullFromGetAuthority() {
|
||||
assertEquals(-1, new GrantedAuthorityImpl("TEST").compareTo(new MockGrantedAuthority()));
|
||||
}
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
private class MockGrantedAuthority implements GrantedAuthority {
|
||||
private class MockGrantedAuthorityImpl implements GrantedAuthority, Comparable {
|
||||
private String role;
|
||||
|
||||
public MockGrantedAuthority() {
|
||||
}
|
||||
|
||||
public MockGrantedAuthority(String role) {
|
||||
public MockGrantedAuthorityImpl(String role) {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
public int compareTo(Object o) {
|
||||
throw new UnsupportedOperationException();
|
||||
return this.role.compareTo(((GrantedAuthority)o).getAuthority());
|
||||
}
|
||||
|
||||
public String getAuthority() {
|
||||
|
||||
-232
@@ -1,232 +0,0 @@
|
||||
package org.springframework.security.authoritymapping;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.log4j.Level;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.security.GrantedAuthority;
|
||||
import org.springframework.security.GrantedAuthorityImpl;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Ruud Senden
|
||||
*/
|
||||
public class MapBasedAttributes2GrantedAuthoritiesMapperTest extends TestCase {
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
// Set Log4j loglevel to debug to include all logstatements in tests
|
||||
Logger.getRootLogger().setLevel(Level.DEBUG);
|
||||
}
|
||||
|
||||
public final void testAfterPropertiesSetNoMap() {
|
||||
MapBasedAttributes2GrantedAuthoritiesMapper mapper = new MapBasedAttributes2GrantedAuthoritiesMapper();
|
||||
try {
|
||||
mapper.afterPropertiesSet();
|
||||
fail("Expected exception not thrown");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
// Expected exception
|
||||
} catch (Exception unexpected) {
|
||||
fail("Unexpected exception: " + unexpected);
|
||||
}
|
||||
}
|
||||
|
||||
public final void testAfterPropertiesSetEmptyMap() {
|
||||
MapBasedAttributes2GrantedAuthoritiesMapper mapper = new MapBasedAttributes2GrantedAuthoritiesMapper();
|
||||
mapper.setAttributes2grantedAuthoritiesMap(new HashMap());
|
||||
try {
|
||||
mapper.afterPropertiesSet();
|
||||
fail("Expected exception not thrown");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
// Expected exception
|
||||
} catch (Exception unexpected) {
|
||||
fail("Unexpected exception: " + unexpected);
|
||||
}
|
||||
}
|
||||
|
||||
public final void testAfterPropertiesSetInvalidKeyTypeMap() {
|
||||
MapBasedAttributes2GrantedAuthoritiesMapper mapper = new MapBasedAttributes2GrantedAuthoritiesMapper();
|
||||
HashMap m = new HashMap();
|
||||
m.put(new Object(),"ga1");
|
||||
mapper.setAttributes2grantedAuthoritiesMap(m);
|
||||
try {
|
||||
mapper.afterPropertiesSet();
|
||||
fail("Expected exception not thrown");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
// Expected exception
|
||||
} catch (Exception unexpected) {
|
||||
fail("Unexpected exception: " + unexpected);
|
||||
}
|
||||
}
|
||||
|
||||
public final void testAfterPropertiesSetInvalidValueTypeMap1() {
|
||||
MapBasedAttributes2GrantedAuthoritiesMapper mapper = new MapBasedAttributes2GrantedAuthoritiesMapper();
|
||||
HashMap m = new HashMap();
|
||||
m.put("role1",new Object());
|
||||
mapper.setAttributes2grantedAuthoritiesMap(m);
|
||||
try {
|
||||
mapper.afterPropertiesSet();
|
||||
fail("Expected exception not thrown");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
// Expected exception
|
||||
} catch (Exception unexpected) {
|
||||
fail("Unexpected exception: " + unexpected);
|
||||
}
|
||||
}
|
||||
|
||||
public final void testAfterPropertiesSetInvalidValueTypeMap2() {
|
||||
MapBasedAttributes2GrantedAuthoritiesMapper mapper = new MapBasedAttributes2GrantedAuthoritiesMapper();
|
||||
HashMap m = new HashMap();
|
||||
m.put("role1",new Object[]{new String[]{"ga1","ga2"}, new Object()});
|
||||
mapper.setAttributes2grantedAuthoritiesMap(m);
|
||||
try {
|
||||
mapper.afterPropertiesSet();
|
||||
fail("Expected exception not thrown");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
// Expected exception
|
||||
} catch (Exception unexpected) {
|
||||
fail("Unexpected exception: " + unexpected);
|
||||
}
|
||||
}
|
||||
|
||||
public final void testAfterPropertiesSetValidMap() {
|
||||
MapBasedAttributes2GrantedAuthoritiesMapper mapper = new MapBasedAttributes2GrantedAuthoritiesMapper();
|
||||
HashMap m = getValidAttributes2GrantedAuthoritiesMap();
|
||||
mapper.setAttributes2grantedAuthoritiesMap(m);
|
||||
try {
|
||||
mapper.afterPropertiesSet();
|
||||
} catch (Exception unexpected) {
|
||||
fail("Unexpected exception: " + unexpected);
|
||||
}
|
||||
}
|
||||
|
||||
public final void testMapping1() {
|
||||
String[] roles = { "role1" };
|
||||
String[] expectedGas = { "ga1" };
|
||||
Attributes2GrantedAuthoritiesMapper mapper = getDefaultMapper();
|
||||
testGetGrantedAuthorities(mapper, roles, expectedGas);
|
||||
}
|
||||
|
||||
public final void testMapping2() {
|
||||
String[] roles = { "role2" };
|
||||
String[] expectedGas = { "ga2" };
|
||||
Attributes2GrantedAuthoritiesMapper mapper = getDefaultMapper();
|
||||
testGetGrantedAuthorities(mapper, roles, expectedGas);
|
||||
}
|
||||
|
||||
public final void testMapping3() {
|
||||
String[] roles = { "role3" };
|
||||
String[] expectedGas = { "ga3", "ga4" };
|
||||
Attributes2GrantedAuthoritiesMapper mapper = getDefaultMapper();
|
||||
testGetGrantedAuthorities(mapper, roles, expectedGas);
|
||||
}
|
||||
|
||||
public final void testMapping4() {
|
||||
String[] roles = { "role4" };
|
||||
String[] expectedGas = { "ga5", "ga6" };
|
||||
Attributes2GrantedAuthoritiesMapper mapper = getDefaultMapper();
|
||||
testGetGrantedAuthorities(mapper, roles, expectedGas);
|
||||
}
|
||||
|
||||
public final void testMapping5() {
|
||||
String[] roles = { "role5" };
|
||||
String[] expectedGas = { "ga7", "ga8", "ga9" };
|
||||
Attributes2GrantedAuthoritiesMapper mapper = getDefaultMapper();
|
||||
testGetGrantedAuthorities(mapper, roles, expectedGas);
|
||||
}
|
||||
|
||||
public final void testMapping6() {
|
||||
String[] roles = { "role6" };
|
||||
String[] expectedGas = { "ga10", "ga11", "ga12" };
|
||||
Attributes2GrantedAuthoritiesMapper mapper = getDefaultMapper();
|
||||
testGetGrantedAuthorities(mapper, roles, expectedGas);
|
||||
}
|
||||
|
||||
public final void testMapping7() {
|
||||
String[] roles = { "role7" };
|
||||
String[] expectedGas = { "ga13", "ga14" };
|
||||
Attributes2GrantedAuthoritiesMapper mapper = getDefaultMapper();
|
||||
testGetGrantedAuthorities(mapper, roles, expectedGas);
|
||||
}
|
||||
|
||||
public final void testMapping8() {
|
||||
String[] roles = { "role8" };
|
||||
String[] expectedGas = { "ga13", "ga14" };
|
||||
Attributes2GrantedAuthoritiesMapper mapper = getDefaultMapper();
|
||||
testGetGrantedAuthorities(mapper, roles, expectedGas);
|
||||
}
|
||||
|
||||
public final void testMapping9() {
|
||||
String[] roles = { "role9" };
|
||||
String[] expectedGas = {};
|
||||
Attributes2GrantedAuthoritiesMapper mapper = getDefaultMapper();
|
||||
testGetGrantedAuthorities(mapper, roles, expectedGas);
|
||||
}
|
||||
|
||||
public final void testMapping10() {
|
||||
String[] roles = { "role10" };
|
||||
String[] expectedGas = {};
|
||||
Attributes2GrantedAuthoritiesMapper mapper = getDefaultMapper();
|
||||
testGetGrantedAuthorities(mapper, roles, expectedGas);
|
||||
}
|
||||
|
||||
public final void testMapping11() {
|
||||
String[] roles = { "role11" };
|
||||
String[] expectedGas = {};
|
||||
Attributes2GrantedAuthoritiesMapper mapper = getDefaultMapper();
|
||||
testGetGrantedAuthorities(mapper, roles, expectedGas);
|
||||
}
|
||||
|
||||
public final void testNonExistingMapping() {
|
||||
String[] roles = { "nonExisting" };
|
||||
String[] expectedGas = {};
|
||||
Attributes2GrantedAuthoritiesMapper mapper = getDefaultMapper();
|
||||
testGetGrantedAuthorities(mapper, roles, expectedGas);
|
||||
}
|
||||
|
||||
public final void testMappingCombination() {
|
||||
String[] roles = { "role1", "role2", "role3", "role4", "role5", "role6", "role7", "role8", "role9", "role10", "role11" };
|
||||
String[] expectedGas = { "ga1", "ga2", "ga3", "ga4", "ga5", "ga6", "ga7", "ga8", "ga9", "ga10", "ga11", "ga12", "ga13", "ga14"};
|
||||
Attributes2GrantedAuthoritiesMapper mapper = getDefaultMapper();
|
||||
testGetGrantedAuthorities(mapper, roles, expectedGas);
|
||||
}
|
||||
|
||||
private HashMap getValidAttributes2GrantedAuthoritiesMap() {
|
||||
HashMap m = new HashMap();
|
||||
m.put("role1","ga1");
|
||||
m.put("role2",new GrantedAuthorityImpl("ga2"));
|
||||
m.put("role3",Arrays.asList(new Object[]{"ga3",new GrantedAuthorityImpl("ga4")}));
|
||||
m.put("role4","ga5,ga6");
|
||||
m.put("role5",Arrays.asList(new Object[]{"ga7","ga8",new Object[]{new GrantedAuthorityImpl("ga9")}}));
|
||||
m.put("role6",new Object[]{"ga10","ga11",new Object[]{new GrantedAuthorityImpl("ga12")}});
|
||||
m.put("role7",new String[]{"ga13","ga14"});
|
||||
m.put("role8",new String[]{"ga13","ga14",null});
|
||||
m.put("role9",null);
|
||||
m.put("role10",new Object[]{});
|
||||
m.put("role11",Arrays.asList(new Object[]{null}));
|
||||
return m;
|
||||
}
|
||||
|
||||
private MapBasedAttributes2GrantedAuthoritiesMapper getDefaultMapper() {
|
||||
MapBasedAttributes2GrantedAuthoritiesMapper mapper = new MapBasedAttributes2GrantedAuthoritiesMapper();
|
||||
mapper.setAttributes2grantedAuthoritiesMap(getValidAttributes2GrantedAuthoritiesMap());
|
||||
mapper.afterPropertiesSet();
|
||||
return mapper;
|
||||
}
|
||||
|
||||
private void testGetGrantedAuthorities(Attributes2GrantedAuthoritiesMapper mapper, String[] roles, String[] expectedGas) {
|
||||
GrantedAuthority[] result = mapper.getGrantedAuthorities(roles);
|
||||
Collection resultColl = new ArrayList(result.length);
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
resultColl.add(result[i].getAuthority());
|
||||
}
|
||||
Collection expectedColl = Arrays.asList(expectedGas);
|
||||
assertTrue("Role collections do not match; result: " + resultColl + ", expected: " + expectedColl, expectedColl
|
||||
.containsAll(resultColl)
|
||||
&& resultColl.containsAll(expectedColl));
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -28,7 +28,7 @@ import java.util.Random;
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
*/
|
||||
public class SessionRegistryImplMTTests extends TestCase {
|
||||
public class SessionRegistryImplMultithreadedTests extends TestCase {
|
||||
private static final Random rnd = new Random();
|
||||
private static boolean errorOccurred;
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
package org.springframework.security.config;
|
||||
|
||||
public abstract class ConfigTestUtils {
|
||||
public static final String AUTH_PROVIDER_XML =
|
||||
" <authentication-provider>" +
|
||||
" <user-service id='us'>" +
|
||||
" <user name='bob' password='bobspassword' authorities='ROLE_A,ROLE_B' />" +
|
||||
" <user name='bill' password='billspassword' authorities='ROLE_A,ROLE_B,AUTH_OTHER' />" +
|
||||
" <user name='admin' password='password' authorities='ROLE_ADMIN,ROLE_USER' />" +
|
||||
" <user name='user' password='password' authorities='ROLE_USER' />" +
|
||||
" </user-service>" +
|
||||
" </authentication-provider>";
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user