1
0
mirror of synced 2026-07-09 04:40:13 +00:00

Compare commits

..

2 Commits

Author SHA1 Message Date
Luke Taylor 45253ca148 Updated sandbox pom versions to match release 2008-06-04 09:56:08 +00:00
Luke Taylor 807ae835b8 [maven-release-plugin] copy for tag spring-security-parent-2.0.2 2008-06-03 16:06:44 +00:00
284 changed files with 3270 additions and 12296 deletions
+2 -8
View File
@@ -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;
}
}
@@ -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 + "]";
}
}
@@ -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 = ("
@@ -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)
@@ -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;
}
@@ -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);
}
}
@@ -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);
+1 -1
View File
@@ -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>
+1 -1
View File
@@ -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>
+1 -1
View File
@@ -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
View File
@@ -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>
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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>
@@ -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);
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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);
}
}
@@ -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,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");
}
@@ -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>
@@ -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>
@@ -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
View File
@@ -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;
}
@@ -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;
}
}
@@ -158,8 +158,4 @@ public class ConcurrentSessionControllerImpl implements ConcurrentSessionControl
public void setSessionRegistry(SessionRegistry sessionRegistry) {
this.sessionRegistry = sessionRegistry;
}
public SessionRegistry getSessionRegistry() {
return sessionRegistry;
}
}
@@ -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));
@@ -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;
}
}
}
@@ -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 &lt;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) {
@@ -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;
}
@@ -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'>.");
}
}
}
@@ -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;
}
}
@@ -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);
}
}
}
@@ -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;
}
@@ -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();
}
}
@@ -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);
@@ -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;
}
}
@@ -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;
}
}
}
@@ -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) {
@@ -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];
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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);
@@ -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 + "]";
}
}
}
@@ -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>&#42</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 + "]";
}
}
}
@@ -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 + "'");
}
}
}
@@ -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 {
@@ -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;
@@ -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()));
}
});
}
@@ -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()) {
@@ -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,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");
}
@@ -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));
}
/**
@@ -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;
}
}
@@ -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 &lt;x509 /&gt; element.
* or namespace support via the &lt;x509 /&gt; 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();
}
}
/**
@@ -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;
}
@@ -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;
}
@@ -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;
}
}
}
@@ -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);
}
@@ -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;
}
}
@@ -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();
@@ -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 {
@@ -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
@@ -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("&lt;");
} else if (c == '>') {
@@ -26,14 +22,12 @@ public abstract class TextUtils {
sb.append("&#034;");
} else if (c == '\'') {
sb.append("&#039;");
} else if (c == '&') {
sb.append("&amp;");
} 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();
}
}
@@ -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
@@ -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"
@@ -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() {
@@ -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));
}
}
@@ -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