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

Compare commits

..

1 Commits

Author SHA1 Message Date
Ben Alex 973fdf69f2 [maven-release-plugin] copy for tag spring-security-parent-2.0.0 2008-04-14 07:06:19 +00:00
151 changed files with 1054 additions and 5468 deletions
+2 -28
View File
@@ -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 ================================================================================================
@@ -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 ===================================================================================================
+1 -1
View File
@@ -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>
+1 -1
View File
@@ -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>
@@ -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 {
+1 -1
View File
@@ -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
View File
@@ -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>
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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>
@@ -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
View File
@@ -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;
@@ -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;
@@ -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";
}
@@ -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);
}
}
@@ -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";
@@ -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;
}
}
@@ -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);
@@ -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) );
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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));
}
}
@@ -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;
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
}
@@ -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;
}
@@ -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 + "'");
}
}
}
@@ -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 ==================================================================================================
@@ -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 + "]";
}
}
@@ -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() + "; ]";
}
}
@@ -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;
}
@@ -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;
}
}
}
@@ -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()) {
@@ -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
@@ -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
@@ -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);
}
}
@@ -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);
}
@@ -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);
@@ -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);
@@ -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);
}
@@ -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;
}
}
@@ -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));
}
}
@@ -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());
}
}
@@ -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);
}
}
@@ -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;
}
@@ -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
View File
@@ -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
View File
@@ -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>
+16 -52
View File
@@ -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
View File
@@ -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
View File
@@ -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$
+4
View File
@@ -0,0 +1,4 @@
classes
generated
reports
target
+42
View File
@@ -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();
}
}
+1 -1
View File
@@ -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
View File
@@ -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>
+1 -1
View File
@@ -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>
+1 -1
View File
@@ -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
View File
@@ -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>
+5 -1
View File
@@ -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"/>
+1 -1
View File
@@ -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
View File
@@ -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>
+1 -1
View File
@@ -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>
+1 -1
View File
@@ -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