Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 973fdf69f2 |
+2
-28
@@ -3,14 +3,13 @@
|
||||
<parent>
|
||||
<artifactId>spring-security-parent</artifactId>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<version>2.0.1</version>
|
||||
<version>2.0.0</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.1</version>
|
||||
<packaging>bundle</packaging>
|
||||
<version>2.0.0</version>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
@@ -45,29 +44,4 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<spring.osgi.export>
|
||||
org.springframework.security.*;version=${pom.version}
|
||||
</spring.osgi.export>
|
||||
|
||||
<spring.osgi.import>
|
||||
net.sf.ehcache.*;version="[1.4.1, 2.0.0)";resolution:=optional,
|
||||
org.springframework.security.*;version="[${pom.version},${pom.version}]",
|
||||
org.springframework.context.*;version="${spring.version.osgi}",
|
||||
org.springframework.dao.*;version="${spring.version.osgi}";resolution:=optional,
|
||||
org.springframework.jdbc.*;version="${spring.version.osgi}";resolution:=optional,
|
||||
org.springframework.transaction.support.*;version="${spring.version.osgi}";resolution:=optional,
|
||||
org.springframework.util.*;version="${spring.version.osgi}",
|
||||
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
|
||||
javax.sql.*
|
||||
</spring.osgi.import>
|
||||
|
||||
<spring.osgi.private.pkg>
|
||||
!org.springframework.security.*
|
||||
</spring.osgi.private.pkg>
|
||||
|
||||
<spring.osgi.symbolic.name>org.springframework.security.acls</spring.osgi.symbolic.name>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -73,7 +73,7 @@ public final class BasicLookupStrategy implements LookupStrategy {
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
/**
|
||||
/**
|
||||
* Constructor accepting mandatory arguments
|
||||
*
|
||||
* @param dataSource to access the database
|
||||
@@ -97,30 +97,30 @@ public final class BasicLookupStrategy implements LookupStrategy {
|
||||
private static String computeRepeatingSql(String repeatingSql, int requiredRepetitions) {
|
||||
Assert.isTrue(requiredRepetitions >= 1, "Must be => 1");
|
||||
|
||||
String startSql = "select acl_object_identity.object_id_identity, "
|
||||
+ "acl_entry.ace_order, "
|
||||
+ "acl_object_identity.id as acl_id, "
|
||||
+ "acl_object_identity.parent_object, "
|
||||
+ "acl_object_identity.entries_inheriting, "
|
||||
+ "acl_entry.id as ace_id, "
|
||||
+ "acl_entry.mask, "
|
||||
+ "acl_entry.granting, "
|
||||
+ "acl_entry.audit_success, "
|
||||
+ "acl_entry.audit_failure, "
|
||||
+ "acl_sid.principal as ace_principal, "
|
||||
+ "acl_sid.sid as ace_sid, "
|
||||
+ "acli_sid.principal as acl_principal, "
|
||||
+ "acli_sid.sid as acl_sid, "
|
||||
+ "acl_class.class "
|
||||
+ "from acl_object_identity "
|
||||
+ "left join acl_sid acli_sid on acli_sid.id = acl_object_identity.owner_sid "
|
||||
+ "left join acl_class on acl_class.id = acl_object_identity.object_id_class "
|
||||
+ "left join acl_entry on acl_object_identity.id = acl_entry.acl_object_identity "
|
||||
+ "left join acl_sid on acl_entry.sid = acl_sid.id "
|
||||
String startSql = "select ACL_OBJECT_IDENTITY.OBJECT_ID_IDENTITY, "
|
||||
+ "ACL_ENTRY.ACE_ORDER, "
|
||||
+ "ACL_OBJECT_IDENTITY.ID as ACL_ID, "
|
||||
+ "ACL_OBJECT_IDENTITY.PARENT_OBJECT, "
|
||||
+ "ACL_OBJECT_IDENTITY.ENTRIES_INHERITING, "
|
||||
+ "ACL_ENTRY.ID as ACE_ID, "
|
||||
+ "ACL_ENTRY.MASK, "
|
||||
+ "ACL_ENTRY.GRANTING, "
|
||||
+ "ACL_ENTRY.AUDIT_SUCCESS, "
|
||||
+ "ACL_ENTRY.AUDIT_FAILURE, "
|
||||
+ "ACL_SID.PRINCIPAL as ACE_PRINCIPAL, "
|
||||
+ "ACL_SID.SID as ACE_SID, "
|
||||
+ "ACLI_SID.PRINCIPAL as ACL_PRINCIPAL, "
|
||||
+ "ACLI_SID.SID as ACL_SID, "
|
||||
+ "ACL_CLASS.CLASS "
|
||||
+ "from ACL_OBJECT_IDENTITY "
|
||||
+ "left join ACL_SID ACLI_SID on ACLI_SID.ID = ACL_OBJECT_IDENTITY.OWNER_SID "
|
||||
+ "left join ACL_CLASS on ACL_CLASS.ID = ACL_OBJECT_IDENTITY.OBJECT_ID_CLASS "
|
||||
+ "left join ACL_ENTRY on ACL_OBJECT_IDENTITY.ID = ACL_ENTRY.ACL_OBJECT_IDENTITY "
|
||||
+ "left join ACL_SID on ACL_ENTRY.SID = ACL_SID.ID "
|
||||
+ "where ( ";
|
||||
|
||||
String endSql = ") order by acl_object_identity.object_id_identity"
|
||||
+ " asc, acl_entry.ace_order asc";
|
||||
String endSql = ") order by ACL_OBJECT_IDENTITY.OBJECT_ID_IDENTITY"
|
||||
+ " asc, ACL_ENTRY.ACE_ORDER asc";
|
||||
|
||||
StringBuffer sqlStringBuffer = new StringBuffer();
|
||||
sqlStringBuffer.append(startSql);
|
||||
@@ -196,30 +196,30 @@ public final class BasicLookupStrategy implements LookupStrategy {
|
||||
*/
|
||||
private void convertCurrentResultIntoObject(Map acls, ResultSet rs)
|
||||
throws SQLException {
|
||||
Long id = new Long(rs.getLong("acl_id"));
|
||||
Long id = new Long(rs.getLong("ACL_ID"));
|
||||
|
||||
// If we already have an ACL for this ID, just create the ACE
|
||||
AclImpl acl = (AclImpl) acls.get(id);
|
||||
|
||||
if (acl == null) {
|
||||
// Make an AclImpl and pop it into the Map
|
||||
ObjectIdentity objectIdentity = new ObjectIdentityImpl(rs.getString("class"),
|
||||
new Long(rs.getLong("object_id_identity")));
|
||||
ObjectIdentity objectIdentity = new ObjectIdentityImpl(rs.getString("CLASS"),
|
||||
new Long(rs.getLong("OBJECT_ID_IDENTITY")));
|
||||
|
||||
Acl parentAcl = null;
|
||||
long parentAclId = rs.getLong("parent_object");
|
||||
long parentAclId = rs.getLong("PARENT_OBJECT");
|
||||
|
||||
if (parentAclId != 0) {
|
||||
parentAcl = new StubAclParent(new Long(parentAclId));
|
||||
}
|
||||
|
||||
boolean entriesInheriting = rs.getBoolean("entries_inheriting");
|
||||
boolean entriesInheriting = rs.getBoolean("ENTRIES_INHERITING");
|
||||
Sid owner;
|
||||
|
||||
if (rs.getBoolean("acl_principal")) {
|
||||
owner = new PrincipalSid(rs.getString("acl_sid"));
|
||||
if (rs.getBoolean("ACL_PRINCIPAL")) {
|
||||
owner = new PrincipalSid(rs.getString("ACL_SID"));
|
||||
} else {
|
||||
owner = new GrantedAuthoritySid(rs.getString("acl_sid"));
|
||||
owner = new GrantedAuthoritySid(rs.getString("ACL_SID"));
|
||||
}
|
||||
|
||||
acl = new AclImpl(objectIdentity, id, aclAuthorizationStrategy, auditLogger, parentAcl, null,
|
||||
@@ -229,20 +229,20 @@ public final class BasicLookupStrategy implements LookupStrategy {
|
||||
|
||||
// Add an extra ACE to the ACL (ORDER BY maintains the ACE list order)
|
||||
// It is permissable to have no ACEs in an ACL (which is detected by a null ACE_SID)
|
||||
if (rs.getString("ace_sid") != null) {
|
||||
Long aceId = new Long(rs.getLong("ace_id"));
|
||||
if (rs.getString("ACE_SID") != null) {
|
||||
Long aceId = new Long(rs.getLong("ACE_ID"));
|
||||
Sid recipient;
|
||||
|
||||
if (rs.getBoolean("ace_principal")) {
|
||||
recipient = new PrincipalSid(rs.getString("ace_sid"));
|
||||
if (rs.getBoolean("ACE_PRINCIPAL")) {
|
||||
recipient = new PrincipalSid(rs.getString("ACE_SID"));
|
||||
} else {
|
||||
recipient = new GrantedAuthoritySid(rs.getString("ace_sid"));
|
||||
recipient = new GrantedAuthoritySid(rs.getString("ACE_SID"));
|
||||
}
|
||||
|
||||
Permission permission = BasePermission.buildFromMask(rs.getInt("mask"));
|
||||
boolean granting = rs.getBoolean("granting");
|
||||
boolean auditSuccess = rs.getBoolean("audit_success");
|
||||
boolean auditFailure = rs.getBoolean("audit_failure");
|
||||
Permission permission = BasePermission.buildFromMask(rs.getInt("MASK"));
|
||||
boolean granting = rs.getBoolean("GRANTING");
|
||||
boolean auditSuccess = rs.getBoolean("AUDIT_SUCCESS");
|
||||
boolean auditFailure = rs.getBoolean("AUDIT_FAILURE");
|
||||
|
||||
AccessControlEntryImpl ace = new AccessControlEntryImpl(aceId, acl, recipient, permission, granting,
|
||||
auditSuccess, auditFailure);
|
||||
@@ -283,7 +283,7 @@ public final class BasicLookupStrategy implements LookupStrategy {
|
||||
|
||||
// Make the "acls" map contain all requested objectIdentities
|
||||
// (including markers to each parent in the hierarchy)
|
||||
String sql = computeRepeatingSql("(acl_object_identity.object_id_identity = ? and acl_class.class = ?)",
|
||||
String sql = computeRepeatingSql("(ACL_OBJECT_IDENTITY.OBJECT_ID_IDENTITY = ? and ACL_CLASS.CLASS = ?)",
|
||||
objectIdentities.length);
|
||||
|
||||
Set parentsToLookup = (Set) jdbcTemplate.query(sql,
|
||||
@@ -338,7 +338,7 @@ public final class BasicLookupStrategy implements LookupStrategy {
|
||||
Assert.notNull(acls, "ACLs are required");
|
||||
Assert.notEmpty(findNow, "Items to find now required");
|
||||
|
||||
String sql = computeRepeatingSql("(acl_object_identity.id = ?)", findNow.size());
|
||||
String sql = computeRepeatingSql("(ACL_OBJECT_IDENTITY.ID = ?)", findNow.size());
|
||||
|
||||
Set parentsToLookup = (Set) jdbcTemplate.query(sql,
|
||||
new PreparedStatementSetter() {
|
||||
@@ -473,7 +473,7 @@ public final class BasicLookupStrategy implements LookupStrategy {
|
||||
convertCurrentResultIntoObject(acls, rs);
|
||||
|
||||
// Figure out if this row means we need to lookup another parent
|
||||
long parentId = rs.getLong("parent_object");
|
||||
long parentId = rs.getLong("PARENT_OBJECT");
|
||||
|
||||
if (parentId != 0) {
|
||||
// See if it's already in the "acls"
|
||||
|
||||
@@ -53,11 +53,11 @@ 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 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 = ("
|
||||
+ "select id FROM acl_class where acl_class.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 = ("
|
||||
+ "SELECT id FROM acl_class WHERE acl_class.class = ?)";
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
|
||||
+14
-13
@@ -62,22 +62,23 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
||||
|
||||
private boolean foreignKeysInDatabase = true;
|
||||
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 deleteClassByClassNameString = "DELETE FROM acl_class WHERE class=?";
|
||||
private String deleteEntryByObjectIdentityForeignKey = "DELETE FROM acl_entry WHERE acl_object_identity=?";
|
||||
private String deleteObjectIdentityByPrimaryKey = "DELETE FROM acl_object_identity WHERE id=?";
|
||||
private String identityQuery = "call identity()";
|
||||
private String insertClass = "insert into acl_class (class) values (?)";
|
||||
private String insertEntry = "insert into acl_entry "
|
||||
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)"
|
||||
+ "values (?, ?, ?, ?, ?, ?, ?)";
|
||||
private String insertObjectIdentity = "insert into acl_object_identity "
|
||||
+ "(object_id_class, object_id_identity, owner_sid, entries_inheriting) " + "values (?, ?, ?, ?)";
|
||||
private String insertSid = "insert into acl_sid (principal, sid) values (?, ?)";
|
||||
private String selectClassPrimaryKey = "select id from acl_class where class=?";
|
||||
private String selectObjectIdentityPrimaryKey = "select acl_object_identity.id from acl_object_identity, acl_class "
|
||||
+ "where acl_object_identity.object_id_class = acl_class.id and acl_class.class=? "
|
||||
+ "VALUES (?, ?, ?, ?, ?, ?, ?)";
|
||||
private String insertObjectIdentity = "INSERT INTO acl_object_identity "
|
||||
+ "(object_id_class, object_id_identity, owner_sid, entries_inheriting) " + "VALUES (?, ?, ?, ?)";
|
||||
private String insertSid = "INSERT INTO acl_sid (principal, sid) VALUES (?, ?)";
|
||||
private String selectClassPrimaryKey = "SELECT id FROM acl_class WHERE class=?";
|
||||
private String selectObjectIdentityPrimaryKey = "SELECT acl_object_identity.id FROM acl_object_identity, acl_class "
|
||||
+ "WHERE acl_object_identity.object_id_class = acl_class.id and acl_class.class=? "
|
||||
+ "and acl_object_identity.object_id_identity = ?";
|
||||
private String selectSidPrimaryKey = "select id from acl_sid where principal=? and sid=?";
|
||||
private String updateObjectIdentity = "update acl_object_identity set "
|
||||
private String selectSidPrimaryKey = "SELECT id FROM acl_sid WHERE principal=? AND sid=?";
|
||||
private String updateObjectIdentity = "UPDATE acl_object_identity SET "
|
||||
+ "parent_object = ?, owner_sid = ?, entries_inheriting = ?" + " where id = ?";
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-adapters</artifactId>
|
||||
<version>2.0.1</version>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
<artifactId>spring-security-catalina</artifactId>
|
||||
<name>Spring Security - Catalina adapter</name>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-adapters</artifactId>
|
||||
<version>2.0.1</version>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
<artifactId>spring-security-jboss</artifactId>
|
||||
<name>Spring Security - JBoss adapter</name>
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ import javax.security.auth.login.LoginException;
|
||||
* which is subsequently available from <code>java:comp/env/security/subject</code>.</p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author Sergio Bern
|
||||
* @author Sergio Bern�
|
||||
* @version $Id:JbossSpringSecurityLoginModule.java 2151 2007-09-22 11:54:13Z luke_t $
|
||||
*/
|
||||
public class JbossSpringSecurityLoginModule extends AbstractServerLoginModule {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-adapters</artifactId>
|
||||
<version>2.0.1</version>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
<artifactId>spring-security-jetty</artifactId>
|
||||
<name>Spring Security - Jetty adapter</name>
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-parent</artifactId>
|
||||
<version>2.0.1</version>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
<artifactId>spring-security-adapters</artifactId>
|
||||
<name>Spring Security - Adapters</name>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-adapters</artifactId>
|
||||
<version>2.0.1</version>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
<artifactId>spring-security-resin</artifactId>
|
||||
<name>Spring Security - Resin adapter</name>
|
||||
|
||||
+2
-27
@@ -3,11 +3,11 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-parent</artifactId>
|
||||
<version>2.0.1</version>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
<artifactId>spring-security-cas-client</artifactId>
|
||||
<name>Spring Security - CAS support</name>
|
||||
<packaging>bundle</packaging>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
@@ -39,29 +39,4 @@
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<spring.osgi.export>
|
||||
org.springframework.security.*;version=${pom.version}
|
||||
</spring.osgi.export>
|
||||
|
||||
<spring.osgi.import>
|
||||
org.springframework.security.*;version="[${pom.version},${pom.version}]",
|
||||
org.springframework.beans.*;version="${spring.version.osgi}",
|
||||
org.springframework.context.*;version="${spring.version.osgi}",
|
||||
org.springframework.dao.*;version="${spring.version.osgi}";resolution:=optional,
|
||||
org.springframework.util.*;version="${spring.version.osgi}",
|
||||
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.1, 4.0.0)"
|
||||
</spring.osgi.import>
|
||||
|
||||
<spring.osgi.private.pkg>
|
||||
!org.springframework.security.*
|
||||
</spring.osgi.private.pkg>
|
||||
|
||||
<spring.osgi.symbolic.name>org.springframework.security.cas</spring.osgi.symbolic.name>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
+21
-30
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-parent</artifactId>
|
||||
<version>2.0.1</version>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
<packaging>bundle</packaging>
|
||||
<artifactId>spring-security-core-tiger</artifactId>
|
||||
@@ -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.aspectj</groupId>
|
||||
<artifactId>aspectjrt</artifactId>
|
||||
@@ -68,6 +61,26 @@
|
||||
<target>1.5</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<version>${felix.version}</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Bundle-SymbolicName>org.springframework.bundle.security.core.tiger</Bundle-SymbolicName>
|
||||
<Export-Package>org.springframework.security.*;version=${pom.version}</Export-Package>
|
||||
<Private-Package>!org.springframework.security.*</Private-Package>
|
||||
<Implementation-Title>${pom.name}</Implementation-Title>
|
||||
<Implementation-Version>${pom.version}</Implementation-Version>
|
||||
<Import-Package>
|
||||
org.springframework*;resolution:=optional;version="[2.0,2.6)",
|
||||
*;resolution:=optional
|
||||
</Import-Package>
|
||||
</instructions>
|
||||
<excludeDependencies>true</excludeDependencies>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<reporting>
|
||||
@@ -81,26 +94,4 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</reporting>
|
||||
|
||||
<properties>
|
||||
<spring.osgi.export>
|
||||
org.springframework.security.*;version=${pom.version}
|
||||
</spring.osgi.export>
|
||||
|
||||
<spring.osgi.import>
|
||||
javax.annotation.*;version="[1.0.0, 2.0.0)",
|
||||
org.springframework.security.*;version="[${pom.version},${pom.version}]",
|
||||
org.springframework.core.*;version="${spring.version.osgi}"
|
||||
</spring.osgi.import>
|
||||
|
||||
<spring.osgi.private.pkg>
|
||||
!org.springframework.security.*
|
||||
</spring.osgi.private.pkg>
|
||||
|
||||
<spring.osgi.include.res>
|
||||
src/main/resources
|
||||
</spring.osgi.include.res>
|
||||
|
||||
<spring.osgi.symbolic.name>org.springframework.security.annotation</spring.osgi.symbolic.name>
|
||||
</properties>
|
||||
</project>
|
||||
|
||||
+2
-36
@@ -1,12 +1,8 @@
|
||||
package org.springframework.security.config;
|
||||
|
||||
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;
|
||||
@@ -15,17 +11,17 @@ 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 GlobalMethodSecurityBeanDefinitionParserTests {
|
||||
private AbstractXmlApplicationContext appContext;
|
||||
private ClassPathXmlApplicationContext appContext;
|
||||
|
||||
private BusinessService target;
|
||||
|
||||
@Before
|
||||
public void loadContext() {
|
||||
appContext = new ClassPathXmlApplicationContext("org/springframework/security/config/global-method-security.xml");
|
||||
target = (BusinessService) appContext.getBean("target");
|
||||
@@ -41,13 +37,11 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
||||
|
||||
@Test(expected=AuthenticationCredentialsNotFoundException.class)
|
||||
public void targetShouldPreventProtectedMethodInvocationWithNoContext() {
|
||||
loadContext();
|
||||
target.someUserMethod1();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void targetShouldAllowProtectedMethodInvocationWithCorrectRole() {
|
||||
loadContext();
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_USER")});
|
||||
SecurityContextHolder.getContext().setAuthentication(token);
|
||||
@@ -57,38 +51,10 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
||||
|
||||
@Test(expected=AccessDeniedException.class)
|
||||
public void targetShouldPreventProtectedMethodInvocationWithIncorrectRole() {
|
||||
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'/>"
|
||||
);
|
||||
|
||||
PostProcessedMockUserDetailsService service = (PostProcessedMockUserDetailsService)appContext.getBean("myUserService");
|
||||
|
||||
assertEquals("Hello from the post processor!", service.getPostProcessorWasHere());
|
||||
}
|
||||
|
||||
@Test(expected=BeanDefinitionParsingException.class)
|
||||
public void duplicateElementCausesError() {
|
||||
setContext(
|
||||
"<global-method-security />" +
|
||||
"<global-method-security />"
|
||||
);
|
||||
}
|
||||
|
||||
private void setContext(String context) {
|
||||
appContext = new InMemoryXmlApplicationContext(context);
|
||||
}
|
||||
}
|
||||
|
||||
+29
-53
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-parent</artifactId>
|
||||
<version>2.0.1</version>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
<packaging>bundle</packaging>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
@@ -141,58 +141,34 @@
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<spring.osgi.export>
|
||||
org.springframework.security.*;version=${pom.version}
|
||||
</spring.osgi.export>
|
||||
|
||||
<spring.osgi.import>
|
||||
!com.ibm.websphere.security,
|
||||
javax.servlet.*;version="[2.4.0, 3.0.0)";resolution:=optional,
|
||||
net.sf.ehcache.*;version="[1.4.1, 2.0.0)";resolution:=optional,
|
||||
org.aopalliance.*;version="[1.0.0, 2.0.0)",
|
||||
org.apache.commons.codec.*;version="[1.3.0, 2.0.0)",
|
||||
org.apache.commons.collections.*;version="[3.2.0, 4.0.0)",
|
||||
org.apache.commons.lang.*;version="[2.1.0, 3.0.0)",
|
||||
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
|
||||
org.apache.directory.server.configuration.*;version="[1.0.2, 2.0.0)";resolution:=optional,
|
||||
org.apache.directory.server.core.*;version="[1.0.2, 2.0.0)";resolution:=optional,
|
||||
org.apache.directory.server.protocol.*;version="[1.0.2, 2.0.0)";resolution:=optional,
|
||||
org.aspectj.*;version="[1.5.4, 2.0.0)";resolution:=optional,
|
||||
org.jaxen.*;version="[1.1.1, 2.0.0)";resolution:=optional,
|
||||
org.springframework.aop.*;version="${spring.version.osgi}",
|
||||
org.springframework.beans.*;version="${spring.version.osgi}",
|
||||
org.springframework.context.*;version="${spring.version.osgi}",
|
||||
org.springframework.core.*;version="${spring.version.osgi}",
|
||||
org.springframework.dao.*;version="${spring.version.osgi}";resolution:=optional,
|
||||
org.springframework.jdbc.*;version="${spring.version.osgi}";resolution:=optional,
|
||||
org.springframework.ldap.*;version="[1.2.1.A, 2.0.0)";resolution:=optional,
|
||||
org.springframework.metadata.*;version="${spring.version.osgi}",
|
||||
org.springframework.mock.*;version="${spring.version.osgi}";resolution:=optional,
|
||||
org.springframework.remoting.*;version="${spring.version.osgi}";resolution:=optional,
|
||||
org.springframework.util.*;version="${spring.version.osgi}",
|
||||
org.springframework.web.*;version="${spring.version.osgi}";resolution:=optional,
|
||||
javax.crypto.*,
|
||||
javax.naming.*,
|
||||
javax.rmi.*,
|
||||
javax.security.*,
|
||||
javax.sql.*,
|
||||
javax.xml.parsers.*,
|
||||
org.w3c.dom.*,
|
||||
org.xml.sax.*,
|
||||
*;resolution:=optional
|
||||
</spring.osgi.import>
|
||||
|
||||
<spring.osgi.private.pkg>
|
||||
!org.springframework.security.*
|
||||
</spring.osgi.private.pkg>
|
||||
<!--
|
||||
<spring.osgi.include.res>
|
||||
src/main/resources
|
||||
</spring.osgi.include.res>
|
||||
-->
|
||||
<spring.osgi.symbolic.name>org.springframework.security.core</spring.osgi.symbolic.name>
|
||||
</properties>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<version>${felix.version}</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Bundle-SymbolicName>org.springframework.bundle.security.core</Bundle-SymbolicName>
|
||||
<Export-Package>org.springframework.security.*;version=${pom.version}</Export-Package>
|
||||
<Private-Package>!org.springframework.security.*</Private-Package>
|
||||
<Implementation-Title>${pom.name}</Implementation-Title>
|
||||
<Implementation-Version>${pom.version}</Implementation-Version>
|
||||
<Import-Package>
|
||||
org.springframework*;resolution:=optional;version="[2.0,2.6)",
|
||||
*;resolution:=optional
|
||||
</Import-Package>
|
||||
<!--
|
||||
<Embed-Dependency>
|
||||
*;scope=compile|runtime;inline=true
|
||||
</Embed-Dependency>
|
||||
-->
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -158,7 +158,8 @@ public class ConfigAttributeDefinition implements Serializable {
|
||||
* Allows <code>AccessDecisionManager</code>s and other classes to loop through every configuration attribute
|
||||
* associated with a target secure object.
|
||||
*
|
||||
* @return the configuration attributes stored in this instance.
|
||||
* @return all the configuration attributes stored by the instance, or <code>null</code> if an
|
||||
* <code>Iterator</code> is unavailable
|
||||
*/
|
||||
public Collection getConfigAttributes() {
|
||||
return this.configAttributes;
|
||||
|
||||
-2
@@ -3,7 +3,6 @@ package org.springframework.security.config;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.support.ManagedList;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
@@ -71,7 +70,6 @@ public class AnonymousBeanDefinitionParser implements BeanDefinitionParser {
|
||||
authMgrProviderList.add(provider);
|
||||
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.ANONYMOUS_PROCESSING_FILTER, filter);
|
||||
ConfigUtils.addHttpFilter(parserContext, new RuntimeBeanReference(BeanIds.ANONYMOUS_PROCESSING_FILTER));
|
||||
parserContext.registerComponent(new BeanComponentDefinition(filter, BeanIds.ANONYMOUS_PROCESSING_FILTER));
|
||||
|
||||
return null;
|
||||
|
||||
-1
@@ -41,7 +41,6 @@ public class BasicAuthenticationBeanDefinitionParser implements BeanDefinitionPa
|
||||
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.BASIC_AUTHENTICATION_FILTER,
|
||||
filterBuilder.getBeanDefinition());
|
||||
ConfigUtils.addHttpFilter(parserContext, new RuntimeBeanReference(BeanIds.BASIC_AUTHENTICATION_FILTER));
|
||||
parserContext.registerComponent(new BeanComponentDefinition(filterBuilder.getBeanDefinition(),
|
||||
BeanIds.BASIC_AUTHENTICATION_FILTER));
|
||||
return null;
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package org.springframework.security.config;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
|
||||
/**
|
||||
* Contains all the default Bean IDs created by the namespace support in Spring Security 2.
|
||||
* <p>
|
||||
@@ -20,7 +18,6 @@ public abstract class BeanIds {
|
||||
static final String CONTEXT_SOURCE_SETTING_POST_PROCESSOR = "_contextSettingPostProcessor";
|
||||
static final String HTTP_POST_PROCESSOR = "_httpConfigBeanFactoryPostProcessor";
|
||||
static final String FILTER_CHAIN_POST_PROCESSOR = "_filterChainProxyPostProcessor";
|
||||
static final String FILTER_LIST = "_filterChainList";
|
||||
|
||||
public static final String JDBC_USER_DETAILS_MANAGER = "_jdbcUserDetailsManager";
|
||||
public static final String USER_DETAILS_SERVICE = "_userDetailsService";
|
||||
@@ -33,7 +30,6 @@ public abstract class BeanIds {
|
||||
public static final String CONCURRENT_SESSION_CONTROLLER = "_concurrentSessionController";
|
||||
public static final String ACCESS_MANAGER = "_accessManager";
|
||||
public static final String AUTHENTICATION_MANAGER = "_authenticationManager";
|
||||
public static final String AFTER_INVOCATION_MANAGER = "_afterInvocationManager";
|
||||
public static final String FORM_LOGIN_FILTER = "_formLoginFilter";
|
||||
public static final String FORM_LOGIN_ENTRY_POINT = "_formLoginEntryPoint";
|
||||
public static final String OPEN_ID_FILTER = "_openIDFilter";
|
||||
@@ -53,7 +49,6 @@ public abstract class BeanIds {
|
||||
public static final String SECURITY_CONTEXT_HOLDER_AWARE_REQUEST_FILTER = "_securityContextHolderAwareRequestFilter";
|
||||
public static final String SESSION_FIXATION_PROTECTION_FILTER = "_sessionFixationProtectionFilter";
|
||||
public static final String METHOD_SECURITY_INTERCEPTOR = "_methodSecurityInterceptor";
|
||||
public static final String METHOD_SECURITY_INTERCEPTOR_POST_PROCESSOR = "_methodSecurityInterceptorPostProcessor";
|
||||
public static final String METHOD_DEFINITION_SOURCE_ADVISOR = "_methodDefinitionSourceAdvisor";
|
||||
public static final String PROTECT_POINTCUT_POST_PROCESSOR = "_protectPointcutPostProcessor";
|
||||
public static final String DELEGATING_METHOD_DEFINITION_SOURCE = "_delegatingMethodDefinitionSource";
|
||||
@@ -66,5 +61,4 @@ public abstract class BeanIds {
|
||||
public static final String X509_AUTH_PROVIDER = "_x509AuthenitcationProvider";
|
||||
public static final String PRE_AUTH_ENTRY_POINT = "_preAuthenticatedProcessingFilterEntryPoint";
|
||||
public static final String REMEMBER_ME_SERVICES_INJECTION_POST_PROCESSOR = "_rememberMeServicesInjectionBeanPostProcessor";
|
||||
|
||||
}
|
||||
|
||||
-2
@@ -55,7 +55,6 @@ public class ConcurrentSessionsBeanDefinitionParser implements BeanDefinitionPar
|
||||
String expiryUrl = element.getAttribute(ATT_EXPIRY_URL);
|
||||
|
||||
if (StringUtils.hasText(expiryUrl)) {
|
||||
ConfigUtils.validateHttpRedirect(expiryUrl, parserContext, source);
|
||||
filterBuilder.addPropertyValue("expiredUrl", expiryUrl);
|
||||
}
|
||||
|
||||
@@ -84,7 +83,6 @@ public class ConcurrentSessionsBeanDefinitionParser implements BeanDefinitionPar
|
||||
parserContext.registerComponent(new BeanComponentDefinition(controller, BeanIds.CONCURRENT_SESSION_CONTROLLER));
|
||||
beanRegistry.registerBeanDefinition(BeanIds.CONCURRENT_SESSION_FILTER, filterBuilder.getBeanDefinition());
|
||||
parserContext.registerComponent(new BeanComponentDefinition(filterBuilder.getBeanDefinition(), BeanIds.CONCURRENT_SESSION_FILTER));
|
||||
ConfigUtils.addHttpFilter(parserContext, new RuntimeBeanReference(BeanIds.CONCURRENT_SESSION_FILTER));
|
||||
|
||||
BeanDefinition providerManager = ConfigUtils.registerProviderManagerIfNecessary(parserContext);
|
||||
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
package org.springframework.security.config;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.BeanMetadataElement;
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
@@ -13,7 +11,7 @@ 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.AuthenticationManager;
|
||||
import org.springframework.security.providers.ProviderManager;
|
||||
import org.springframework.security.userdetails.UserDetailsService;
|
||||
import org.springframework.security.vote.AffirmativeBased;
|
||||
@@ -88,6 +86,7 @@ public abstract class ConfigUtils {
|
||||
return authManager;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@@ -103,89 +102,29 @@ public abstract class ConfigUtils {
|
||||
throw new IllegalArgumentException("No UserDetailsService registered.");
|
||||
|
||||
} else if (services.length > 1) {
|
||||
throw new IllegalArgumentException("More than one UserDetailsService registered. Please " +
|
||||
throw new IllegalArgumentException("More than one UserDetailsService registered. Please" +
|
||||
"use a specific Id in your configuration");
|
||||
}
|
||||
|
||||
return new RuntimeBeanReference(services[0]);
|
||||
}
|
||||
|
||||
private static AuthenticationManager getAuthenticationManager(ConfigurableListableBeanFactory bf) {
|
||||
Map authManagers = bf.getBeansOfType(AuthenticationManager.class);
|
||||
|
||||
if (authManagers.size() == 0) {
|
||||
throw new IllegalArgumentException("No AuthenticationManager registered. " +
|
||||
"Make sure you have configured at least one AuthenticationProvider?");
|
||||
|
||||
} else if (authManagers.size() > 1) {
|
||||
throw new IllegalArgumentException("More than one AuthenticationManager registered.");
|
||||
}
|
||||
|
||||
return (AuthenticationManager) authManagers.values().toArray()[0];
|
||||
}
|
||||
|
||||
static ManagedList getRegisteredProviders(ParserContext parserContext) {
|
||||
BeanDefinition authManager = registerProviderManagerIfNecessary(parserContext);
|
||||
return (ManagedList) authManager.getPropertyValues().getPropertyValue("providers").getValue();
|
||||
}
|
||||
|
||||
static ManagedList getRegisteredAfterInvocationProviders(ParserContext parserContext) {
|
||||
BeanDefinition manager = registerAfterInvocationProviderManagerIfNecessary(parserContext);
|
||||
return (ManagedList) manager.getPropertyValues().getPropertyValue("providers").getValue();
|
||||
}
|
||||
|
||||
private static BeanDefinition registerAfterInvocationProviderManagerIfNecessary(ParserContext parserContext) {
|
||||
if(parserContext.getRegistry().containsBeanDefinition(BeanIds.AFTER_INVOCATION_MANAGER)) {
|
||||
return parserContext.getRegistry().getBeanDefinition(BeanIds.AFTER_INVOCATION_MANAGER);
|
||||
}
|
||||
|
||||
BeanDefinition manager = new RootBeanDefinition(AfterInvocationProviderManager.class);
|
||||
manager.getPropertyValues().addPropertyValue("providers", new ManagedList());
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.AFTER_INVOCATION_MANAGER, manager);
|
||||
|
||||
return manager;
|
||||
}
|
||||
|
||||
private static void registerFilterChainPostProcessorIfNecessary(ParserContext pc) {
|
||||
if (pc.getRegistry().containsBeanDefinition(BeanIds.FILTER_CHAIN_POST_PROCESSOR)) {
|
||||
return;
|
||||
}
|
||||
// Post processor specifically to assemble and order the filter chain immediately before the FilterChainProxy is initialized.
|
||||
RootBeanDefinition filterChainPostProcessor = new RootBeanDefinition(FilterChainProxyPostProcessor.class);
|
||||
filterChainPostProcessor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
pc.getRegistry().registerBeanDefinition(BeanIds.FILTER_CHAIN_POST_PROCESSOR, filterChainPostProcessor);
|
||||
RootBeanDefinition filterList = new RootBeanDefinition(FilterChainList.class);
|
||||
filterList.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
pc.getRegistry().registerBeanDefinition(BeanIds.FILTER_LIST, filterList);
|
||||
}
|
||||
|
||||
static void addHttpFilter(ParserContext pc, BeanMetadataElement filter) {
|
||||
registerFilterChainPostProcessorIfNecessary(pc);
|
||||
|
||||
RootBeanDefinition filterList = (RootBeanDefinition) pc.getRegistry().getBeanDefinition(BeanIds.FILTER_LIST);
|
||||
|
||||
ManagedList filters;
|
||||
MutablePropertyValues pvs = filterList.getPropertyValues();
|
||||
if (pvs.contains("filters")) {
|
||||
filters = (ManagedList) pvs.getPropertyValue("filters").getValue();
|
||||
} else {
|
||||
filters = new ManagedList();
|
||||
pvs.addPropertyValue("filters", filters);
|
||||
}
|
||||
|
||||
filters.add(filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bean which holds the list of filters which are maintained in the context and modified by calls to
|
||||
* addHttpFilter. The post processor retrieves these before injecting the list into the FilterChainProxy.
|
||||
*/
|
||||
public static class FilterChainList {
|
||||
List filters;
|
||||
|
||||
public List getFilters() {
|
||||
return filters;
|
||||
}
|
||||
|
||||
public void setFilters(List filters) {
|
||||
this.filters = filters;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the value of an XML attribute which represents a redirect URL.
|
||||
* If not empty or starting with "/" or "http" it will raise an error.
|
||||
*/
|
||||
static void validateHttpRedirect(String url, ParserContext pc, Object source) {
|
||||
if (!StringUtils.hasText(url) || url.startsWith("/") || url.toLowerCase().startsWith("http")) {
|
||||
return;
|
||||
}
|
||||
pc.getReaderContext().error(url + " is not a valid redirect URL (must start with '/' or http(s))", source);
|
||||
}
|
||||
}
|
||||
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
package org.springframework.security.config;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionDecorator;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* Adds the decorated {@link org.springframework.security.afterinvocation.AfterInvocationProvider} to the
|
||||
* AfterInvocationProviderManager's list.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 2.0
|
||||
*/
|
||||
public class CustomAfterInvocationProviderBeanDefinitionDecorator implements BeanDefinitionDecorator {
|
||||
|
||||
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder holder, ParserContext parserContext) {
|
||||
ConfigUtils.getRegisteredAfterInvocationProviders(parserContext).add(holder.getBeanDefinition());
|
||||
|
||||
return holder;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,7 +13,6 @@ abstract class Elements {
|
||||
public static final String JDBC_USER_SERVICE = "jdbc-user-service";
|
||||
public static final String FILTER_CHAIN_MAP = "filter-chain-map";
|
||||
public static final String INTERCEPT_METHODS = "intercept-methods";
|
||||
public static final String INTERCEPT_URL = "intercept-url";
|
||||
public static final String AUTHENTICATION_PROVIDER = "authentication-provider";
|
||||
public static final String HTTP = "http";
|
||||
public static final String LDAP_PROVIDER = "ldap-authentication-provider";
|
||||
@@ -36,7 +35,6 @@ abstract class Elements {
|
||||
public static final String PORT_MAPPING = "port-mapping";
|
||||
public static final String CUSTOM_FILTER = "custom-filter";
|
||||
public static final String CUSTOM_AUTH_PROVIDER = "custom-authentication-provider";
|
||||
public static final String CUSTOM_AFTER_INVOCATION_PROVIDER = "custom-after-invocation-provider";
|
||||
public static final String X509 = "x509";
|
||||
public static final String FILTER_INVOCATION_DEFINITION_SOURCE = "filter-invocation-definition-source";
|
||||
public static final String LDAP_PASSWORD_COMPARE = "password-compare";
|
||||
|
||||
+45
-148
@@ -2,6 +2,7 @@ package org.springframework.security.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -16,21 +17,8 @@ import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.core.OrderComparator;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.security.ConfigAttributeDefinition;
|
||||
import org.springframework.security.config.ConfigUtils.FilterChainList;
|
||||
import org.springframework.security.context.HttpSessionContextIntegrationFilter;
|
||||
import org.springframework.security.intercept.web.DefaultFilterInvocationDefinitionSource;
|
||||
import org.springframework.security.intercept.web.FilterSecurityInterceptor;
|
||||
import org.springframework.security.providers.anonymous.AnonymousAuthenticationToken;
|
||||
import org.springframework.security.providers.anonymous.AnonymousProcessingFilter;
|
||||
import org.springframework.security.ui.ExceptionTranslationFilter;
|
||||
import org.springframework.security.ui.SessionFixationProtectionFilter;
|
||||
import org.springframework.security.ui.basicauth.BasicProcessingFilter;
|
||||
import org.springframework.security.ui.webapp.AuthenticationProcessingFilter;
|
||||
import org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint;
|
||||
import org.springframework.security.ui.webapp.DefaultLoginPageGeneratingFilter;
|
||||
import org.springframework.security.util.FilterChainProxy;
|
||||
import org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -41,161 +29,70 @@ import org.springframework.security.wrapper.SecurityContextHolderAwareRequestFil
|
||||
public class FilterChainProxyPostProcessor implements BeanPostProcessor, BeanFactoryAware {
|
||||
private Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private ListableBeanFactory beanFactory;
|
||||
|
||||
private ListableBeanFactory beanFactory;
|
||||
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
if(!beanName.equals(BeanIds.FILTER_CHAIN_PROXY)) {
|
||||
return bean;
|
||||
}
|
||||
|
||||
FilterChainProxy filterChainProxy = (FilterChainProxy) bean;
|
||||
FilterChainList filterList = (FilterChainList) beanFactory.getBean(BeanIds.FILTER_LIST);
|
||||
|
||||
List filters = new ArrayList(filterList.getFilters());
|
||||
Collections.sort(filters, new OrderComparator());
|
||||
|
||||
logger.info("Checking sorted filter chain: " + filters);
|
||||
|
||||
for(int i=0; i < filters.size(); i++) {
|
||||
Ordered filter = (Ordered)filters.get(i);
|
||||
// Set the default match
|
||||
List defaultFilterChain = orderFilters(beanFactory);
|
||||
|
||||
if (i > 0) {
|
||||
Ordered previous = (Ordered)filters.get(i-1);
|
||||
if (filter.getOrder() == previous.getOrder()) {
|
||||
throw new SecurityConfigurationException("Filters '" + unwrapFilter(filter) + "' and '" +
|
||||
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 not avoiding the use of <http auto-config='true'>.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("Filter chain...");
|
||||
for (int i=0; i < filters.size(); i++) {
|
||||
// Remove the ordered wrapper from the filter and put it back in the chain at the same position.
|
||||
Filter filter = unwrapFilter(filters.get(i));
|
||||
logger.info("[" + i + "] - " + filter);
|
||||
filters.set(i, filter);
|
||||
}
|
||||
|
||||
checkFilterStack(filters);
|
||||
|
||||
// Note that this returns a copy
|
||||
Map filterMap = filterChainProxy.getFilterChainMap();
|
||||
filterMap.put(filterChainProxy.getMatcher().getUniversalMatchPattern(), filters);
|
||||
String allUrlsMatch = filterChainProxy.getMatcher().getUniversalMatchPattern();
|
||||
|
||||
filterMap.put(allUrlsMatch, defaultFilterChain);
|
||||
filterChainProxy.setFilterChainMap(filterMap);
|
||||
|
||||
checkLoginPageIsntProtected(filterChainProxy);
|
||||
|
||||
logger.info("FilterChainProxy: " + filterChainProxy);
|
||||
|
||||
logger.info("Configured filter chain(s): " + filterChainProxy);
|
||||
|
||||
return bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the filter list for possible errors and logs them
|
||||
*/
|
||||
private void checkFilterStack(List filters) {
|
||||
checkForDuplicates(HttpSessionContextIntegrationFilter.class, filters);
|
||||
checkForDuplicates(AuthenticationProcessingFilter.class, filters);
|
||||
checkForDuplicates(SessionFixationProtectionFilter.class, filters);
|
||||
checkForDuplicates(BasicProcessingFilter.class, filters);
|
||||
checkForDuplicates(SecurityContextHolderAwareRequestFilter.class, filters);
|
||||
checkForDuplicates(ExceptionTranslationFilter.class, filters);
|
||||
checkForDuplicates(FilterSecurityInterceptor.class, filters);
|
||||
}
|
||||
|
||||
private void checkForDuplicates(Class clazz, List filters) {
|
||||
for (int i=0; i < filters.size(); i++) {
|
||||
Filter f1 = (Filter)filters.get(i);
|
||||
if (clazz.isAssignableFrom(f1.getClass())) {
|
||||
// Found the first one, check remaining for another
|
||||
for (int j=i+1; j < filters.size(); j++) {
|
||||
Filter f2 = (Filter)filters.get(j);
|
||||
if (clazz.isAssignableFrom(f2.getClass())) {
|
||||
logger.warn("Possible error: Filters at position " + i + " and " + j + " are both " +
|
||||
"instances of " + clazz.getName());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Checks for the common error of having a login page URL protected by the security interceptor */
|
||||
private void checkLoginPageIsntProtected(FilterChainProxy fcp) {
|
||||
ExceptionTranslationFilter etf = (ExceptionTranslationFilter) beanFactory.getBean(BeanIds.EXCEPTION_TRANSLATION_FILTER);
|
||||
|
||||
if (etf.getAuthenticationEntryPoint() instanceof AuthenticationProcessingFilterEntryPoint) {
|
||||
String loginPage =
|
||||
((AuthenticationProcessingFilterEntryPoint)etf.getAuthenticationEntryPoint()).getLoginFormUrl();
|
||||
List filters = fcp.getFilters(loginPage);
|
||||
logger.info("Checking whether login URL '" + loginPage + "' is accessible with your configuration");
|
||||
|
||||
if (filters == null || filters.isEmpty()) {
|
||||
logger.debug("Filter chain is empty for the login page");
|
||||
return;
|
||||
}
|
||||
|
||||
if (loginPage.equals(DefaultLoginPageGeneratingFilter.DEFAULT_LOGIN_PAGE_URL) &&
|
||||
beanFactory.containsBean(BeanIds.DEFAULT_LOGIN_PAGE_GENERATING_FILTER)) {
|
||||
logger.debug("Default generated login page is in use");
|
||||
return;
|
||||
}
|
||||
|
||||
FilterSecurityInterceptor fsi =
|
||||
((FilterSecurityInterceptor)beanFactory.getBean(BeanIds.FILTER_SECURITY_INTERCEPTOR));
|
||||
DefaultFilterInvocationDefinitionSource fids =
|
||||
(DefaultFilterInvocationDefinitionSource) fsi.getObjectDefinitionSource();
|
||||
ConfigAttributeDefinition cad = fids.lookupAttributes(loginPage, "POST");
|
||||
|
||||
if (cad == null) {
|
||||
logger.debug("No access attributes defined for login page URL");
|
||||
if (fsi.isRejectPublicInvocations()) {
|
||||
logger.warn("FilterSecurityInterceptor is configured to reject public invocations." +
|
||||
" Your login page may not be accessible.");
|
||||
}
|
||||
return;
|
||||
|
||||
private List orderFilters(ListableBeanFactory beanFactory) {
|
||||
Map filters = beanFactory.getBeansOfType(Filter.class);
|
||||
|
||||
Assert.notEmpty(filters, "No filters found in app context!");
|
||||
|
||||
Iterator ids = filters.keySet().iterator();
|
||||
|
||||
List orderedFilters = new ArrayList();
|
||||
|
||||
while (ids.hasNext()) {
|
||||
String id = (String) ids.next();
|
||||
Filter filter = (Filter) filters.get(id);
|
||||
|
||||
if (filter instanceof FilterChainProxy) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!beanFactory.containsBean(BeanIds.ANONYMOUS_PROCESSING_FILTER)) {
|
||||
logger.warn("The login page is being protected by the filter chain, but you don't appear to have" +
|
||||
" anonymous authentication enabled. This is almost certainly an error.");
|
||||
return;
|
||||
// Filters must be Spring security filters or wrapped using <custom-filter>
|
||||
if (!filter.getClass().getName().startsWith("org.springframework.security")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Simulate an anonymous access with the supplied attributes.
|
||||
AnonymousProcessingFilter anonPF = (AnonymousProcessingFilter) beanFactory.getBean(BeanIds.ANONYMOUS_PROCESSING_FILTER);
|
||||
AnonymousAuthenticationToken token =
|
||||
new AnonymousAuthenticationToken("key", anonPF.getUserAttribute().getPassword(),
|
||||
anonPF.getUserAttribute().getAuthorities());
|
||||
try {
|
||||
fsi.getAccessDecisionManager().decide(token, new Object(), cad);
|
||||
} catch (Exception e) {
|
||||
logger.warn("Anonymous access to the login page doesn't appear to be enabled. This is almost certainly " +
|
||||
"an error. Please check your configuration allows unauthenticated access to the configured " +
|
||||
"login page. (Simulated access was rejected: " + e + ")");
|
||||
|
||||
if (!(filter instanceof Ordered)) {
|
||||
logger.info("Filter " + id + " doesn't implement the Ordered interface, skipping it.");
|
||||
continue;
|
||||
}
|
||||
|
||||
orderedFilters.add(filter);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the delegate filter of a wrapper, or the unchanged filter if it isn't wrapped.
|
||||
*/
|
||||
private Filter unwrapFilter(Object filter) {
|
||||
if (filter instanceof OrderedFilterBeanDefinitionDecorator.OrderedFilterDecorator) {
|
||||
return ((OrderedFilterBeanDefinitionDecorator.OrderedFilterDecorator)filter).getDelegate();
|
||||
}
|
||||
|
||||
return (Filter) filter;
|
||||
}
|
||||
|
||||
Collections.sort(orderedFilters, new OrderComparator());
|
||||
|
||||
return orderedFilters;
|
||||
}
|
||||
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
return bean;
|
||||
}
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = (ListableBeanFactory) beanFactory;
|
||||
}
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = (ListableBeanFactory) beanFactory;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -44,8 +44,8 @@ public class FilterInvocationDefinitionSourceBeanDefinitionParser extends Abstra
|
||||
UrlMatcher matcher = HttpSecurityBeanDefinitionParser.createUrlMatcher(element);
|
||||
boolean convertPathsToLowerCase = (matcher instanceof AntUrlPathMatcher) && matcher.requiresLowerCaseUrl();
|
||||
|
||||
LinkedHashMap requestMap =
|
||||
HttpSecurityBeanDefinitionParser.parseInterceptUrlsForFilterInvocationRequestMap(interceptUrls,
|
||||
LinkedHashMap requestMap = new LinkedHashMap();
|
||||
HttpSecurityBeanDefinitionParser.parseInterceptUrlsForFilterInvocationRequestMap(interceptUrls, requestMap,
|
||||
convertPathsToLowerCase, parserContext);
|
||||
|
||||
builder.addConstructorArg(matcher);
|
||||
|
||||
+4
-9
@@ -46,7 +46,7 @@ public class FormLoginBeanDefinitionParser implements BeanDefinitionParser {
|
||||
this.filterClassName = filterClassName;
|
||||
}
|
||||
|
||||
public BeanDefinition parse(Element elt, ParserContext pc) {
|
||||
public BeanDefinition parse(Element elt, ParserContext parserContext) {
|
||||
String loginUrl = null;
|
||||
String defaultTargetUrl = null;
|
||||
String authenticationFailureUrl = null;
|
||||
@@ -55,31 +55,26 @@ public class FormLoginBeanDefinitionParser implements BeanDefinitionParser {
|
||||
Object source = null;
|
||||
|
||||
if (elt != null) {
|
||||
source = pc.extractSource(elt);
|
||||
loginUrl = elt.getAttribute(ATT_LOGIN_URL);
|
||||
ConfigUtils.validateHttpRedirect(loginUrl, pc, source);
|
||||
defaultTargetUrl = elt.getAttribute(ATT_FORM_LOGIN_TARGET_URL);
|
||||
ConfigUtils.validateHttpRedirect(defaultTargetUrl, pc, source);
|
||||
authenticationFailureUrl = elt.getAttribute(ATT_FORM_LOGIN_AUTHENTICATION_FAILURE_URL);
|
||||
ConfigUtils.validateHttpRedirect(authenticationFailureUrl, pc, source);
|
||||
alwaysUseDefault = elt.getAttribute(ATT_ALWAYS_USE_DEFAULT_TARGET_URL);
|
||||
loginPage = elt.getAttribute(ATT_LOGIN_PAGE);
|
||||
|
||||
if (!StringUtils.hasText(loginPage)) {
|
||||
loginPage = null;
|
||||
}
|
||||
ConfigUtils.validateHttpRedirect(loginPage, pc, source);
|
||||
|
||||
source = parserContext.extractSource(elt);
|
||||
}
|
||||
|
||||
ConfigUtils.registerProviderManagerIfNecessary(pc);
|
||||
ConfigUtils.registerProviderManagerIfNecessary(parserContext);
|
||||
|
||||
filterBean = createFilterBean(loginUrl, defaultTargetUrl, alwaysUseDefault, loginPage, authenticationFailureUrl);
|
||||
filterBean.setSource(source);
|
||||
filterBean.getPropertyValues().addPropertyValue("authenticationManager",
|
||||
new RuntimeBeanReference(BeanIds.AUTHENTICATION_MANAGER));
|
||||
|
||||
if (pc.getRegistry().containsBeanDefinition(BeanIds.REMEMBER_ME_SERVICES)) {
|
||||
if (parserContext.getRegistry().containsBeanDefinition(BeanIds.REMEMBER_ME_SERVICES)) {
|
||||
filterBean.getPropertyValues().addPropertyValue("rememberMeServices",
|
||||
new RuntimeBeanReference(BeanIds.REMEMBER_ME_SERVICES) );
|
||||
}
|
||||
|
||||
+70
-107
@@ -20,6 +20,7 @@ import org.springframework.security.intercept.method.MapBasedMethodDefinitionSou
|
||||
import org.springframework.security.intercept.method.ProtectPointcutPostProcessor;
|
||||
import org.springframework.security.intercept.method.aopalliance.MethodDefinitionSourceAdvisor;
|
||||
import org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
@@ -47,26 +48,67 @@ class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
parserContext.getReaderContext().error("Cannot locate '" + className + "'", element);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
Object source = parserContext.extractSource(element);
|
||||
// The list of method metadata delegates
|
||||
ManagedList delegates = new ManagedList();
|
||||
|
||||
boolean jsr250Enabled = registerAnnotationBasedMethodDefinitionSources(element, parserContext, delegates);
|
||||
|
||||
MapBasedMethodDefinitionSource mapBasedMethodDefinitionSource = new MapBasedMethodDefinitionSource();
|
||||
delegates.add(mapBasedMethodDefinitionSource);
|
||||
|
||||
// Now create a Map<String, ConfigAttribute> for each <protect-pointcut> sub-element
|
||||
Map pointcutMap = parseProtectPointcuts(parserContext,
|
||||
DomUtils.getChildElementsByTagName(element, Elements.PROTECT_POINTCUT));
|
||||
|
||||
if (pointcutMap.size() > 0) {
|
||||
registerProtectPointcutPostProcessor(parserContext, pointcutMap, mapBasedMethodDefinitionSource, source);
|
||||
boolean useJsr250 = "enabled".equals(element.getAttribute(ATT_USE_JSR250));
|
||||
boolean useSecured = "enabled".equals(element.getAttribute(ATT_USE_SECURED));
|
||||
|
||||
// Check the required classes are present
|
||||
if (useSecured) {
|
||||
validatePresent(SECURED_METHOD_DEFINITION_SOURCE_CLASS, element, parserContext);
|
||||
validatePresent(SECURED_DEPENDENCY_CLASS, element, parserContext);
|
||||
}
|
||||
|
||||
if (useJsr250) {
|
||||
validatePresent(JSR_250_SECURITY_METHOD_DEFINITION_SOURCE_CLASS, element, parserContext);
|
||||
validatePresent(JSR_250_VOTER_CLASS, element, parserContext);
|
||||
}
|
||||
|
||||
registerDelegatingMethodDefinitionSource(parserContext, delegates, source);
|
||||
// Now create a Map<String, ConfigAttribute> for each <protect-pointcut> sub-element
|
||||
Map pointcutMap = new LinkedHashMap();
|
||||
List protect = DomUtils.getChildElementsByTagName(element, Elements.PROTECT_POINTCUT);
|
||||
|
||||
for (Iterator i = protect.iterator(); i.hasNext();) {
|
||||
Element childElt = (Element) i.next();
|
||||
String accessConfig = childElt.getAttribute(ATT_ACCESS);
|
||||
String expression = childElt.getAttribute(ATT_EXPRESSION);
|
||||
Assert.hasText(accessConfig, "Access configuration required for '" + childElt + "'");
|
||||
Assert.hasText(expression, "Expression required for '" + childElt + "'");
|
||||
|
||||
ConfigAttributeDefinition def = new ConfigAttributeDefinition(StringUtils.commaDelimitedListToStringArray(accessConfig));
|
||||
pointcutMap.put(expression, def);
|
||||
}
|
||||
|
||||
MapBasedMethodDefinitionSource mapBasedMethodDefinitionSource = new MapBasedMethodDefinitionSource();
|
||||
|
||||
// Now create and populate our ProtectPointcutBeanPostProcessor, if needed
|
||||
if (pointcutMap.size() > 0) {
|
||||
RootBeanDefinition ppbp = new RootBeanDefinition(ProtectPointcutPostProcessor.class);
|
||||
ppbp.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
ppbp.setSource(parserContext.extractSource(element));
|
||||
ppbp.getConstructorArgumentValues().addGenericArgumentValue(mapBasedMethodDefinitionSource);
|
||||
ppbp.getPropertyValues().addPropertyValue("pointcutMap", pointcutMap);
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.PROTECT_POINTCUT_POST_PROCESSOR, ppbp);
|
||||
}
|
||||
|
||||
// Create our list of method metadata delegates
|
||||
ManagedList delegates = new ManagedList();
|
||||
delegates.add(mapBasedMethodDefinitionSource);
|
||||
|
||||
if (useSecured) {
|
||||
delegates.add(BeanDefinitionBuilder.rootBeanDefinition(SECURED_METHOD_DEFINITION_SOURCE_CLASS).getBeanDefinition());
|
||||
}
|
||||
|
||||
if (useJsr250) {
|
||||
delegates.add(BeanDefinitionBuilder.rootBeanDefinition(JSR_250_SECURITY_METHOD_DEFINITION_SOURCE_CLASS).getBeanDefinition());
|
||||
}
|
||||
|
||||
// Register our DelegatingMethodDefinitionSource
|
||||
RootBeanDefinition delegatingMethodDefinitionSource = new RootBeanDefinition(DelegatingMethodDefinitionSource.class);
|
||||
delegatingMethodDefinitionSource.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
delegatingMethodDefinitionSource.setSource(parserContext.extractSource(element));
|
||||
delegatingMethodDefinitionSource.getPropertyValues().addPropertyValue("methodDefinitionSources", delegates);
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.DELEGATING_METHOD_DEFINITION_SOURCE, delegatingMethodDefinitionSource);
|
||||
|
||||
// Register the applicable AccessDecisionManager, handling the special JSR 250 voter if being used
|
||||
String accessManagerId = element.getAttribute(ATT_ACCESS_MGR);
|
||||
@@ -74,94 +116,17 @@ class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
if (!StringUtils.hasText(accessManagerId)) {
|
||||
ConfigUtils.registerDefaultAccessManagerIfNecessary(parserContext);
|
||||
|
||||
if (jsr250Enabled) {
|
||||
if (useJsr250) {
|
||||
ConfigUtils.addVoter(new RootBeanDefinition(JSR_250_VOTER_CLASS, null, null), parserContext);
|
||||
}
|
||||
|
||||
accessManagerId = BeanIds.ACCESS_MANAGER;
|
||||
}
|
||||
|
||||
registerMethodSecurityInterceptor(parserContext, accessManagerId, source);
|
||||
|
||||
registerAdvisor(parserContext, source);
|
||||
|
||||
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether JSR-250 and/or Secured annotations are enabled and adds the appropriate
|
||||
* MethodDefinitionSource delegates if required.
|
||||
*/
|
||||
private boolean registerAnnotationBasedMethodDefinitionSources(Element element, ParserContext pc, ManagedList delegates) {
|
||||
boolean useJsr250 = "enabled".equals(element.getAttribute(ATT_USE_JSR250));
|
||||
boolean useSecured = "enabled".equals(element.getAttribute(ATT_USE_SECURED));
|
||||
|
||||
// Check the required classes are present
|
||||
if (useSecured) {
|
||||
validatePresent(SECURED_METHOD_DEFINITION_SOURCE_CLASS, element, pc);
|
||||
validatePresent(SECURED_DEPENDENCY_CLASS, element, pc);
|
||||
delegates.add(BeanDefinitionBuilder.rootBeanDefinition(SECURED_METHOD_DEFINITION_SOURCE_CLASS).getBeanDefinition());
|
||||
}
|
||||
|
||||
if (useJsr250) {
|
||||
validatePresent(JSR_250_SECURITY_METHOD_DEFINITION_SOURCE_CLASS, element, pc);
|
||||
validatePresent(JSR_250_VOTER_CLASS, element, pc);
|
||||
delegates.add(BeanDefinitionBuilder.rootBeanDefinition(JSR_250_SECURITY_METHOD_DEFINITION_SOURCE_CLASS).getBeanDefinition());
|
||||
}
|
||||
|
||||
return useJsr250;
|
||||
}
|
||||
|
||||
private void registerDelegatingMethodDefinitionSource(ParserContext parserContext, ManagedList delegates, Object source) {
|
||||
if (parserContext.getRegistry().containsBeanDefinition(BeanIds.DELEGATING_METHOD_DEFINITION_SOURCE)) {
|
||||
parserContext.getReaderContext().error("Duplicate <global-method-security> detected.", source);
|
||||
}
|
||||
RootBeanDefinition delegatingMethodDefinitionSource = new RootBeanDefinition(DelegatingMethodDefinitionSource.class);
|
||||
delegatingMethodDefinitionSource.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
delegatingMethodDefinitionSource.setSource(source);
|
||||
delegatingMethodDefinitionSource.getPropertyValues().addPropertyValue("methodDefinitionSources", delegates);
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.DELEGATING_METHOD_DEFINITION_SOURCE, delegatingMethodDefinitionSource);
|
||||
}
|
||||
|
||||
private void registerProtectPointcutPostProcessor(ParserContext parserContext, Map pointcutMap,
|
||||
MapBasedMethodDefinitionSource mapBasedMethodDefinitionSource, Object source) {
|
||||
RootBeanDefinition ppbp = new RootBeanDefinition(ProtectPointcutPostProcessor.class);
|
||||
ppbp.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
ppbp.setSource(source);
|
||||
ppbp.getConstructorArgumentValues().addGenericArgumentValue(mapBasedMethodDefinitionSource);
|
||||
ppbp.getPropertyValues().addPropertyValue("pointcutMap", pointcutMap);
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.PROTECT_POINTCUT_POST_PROCESSOR, ppbp);
|
||||
}
|
||||
|
||||
private Map parseProtectPointcuts(ParserContext parserContext, List protectPointcutElts) {
|
||||
Map pointcutMap = new LinkedHashMap();
|
||||
|
||||
for (Iterator i = protectPointcutElts.iterator(); i.hasNext();) {
|
||||
Element childElt = (Element) i.next();
|
||||
String accessConfig = childElt.getAttribute(ATT_ACCESS);
|
||||
String expression = childElt.getAttribute(ATT_EXPRESSION);
|
||||
|
||||
if (!StringUtils.hasText(accessConfig)) {
|
||||
parserContext.getReaderContext().error("Access configuration required", parserContext.extractSource(childElt));
|
||||
}
|
||||
|
||||
if (!StringUtils.hasText(expression)) {
|
||||
parserContext.getReaderContext().error("Pointcut expression required", parserContext.extractSource(childElt));
|
||||
}
|
||||
|
||||
ConfigAttributeDefinition def = new ConfigAttributeDefinition(StringUtils.commaDelimitedListToStringArray(accessConfig));
|
||||
pointcutMap.put(expression, def);
|
||||
}
|
||||
|
||||
return pointcutMap;
|
||||
}
|
||||
|
||||
private void registerMethodSecurityInterceptor(ParserContext parserContext, String accessManagerId, Object source) {
|
||||
// MethodSecurityInterceptor
|
||||
RootBeanDefinition interceptor = new RootBeanDefinition(MethodSecurityInterceptor.class);
|
||||
interceptor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
interceptor.setSource(source);
|
||||
interceptor.setSource(parserContext.extractSource(element));
|
||||
|
||||
interceptor.getPropertyValues().addPropertyValue("accessDecisionManager", new RuntimeBeanReference(accessManagerId));
|
||||
interceptor.getPropertyValues().addPropertyValue("authenticationManager", new RuntimeBeanReference(BeanIds.AUTHENTICATION_MANAGER));
|
||||
@@ -169,17 +134,15 @@ class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.METHOD_SECURITY_INTERCEPTOR, interceptor);
|
||||
parserContext.registerComponent(new BeanComponentDefinition(interceptor, BeanIds.METHOD_SECURITY_INTERCEPTOR));
|
||||
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.METHOD_SECURITY_INTERCEPTOR_POST_PROCESSOR,
|
||||
new RootBeanDefinition(MethodSecurityInterceptorPostProcessor.class));
|
||||
}
|
||||
|
||||
private void registerAdvisor(ParserContext parserContext, Object source) {
|
||||
// MethodDefinitionSourceAdvisor
|
||||
RootBeanDefinition advisor = new RootBeanDefinition(MethodDefinitionSourceAdvisor.class);
|
||||
advisor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
advisor.setSource(source);
|
||||
advisor.getConstructorArgumentValues().addGenericArgumentValue(BeanIds.METHOD_SECURITY_INTERCEPTOR);
|
||||
advisor.getConstructorArgumentValues().addGenericArgumentValue(new RuntimeBeanReference(BeanIds.DELEGATING_METHOD_DEFINITION_SOURCE));
|
||||
advisor.setSource(parserContext.extractSource(element));
|
||||
advisor.getConstructorArgumentValues().addGenericArgumentValue(interceptor);
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.METHOD_DEFINITION_SOURCE_ADVISOR, advisor);
|
||||
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.METHOD_DEFINITION_SOURCE_ADVISOR, advisor);
|
||||
}
|
||||
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
+166
-212
@@ -97,57 +97,154 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
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";
|
||||
|
||||
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
ConfigUtils.registerProviderManagerIfNecessary(parserContext);
|
||||
final BeanDefinitionRegistry registry = parserContext.getRegistry();
|
||||
final UrlMatcher matcher = createUrlMatcher(element);
|
||||
final Object source = parserContext.extractSource(element);
|
||||
// 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();
|
||||
BeanDefinitionRegistry registry = parserContext.getRegistry();
|
||||
RootBeanDefinition filterChainProxy = new RootBeanDefinition(FilterChainProxy.class);
|
||||
RootBeanDefinition httpScif = new RootBeanDefinition(HttpSessionContextIntegrationFilter.class);
|
||||
|
||||
registerFilterChainProxy(parserContext, filterChainMap, matcher, source);
|
||||
|
||||
parseInterceptUrlsForChannelSecurityAndFilterChain(interceptUrlElts, filterChainMap, channelRequestMap,
|
||||
convertPathsToLowerCase, parserContext);
|
||||
BeanDefinition portMapper = new PortMappingsBeanDefinitionParser().parse(
|
||||
DomUtils.getChildElementByTagName(element, Elements.PORT_MAPPINGS), parserContext);
|
||||
registry.registerBeanDefinition(BeanIds.PORT_MAPPER, portMapper);
|
||||
|
||||
registerHttpSessionIntegrationFilter(element, parserContext);
|
||||
RuntimeBeanReference portMapperRef = new RuntimeBeanReference(BeanIds.PORT_MAPPER);
|
||||
|
||||
String createSession = element.getAttribute(ATT_CREATE_SESSION);
|
||||
if (OPT_CREATE_SESSION_ALWAYS.equals(createSession)) {
|
||||
httpScif.getPropertyValues().addPropertyValue("allowSessionCreation", Boolean.TRUE);
|
||||
httpScif.getPropertyValues().addPropertyValue("forceEagerSessionCreation", Boolean.TRUE);
|
||||
} else if (OPT_CREATE_SESSION_NEVER.equals(createSession)) {
|
||||
httpScif.getPropertyValues().addPropertyValue("allowSessionCreation", Boolean.FALSE);
|
||||
httpScif.getPropertyValues().addPropertyValue("forceEagerSessionCreation", Boolean.FALSE);
|
||||
} else {
|
||||
createSession = DEF_CREATE_SESSION_IF_REQUIRED;
|
||||
httpScif.getPropertyValues().addPropertyValue("allowSessionCreation", Boolean.TRUE);
|
||||
httpScif.getPropertyValues().addPropertyValue("forceEagerSessionCreation", Boolean.FALSE);
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder filterSecurityInterceptorBuilder
|
||||
= BeanDefinitionBuilder.rootBeanDefinition(FilterSecurityInterceptor.class);
|
||||
|
||||
BeanDefinitionBuilder exceptionTranslationFilterBuilder
|
||||
= BeanDefinitionBuilder.rootBeanDefinition(ExceptionTranslationFilter.class);
|
||||
|
||||
registerServletApiFilter(element, parserContext);
|
||||
|
||||
// Set up the access manager reference for http
|
||||
String accessDeniedPage = element.getAttribute(ATT_ACCESS_DENIED_PAGE);
|
||||
if (StringUtils.hasText(accessDeniedPage)) {
|
||||
AccessDeniedHandlerImpl accessDeniedHandler = new AccessDeniedHandlerImpl();
|
||||
accessDeniedHandler.setErrorPage(accessDeniedPage);
|
||||
exceptionTranslationFilterBuilder.addPropertyValue("accessDeniedHandler", accessDeniedHandler);
|
||||
}
|
||||
|
||||
|
||||
Map filterChainMap = new LinkedHashMap();
|
||||
|
||||
UrlMatcher matcher = createUrlMatcher(element);
|
||||
|
||||
filterChainProxy.getPropertyValues().addPropertyValue("matcher", matcher);
|
||||
|
||||
// Add servlet-api integration filter if required
|
||||
String provideServletApi = element.getAttribute(ATT_SERVLET_API_PROVISION);
|
||||
if (!StringUtils.hasText(provideServletApi)) {
|
||||
provideServletApi = DEF_SERVLET_API_PROVISION;
|
||||
}
|
||||
|
||||
if ("true".equals(provideServletApi)) {
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.SECURITY_CONTEXT_HOLDER_AWARE_REQUEST_FILTER,
|
||||
new RootBeanDefinition(SecurityContextHolderAwareRequestFilter.class));
|
||||
}
|
||||
|
||||
filterChainProxy.getPropertyValues().addPropertyValue("filterChainMap", filterChainMap);
|
||||
|
||||
// Set up the access manager and authentication manager references for http
|
||||
String accessManagerId = element.getAttribute(ATT_ACCESS_MGR);
|
||||
|
||||
if (!StringUtils.hasText(accessManagerId)) {
|
||||
ConfigUtils.registerDefaultAccessManagerIfNecessary(parserContext);
|
||||
accessManagerId = BeanIds.ACCESS_MANAGER;
|
||||
}
|
||||
|
||||
filterSecurityInterceptorBuilder.addPropertyValue("accessDecisionManager",
|
||||
new RuntimeBeanReference(accessManagerId));
|
||||
filterSecurityInterceptorBuilder.addPropertyValue("authenticationManager",
|
||||
ConfigUtils.registerProviderManagerIfNecessary(parserContext));
|
||||
|
||||
// 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);
|
||||
if ("true".equals(element.getAttribute(ATT_ONCE_PER_REQUEST))) {
|
||||
filterSecurityInterceptorBuilder.addPropertyValue("observeOncePerRequest", Boolean.TRUE);
|
||||
}
|
||||
|
||||
registerExceptionTranslationFilter(element, parserContext);
|
||||
// SEC-501 - should paths stored in request maps be converted to lower case
|
||||
// true if Ant path and using lower case
|
||||
boolean convertPathsToLowerCase = (matcher instanceof AntUrlPathMatcher) && matcher.requiresLowerCaseUrl();
|
||||
|
||||
LinkedHashMap channelRequestMap = new LinkedHashMap();
|
||||
LinkedHashMap filterInvocationDefinitionMap = new LinkedHashMap();
|
||||
|
||||
List interceptUrlElts = DomUtils.getChildElementsByTagName(element, "intercept-url");
|
||||
parseInterceptUrlsForChannelSecurityAndFilterChain(interceptUrlElts, filterChainMap, channelRequestMap,
|
||||
convertPathsToLowerCase, parserContext);
|
||||
parseInterceptUrlsForFilterInvocationRequestMap(interceptUrlElts, filterInvocationDefinitionMap,
|
||||
convertPathsToLowerCase, parserContext);
|
||||
|
||||
DefaultFilterInvocationDefinitionSource interceptorFilterInvDefSource =
|
||||
new DefaultFilterInvocationDefinitionSource(matcher, filterInvocationDefinitionMap);
|
||||
DefaultFilterInvocationDefinitionSource channelFilterInvDefSource =
|
||||
new DefaultFilterInvocationDefinitionSource(matcher, channelRequestMap);
|
||||
|
||||
filterSecurityInterceptorBuilder.addPropertyValue("objectDefinitionSource", interceptorFilterInvDefSource);
|
||||
|
||||
|
||||
// Check if we need to register the channel processing beans
|
||||
if (channelRequestMap.size() > 0) {
|
||||
// At least one channel requirement has been specified
|
||||
registerChannelProcessingBeans(parserContext, matcher, channelRequestMap);
|
||||
}
|
||||
|
||||
registerFilterSecurityInterceptor(element, parserContext, matcher, accessManagerId,
|
||||
parseInterceptUrlsForFilterInvocationRequestMap(interceptUrlElts, convertPathsToLowerCase, parserContext));
|
||||
RootBeanDefinition channelFilter = new RootBeanDefinition(ChannelProcessingFilter.class);
|
||||
channelFilter.getPropertyValues().addPropertyValue("channelDecisionManager",
|
||||
new RuntimeBeanReference(BeanIds.CHANNEL_DECISION_MANAGER));
|
||||
|
||||
boolean sessionControlEnabled = registerConcurrentSessionControlBeansIfRequired(element, parserContext);
|
||||
channelFilter.getPropertyValues().addPropertyValue("filterInvocationDefinitionSource",
|
||||
channelFilterInvDefSource);
|
||||
RootBeanDefinition channelDecisionManager = new RootBeanDefinition(ChannelDecisionManagerImpl.class);
|
||||
ManagedList channelProcessors = new ManagedList(3);
|
||||
RootBeanDefinition secureChannelProcessor = new RootBeanDefinition(SecureChannelProcessor.class);
|
||||
RootBeanDefinition retryWithHttp = new RootBeanDefinition(RetryWithHttpEntryPoint.class);
|
||||
RootBeanDefinition retryWithHttps = new RootBeanDefinition(RetryWithHttpsEntryPoint.class);
|
||||
retryWithHttp.getPropertyValues().addPropertyValue("portMapper", portMapperRef);
|
||||
retryWithHttps.getPropertyValues().addPropertyValue("portMapper", portMapperRef);
|
||||
secureChannelProcessor.getPropertyValues().addPropertyValue("entryPoint", retryWithHttps);
|
||||
RootBeanDefinition inSecureChannelProcessor = new RootBeanDefinition(InsecureChannelProcessor.class);
|
||||
inSecureChannelProcessor.getPropertyValues().addPropertyValue("entryPoint", retryWithHttp);
|
||||
channelProcessors.add(secureChannelProcessor);
|
||||
channelProcessors.add(inSecureChannelProcessor);
|
||||
channelDecisionManager.getPropertyValues().addPropertyValue("channelProcessors", channelProcessors);
|
||||
|
||||
registry.registerBeanDefinition(BeanIds.CHANNEL_PROCESSING_FILTER, channelFilter);
|
||||
registry.registerBeanDefinition(BeanIds.CHANNEL_DECISION_MANAGER, channelDecisionManager);
|
||||
}
|
||||
|
||||
Element sessionControlElt = DomUtils.getChildElementByTagName(element, Elements.CONCURRENT_SESSIONS);
|
||||
if (sessionControlElt != null) {
|
||||
new ConcurrentSessionsBeanDefinitionParser().parse(sessionControlElt, parserContext);
|
||||
logger.info("Concurrent session filter in use, setting 'forceEagerSessionCreation' to true");
|
||||
httpScif.getPropertyValues().addPropertyValue("forceEagerSessionCreation", Boolean.TRUE);
|
||||
}
|
||||
|
||||
String sessionFixationAttribute = element.getAttribute(ATT_SESSION_FIXATION_PROTECTION);
|
||||
|
||||
registerSessionFixationProtectionFilter(parserContext, element.getAttribute(ATT_SESSION_FIXATION_PROTECTION),
|
||||
sessionControlEnabled);
|
||||
if(!StringUtils.hasText(sessionFixationAttribute)) {
|
||||
sessionFixationAttribute = OPT_SESSION_FIXATION_MIGRATE_SESSION;
|
||||
}
|
||||
|
||||
if (!sessionFixationAttribute.equals(OPT_SESSION_FIXATION_NO_PROTECTION)) {
|
||||
BeanDefinitionBuilder sessionFixationFilter =
|
||||
BeanDefinitionBuilder.rootBeanDefinition(SessionFixationProtectionFilter.class);
|
||||
sessionFixationFilter.addPropertyValue("migrateSessionAttributes",
|
||||
Boolean.valueOf(sessionFixationAttribute.equals(OPT_SESSION_FIXATION_MIGRATE_SESSION)));
|
||||
if (sessionControlElt != null) {
|
||||
sessionFixationFilter.addPropertyReference("sessionRegistry", BeanIds.SESSION_REGISTRY);
|
||||
}
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.SESSION_FIXATION_PROTECTION_FILTER,
|
||||
sessionFixationFilter.getBeanDefinition());
|
||||
}
|
||||
|
||||
boolean autoConfig = false;
|
||||
if ("true".equals(element.getAttribute(ATT_AUTO_CONFIG))) {
|
||||
@@ -181,158 +278,26 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
new X509BeanDefinitionParser().parse(x509Elt, parserContext);
|
||||
}
|
||||
|
||||
registry.registerBeanDefinition(BeanIds.FILTER_CHAIN_PROXY, filterChainProxy);
|
||||
registry.registerAlias(BeanIds.FILTER_CHAIN_PROXY, BeanIds.SPRING_SECURITY_FILTER_CHAIN);
|
||||
registry.registerBeanDefinition(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER, httpScif);
|
||||
registry.registerBeanDefinition(BeanIds.EXCEPTION_TRANSLATION_FILTER, exceptionTranslationFilterBuilder.getBeanDefinition());
|
||||
registry.registerBeanDefinition(BeanIds.FILTER_SECURITY_INTERCEPTOR, filterSecurityInterceptorBuilder.getBeanDefinition());
|
||||
|
||||
// Register the post processor which will tie up the loose ends in the configuration once the app context has been created and all beans are available.
|
||||
RootBeanDefinition postProcessor = new RootBeanDefinition(HttpSecurityConfigPostProcessor.class);
|
||||
postProcessor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
registry.registerBeanDefinition(BeanIds.HTTP_POST_PROCESSOR, postProcessor);
|
||||
|
||||
|
||||
// Post processor specifically to assemble and order the filter chain immediately before the FilterChainProxy is initialized.
|
||||
RootBeanDefinition filterChainPostProcessor = new RootBeanDefinition(FilterChainProxyPostProcessor.class);
|
||||
filterChainPostProcessor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
registry.registerBeanDefinition(BeanIds.FILTER_CHAIN_POST_PROCESSOR, filterChainPostProcessor);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
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("filterChainMap", filterChainMap);
|
||||
pc.getRegistry().registerBeanDefinition(BeanIds.FILTER_CHAIN_PROXY, filterChainProxy);
|
||||
pc.getRegistry().registerAlias(BeanIds.FILTER_CHAIN_PROXY, BeanIds.SPRING_SECURITY_FILTER_CHAIN);
|
||||
}
|
||||
|
||||
private void registerHttpSessionIntegrationFilter(Element element, ParserContext pc) {
|
||||
RootBeanDefinition httpScif = new RootBeanDefinition(HttpSessionContextIntegrationFilter.class);
|
||||
|
||||
String createSession = element.getAttribute(ATT_CREATE_SESSION);
|
||||
if (OPT_CREATE_SESSION_ALWAYS.equals(createSession)) {
|
||||
httpScif.getPropertyValues().addPropertyValue("allowSessionCreation", Boolean.TRUE);
|
||||
httpScif.getPropertyValues().addPropertyValue("forceEagerSessionCreation", Boolean.TRUE);
|
||||
} else if (OPT_CREATE_SESSION_NEVER.equals(createSession)) {
|
||||
httpScif.getPropertyValues().addPropertyValue("allowSessionCreation", Boolean.FALSE);
|
||||
httpScif.getPropertyValues().addPropertyValue("forceEagerSessionCreation", Boolean.FALSE);
|
||||
} else {
|
||||
createSession = DEF_CREATE_SESSION_IF_REQUIRED;
|
||||
httpScif.getPropertyValues().addPropertyValue("allowSessionCreation", Boolean.TRUE);
|
||||
httpScif.getPropertyValues().addPropertyValue("forceEagerSessionCreation", Boolean.FALSE);
|
||||
}
|
||||
|
||||
pc.getRegistry().registerBeanDefinition(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER, httpScif);
|
||||
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER));
|
||||
}
|
||||
|
||||
// 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)) {
|
||||
provideServletApi = DEF_SERVLET_API_PROVISION;
|
||||
}
|
||||
|
||||
if ("true".equals(provideServletApi)) {
|
||||
pc.getRegistry().registerBeanDefinition(BeanIds.SECURITY_CONTEXT_HOLDER_AWARE_REQUEST_FILTER,
|
||||
new RootBeanDefinition(SecurityContextHolderAwareRequestFilter.class));
|
||||
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);
|
||||
sessionIntegrationFilter.getPropertyValues().addPropertyValue("forceEagerSessionCreation", Boolean.TRUE);
|
||||
return true;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (StringUtils.hasText(accessDeniedPage)) {
|
||||
AccessDeniedHandlerImpl accessDeniedHandler = new AccessDeniedHandlerImpl();
|
||||
accessDeniedHandler.setErrorPage(accessDeniedPage);
|
||||
exceptionTranslationFilterBuilder.addPropertyValue("accessDeniedHandler", accessDeniedHandler);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
builder.addPropertyValue("objectDefinitionSource",
|
||||
new DefaultFilterInvocationDefinitionSource(matcher, filterInvocationDefinitionMap));
|
||||
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",
|
||||
new RuntimeBeanReference(BeanIds.CHANNEL_DECISION_MANAGER));
|
||||
DefaultFilterInvocationDefinitionSource channelFilterInvDefSource =
|
||||
new DefaultFilterInvocationDefinitionSource(matcher, channelRequestMap);
|
||||
|
||||
|
||||
channelFilter.getPropertyValues().addPropertyValue("filterInvocationDefinitionSource",
|
||||
channelFilterInvDefSource);
|
||||
RootBeanDefinition channelDecisionManager = new RootBeanDefinition(ChannelDecisionManagerImpl.class);
|
||||
ManagedList channelProcessors = new ManagedList(3);
|
||||
RootBeanDefinition secureChannelProcessor = new RootBeanDefinition(SecureChannelProcessor.class);
|
||||
RootBeanDefinition retryWithHttp = new RootBeanDefinition(RetryWithHttpEntryPoint.class);
|
||||
RootBeanDefinition retryWithHttps = new RootBeanDefinition(RetryWithHttpsEntryPoint.class);
|
||||
RuntimeBeanReference portMapper = new RuntimeBeanReference(BeanIds.PORT_MAPPER);
|
||||
retryWithHttp.getPropertyValues().addPropertyValue("portMapper", portMapper);
|
||||
retryWithHttps.getPropertyValues().addPropertyValue("portMapper", portMapper);
|
||||
secureChannelProcessor.getPropertyValues().addPropertyValue("entryPoint", retryWithHttps);
|
||||
RootBeanDefinition inSecureChannelProcessor = new RootBeanDefinition(InsecureChannelProcessor.class);
|
||||
inSecureChannelProcessor.getPropertyValues().addPropertyValue("entryPoint", retryWithHttp);
|
||||
channelProcessors.add(secureChannelProcessor);
|
||||
channelProcessors.add(inSecureChannelProcessor);
|
||||
channelDecisionManager.getPropertyValues().addPropertyValue("channelProcessors", channelProcessors);
|
||||
|
||||
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.rootBeanDefinition(SessionFixationProtectionFilter.class);
|
||||
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,
|
||||
sessionFixationFilter.getBeanDefinition());
|
||||
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.SESSION_FIXATION_PROTECTION_FILTER));
|
||||
}
|
||||
}
|
||||
|
||||
private void parseBasicFormLoginAndOpenID(Element element, ParserContext pc, boolean autoConfig) {
|
||||
private void parseBasicFormLoginAndOpenID(Element element, ParserContext parserContext, boolean autoConfig) {
|
||||
RootBeanDefinition formLoginFilter = null;
|
||||
RootBeanDefinition formLoginEntryPoint = null;
|
||||
String formLoginPage = null;
|
||||
@@ -343,12 +308,12 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
String realm = element.getAttribute(ATT_REALM);
|
||||
if (!StringUtils.hasText(realm)) {
|
||||
realm = DEF_REALM;
|
||||
}
|
||||
}
|
||||
|
||||
Element basicAuthElt = DomUtils.getChildElementByTagName(element, Elements.BASIC_AUTH);
|
||||
if (basicAuthElt != null || autoConfig) {
|
||||
new BasicAuthenticationBeanDefinitionParser(realm).parse(basicAuthElt, pc);
|
||||
}
|
||||
new BasicAuthenticationBeanDefinitionParser(realm).parse(basicAuthElt, parserContext);
|
||||
}
|
||||
|
||||
Element formLoginElt = DomUtils.getChildElementByTagName(element, Elements.FORM_LOGIN);
|
||||
|
||||
@@ -356,7 +321,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_security_check",
|
||||
"org.springframework.security.ui.webapp.AuthenticationProcessingFilter");
|
||||
|
||||
parser.parse(formLoginElt, pc);
|
||||
parser.parse(formLoginElt, parserContext);
|
||||
formLoginFilter = parser.getFilterBean();
|
||||
formLoginEntryPoint = parser.getEntryPointBean();
|
||||
formLoginPage = parser.getLoginPage();
|
||||
@@ -368,7 +333,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_openid_security_check",
|
||||
"org.springframework.security.ui.openid.OpenIDAuthenticationProcessingFilter");
|
||||
|
||||
parser.parse(openIDLoginElt, pc);
|
||||
parser.parse(openIDLoginElt, parserContext);
|
||||
openIDFilter = parser.getFilterBean();
|
||||
openIDEntryPoint = parser.getEntryPointBean();
|
||||
openIDLoginPage = parser.getLoginPage();
|
||||
@@ -383,25 +348,23 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
}
|
||||
|
||||
BeanDefinition openIDProvider = openIDProviderBuilder.getBeanDefinition();
|
||||
ConfigUtils.getRegisteredProviders(pc).add(openIDProvider);
|
||||
ConfigUtils.getRegisteredProviders(parserContext).add(openIDProvider);
|
||||
|
||||
pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_PROVIDER, openIDProvider);
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_PROVIDER, openIDProvider);
|
||||
}
|
||||
|
||||
boolean needLoginPage = false;
|
||||
|
||||
if (formLoginFilter != null) {
|
||||
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);
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.FORM_LOGIN_FILTER, formLoginFilter);
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.FORM_LOGIN_ENTRY_POINT, formLoginEntryPoint);
|
||||
}
|
||||
|
||||
if (openIDFilter != null) {
|
||||
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);
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_FILTER, openIDFilter);
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_ENTRY_POINT, openIDEntryPoint);
|
||||
}
|
||||
|
||||
// If no login page has been defined, add in the default page generator.
|
||||
@@ -419,9 +382,8 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
loginPageFilter.addConstructorArg(new RuntimeBeanReference(BeanIds.OPEN_ID_FILTER));
|
||||
}
|
||||
|
||||
pc.getRegistry().registerBeanDefinition(BeanIds.DEFAULT_LOGIN_PAGE_GENERATING_FILTER,
|
||||
parserContext.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.
|
||||
@@ -429,39 +391,33 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
String customEntryPoint = element.getAttribute(ATT_ENTRY_POINT_REF);
|
||||
|
||||
if (StringUtils.hasText(customEntryPoint)) {
|
||||
pc.getRegistry().registerAlias(customEntryPoint, BeanIds.MAIN_ENTRY_POINT);
|
||||
parserContext.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);
|
||||
parserContext.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);
|
||||
parserContext.getRegistry().registerAlias(BeanIds.FORM_LOGIN_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise use OpenID if enabled
|
||||
// Otherwise use OpenID
|
||||
if (openIDFilter != null && formLoginFilter == null) {
|
||||
pc.getRegistry().registerAlias(BeanIds.OPEN_ID_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
|
||||
parserContext.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 ",
|
||||
pc.extractSource(element));
|
||||
parserContext.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 ",
|
||||
parserContext.extractSource(element));
|
||||
}
|
||||
|
||||
static UrlMatcher createUrlMatcher(Element element) {
|
||||
@@ -556,9 +512,9 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
}
|
||||
}
|
||||
|
||||
static LinkedHashMap parseInterceptUrlsForFilterInvocationRequestMap(List urlElts, boolean useLowerCasePaths, ParserContext parserContext) {
|
||||
LinkedHashMap filterInvocationDefinitionMap = new LinkedHashMap();
|
||||
|
||||
static void parseInterceptUrlsForFilterInvocationRequestMap(List urlElts, Map filterInvocationDefinitionMap,
|
||||
boolean useLowerCasePaths, ParserContext parserContext) {
|
||||
|
||||
Iterator urlEltsIterator = urlElts.iterator();
|
||||
ConfigAttributeEditor editor = new ConfigAttributeEditor();
|
||||
|
||||
@@ -588,8 +544,6 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
filterInvocationDefinitionMap.put(new RequestKey(path, method), editor.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return filterInvocationDefinitionMap;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
-9
@@ -4,6 +4,7 @@ import org.springframework.security.userdetails.jdbc.JdbcUserDetailsManager;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
@@ -16,30 +17,26 @@ public class JdbcUserServiceBeanDefinitionParser extends AbstractUserDetailsServ
|
||||
static final String ATT_USERS_BY_USERNAME_QUERY = "users-by-username-query";
|
||||
static final String ATT_AUTHORITIES_BY_USERNAME_QUERY = "authorities-by-username-query";
|
||||
static final String ATT_GROUP_AUTHORITIES_QUERY = "group-authorities-by-username-query";
|
||||
static final String ATT_ROLE_PREFIX = "role-prefix";
|
||||
|
||||
protected Class getBeanClass(Element element) {
|
||||
return JdbcUserDetailsManager.class;
|
||||
}
|
||||
|
||||
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
|
||||
// TODO: Set authenticationManager property
|
||||
String dataSource = element.getAttribute(ATT_DATA_SOURCE);
|
||||
|
||||
// An explicit dataSource was specified, so use it
|
||||
if (dataSource != null) {
|
||||
builder.addPropertyReference("dataSource", dataSource);
|
||||
} else {
|
||||
parserContext.getReaderContext().error(ATT_DATA_SOURCE + " is required for "
|
||||
+ Elements.JDBC_USER_SERVICE, parserContext.extractSource(element));
|
||||
// TODO: Have some sensible fallback if dataSource not specified, eg autowire
|
||||
throw new BeanDefinitionStoreException(ATT_DATA_SOURCE + " is required for "
|
||||
+ Elements.JDBC_USER_SERVICE );
|
||||
}
|
||||
|
||||
String usersQuery = element.getAttribute(ATT_USERS_BY_USERNAME_QUERY);
|
||||
String authoritiesQuery = element.getAttribute(ATT_AUTHORITIES_BY_USERNAME_QUERY);
|
||||
String groupAuthoritiesQuery = element.getAttribute(ATT_GROUP_AUTHORITIES_QUERY);
|
||||
String rolePrefix = element.getAttribute(ATT_ROLE_PREFIX);
|
||||
|
||||
if (StringUtils.hasText(rolePrefix)) {
|
||||
builder.addPropertyValue("rolePrefix", rolePrefix);
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(usersQuery)) {
|
||||
builder.addPropertyValue("usersByUsernameQuery", usersQuery);
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
package org.springframework.security.config;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.security.ldap.SpringSecurityContextSource;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.security.ldap.SpringSecurityContextSource;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
@@ -16,56 +17,35 @@ import org.springframework.security.ldap.SpringSecurityContextSource;
|
||||
*/
|
||||
class LdapConfigUtils {
|
||||
|
||||
/**
|
||||
* Checks for the presence of a ContextSource instance. Also supplies the standard reference to any
|
||||
* unconfigured <ldap-authentication-provider> or <ldap-user-service> beans. This is
|
||||
* necessary in cases where the user has given the server a specific Id, but hasn't used
|
||||
* the server-ref attribute to link this to the other ldap definitions. See SEC-799.
|
||||
*/
|
||||
/** Checks for the presence of a ContextSource instance */
|
||||
private static class ContextSourceSettingPostProcessor implements BeanFactoryPostProcessor, Ordered {
|
||||
/** If set to true, a bean parser has indicated that the default context source name needs to be set */
|
||||
private boolean defaultNameRequired;
|
||||
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory bf) throws BeansException {
|
||||
String[] sources = bf.getBeanNamesForType(SpringSecurityContextSource.class);
|
||||
Map beans = bf.getBeansOfType(SpringSecurityContextSource.class);
|
||||
|
||||
if (sources.length == 0) {
|
||||
if (beans.size() == 0) {
|
||||
throw new SecurityConfigurationException("No SpringSecurityContextSource instances found. Have you " +
|
||||
"added an <" + Elements.LDAP_SERVER + " /> element to your application context?");
|
||||
}
|
||||
|
||||
if (!bf.containsBean(BeanIds.CONTEXT_SOURCE) && defaultNameRequired) {
|
||||
if (sources.length > 1) {
|
||||
throw new SecurityConfigurationException("More than one SpringSecurityContextSource instance found. " +
|
||||
"Please specify a specific server id using the 'server-ref' attribute when configuring your <" +
|
||||
Elements.LDAP_PROVIDER + "> " + "or <" + Elements.LDAP_USER_SERVICE + ">.");
|
||||
}
|
||||
|
||||
bf.registerAlias(sources[0], BeanIds.CONTEXT_SOURCE);
|
||||
}
|
||||
}
|
||||
|
||||
public void setDefaultNameRequired(boolean defaultNameRequired) {
|
||||
this.defaultNameRequired = defaultNameRequired;
|
||||
|
||||
// else if (beans.size() > 1) {
|
||||
// throw new SecurityConfigurationException("More than one SpringSecurityContextSource instance found. " +
|
||||
// "Please specify a specific server id when configuring your <" + Elements.LDAP_PROVIDER + "> " +
|
||||
// "or <" + Elements.LDAP_USER_SERVICE + ">.");
|
||||
// }
|
||||
}
|
||||
|
||||
public int getOrder() {
|
||||
return LOWEST_PRECEDENCE;
|
||||
}
|
||||
}
|
||||
|
||||
static void registerPostProcessorIfNecessary(BeanDefinitionRegistry registry, boolean defaultNameRequired) {
|
||||
|
||||
static void registerPostProcessorIfNecessary(BeanDefinitionRegistry registry) {
|
||||
if (registry.containsBeanDefinition(BeanIds.CONTEXT_SOURCE_SETTING_POST_PROCESSOR)) {
|
||||
if (defaultNameRequired) {
|
||||
BeanDefinition bd = registry.getBeanDefinition(BeanIds.CONTEXT_SOURCE_SETTING_POST_PROCESSOR);
|
||||
bd.getPropertyValues().addPropertyValue("defaultNameRequired", Boolean.valueOf(defaultNameRequired));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
BeanDefinition bd = new RootBeanDefinition(ContextSourceSettingPostProcessor.class);
|
||||
registry.registerBeanDefinition(BeanIds.CONTEXT_SOURCE_SETTING_POST_PROCESSOR, bd);
|
||||
bd.getPropertyValues().addPropertyValue("defaultNameRequired", Boolean.valueOf(defaultNameRequired));
|
||||
registry.registerBeanDefinition(BeanIds.CONTEXT_SOURCE_SETTING_POST_PROCESSOR,
|
||||
new RootBeanDefinition(ContextSourceSettingPostProcessor.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
-16
@@ -27,8 +27,7 @@ public class LdapProviderBeanDefinitionParser implements BeanDefinitionParser {
|
||||
private Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private static final String ATT_USER_DN_PATTERN = "user-dn-pattern";
|
||||
private static final String ATT_USER_PASSWORD = "password-attribute";
|
||||
private static final String ATT_HASH = PasswordEncoderParser.ATT_HASH;
|
||||
private static final String ATT_USER_PASSWORD= "password-attribute";
|
||||
|
||||
private static final String DEF_USER_SEARCH_FILTER="uid={0}";
|
||||
|
||||
@@ -52,9 +51,8 @@ public class LdapProviderBeanDefinitionParser implements BeanDefinitionParser {
|
||||
searchBean.getConstructorArgumentValues().addIndexedArgumentValue(2, contextSource);
|
||||
}
|
||||
|
||||
RootBeanDefinition authenticator = new RootBeanDefinition(BindAuthenticator.class);
|
||||
RootBeanDefinition authenticator = new RootBeanDefinition(BindAuthenticator.class);
|
||||
Element passwordCompareElt = DomUtils.getChildElementByTagName(elt, Elements.LDAP_PASSWORD_COMPARE);
|
||||
|
||||
if (passwordCompareElt != null) {
|
||||
authenticator = new RootBeanDefinition(PasswordComparisonAuthenticator.class);
|
||||
|
||||
@@ -64,24 +62,16 @@ public class LdapProviderBeanDefinitionParser implements BeanDefinitionParser {
|
||||
}
|
||||
|
||||
Element passwordEncoderElement = DomUtils.getChildElementByTagName(passwordCompareElt, Elements.PASSWORD_ENCODER);
|
||||
String hash = passwordCompareElt.getAttribute(ATT_HASH);
|
||||
|
||||
if (passwordEncoderElement != null) {
|
||||
if (StringUtils.hasText(hash)) {
|
||||
parserContext.getReaderContext().warning("Attribute 'hash' cannot be used with 'password-encoder' and " +
|
||||
"will be ignored.", parserContext.extractSource(elt));
|
||||
}
|
||||
PasswordEncoderParser pep = new PasswordEncoderParser(passwordEncoderElement, parserContext);
|
||||
authenticator.getPropertyValues().addPropertyValue("passwordEncoder", pep.getPasswordEncoder());
|
||||
|
||||
if (pep.getSaltSource() != null) {
|
||||
parserContext.getReaderContext().warning("Salt source information isn't valid when used with LDAP", passwordEncoderElement);
|
||||
}
|
||||
} else if (StringUtils.hasText(hash)) {
|
||||
Class encoderClass = (Class) PasswordEncoderParser.ENCODER_CLASSES.get(hash);
|
||||
authenticator.getPropertyValues().addPropertyValue("passwordEncoder", new RootBeanDefinition(encoderClass));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
authenticator.getConstructorArgumentValues().addGenericArgumentValue(contextSource);
|
||||
authenticator.getPropertyValues().addPropertyValue("userDnPatterns", userDnPatternArray);
|
||||
@@ -93,9 +83,9 @@ public class LdapProviderBeanDefinitionParser implements BeanDefinitionParser {
|
||||
RootBeanDefinition ldapProvider = new RootBeanDefinition(LdapAuthenticationProvider.class);
|
||||
ldapProvider.getConstructorArgumentValues().addGenericArgumentValue(authenticator);
|
||||
ldapProvider.getConstructorArgumentValues().addGenericArgumentValue(LdapUserServiceBeanDefinitionParser.parseAuthoritiesPopulator(elt, parserContext));
|
||||
ldapProvider.getPropertyValues().addPropertyValue("userDetailsContextMapper",
|
||||
LdapUserServiceBeanDefinitionParser.parseUserDetailsClass(elt, parserContext));
|
||||
|
||||
|
||||
LdapConfigUtils.registerPostProcessorIfNecessary(parserContext.getRegistry());
|
||||
|
||||
ConfigUtils.getRegisteredProviders(parserContext).add(ldapProvider);
|
||||
|
||||
return null;
|
||||
|
||||
+17
-46
@@ -1,9 +1,6 @@
|
||||
package org.springframework.security.config;
|
||||
|
||||
import org.springframework.security.userdetails.ldap.InetOrgPersonContextMapper;
|
||||
import org.springframework.security.userdetails.ldap.LdapUserDetailsMapper;
|
||||
import org.springframework.security.userdetails.ldap.LdapUserDetailsService;
|
||||
import org.springframework.security.userdetails.ldap.PersonContextMapper;
|
||||
import org.springframework.security.ldap.search.FilterBasedLdapUserSearch;
|
||||
import org.springframework.security.ldap.populator.DefaultLdapAuthoritiesPopulator;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
@@ -20,7 +17,7 @@ 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 = "";
|
||||
@@ -30,11 +27,6 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ
|
||||
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 = "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";
|
||||
|
||||
protected Class getBeanClass(Element element) {
|
||||
return LdapUserDetailsService.class;
|
||||
@@ -48,7 +40,8 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ
|
||||
|
||||
builder.addConstructorArg(parseSearchBean(elt, parserContext));
|
||||
builder.addConstructorArg(parseAuthoritiesPopulator(elt, parserContext));
|
||||
builder.addPropertyValue("userDetailsMapper", parseUserDetailsClass(elt, parserContext));
|
||||
|
||||
LdapConfigUtils.registerPostProcessorIfNecessary(parserContext.getRegistry());
|
||||
}
|
||||
|
||||
static RootBeanDefinition parseSearchBean(Element elt, ParserContext parserContext) {
|
||||
@@ -68,48 +61,33 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ
|
||||
return null;
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder searchBuilder = BeanDefinitionBuilder.rootBeanDefinition(FilterBasedLdapUserSearch.class);
|
||||
searchBuilder.setSource(source);
|
||||
searchBuilder.addConstructorArg(userSearchBase);
|
||||
searchBuilder.addConstructorArg(userSearchFilter);
|
||||
searchBuilder.addConstructorArg(parseServerReference(elt, parserContext));
|
||||
RootBeanDefinition search = new RootBeanDefinition(FilterBasedLdapUserSearch.class);
|
||||
search.setSource(source);
|
||||
search.getConstructorArgumentValues().addIndexedArgumentValue(0, userSearchBase);
|
||||
search.getConstructorArgumentValues().addIndexedArgumentValue(1, userSearchFilter);
|
||||
search.getConstructorArgumentValues().addIndexedArgumentValue(2, parseServerReference(elt, parserContext));
|
||||
|
||||
return (RootBeanDefinition) searchBuilder.getBeanDefinition();
|
||||
return search;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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(PersonContextMapper.class);
|
||||
} else if (OPT_INETORGPERSON.equals(userDetailsClass)) {
|
||||
return new RootBeanDefinition(InetOrgPersonContextMapper.class);
|
||||
}
|
||||
return new RootBeanDefinition(LdapUserDetailsMapper.class);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -118,23 +96,16 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ
|
||||
groupSearchBase = DEF_GROUP_SEARCH_BASE;
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder populator = BeanDefinitionBuilder.rootBeanDefinition(DefaultLdapAuthoritiesPopulator.class);
|
||||
RootBeanDefinition populator = new RootBeanDefinition(DefaultLdapAuthoritiesPopulator.class);
|
||||
populator.setSource(parserContext.extractSource(elt));
|
||||
populator.addConstructorArg(parseServerReference(elt, parserContext));
|
||||
populator.addConstructorArg(groupSearchBase);
|
||||
populator.addPropertyValue("groupSearchFilter", groupSearchFilter);
|
||||
|
||||
if (StringUtils.hasText(rolePrefix)) {
|
||||
if ("none".equals(rolePrefix)) {
|
||||
rolePrefix = "";
|
||||
}
|
||||
populator.addPropertyValue("rolePrefix", rolePrefix);
|
||||
}
|
||||
populator.getConstructorArgumentValues().addIndexedArgumentValue(0, parseServerReference(elt, parserContext));
|
||||
populator.getConstructorArgumentValues().addIndexedArgumentValue(1, groupSearchBase);
|
||||
populator.getPropertyValues().addPropertyValue("groupSearchFilter", groupSearchFilter);
|
||||
|
||||
if (StringUtils.hasLength(groupRoleAttribute)) {
|
||||
populator.addPropertyValue("groupRoleAttribute", groupRoleAttribute);
|
||||
populator.getPropertyValues().addPropertyValue("groupRoleAttribute", groupRoleAttribute);
|
||||
}
|
||||
|
||||
return (RootBeanDefinition) populator.getBeanDefinition();
|
||||
return populator;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-8
@@ -31,18 +31,15 @@ public class LogoutBeanDefinitionParser implements BeanDefinitionParser {
|
||||
String logoutSuccessUrl = null;
|
||||
String invalidateSession = null;
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(LogoutFilter.class);
|
||||
|
||||
if (element != null) {
|
||||
Object source = parserContext.extractSource(element);
|
||||
builder.setSource(source);
|
||||
logoutUrl = element.getAttribute(ATT_LOGOUT_URL);
|
||||
ConfigUtils.validateHttpRedirect(logoutUrl, parserContext, source);
|
||||
logoutSuccessUrl = element.getAttribute(ATT_LOGOUT_SUCCESS_URL);
|
||||
ConfigUtils.validateHttpRedirect(logoutSuccessUrl, parserContext, source);
|
||||
invalidateSession = element.getAttribute(ATT_INVALIDATE_SESSION);
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(LogoutFilter.class);
|
||||
builder.setSource(parserContext.extractSource(element));
|
||||
|
||||
if (!StringUtils.hasText(logoutUrl)) {
|
||||
logoutUrl = DEF_LOGOUT_URL;
|
||||
}
|
||||
@@ -73,8 +70,7 @@ public class LogoutBeanDefinitionParser implements BeanDefinitionParser {
|
||||
builder.addConstructorArg(handlers);
|
||||
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.LOGOUT_FILTER, builder.getBeanDefinition());
|
||||
ConfigUtils.addHttpFilter(parserContext, new RuntimeBeanReference(BeanIds.LOGOUT_FILTER));
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
-48
@@ -1,48 +0,0 @@
|
||||
package org.springframework.security.config;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.security.AfterInvocationManager;
|
||||
import org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor;
|
||||
|
||||
/**
|
||||
* BeanPostProcessor which sets the AfterInvocationManager on the default MethodSecurityInterceptor,
|
||||
* if one has been configured.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
*
|
||||
*/
|
||||
public class MethodSecurityInterceptorPostProcessor implements BeanPostProcessor, BeanFactoryAware{
|
||||
private Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
if(!beanName.equals(BeanIds.METHOD_SECURITY_INTERCEPTOR)) {
|
||||
return bean;
|
||||
}
|
||||
|
||||
MethodSecurityInterceptor interceptor = (MethodSecurityInterceptor) bean;
|
||||
|
||||
if (beanFactory.containsBean(BeanIds.AFTER_INVOCATION_MANAGER)) {
|
||||
logger.debug("Setting AfterInvocationManaer on MethodSecurityInterceptor");
|
||||
interceptor.setAfterInvocationManager((AfterInvocationManager)
|
||||
beanFactory.getBean(BeanIds.AFTER_INVOCATION_MANAGER));
|
||||
}
|
||||
|
||||
return bean;
|
||||
}
|
||||
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) {
|
||||
return bean;
|
||||
}
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
}
|
||||
+6
-15
@@ -9,8 +9,8 @@ import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionDecorator;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
@@ -22,8 +22,8 @@ import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* Replaces a Spring bean of type "Filter" with a wrapper class which implements the <tt>Ordered</tt>
|
||||
* interface. This allows user to add their own filter 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.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
@@ -39,17 +39,16 @@ public class OrderedFilterBeanDefinitionDecorator implements BeanDefinitionDecor
|
||||
Element elt = (Element)node;
|
||||
String order = getOrder(elt, parserContext);
|
||||
|
||||
BeanDefinition filter = holder.getBeanDefinition();
|
||||
BeanDefinitionBuilder wrapper = BeanDefinitionBuilder.rootBeanDefinition("org.springframework.security.config.OrderedFilterBeanDefinitionDecorator$OrderedFilterDecorator");
|
||||
wrapper.addConstructorArg(holder.getBeanName());
|
||||
wrapper.addConstructorArg(new RuntimeBeanReference(holder.getBeanName()));
|
||||
wrapper.addConstructorArg(filter);
|
||||
|
||||
if (StringUtils.hasText(order)) {
|
||||
wrapper.addPropertyValue("order", order);
|
||||
}
|
||||
|
||||
ConfigUtils.addHttpFilter(parserContext, wrapper.getBeanDefinition());
|
||||
|
||||
return holder;
|
||||
return new BeanDefinitionHolder(wrapper.getBeanDefinition(), holder.getBeanName());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -120,13 +119,5 @@ public class OrderedFilterBeanDefinitionDecorator implements BeanDefinitionDecor
|
||||
public String getBeanName() {
|
||||
return beanName;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "OrderedFilterDecorator[ delegate=" + delegate + "; order=" + getOrder() + "]";
|
||||
}
|
||||
|
||||
Filter getDelegate() {
|
||||
return delegate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-1
@@ -103,7 +103,6 @@ public class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_SERVICES, services);
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_FILTER, filter);
|
||||
ConfigUtils.addHttpFilter(parserContext, new RuntimeBeanReference(BeanIds.REMEMBER_ME_FILTER));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,5 @@ public class SecurityNamespaceHandler extends NamespaceHandlerSupport {
|
||||
registerBeanDefinitionDecorator(Elements.FILTER_CHAIN_MAP, new FilterChainMapBeanDefinitionDecorator());
|
||||
registerBeanDefinitionDecorator(Elements.CUSTOM_FILTER, new OrderedFilterBeanDefinitionDecorator());
|
||||
registerBeanDefinitionDecorator(Elements.CUSTOM_AUTH_PROVIDER, new CustomAuthenticationProviderBeanDefinitionDecorator());
|
||||
registerBeanDefinitionDecorator(Elements.CUSTOM_AFTER_INVOCATION_PROVIDER, new CustomAfterInvocationProviderBeanDefinitionDecorator());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,6 @@ public class X509BeanDefinitionParser implements BeanDefinitionParser {
|
||||
filterBuilder.addPropertyValue("authenticationManager", new RuntimeBeanReference(BeanIds.AUTHENTICATION_MANAGER));
|
||||
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.X509_FILTER, filterBuilder.getBeanDefinition());
|
||||
ConfigUtils.addHttpFilter(parserContext, new RuntimeBeanReference(BeanIds.X509_FILTER));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
+7
-21
@@ -28,8 +28,6 @@ import javax.servlet.http.HttpSession;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.security.AuthenticationTrustResolver;
|
||||
import org.springframework.security.AuthenticationTrustResolverImpl;
|
||||
import org.springframework.security.ui.SpringSecurityFilter;
|
||||
import org.springframework.security.ui.FilterChainOrder;
|
||||
|
||||
@@ -152,8 +150,6 @@ public class HttpSessionContextIntegrationFilter extends SpringSecurityFilter im
|
||||
* method.
|
||||
*/
|
||||
private boolean cloneFromHttpSession = false;
|
||||
|
||||
private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl();
|
||||
|
||||
public boolean isCloneFromHttpSession() {
|
||||
return cloneFromHttpSession;
|
||||
@@ -180,8 +176,6 @@ public class HttpSessionContextIntegrationFilter extends SpringSecurityFilter im
|
||||
throw new IllegalArgumentException(
|
||||
"If using forceEagerSessionCreation, you must set allowSessionCreation to also be true");
|
||||
}
|
||||
|
||||
contextObject = generateNewContext();
|
||||
}
|
||||
|
||||
public void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
|
||||
@@ -326,8 +320,7 @@ public class HttpSessionContextIntegrationFilter extends SpringSecurityFilter im
|
||||
|
||||
/**
|
||||
* Stores the supplied security context in the session (if available) and if it has changed since it was
|
||||
* set at the start of the request. If the AuthenticationTrustResolver identifies the current user as
|
||||
* anonymous, then the context will not be stored.
|
||||
* set at the start of the request.
|
||||
*
|
||||
* @param securityContext the context object obtained from the SecurityContextHolder after the request has
|
||||
* been processed by the filter chain. SecurityContextHolder.getContext() cannot be used to obtain
|
||||
@@ -363,7 +356,7 @@ public class HttpSessionContextIntegrationFilter extends SpringSecurityFilter im
|
||||
+ "(because the allowSessionCreation property is false) - SecurityContext thus not "
|
||||
+ "stored for next request");
|
||||
}
|
||||
} else if (!contextObject.equals(securityContext)) {
|
||||
} else if (!contextObject.equals(securityContext)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("HttpSession being created as SecurityContextHolder contents are non-default");
|
||||
}
|
||||
@@ -383,18 +376,11 @@ public class HttpSessionContextIntegrationFilter extends SpringSecurityFilter im
|
||||
// If HttpSession exists, store current SecurityContextHolder contents but only if
|
||||
// the SecurityContext has actually changed (see JIRA SEC-37)
|
||||
if (httpSession != null && securityContext.hashCode() != contextHashBeforeChainExecution) {
|
||||
// See SEC-766
|
||||
if (authenticationTrustResolver.isAnonymous(securityContext.getAuthentication())) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("SecurityContext contents are anonymous - context will not be stored in HttpSession. ");
|
||||
}
|
||||
} else {
|
||||
httpSession.setAttribute(SPRING_SECURITY_CONTEXT_KEY, securityContext);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("SecurityContext stored to HttpSession: '" + securityContext + "'");
|
||||
}
|
||||
}
|
||||
httpSession.setAttribute(SPRING_SECURITY_CONTEXT_KEY, securityContext);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("SecurityContext stored to HttpSession: '" + securityContext + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+9
-52
@@ -23,18 +23,13 @@ import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.aop.Pointcut;
|
||||
import org.springframework.aop.support.AbstractPointcutAdvisor;
|
||||
import org.springframework.aop.support.StaticMethodMatcherPointcut;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.security.intercept.method.MethodDefinitionSource;
|
||||
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
|
||||
* <code>MethodSecurityInterceptor</code> run and find out itself that it has no work to do.
|
||||
* public (ie non-secure) methods.<p>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
|
||||
* {@link org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator}, which makes
|
||||
@@ -47,47 +42,22 @@ import org.springframework.util.Assert;
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class MethodDefinitionSourceAdvisor extends AbstractPointcutAdvisor implements BeanFactoryAware {
|
||||
public class MethodDefinitionSourceAdvisor extends AbstractPointcutAdvisor {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private MethodDefinitionSource attributeSource;
|
||||
private MethodSecurityInterceptor interceptor;
|
||||
private Pointcut pointcut = new MethodDefinitionSourcePointcut();
|
||||
private BeanFactory beanFactory;
|
||||
private String adviceBeanName;
|
||||
private final Object adviceMonitor = new Object();
|
||||
private Pointcut pointcut;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
/**
|
||||
* @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");
|
||||
|
||||
this.interceptor = advice;
|
||||
|
||||
Assert.notNull(advice.getObjectDefinitionSource(), "Cannot construct a MethodDefinitionSourceAdvisor using a MethodSecurityInterceptor that has no ObjectDefinitionSource configured");
|
||||
|
||||
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
|
||||
* (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
|
||||
* 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;
|
||||
this.pointcut = new MethodDefinitionSourcePointcut();
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
@@ -97,20 +67,7 @@ public class MethodDefinitionSourceAdvisor extends AbstractPointcutAdvisor imple
|
||||
}
|
||||
|
||||
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;
|
||||
return interceptor;
|
||||
}
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
+1
-1
@@ -179,7 +179,7 @@ public class DefaultFilterInvocationDefinitionSource implements FilterInvocation
|
||||
* @return the <code>ConfigAttributeDefinition</code> that applies to the specified <code>FilterInvocation</code>
|
||||
* or null if no match is foud
|
||||
*/
|
||||
public ConfigAttributeDefinition lookupAttributes(String url, String method) {
|
||||
protected ConfigAttributeDefinition lookupAttributes(String url, String method) {
|
||||
if (stripQueryStringFromUrls) {
|
||||
// Strip anything after a question mark symbol, as per SEC-161. See also SEC-321
|
||||
int firstQuestionMarkIndex = url.indexOf("?");
|
||||
|
||||
@@ -3,7 +3,6 @@ package org.springframework.security.intercept.web;
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 2.0
|
||||
*/
|
||||
public class RequestKey {
|
||||
private String url;
|
||||
@@ -48,10 +47,10 @@ public class RequestKey {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (method == null) {
|
||||
return key.method == null;
|
||||
if (method == null && key.method != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return method.equals(key.method);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
package org.springframework.security.token;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* The default implementation of {@link Token}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @since 2.0.1
|
||||
*/
|
||||
public class DefaultToken implements Token {
|
||||
private String key;
|
||||
private long keyCreationTime;
|
||||
private String extendedInformation;
|
||||
|
||||
public DefaultToken(String key, long keyCreationTime, String extendedInformation) {
|
||||
Assert.hasText(key, "Key required");
|
||||
Assert.notNull(extendedInformation, "Extended information cannot be null");
|
||||
this.key = key;
|
||||
this.keyCreationTime = keyCreationTime;
|
||||
this.extendedInformation = extendedInformation;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public long getKeyCreationTime() {
|
||||
return keyCreationTime;
|
||||
}
|
||||
|
||||
public String getExtendedInformation() {
|
||||
return extendedInformation;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (obj != null && obj instanceof DefaultToken) {
|
||||
DefaultToken rhs = (DefaultToken) obj;
|
||||
return this.key.equals(rhs.key) && this.keyCreationTime == rhs.keyCreationTime && this.extendedInformation.equals(rhs.extendedInformation);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int code = 979;
|
||||
code = code * key.hashCode();
|
||||
code = code * new Long(keyCreationTime).hashCode();
|
||||
code = code * extendedInformation.hashCode();
|
||||
return code;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "DefaultToken[key=" + new String(key) + "; creation=" + new Date(keyCreationTime) + "; extended=" + extendedInformation + "]";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
-170
@@ -1,170 +0,0 @@
|
||||
package org.springframework.security.token;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.security.util.Sha512DigestUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Basic implementation of {@link TokenService} that is compatible with clusters and across machine restarts,
|
||||
* without requiring database persistence.
|
||||
*
|
||||
* <p>
|
||||
* Keys are produced in the format:
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Base64(creationTime + ":" + hex(pseudoRandomNumber) + ":" + extendedInformation + ":" +
|
||||
* Sha512Hex(creationTime + ":" + hex(pseudoRandomNumber) + ":" + extendedInformation + ":" + serverSecret) )
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* In the above, <code>creationTime</code>, <code>tokenKey</code> and <code>extendedInformation</code>
|
||||
* are equal to that stored in {@link Token}. The <code>Sha512Hex</code> includes the same payload,
|
||||
* plus a <code>serverSecret</code>.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* The <code>serverSecret</code> varies every millisecond. It relies on two static server-side secrets. The first
|
||||
* is a password, and the second is a server integer. Both of these must remain the same for any issued keys
|
||||
* to subsequently be recognised. The applicable <code>serverSecret</code> in any millisecond is computed by
|
||||
* <code>password</code> + ":" + (<code>creationTime</code> % <code>serverInteger</code>). This approach
|
||||
* further obfuscates the actual server secret and renders attempts to compute the server secret more
|
||||
* limited in usefulness (as any false tokens would be forced to have a <code>creationTime</code> equal
|
||||
* to the computed hash). Recall that framework features depending on token services should reject tokens
|
||||
* that are relatively old in any event.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* A further consideration of this class is the requirement for cryptographically strong pseudo-random numbers.
|
||||
* To this end, the use of {@link SecureRandomFactoryBean} is recommended to inject the property.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* This implementation uses UTF-8 encoding internally for string manipulation.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
*
|
||||
*/
|
||||
public class KeyBasedPersistenceTokenService implements TokenService, InitializingBean {
|
||||
private int pseudoRandomNumberBits = 256;
|
||||
private String serverSecret;
|
||||
private Integer serverInteger;
|
||||
private SecureRandom secureRandom;
|
||||
|
||||
public Token allocateToken(String extendedInformation) {
|
||||
Assert.notNull(extendedInformation, "Must provided non-null extendedInformation (but it can be empty)");
|
||||
long creationTime = new Date().getTime();
|
||||
String serverSecret = computeServerSecretApplicableAt(creationTime);
|
||||
String pseudoRandomNumber = generatePseudoRandomNumber();
|
||||
String content = new Long(creationTime).toString() + ":" + pseudoRandomNumber + ":" + extendedInformation;
|
||||
|
||||
// Compute key
|
||||
String sha512Hex = Sha512DigestUtils.shaHex(content + ":" + serverSecret);
|
||||
String keyPayload = content + ":" + sha512Hex;
|
||||
String key = convertToString(Base64.encodeBase64(convertToBytes(keyPayload)));
|
||||
|
||||
return new DefaultToken(key, creationTime, extendedInformation);
|
||||
}
|
||||
|
||||
public Token verifyToken(String key) {
|
||||
if (key == null || "".equals(key)) {
|
||||
return null;
|
||||
}
|
||||
String[] tokens = StringUtils.delimitedListToStringArray(convertToString(Base64.decodeBase64(convertToBytes(key))), ":");
|
||||
Assert.isTrue(tokens.length >= 4, "Expected 4 or more tokens but found " + tokens.length);
|
||||
|
||||
long creationTime;
|
||||
try {
|
||||
creationTime = Long.decode(tokens[0]).longValue();
|
||||
} catch (NumberFormatException nfe) {
|
||||
throw new IllegalArgumentException("Expected number but found " + tokens[0]);
|
||||
}
|
||||
|
||||
String serverSecret = computeServerSecretApplicableAt(creationTime);
|
||||
String pseudoRandomNumber = tokens[1];
|
||||
|
||||
// Permit extendedInfo to itself contain ":" characters
|
||||
StringBuffer extendedInfo = new StringBuffer();
|
||||
for (int i = 2; i < tokens.length-1; i++) {
|
||||
if (i > 2) {
|
||||
extendedInfo.append(":");
|
||||
}
|
||||
extendedInfo.append(tokens[i]);
|
||||
}
|
||||
|
||||
String sha1Hex = tokens[tokens.length-1];
|
||||
|
||||
// Verification
|
||||
String content = new Long(creationTime).toString() + ":" + pseudoRandomNumber + ":" + extendedInfo.toString();
|
||||
String expectedSha512Hex = Sha512DigestUtils.shaHex(content + ":" + serverSecret);
|
||||
Assert.isTrue(expectedSha512Hex.equals(sha1Hex), "Key verification failure");
|
||||
|
||||
return new DefaultToken(key, creationTime, extendedInfo.toString());
|
||||
}
|
||||
|
||||
private byte[] convertToBytes(String input) {
|
||||
try {
|
||||
return input.getBytes("UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private String convertToString(byte[] bytes) {
|
||||
try {
|
||||
return new String(bytes, "UTF-8");
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a pseduo random number (hex encoded)
|
||||
*/
|
||||
private String generatePseudoRandomNumber() {
|
||||
byte[] randomizedBits = new byte[pseudoRandomNumberBits];
|
||||
secureRandom.nextBytes(randomizedBits);
|
||||
return new String(Hex.encodeHex(randomizedBits));
|
||||
}
|
||||
|
||||
private String computeServerSecretApplicableAt(long time) {
|
||||
return serverSecret + ":" + new Long(time % serverInteger.intValue()).intValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param serverSecret the new secret, which can contain a ":" if desired (never being sent to the client)
|
||||
*/
|
||||
public void setServerSecret(String serverSecret) {
|
||||
this.serverSecret = serverSecret;
|
||||
}
|
||||
|
||||
public void setSecureRandom(SecureRandom secureRandom) {
|
||||
this.secureRandom = secureRandom;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param pseudoRandomNumberBits changes the number of bits issued (must be >= 0; defaults to 256)
|
||||
*/
|
||||
public void setPseudoRandomNumberBits(int pseudoRandomNumberBits) {
|
||||
Assert.isTrue(pseudoRandomNumberBits >= 0, "Must have a positive pseudo random number bit size");
|
||||
this.pseudoRandomNumberBits = pseudoRandomNumberBits;
|
||||
}
|
||||
|
||||
public void setServerInteger(Integer serverInteger) {
|
||||
this.serverInteger = serverInteger;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.hasText(serverSecret, "Server secret required");
|
||||
Assert.notNull(serverInteger, "Server integer required");
|
||||
Assert.notNull(secureRandom, "SecureRandom instance required");
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
package org.springframework.security.token;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
|
||||
/**
|
||||
* Creates a {@link SecureRandom} instance.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @since 2.0.1
|
||||
*
|
||||
*/
|
||||
public class SecureRandomFactoryBean implements FactoryBean {
|
||||
|
||||
private String algorithm = "SHA1PRNG";
|
||||
private Resource seed;
|
||||
|
||||
public Object getObject() throws Exception {
|
||||
SecureRandom rnd = SecureRandom.getInstance(algorithm);
|
||||
|
||||
if (seed != null) {
|
||||
// Seed specified, so use it
|
||||
byte[] seedBytes = FileCopyUtils.copyToByteArray(seed.getInputStream());
|
||||
rnd.setSeed(seedBytes);
|
||||
} else {
|
||||
// Request the next bytes, thus eagerly incurring the expense of default seeding
|
||||
rnd.nextBytes(new byte[1]);
|
||||
}
|
||||
|
||||
return rnd;
|
||||
}
|
||||
|
||||
public Class getObjectType() {
|
||||
return SecureRandom.class;
|
||||
}
|
||||
|
||||
public boolean isSingleton() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the Pseudo Random Number Generator (PRNG) algorithm to be nominated. Defaults to
|
||||
* SHA1PRNG.
|
||||
*
|
||||
* @param algorithm to use (mandatory)
|
||||
*/
|
||||
public void setAlgorithm(String algorithm) {
|
||||
Assert.hasText(algorithm, "Algorithm required");
|
||||
this.algorithm = algorithm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the user to specify a resource which will act as a seed for the {@link SecureRandom}
|
||||
* instance. Specifically, the resource will be read into an {@link InputStream} and those
|
||||
* bytes presented to the {@link SecureRandom#setSeed(byte[])} method. Note that this will
|
||||
* simply supplement, rather than replace, the existing seed. As such, it is always safe to
|
||||
* set a seed using this method (it never reduces randomness).
|
||||
*
|
||||
* @param seed to use, or <code>null</code> if no additional seeding is needed
|
||||
*/
|
||||
public void setSeed(Resource seed) {
|
||||
this.seed = seed;
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package org.springframework.security.token;
|
||||
|
||||
|
||||
/**
|
||||
* A token issued by {@link TokenService}.
|
||||
*
|
||||
* <p>
|
||||
* It is important that the keys assigned to tokens are sufficiently randomised and secured that
|
||||
* they can serve as identifying a unique user session. Implementations of {@link TokenService}
|
||||
* are free to use encryption or encoding strategies of their choice. It is strongly recommended that
|
||||
* keys are of sufficient length to balance safety against persistence cost. In relation to persistence
|
||||
* cost, it is strongly recommended that returned keys are small enough for encoding in a cookie.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @since 2.0.1
|
||||
*/
|
||||
public interface Token {
|
||||
|
||||
/**
|
||||
* Obtains the randomised, secure key assigned to this token. Presentation of this token to
|
||||
* {@link TokenService} will always return a <code>Token</code> that is equal to the original
|
||||
* <code>Token</code> issued for that key.
|
||||
*
|
||||
* @return a key with appropriate randomness and security.
|
||||
*/
|
||||
String getKey();
|
||||
|
||||
/**
|
||||
* The time the token key was initially created is available from this method. Note that a given
|
||||
* token must never have this creation time changed. If necessary, a new token can be
|
||||
* requested from the {@link TokenService} to replace the original token.
|
||||
*
|
||||
* @return the time this token key was created, in the same format as specified by {@link Date#getTime()).
|
||||
*/
|
||||
long getKeyCreationTime();
|
||||
|
||||
/**
|
||||
* Obtains the extended information associated within the token, which was presented when the token
|
||||
* was first created.
|
||||
*
|
||||
* @return the user-specified extended information, if any
|
||||
*/
|
||||
String getExtendedInformation();
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package org.springframework.security.token;
|
||||
|
||||
|
||||
/**
|
||||
* Provides a mechanism to allocate and rebuild secure, randomised tokens.
|
||||
*
|
||||
* <p>
|
||||
* Implementations are solely concern with issuing a new {@link Token} on demand. The
|
||||
* issued <code>Token</code> may contain user-specified extended information. The token also
|
||||
* contains a cryptographically strong, byte array-based key. This permits the token to be
|
||||
* used to identify a user session, if desired. The key can subsequently be re-presented
|
||||
* to the <code>TokenService</code> for verification and reconstruction of a <code>Token</code>
|
||||
* equal to the original <code>Token</code>.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Given the tightly-focused behaviour provided by this interface, it can serve as a building block
|
||||
* for more sophisticated token-based solutions. For example, authentication systems that depend on
|
||||
* stateless session keys. These could, for instance, place the username inside the user-specified
|
||||
* extended information associated with the key). It is important to recognise that we do not intend
|
||||
* for this interface to be expanded to provide such capabilities directly.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @since 2.0.1
|
||||
*
|
||||
*/
|
||||
public interface TokenService {
|
||||
/**
|
||||
* Forces the allocation of a new {@link Token}.
|
||||
*
|
||||
* @param the extended information desired in the token (cannot be <code>null</code>, but can be empty)
|
||||
* @return a new token that has not been issued previously, and is guaranteed to be recognised
|
||||
* by this implementation's {@link #verifyToken(String)} at any future time.
|
||||
*/
|
||||
Token allocateToken(String extendedInformation);
|
||||
|
||||
/**
|
||||
* Permits verification the <{@link Token#getKey()} was issued by this <code>TokenService</code> and
|
||||
* reconstructs the corresponding <code>Token</code>.
|
||||
*
|
||||
* @param key as obtained from {@link Token#getKey()} and created by this implementation
|
||||
* @return the token, or <code>null</code> if the token was not issued by this <code>TokenService</code>
|
||||
*/
|
||||
Token verifyToken(String key);
|
||||
}
|
||||
@@ -56,6 +56,6 @@ public abstract class SpringSecurityFilter implements Filter, Ordered {
|
||||
protected abstract void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException;
|
||||
|
||||
public String toString() {
|
||||
return getClass().getName() + "[ order=" + getOrder() + "; ]";
|
||||
return getClass() + "[ order=" + getOrder() + "; ]";
|
||||
}
|
||||
}
|
||||
+3
-7
@@ -23,7 +23,6 @@ import org.springframework.security.ui.rememberme.AbstractRememberMeServices;
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 2.0
|
||||
*/
|
||||
public class DefaultLoginPageGeneratingFilter extends SpringSecurityFilter {
|
||||
public static final String DEFAULT_LOGIN_PAGE_URL = "/spring_security_login";
|
||||
@@ -72,14 +71,11 @@ public class DefaultLoginPageGeneratingFilter extends SpringSecurityFilter {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||
if (isLoginUrlRequest(request)) {
|
||||
String loginPageHtml = generateLoginPageHtml(request);
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
response.setContentType("text/html");
|
||||
response.setContentLength(loginPageHtml.length());
|
||||
response.getOutputStream().print(loginPageHtml);
|
||||
response.getOutputStream().print(generateLoginPageHtml(request));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
+17
-188
@@ -28,121 +28,34 @@ import org.springframework.ldap.core.DirContextOperations;
|
||||
* @author Luke
|
||||
* @version $Id$
|
||||
*/
|
||||
public class InetOrgPerson extends Person {
|
||||
private String carLicense;
|
||||
// Person.cn
|
||||
private String destinationIndicator;
|
||||
private String departmentNumber;
|
||||
// Person.description
|
||||
private String displayName;
|
||||
private String employeeNumber;
|
||||
private String homePhone;
|
||||
private String homePostalAddress;
|
||||
private String initials;
|
||||
private String mail;
|
||||
private String mobile;
|
||||
private String o;
|
||||
private String ou;
|
||||
private String postalAddress;
|
||||
private String postalCode;
|
||||
private String roomNumber;
|
||||
private String street;
|
||||
// Person.sn
|
||||
// Person.telephoneNumber
|
||||
private String title;
|
||||
public class InetOrgPerson extends Person {
|
||||
private String mail;
|
||||
private String uid;
|
||||
private String employeeNumber;
|
||||
private String destinationIndicator;
|
||||
|
||||
public String getMail() {
|
||||
return mail;
|
||||
}
|
||||
|
||||
public String getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
public String getMail() {
|
||||
return mail;
|
||||
}
|
||||
|
||||
public String getEmployeeNumber() {
|
||||
return employeeNumber;
|
||||
}
|
||||
|
||||
public String getInitials() {
|
||||
return initials;
|
||||
}
|
||||
|
||||
public String getDestinationIndicator() {
|
||||
return destinationIndicator;
|
||||
}
|
||||
|
||||
public String getO() {
|
||||
return o;
|
||||
}
|
||||
|
||||
public String getOu() {
|
||||
return ou;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public String getCarLicense() {
|
||||
return carLicense;
|
||||
}
|
||||
|
||||
public String getDepartmentNumber() {
|
||||
return departmentNumber;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public String getHomePhone() {
|
||||
return homePhone;
|
||||
}
|
||||
|
||||
public String getRoomNumber() {
|
||||
return roomNumber;
|
||||
}
|
||||
|
||||
public String getHomePostalAddress() {
|
||||
return homePostalAddress;
|
||||
}
|
||||
|
||||
public String getMobile() {
|
||||
return mobile;
|
||||
}
|
||||
|
||||
public String getPostalAddress() {
|
||||
return postalAddress;
|
||||
}
|
||||
|
||||
public String getPostalCode() {
|
||||
return postalCode;
|
||||
}
|
||||
|
||||
public String getStreet() {
|
||||
return street;
|
||||
}
|
||||
|
||||
protected void populateContext(DirContextAdapter adapter) {
|
||||
protected void populateContext(DirContextAdapter adapter) {
|
||||
super.populateContext(adapter);
|
||||
adapter.setAttributeValue("carLicense", carLicense);
|
||||
adapter.setAttributeValue("departmentNumber", departmentNumber);
|
||||
adapter.setAttributeValue("destinationIndicator", destinationIndicator);
|
||||
adapter.setAttributeValue("displayName", displayName);
|
||||
adapter.setAttributeValue("employeeNumber", employeeNumber);
|
||||
adapter.setAttributeValue("homePhone", homePhone);
|
||||
adapter.setAttributeValue("homePostalAddress", homePostalAddress);
|
||||
adapter.setAttributeValue("initials", initials);
|
||||
adapter.setAttributeValue("mail", mail);
|
||||
adapter.setAttributeValue("mobile", mobile);
|
||||
adapter.setAttributeValue("postalAddress", postalAddress);
|
||||
adapter.setAttributeValue("postalCode", postalCode);
|
||||
adapter.setAttributeValue("ou", ou);
|
||||
adapter.setAttributeValue("o", o);
|
||||
adapter.setAttributeValue("roomNumber", roomNumber);
|
||||
adapter.setAttributeValue("street", street);
|
||||
adapter.setAttributeValue("uid", uid);
|
||||
adapter.setAttributeValue("employeeNumber", employeeNumber);
|
||||
adapter.setAttributeValue("destinationIndicator", destinationIndicator);
|
||||
adapter.setAttributeValues("objectclass", new String[] {"top", "person", "organizationalPerson", "inetOrgPerson"});
|
||||
}
|
||||
|
||||
@@ -152,46 +65,18 @@ public class InetOrgPerson extends Person {
|
||||
|
||||
public Essence(InetOrgPerson copyMe) {
|
||||
super(copyMe);
|
||||
setCarLicense(copyMe.getCarLicense());
|
||||
setDepartmentNumber(copyMe.getDepartmentNumber());
|
||||
setDestinationIndicator(copyMe.getDestinationIndicator());
|
||||
setDisplayName(copyMe.getDisplayName());
|
||||
setEmployeeNumber(copyMe.getEmployeeNumber());
|
||||
setHomePhone(copyMe.getHomePhone());
|
||||
setHomePostalAddress(copyMe.getHomePostalAddress());
|
||||
setInitials(copyMe.getInitials());
|
||||
setMail(copyMe.getMail());
|
||||
setMobile(copyMe.getMobile());
|
||||
setO(copyMe.getO());
|
||||
setOu(copyMe.getOu());
|
||||
setPostalAddress(copyMe.getPostalAddress());
|
||||
setPostalCode(copyMe.getPostalCode());
|
||||
setRoomNumber(copyMe.getRoomNumber());
|
||||
setStreet(copyMe.getStreet());
|
||||
setTitle(copyMe.getTitle());
|
||||
setUid(copyMe.getUid());
|
||||
setDestinationIndicator(copyMe.getDestinationIndicator());
|
||||
setEmployeeNumber(copyMe.getEmployeeNumber());
|
||||
}
|
||||
|
||||
public Essence(DirContextOperations ctx) {
|
||||
public Essence(DirContextOperations ctx) {
|
||||
super(ctx);
|
||||
setCarLicense(ctx.getStringAttribute("carLicense"));
|
||||
setDepartmentNumber(ctx.getStringAttribute("departmentNumber"));
|
||||
setDestinationIndicator(ctx.getStringAttribute("destinationIndicator"));
|
||||
setDisplayName(ctx.getStringAttribute("displayName"));
|
||||
setEmployeeNumber(ctx.getStringAttribute("employeeNumber"));
|
||||
setHomePhone(ctx.getStringAttribute("homePhone"));
|
||||
setHomePostalAddress(ctx.getStringAttribute("homePostalAddress"));
|
||||
setInitials(ctx.getStringAttribute("initials"));
|
||||
setMail(ctx.getStringAttribute("mail"));
|
||||
setMobile(ctx.getStringAttribute("mobile"));
|
||||
setO(ctx.getStringAttribute("o"));
|
||||
setOu(ctx.getStringAttribute("ou"));
|
||||
setPostalAddress(ctx.getStringAttribute("postalAddress"));
|
||||
setPostalCode(ctx.getStringAttribute("postalCode"));
|
||||
setRoomNumber(ctx.getStringAttribute("roomNumber"));
|
||||
setStreet(ctx.getStringAttribute("street"));
|
||||
setTitle(ctx.getStringAttribute("title"));
|
||||
setUid(ctx.getStringAttribute("uid"));
|
||||
setUid(ctx.getStringAttribute("uid"));
|
||||
setEmployeeNumber(ctx.getStringAttribute("employeeNumber"));
|
||||
setDestinationIndicator(ctx.getStringAttribute("destinationIndicator"));
|
||||
}
|
||||
|
||||
protected LdapUserDetailsImpl createTarget() {
|
||||
@@ -209,38 +94,6 @@ public class InetOrgPerson extends Person {
|
||||
setUsername(uid);
|
||||
}
|
||||
}
|
||||
|
||||
public void setInitials(String initials) {
|
||||
((InetOrgPerson) instance).initials = initials;
|
||||
}
|
||||
|
||||
public void setO(String organization) {
|
||||
((InetOrgPerson) instance).o = organization;
|
||||
}
|
||||
|
||||
public void setOu(String ou) {
|
||||
((InetOrgPerson) instance).ou = ou;
|
||||
}
|
||||
|
||||
public void setRoomNumber(String no) {
|
||||
((InetOrgPerson) instance).roomNumber = no;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
((InetOrgPerson) instance).title = title;
|
||||
}
|
||||
|
||||
public void setCarLicense(String carLicense) {
|
||||
((InetOrgPerson) instance).carLicense = carLicense;
|
||||
}
|
||||
|
||||
public void setDepartmentNumber(String departmentNumber) {
|
||||
((InetOrgPerson) instance).departmentNumber = departmentNumber;
|
||||
}
|
||||
|
||||
public void setDisplayName(String displayName) {
|
||||
((InetOrgPerson) instance).displayName = displayName;
|
||||
}
|
||||
|
||||
public void setEmployeeNumber(String no) {
|
||||
((InetOrgPerson) instance).employeeNumber = no;
|
||||
@@ -249,29 +102,5 @@ public class InetOrgPerson extends Person {
|
||||
public void setDestinationIndicator(String destination) {
|
||||
((InetOrgPerson) instance).destinationIndicator = destination;
|
||||
}
|
||||
|
||||
public void setHomePhone(String homePhone) {
|
||||
((InetOrgPerson) instance).homePhone = homePhone;
|
||||
}
|
||||
|
||||
public void setStreet(String street) {
|
||||
((InetOrgPerson) instance).street = street;
|
||||
}
|
||||
|
||||
public void setPostalCode(String postalCode) {
|
||||
((InetOrgPerson) instance).postalCode = postalCode;
|
||||
}
|
||||
|
||||
public void setPostalAddress(String postalAddress) {
|
||||
((InetOrgPerson) instance).postalAddress = postalAddress;
|
||||
}
|
||||
|
||||
public void setMobile(String mobile) {
|
||||
((InetOrgPerson) instance).mobile = mobile;
|
||||
}
|
||||
|
||||
public void setHomePostalAddress(String homePostalAddress) {
|
||||
((InetOrgPerson) instance).homePostalAddress = homePostalAddress;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -31,9 +31,9 @@ public interface LdapUserDetails extends UserDetails {
|
||||
|
||||
/**
|
||||
* The attributes for the user's entry in the directory (or a subset of them, depending on what was
|
||||
* retrieved from the directory).
|
||||
* retrieved from the directory)
|
||||
*
|
||||
* @deprecated Map additional attributes to user properties in a custom object rather than accessing them here.
|
||||
* @deprecated Map additional attributes to properties in a subclass rather than accessing them here.
|
||||
* @return the user's attributes, or an empty array if none were obtained, never null.
|
||||
*/
|
||||
Attributes getAttributes();
|
||||
|
||||
@@ -35,8 +35,6 @@ import java.util.Arrays;
|
||||
*/
|
||||
public class Person extends LdapUserDetailsImpl {
|
||||
private String sn;
|
||||
private String description;
|
||||
private String telephoneNumber;
|
||||
private List cn = new ArrayList();
|
||||
|
||||
protected Person() {
|
||||
@@ -49,20 +47,10 @@ public class Person extends LdapUserDetailsImpl {
|
||||
public String[] getCn() {
|
||||
return (String[]) cn.toArray(new String[cn.size()]);
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public String getTelephoneNumber() {
|
||||
return telephoneNumber;
|
||||
}
|
||||
|
||||
protected void populateContext(DirContextAdapter adapter) {
|
||||
protected void populateContext(DirContextAdapter adapter) {
|
||||
adapter.setAttributeValue("sn", sn);
|
||||
adapter.setAttributeValues("cn", getCn());
|
||||
adapter.setAttributeValue("description", getDescription());
|
||||
adapter.setAttributeValue("telephoneNumber", getTelephoneNumber());
|
||||
|
||||
if(getPassword() != null) {
|
||||
adapter.setAttributeValue("userPassword", getPassword());
|
||||
@@ -79,8 +67,6 @@ public class Person extends LdapUserDetailsImpl {
|
||||
super(ctx);
|
||||
setCn(ctx.getStringAttributes("cn"));
|
||||
setSn(ctx.getStringAttribute("sn"));
|
||||
setDescription(ctx.getStringAttribute("description"));
|
||||
setTelephoneNumber(ctx.getStringAttribute("telephoneNumber"));
|
||||
Object passo = ctx.getObjectAttribute("userPassword");
|
||||
|
||||
if(passo != null) {
|
||||
@@ -89,11 +75,9 @@ public class Person extends LdapUserDetailsImpl {
|
||||
}
|
||||
}
|
||||
|
||||
public Essence(Person copyMe) {
|
||||
public Essence(Person copyMe) {
|
||||
super(copyMe);
|
||||
setSn(copyMe.sn);
|
||||
setDescription(copyMe.getDescription());
|
||||
setTelephoneNumber(copyMe.getTelephoneNumber());
|
||||
((Person) instance).cn = new ArrayList(copyMe.cn);
|
||||
}
|
||||
|
||||
@@ -112,14 +96,6 @@ public class Person extends LdapUserDetailsImpl {
|
||||
public void addCn(String value) {
|
||||
((Person) instance).cn.add(value);
|
||||
}
|
||||
|
||||
public void setTelephoneNumber(String tel) {
|
||||
((Person) instance).telephoneNumber = tel;
|
||||
}
|
||||
|
||||
public void setDescription(String desc) {
|
||||
((Person) instance).description = desc;
|
||||
}
|
||||
|
||||
public LdapUserDetails createUserDetails() {
|
||||
Person p = (Person) super.createUserDetails();
|
||||
|
||||
@@ -2,6 +2,8 @@ package org.springframework.security.util;
|
||||
|
||||
import org.springframework.util.PathMatcher;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Ant path strategy for URL matching.
|
||||
@@ -10,6 +12,8 @@ import org.springframework.util.AntPathMatcher;
|
||||
* @version $Id$
|
||||
*/
|
||||
public class AntUrlPathMatcher implements UrlMatcher {
|
||||
private static final Log logger = LogFactory.getLog(AntUrlPathMatcher.class);
|
||||
|
||||
private boolean requiresLowerCaseUrl = true;
|
||||
private PathMatcher pathMatcher = new AntPathMatcher();
|
||||
|
||||
@@ -44,8 +48,4 @@ public class AntUrlPathMatcher implements UrlMatcher {
|
||||
public boolean requiresLowerCaseUrl() {
|
||||
return requiresLowerCaseUrl;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getClass().getName() + "[requiresLowerCase='" + requiresLowerCaseUrl + "']";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,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());
|
||||
setFilterChainMap(converter.getFilterChainMap());
|
||||
setMatcher(converter.getMatcher());
|
||||
fids = null;
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ public class FilterChainProxy implements Filter, InitializingBean, ApplicationCo
|
||||
* @param url the request URL
|
||||
* @return an ordered array of Filters defining the filter chain
|
||||
*/
|
||||
public List getFilters(String url) {
|
||||
List getFilters(String url) {
|
||||
Iterator filterChains = filterChainMap.entrySet().iterator();
|
||||
|
||||
while (filterChains.hasNext()) {
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ public class InMemoryXmlApplicationContext extends AbstractXmlApplicationContext
|
||||
" xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'\n" +
|
||||
" xsi:schemaLocation='http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd\n" +
|
||||
"http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd\n" +
|
||||
"http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.1.xsd'>\n";
|
||||
"http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd'>\n";
|
||||
private static final String BEANS_CLOSE = "</b:beans>\n";
|
||||
|
||||
Resource inMemoryXml;
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
package org.springframework.security.util;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
|
||||
/**
|
||||
* Provides SHA512 digest methods.
|
||||
*
|
||||
* <p>
|
||||
* Based on Commons Codec, which does not presently provide SHA512 support.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @since 2.0.1
|
||||
*
|
||||
*/
|
||||
public abstract class Sha512DigestUtils {
|
||||
/**
|
||||
* Returns a MessageDigest for the given <code>algorithm</code>.
|
||||
*
|
||||
* @param algorithm The MessageDigest algorithm name.
|
||||
* @return An MD5 digest instance.
|
||||
* @throws RuntimeException when a {@link java.security.NoSuchAlgorithmException} is caught,
|
||||
*/
|
||||
static MessageDigest getDigest(String algorithm) {
|
||||
try {
|
||||
return MessageDigest.getInstance(algorithm);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an SHA digest.
|
||||
*
|
||||
* @return An SHA digest instance.
|
||||
* @throws RuntimeException when a {@link java.security.NoSuchAlgorithmException} is caught,
|
||||
*/
|
||||
private static MessageDigest getSha512Digest() {
|
||||
return getDigest("SHA-512");
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the SHA digest and returns the value as a
|
||||
* <code>byte[]</code>.
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @return SHA digest
|
||||
*/
|
||||
public static byte[] sha(byte[] data) {
|
||||
return getSha512Digest().digest(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the SHA digest and returns the value as a
|
||||
* <code>byte[]</code>.
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @return SHA digest
|
||||
*/
|
||||
public static byte[] sha(String data) {
|
||||
return sha(data.getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the SHA digest and returns the value as a hex string.
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @return SHA digest as a hex string
|
||||
*/
|
||||
public static String shaHex(byte[] data) {
|
||||
return new String(Hex.encodeHex(sha(data)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the SHA digest and returns the value as a hex string.
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @return SHA digest as a hex string
|
||||
*/
|
||||
public static String shaHex(String data) {
|
||||
return new String(Hex.encodeHex(sha(data)));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,3 +1,2 @@
|
||||
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
|
||||
|
||||
|
||||
-1335
File diff suppressed because it is too large
Load Diff
+3
-24
@@ -52,10 +52,6 @@ system-wide =
|
||||
|
||||
boolean = "true" | "false"
|
||||
|
||||
role-prefix =
|
||||
## A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_").
|
||||
attribute role-prefix {xsd:string}
|
||||
|
||||
|
||||
ldap-server =
|
||||
## Defines an LDAP server location or starts an embedded server. The url indicates the location of a remote server. If no url is given, an embedded server will be started, listening on the supplied port number. The port is optional and defaults to 33389. A Spring LDAP ContextSource bean will be registered for the server with the id supplied.
|
||||
@@ -90,13 +86,10 @@ user-search-filter-attribute =
|
||||
attribute user-search-filter {xsd:string}
|
||||
user-search-base-attribute =
|
||||
## Search base for user searches. Defaults to "".
|
||||
attribute user-search-base {xsd:string}
|
||||
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".
|
||||
attribute group-role-attribute {xsd:string}
|
||||
user-details-class-attribute =
|
||||
## Allows the objectClass of the user entry to be specified. If set, the framework will attempt to load standard attributes for the defined class into the returned UserDetails object
|
||||
attribute user-details-class {"person" | "inetOrgPerson"}
|
||||
|
||||
|
||||
ldap-user-service =
|
||||
@@ -116,10 +109,6 @@ ldap-us.attlist &=
|
||||
group-role-attribute-attribute?
|
||||
ldap-us.attlist &=
|
||||
cache-ref?
|
||||
ldap-us.attlist &=
|
||||
role-prefix?
|
||||
ldap-us.attlist &=
|
||||
user-details-class-attribute?
|
||||
|
||||
ldap-authentication-provider =
|
||||
## Sets up an ldap authentication provider
|
||||
@@ -139,10 +128,6 @@ ldap-ap.attlist &=
|
||||
ldap-ap.attlist &=
|
||||
## A specific pattern used to build the user's DN, for example "uid={0},ou=people". The key "{0}" must be present and will be substituted with the username.
|
||||
attribute user-dn-pattern {xsd:string}?
|
||||
ldap-ap.attlist &=
|
||||
role-prefix?
|
||||
ldap-ap.attlist &=
|
||||
user-details-class-attribute?
|
||||
|
||||
password-compare-element =
|
||||
## Specifies that an LDAP provider should use an LDAP compare operation of the user's password to authenticate the user
|
||||
@@ -186,8 +171,6 @@ global-method-security.attlist &=
|
||||
## Optional AccessDecisionManager bean ID to override the default used for method security.
|
||||
attribute access-decision-manager-ref {xsd:string}?
|
||||
|
||||
custom-after-invocation-provider =
|
||||
element custom-after-invocation-provider {empty}
|
||||
|
||||
protect-pointcut =
|
||||
## Defines a protected pointcut and the access control configuration attributes that apply to it. Every bean registered in the Spring application context that provides a method that matches the pointcut will receive security authorization.
|
||||
@@ -231,7 +214,7 @@ http.attlist &=
|
||||
## Allows a customized AuthenticationEntryPoint to be used.
|
||||
attribute entry-point-ref {xsd:string}?
|
||||
http.attlist &=
|
||||
## Corresponds to the observeOncePerRequest property of FilterSecurityInterceptor. Defaults to "true"
|
||||
## Corresponds to the observeOncePerRequest property of FilterSecurityInterceptor. Defaults to "false"
|
||||
attribute once-per-request {boolean}?
|
||||
http.attlist &=
|
||||
## Allows the access denied page to be set (the user will be redirected here if an AccessDeniedException is raised).
|
||||
@@ -422,9 +405,7 @@ user.attlist &=
|
||||
user.attlist &=
|
||||
## Can be set to "true" to mark an account as locked and unusable.
|
||||
attribute locked {boolean}?
|
||||
user.attlist &=
|
||||
## Can be set to "true" to mark an account as disabled and unusable.
|
||||
attribute disabled {boolean}?
|
||||
|
||||
|
||||
jdbc-user-service =
|
||||
## Causes creation of a JDBC-based UserDetailsService.
|
||||
@@ -443,8 +424,6 @@ jdbc-user-service.attlist &=
|
||||
jdbc-user-service.attlist &=
|
||||
## An SQL statement to query user's group authorities given a username.
|
||||
attribute group-authorities-by-username-query {xsd:string}?
|
||||
jdbc-user-service.attlist &=
|
||||
role-prefix?
|
||||
|
||||
|
||||
any-user-service = user-service | jdbc-user-service | ldap-user-service
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
package org.springframework.security.config;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.support.AbstractXmlApplicationContext;
|
||||
import org.springframework.security.afterinvocation.AfterInvocationProviderManager;
|
||||
import org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor;
|
||||
import org.springframework.security.util.InMemoryXmlApplicationContext;
|
||||
|
||||
public class CustomAfterInvocationProviderBeanDefinitionDecoratorTests {
|
||||
private AbstractXmlApplicationContext appContext;
|
||||
|
||||
@After
|
||||
public void closeAppContext() {
|
||||
if (appContext != null) {
|
||||
appContext.close();
|
||||
appContext = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customAuthenticationProviderIsAddedToInterceptor() {
|
||||
setContext(
|
||||
"<global-method-security />" +
|
||||
"<b:bean id='aip' class='org.springframework.security.config.MockAfterInvocationProvider'>" +
|
||||
" <custom-after-invocation-provider />" +
|
||||
"</b:bean>" +
|
||||
HttpSecurityBeanDefinitionParserTests.AUTH_PROVIDER_XML
|
||||
);
|
||||
|
||||
MethodSecurityInterceptor msi = (MethodSecurityInterceptor) appContext.getBean(BeanIds.METHOD_SECURITY_INTERCEPTOR);
|
||||
AfterInvocationProviderManager apm = (AfterInvocationProviderManager) msi.getAfterInvocationManager();
|
||||
assertNotNull(apm);
|
||||
assertEquals(1, apm.getProviders().size());
|
||||
assertTrue(apm.getProviders().get(0) instanceof MockAfterInvocationProvider);
|
||||
}
|
||||
|
||||
private void setContext(String context) {
|
||||
appContext = new InMemoryXmlApplicationContext(context);
|
||||
}
|
||||
}
|
||||
+18
-125
@@ -8,8 +8,6 @@ import java.util.List;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
|
||||
import org.springframework.context.support.AbstractXmlApplicationContext;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
@@ -43,7 +41,6 @@ import org.springframework.security.ui.webapp.DefaultLoginPageGeneratingFilter;
|
||||
import org.springframework.security.util.FieldUtils;
|
||||
import org.springframework.security.util.FilterChainProxy;
|
||||
import org.springframework.security.util.InMemoryXmlApplicationContext;
|
||||
import org.springframework.security.util.MockFilter;
|
||||
import org.springframework.security.util.PortMapperImpl;
|
||||
import org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
@@ -70,11 +67,6 @@ public class HttpSecurityBeanDefinitionParserTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void minimalConfigurationParses() {
|
||||
setContext("<http><http-basic /></http>" + AUTH_PROVIDER_XML);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void httpAutoConfigSetsUpCorrectFilterList() throws Exception {
|
||||
setContext("<http auto-config='true' />" + AUTH_PROVIDER_XML);
|
||||
@@ -84,11 +76,6 @@ public class HttpSecurityBeanDefinitionParserTests {
|
||||
checkAutoConfigFilters(filterList);
|
||||
}
|
||||
|
||||
@Test(expected=BeanDefinitionParsingException.class)
|
||||
public void duplicateElementCausesError() throws Exception {
|
||||
setContext("<http auto-config='true' /><http auto-config='true' />" + AUTH_PROVIDER_XML);
|
||||
}
|
||||
|
||||
private void checkAutoConfigFilters(List filterList) throws Exception {
|
||||
assertEquals("Expected 11 filters in chain", 11, filterList.size());
|
||||
|
||||
@@ -110,10 +97,7 @@ public class HttpSecurityBeanDefinitionParserTests {
|
||||
assertTrue(filters.next() instanceof RememberMeProcessingFilter);
|
||||
assertTrue(filters.next() instanceof AnonymousProcessingFilter);
|
||||
assertTrue(filters.next() instanceof ExceptionTranslationFilter);
|
||||
Object fsiObj = filters.next();
|
||||
assertTrue(fsiObj instanceof FilterSecurityInterceptor);
|
||||
FilterSecurityInterceptor fsi = (FilterSecurityInterceptor) fsiObj;
|
||||
assertTrue(fsi.isObserveOncePerRequest());
|
||||
assertTrue(filters.next() instanceof FilterSecurityInterceptor);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -173,40 +157,6 @@ public class HttpSecurityBeanDefinitionParserTests {
|
||||
assertEquals("/default", filter.getDefaultTargetUrl());
|
||||
assertEquals(Boolean.TRUE, FieldUtils.getFieldValue(filter, "alwaysUseDefaultTargetUrl"));
|
||||
}
|
||||
|
||||
@Test(expected=BeanDefinitionParsingException.class)
|
||||
public void invalidLoginPageIsDetected() throws Exception {
|
||||
setContext(
|
||||
"<http>" +
|
||||
" <form-login login-page='noLeadingSlash'/>" +
|
||||
"</http>" + AUTH_PROVIDER_XML);
|
||||
}
|
||||
|
||||
@Test(expected=BeanDefinitionParsingException.class)
|
||||
public void invalidDefaultTargetUrlIsDetected() throws Exception {
|
||||
setContext(
|
||||
"<http>" +
|
||||
" <form-login default-target-url='noLeadingSlash'/>" +
|
||||
"</http>" + AUTH_PROVIDER_XML);
|
||||
}
|
||||
|
||||
@Test(expected=BeanDefinitionParsingException.class)
|
||||
public void invalidLogoutUrlIsDetected() throws Exception {
|
||||
setContext(
|
||||
"<http>" +
|
||||
" <logout logout-url='noLeadingSlash'/>" +
|
||||
" <form-login />" +
|
||||
"</http>" + AUTH_PROVIDER_XML);
|
||||
}
|
||||
|
||||
@Test(expected=BeanDefinitionParsingException.class)
|
||||
public void invalidLogoutSuccessUrlIsDetected() throws Exception {
|
||||
setContext(
|
||||
"<http>" +
|
||||
" <logout logout-success-url='noLeadingSlash'/>" +
|
||||
" <form-login />" +
|
||||
"</http>" + AUTH_PROVIDER_XML);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lowerCaseComparisonIsRespectedBySecurityFilterInvocationDefinitionSource() throws Exception {
|
||||
@@ -245,14 +195,19 @@ public class HttpSecurityBeanDefinitionParserTests {
|
||||
assertTrue(attrs.contains(new SecurityConfig("ROLE_B")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void minimalConfigurationParses() {
|
||||
setContext("<http><http-basic /></http>" + AUTH_PROVIDER_XML);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void oncePerRequestAttributeIsSupported() throws Exception {
|
||||
setContext("<http once-per-request='false'><http-basic /></http>" + AUTH_PROVIDER_XML);
|
||||
setContext("<http once-per-request='true'><http-basic /></http>" + AUTH_PROVIDER_XML);
|
||||
List filters = getFilters("/someurl");
|
||||
|
||||
FilterSecurityInterceptor fsi = (FilterSecurityInterceptor) filters.get(filters.size() - 1);
|
||||
|
||||
assertFalse(fsi.isObserveOncePerRequest());
|
||||
assertTrue(fsi.isObserveOncePerRequest());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -263,11 +218,6 @@ public class HttpSecurityBeanDefinitionParserTests {
|
||||
ExceptionTranslationFilter etf = (ExceptionTranslationFilter) filters.get(filters.size() - 2);
|
||||
|
||||
assertEquals("/access-denied", FieldUtils.getFieldValue(etf, "accessDeniedHandler.errorPage"));
|
||||
}
|
||||
|
||||
@Test(expected=BeanDefinitionParsingException.class)
|
||||
public void invalidAccessDeniedUrlIsDetected() throws Exception {
|
||||
setContext("<http auto-config='true' access-denied-page='noLeadingSlash'/>" + AUTH_PROVIDER_XML);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -300,36 +250,23 @@ public class HttpSecurityBeanDefinitionParserTests {
|
||||
|
||||
@Test
|
||||
public void externalFiltersAreTreatedCorrectly() throws Exception {
|
||||
// Decorated user-filters should be added to stack. The others should be ignored.
|
||||
// Decorated user-filter should be added to stack. The other one should be ignored
|
||||
setContext(
|
||||
"<http auto-config='true'/>" + AUTH_PROVIDER_XML +
|
||||
"<b:bean id='userFilter' class='org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter'>" +
|
||||
" <custom-filter after='LOGOUT_FILTER'/>" +
|
||||
"<b:bean id='userFilter' class='org.springframework.security.util.MockFilter'>" +
|
||||
" <custom-filter after='SESSION_CONTEXT_INTEGRATION_FILTER'/>" +
|
||||
"</b:bean>" +
|
||||
"<b:bean id='userFilter1' class='org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter'>" +
|
||||
" <custom-filter before='SESSION_CONTEXT_INTEGRATION_FILTER'/>" +
|
||||
"</b:bean>" +
|
||||
"<b:bean id='userFilter2' class='org.springframework.security.util.MockFilter'>" +
|
||||
" <custom-filter position='FIRST'/>" +
|
||||
"</b:bean>" +
|
||||
"<b:bean id='userFilter3' class='org.springframework.security.util.MockFilter'/>" +
|
||||
"<b:bean id='userFilter4' class='org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter'/>"
|
||||
);
|
||||
"<b:bean id='userFilter3' class='org.springframework.security.util.MockFilter'/>");
|
||||
List filters = getFilters("/someurl");
|
||||
|
||||
assertEquals(14, filters.size());
|
||||
assertTrue(filters.get(0) instanceof MockFilter);
|
||||
assertTrue(filters.get(1) instanceof SecurityContextHolderAwareRequestFilter);
|
||||
assertTrue(filters.get(5) instanceof SecurityContextHolderAwareRequestFilter);
|
||||
}
|
||||
|
||||
@Test(expected=BeanCreationException.class)
|
||||
public void twoFiltersWithSameOrderAreRejected() {
|
||||
setContext(
|
||||
"<http auto-config='true'/>" + AUTH_PROVIDER_XML +
|
||||
"<b:bean id='userFilter' class='org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter'>" +
|
||||
" <custom-filter position='LOGOUT_FILTER'/>" +
|
||||
"</b:bean>");
|
||||
assertEquals(13, filters.size());
|
||||
assertTrue(filters.get(0) instanceof OrderedFilterBeanDefinitionDecorator.OrderedFilterDecorator);
|
||||
assertTrue(filters.get(2) instanceof OrderedFilterBeanDefinitionDecorator.OrderedFilterDecorator);
|
||||
assertEquals("userFilter", ((OrderedFilterBeanDefinitionDecorator.OrderedFilterDecorator)filters.get(2)).getBeanName());
|
||||
assertEquals("userFilter2", ((OrderedFilterBeanDefinitionDecorator.OrderedFilterDecorator)filters.get(0)).getBeanName());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -410,7 +347,7 @@ public class HttpSecurityBeanDefinitionParserTests {
|
||||
auth.setDetails(new WebAuthenticationDetails(req));
|
||||
seshController.checkAuthenticationAllowed(auth);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void customEntryPointIsSupported() throws Exception {
|
||||
setContext(
|
||||
@@ -463,50 +400,6 @@ public class HttpSecurityBeanDefinitionParserTests {
|
||||
assertEquals("Hello from the post processor!", service.getPostProcessorWasHere());
|
||||
}
|
||||
|
||||
/**
|
||||
* SEC-795. Two methods that exercise the scenarios that will or won't result in a protected login page warning.
|
||||
* Check the log.
|
||||
*/
|
||||
@Test
|
||||
public void unprotectedLoginPageDoesntResultInWarning() {
|
||||
// Anonymous access configured
|
||||
setContext(
|
||||
" <http>" +
|
||||
" <intercept-url pattern='/login.jsp*' access='IS_AUTHENTICATED_ANONYMOUSLY'/>" +
|
||||
" <intercept-url pattern='/**' access='ROLE_A'/>" +
|
||||
" <anonymous />" +
|
||||
" <form-login login-page='/login.jsp' default-target-url='/messageList.html'/>" +
|
||||
" </http>" + AUTH_PROVIDER_XML);
|
||||
closeAppContext();
|
||||
// No filters applied to login page
|
||||
setContext(
|
||||
" <http>" +
|
||||
" <intercept-url pattern='/login.jsp*' filters='none'/>" +
|
||||
" <intercept-url pattern='/**' access='ROLE_A'/>" +
|
||||
" <anonymous />" +
|
||||
" <form-login login-page='/login.jsp' default-target-url='/messageList.html'/>" +
|
||||
" </http>" + AUTH_PROVIDER_XML);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void protectedLoginPageResultsInWarning() {
|
||||
// Protected, no anonymous filter configured.
|
||||
setContext(
|
||||
" <http>" +
|
||||
" <intercept-url pattern='/**' access='ROLE_A'/>" +
|
||||
" <form-login login-page='/login.jsp' default-target-url='/messageList.html'/>" +
|
||||
" </http>" + AUTH_PROVIDER_XML);
|
||||
closeAppContext();
|
||||
// Protected, anonymous provider but no access
|
||||
setContext(
|
||||
" <http>" +
|
||||
" <intercept-url pattern='/**' access='ROLE_A'/>" +
|
||||
" <anonymous />" +
|
||||
" <form-login login-page='/login.jsp' default-target-url='/messageList.html'/>" +
|
||||
" </http>" + AUTH_PROVIDER_XML);
|
||||
}
|
||||
|
||||
|
||||
private void setContext(String context) {
|
||||
appContext = new InMemoryXmlApplicationContext(context);
|
||||
}
|
||||
|
||||
+1
-12
@@ -10,9 +10,7 @@ import org.springframework.security.AuthenticationManager;
|
||||
import org.springframework.security.providers.ProviderManager;
|
||||
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.providers.dao.DaoAuthenticationProvider;
|
||||
import org.springframework.security.userdetails.UserDetails;
|
||||
import org.springframework.security.userdetails.jdbc.JdbcUserDetailsManager;
|
||||
import org.springframework.security.util.AuthorityUtils;
|
||||
import org.springframework.security.util.InMemoryXmlApplicationContext;
|
||||
|
||||
/**
|
||||
@@ -63,7 +61,7 @@ public class JdbcUserServiceBeanDefinitionParserTests {
|
||||
JdbcUserDetailsManager mgr = (JdbcUserDetailsManager) appContext.getBean("myUserService");
|
||||
assertTrue(mgr.loadUserByUsername("rod") != null);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void cacheRefIsparsedCorrectly() {
|
||||
setContext("<jdbc-user-service id='myUserService' cache-ref='userCache' data-source-ref='dataSource'/>"
|
||||
@@ -96,15 +94,6 @@ public class JdbcUserServiceBeanDefinitionParserTests {
|
||||
provider.authenticate(new UsernamePasswordAuthenticationToken("rod","koala"));
|
||||
assertNotNull("Cache should contain user after authentication", provider.getUserCache().getUserFromCache("rod"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rolePrefixIsUsedWhenSet() {
|
||||
setContext("<jdbc-user-service id='myUserService' role-prefix='PREFIX_' data-source-ref='dataSource'/>" + DATA_SOURCE);
|
||||
JdbcUserDetailsManager mgr = (JdbcUserDetailsManager) appContext.getBean("myUserService");
|
||||
UserDetails rod = mgr.loadUserByUsername("rod");
|
||||
assertTrue(AuthorityUtils.authorityArrayToSet(rod.getAuthorities()).contains("PREFIX_ROLE_SUPERVISOR"));
|
||||
}
|
||||
|
||||
|
||||
private void setContext(String context) {
|
||||
appContext = new InMemoryXmlApplicationContext(context);
|
||||
|
||||
+8
-48
@@ -1,18 +1,14 @@
|
||||
package org.springframework.security.config;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.providers.ProviderManager;
|
||||
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.providers.ldap.LdapAuthenticationProvider;
|
||||
import org.springframework.security.userdetails.ldap.InetOrgPersonContextMapper;
|
||||
import org.springframework.security.userdetails.ldap.LdapUserDetailsImpl;
|
||||
import org.springframework.security.util.FieldUtils;
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.util.InMemoryXmlApplicationContext;
|
||||
import org.springframework.security.userdetails.ldap.LdapUserDetailsImpl;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
import org.junit.After;
|
||||
|
||||
|
||||
/**
|
||||
@@ -45,31 +41,9 @@ public class LdapProviderBeanDefinitionParserTests {
|
||||
public void missingServerEltCausesConfigException() {
|
||||
setContext("<ldap-authentication-provider />");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void supportsPasswordComparisonAuthentication() {
|
||||
setContext("<ldap-server /> " +
|
||||
"<ldap-authentication-provider user-dn-pattern='uid={0},ou=people'>" +
|
||||
" <password-compare />" +
|
||||
"</ldap-authentication-provider>");
|
||||
LdapAuthenticationProvider provider = getProvider();
|
||||
provider.authenticate(new UsernamePasswordAuthenticationToken("ben", "benspassword"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void supportsPasswordComparisonAuthenticationWithHashAttribute() {
|
||||
setContext("<ldap-server /> " +
|
||||
"<ldap-authentication-provider user-dn-pattern='uid={0},ou=people'>" +
|
||||
" <password-compare password-attribute='uid' hash='plaintext'/>" +
|
||||
"</ldap-authentication-provider>");
|
||||
LdapAuthenticationProvider provider = getProvider();
|
||||
provider.authenticate(new UsernamePasswordAuthenticationToken("ben", "ben"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supportsPasswordComparisonAuthenticationWithPasswordEncoder() {
|
||||
setContext("<ldap-server /> " +
|
||||
"<ldap-authentication-provider user-dn-pattern='uid={0},ou=people'>" +
|
||||
" <password-compare password-attribute='uid'>" +
|
||||
@@ -78,26 +52,12 @@ public class LdapProviderBeanDefinitionParserTests {
|
||||
"</ldap-authentication-provider>");
|
||||
LdapAuthenticationProvider provider = getProvider();
|
||||
provider.authenticate(new UsernamePasswordAuthenticationToken("ben", "ben"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void detectsNonStandardServerId() {
|
||||
setContext("<ldap-server id='myServer'/> " +
|
||||
"<ldap-authentication-provider />");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inetOrgContextMapperIsSupported() throws Exception {
|
||||
setContext(
|
||||
"<ldap-server id='someServer' url='ldap://127.0.0.1:343/dc=springframework,dc=org'/>" +
|
||||
"<ldap-authentication-provider user-details-class='inetOrgPerson'/>");
|
||||
LdapAuthenticationProvider provider = getProvider();
|
||||
assertTrue(FieldUtils.getFieldValue(provider, "userDetailsContextMapper") instanceof InetOrgPersonContextMapper);
|
||||
}
|
||||
|
||||
|
||||
private void setContext(String context) {
|
||||
appCtx = new InMemoryXmlApplicationContext(context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private LdapAuthenticationProvider getProvider() {
|
||||
ProviderManager authManager = (ProviderManager) appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER);
|
||||
|
||||
+3
-50
@@ -7,8 +7,6 @@ import org.springframework.security.util.AuthorityUtils;
|
||||
import org.springframework.security.util.InMemoryXmlApplicationContext;
|
||||
import org.springframework.security.userdetails.UserDetailsService;
|
||||
import org.springframework.security.userdetails.UserDetails;
|
||||
import org.springframework.security.userdetails.ldap.InetOrgPerson;
|
||||
import org.springframework.security.userdetails.ldap.Person;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.After;
|
||||
@@ -43,15 +41,12 @@ public class LdapUserServiceBeanDefinitionParserTests {
|
||||
|
||||
Set authorities = AuthorityUtils.authorityArrayToSet(ben.getAuthorities());
|
||||
assertEquals(2, authorities.size());
|
||||
assertTrue(authorities.contains("ROLE_DEVELOPERS"));
|
||||
assertTrue(authorities.contains(new GrantedAuthorityImpl("ROLE_DEVELOPERS")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void differentUserSearchBaseWorksAsExpected() throws Exception {
|
||||
setContext("<ldap-user-service id='ldapUDS' " +
|
||||
" user-search-base='ou=otherpeople' " +
|
||||
" user-search-filter='(cn={0})' " +
|
||||
" group-search-filter='member={0}' /><ldap-server />");
|
||||
setContext("<ldap-user-service id='ldapUDS' user-search-base='ou=otherpeople' user-search-filter='(cn={0})' group-search-filter='member={0}' /><ldap-server />");
|
||||
|
||||
UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
|
||||
UserDetails joe = uds.loadUserByUsername("Joe Smeth");
|
||||
@@ -59,27 +54,6 @@ public class LdapUserServiceBeanDefinitionParserTests {
|
||||
assertEquals("Joe Smeth", joe.getUsername());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rolePrefixIsSupported() throws Exception {
|
||||
setContext(
|
||||
"<ldap-user-service id='ldapUDS' " +
|
||||
" user-search-filter='(uid={0})' " +
|
||||
" group-search-filter='member={0}' role-prefix='PREFIX_'/>" +
|
||||
"<ldap-user-service id='ldapUDSNoPrefix' " +
|
||||
" user-search-filter='(uid={0})' " +
|
||||
" group-search-filter='member={0}' role-prefix='none'/><ldap-server />");
|
||||
|
||||
UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
|
||||
UserDetails ben = uds.loadUserByUsername("ben");
|
||||
assertTrue(AuthorityUtils.authorityArrayToSet(ben.getAuthorities()).contains("PREFIX_DEVELOPERS"));
|
||||
|
||||
uds = (UserDetailsService) appCtx.getBean("ldapUDSNoPrefix");
|
||||
ben = uds.loadUserByUsername("ben");
|
||||
assertTrue(AuthorityUtils.authorityArrayToSet(ben.getAuthorities()).contains("DEVELOPERS"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void differentGroupRoleAttributeWorksAsExpected() throws Exception {
|
||||
setContext("<ldap-user-service id='ldapUDS' user-search-filter='(uid={0})' group-role-attribute='ou' group-search-filter='member={0}' /><ldap-server />");
|
||||
@@ -101,28 +75,7 @@ public class LdapUserServiceBeanDefinitionParserTests {
|
||||
" <ldap-user-service user-search-filter='(uid={0})' />" +
|
||||
"</authentication-provider>");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void personContextMapperIsSupported() {
|
||||
setContext(
|
||||
"<ldap-server />" +
|
||||
"<ldap-user-service id='ldapUDS' user-search-filter='(uid={0})' user-details-class='person'/>");
|
||||
UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
|
||||
UserDetails ben = uds.loadUserByUsername("ben");
|
||||
assertTrue(ben instanceof Person);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inetOrgContextMapperIsSupported() {
|
||||
setContext(
|
||||
"<ldap-server id='someServer'/>" +
|
||||
"<ldap-user-service id='ldapUDS' user-search-filter='(uid={0})' user-details-class='inetOrgPerson'/>");
|
||||
UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
|
||||
UserDetails ben = uds.loadUserByUsername("ben");
|
||||
assertTrue(ben instanceof InetOrgPerson);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void setContext(String context) {
|
||||
appCtx = new InMemoryXmlApplicationContext(context);
|
||||
}
|
||||
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
package org.springframework.security.config;
|
||||
|
||||
import org.springframework.security.AccessDeniedException;
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.ConfigAttribute;
|
||||
import org.springframework.security.ConfigAttributeDefinition;
|
||||
import org.springframework.security.afterinvocation.AfterInvocationProvider;
|
||||
|
||||
public class MockAfterInvocationProvider implements AfterInvocationProvider {
|
||||
|
||||
public Object decide(Authentication authentication, Object object, ConfigAttributeDefinition config, Object returnedObject)
|
||||
throws AccessDeniedException {
|
||||
return returnedObject;
|
||||
}
|
||||
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean supports(Class clazz) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
-18
@@ -1,9 +1,6 @@
|
||||
package org.springframework.security.config;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.springframework.security.util.InMemoryXmlApplicationContext;
|
||||
import org.springframework.security.userdetails.UserDetails;
|
||||
import org.springframework.security.userdetails.UserDetailsService;
|
||||
import org.springframework.context.support.AbstractXmlApplicationContext;
|
||||
import org.springframework.beans.FatalBeanException;
|
||||
@@ -45,21 +42,6 @@ public class UserServiceBeanDefinitionParserTests {
|
||||
userService.loadUserByUsername("joe");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void disabledAndEmbeddedFlagsAreSupported() {
|
||||
setContext(
|
||||
"<user-service id='service'>" +
|
||||
" <user name='joe' password='joespassword' authorities='ROLE_A' locked='true'/>" +
|
||||
" <user name='bob' password='bobspassword' authorities='ROLE_A' disabled='true'/>" +
|
||||
"</user-service>");
|
||||
UserDetailsService userService = (UserDetailsService) appContext.getBean("service");
|
||||
UserDetails joe = userService.loadUserByUsername("joe");
|
||||
assertFalse(joe.isAccountNonLocked());
|
||||
UserDetails bob = userService.loadUserByUsername("bob");
|
||||
assertFalse(bob.isEnabled());
|
||||
}
|
||||
|
||||
|
||||
@Test(expected=FatalBeanException.class)
|
||||
public void userWithBothPropertiesAndEmbeddedUsersThrowsException() {
|
||||
setContext(
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
package org.springframework.security.intercept.web;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
*
|
||||
*/
|
||||
public class RequestKeyTests {
|
||||
|
||||
@Test
|
||||
public void equalsWorksWithNullHttpMethod() {
|
||||
RequestKey key1 = new RequestKey("/someurl");
|
||||
RequestKey key2 = new RequestKey("/someurl");
|
||||
|
||||
assertEquals(key1, key2);
|
||||
key1 = new RequestKey("/someurl","GET");
|
||||
assertFalse(key1.equals(key2));
|
||||
assertFalse(key2.equals(key1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void keysWithSameUrlAndHttpMethodAreEqual() {
|
||||
RequestKey key1 = new RequestKey("/someurl", "GET");
|
||||
RequestKey key2 = new RequestKey("/someurl", "GET");
|
||||
|
||||
assertEquals(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void keysWithSameUrlAndDifferentHttpMethodAreNotEqual() {
|
||||
RequestKey key1 = new RequestKey("/someurl", "GET");
|
||||
RequestKey key2 = new RequestKey("/someurl", "POST");
|
||||
|
||||
assertFalse(key1.equals(key2));
|
||||
assertFalse(key2.equals(key1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void keysWithDifferentUrlsAreNotEquals() {
|
||||
RequestKey key1 = new RequestKey("/someurl", "GET");
|
||||
RequestKey key2 = new RequestKey("/anotherurl", "GET");
|
||||
|
||||
assertFalse(key1.equals(key2));
|
||||
assertFalse(key2.equals(key1));
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package org.springframework.security.token;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Tests {@link DefaultToken}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
*
|
||||
*/
|
||||
public class DefaultTokenTests {
|
||||
@Test
|
||||
public void testEquality() {
|
||||
String key = "key";
|
||||
long created = new Date().getTime();
|
||||
String extendedInformation = "extended";
|
||||
|
||||
DefaultToken t1 = new DefaultToken(key, created, extendedInformation);
|
||||
DefaultToken t2 = new DefaultToken(key, created, extendedInformation);
|
||||
Assert.assertEquals(t1, t2);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testRejectsNullExtendedInformation() {
|
||||
String key = "key";
|
||||
long created = new Date().getTime();
|
||||
new DefaultToken(key, created, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualityWithDifferentExtendedInformation3() {
|
||||
String key = "key";
|
||||
long created = new Date().getTime();
|
||||
|
||||
DefaultToken t1 = new DefaultToken(key, created, "length1");
|
||||
DefaultToken t2 = new DefaultToken(key, created, "longerLength2");
|
||||
Assert.assertFalse(t1.equals(t2));
|
||||
}
|
||||
}
|
||||
-84
@@ -1,84 +0,0 @@
|
||||
|
||||
|
||||
package org.springframework.security.token;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Date;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Tests {@link KeyBasedPersistenceTokenService}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
*
|
||||
*/
|
||||
public class KeyBasedPersistenceTokenServiceTests {
|
||||
|
||||
private KeyBasedPersistenceTokenService getService() {
|
||||
SecureRandomFactoryBean fb = new SecureRandomFactoryBean();
|
||||
KeyBasedPersistenceTokenService service = new KeyBasedPersistenceTokenService();
|
||||
service.setServerSecret("MY:SECRET$$$#");
|
||||
service.setServerInteger(new Integer(454545));
|
||||
try {
|
||||
SecureRandom rnd = (SecureRandom) fb.getObject();
|
||||
service.setSecureRandom(rnd);
|
||||
service.afterPropertiesSet();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return service;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOperationWithSimpleExtendedInformation() {
|
||||
KeyBasedPersistenceTokenService service = getService();
|
||||
Token token = service.allocateToken("Hello world");
|
||||
Token result = service.verifyToken(token.getKey());
|
||||
Assert.assertEquals(token, result);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testOperationWithComplexExtendedInformation() {
|
||||
KeyBasedPersistenceTokenService service = getService();
|
||||
Token token = service.allocateToken("Hello:world:::");
|
||||
Token result = service.verifyToken(token.getKey());
|
||||
Assert.assertEquals(token, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOperationWithEmptyRandomNumber() {
|
||||
KeyBasedPersistenceTokenService service = getService();
|
||||
service.setPseudoRandomNumberBits(0);
|
||||
Token token = service.allocateToken("Hello:world:::");
|
||||
Token result = service.verifyToken(token.getKey());
|
||||
Assert.assertEquals(token, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOperationWithNoExtendedInformation() {
|
||||
KeyBasedPersistenceTokenService service = getService();
|
||||
Token token = service.allocateToken("");
|
||||
Token result = service.verifyToken(token.getKey());
|
||||
Assert.assertEquals(token, result);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testOperationWithMissingKey() {
|
||||
KeyBasedPersistenceTokenService service = getService();
|
||||
Token token = new DefaultToken("", new Date().getTime(), "");
|
||||
service.verifyToken(token.getKey());
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testOperationWithTamperedKey() {
|
||||
KeyBasedPersistenceTokenService service = getService();
|
||||
Token goodToken = service.allocateToken("");
|
||||
String fake = goodToken.getKey().toUpperCase();
|
||||
Token token = new DefaultToken(fake, new Date().getTime(), "");
|
||||
service.verifyToken(token.getKey());
|
||||
}
|
||||
}
|
||||
-51
@@ -1,51 +0,0 @@
|
||||
package org.springframework.security.token;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
/**
|
||||
* Tests {@link SecureRandomFactoryBean}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
*
|
||||
*/
|
||||
public class SecureRandomFactoryBeanTests {
|
||||
@Test
|
||||
public void testObjectType() {
|
||||
SecureRandomFactoryBean factory = new SecureRandomFactoryBean();
|
||||
Assert.assertEquals(SecureRandom.class, factory.getObjectType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsSingleton() {
|
||||
SecureRandomFactoryBean factory = new SecureRandomFactoryBean();
|
||||
Assert.assertFalse(factory.isSingleton());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreatesUsingDefaults() throws Exception {
|
||||
SecureRandomFactoryBean factory = new SecureRandomFactoryBean();
|
||||
Object result = factory.getObject();
|
||||
Assert.assertTrue(result instanceof SecureRandom);
|
||||
int rnd = ((SecureRandom)result).nextInt();
|
||||
Assert.assertTrue(rnd != 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreatesUsingSeed() throws Exception {
|
||||
SecureRandomFactoryBean factory = new SecureRandomFactoryBean();
|
||||
Resource resource = new ClassPathResource("org/springframework/security/token/SecureRandomFactoryBeanTests.class");
|
||||
Assert.assertNotNull(resource);
|
||||
factory.setSeed(resource);
|
||||
Object result = factory.getObject();
|
||||
Assert.assertTrue(result instanceof SecureRandom);
|
||||
int rnd = ((SecureRandom)result).nextInt();
|
||||
Assert.assertTrue(rnd != 0);
|
||||
}
|
||||
|
||||
}
|
||||
+7
-54
@@ -16,6 +16,7 @@ public class InetOrgPersonTests extends TestCase {
|
||||
InetOrgPerson p = (InetOrgPerson) essence.createUserDetails();
|
||||
|
||||
assertEquals("ghengis", p.getUsername());
|
||||
|
||||
}
|
||||
|
||||
public void testUsernameIsDifferentFromContextUidIfSet() {
|
||||
@@ -31,23 +32,11 @@ public class InetOrgPersonTests extends TestCase {
|
||||
InetOrgPerson.Essence essence = new InetOrgPerson.Essence(createUserContext());
|
||||
InetOrgPerson p = (InetOrgPerson) essence.createUserDetails();
|
||||
|
||||
assertEquals("HORS1", p.getCarLicense());
|
||||
assertEquals("ghengis@mongolia", p.getMail());
|
||||
assertEquals("Khan", p.getSn());
|
||||
assertEquals("Ghengis Khan", p.getCn()[0]);
|
||||
assertEquals("00001", p.getEmployeeNumber());
|
||||
assertEquals("+442075436521", p.getTelephoneNumber());
|
||||
assertEquals("Steppes", p.getHomePostalAddress());
|
||||
assertEquals("+467575436521", p.getHomePhone());
|
||||
assertEquals("Hordes", p.getO());
|
||||
assertEquals("Horde1", p.getOu());
|
||||
assertEquals("On the Move", p.getPostalAddress());
|
||||
assertEquals("Changes Frequently", p.getPostalCode());
|
||||
assertEquals("Yurt 1", p.getRoomNumber());
|
||||
assertEquals("Westward Avenue", p.getStreet());
|
||||
assertEquals("Scary", p.getDescription());
|
||||
assertEquals("Ghengis McCann", p.getDisplayName());
|
||||
assertEquals("G", p.getInitials());
|
||||
assertEquals("West", p.getDestinationIndicator());
|
||||
}
|
||||
|
||||
public void testPasswordIsSetFromContextUserPassword() {
|
||||
@@ -55,57 +44,21 @@ public class InetOrgPersonTests extends TestCase {
|
||||
InetOrgPerson p = (InetOrgPerson) essence.createUserDetails();
|
||||
|
||||
assertEquals("pillage", p.getPassword());
|
||||
}
|
||||
|
||||
public void testMappingBackToContextMatchesOriginalData() {
|
||||
DirContextAdapter ctx1 = createUserContext();
|
||||
DirContextAdapter ctx2 = new DirContextAdapter();
|
||||
ctx1.setAttributeValues("objectclass", new String[] {"top", "person", "organizationalPerson", "inetOrgPerson"});
|
||||
ctx2.setDn(new DistinguishedName("ignored=ignored"));
|
||||
InetOrgPerson p = (InetOrgPerson) (new InetOrgPerson.Essence(ctx1)).createUserDetails();
|
||||
p.populateContext(ctx2);
|
||||
|
||||
assertEquals(ctx1, ctx2);
|
||||
|
||||
}
|
||||
|
||||
public void testCopyMatchesOriginalData() {
|
||||
DirContextAdapter ctx1 = createUserContext();
|
||||
DirContextAdapter ctx2 = new DirContextAdapter();
|
||||
ctx2.setDn(new DistinguishedName("ignored=ignored"));
|
||||
ctx1.setAttributeValues("objectclass", new String[] {"top", "person", "organizationalPerson", "inetOrgPerson"});
|
||||
InetOrgPerson p = (InetOrgPerson) (new InetOrgPerson.Essence(ctx1)).createUserDetails();
|
||||
InetOrgPerson p2 = (InetOrgPerson) new InetOrgPerson.Essence(p).createUserDetails();
|
||||
p2.populateContext(ctx2);
|
||||
|
||||
assertEquals(ctx1, ctx2);
|
||||
}
|
||||
|
||||
private DirContextAdapter createUserContext() {
|
||||
DirContextAdapter ctx = new DirContextAdapter();
|
||||
|
||||
ctx.setDn(new DistinguishedName("ignored=ignored"));
|
||||
ctx.setAttributeValue("uid", "ghengis");
|
||||
ctx.setAttributeValue("userPassword", "pillage");
|
||||
ctx.setAttributeValue("carLicense", "HORS1");
|
||||
ctx.setAttributeValue("cn", "Ghengis Khan");
|
||||
ctx.setAttributeValue("description", "Scary");
|
||||
ctx.setAttributeValue("destinationIndicator", "West");
|
||||
ctx.setAttributeValue("displayName", "Ghengis McCann");
|
||||
ctx.setAttributeValue("homePhone", "+467575436521");
|
||||
ctx.setAttributeValue("initials", "G");
|
||||
ctx.setAttributeValue("employeeNumber", "00001");
|
||||
ctx.setAttributeValue("homePostalAddress", "Steppes");
|
||||
ctx.setAttributeValue("mail", "ghengis@mongolia");
|
||||
ctx.setAttributeValue("mobile", "always");
|
||||
ctx.setAttributeValue("o", "Hordes");
|
||||
ctx.setAttributeValue("ou", "Horde1");
|
||||
ctx.setAttributeValue("postalAddress", "On the Move");
|
||||
ctx.setAttributeValue("postalCode", "Changes Frequently");
|
||||
ctx.setAttributeValue("roomNumber", "Yurt 1");
|
||||
ctx.setAttributeValue("roomNumber", "Yurt 1");
|
||||
ctx.setAttributeValue("cn", "Ghengis Khan");
|
||||
ctx.setAttributeValue("sn", "Khan");
|
||||
ctx.setAttributeValue("street", "Westward Avenue");
|
||||
ctx.setAttributeValue("telephoneNumber", "+442075436521");
|
||||
ctx.setAttributeValue("employeeNumber", "00001");
|
||||
ctx.setAttributeValue("destinationIndicator", "West");
|
||||
ctx.setAttributeValue("o", "Hordes");
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
+1
-12
@@ -116,21 +116,10 @@ public class LdapUserDetailsManagerTests extends AbstractLdapIntegrationTests {
|
||||
@Test
|
||||
public void testCreateNewUserSucceeds() {
|
||||
InetOrgPerson.Essence p = new InetOrgPerson.Essence();
|
||||
p.setCarLicense("XXX");
|
||||
p.setCn(new String[] {"Joe Smeth"});
|
||||
p.setDepartmentNumber("5679");
|
||||
p.setDescription("Some description");
|
||||
p.setDn("whocares");
|
||||
p.setEmployeeNumber("E781");
|
||||
p.setInitials("J");
|
||||
p.setMail("joe@smeth.com");
|
||||
p.setMobile("+44776542911");
|
||||
p.setOu("Joes Unit");
|
||||
p.setO("Organization");
|
||||
p.setRoomNumber("500X");
|
||||
p.setCn(new String[] {"Joe Smeth"});
|
||||
p.setSn("Smeth");
|
||||
p.setUid("joe");
|
||||
|
||||
p.setAuthorities(TEST_AUTHORITIES);
|
||||
|
||||
mgr.createUser(p.createUserDetails());
|
||||
|
||||
@@ -137,12 +137,6 @@ public class FilterChainProxyTests {
|
||||
doNormalOperation(filterChainProxy);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void proxyPathWithoutLowerCaseConversionShouldntMatchDifferentCasePath() throws Exception {
|
||||
FilterChainProxy filterChainProxy = (FilterChainProxy) appCtx.getBean("filterChainNonLowerCase", FilterChainProxy.class);
|
||||
assertNull(filterChainProxy.getFilters("/some/other/path/blah"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void normalOperationWithNewConfig() throws Exception {
|
||||
FilterChainProxy filterChainProxy = (FilterChainProxy) appCtx.getBean("newFilterChainProxy", FilterChainProxy.class);
|
||||
@@ -169,8 +163,7 @@ public class FilterChainProxyTests {
|
||||
assertEquals(1, filters.size());
|
||||
assertTrue(filters.get(0) instanceof MockFilter);
|
||||
|
||||
filters = filterChainProxy.getFilters("/some/other/path/blah");
|
||||
assertNotNull(filters);
|
||||
filters = filterChainProxy.getFilters("/sOme/other/path/blah");
|
||||
assertEquals(3, filters.size());
|
||||
assertTrue(filters.get(0) instanceof HttpSessionContextIntegrationFilter);
|
||||
assertTrue(filters.get(1) instanceof MockFilter);
|
||||
|
||||
@@ -53,17 +53,6 @@ http://www.springframework.org/schema/security http://www.springframework.org/sc
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="filterChainNonLowerCase" class="org.springframework.security.util.FilterChainProxy">
|
||||
<property name="filterInvocationDefinitionSource">
|
||||
<value>
|
||||
PATTERN_TYPE_APACHE_ANT
|
||||
/foo/**=mockFilter
|
||||
/SOME/other/path/**=sif,mockFilter,mockFilter2
|
||||
/do/not/filter=#NONE#
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="newFilterChainProxy" class="org.springframework.security.util.FilterChainProxy">
|
||||
<sec:filter-chain-map path-type="ant">
|
||||
<sec:filter-chain pattern="/foo/**" filters="mockFilter"/>
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-parent</artifactId>
|
||||
<version>2.0.1</version>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
<packaging>jar</packaging>
|
||||
<artifactId>spring-security-ntlm</artifactId>
|
||||
|
||||
+3
-24
@@ -3,13 +3,13 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-parent</artifactId>
|
||||
<version>2.0.1</version>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
<artifactId>spring-security-openid</artifactId>
|
||||
<name>Spring Security - OpenID support</name>
|
||||
<description>Spring Security - Support for OpenID</description>
|
||||
<version>2.0.1</version>
|
||||
<packaging>bundle</packaging>
|
||||
<version>2.0.0</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
@@ -39,25 +39,4 @@
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<spring.osgi.export>
|
||||
org.springframework.security.*;version=${pom.version}
|
||||
</spring.osgi.export>
|
||||
|
||||
<spring.osgi.import>
|
||||
javax.servlet.*;version="[2.4.0, 3.0.0)",
|
||||
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
|
||||
org.openid4java.*;version="[0.9.3, 1.0.0)",
|
||||
org.springframework.security.*;version="[${pom.version},${pom.version}]",
|
||||
org.springframework.beans.*;version="${spring.version.osgi}",
|
||||
org.springframework.util.*;version="${spring.version.osgi}"
|
||||
</spring.osgi.import>
|
||||
|
||||
<spring.osgi.private.pkg>
|
||||
!org.springframework.security.*
|
||||
</spring.osgi.private.pkg>
|
||||
|
||||
<spring.osgi.symbolic.name>org.springframework.security.openid</spring.osgi.symbolic.name>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -3,13 +3,13 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-parent</artifactId>
|
||||
<version>2.0.1</version>
|
||||
<version>2.0.0</version>
|
||||
<name>Spring Security</name>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
<module>core</module>
|
||||
<module>core-tiger</module>
|
||||
<module>core</module>
|
||||
<module>core-tiger</module>
|
||||
<module>adapters</module>
|
||||
<module>portlet</module>
|
||||
<module>ntlm</module>
|
||||
@@ -38,9 +38,9 @@
|
||||
|
||||
<!-- Note when doing releases: tagBase is set in release plugin configuration below -->
|
||||
<scm>
|
||||
<connection>scm:svn:https://acegisecurity.svn.sourceforge.net/svnroot/acegisecurity/spring-security/tags/spring-security-parent-2.0.1</connection>
|
||||
<developerConnection>scm:svn:https://acegisecurity.svn.sourceforge.net/svnroot/acegisecurity/spring-security/tags/spring-security-parent-2.0.1</developerConnection>
|
||||
<url>http://acegisecurity.svn.sourceforge.net/viewcvs.cgi/acegisecurity/spring-security/tags/spring-security-parent-2.0.1</url>
|
||||
<connection>scm:svn:https://acegisecurity.svn.sourceforge.net/svnroot/acegisecurity/spring-security/tags/spring-security-parent-2.0.0</connection>
|
||||
<developerConnection>scm:svn:https://acegisecurity.svn.sourceforge.net/svnroot/acegisecurity/spring-security/tags/spring-security-parent-2.0.0</developerConnection>
|
||||
<url>http://acegisecurity.svn.sourceforge.net/viewcvs.cgi/acegisecurity/spring-security/tags/spring-security-parent-2.0.0</url>
|
||||
</scm>
|
||||
|
||||
<issueManagement>
|
||||
@@ -221,12 +221,6 @@
|
||||
<contributor>
|
||||
<name>Martin Algesten</name>
|
||||
</contributor>
|
||||
<contributor>
|
||||
<name>Ruud Senden</name>
|
||||
</contributor>
|
||||
<contributor>
|
||||
<name>Michael Mayr</name>
|
||||
</contributor>
|
||||
</contributors>
|
||||
|
||||
<dependencies>
|
||||
@@ -255,7 +249,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-clean-plugin</artifactId>
|
||||
<version>2.2</version>
|
||||
<version>2.1.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
@@ -265,7 +259,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.4.2</version>
|
||||
<version>2.3.1</version>
|
||||
<configuration>
|
||||
<includes>
|
||||
<include>**/*Tests.class</include>
|
||||
@@ -453,36 +447,8 @@
|
||||
</copy>
|
||||
</postProcess>
|
||||
</configuration>
|
||||
|
||||
</plugin>
|
||||
<!-- OSGi Felix bundle plugin -->
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<version>1.4.0</version>
|
||||
<extensions>true</extensions>
|
||||
|
||||
<configuration>
|
||||
<obrRepository>NONE</obrRepository>
|
||||
<instructions>
|
||||
<!-- bundle specific conf -->
|
||||
<Bundle-Name>${artifactId}</Bundle-Name>
|
||||
<Bundle-SymbolicName>${spring.osgi.symbolic.name}</Bundle-SymbolicName>
|
||||
<Bundle-Vendor>SpringSource</Bundle-Vendor>
|
||||
<Export-Package>${spring.osgi.export}</Export-Package>
|
||||
<Import-Package>${spring.osgi.import}</Import-Package>
|
||||
<Private-Package>${spring.osgi.private.pkg}</Private-Package>
|
||||
<!--Include-Resource>${spring.osgi.include.res}</Include-Resource-->
|
||||
<!-- jar entries -->
|
||||
<Implementation-Title>Spring Security</Implementation-Title>
|
||||
<Implementation-Version>${pom.version}</Implementation-Version>
|
||||
<Implementation-Vendor>SpringSource</Implementation-Vendor>
|
||||
<Implementation-Vendor-Id>org.springframework.security</Implementation-Vendor-Id>
|
||||
<!-- Spring specific entries -->
|
||||
<!--Spring-Version>${spring.maven.artifact.version}</Spring-Version-->
|
||||
</instructions>
|
||||
<excludeDependencies>true</excludeDependencies>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
@@ -491,12 +457,10 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-report-plugin</artifactId>
|
||||
<version>2.4.2</version>
|
||||
<!--
|
||||
<version>2.4</version>
|
||||
<configuration>
|
||||
<aggregate>true</aggregate>
|
||||
</configuration>
|
||||
-->
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
@@ -528,18 +492,18 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.4</version>
|
||||
<version>2.3</version>
|
||||
<configuration>
|
||||
<aggregate>true</aggregate>
|
||||
<header>Spring Security Framework</header>
|
||||
<quiet>true</quiet>
|
||||
<excludePackageNames>sample,bigbank,zzz</excludePackageNames>
|
||||
<excludePackageNames>sample,bigbank</excludePackageNames>
|
||||
<links>
|
||||
<link>
|
||||
http://java.sun.com/j2se/1.5.0/docs/api
|
||||
</link>
|
||||
<link>
|
||||
http://static.springframework.org/spring/docs/2.5.x/api/
|
||||
http://www.springframework.org/docs/api/
|
||||
</link>
|
||||
<link>
|
||||
http://commons.apache.org/dbcp/apidocs/
|
||||
@@ -566,7 +530,7 @@
|
||||
http://developer.ja-sig.org/projects/cas/cas-server-core/cas-server/cas-server-core/apidocs/
|
||||
</link>
|
||||
<link>
|
||||
http://tomcat.apache.org/tomcat-5.5-doc/servletapi/
|
||||
http://tomcat.apache.org/tomcat-5.0-doc/servletapi/
|
||||
</link>
|
||||
</links>
|
||||
</configuration>
|
||||
@@ -574,7 +538,7 @@
|
||||
<reportSet>
|
||||
<reports>
|
||||
<report>javadoc</report>
|
||||
<!--<report>test-javadoc</report> -->
|
||||
<!-- <report>test-javadoc</report> -->
|
||||
</reports>
|
||||
</reportSet>
|
||||
</reportSets>
|
||||
@@ -733,7 +697,7 @@
|
||||
</dependencyManagement>
|
||||
<properties>
|
||||
<spring.version>2.0.8</spring.version>
|
||||
<spring.version.osgi>[2.0.8, 3.0.0)</spring.version.osgi>
|
||||
<felix.version>1.4.0</felix.version>
|
||||
<jstl.version>1.1.2</jstl.version>
|
||||
|
||||
<docbook.source>${basedir}/src/docbkx</docbook.source>
|
||||
|
||||
+3
-3
@@ -3,18 +3,18 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-parent</artifactId>
|
||||
<version>2.0.1</version>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
<artifactId>spring-security-portlet</artifactId>
|
||||
<name>Spring Security - Portlet support</name>
|
||||
<description>Spring Security - Support for JSR 168 Portlets</description>
|
||||
<version>2.0.1</version>
|
||||
<version>2.0.0</version>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>2.0.1</version>
|
||||
<version>2.0.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
|
||||
+13
-23
@@ -17,39 +17,29 @@ http://www.springframework.org/projects/.
|
||||
BUILDING
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Spring Security is built using Maven. Please read the "Building from Source" page
|
||||
at http://static.springframework.org/spring-security/site/.
|
||||
Spring Security is built using Maven. Please read the "Building" page
|
||||
at http://static.springframework.org/spring-security/site/building.html.
|
||||
This page is also included in the /docs directory of official release ZIPs.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
DOCUMENTATION
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Be sure to read the Reference Guide, which is available from the web site.
|
||||
Every class also has thorough JavaDocs, which are also available on the web site.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
QUICK START
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
We recommend you visit http://static.springframework.org/spring-security/site and
|
||||
read the "Suggested Steps" page.
|
||||
We recommend you visit http://acegisecurity.org and read the "Suggested Steps"
|
||||
page. This page is also included in the /docs directory of official release
|
||||
ZIPs.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
MAVEN REPOSITORY DOWNLOADS
|
||||
DOCUMENTATION
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Release jars for the project are available from the central maven repository
|
||||
|
||||
http://repo1.maven.org/maven2/org/springframework/security/
|
||||
|
||||
Note that milestone releases and snapshots are not uploaded to the central
|
||||
repository, but can be obtained from te Spring milestone repository.
|
||||
This blog article has full details on how to download milestone or snapshot
|
||||
jars or use them in a Maven-based project build:
|
||||
|
||||
http://blog.springsource.com/main/2007/09/18/maven-artifacts-2/
|
||||
http://acegisecurity.org has a wide range of articles about Spring Security,
|
||||
including links to external resources. A copy of this web site is included in
|
||||
the /docs directory of official release ZIPs.
|
||||
|
||||
Be sure to read the Reference Guide, which is available from the web site (and
|
||||
/docs directory as described above). Every class also has thorough JavaDocs.
|
||||
The core JavaDocs can be found in /docs/multiproject/acegi-security/apidocs/.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
OBTAINING SUPPORT
|
||||
@@ -74,7 +64,7 @@ discussions. You can join at:
|
||||
https://lists.sourceforge.net/lists/listinfo/acegisecurity-developer.
|
||||
|
||||
Links to mailing list archives, the forums, and other useful resources are
|
||||
available from the web site.
|
||||
available from http://acegisecurity.org.
|
||||
|
||||
|
||||
$Id$
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
classes
|
||||
generated
|
||||
reports
|
||||
target
|
||||
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-samples</artifactId>
|
||||
<version>2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-security-sample-attributes</artifactId>
|
||||
<name>Spring Security - Attributes sample</name>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>xdoclet</groupId>
|
||||
<artifactId>xjavadoc</artifactId>
|
||||
<version>1.0.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-collections</groupId>
|
||||
<artifactId>commons-collections</artifactId>
|
||||
<version>3.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-attributes</groupId>
|
||||
<artifactId>commons-attributes-compiler</artifactId>
|
||||
<version>2.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-attributes</groupId>
|
||||
<artifactId>commons-attributes-api</artifactId>
|
||||
<version>2.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-attributes</groupId>
|
||||
<artifactId>commons-attributes-plugin</artifactId>
|
||||
<version>2.1</version>
|
||||
<type>plugin</type>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,48 @@
|
||||
/* 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 sample.attributes;
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @author Cameron Braid
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*
|
||||
*/
|
||||
public interface BankService {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* The SecurityConfig below will be merged with the interface-level SecurityConfig above by Commons Attributes.
|
||||
* ie: this is equivalent to defining BankService=ROLE_TELLER,ROLE_PERMISSION_BALANACE in the bean context.
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*
|
||||
* @@net.sf.acegisecurity.SecurityConfig("ROLE_PERMISSION_BALANCE")
|
||||
*/
|
||||
float balance(String accountNumber);
|
||||
|
||||
/**
|
||||
* The SecurityConfig below will be merged with the interface-level SecurityConfig above by Commons Attributes.
|
||||
* ie: this is equivalent to defining BankService=ROLE_TELLER,ROLE_PERMISSION_LIST in the bean context.
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*
|
||||
* @@net.sf.acegisecurity.SecurityConfig("ROLE_PERMISSION_LIST")
|
||||
*/
|
||||
String[] listAccounts();
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/* 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 sample.attributes;
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @author Cameron Braid
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class BankServiceImpl implements BankService {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public float balance(String accountNumber) {
|
||||
return 42000000;
|
||||
}
|
||||
|
||||
public String[] listAccounts() {
|
||||
return new String[] {"1", "2", "3"};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/* 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 sample.attributes;
|
||||
|
||||
import org.acegisecurity.AccessDeniedException;
|
||||
import org.acegisecurity.GrantedAuthority;
|
||||
import org.acegisecurity.GrantedAuthorityImpl;
|
||||
|
||||
import org.acegisecurity.context.SecurityContextHolder;
|
||||
import org.acegisecurity.context.SecurityContextImpl;
|
||||
|
||||
import org.acegisecurity.providers.TestingAuthenticationToken;
|
||||
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @author Cameron Braid
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class Main {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* This can be done in a web app by using a filter or <code>SpringMvcIntegrationInterceptor</code>.
|
||||
*/
|
||||
private static void createSecureContext() {
|
||||
TestingAuthenticationToken auth = new TestingAuthenticationToken("test", "test",
|
||||
new GrantedAuthority[] {
|
||||
new GrantedAuthorityImpl("ROLE_TELLER"), new GrantedAuthorityImpl("ROLE_PERMISSION_LIST")
|
||||
});
|
||||
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
}
|
||||
|
||||
private static void destroySecureContext() {
|
||||
SecurityContextHolder.setContext(new SecurityContextImpl());
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
createSecureContext();
|
||||
|
||||
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
|
||||
BankService service = (BankService) context.getBean("bankService");
|
||||
|
||||
// will succeed
|
||||
service.listAccounts();
|
||||
|
||||
// will fail
|
||||
try {
|
||||
System.out.println(
|
||||
"We expect an AccessDeniedException now, as we do not hold the ROLE_PERMISSION_BALANCE granted authority, and we're using a unanimous access decision manager... ");
|
||||
service.balance("1");
|
||||
} catch (AccessDeniedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
destroySecureContext();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
|
||||
<!--
|
||||
* Copyright 2004 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*
|
||||
* $Id$
|
||||
-->
|
||||
|
||||
<beans>
|
||||
|
||||
<!-- =================== SECURITY SYSTEM DEFINITIONS ================== -->
|
||||
|
||||
<!-- RunAsManager -->
|
||||
<bean id="runAsManager" class="org.springframework.security.runas.RunAsManagerImpl">
|
||||
<property name="key"><value>my_run_as_password</value></property>
|
||||
</bean>
|
||||
|
||||
<!-- ~~~~~~~~~~~~~~~~~~~~ AUTHENTICATION DEFINITIONS ~~~~~~~~~~~~~~~~~~ -->
|
||||
|
||||
<!-- This authentication provider accepts any presented TestingAuthenticationToken -->
|
||||
<bean id="testingAuthenticationProvider" class="org.springframework.security.providers.TestingAuthenticationProvider"/>
|
||||
|
||||
<!-- The authentication manager that iterates through our only authentication provider -->
|
||||
<bean id="authenticationManager" class="org.springframework.security.providers.ProviderManager">
|
||||
<property name="providers">
|
||||
<list>
|
||||
<ref local="testingAuthenticationProvider"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- ~~~~~~~~~~~~~~~~~~~~ AUTHORIZATION DEFINITIONS ~~~~~~~~~~~~~~~~~~~ -->
|
||||
|
||||
<!-- An access decision voter that reads ROLE_* configuaration settings -->
|
||||
<bean id="roleVoter" class="org.springframework.security.vote.RoleVoter"/>
|
||||
|
||||
<!-- A unanimous access decision manager -->
|
||||
<bean id="accessDecisionManager" class="org.springframework.security.vote.UnanimousBased">
|
||||
<property name="allowIfAllAbstainDecisions"><value>false</value></property>
|
||||
<property name="decisionVoters">
|
||||
<list>
|
||||
<ref local="roleVoter"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- ===================== SECURITY DEFINITIONS ======================= -->
|
||||
|
||||
<bean id="attributes" class="org.springframework.metadata.commons.CommonsAttributes"/>
|
||||
<bean id="objectDefinitionSource" class="org.springframework.security.intercept.method.MethodDefinitionAttributes">
|
||||
<property name="attributes"><ref local="attributes"/></property>
|
||||
</bean>
|
||||
|
||||
<!-- We don't validate config attributes, as it's unsupported by MethodDefinitionAttributes -->
|
||||
<bean id="securityInterceptor" class="org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor">
|
||||
<property name="validateConfigAttributes"><value>false</value></property>
|
||||
<property name="authenticationManager"><ref local="authenticationManager"/></property>
|
||||
<property name="accessDecisionManager"><ref local="accessDecisionManager"/></property>
|
||||
<property name="runAsManager"><ref local="runAsManager"/></property>
|
||||
<property name="objectDefinitionSource"><ref local="objectDefinitionSource"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="bankService" class="sample.attributes.BankServiceImpl"/>
|
||||
|
||||
<!--
|
||||
This bean is a postprocessor that will automatically apply relevant advisors
|
||||
to any bean in child factories.
|
||||
-->
|
||||
<bean id="autoproxy"
|
||||
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
|
||||
</bean>
|
||||
|
||||
<!--
|
||||
AOP advisor that will automatically wire the MethodSecurityInterceptor (above)
|
||||
into BankServiceImpl (above). The configuration attributes used are obtained
|
||||
from the securityInterceptor.objectDefinitionSouce, which in the
|
||||
above configuration is a Commons Attributes-based source.
|
||||
-->
|
||||
<bean id="methodSecurityAdvisor"
|
||||
class="org.springframework.security.intercept.method.aopalliance.MethodDefinitionSourceAdvisor"
|
||||
autowire="constructor" >
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,96 @@
|
||||
/* 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 sample.attributes;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.acegisecurity.AccessDeniedException;
|
||||
import org.acegisecurity.GrantedAuthority;
|
||||
import org.acegisecurity.GrantedAuthorityImpl;
|
||||
|
||||
import org.acegisecurity.context.SecurityContextHolder;
|
||||
import org.acegisecurity.context.SecurityContextImpl;
|
||||
|
||||
import org.acegisecurity.providers.TestingAuthenticationToken;
|
||||
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
|
||||
/**
|
||||
* Tests security objects.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class BankTests extends TestCase {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private BankService service;
|
||||
private ClassPathXmlApplicationContext ctx;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public BankTests() {
|
||||
}
|
||||
|
||||
public BankTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
|
||||
service = (BankService) ctx.getBean("bankService");
|
||||
}
|
||||
|
||||
public void tearDown() {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
private static void createSecureContext() {
|
||||
TestingAuthenticationToken auth = new TestingAuthenticationToken("test", "test",
|
||||
new GrantedAuthority[] {
|
||||
new GrantedAuthorityImpl("ROLE_TELLER"), new GrantedAuthorityImpl("ROLE_PERMISSION_LIST")
|
||||
});
|
||||
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
}
|
||||
|
||||
private static void destroySecureContext() {
|
||||
SecurityContextHolder.setContext(new SecurityContextImpl());
|
||||
}
|
||||
|
||||
public void testDeniedAccess() throws Exception {
|
||||
createSecureContext();
|
||||
|
||||
try {
|
||||
service.balance("1");
|
||||
fail("Should have thrown AccessDeniedException");
|
||||
} catch (AccessDeniedException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
destroySecureContext();
|
||||
}
|
||||
|
||||
public void testListAccounts() throws Exception {
|
||||
createSecureContext();
|
||||
service.listAccounts();
|
||||
destroySecureContext();
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-samples-cas</artifactId>
|
||||
<version>2.0.1</version>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-samples-cas-client</artifactId>
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-samples</artifactId>
|
||||
<version>2.0.1</version>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-samples-cas</artifactId>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-samples-cas</artifactId>
|
||||
<version>2.0.1</version>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-samples-cas-server</artifactId>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-samples</artifactId>
|
||||
<version>2.0.1</version>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
<artifactId>spring-security-samples-contacts</artifactId>
|
||||
<name>Spring Security - Contacts sample</name>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
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.1.xsd">
|
||||
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
|
||||
|
||||
|
||||
<http auto-config="true" realm="Contacts Realm">
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-samples</artifactId>
|
||||
<version>2.0.1</version>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
<artifactId>spring-security-samples-dms</artifactId>
|
||||
<name>Spring Security - DMS sample</name>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-samples</artifactId>
|
||||
<version>2.0.1</version>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-samples-ldap</artifactId>
|
||||
@@ -44,23 +44,27 @@
|
||||
<artifactId>apacheds-core</artifactId>
|
||||
<version>1.0.2</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.server</groupId>
|
||||
<artifactId>apacheds-server-jndi</artifactId>
|
||||
<version>1.0.2</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<version>1.4.3</version>
|
||||
<scope>runtime</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ldap</groupId>
|
||||
<artifactId>spring-ldap</artifactId>
|
||||
<version>1.2.1</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
xmlns:beans="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.1.xsd">
|
||||
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
|
||||
|
||||
<http>
|
||||
<intercept-url pattern="/secure/extreme/**" access="ROLE_SUPERVISOR"/>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-samples</artifactId>
|
||||
<version>2.0.1</version>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-samples-openid</artifactId>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
package zzz;
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
@@ -10,7 +10,7 @@
|
||||
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.1.xsd">
|
||||
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
|
||||
|
||||
<http>
|
||||
<intercept-url pattern="/**" access="ROLE_USER"/>
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-parent</artifactId>
|
||||
<version>2.0.1</version>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-samples</artifactId>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-samples</artifactId>
|
||||
<version>2.0.1</version>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-samples-portlet</artifactId>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-samples</artifactId>
|
||||
<version>2.0.1</version>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-samples-preauth</artifactId>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
xmlns:sec="http://www.springframework.org/schema/security"
|
||||
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.1.xsd">
|
||||
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
|
||||
|
||||
<bean id="filterChainProxy" class="org.springframework.security.util.FilterChainProxy">
|
||||
<sec:filter-chain-map path-type="ant">
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user