Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1bc1196baa |
+23
-20
@@ -1,28 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="core/src/main/java"/>
|
||||
<classpathentry kind="src" path="core/src/main/resources"/>
|
||||
<classpathentry kind="src" path="core/src/test/java"/>
|
||||
<classpathentry kind="src" path="core/src/test/resources"/>
|
||||
<classpathentry kind="src" path="sandbox/other/src/main/java"/>
|
||||
<classpathentry kind="src" path="sandbox/other/src/test/java"/>
|
||||
<classpathentry kind="src" path="samples/contacts/src/main/java"/>
|
||||
<classpathentry kind="src" path="samples/contacts/src/main/resources"/>
|
||||
<classpathentry kind="src" path="samples/contacts/src/test/java"/>
|
||||
<classpathentry kind="src" path="samples/contacts/src/test/resources"/>
|
||||
<classpathentry kind="src" path="samples/acegifier/src/main/java"/>
|
||||
<classpathentry kind="src" path="samples/acegifier/src/main/resources"/>
|
||||
<classpathentry kind="src" path="samples/acegifier/src/test/java"/>
|
||||
<classpathentry kind="src" path="samples/acegifier/src/test/resources"/>
|
||||
<classpathentry kind="src" path="samples/attributes/src/main/java"/>
|
||||
<classpathentry kind="src" path="samples/acegifier/src/test/resources"/>
|
||||
<classpathentry kind="src" path="samples/acegifier/src/main/resources"/>
|
||||
<classpathentry kind="src" path="samples/acegifier/src/main/java"/>
|
||||
<classpathentry kind="src" path="samples/acegifier/src/test/java"/>
|
||||
<classpathentry kind="src" path="domain/src/main/java"/>
|
||||
<classpathentry kind="src" path="domain/src/main/resource"/>
|
||||
<classpathentry kind="src" path="domain/src/test/java"/>
|
||||
<classpathentry kind="src" path="domain/src/test/resources"/>
|
||||
<classpathentry kind="src" path="adapters/catalina/src/main/resources"/>
|
||||
<classpathentry kind="src" path="samples/attributes/src/main/resources"/>
|
||||
<classpathentry kind="src" path="samples/attributes/src/test/java"/>
|
||||
<classpathentry kind="src" path="adapters/cas/src/test/resources"/>
|
||||
<classpathentry kind="src" path="adapters/cas/src/main/resources"/>
|
||||
<classpathentry kind="src" path="core/src/main/resources"/>
|
||||
<classpathentry kind="src" path="core/src/test/resources"/>
|
||||
<classpathentry kind="src" path="samples/contacts/src/main/java"/>
|
||||
<classpathentry kind="src" path="sandbox/src/main/java"/>
|
||||
<classpathentry kind="src" path="sandbox/src/test/java"/>
|
||||
<classpathentry kind="src" path="adapters/cas/src/main/java"/>
|
||||
<classpathentry kind="src" path="adapters/cas/src/test/java"/>
|
||||
<classpathentry kind="src" path="adapters/catalina/src/main/java"/>
|
||||
<classpathentry kind="src" path="adapters/catalina/src/main/resources"/>
|
||||
<classpathentry kind="src" path="adapters/catalina/src/test/java"/>
|
||||
<classpathentry kind="src" path="adapters/jboss/src/main/java"/>
|
||||
<classpathentry kind="src" path="adapters/jboss/src/test/java"/>
|
||||
@@ -30,10 +29,12 @@
|
||||
<classpathentry kind="src" path="adapters/jetty/src/test/java"/>
|
||||
<classpathentry kind="src" path="adapters/resin/src/main/java"/>
|
||||
<classpathentry kind="src" path="adapters/resin/src/test/java"/>
|
||||
<classpathentry kind="src" path="core/src/main/java"/>
|
||||
<classpathentry kind="src" path="core/src/test/java"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="var" path="MAVEN_REPO/com.caucho/jars/resin-3.0.9.jar"/>
|
||||
<classpathentry kind="var" path="MAVEN_REPO/org.springframework/jars/spring-1.2.8.jar"/>
|
||||
<classpathentry kind="var" path="MAVEN_REPO/org.springframework/jars/spring-mock-1.2.8.jar"/>
|
||||
<classpathentry kind="var" path="MAVEN_REPO/org.springframework/jars/spring-2.0-m2.jar"/>
|
||||
<classpathentry kind="var" path="MAVEN_REPO/org.springframework/jars/spring-mock-2.0-m2.jar"/>
|
||||
<classpathentry kind="var" path="MAVEN_REPO/aopalliance/jars/aopalliance-1.0.jar"/>
|
||||
<classpathentry kind="var" path="MAVEN_REPO/aspectj/jars/aspectjrt-1.2.jar"/>
|
||||
<classpathentry kind="var" path="MAVEN_REPO/cas/jars/casclient-2.0.11.jar"/>
|
||||
@@ -41,7 +42,7 @@
|
||||
<classpathentry kind="var" path="MAVEN_REPO/commons-codec/jars/commons-codec-1.3.jar"/>
|
||||
<classpathentry kind="var" path="MAVEN_REPO/commons-collections/jars/commons-collections-3.1.jar"/>
|
||||
<classpathentry kind="var" path="MAVEN_REPO/commons-logging/jars/commons-logging-1.0.4.jar"/>
|
||||
<classpathentry kind="var" path="MAVEN_REPO/hsqldb/jars/hsqldb-1.8.0.4.jar"/>
|
||||
<classpathentry kind="var" path="MAVEN_REPO/hsqldb/jars/hsqldb-1.7.3.0.jar"/>
|
||||
<classpathentry kind="var" path="MAVEN_REPO/oro/jars/oro-2.0.8.jar"/>
|
||||
<classpathentry kind="var" path="MAVEN_REPO/javax.servlet/jars/servlet-api-2.4.jar"/>
|
||||
<classpathentry kind="var" path="MAVEN_REPO/tomcat/jars/catalina-4.1.9.jar"/>
|
||||
@@ -52,15 +53,16 @@
|
||||
<classpathentry kind="var" path="MAVEN_REPO/ehcache/jars/ehcache-1.1.jar"/>
|
||||
<classpathentry kind="var" path="MAVEN_REPO/javax.servlet/jars/jsp-api-2.0.jar"/>
|
||||
<classpathentry kind="var" path="MAVEN_REPO/hibernate/jars/hibernate-3.0.3.jar"/>
|
||||
<classpathentry kind="var" path="MAVEN_REPO/commons-lang/jars/commons-lang-2.0.jar"/>
|
||||
<classpathentry sourcepath="DIST_BASE/commons-beanutils-1.6.1-src/src/java" kind="var" path="MAVEN_REPO/commons-beanutils/jars/commons-beanutils-1.6.1.jar"/>
|
||||
<classpathentry kind="src" path="samples/contacts-tiger/src/main/java"/>
|
||||
<classpathentry kind="src" path="core-tiger/src/main/java"/>
|
||||
<classpathentry kind="src" path="core-tiger/src/main/resources"/>
|
||||
<classpathentry kind="src" path="core-tiger/src/test/java"/>
|
||||
<classpathentry kind="src" path="core-tiger/src/main/resources"/>
|
||||
<classpathentry kind="src" path="core-tiger/src/test/resources"/>
|
||||
<classpathentry kind="src" path="samples/annotations/src/main/java"/>
|
||||
<classpathentry kind="src" path="samples/annotations/src/main/resources"/>
|
||||
<classpathentry kind="src" path="samples/annotations/src/test/java"/>
|
||||
<classpathentry kind="src" path="samples/contacts-tiger/src/main/java"/>
|
||||
<classpathentry kind="var" path="MAVEN_REPO/org.samba.jcifs/jars/jcifs-1.2.6.jar"/>
|
||||
<classpathentry kind="var" path="MAVEN_REPO/dom4j/jars/dom4j-1.6.jar"/>
|
||||
<classpathentry kind="var" path="MAVEN_REPO/xerces/jars/xercesImpl-2.6.2.jar"/>
|
||||
@@ -74,6 +76,7 @@
|
||||
<classpathentry kind="var" path="MAVEN_REPO/org.apache.directory.shared/jars/shared-ldap-0.9.5.jar"/>
|
||||
<classpathentry kind="var" path="MAVEN_REPO/antlr/jars/antlr-2.7.2.jar"/>
|
||||
<classpathentry kind="var" path="MAVEN_REPO/ldapsdk/jars/ldapsdk-4.1.jar"/>
|
||||
<classpathentry kind="var" path="MAVEN_REPO/org.springframework/jars/spring-hibernate3-2.0-m2.jar"/>
|
||||
<classpathentry kind="var" path="MAVEN_REPO/cas/jars/cas-server-3.0.4.jar"/>
|
||||
<classpathentry kind="var" path="MAVEN_REPO/net.sourceforge.retroweaver/jars/retroweaver-1.0fcs.jar"/>
|
||||
<classpathentry kind="var" path="MAVEN_REPO/taglibs/jars/standard-1.0.6.jar"/>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.acegisecurity</groupId>
|
||||
<artifactId>acegi-security-adapters</artifactId>
|
||||
<version>1.1-SNAPSHOT</version>
|
||||
<version>1.0.1</version>
|
||||
</parent>
|
||||
<artifactId>acegi-security-cas</artifactId>
|
||||
<name>Acegi Security System for Spring - CAS adapter</name>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.acegisecurity</groupId>
|
||||
<artifactId>acegi-security-adapters</artifactId>
|
||||
<version>1.1-SNAPSHOT</version>
|
||||
<version>1.0.1</version>
|
||||
</parent>
|
||||
<artifactId>acegi-security-catalina</artifactId>
|
||||
<name>Acegi Security System for Spring - Catalina adapter</name>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.acegisecurity</groupId>
|
||||
<artifactId>acegi-security-adapters</artifactId>
|
||||
<version>1.1-SNAPSHOT</version>
|
||||
<version>1.0.1</version>
|
||||
</parent>
|
||||
<artifactId>acegi-security-jboss</artifactId>
|
||||
<name>Acegi Security System for Spring - JBoss adapter</name>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.acegisecurity</groupId>
|
||||
<artifactId>acegi-security-adapters</artifactId>
|
||||
<version>1.1-SNAPSHOT</version>
|
||||
<version>1.0.1</version>
|
||||
</parent>
|
||||
<artifactId>acegi-security-jetty</artifactId>
|
||||
<name>Acegi Security System for Spring - Jetty adapter</name>
|
||||
|
||||
@@ -31,7 +31,6 @@ import org.mortbay.http.UserPrincipal;
|
||||
public class JettyAcegiUserToken extends AbstractAdapterAuthenticationToken implements UserPrincipal {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private String password;
|
||||
private String username;
|
||||
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.acegisecurity</groupId>
|
||||
<artifactId>acegi-security-parent</artifactId>
|
||||
<version>1.1-SNAPSHOT</version>
|
||||
<version>1.0.1</version>
|
||||
</parent>
|
||||
<artifactId>acegi-security-adapters</artifactId>
|
||||
<name>Acegi Security System for Spring - Adapters</name>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<dependency>
|
||||
<groupId>org.acegisecurity</groupId>
|
||||
<artifactId>acegi-security</artifactId>
|
||||
<version>1.0.3</version>
|
||||
<version>1.0.0</version>
|
||||
<type>jar</type>
|
||||
<url>http://acegisecurity.org</url>
|
||||
<properties>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.acegisecurity</groupId>
|
||||
<artifactId>acegi-security-adapters</artifactId>
|
||||
<version>1.1-SNAPSHOT</version>
|
||||
<version>1.0.1</version>
|
||||
</parent>
|
||||
<artifactId>acegi-security-resin</artifactId>
|
||||
<name>Acegi Security System for Spring - Resin adapter</name>
|
||||
|
||||
+1
-9
@@ -3,17 +3,10 @@
|
||||
<parent>
|
||||
<groupId>org.acegisecurity</groupId>
|
||||
<artifactId>acegi-security-parent</artifactId>
|
||||
<version>1.1-SNAPSHOT</version>
|
||||
<version>1.0.1</version>
|
||||
</parent>
|
||||
<artifactId>acegi-security-tiger</artifactId>
|
||||
<name>Acegi Security System for Spring - Java 5 (Tiger)</name>
|
||||
|
||||
<scm>
|
||||
<connection>scm:svn:https://svn.sourceforge.net/svnroot/acegisecurity/trunk/acegisecurity/core-tiger</connection>
|
||||
<developerConnection>scm:svn:https://svn.sourceforge.net/svnroot/acegisecurity/trunk/acegisecurity/core-tiger</developerConnection>
|
||||
<url>http://svn.sourceforge.net/viewcvs.cgi/acegisecurity/trunk/acegisecurity/core-tiger/</url>
|
||||
</scm>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.acegisecurity</groupId>
|
||||
@@ -26,7 +19,6 @@
|
||||
<version>1.2.7</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<dependency>
|
||||
<groupId>org.acegisecurity</groupId>
|
||||
<artifactId>acegi-security</artifactId>
|
||||
<version>1.0.3</version>
|
||||
<version>1.0.0</version>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
+2
-17
@@ -12,14 +12,13 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.acegisecurity.annotation;
|
||||
|
||||
import org.acegisecurity.SecurityConfig;
|
||||
|
||||
import org.springframework.metadata.Attributes;
|
||||
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
@@ -44,8 +43,6 @@ import java.util.Set;
|
||||
* </bean></pre></p>
|
||||
* <p>These security annotations are similiar to the Commons Attributes approach, however they are using Java 5
|
||||
* language-level metadata support.</p>
|
||||
* <p>This class should be used with Spring 2.0 or above, as it relies upon utility classes in Spring 2.0 for
|
||||
* correct introspection of annotations on bridge methods.</p>
|
||||
*
|
||||
* @author Mark St.Godard
|
||||
* @version $Id$
|
||||
@@ -99,19 +96,7 @@ public class SecurityAnnotationAttributes implements Attributes {
|
||||
public Collection getAttributes(Method method) {
|
||||
Set<SecurityConfig> attributes = new HashSet<SecurityConfig>();
|
||||
|
||||
Annotation[] annotations = null;
|
||||
|
||||
// Use AnnotationUtils if in classpath (ie Spring 1.2.9+ deployment)
|
||||
try {
|
||||
Class clazz = ClassUtils.forName("org.springframework.core.annotation.AnnotationUtils");
|
||||
Method m = clazz.getMethod("getAnnotations", new Class[] {Method.class});
|
||||
annotations = (Annotation[]) m.invoke(null, new Object[] {method});
|
||||
} catch (Exception ex) {
|
||||
// Fallback to manual retrieval if no AnnotationUtils available
|
||||
annotations = method.getAnnotations();
|
||||
}
|
||||
|
||||
for (Annotation annotation : annotations) {
|
||||
for (Annotation annotation : method.getAnnotations()) {
|
||||
// check for Secured annotations
|
||||
if (annotation instanceof Secured) {
|
||||
Secured attr = (Secured) annotation;
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
package org.acegisecurity.annotation;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joe Scalise
|
||||
*/
|
||||
public class BusinessServiceImpl<E extends Entity> implements BusinessService {
|
||||
|
||||
@Secured({"ROLE_USER"})
|
||||
public void someUserMethod1() {
|
||||
}
|
||||
|
||||
@Secured({"ROLE_USER"})
|
||||
public void someUserMethod2() {
|
||||
}
|
||||
|
||||
@Secured({"ROLE_USER", "ROLE_ADMIN"})
|
||||
public void someUserAndAdminMethod() {
|
||||
}
|
||||
|
||||
@Secured({"ROLE_ADMIN"})
|
||||
public void someAdminMethod() {
|
||||
}
|
||||
|
||||
public E someUserMethod3(final E entity) {
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package org.acegisecurity.annotation;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joe Scalise
|
||||
*/
|
||||
public class Department extends Entity {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private boolean active = true;
|
||||
|
||||
//~ Constructors ===========================================================
|
||||
|
||||
public Department(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public boolean isActive() {
|
||||
return this.active;
|
||||
}
|
||||
|
||||
void deactive() {
|
||||
this.active = true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package org.acegisecurity.annotation;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joe Scalise
|
||||
*/
|
||||
public interface DepartmentService extends BusinessService {
|
||||
|
||||
@Secured({"ROLE_USER"})
|
||||
Department someUserMethod3(Department dept);
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package org.acegisecurity.annotation;
|
||||
|
||||
/**
|
||||
* @author Joe Scalise
|
||||
*/
|
||||
public class DepartmentServiceImpl extends BusinessServiceImpl <Department> implements DepartmentService {
|
||||
|
||||
@Secured({"ROLE_ADMIN"})
|
||||
public Department someUserMethod3(final Department dept) {
|
||||
return super.someUserMethod3(dept);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package org.acegisecurity.annotation;
|
||||
|
||||
/**
|
||||
* Class to act as a superclass for annotations testing.
|
||||
*
|
||||
* @author Ben Alex
|
||||
*
|
||||
*/
|
||||
public class Entity {
|
||||
public Entity(String someParameter) {}
|
||||
}
|
||||
+2
-67
@@ -12,15 +12,13 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.acegisecurity.annotation;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.acegisecurity.SecurityConfig;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.metadata.Attributes;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
@@ -33,14 +31,12 @@ import java.util.Collection;
|
||||
* Tests for {@link org.acegisecurity.annotation.SecurityAnnotationAttributes}
|
||||
*
|
||||
* @author Mark St.Godard
|
||||
* @author Joe Scalise
|
||||
* @version $Id$
|
||||
* @version $Revision$
|
||||
*/
|
||||
public class SecurityAnnotationAttributesTests extends TestCase {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private Attributes attributes;
|
||||
private Log logger = LogFactory.getLog(SecurityAnnotationAttributesTests.class);
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
@@ -49,67 +45,6 @@ public class SecurityAnnotationAttributesTests extends TestCase {
|
||||
this.attributes = new SecurityAnnotationAttributes();
|
||||
}
|
||||
|
||||
public void testGenericsSuperclassDeclarationsAreIncludedWhenSubclassesOverride() {
|
||||
Method method = null;
|
||||
|
||||
try {
|
||||
method = DepartmentServiceImpl.class.getMethod("someUserMethod3", new Class[] {Department.class});
|
||||
} catch (NoSuchMethodException unexpected) {
|
||||
fail("Should be a superMethod called 'someUserMethod3' on class!");
|
||||
}
|
||||
|
||||
Collection attrs = this.attributes.getAttributes(method);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("attrs: ");
|
||||
logger.debug(attrs);
|
||||
}
|
||||
|
||||
assertNotNull(attrs);
|
||||
|
||||
// expect 1 attribute
|
||||
assertTrue("Did not find 1 attribute", attrs.size() == 1);
|
||||
|
||||
// should have 1 SecurityConfig
|
||||
for (Object obj : attrs) {
|
||||
assertTrue(obj instanceof SecurityConfig);
|
||||
|
||||
SecurityConfig sc = (SecurityConfig) obj;
|
||||
assertEquals("Found an incorrect role", "ROLE_ADMIN", sc.getAttribute());
|
||||
}
|
||||
|
||||
Method superMethod = null;
|
||||
|
||||
try {
|
||||
superMethod = DepartmentServiceImpl.class.getMethod("someUserMethod3", new Class[] {Entity.class});
|
||||
} catch (NoSuchMethodException unexpected) {
|
||||
fail("Should be a superMethod called 'someUserMethod3' on class!");
|
||||
}
|
||||
|
||||
System.out.println(superMethod);
|
||||
|
||||
Collection superAttrs = this.attributes.getAttributes(superMethod);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("superAttrs: ");
|
||||
logger.debug(superAttrs);
|
||||
}
|
||||
|
||||
assertNotNull(superAttrs);
|
||||
|
||||
// TODO: Enable this part of the test once we can build against Spring 2.0+ and above only (SEC-274)
|
||||
/*
|
||||
// expect 1 attribute
|
||||
assertTrue("Did not find 1 attribute", superAttrs.size() == 1);
|
||||
// should have 1 SecurityConfig
|
||||
for (Object obj : superAttrs) {
|
||||
assertTrue(obj instanceof SecurityConfig);
|
||||
SecurityConfig sc = (SecurityConfig) obj;
|
||||
assertEquals("Found an incorrect role", "ROLE_ADMIN", sc.getAttribute());
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
public void testGetAttributesClass() {
|
||||
Collection attrs = this.attributes.getAttributes(BusinessService.class);
|
||||
|
||||
|
||||
+21
-44
@@ -1,33 +1,27 @@
|
||||
<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">
|
||||
<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.acegisecurity</groupId>
|
||||
<artifactId>acegi-security-parent</artifactId>
|
||||
<version>1.1-SNAPSHOT</version>
|
||||
<version>1.0.1</version>
|
||||
</parent>
|
||||
<artifactId>acegi-security</artifactId>
|
||||
<name>Acegi Security System for Spring</name>
|
||||
|
||||
<scm>
|
||||
<connection>scm:svn:https://svn.sourceforge.net/svnroot/acegisecurity/trunk/acegisecurity/core</connection>
|
||||
<developerConnection>scm:svn:https://svn.sourceforge.net/svnroot/acegisecurity/trunk/acegisecurity/core</developerConnection>
|
||||
<url>http://svn.sourceforge.net/viewcvs.cgi/acegisecurity/trunk/acegisecurity/core/</url>
|
||||
</scm>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-remoting</artifactId>
|
||||
<version>1.2.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
<version>1.2.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-support</artifactId>
|
||||
<version>1.2.7</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -57,6 +51,11 @@
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<version>1.0.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-lang</groupId>
|
||||
<artifactId>commons-lang</artifactId>
|
||||
<version>2.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
@@ -93,19 +92,25 @@
|
||||
<dependency>
|
||||
<groupId>hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
<version>1.8.0.4</version>
|
||||
<version>1.7.3.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.server</groupId>
|
||||
<artifactId>apacheds-core</artifactId>
|
||||
<version>1.0-RC3</version>
|
||||
<version>1.0-RC1</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>nlog4j</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<version>1.0.1</version>
|
||||
<version>1.0-rc5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -118,35 +123,7 @@
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>${basedir}/../</directory>
|
||||
<targetPath>META-INF</targetPath>
|
||||
<includes>
|
||||
<include>notice.txt</include>
|
||||
</includes>
|
||||
<filtering>false</filtering>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>${basedir}/src/main/resources/org/acegisecurity/taglibs</directory>
|
||||
<targetPath>META-INF</targetPath>
|
||||
<includes>
|
||||
<include>*.tld</include>
|
||||
</includes>
|
||||
<filtering>false</filtering>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>${basedir}/src/main/resources</directory>
|
||||
<targetPath>/</targetPath>
|
||||
<includes>
|
||||
<include>**/*</include>
|
||||
</includes>
|
||||
<filtering>false</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
</project>
|
||||
@@ -29,7 +29,7 @@ public class BadCredentialsException extends AuthenticationException {
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
/**
|
||||
/**
|
||||
* Constructs a <code>BadCredentialsException</code> with the specified
|
||||
* message.
|
||||
*
|
||||
@@ -44,7 +44,7 @@ public class BadCredentialsException extends AuthenticationException {
|
||||
this.extraInformation = extraInformation;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Constructs a <code>BadCredentialsException</code> with the specified
|
||||
* message and root cause.
|
||||
*
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
|
||||
package org.acegisecurity;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Represents an authority granted to an {@link Authentication} object.
|
||||
*
|
||||
@@ -29,7 +27,7 @@ import java.io.Serializable;
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public interface GrantedAuthority extends Serializable {
|
||||
public interface GrantedAuthority {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,7 +28,6 @@ import java.io.Serializable;
|
||||
public class GrantedAuthorityImpl implements GrantedAuthority, Serializable {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private String role;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
@@ -35,6 +35,10 @@ public class SecurityConfig implements ConfigAttribute {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof String) {
|
||||
return obj.equals(this.attrib);
|
||||
}
|
||||
|
||||
if (obj instanceof ConfigAttribute) {
|
||||
ConfigAttribute attr = (ConfigAttribute) obj;
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.acegisecurity.acl.basic;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Stores some privileges typical of a domain object.
|
||||
*
|
||||
@@ -44,18 +45,14 @@ public class SimpleAclEntry extends AbstractBasicAclEntry {
|
||||
public static final int READ_WRITE_DELETE = READ | WRITE | DELETE;
|
||||
|
||||
// Array required by the abstract superclass via getValidPermissions()
|
||||
private static final int[] VALID_PERMISSIONS = {
|
||||
private static final int[] validPermissions = {
|
||||
NOTHING, ADMINISTRATION, READ, WRITE, CREATE, DELETE, READ_WRITE_CREATE_DELETE, READ_WRITE_CREATE,
|
||||
READ_WRITE, READ_WRITE_DELETE
|
||||
};
|
||||
|
||||
private static final String[] VALID_PERMISSIONS_AS_STRING = {
|
||||
"NOTHING", "ADMINISTRATION", "READ", "WRITE", "CREATE", "DELETE", "READ_WRITE_CREATE_DELETE", "READ_WRITE_CREATE",
|
||||
"READ_WRITE", "READ_WRITE_DELETE" };
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
/**
|
||||
/**
|
||||
* Allows {@link BasicAclDao} implementations to construct this object
|
||||
* using <code>newInstance()</code>.
|
||||
*
|
||||
@@ -74,11 +71,8 @@ public class SimpleAclEntry extends AbstractBasicAclEntry {
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* @return a copy of the permissions array, changes to the values won't affect this class.
|
||||
*/
|
||||
public int[] getValidPermissions() {
|
||||
return (int[]) VALID_PERMISSIONS.clone();
|
||||
return validPermissions;
|
||||
}
|
||||
|
||||
public String printPermissionsBlock(int i) {
|
||||
@@ -116,35 +110,4 @@ public class SimpleAclEntry extends AbstractBasicAclEntry {
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a permission {@link String} literal and return associated value.
|
||||
*
|
||||
* @param permission one of the field names that represent a permission: <code>ADMINISTRATION</code>,
|
||||
* <code>READ</code>, <code>WRITE</code>,...
|
||||
* @return the value associated to that permission
|
||||
* @throws IllegalArgumentException if argument is not a valid permission
|
||||
*/
|
||||
public static int parsePermission(String permission) {
|
||||
for (int i = 0; i < VALID_PERMISSIONS_AS_STRING.length; i++) {
|
||||
if (VALID_PERMISSIONS_AS_STRING[i].equalsIgnoreCase(permission)) {
|
||||
return VALID_PERMISSIONS[i];
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Permission provided does not exist: " + permission);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a list of permission {@link String} literals and return associated values.
|
||||
*
|
||||
* @param permissions array with permissions as {@link String}
|
||||
* @see #parsePermission(String) for valid values
|
||||
*/
|
||||
public static int[] parsePermissions(String[] permissions) {
|
||||
int[] requirepermissionAsIntArray = new int[permissions.length];
|
||||
for (int i = 0; i < requirepermissionAsIntArray.length; i++) {
|
||||
requirepermissionAsIntArray[i] = parsePermission(permissions[i]);
|
||||
}
|
||||
return requirepermissionAsIntArray;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.acegisecurity.acls.domain;
|
||||
|
||||
import org.acegisecurity.AccessDeniedException;
|
||||
import org.acegisecurity.Authentication;
|
||||
import org.acegisecurity.GrantedAuthority;
|
||||
|
||||
import org.acegisecurity.acls.Acl;
|
||||
import org.acegisecurity.acls.Permission;
|
||||
import org.acegisecurity.acls.sid.PrincipalSid;
|
||||
import org.acegisecurity.acls.sid.Sid;
|
||||
import org.acegisecurity.acls.sid.SidRetrievalStrategy;
|
||||
import org.acegisecurity.acls.sid.SidRetrievalStrategyImpl;
|
||||
|
||||
import org.acegisecurity.context.SecurityContextHolder;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* Default implementation of {@link AclAuthorizationStrategy}.<p>Permission will be granted provided the current
|
||||
* principal is either the owner (as defined by the ACL), has {@link BasePermission#ADMINISTRATION} (as defined by the
|
||||
* ACL and via a {@link Sid} retrieved for the current principal via {@link #sidRetrievalStrategy}), or if the current
|
||||
* principal holds the relevant system-wide {@link GrantedAuthority} and injected into the constructor.</p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private GrantedAuthority gaGeneralChanges;
|
||||
private GrantedAuthority gaModifyAuditing;
|
||||
private GrantedAuthority gaTakeOwnership;
|
||||
private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
/**
|
||||
* Constructor. The only mandatory parameter relates to the system-wide {@link GrantedAuthority} instances that
|
||||
* can be held to always permit ACL changes.
|
||||
*
|
||||
* @param auths an array of <code>GrantedAuthority</code>s that have
|
||||
* special permissions (index 0 is the authority needed to change
|
||||
* ownership, index 1 is the authority needed to modify auditing details,
|
||||
* index 2 is the authority needed to change other ACL and ACE details) (required)
|
||||
*/
|
||||
public AclAuthorizationStrategyImpl(GrantedAuthority[] auths) {
|
||||
Assert.notEmpty(auths, "GrantedAuthority[] with three elements required");
|
||||
Assert.isTrue(auths.length == 3, "GrantedAuthority[] with three elements required");
|
||||
this.gaTakeOwnership = auths[0];
|
||||
this.gaModifyAuditing = auths[1];
|
||||
this.gaGeneralChanges = auths[2];
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void securityCheck(Acl acl, int changeType) {
|
||||
if ((SecurityContextHolder.getContext() == null)
|
||||
|| (SecurityContextHolder.getContext().getAuthentication() == null)
|
||||
|| !SecurityContextHolder.getContext().getAuthentication().isAuthenticated()) {
|
||||
throw new AccessDeniedException("Authenticated principal required to operate with ACLs");
|
||||
}
|
||||
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
|
||||
// Check if authorized by virtue of ACL ownership
|
||||
Sid currentUser = new PrincipalSid(authentication);
|
||||
|
||||
if (currentUser.equals(acl.getOwner()) && ((changeType == CHANGE_GENERAL) || (changeType == CHANGE_OWNERSHIP))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Not authorized by ACL ownership; try via adminstrative permissions
|
||||
GrantedAuthority requiredAuthority = null;
|
||||
|
||||
if (changeType == CHANGE_AUDITING) {
|
||||
requiredAuthority = this.gaModifyAuditing;
|
||||
} else if (changeType == CHANGE_GENERAL) {
|
||||
requiredAuthority = this.gaGeneralChanges;
|
||||
} else if (changeType == CHANGE_OWNERSHIP) {
|
||||
requiredAuthority = this.gaTakeOwnership;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown change type");
|
||||
}
|
||||
|
||||
// Iterate this principal's authorities to determine right
|
||||
GrantedAuthority[] auths = authentication.getAuthorities();
|
||||
|
||||
for (int i = 0; i < auths.length; i++) {
|
||||
if (requiredAuthority.equals(auths[i])) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to get permission via ACEs within the ACL
|
||||
Sid[] sids = sidRetrievalStrategy.getSids(authentication);
|
||||
|
||||
if (acl.isGranted(new Permission[] {BasePermission.ADMINISTRATION}, sids, false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new AccessDeniedException(
|
||||
"Principal does not have required ACL permissions to perform requested operation");
|
||||
}
|
||||
|
||||
public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) {
|
||||
Assert.notNull(sidRetrievalStrategy, "SidRetrievalStrategy required");
|
||||
this.sidRetrievalStrategy = sidRetrievalStrategy;
|
||||
}
|
||||
}
|
||||
@@ -1,164 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.acegisecurity.acls.domain;
|
||||
|
||||
import org.acegisecurity.acls.AclFormattingUtils;
|
||||
import org.acegisecurity.acls.Permission;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Vector;
|
||||
|
||||
|
||||
/**
|
||||
* A set of standard permissions.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class BasePermission implements Permission {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
public static final Permission READ = new BasePermission(1 << 0, 'R'); // 1
|
||||
public static final Permission WRITE = new BasePermission(1 << 1, 'W'); // 2
|
||||
public static final Permission CREATE = new BasePermission(1 << 2, 'C'); // 4
|
||||
public static final Permission DELETE = new BasePermission(1 << 3, 'D'); // 8
|
||||
public static final Permission ADMINISTRATION = new BasePermission(1 << 4, 'A'); // 16
|
||||
private static Map locallyDeclaredPermissionsByInteger = new HashMap();
|
||||
private static Map locallyDeclaredPermissionsByName = new HashMap();
|
||||
|
||||
static {
|
||||
Field[] fields = BasePermission.class.getDeclaredFields();
|
||||
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
try {
|
||||
Object fieldValue = fields[i].get(null);
|
||||
|
||||
if (BasePermission.class.isAssignableFrom(fieldValue.getClass())) {
|
||||
// Found a BasePermission static field
|
||||
BasePermission perm = (BasePermission) fieldValue;
|
||||
locallyDeclaredPermissionsByInteger.put(new Integer(perm.getMask()), perm);
|
||||
locallyDeclaredPermissionsByName.put(fields[i].getName(), perm);
|
||||
}
|
||||
} catch (Exception ignore) {}
|
||||
}
|
||||
}
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private char code;
|
||||
private int mask;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
private BasePermission(int mask, char code) {
|
||||
this.mask = mask;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Dynamically creates a <code>CumulativePermission</code> or <code>BasePermission</code> representing the
|
||||
* active bits in the passed mask.
|
||||
*
|
||||
* @param mask to build
|
||||
*
|
||||
* @return a Permission representing the requested object
|
||||
*/
|
||||
public static Permission buildFromMask(int mask) {
|
||||
if (locallyDeclaredPermissionsByInteger.containsKey(new Integer(mask))) {
|
||||
// The requested mask has an exactly match against a statically-defined BasePermission, so return it
|
||||
return (Permission) locallyDeclaredPermissionsByInteger.get(new Integer(mask));
|
||||
}
|
||||
|
||||
// To get this far, we have to use a CumulativePermission
|
||||
CumulativePermission permission = new CumulativePermission();
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
int permissionToCheck = 1 << i;
|
||||
|
||||
if ((mask & permissionToCheck) == permissionToCheck) {
|
||||
Permission p = (Permission) locallyDeclaredPermissionsByInteger.get(new Integer(permissionToCheck));
|
||||
Assert.state(p != null,
|
||||
"Mask " + permissionToCheck + " does not have a corresponding static BasePermission");
|
||||
permission.set(p);
|
||||
}
|
||||
}
|
||||
|
||||
return permission;
|
||||
}
|
||||
|
||||
public static Permission[] buildFromMask(int[] masks) {
|
||||
if ((masks == null) || (masks.length == 0)) {
|
||||
return new Permission[] {};
|
||||
}
|
||||
|
||||
List list = new Vector();
|
||||
|
||||
for (int i = 0; i < masks.length; i++) {
|
||||
list.add(BasePermission.buildFromMask(masks[i]));
|
||||
}
|
||||
|
||||
return (Permission[]) list.toArray(new Permission[] {});
|
||||
}
|
||||
|
||||
public static Permission buildFromName(String name) {
|
||||
Assert.isTrue(locallyDeclaredPermissionsByName.containsKey(name), "Unknown permission '" + name + "'");
|
||||
|
||||
return (Permission) locallyDeclaredPermissionsByName.get(name);
|
||||
}
|
||||
|
||||
public static Permission[] buildFromName(String[] names) {
|
||||
if ((names == null) || (names.length == 0)) {
|
||||
return new Permission[] {};
|
||||
}
|
||||
|
||||
List list = new Vector();
|
||||
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
list.add(BasePermission.buildFromName(names[i]));
|
||||
}
|
||||
|
||||
return (Permission[]) list.toArray(new Permission[] {});
|
||||
}
|
||||
|
||||
public boolean equals(Object arg0) {
|
||||
if (!(arg0 instanceof BasePermission)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BasePermission rhs = (BasePermission) arg0;
|
||||
|
||||
return (this.mask == rhs.getMask());
|
||||
}
|
||||
|
||||
public int getMask() {
|
||||
return mask;
|
||||
}
|
||||
|
||||
public String getPattern() {
|
||||
return AclFormattingUtils.printBinary(mask, code);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "BasePermission[" + getPattern() + "=" + mask + "]";
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
Basic implementation of access control lists (ACLs) interfaces.
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,114 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.acegisecurity.acls.jdbc;
|
||||
|
||||
import org.acegisecurity.acls.Acl;
|
||||
import org.acegisecurity.acls.AclService;
|
||||
import org.acegisecurity.acls.NotFoundException;
|
||||
import org.acegisecurity.acls.objectidentity.ObjectIdentity;
|
||||
import org.acegisecurity.acls.objectidentity.ObjectIdentityImpl;
|
||||
import org.acegisecurity.acls.sid.Sid;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
|
||||
/**
|
||||
* Simple JDBC-based implementation of <code>AclService</code>.<p>Requires the "dirty" flags in {@link
|
||||
* org.acegisecurity.acls.domain.AclImpl} and {@link org.acegisecurity.acls.domain.AccessControlEntryImpl} to be set,
|
||||
* so that the implementation can detect changed parameters easily.</p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
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 = ?)";
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
protected JdbcTemplate jdbcTemplate;
|
||||
private LookupStrategy lookupStrategy;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public JdbcAclService(DataSource dataSource, LookupStrategy lookupStrategy) {
|
||||
Assert.notNull(dataSource, "DataSource required");
|
||||
Assert.notNull(lookupStrategy, "LookupStrategy required");
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
this.lookupStrategy = lookupStrategy;
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public ObjectIdentity[] findChildren(ObjectIdentity parentIdentity) {
|
||||
Object[] args = {parentIdentity.getIdentifier(), parentIdentity.getJavaType().getName()};
|
||||
List objects = jdbcTemplate.query(selectAclObjectWithParent, args,
|
||||
new RowMapper() {
|
||||
public Object mapRow(ResultSet rs, int rowNum)
|
||||
throws SQLException {
|
||||
String javaType = rs.getString("class");
|
||||
String identifier = rs.getString("obj_id");
|
||||
|
||||
return new ObjectIdentityImpl(javaType, identifier);
|
||||
}
|
||||
});
|
||||
|
||||
return (ObjectIdentityImpl[]) objects.toArray(new ObjectIdentityImpl[] {});
|
||||
}
|
||||
|
||||
public Acl readAclById(ObjectIdentity object, Sid[] sids)
|
||||
throws NotFoundException {
|
||||
Map map = readAclsById(new ObjectIdentity[] {object}, sids);
|
||||
|
||||
if (map.size() == 0) {
|
||||
throw new NotFoundException("Could not find ACL");
|
||||
} else {
|
||||
return (Acl) map.get(object);
|
||||
}
|
||||
}
|
||||
|
||||
public Acl readAclById(ObjectIdentity object) throws NotFoundException {
|
||||
return readAclById(object, null);
|
||||
}
|
||||
|
||||
public Map readAclsById(ObjectIdentity[] objects) {
|
||||
return readAclsById(objects, null);
|
||||
}
|
||||
|
||||
public Map readAclsById(ObjectIdentity[] objects, Sid[] sids)
|
||||
throws NotFoundException {
|
||||
return lookupStrategy.readAclsById(objects, sids);
|
||||
}
|
||||
}
|
||||
@@ -1,368 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.acegisecurity.acls.jdbc;
|
||||
|
||||
import org.acegisecurity.Authentication;
|
||||
|
||||
import org.acegisecurity.acls.AccessControlEntry;
|
||||
import org.acegisecurity.acls.Acl;
|
||||
import org.acegisecurity.acls.AlreadyExistsException;
|
||||
import org.acegisecurity.acls.ChildrenExistException;
|
||||
import org.acegisecurity.acls.MutableAcl;
|
||||
import org.acegisecurity.acls.MutableAclService;
|
||||
import org.acegisecurity.acls.NotFoundException;
|
||||
import org.acegisecurity.acls.domain.AccessControlEntryImpl;
|
||||
import org.acegisecurity.acls.objectidentity.ObjectIdentity;
|
||||
import org.acegisecurity.acls.objectidentity.ObjectIdentityImpl;
|
||||
import org.acegisecurity.acls.sid.GrantedAuthoritySid;
|
||||
import org.acegisecurity.acls.sid.PrincipalSid;
|
||||
import org.acegisecurity.acls.sid.Sid;
|
||||
|
||||
import org.acegisecurity.context.SecurityContextHolder;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
|
||||
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
|
||||
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
|
||||
/**
|
||||
* Provides a base implementation of {@link MutableAclService}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author Johannes Zlattinger
|
||||
* @version $Id$
|
||||
*/
|
||||
public class JdbcMutableAclService extends JdbcAclService implements MutableAclService {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private AclCache aclCache;
|
||||
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 (id, class) VALUES (null, ?)";
|
||||
private String insertEntry = "INSERT INTO acl_entry "
|
||||
+ "(id, acl_object_identity, ace_order, sid, mask, granting, audit_success, audit_failure)"
|
||||
+ "VALUES (null, ?, ?, ?, ?, ?, ?, ?)";
|
||||
private String insertObjectIdentity = "INSERT INTO acl_object_identity "
|
||||
+ "(id, object_id_class, object_id_identity, owner_sid, entries_inheriting) " + "VALUES (null, ?, ?, ?, ?)";
|
||||
private String insertSid = "INSERT INTO acl_sid (id, principal, sid) VALUES (null, ?, ?)";
|
||||
private String selectClassPrimaryKey = "SELECT id FROM acl_class WHERE class=?";
|
||||
private String selectCountObjectIdentityRowsForParticularClassNameString = "SELECT COUNT(acl_object_identity.id) "
|
||||
+ "FROM acl_object_identity, acl_class WHERE acl_class.id = acl_object_identity.object_id_class and 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 "
|
||||
+ "parent_object = ?, owner_sid = ?, entries_inheriting = ?" + "where id = ?";
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public JdbcMutableAclService(DataSource dataSource, LookupStrategy lookupStrategy, AclCache aclCache) {
|
||||
super(dataSource, lookupStrategy);
|
||||
Assert.notNull(aclCache, "AclCache required");
|
||||
this.aclCache = aclCache;
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public MutableAcl createAcl(ObjectIdentity objectIdentity)
|
||||
throws AlreadyExistsException {
|
||||
Assert.notNull(objectIdentity, "Object Identity required");
|
||||
|
||||
// Check this object identity hasn't already been persisted
|
||||
if (retrieveObjectIdentityPrimaryKey(objectIdentity) != null) {
|
||||
throw new AlreadyExistsException("Object identity '" + objectIdentity + "' already exists");
|
||||
}
|
||||
|
||||
// Need to retrieve the current principal, in order to know who "owns" this ACL (can be changed later on)
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
PrincipalSid sid = new PrincipalSid(auth);
|
||||
|
||||
// Create the acl_object_identity row
|
||||
createObjectIdentity(objectIdentity, sid);
|
||||
|
||||
// Retrieve the ACL via superclass (ensures cache registration, proper retrieval etc)
|
||||
Acl acl = readAclById(objectIdentity);
|
||||
Assert.isInstanceOf(MutableAcl.class, acl, "MutableAcl should be been returned");
|
||||
|
||||
return (MutableAcl) acl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new row in acl_entry for every ACE defined in the passed MutableAcl object.
|
||||
*
|
||||
* @param acl containing the ACEs to insert
|
||||
*/
|
||||
protected void createEntries(final MutableAcl acl) {
|
||||
jdbcTemplate.batchUpdate(insertEntry,
|
||||
new BatchPreparedStatementSetter() {
|
||||
public int getBatchSize() {
|
||||
return acl.getEntries().length;
|
||||
}
|
||||
|
||||
public void setValues(PreparedStatement stmt, int i)
|
||||
throws SQLException {
|
||||
AccessControlEntry entry_ = (AccessControlEntry) Array.get(acl.getEntries(), i);
|
||||
Assert.isTrue(entry_ instanceof AccessControlEntryImpl, "Unknown ACE class");
|
||||
|
||||
AccessControlEntryImpl entry = (AccessControlEntryImpl) entry_;
|
||||
|
||||
stmt.setLong(1, ((Long) acl.getId()).longValue());
|
||||
stmt.setInt(2, i);
|
||||
stmt.setLong(3, createOrRetrieveSidPrimaryKey(entry.getSid(), true).longValue());
|
||||
stmt.setInt(4, entry.getPermission().getMask());
|
||||
stmt.setBoolean(5, entry.isGranting());
|
||||
stmt.setBoolean(6, entry.isAuditSuccess());
|
||||
stmt.setBoolean(7, entry.isAuditFailure());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an entry in the acl_object_identity table for the passed ObjectIdentity. The Sid is also
|
||||
* necessary, as acl_object_identity has defined the sid column as non-null.
|
||||
*
|
||||
* @param object to represent an acl_object_identity for
|
||||
* @param owner for the SID column (will be created if there is no acl_sid entry for this particular Sid already)
|
||||
*/
|
||||
protected void createObjectIdentity(ObjectIdentity object, Sid owner) {
|
||||
Long sidId = createOrRetrieveSidPrimaryKey(owner, true);
|
||||
Long classId = createOrRetrieveClassPrimaryKey(object.getJavaType(), true);
|
||||
jdbcTemplate.update(insertObjectIdentity,
|
||||
new Object[] {classId, object.getIdentifier().toString(), sidId, new Boolean(true)});
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the primary key from acl_class, creating a new row if needed and the allowCreate property is
|
||||
* true.
|
||||
*
|
||||
* @param clazz to find or create an entry for (this implementation uses the fully-qualified class name String)
|
||||
* @param allowCreate true if creation is permitted if not found
|
||||
*
|
||||
* @return the primary key or null if not found
|
||||
*/
|
||||
protected Long createOrRetrieveClassPrimaryKey(Class clazz, boolean allowCreate) {
|
||||
List classIds = jdbcTemplate.queryForList(selectClassPrimaryKey, new Object[] {clazz.getName()}, Long.class);
|
||||
Long classId = null;
|
||||
|
||||
if (classIds.isEmpty()) {
|
||||
if (allowCreate) {
|
||||
classId = null;
|
||||
jdbcTemplate.update(insertClass, new Object[] {clazz.getName()});
|
||||
Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), "Transaction must be running");
|
||||
classId = new Long(jdbcTemplate.queryForLong(identityQuery));
|
||||
}
|
||||
} else {
|
||||
classId = (Long) classIds.iterator().next();
|
||||
}
|
||||
|
||||
return classId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the primary key from acl_sid, creating a new row if needed and the allowCreate property is
|
||||
* true.
|
||||
*
|
||||
* @param sid to find or create
|
||||
* @param allowCreate true if creation is permitted if not found
|
||||
*
|
||||
* @return the primary key or null if not found
|
||||
*
|
||||
* @throws IllegalArgumentException DOCUMENT ME!
|
||||
*/
|
||||
protected Long createOrRetrieveSidPrimaryKey(Sid sid, boolean allowCreate) {
|
||||
Assert.notNull(sid, "Sid required");
|
||||
|
||||
String sidName = null;
|
||||
boolean principal = true;
|
||||
|
||||
if (sid instanceof PrincipalSid) {
|
||||
sidName = ((PrincipalSid) sid).getPrincipal();
|
||||
} else if (sid instanceof GrantedAuthoritySid) {
|
||||
sidName = ((GrantedAuthoritySid) sid).getGrantedAuthority();
|
||||
principal = false;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported implementation of Sid");
|
||||
}
|
||||
|
||||
List sidIds = jdbcTemplate.queryForList(selectSidPrimaryKey, new Object[] {new Boolean(principal), sidName},
|
||||
Long.class);
|
||||
Long sidId = null;
|
||||
|
||||
if (sidIds.isEmpty()) {
|
||||
if (allowCreate) {
|
||||
sidId = null;
|
||||
jdbcTemplate.update(insertSid, new Object[] {new Boolean(principal), sidName});
|
||||
Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), "Transaction must be running");
|
||||
sidId = new Long(jdbcTemplate.queryForLong(identityQuery));
|
||||
}
|
||||
} else {
|
||||
sidId = (Long) sidIds.iterator().next();
|
||||
}
|
||||
|
||||
return sidId;
|
||||
}
|
||||
|
||||
public void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren)
|
||||
throws ChildrenExistException {
|
||||
Assert.notNull(objectIdentity, "Object Identity required");
|
||||
Assert.notNull(objectIdentity.getIdentifier(), "Object Identity doesn't provide an identifier");
|
||||
|
||||
// Recursively call this method for children, or handle children if they don't want automatic recursion
|
||||
ObjectIdentity[] children = findChildren(objectIdentity);
|
||||
|
||||
if (deleteChildren) {
|
||||
for (int i = 0; i < children.length; i++) {
|
||||
deleteAcl(children[i], true);
|
||||
}
|
||||
} else if (children.length > 0) {
|
||||
throw new ChildrenExistException("Cannot delete '" + objectIdentity + "' (has " + children.length
|
||||
+ " children)");
|
||||
}
|
||||
|
||||
// Delete this ACL's ACEs in the acl_entry table
|
||||
deleteEntries(objectIdentity);
|
||||
|
||||
// Delete this ACL's acl_object_identity row
|
||||
deleteObjectIdentityAndOptionallyClass(objectIdentity);
|
||||
|
||||
// Clear the cache
|
||||
aclCache.evictFromCache(objectIdentity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes all ACEs defined in the acl_entry table belonging to the presented ObjectIdentity
|
||||
*
|
||||
* @param oid the rows in acl_entry to delete
|
||||
*/
|
||||
protected void deleteEntries(ObjectIdentity oid) {
|
||||
jdbcTemplate.update(deleteEntryByObjectIdentityForeignKey, new Object[] {retrieveObjectIdentityPrimaryKey(oid)});
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a single row from acl_object_identity that is associated with the presented ObjectIdentity. In
|
||||
* addition, deletes the corresponding row from acl_class if there are no more entries in acl_object_identity that
|
||||
* use that particular acl_class. This keeps the acl_class table reasonably small.
|
||||
*
|
||||
* @param oid to delete the acl_object_identity (and clean up acl_class for that class name if appropriate)
|
||||
*/
|
||||
protected void deleteObjectIdentityAndOptionallyClass(ObjectIdentity oid) {
|
||||
// Delete the acl_object_identity row
|
||||
jdbcTemplate.update(deleteObjectIdentityByPrimaryKey, new Object[] {retrieveObjectIdentityPrimaryKey(oid)});
|
||||
|
||||
// Delete the acl_class row, assuming there are no other references to it in acl_object_identity
|
||||
Object[] className = {oid.getJavaType().getName()};
|
||||
long numObjectIdentities = jdbcTemplate.queryForLong(selectCountObjectIdentityRowsForParticularClassNameString,
|
||||
className);
|
||||
|
||||
if (numObjectIdentities == 0) {
|
||||
// No more rows
|
||||
jdbcTemplate.update(deleteClassByClassNameString, className);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the primary key from the acl_object_identity table for the passed ObjectIdentity. Unlike some
|
||||
* other methods in this implementation, this method will NOT create a row (use {@link
|
||||
* #createObjectIdentity(ObjectIdentity, Sid)} instead).
|
||||
*
|
||||
* @param oid to find
|
||||
*
|
||||
* @return the object identity or null if not found
|
||||
*/
|
||||
protected Long retrieveObjectIdentityPrimaryKey(ObjectIdentity oid) {
|
||||
try {
|
||||
return new Long(jdbcTemplate.queryForLong(selectObjectIdentityPrimaryKey,
|
||||
new Object[] {oid.getJavaType().getName(), oid.getIdentifier()}));
|
||||
} catch (DataAccessException notFound) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation will simply delete all ACEs in the database and recreate them on each invocation of
|
||||
* this method. A more comprehensive implementation might use dirty state checking, or more likely use ORM
|
||||
* capabilities for create, update and delete operations of {@link MutableAcl}.
|
||||
*
|
||||
* @param acl DOCUMENT ME!
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*
|
||||
* @throws NotFoundException DOCUMENT ME!
|
||||
*/
|
||||
public MutableAcl updateAcl(MutableAcl acl) throws NotFoundException {
|
||||
Assert.notNull(acl.getId(), "Object Identity doesn't provide an identifier");
|
||||
|
||||
// Delete this ACL's ACEs in the acl_entry table
|
||||
deleteEntries(acl.getObjectIdentity());
|
||||
|
||||
// Create this ACL's ACEs in the acl_entry table
|
||||
createEntries(acl);
|
||||
|
||||
// Change the mutable columns in acl_object_identity
|
||||
updateObjectIdentity(acl);
|
||||
|
||||
// Clear the cache
|
||||
aclCache.evictFromCache(acl.getObjectIdentity());
|
||||
|
||||
// Retrieve the ACL via superclass (ensures cache registration, proper retrieval etc)
|
||||
return (MutableAcl) super.readAclById(acl.getObjectIdentity());
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an existing acl_object_identity row, with new information presented in the passed MutableAcl
|
||||
* object. Also will create an acl_sid entry if needed for the Sid that owns the MutableAcl.
|
||||
*
|
||||
* @param acl to modify (a row must already exist in acl_object_identity)
|
||||
*
|
||||
* @throws NotFoundException DOCUMENT ME!
|
||||
*/
|
||||
protected void updateObjectIdentity(MutableAcl acl) {
|
||||
Long parentId = null;
|
||||
|
||||
if (acl.getParentAcl() != null) {
|
||||
Assert.isInstanceOf(ObjectIdentityImpl.class, acl.getParentAcl().getObjectIdentity(),
|
||||
"Implementation only supports ObjectIdentityImpl");
|
||||
|
||||
ObjectIdentityImpl oii = (ObjectIdentityImpl) acl.getParentAcl().getObjectIdentity();
|
||||
parentId = retrieveObjectIdentityPrimaryKey(oii);
|
||||
}
|
||||
|
||||
Assert.notNull(acl.getOwner(), "Owner is required in this implementation");
|
||||
|
||||
Long ownerSid = createOrRetrieveSidPrimaryKey(acl.getOwner(), true);
|
||||
int count = jdbcTemplate.update(updateObjectIdentity,
|
||||
new Object[] {parentId, ownerSid, new Boolean(acl.isEntriesInheriting()), acl.getId()});
|
||||
|
||||
if (count != 1) {
|
||||
throw new NotFoundException("Unable to locate ACL to update");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
JDBC-based persistence of ACL information.
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,5 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
Provides indirection between ACL packages and domain objects.
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,5 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
Interfaces and shared classes to manage access control lists (ACLs) for domain object instances.
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,32 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.acegisecurity.acls.sid;
|
||||
|
||||
import org.acegisecurity.Authentication;
|
||||
|
||||
|
||||
/**
|
||||
* Strategy interface that provides an ability to determine the {@link Sid} instances applicable
|
||||
* for an {@link Authentication}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public interface SidRetrievalStrategy {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public Sid[] getSids(Authentication authentication);
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.acegisecurity.acls.sid;
|
||||
|
||||
import org.acegisecurity.Authentication;
|
||||
import org.acegisecurity.GrantedAuthority;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
|
||||
/**
|
||||
* Basic implementation of {@link SidRetrievalStrategy} that creates a {@link Sid} for the principal, as well as
|
||||
* every granted authority the principal holds.<p>The returned array will always contain the {@link PrincipalSid}
|
||||
* before any {@link GrantedAuthoritySid} elements.</p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class SidRetrievalStrategyImpl implements SidRetrievalStrategy {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public Sid[] getSids(Authentication authentication) {
|
||||
List list = new Vector();
|
||||
list.add(new PrincipalSid(authentication));
|
||||
|
||||
GrantedAuthority[] authorities = authentication.getAuthorities();
|
||||
|
||||
for (int i = 0; i < authorities.length; i++) {
|
||||
list.add(new GrantedAuthoritySid(authorities[i]));
|
||||
}
|
||||
|
||||
return (Sid[]) list.toArray(new Sid[] {});
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
Provides indirection between ACL packages and security identities, such as principals and GrantedAuthority[]s.
|
||||
</body>
|
||||
</html>
|
||||
@@ -29,7 +29,6 @@ import java.security.Principal;
|
||||
public class PrincipalAcegiUserToken extends AbstractAdapterAuthenticationToken implements Principal {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private Object principal;
|
||||
private String password;
|
||||
private String username;
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.acegisecurity.afterinvocation;
|
||||
|
||||
import org.acegisecurity.Authentication;
|
||||
import org.acegisecurity.ConfigAttribute;
|
||||
|
||||
import org.acegisecurity.acls.Acl;
|
||||
import org.acegisecurity.acls.AclService;
|
||||
import org.acegisecurity.acls.NotFoundException;
|
||||
import org.acegisecurity.acls.Permission;
|
||||
import org.acegisecurity.acls.domain.BasePermission;
|
||||
import org.acegisecurity.acls.objectidentity.ObjectIdentity;
|
||||
import org.acegisecurity.acls.objectidentity.ObjectIdentityRetrievalStrategy;
|
||||
import org.acegisecurity.acls.objectidentity.ObjectIdentityRetrievalStrategyImpl;
|
||||
import org.acegisecurity.acls.sid.Sid;
|
||||
import org.acegisecurity.acls.sid.SidRetrievalStrategy;
|
||||
import org.acegisecurity.acls.sid.SidRetrievalStrategyImpl;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @author $author$
|
||||
* @version $Revision$
|
||||
*/
|
||||
public abstract class AbstractAclProvider implements AfterInvocationProvider {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private AclService aclService;
|
||||
private Class processDomainObjectClass = Object.class;
|
||||
private ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl();
|
||||
private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();
|
||||
private String processConfigAttribute;
|
||||
private Permission[] requirePermission = {BasePermission.READ};
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public AbstractAclProvider(AclService aclService, String processConfigAttribute, Permission[] requirePermission) {
|
||||
Assert.hasText(processConfigAttribute, "A processConfigAttribute is mandatory");
|
||||
Assert.notNull(aclService, "An AclService is mandatory");
|
||||
|
||||
if ((requirePermission == null) || (requirePermission.length == 0)) {
|
||||
throw new IllegalArgumentException("One or more requirePermission entries is mandatory");
|
||||
}
|
||||
|
||||
this.aclService = aclService;
|
||||
this.processConfigAttribute = processConfigAttribute;
|
||||
this.requirePermission = requirePermission;
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
protected Class getProcessDomainObjectClass() {
|
||||
return processDomainObjectClass;
|
||||
}
|
||||
|
||||
protected boolean hasPermission(Authentication authentication, Object domainObject) {
|
||||
// Obtain the OID applicable to the domain object
|
||||
ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy.getObjectIdentity(domainObject);
|
||||
|
||||
// Obtain the SIDs applicable to the principal
|
||||
Sid[] sids = sidRetrievalStrategy.getSids(authentication);
|
||||
|
||||
Acl acl = null;
|
||||
|
||||
try {
|
||||
// Lookup only ACLs for SIDs we're interested in
|
||||
acl = aclService.readAclById(objectIdentity, sids);
|
||||
|
||||
return acl.isGranted(requirePermission, sids, false);
|
||||
} catch (NotFoundException ignore) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void setObjectIdentityRetrievalStrategy(ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) {
|
||||
Assert.notNull(objectIdentityRetrievalStrategy, "ObjectIdentityRetrievalStrategy required");
|
||||
this.objectIdentityRetrievalStrategy = objectIdentityRetrievalStrategy;
|
||||
}
|
||||
|
||||
protected void setProcessConfigAttribute(String processConfigAttribute) {
|
||||
Assert.hasText(processConfigAttribute, "A processConfigAttribute is mandatory");
|
||||
this.processConfigAttribute = processConfigAttribute;
|
||||
}
|
||||
|
||||
public void setProcessDomainObjectClass(Class processDomainObjectClass) {
|
||||
Assert.notNull(processDomainObjectClass, "processDomainObjectClass cannot be set to null");
|
||||
this.processDomainObjectClass = processDomainObjectClass;
|
||||
}
|
||||
|
||||
public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) {
|
||||
Assert.notNull(sidRetrievalStrategy, "SidRetrievalStrategy required");
|
||||
this.sidRetrievalStrategy = sidRetrievalStrategy;
|
||||
}
|
||||
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
if ((attribute.getAttribute() != null) && attribute.getAttribute().equals(this.processConfigAttribute)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation supports any type of class, because it does not query the presented secure object.
|
||||
*
|
||||
* @param clazz the secure object
|
||||
*
|
||||
* @return always <code>true</code>
|
||||
*/
|
||||
public boolean supports(Class clazz) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
-133
@@ -1,133 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.acegisecurity.afterinvocation;
|
||||
|
||||
import org.acegisecurity.AccessDeniedException;
|
||||
import org.acegisecurity.Authentication;
|
||||
import org.acegisecurity.AuthorizationServiceException;
|
||||
import org.acegisecurity.ConfigAttribute;
|
||||
import org.acegisecurity.ConfigAttributeDefinition;
|
||||
|
||||
import org.acegisecurity.acls.Acl;
|
||||
import org.acegisecurity.acls.AclService;
|
||||
import org.acegisecurity.acls.Permission;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
|
||||
/**
|
||||
* <p>Given a <code>Collection</code> of domain object instances returned from a secure object invocation, remove
|
||||
* any <code>Collection</code> elements the principal does not have appropriate permission to access as defined by the
|
||||
* {@link AclService}.</p>
|
||||
* <p>The <code>AclService</code> is used to retrieve the access control list (ACL) permissions associated with
|
||||
* each <code>Collection</code> domain object instance element for the current <code>Authentication</code> object.</p>
|
||||
* <p>This after invocation provider will fire if any {@link ConfigAttribute#getAttribute()} matches the {@link
|
||||
* #processConfigAttribute}. The provider will then lookup the ACLs from the <code>AclService</code> and ensure the
|
||||
* principal is {@link Acl#isGranted(org.acegisecurity.acls.Permission[], org.acegisecurity.acls.sid.Sid[], boolean)}
|
||||
* when presenting the {@link #requirePermission} array to that method.</p>
|
||||
* <p>If the principal does not have permission, that element will not be included in the returned
|
||||
* <code>Collection</code>.</p>
|
||||
* <p>Often users will setup a <code>BasicAclEntryAfterInvocationProvider</code> with a {@link
|
||||
* #processConfigAttribute} of <code>AFTER_ACL_COLLECTION_READ</code> and a {@link #requirePermission} of
|
||||
* <code>BasePermission.READ</code>. These are also the defaults.</p>
|
||||
* <p>If the provided <code>returnObject</code> is <code>null</code>, a <code>null</code><code>Collection</code>
|
||||
* will be returned. If the provided <code>returnObject</code> is not a <code>Collection</code>, an {@link
|
||||
* AuthorizationServiceException} will be thrown.</p>
|
||||
* <p>All comparisons and prefixes are case sensitive.</p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author Paulo Neves
|
||||
* @version $Id$
|
||||
*/
|
||||
public class AclEntryAfterInvocationCollectionFilteringProvider extends AbstractAclProvider {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
protected static final Log logger = LogFactory.getLog(AclEntryAfterInvocationCollectionFilteringProvider.class);
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public AclEntryAfterInvocationCollectionFilteringProvider(AclService aclService, Permission[] requirePermission) {
|
||||
super(aclService, "AFTER_ACL_COLLECTION_READ", requirePermission);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public Object decide(Authentication authentication, Object object, ConfigAttributeDefinition config,
|
||||
Object returnedObject) throws AccessDeniedException {
|
||||
Iterator iter = config.getConfigAttributes();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
ConfigAttribute attr = (ConfigAttribute) iter.next();
|
||||
|
||||
if (this.supports(attr)) {
|
||||
// Need to process the Collection for this invocation
|
||||
if (returnedObject == null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Return object is null, skipping");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
Filterer filterer = null;
|
||||
|
||||
if (returnedObject instanceof Collection) {
|
||||
Collection collection = (Collection) returnedObject;
|
||||
filterer = new CollectionFilterer(collection);
|
||||
} else if (returnedObject.getClass().isArray()) {
|
||||
Object[] array = (Object[]) returnedObject;
|
||||
filterer = new ArrayFilterer(array);
|
||||
} else {
|
||||
throw new AuthorizationServiceException(
|
||||
"A Collection or an array (or null) was required as the returnedObject, but the returnedObject was: "
|
||||
+ returnedObject);
|
||||
}
|
||||
|
||||
// Locate unauthorised Collection elements
|
||||
Iterator collectionIter = filterer.iterator();
|
||||
|
||||
while (collectionIter.hasNext()) {
|
||||
Object domainObject = collectionIter.next();
|
||||
|
||||
boolean hasPermission = false;
|
||||
|
||||
if (domainObject == null) {
|
||||
hasPermission = true;
|
||||
} else if (!getProcessDomainObjectClass().isAssignableFrom(domainObject.getClass())) {
|
||||
hasPermission = true;
|
||||
} else {
|
||||
hasPermission = hasPermission(authentication, domainObject);
|
||||
|
||||
if (!hasPermission) {
|
||||
filterer.remove(domainObject);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Principal is NOT authorised for element: " + domainObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return filterer.getFilteredObject();
|
||||
}
|
||||
}
|
||||
|
||||
return returnedObject;
|
||||
}
|
||||
}
|
||||
-119
@@ -1,119 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.acegisecurity.afterinvocation;
|
||||
|
||||
import org.acegisecurity.AccessDeniedException;
|
||||
import org.acegisecurity.AcegiMessageSource;
|
||||
import org.acegisecurity.Authentication;
|
||||
import org.acegisecurity.ConfigAttribute;
|
||||
import org.acegisecurity.ConfigAttributeDefinition;
|
||||
|
||||
import org.acegisecurity.acls.Acl;
|
||||
import org.acegisecurity.acls.AclService;
|
||||
import org.acegisecurity.acls.Permission;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.MessageSourceAware;
|
||||
import org.springframework.context.support.MessageSourceAccessor;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
|
||||
/**
|
||||
* <p>Given a domain object instance returned from a secure object invocation, ensures the principal has
|
||||
* appropriate permission as defined by the {@link AclService}.</p>
|
||||
* <p>The <code>AclService</code> is used to retrieve the access control list (ACL) permissions associated with a
|
||||
* domain object instance for the current <code>Authentication</code> object.</p>
|
||||
* <p>This after invocation provider will fire if any {@link ConfigAttribute#getAttribute()} matches the {@link
|
||||
* #processConfigAttribute}. The provider will then lookup the ACLs from the <code>AclService</code> and ensure the
|
||||
* principal is {@link Acl#isGranted(org.acegisecurity.acls.Permission[], org.acegisecurity.acls.sid.Sid[], boolean)}
|
||||
* when presenting the {@link #requirePermission} array to that method.</p>
|
||||
* <p>Often users will setup an <code>AclEntryAfterInvocationProvider</code> with a {@link
|
||||
* #processConfigAttribute} of <code>AFTER_ACL_READ</code> and a {@link #requirePermission} of
|
||||
* <code>BasePermission.READ</code>. These are also the defaults.</p>
|
||||
* <p>If the principal does not have sufficient permissions, an <code>AccessDeniedException</code> will be thrown.</p>
|
||||
* <p>If the provided <code>returnObject</code> is <code>null</code>, permission will always be granted and
|
||||
* <code>null</code> will be returned.</p>
|
||||
* <p>All comparisons and prefixes are case sensitive.</p>
|
||||
*/
|
||||
public class AclEntryAfterInvocationProvider extends AbstractAclProvider implements MessageSourceAware {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
protected static final Log logger = LogFactory.getLog(AclEntryAfterInvocationProvider.class);
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor();
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public AclEntryAfterInvocationProvider(AclService aclService, Permission[] requirePermission) {
|
||||
super(aclService, "AFTER_ACL_READ", requirePermission);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public Object decide(Authentication authentication, Object object, ConfigAttributeDefinition config,
|
||||
Object returnedObject) throws AccessDeniedException {
|
||||
Iterator iter = config.getConfigAttributes();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
ConfigAttribute attr = (ConfigAttribute) iter.next();
|
||||
|
||||
if (this.supports(attr)) {
|
||||
// Need to make an access decision on this invocation
|
||||
if (returnedObject == null) {
|
||||
// AclManager interface contract prohibits nulls
|
||||
// As they have permission to null/nothing, grant access
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Return object is null, skipping");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!getProcessDomainObjectClass().isAssignableFrom(returnedObject.getClass())) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Return object is not applicable for this provider, skipping");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (hasPermission(authentication, returnedObject)) {
|
||||
return returnedObject;
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Denying access");
|
||||
}
|
||||
|
||||
throw new AccessDeniedException(messages.getMessage(
|
||||
"BasicAclEntryAfterInvocationProvider.noPermission",
|
||||
new Object[] {authentication.getName(), returnedObject},
|
||||
"Authentication {0} has NO permissions to the domain object {1}"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return returnedObject;
|
||||
}
|
||||
|
||||
public void setMessageSource(MessageSource messages) {
|
||||
this.messages = new MessageSourceAccessor(messages);
|
||||
}
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.acegisecurity.afterinvocation;
|
||||
|
||||
import org.apache.commons.collections.iterators.ArrayIterator;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
* A filter used to filter arrays.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author Paulo Neves
|
||||
* @version $Id$
|
||||
*/
|
||||
class ArrayFilterer implements Filterer {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
protected static final Log logger = LogFactory.getLog(BasicAclEntryAfterInvocationCollectionFilteringProvider.class);
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private Set removeList;
|
||||
private Object[] list;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
ArrayFilterer(Object[] list) {
|
||||
this.list = list;
|
||||
|
||||
// Collect the removed objects to a HashSet so that
|
||||
// it is fast to lookup them when a filtered array
|
||||
// is constructed.
|
||||
removeList = new HashSet();
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
*
|
||||
* @see org.acegisecurity.afterinvocation.Filterer#getFilteredObject()
|
||||
*/
|
||||
public Object getFilteredObject() {
|
||||
// Recreate an array of same type and filter the removed objects.
|
||||
int originalSize = list.length;
|
||||
int sizeOfResultingList = originalSize - removeList.size();
|
||||
Object[] filtered = (Object[]) Array.newInstance(list.getClass().getComponentType(), sizeOfResultingList);
|
||||
|
||||
for (int i = 0, j = 0; i < list.length; i++) {
|
||||
Object object = list[i];
|
||||
|
||||
if (!removeList.contains(object)) {
|
||||
filtered[j] = object;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Original array contained " + originalSize + " elements; now contains " + sizeOfResultingList
|
||||
+ " elements");
|
||||
}
|
||||
|
||||
return filtered;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see org.acegisecurity.afterinvocation.Filterer#iterator()
|
||||
*/
|
||||
public Iterator iterator() {
|
||||
return new ArrayIterator(list);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see org.acegisecurity.afterinvocation.Filterer#remove(java.lang.Object)
|
||||
*/
|
||||
public void remove(Object object) {
|
||||
removeList.add(object);
|
||||
}
|
||||
}
|
||||
+203
-31
@@ -12,6 +12,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.acegisecurity.afterinvocation;
|
||||
|
||||
import org.acegisecurity.AccessDeniedException;
|
||||
@@ -25,6 +26,7 @@ import org.acegisecurity.acl.AclManager;
|
||||
import org.acegisecurity.acl.basic.BasicAclEntry;
|
||||
import org.acegisecurity.acl.basic.SimpleAclEntry;
|
||||
|
||||
import org.apache.commons.collections.iterators.ArrayIterator;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
@@ -32,8 +34,12 @@ import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
@@ -129,40 +135,42 @@ public class BasicAclEntryAfterInvocationCollectionFilteringProvider implements
|
||||
|
||||
boolean hasPermission = false;
|
||||
|
||||
AclEntry[] acls = null;
|
||||
|
||||
if (domainObject == null) {
|
||||
hasPermission = true;
|
||||
} else if (!processDomainObjectClass.isAssignableFrom(domainObject.getClass())) {
|
||||
hasPermission = true;
|
||||
} else {
|
||||
AclEntry[] acls = aclManager.getAcls(domainObject, authentication);
|
||||
acls = aclManager.getAcls(domainObject, authentication);
|
||||
}
|
||||
|
||||
if ((acls != null) && (acls.length != 0)) {
|
||||
for (int i = 0; i < acls.length; i++) {
|
||||
// Locate processable AclEntrys
|
||||
if (acls[i] instanceof BasicAclEntry) {
|
||||
BasicAclEntry processableAcl = (BasicAclEntry) acls[i];
|
||||
if ((acls != null) && (acls.length != 0)) {
|
||||
for (int i = 0; i < acls.length; i++) {
|
||||
// Locate processable AclEntrys
|
||||
if (acls[i] instanceof BasicAclEntry) {
|
||||
BasicAclEntry processableAcl = (BasicAclEntry) acls[i];
|
||||
|
||||
// See if principal has any of the required permissions
|
||||
for (int y = 0; y < requirePermission.length; y++) {
|
||||
if (processableAcl.isPermitted(requirePermission[y])) {
|
||||
hasPermission = true;
|
||||
// See if principal has any of the required permissions
|
||||
for (int y = 0; y < requirePermission.length; y++) {
|
||||
if (processableAcl.isPermitted(requirePermission[y])) {
|
||||
hasPermission = true;
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Principal is authorised for element: " + domainObject
|
||||
+ " due to ACL: " + processableAcl.toString());
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Principal is authorised for element: " + domainObject
|
||||
+ " due to ACL: " + processableAcl.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasPermission) {
|
||||
filterer.remove(domainObject);
|
||||
if (!hasPermission) {
|
||||
filterer.remove(domainObject);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Principal is NOT authorised for element: " + domainObject);
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Principal is NOT authorised for element: " + domainObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -203,18 +211,6 @@ public class BasicAclEntryAfterInvocationCollectionFilteringProvider implements
|
||||
this.requirePermission = requirePermission;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow setting permissions with String literals instead of integers as {@link
|
||||
* #setRequirePermission(int[])}
|
||||
*
|
||||
* @param requirePermission permission literals
|
||||
*
|
||||
* @see SimpleAclEntry#parsePermissions(String[]) for valid values
|
||||
*/
|
||||
public void setRequirePermissionFromString(String[] requirePermission) {
|
||||
setRequirePermission(SimpleAclEntry.parsePermissions(requirePermission));
|
||||
}
|
||||
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
if ((attribute.getAttribute() != null) && attribute.getAttribute().equals(getProcessConfigAttribute())) {
|
||||
return true;
|
||||
@@ -234,3 +230,179 @@ public class BasicAclEntryAfterInvocationCollectionFilteringProvider implements
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Filter strategy interface.
|
||||
*/
|
||||
interface Filterer {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Gets the filtered collection or array.
|
||||
*
|
||||
* @return the filtered collection or array
|
||||
*/
|
||||
public Object getFilteredObject();
|
||||
|
||||
/**
|
||||
* Returns an iterator over the filtered collection or array.
|
||||
*
|
||||
* @return an Iterator
|
||||
*/
|
||||
public Iterator iterator();
|
||||
|
||||
/**
|
||||
* Removes the the given object from the resulting list.
|
||||
*
|
||||
* @param object the object to be removed
|
||||
*/
|
||||
public void remove(Object object);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A filter used to filter Collections.
|
||||
*/
|
||||
class CollectionFilterer implements Filterer {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
protected static final Log logger = LogFactory.getLog(BasicAclEntryAfterInvocationCollectionFilteringProvider.class);
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private Collection collection;
|
||||
|
||||
// collectionIter offers significant performance optimisations (as
|
||||
// per acegisecurity-developer mailing list conversation 19/5/05)
|
||||
private Iterator collectionIter;
|
||||
private Set removeList;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
CollectionFilterer(Collection collection) {
|
||||
this.collection = collection;
|
||||
|
||||
// We create a Set of objects to be removed from the Collection,
|
||||
// as ConcurrentModificationException prevents removal during
|
||||
// iteration, and making a new Collection to be returned is
|
||||
// problematic as the original Collection implementation passed
|
||||
// to the method may not necessarily be re-constructable (as
|
||||
// the Collection(collection) constructor is not guaranteed and
|
||||
// manually adding may lose sort order or other capabilities)
|
||||
removeList = new HashSet();
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
*
|
||||
* @see org.acegisecurity.afterinvocation.Filterer#getFilteredObject()
|
||||
*/
|
||||
public Object getFilteredObject() {
|
||||
// Now the Iterator has ended, remove Objects from Collection
|
||||
Iterator removeIter = removeList.iterator();
|
||||
|
||||
int originalSize = collection.size();
|
||||
|
||||
while (removeIter.hasNext()) {
|
||||
collection.remove(removeIter.next());
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Original collection contained " + originalSize + " elements; now contains "
|
||||
+ collection.size() + " elements");
|
||||
}
|
||||
|
||||
return collection;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see org.acegisecurity.afterinvocation.Filterer#iterator()
|
||||
*/
|
||||
public Iterator iterator() {
|
||||
collectionIter = collection.iterator();
|
||||
|
||||
return collectionIter;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see org.acegisecurity.afterinvocation.Filterer#remove(java.lang.Object)
|
||||
*/
|
||||
public void remove(Object object) {
|
||||
collectionIter.remove();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A filter used to filter arrays.
|
||||
*/
|
||||
class ArrayFilterer implements Filterer {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
protected static final Log logger = LogFactory.getLog(BasicAclEntryAfterInvocationCollectionFilteringProvider.class);
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private Set removeList;
|
||||
private Object[] list;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
ArrayFilterer(Object[] list) {
|
||||
this.list = list;
|
||||
|
||||
// Collect the removed objects to a HashSet so that
|
||||
// it is fast to lookup them when a filtered array
|
||||
// is constructed.
|
||||
removeList = new HashSet();
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
*
|
||||
* @see org.acegisecurity.afterinvocation.Filterer#getFilteredObject()
|
||||
*/
|
||||
public Object getFilteredObject() {
|
||||
// Recreate an array of same type and filter the removed objects.
|
||||
int originalSize = list.length;
|
||||
int sizeOfResultingList = originalSize - removeList.size();
|
||||
Object[] filtered = (Object[]) Array.newInstance(list.getClass().getComponentType(), sizeOfResultingList);
|
||||
|
||||
for (int i = 0, j = 0; i < list.length; i++) {
|
||||
Object object = list[i];
|
||||
|
||||
if (!removeList.contains(object)) {
|
||||
filtered[j] = object;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Original array contained " + originalSize + " elements; now contains " + sizeOfResultingList
|
||||
+ " elements");
|
||||
}
|
||||
|
||||
return filtered;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see org.acegisecurity.afterinvocation.Filterer#iterator()
|
||||
*/
|
||||
public Iterator iterator() {
|
||||
return new ArrayIterator(list);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see org.acegisecurity.afterinvocation.Filterer#remove(java.lang.Object)
|
||||
*/
|
||||
public void remove(Object object) {
|
||||
removeList.add(object);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-10
@@ -39,6 +39,7 @@ import org.springframework.util.Assert;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
|
||||
/**
|
||||
* <p>Given a domain object instance returned from a secure object invocation, ensures the principal has
|
||||
* appropriate permission as defined by the {@link AclManager}.</p>
|
||||
@@ -186,16 +187,6 @@ public class BasicAclEntryAfterInvocationProvider implements AfterInvocationProv
|
||||
this.requirePermission = requirePermission;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow setting permissions with String literals instead of integers as {@link #setRequirePermission(int[])}
|
||||
*
|
||||
* @param requirePermission Permission literals
|
||||
* @see SimpleAclEntry#parsePermissions(String[]) for valid values
|
||||
*/
|
||||
public void setRequirePermissionFromString(String[] requirePermission) {
|
||||
setRequirePermission(SimpleAclEntry.parsePermissions(requirePermission));
|
||||
}
|
||||
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
if ((attribute.getAttribute() != null) && attribute.getAttribute().equals(getProcessConfigAttribute())) {
|
||||
return true;
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.acegisecurity.afterinvocation;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
* A filter used to filter Collections.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author Paulo Neves
|
||||
* @version $Id$
|
||||
*/
|
||||
class CollectionFilterer implements Filterer {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
protected static final Log logger = LogFactory.getLog(BasicAclEntryAfterInvocationCollectionFilteringProvider.class);
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private Collection collection;
|
||||
|
||||
// collectionIter offers significant performance optimisations (as
|
||||
// per acegisecurity-developer mailing list conversation 19/5/05)
|
||||
private Iterator collectionIter;
|
||||
private Set removeList;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
CollectionFilterer(Collection collection) {
|
||||
this.collection = collection;
|
||||
|
||||
// We create a Set of objects to be removed from the Collection,
|
||||
// as ConcurrentModificationException prevents removal during
|
||||
// iteration, and making a new Collection to be returned is
|
||||
// problematic as the original Collection implementation passed
|
||||
// to the method may not necessarily be re-constructable (as
|
||||
// the Collection(collection) constructor is not guaranteed and
|
||||
// manually adding may lose sort order or other capabilities)
|
||||
removeList = new HashSet();
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
*
|
||||
* @see org.acegisecurity.afterinvocation.Filterer#getFilteredObject()
|
||||
*/
|
||||
public Object getFilteredObject() {
|
||||
// Now the Iterator has ended, remove Objects from Collection
|
||||
Iterator removeIter = removeList.iterator();
|
||||
|
||||
int originalSize = collection.size();
|
||||
|
||||
while (removeIter.hasNext()) {
|
||||
collection.remove(removeIter.next());
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Original collection contained " + originalSize + " elements; now contains "
|
||||
+ collection.size() + " elements");
|
||||
}
|
||||
|
||||
return collection;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see org.acegisecurity.afterinvocation.Filterer#iterator()
|
||||
*/
|
||||
public Iterator iterator() {
|
||||
collectionIter = collection.iterator();
|
||||
|
||||
return collectionIter;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see org.acegisecurity.afterinvocation.Filterer#remove(java.lang.Object)
|
||||
*/
|
||||
public void remove(Object object) {
|
||||
removeList.add(object);
|
||||
}
|
||||
}
|
||||
+8
-46
@@ -15,8 +15,12 @@
|
||||
|
||||
package org.acegisecurity.context;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
@@ -27,12 +31,6 @@ import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
|
||||
/**
|
||||
* <p>Populates the {@link SecurityContextHolder} with information obtained from the <code>HttpSession</code>.</p>
|
||||
@@ -101,30 +99,6 @@ public class HttpSessionContextIntegrationFilter implements InitializingBean, Fi
|
||||
* are conscious of the session creation overhead.
|
||||
*/
|
||||
private boolean forceEagerSessionCreation = false;
|
||||
|
||||
/**
|
||||
* Indicates whether the <code>SecurityContext</code> will be cloned from the <code>HttpSession</code>. The
|
||||
* default is to simply reference (ie the default is <code>false</code>). The default may cause issues if
|
||||
* concurrent threads need to have a different security identity from other threads being concurrently processed
|
||||
* that share the same <code>HttpSession</code>. In most normal environments this does not represent an issue,
|
||||
* as changes to the security identity in one thread is allowed to affect the security identitiy in other
|
||||
* threads associated with the same <code>HttpSession</code>. For unusual cases where this is not permitted,
|
||||
* change this value to <code>true</code> and ensure the {@link #context} is set to a <code>SecurityContext</code>
|
||||
* that implements {@link Cloneable} and overrides the <code>clone()</code> method.
|
||||
*/
|
||||
private boolean cloneFromHttpSession = false;
|
||||
|
||||
public boolean isCloneFromHttpSession() {
|
||||
return cloneFromHttpSession;
|
||||
}
|
||||
|
||||
public void setCloneFromHttpSession(boolean cloneFromHttpSession) {
|
||||
this.cloneFromHttpSession = cloneFromHttpSession;
|
||||
}
|
||||
|
||||
public HttpSessionContextIntegrationFilter() throws ServletException {
|
||||
this.contextObject = generateNewContext();
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
@@ -139,6 +113,8 @@ public class HttpSessionContextIntegrationFilter implements InitializingBean, Fi
|
||||
throw new IllegalArgumentException(
|
||||
"If using forceEagerSessionCreation, you must set allowSessionCreation to also be true");
|
||||
}
|
||||
|
||||
this.contextObject = generateNewContext();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -167,21 +143,7 @@ public class HttpSessionContextIntegrationFilter implements InitializingBean, Fi
|
||||
httpSessionExistedAtStartOfRequest = true;
|
||||
|
||||
Object contextFromSessionObject = httpSession.getAttribute(ACEGI_SECURITY_CONTEXT_KEY);
|
||||
|
||||
// Clone if required (see SEC-356)
|
||||
if (cloneFromHttpSession) {
|
||||
Assert.isInstanceOf(Cloneable.class, contextFromSessionObject, "Context must implement Clonable and provide a Object.clone() method");
|
||||
try {
|
||||
Method m = contextFromSessionObject.getClass().getMethod("clone", new Class[] {});
|
||||
if (!m.isAccessible()) {
|
||||
m.setAccessible(true);
|
||||
}
|
||||
contextFromSessionObject = m.invoke(contextFromSessionObject, new Object[] {});
|
||||
} catch (Exception ex) {
|
||||
ReflectionUtils.handleReflectionException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (contextFromSessionObject != null) {
|
||||
if (contextFromSessionObject instanceof SecurityContext) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
|
||||
+1
-7
@@ -15,19 +15,13 @@
|
||||
|
||||
package org.acegisecurity.event.authorization;
|
||||
|
||||
import org.acegisecurity.AccessDecisionManager;
|
||||
import org.acegisecurity.AccessDeniedException;
|
||||
import org.acegisecurity.AfterInvocationManager;
|
||||
import org.acegisecurity.Authentication;
|
||||
import org.acegisecurity.ConfigAttributeDefinition;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates a secure object invocation failed because the principal could not
|
||||
* be authorized for the request.
|
||||
*
|
||||
* <p>This event might be thrown as a result of either an
|
||||
* {@link AccessDecisionManager} or an {@link AfterInvocationManager}.
|
||||
* Indicates a secure object invocation failed because the principal could not be authorized for the request.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
|
||||
@@ -41,7 +41,6 @@ import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.ApplicationEventPublisherAware;
|
||||
import org.springframework.context.MessageSource;
|
||||
@@ -148,17 +147,8 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, A
|
||||
}
|
||||
|
||||
if (afterInvocationManager != null) {
|
||||
// Attempt after invocation handling
|
||||
try {
|
||||
returnedObject = afterInvocationManager.decide(token.getAuthentication(), token.getSecureObject(),
|
||||
token.getAttr(), returnedObject);
|
||||
} catch (AccessDeniedException accessDeniedException) {
|
||||
AuthorizationFailureEvent event = new AuthorizationFailureEvent(token.getSecureObject(),
|
||||
token.getAttr(), token.getAuthentication(), accessDeniedException);
|
||||
publishEvent(event);
|
||||
|
||||
throw accessDeniedException;
|
||||
}
|
||||
returnedObject = afterInvocationManager.decide(token.getAuthentication(), token.getSecureObject(),
|
||||
token.getAttr(), returnedObject);
|
||||
}
|
||||
|
||||
return returnedObject;
|
||||
@@ -286,7 +276,7 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, A
|
||||
} catch (AccessDeniedException accessDeniedException) {
|
||||
AuthorizationFailureEvent event = new AuthorizationFailureEvent(object, attr, authenticated,
|
||||
accessDeniedException);
|
||||
publishEvent(event);
|
||||
this.eventPublisher.publishEvent(event);
|
||||
|
||||
throw accessDeniedException;
|
||||
}
|
||||
@@ -296,7 +286,7 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, A
|
||||
}
|
||||
|
||||
AuthorizedEvent event = new AuthorizedEvent(object, attr, authenticated);
|
||||
publishEvent(event);
|
||||
this.eventPublisher.publishEvent(event);
|
||||
|
||||
// Attempt to run as a different user
|
||||
Authentication runAs = this.runAsManager.buildRunAs(authenticated, object, attr);
|
||||
@@ -321,7 +311,7 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, A
|
||||
logger.debug("Public object - authentication not attempted");
|
||||
}
|
||||
|
||||
publishEvent(new PublicInvocationEvent(object));
|
||||
this.eventPublisher.publishEvent(new PublicInvocationEvent(object));
|
||||
|
||||
return null; // no further work post-invocation
|
||||
}
|
||||
@@ -340,7 +330,7 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, A
|
||||
|
||||
AuthenticationCredentialsNotFoundEvent event = new AuthenticationCredentialsNotFoundEvent(secureObject,
|
||||
configAttribs, exception);
|
||||
publishEvent(event);
|
||||
this.eventPublisher.publishEvent(event);
|
||||
|
||||
throw exception;
|
||||
}
|
||||
@@ -441,10 +431,4 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, A
|
||||
public void setValidateConfigAttributes(boolean validateConfigAttributes) {
|
||||
this.validateConfigAttributes = validateConfigAttributes;
|
||||
}
|
||||
|
||||
private void publishEvent(ApplicationEvent event) {
|
||||
if (this.eventPublisher != null) {
|
||||
this.eventPublisher.publishEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ package org.acegisecurity.intercept.method;
|
||||
|
||||
import org.acegisecurity.ConfigAttribute;
|
||||
import org.acegisecurity.ConfigAttributeDefinition;
|
||||
import org.acegisecurity.SecurityConfig;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -233,25 +232,4 @@ public class MethodDefinitionMap extends AbstractMethodDefinitionSource {
|
||||
definition.addConfigAttribute((ConfigAttribute) attribs.next());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Easier configuration of the instance, using {@link MethodDefinitionSourceMapping}.
|
||||
*
|
||||
* @param mappings {@link List} of {@link MethodDefinitionSourceMapping} objects.
|
||||
*/
|
||||
public void setMappings(List mappings) {
|
||||
Iterator it = mappings.iterator();
|
||||
while (it.hasNext()) {
|
||||
MethodDefinitionSourceMapping mapping = (MethodDefinitionSourceMapping) it.next();
|
||||
ConfigAttributeDefinition configDefinition = new ConfigAttributeDefinition();
|
||||
|
||||
Iterator configAttributesIt = mapping.getConfigAttributes().iterator();
|
||||
while (configAttributesIt.hasNext()) {
|
||||
String s = (String) configAttributesIt.next();
|
||||
configDefinition.addConfigAttribute(new SecurityConfig(s));
|
||||
}
|
||||
|
||||
addSecureMethod(mapping.getMethodName(), configDefinition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
-13
@@ -15,17 +15,17 @@
|
||||
|
||||
package org.acegisecurity.intercept.method;
|
||||
|
||||
import org.acegisecurity.ConfigAttributeDefinition;
|
||||
import org.acegisecurity.ConfigAttributeEditor;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.propertyeditors.PropertiesEditor;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
|
||||
@@ -56,24 +56,20 @@ public class MethodDefinitionSourceEditor extends PropertyEditorSupport {
|
||||
Properties props = (Properties) propertiesEditor.getValue();
|
||||
|
||||
// Now we have properties, process each one individually
|
||||
List mappings = new ArrayList();
|
||||
ConfigAttributeEditor configAttribEd = new ConfigAttributeEditor();
|
||||
|
||||
for (Iterator iter = props.keySet().iterator(); iter.hasNext();) {
|
||||
String name = (String) iter.next();
|
||||
String value = props.getProperty(name);
|
||||
|
||||
MethodDefinitionSourceMapping mapping = new MethodDefinitionSourceMapping();
|
||||
mapping.setMethodName(name);
|
||||
// Convert value to series of security configuration attributes
|
||||
configAttribEd.setAsText(value);
|
||||
|
||||
String[] tokens = StringUtils.commaDelimitedListToStringArray(value);
|
||||
ConfigAttributeDefinition attr = (ConfigAttributeDefinition) configAttribEd.getValue();
|
||||
|
||||
for (int i = 0; i < tokens.length; i++) {
|
||||
mapping.addConfigAttribute(tokens[i].trim());
|
||||
}
|
||||
|
||||
mappings.add(mapping);
|
||||
// Register name and attribute
|
||||
source.addSecureMethod(name, attr);
|
||||
}
|
||||
source.setMappings(mappings);
|
||||
}
|
||||
|
||||
setValue(source);
|
||||
|
||||
-82
@@ -1,82 +0,0 @@
|
||||
/* Copyright 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.acegisecurity.intercept.method;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.acegisecurity.ConfigAttribute;
|
||||
|
||||
/**
|
||||
* Configuration entry for {@link MethodDefinitionSource}, that holds
|
||||
* the method to be protected and the {@link ConfigAttribute}s as {@link String}
|
||||
* that apply to that url.
|
||||
*
|
||||
* @author <a href="mailto:carlos@apache.org">Carlos Sanchez</a>
|
||||
* @version $Id$
|
||||
* @since 1.1
|
||||
*/
|
||||
public class MethodDefinitionSourceMapping {
|
||||
|
||||
private String methodName;
|
||||
|
||||
private List configAttributes = new ArrayList();
|
||||
|
||||
/**
|
||||
* Name of the method to be secured, including package and class name.
|
||||
* eg. <code>org.mydomain.MyClass.myMethod</code>
|
||||
*
|
||||
* @param methodName
|
||||
*/
|
||||
public void setMethodName(String methodName) {
|
||||
this.methodName = methodName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Name of the method to be secured.
|
||||
*
|
||||
* @return the name of the method
|
||||
*/
|
||||
public String getMethodName() {
|
||||
return methodName;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param roles {@link List}<{@link String}>
|
||||
*/
|
||||
public void setConfigAttributes(List roles) {
|
||||
this.configAttributes = roles;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return {@link List}<{@link String}>
|
||||
*/
|
||||
public List getConfigAttributes() {
|
||||
return configAttributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a {@link ConfigAttribute} as {@link String}
|
||||
*
|
||||
* @param configAttribute
|
||||
*/
|
||||
public void addConfigAttribute(String configAttribute) {
|
||||
configAttributes.add(configAttribute);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/* Copyright 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.acegisecurity.intercept.web;
|
||||
|
||||
/**
|
||||
* Interface to join {@link FilterInvocationDefinitionMap} and
|
||||
* {@link FilterInvocationDefinitionSource}.
|
||||
*
|
||||
* @author <a href="mailto:carlos@apache.org">Carlos Sanchez</a>
|
||||
* @version $Id$
|
||||
* @since 1.1
|
||||
*/
|
||||
public interface FilterInvocationDefinition extends FilterInvocationDefinitionMap, FilterInvocationDefinitionSource {
|
||||
}
|
||||
-153
@@ -1,153 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.acegisecurity.intercept.web;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.acegisecurity.ConfigAttributeDefinition;
|
||||
import org.acegisecurity.SecurityConfig;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Decorator of {@link FilterInvocationDefinition} for easier configuration,
|
||||
* using {@link FilterInvocationDefinitionSourceMapping}.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Delegates all calls to decorated object set in constructor
|
||||
* {@link #FilterInvocationDefinitionDecorator(FilterInvocationDefinition)} or
|
||||
* by calling {@link #setDecorated(FilterInvocationDefinition)}
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="mailto:carlos@apache.org">Carlos Sanchez</a>
|
||||
* @version $Id$
|
||||
* @since 1.1
|
||||
*/
|
||||
public class FilterInvocationDefinitionDecorator implements FilterInvocationDefinition {
|
||||
|
||||
private FilterInvocationDefinition decorated;
|
||||
|
||||
private List mappings;
|
||||
|
||||
public FilterInvocationDefinitionDecorator() {
|
||||
}
|
||||
|
||||
public FilterInvocationDefinitionDecorator(FilterInvocationDefinition decorated) {
|
||||
this.setDecorated(decorated);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the decorated object
|
||||
*
|
||||
* @param decorated
|
||||
* the decorated {@link FilterInvocationDefinition}
|
||||
*/
|
||||
public void setDecorated(FilterInvocationDefinition decorated) {
|
||||
this.decorated = decorated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get decorated object
|
||||
*
|
||||
* @return the decorated {@link FilterInvocationDefinition}
|
||||
*/
|
||||
public FilterInvocationDefinition getDecorated() {
|
||||
return decorated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the decorated {@link FilterInvocationDefinitionMap} easier,
|
||||
* using {@link FilterInvocationDefinitionSourceMapping}.
|
||||
*
|
||||
* @param mappings
|
||||
* {@link List} of
|
||||
* {@link FilterInvocationDefinitionSourceMapping} objects.
|
||||
*/
|
||||
public void setMappings(List mappings) {
|
||||
|
||||
if (decorated == null) {
|
||||
throw new IllegalStateException("decorated object has not been set");
|
||||
}
|
||||
|
||||
this.mappings = mappings;
|
||||
Iterator it = mappings.iterator();
|
||||
while (it.hasNext()) {
|
||||
FilterInvocationDefinitionSourceMapping mapping = (FilterInvocationDefinitionSourceMapping) it.next();
|
||||
ConfigAttributeDefinition configDefinition = new ConfigAttributeDefinition();
|
||||
|
||||
Iterator configAttributesIt = mapping.getConfigAttributes().iterator();
|
||||
while (configAttributesIt.hasNext()) {
|
||||
String s = (String) configAttributesIt.next();
|
||||
configDefinition.addConfigAttribute(new SecurityConfig(s));
|
||||
}
|
||||
|
||||
decorated.addSecureUrl(mapping.getUrl(), configDefinition);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mappings used for configuration.
|
||||
*
|
||||
* @return {@link List} of {@link FilterInvocationDefinitionSourceMapping}
|
||||
* objects.
|
||||
*/
|
||||
public List getMappings() {
|
||||
return mappings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegate to decorated object
|
||||
*/
|
||||
public void addSecureUrl(String expression, ConfigAttributeDefinition attr) {
|
||||
getDecorated().addSecureUrl(expression, attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegate to decorated object
|
||||
*/
|
||||
public boolean isConvertUrlToLowercaseBeforeComparison() {
|
||||
return getDecorated().isConvertUrlToLowercaseBeforeComparison();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegate to decorated object
|
||||
*/
|
||||
public void setConvertUrlToLowercaseBeforeComparison(boolean convertUrlToLowercaseBeforeComparison) {
|
||||
getDecorated().setConvertUrlToLowercaseBeforeComparison(convertUrlToLowercaseBeforeComparison);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegate to decorated object
|
||||
*/
|
||||
public ConfigAttributeDefinition getAttributes(Object object) throws IllegalArgumentException {
|
||||
return getDecorated().getAttributes(object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegate to decorated object
|
||||
*/
|
||||
public Iterator getConfigAttributeDefinitions() {
|
||||
return getDecorated().getConfigAttributeDefinitions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegate to decorated object
|
||||
*/
|
||||
public boolean supports(Class clazz) {
|
||||
return getDecorated().supports(clazz);
|
||||
}
|
||||
}
|
||||
+21
-29
@@ -15,17 +15,18 @@
|
||||
|
||||
package org.acegisecurity.intercept.web;
|
||||
|
||||
import org.acegisecurity.ConfigAttributeDefinition;
|
||||
import org.acegisecurity.ConfigAttributeEditor;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.acegisecurity.util.StringSplitUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
||||
/**
|
||||
@@ -49,22 +50,19 @@ public class FilterInvocationDefinitionSourceEditor extends PropertyEditorSuppor
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void setAsText(String s) throws IllegalArgumentException {
|
||||
FilterInvocationDefinitionDecorator source = new FilterInvocationDefinitionDecorator();
|
||||
FilterInvocationDefinitionMap source = new RegExpBasedFilterInvocationDefinitionMap();
|
||||
|
||||
if ((s == null) || "".equals(s)) {
|
||||
// Leave target object empty
|
||||
source.setDecorated(new RegExpBasedFilterInvocationDefinitionMap());
|
||||
} else {
|
||||
// Check if we need to override the default definition map
|
||||
if (s.lastIndexOf(DIRECTIVE_PATTERN_TYPE_APACHE_ANT) != -1) {
|
||||
source.setDecorated(new PathBasedFilterInvocationDefinitionMap());
|
||||
source = new PathBasedFilterInvocationDefinitionMap();
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(("Detected " + DIRECTIVE_PATTERN_TYPE_APACHE_ANT
|
||||
+ " directive; using Apache Ant style path expressions"));
|
||||
}
|
||||
} else {
|
||||
source.setDecorated(new RegExpBasedFilterInvocationDefinitionMap());
|
||||
}
|
||||
|
||||
if (s.lastIndexOf(DIRECTIVE_CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON) != -1) {
|
||||
@@ -79,8 +77,6 @@ public class FilterInvocationDefinitionSourceEditor extends PropertyEditorSuppor
|
||||
BufferedReader br = new BufferedReader(new StringReader(s));
|
||||
int counter = 0;
|
||||
String line;
|
||||
|
||||
List mappings = new ArrayList();
|
||||
|
||||
while (true) {
|
||||
counter++;
|
||||
@@ -133,16 +129,16 @@ public class FilterInvocationDefinitionSourceEditor extends PropertyEditorSuppor
|
||||
|
||||
// Tokenize the line into its name/value tokens
|
||||
// As per SEC-219, use the LAST equals as the delimiter between LHS and RHS
|
||||
String name = StringSplitUtils.substringBeforeLast(line, "=");
|
||||
String value = StringSplitUtils.substringAfterLast(line, "=");
|
||||
String name = StringUtils.substringBeforeLast(line, "=");
|
||||
String value = StringUtils.substringAfterLast(line, "=");
|
||||
|
||||
if (!StringUtils.hasText(name) || !StringUtils.hasText(value)) {
|
||||
if (StringUtils.isBlank(name) || StringUtils.isBlank(value)) {
|
||||
throw new IllegalArgumentException("Failed to parse a valid name/value pair from " + line);
|
||||
}
|
||||
|
||||
// Attempt to detect malformed lines (as per SEC-204)
|
||||
if (source.isConvertUrlToLowercaseBeforeComparison()
|
||||
&& source.getDecorated() instanceof PathBasedFilterInvocationDefinitionMap) {
|
||||
&& source instanceof PathBasedFilterInvocationDefinitionMap) {
|
||||
// Should all be lowercase; check each character
|
||||
// We only do this for Ant (regexp have control chars)
|
||||
for (int i = 0; i < name.length(); i++) {
|
||||
@@ -157,21 +153,17 @@ public class FilterInvocationDefinitionSourceEditor extends PropertyEditorSuppor
|
||||
}
|
||||
}
|
||||
|
||||
FilterInvocationDefinitionSourceMapping mapping = new FilterInvocationDefinitionSourceMapping();
|
||||
mapping.setUrl(name);
|
||||
// Convert value to series of security configuration attributes
|
||||
ConfigAttributeEditor configAttribEd = new ConfigAttributeEditor();
|
||||
configAttribEd.setAsText(value);
|
||||
|
||||
String[] tokens = org.springframework.util.StringUtils
|
||||
.commaDelimitedListToStringArray(value);
|
||||
ConfigAttributeDefinition attr = (ConfigAttributeDefinition) configAttribEd.getValue();
|
||||
|
||||
for (int i = 0; i < tokens.length; i++) {
|
||||
mapping.addConfigAttribute(tokens[i].trim());
|
||||
}
|
||||
|
||||
mappings.add(mapping);
|
||||
// Register the regular expression and its attribute
|
||||
source.addSecureUrl(name, attr);
|
||||
}
|
||||
source.setMappings(mappings);
|
||||
}
|
||||
|
||||
setValue(source.getDecorated());
|
||||
setValue(source);
|
||||
}
|
||||
}
|
||||
|
||||
-82
@@ -1,82 +0,0 @@
|
||||
/* Copyright 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.acegisecurity.intercept.web;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.acegisecurity.ConfigAttribute;
|
||||
|
||||
/**
|
||||
* Configuration entry for {@link FilterInvocationDefinitionSource}, that holds
|
||||
* the url to be protected and the {@link ConfigAttribute}s as {@link String}
|
||||
* that apply to that url.
|
||||
*
|
||||
* @author <a href="mailto:carlos@apache.org">Carlos Sanchez</a>
|
||||
* @version $Id$
|
||||
* @since 1.1
|
||||
*/
|
||||
public class FilterInvocationDefinitionSourceMapping {
|
||||
|
||||
private String url;
|
||||
|
||||
private List configAttributes = new ArrayList();
|
||||
|
||||
/**
|
||||
* Url to be secured.
|
||||
*
|
||||
* @param url
|
||||
*/
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Url to be secured.
|
||||
*
|
||||
* @return the url
|
||||
*/
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param roles
|
||||
* {@link List}<{@link String}>
|
||||
*/
|
||||
public void setConfigAttributes(List roles) {
|
||||
this.configAttributes = roles;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return {@link List}<{@link String}>
|
||||
*/
|
||||
public List getConfigAttributes() {
|
||||
return configAttributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a {@link ConfigAttribute} as {@link String}
|
||||
*
|
||||
* @param configAttribute
|
||||
*/
|
||||
public void addConfigAttribute(String configAttribute) {
|
||||
configAttributes.add(configAttribute);
|
||||
}
|
||||
|
||||
}
|
||||
+4
-4
@@ -44,7 +44,7 @@ import java.util.Vector;
|
||||
* @version $Id$
|
||||
*/
|
||||
public class PathBasedFilterInvocationDefinitionMap extends AbstractFilterInvocationDefinitionSource
|
||||
implements FilterInvocationDefinition {
|
||||
implements FilterInvocationDefinitionMap {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
private static final Log logger = LogFactory.getLog(PathBasedFilterInvocationDefinitionMap.class);
|
||||
@@ -86,14 +86,14 @@ public class PathBasedFilterInvocationDefinitionMap extends AbstractFilterInvoca
|
||||
}
|
||||
|
||||
public ConfigAttributeDefinition lookupAttributes(String url) {
|
||||
// Strip anything after a question mark symbol, as per SEC-161. See also SEC-321
|
||||
int firstQuestionMarkIndex = url.indexOf("?");
|
||||
// Strip anything after a question mark symbol, as per SEC-161.
|
||||
int firstQuestionMarkIndex = url.lastIndexOf("?");
|
||||
|
||||
if (firstQuestionMarkIndex != -1) {
|
||||
url = url.substring(0, firstQuestionMarkIndex);
|
||||
}
|
||||
|
||||
if (isConvertUrlToLowercaseBeforeComparison()) {
|
||||
if (convertUrlToLowercaseBeforeComparison) {
|
||||
url = url.toLowerCase();
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
|
||||
+2
-2
@@ -45,7 +45,7 @@ import java.util.Vector;
|
||||
* <p>If no registered regular expressions match the HTTP URL, <code>null</code> is returned.</p>
|
||||
*/
|
||||
public class RegExpBasedFilterInvocationDefinitionMap extends AbstractFilterInvocationDefinitionSource
|
||||
implements FilterInvocationDefinition {
|
||||
implements FilterInvocationDefinitionMap {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
private static final Log logger = LogFactory.getLog(RegExpBasedFilterInvocationDefinitionMap.class);
|
||||
@@ -100,7 +100,7 @@ public class RegExpBasedFilterInvocationDefinitionMap extends AbstractFilterInvo
|
||||
|
||||
Iterator iter = requestMap.iterator();
|
||||
|
||||
if (isConvertUrlToLowercaseBeforeComparison()) {
|
||||
if (convertUrlToLowercaseBeforeComparison) {
|
||||
url = url.toLowerCase();
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
|
||||
@@ -34,8 +34,6 @@ import java.util.StringTokenizer;
|
||||
import javax.naming.CommunicationException;
|
||||
import javax.naming.Context;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.OperationNotSupportedException;
|
||||
import javax.naming.ldap.InitialLdapContext;
|
||||
import javax.naming.directory.DirContext;
|
||||
import javax.naming.directory.InitialDirContext;
|
||||
|
||||
@@ -106,32 +104,13 @@ public class DefaultInitialDirContextFactory implements InitialDirContextFactory
|
||||
*/
|
||||
private boolean useConnectionPool = true;
|
||||
|
||||
/** Set to true for ldap v3 compatible servers */
|
||||
private boolean useLdapContext = false;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
/**
|
||||
* Create and initialize an instance to the LDAP url provided
|
||||
*
|
||||
* @param providerUrl a String of the form <code>ldap://localhost:389/base_dn<code>
|
||||
*/
|
||||
public DefaultInitialDirContextFactory(String providerUrl) {
|
||||
this.setProviderUrl(providerUrl);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Set the LDAP url
|
||||
*
|
||||
* @param providerUrl a String of the form <code>ldap://localhost:389/base_dn<code>
|
||||
*/
|
||||
private void setProviderUrl(String providerUrl) {
|
||||
Assert.hasLength(providerUrl, "An LDAP connection URL must be supplied.");
|
||||
|
||||
this.providerUrl = providerUrl;
|
||||
|
||||
Assert.hasLength(providerUrl, "An LDAP connection URL must be supplied.");
|
||||
|
||||
StringTokenizer st = new StringTokenizer(providerUrl);
|
||||
|
||||
// Work out rootDn from the first URL and check that the other URLs (if any) match
|
||||
@@ -152,14 +131,7 @@ public class DefaultInitialDirContextFactory implements InitialDirContextFactory
|
||||
//Assert.isTrue(uri.getScheme().equals("ldap"), "Ldap URL must start with 'ldap://'");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the LDAP url
|
||||
*
|
||||
* @return the url
|
||||
*/
|
||||
private String getProviderUrl() {
|
||||
return providerUrl;
|
||||
}
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
private InitialDirContext connect(Hashtable env) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
@@ -173,22 +145,17 @@ public class DefaultInitialDirContextFactory implements InitialDirContextFactory
|
||||
}
|
||||
|
||||
try {
|
||||
return useLdapContext ? new InitialLdapContext(env, null) : new InitialDirContext(env);
|
||||
} catch (NamingException ne) {
|
||||
if ((ne instanceof javax.naming.AuthenticationException) ||
|
||||
(ne instanceof OperationNotSupportedException)) {
|
||||
throw new BadCredentialsException(messages.getMessage("DefaultIntitalDirContextFactory.badCredentials",
|
||||
"Bad credentials"), ne);
|
||||
}
|
||||
|
||||
if (ne instanceof CommunicationException) {
|
||||
throw new LdapDataAccessException(messages.getMessage(
|
||||
"DefaultIntitalDirContextFactory.communicationFailure", "Unable to connect to LDAP server"), ne);
|
||||
}
|
||||
|
||||
return new InitialDirContext(env);
|
||||
} catch (CommunicationException ce) {
|
||||
throw new LdapDataAccessException(messages.getMessage(
|
||||
"DefaultIntitalDirContextFactory.communicationFailure", "Unable to connect to LDAP server"), ce);
|
||||
} catch (javax.naming.AuthenticationException ae) {
|
||||
throw new BadCredentialsException(messages.getMessage("DefaultIntitalDirContextFactory.badCredentials",
|
||||
"Bad credentials"), ae);
|
||||
} catch (NamingException nx) {
|
||||
throw new LdapDataAccessException(messages.getMessage(
|
||||
"DefaultIntitalDirContextFactory.unexpectedException",
|
||||
"Failed to obtain InitialDirContext due to unexpected exception"), ne);
|
||||
"Failed to obtain InitialDirContext due to unexpected exception"), nx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,7 +169,7 @@ public class DefaultInitialDirContextFactory implements InitialDirContextFactory
|
||||
|
||||
env.put(Context.SECURITY_AUTHENTICATION, authenticationType);
|
||||
env.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactory);
|
||||
env.put(Context.PROVIDER_URL, getProviderUrl());
|
||||
env.put(Context.PROVIDER_URL, providerUrl);
|
||||
|
||||
if (useConnectionPool) {
|
||||
env.put(CONNECTION_POOL_KEY, "true");
|
||||
@@ -313,8 +280,4 @@ public class DefaultInitialDirContextFactory implements InitialDirContextFactory
|
||||
public void setUseConnectionPool(boolean useConnectionPool) {
|
||||
this.useConnectionPool = useConnectionPool;
|
||||
}
|
||||
|
||||
public void setUseLdapContext(boolean useLdapContext) {
|
||||
this.useLdapContext = useLdapContext;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ import java.util.Set;
|
||||
import javax.naming.NameNotFoundException;
|
||||
import javax.naming.NamingEnumeration;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.Context;
|
||||
import javax.naming.directory.Attribute;
|
||||
import javax.naming.directory.Attributes;
|
||||
import javax.naming.directory.DirContext;
|
||||
@@ -133,21 +132,17 @@ public class LdapTemplate {
|
||||
|
||||
public boolean nameExists(final String dn) {
|
||||
Boolean exists = (Boolean) execute(new LdapCallback() {
|
||||
public Object doInDirContext(DirContext ctx)
|
||||
throws NamingException {
|
||||
try {
|
||||
Object obj = ctx.lookup(LdapUtils.getRelativeName(dn, ctx));
|
||||
if (obj instanceof Context) {
|
||||
LdapUtils.closeContext((Context) obj);
|
||||
public Object doInDirContext(DirContext ctx)
|
||||
throws NamingException {
|
||||
try {
|
||||
ctx.lookup(LdapUtils.getRelativeName(dn, ctx));
|
||||
} catch (NameNotFoundException nnfe) {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
|
||||
} catch (NameNotFoundException nnfe) {
|
||||
return Boolean.FALSE;
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return exists.booleanValue();
|
||||
}
|
||||
|
||||
@@ -51,7 +51,6 @@ import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.ApplicationEventPublisherAware;
|
||||
import org.springframework.context.MessageSource;
|
||||
@@ -96,7 +95,6 @@ public class ProviderManager extends AbstractAuthenticationManager implements In
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
private static final Log logger = LogFactory.getLog(ProviderManager.class);
|
||||
private static final Properties DEFAULT_EXCEPTION_MAPPINGS = new Properties();
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
@@ -104,39 +102,36 @@ public class ProviderManager extends AbstractAuthenticationManager implements In
|
||||
private ConcurrentSessionController sessionController = new NullConcurrentSessionController();
|
||||
private List providers;
|
||||
protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor();
|
||||
private Properties exceptionMappings = new Properties();
|
||||
|
||||
static {
|
||||
DEFAULT_EXCEPTION_MAPPINGS.put(AccountExpiredException.class.getName(),
|
||||
AuthenticationFailureExpiredEvent.class.getName());
|
||||
DEFAULT_EXCEPTION_MAPPINGS.put(AuthenticationServiceException.class.getName(),
|
||||
AuthenticationFailureServiceExceptionEvent.class.getName());
|
||||
DEFAULT_EXCEPTION_MAPPINGS.put(LockedException.class.getName(), AuthenticationFailureLockedEvent.class.getName());
|
||||
DEFAULT_EXCEPTION_MAPPINGS.put(CredentialsExpiredException.class.getName(),
|
||||
AuthenticationFailureCredentialsExpiredEvent.class.getName());
|
||||
DEFAULT_EXCEPTION_MAPPINGS.put(DisabledException.class.getName(), AuthenticationFailureDisabledEvent.class.getName());
|
||||
DEFAULT_EXCEPTION_MAPPINGS.put(BadCredentialsException.class.getName(),
|
||||
AuthenticationFailureBadCredentialsEvent.class.getName());
|
||||
DEFAULT_EXCEPTION_MAPPINGS.put(UsernameNotFoundException.class.getName(),
|
||||
AuthenticationFailureBadCredentialsEvent.class.getName());
|
||||
DEFAULT_EXCEPTION_MAPPINGS.put(ConcurrentLoginException.class.getName(),
|
||||
AuthenticationFailureConcurrentLoginEvent.class.getName());
|
||||
DEFAULT_EXCEPTION_MAPPINGS.put(ProviderNotFoundException.class.getName(),
|
||||
AuthenticationFailureProviderNotFoundEvent.class.getName());
|
||||
DEFAULT_EXCEPTION_MAPPINGS.put(ProxyUntrustedException.class.getName(),
|
||||
AuthenticationFailureProxyUntrustedEvent.class.getName());
|
||||
}
|
||||
|
||||
public ProviderManager() {
|
||||
exceptionMappings.putAll(DEFAULT_EXCEPTION_MAPPINGS);
|
||||
}
|
||||
private Properties exceptionMappings;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
checkIfValidList(this.providers);
|
||||
Assert.notNull(this.messages, "A message source must be set");
|
||||
doAddExtraDefaultExceptionMappings(DEFAULT_EXCEPTION_MAPPINGS);
|
||||
|
||||
if (exceptionMappings == null) {
|
||||
exceptionMappings = new Properties();
|
||||
exceptionMappings.put(AccountExpiredException.class.getName(),
|
||||
AuthenticationFailureExpiredEvent.class.getName());
|
||||
exceptionMappings.put(AuthenticationServiceException.class.getName(),
|
||||
AuthenticationFailureServiceExceptionEvent.class.getName());
|
||||
exceptionMappings.put(LockedException.class.getName(), AuthenticationFailureLockedEvent.class.getName());
|
||||
exceptionMappings.put(CredentialsExpiredException.class.getName(),
|
||||
AuthenticationFailureCredentialsExpiredEvent.class.getName());
|
||||
exceptionMappings.put(DisabledException.class.getName(), AuthenticationFailureDisabledEvent.class.getName());
|
||||
exceptionMappings.put(BadCredentialsException.class.getName(),
|
||||
AuthenticationFailureBadCredentialsEvent.class.getName());
|
||||
exceptionMappings.put(UsernameNotFoundException.class.getName(),
|
||||
AuthenticationFailureBadCredentialsEvent.class.getName());
|
||||
exceptionMappings.put(ConcurrentLoginException.class.getName(),
|
||||
AuthenticationFailureConcurrentLoginEvent.class.getName());
|
||||
exceptionMappings.put(ProviderNotFoundException.class.getName(),
|
||||
AuthenticationFailureProviderNotFoundEvent.class.getName());
|
||||
exceptionMappings.put(ProxyUntrustedException.class.getName(),
|
||||
AuthenticationFailureProxyUntrustedEvent.class.getName());
|
||||
doAddExtraDefaultExceptionMappings(exceptionMappings);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkIfValidList(List listToCheck) {
|
||||
@@ -194,7 +189,7 @@ public class ProviderManager extends AbstractAuthenticationManager implements In
|
||||
|
||||
if (result != null) {
|
||||
sessionController.registerSuccessfulAuthentication(result);
|
||||
publishEvent(new AuthenticationSuccessEvent(result));
|
||||
applicationEventPublisher.publishEvent(new AuthenticationSuccessEvent(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -227,7 +222,7 @@ public class ProviderManager extends AbstractAuthenticationManager implements In
|
||||
}
|
||||
|
||||
if (event != null) {
|
||||
publishEvent(event);
|
||||
applicationEventPublisher.publishEvent(event);
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("No event was found for the exception " + lastException.getClass().getName());
|
||||
@@ -273,8 +268,16 @@ public class ProviderManager extends AbstractAuthenticationManager implements In
|
||||
Iterator iter = newList.iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
Object currentObject = iter.next();
|
||||
Assert.isInstanceOf(AuthenticationProvider.class, currentObject, "Can only provide AuthenticationProvider instances");
|
||||
Object currentObject = null;
|
||||
|
||||
try {
|
||||
currentObject = iter.next();
|
||||
|
||||
AuthenticationProvider attemptToCast = (AuthenticationProvider) currentObject;
|
||||
} catch (ClassCastException cce) {
|
||||
throw new IllegalArgumentException("AuthenticationProvider " + currentObject.getClass().getName()
|
||||
+ " must implement AuthenticationProvider");
|
||||
}
|
||||
}
|
||||
|
||||
this.providers = newList;
|
||||
@@ -289,10 +292,4 @@ public class ProviderManager extends AbstractAuthenticationManager implements In
|
||||
public void setSessionController(ConcurrentSessionController sessionController) {
|
||||
this.sessionController = sessionController;
|
||||
}
|
||||
|
||||
private void publishEvent( ApplicationEvent event ) {
|
||||
if ( applicationEventPublisher != null ) {
|
||||
applicationEventPublisher.publishEvent( event );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ import org.acegisecurity.GrantedAuthority;
|
||||
public class TestingAuthenticationToken extends AbstractAuthenticationToken {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private Object credentials;
|
||||
private Object principal;
|
||||
|
||||
|
||||
-1
@@ -30,7 +30,6 @@ import org.acegisecurity.GrantedAuthority;
|
||||
public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationToken {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private Object credentials;
|
||||
private Object principal;
|
||||
|
||||
|
||||
-1
@@ -31,7 +31,6 @@ import java.io.Serializable;
|
||||
public class AnonymousAuthenticationToken extends AbstractAuthenticationToken implements Serializable {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private Object principal;
|
||||
private int keyHash;
|
||||
|
||||
|
||||
@@ -35,7 +35,6 @@ import java.util.List;
|
||||
public class CasAuthenticationToken extends AbstractAuthenticationToken implements Serializable {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final List proxyList;
|
||||
private final Object credentials;
|
||||
private final Object principal;
|
||||
|
||||
+2
-2
@@ -55,7 +55,7 @@ public class DaoCasAuthoritiesPopulator implements CasAuthoritiesPopulator, Init
|
||||
return userDetailsService;
|
||||
}
|
||||
|
||||
public void setUserDetailsService(UserDetailsService userDetailsService) {
|
||||
this.userDetailsService = userDetailsService;
|
||||
public void setUserDetailsService(UserDetailsService authenticationDao) {
|
||||
this.userDetailsService = authenticationDao;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ import org.springframework.util.Assert;
|
||||
public abstract class AbstractTicketValidator implements TicketValidator, InitializingBean {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
private static final Log logger = LogFactory.getLog(AbstractTicketValidator.class);
|
||||
private static final Log logger = LogFactory.getLog(CasProxyTicketValidator.class);
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
|
||||
+4
-9
@@ -145,15 +145,10 @@ public abstract class AbstractUserDetailsAuthenticationProvider implements Authe
|
||||
try {
|
||||
additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication);
|
||||
} catch (AuthenticationException exception) {
|
||||
if(cacheWasUsed) {
|
||||
// There was a problem, so try again after checking
|
||||
// we're using latest data (ie not from the cache)
|
||||
cacheWasUsed = false;
|
||||
user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication);
|
||||
additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication);
|
||||
} else {
|
||||
throw exception;
|
||||
}
|
||||
// There was a problem, so try again after checking we're using latest data
|
||||
cacheWasUsed = false;
|
||||
user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication);
|
||||
additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication);
|
||||
}
|
||||
|
||||
if (!user.isCredentialsNonExpired()) {
|
||||
|
||||
@@ -44,7 +44,6 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
|
||||
private PasswordEncoder passwordEncoder = new PlaintextPasswordEncoder();
|
||||
private SaltSource saltSource;
|
||||
private UserDetailsService userDetailsService;
|
||||
private boolean includeDetailsObject = true;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
@@ -59,12 +58,12 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
|
||||
|
||||
if (!passwordEncoder.isPasswordValid(userDetails.getPassword(), authentication.getCredentials().toString(), salt)) {
|
||||
throw new BadCredentialsException(messages.getMessage(
|
||||
"AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"), includeDetailsObject ? userDetails : null);
|
||||
"AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"), userDetails);
|
||||
}
|
||||
}
|
||||
|
||||
protected void doAfterPropertiesSet() throws Exception {
|
||||
Assert.notNull(this.userDetailsService, "A UserDetailsService must be set");
|
||||
Assert.notNull(this.userDetailsService, "An Authentication DAO must be set");
|
||||
}
|
||||
|
||||
public PasswordEncoder getPasswordEncoder() {
|
||||
@@ -91,7 +90,7 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
|
||||
|
||||
if (loadedUser == null) {
|
||||
throw new AuthenticationServiceException(
|
||||
"UserDetailsService returned null, which is an interface contract violation");
|
||||
"AuthenticationDao returned null, which is an interface contract violation");
|
||||
}
|
||||
|
||||
return loadedUser;
|
||||
@@ -118,15 +117,7 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
|
||||
this.saltSource = saltSource;
|
||||
}
|
||||
|
||||
public void setUserDetailsService(UserDetailsService userDetailsService) {
|
||||
this.userDetailsService = userDetailsService;
|
||||
public void setUserDetailsService(UserDetailsService authenticationDao) {
|
||||
this.userDetailsService = authenticationDao;
|
||||
}
|
||||
|
||||
public boolean isIncludeDetailsObject() {
|
||||
return includeDetailsObject;
|
||||
}
|
||||
|
||||
public void setIncludeDetailsObject(boolean includeDetailsObject) {
|
||||
this.includeDetailsObject = includeDetailsObject;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public interface PasswordEncoder {
|
||||
* @param salt optionally used by the implementation to "salt" the raw password before encoding. A
|
||||
* <code>null</code> value is legal.
|
||||
*
|
||||
* @return encoded password
|
||||
* @return DOCUMENT ME!
|
||||
*
|
||||
* @throws DataAccessException DOCUMENT ME!
|
||||
*/
|
||||
@@ -67,7 +67,7 @@ public interface PasswordEncoder {
|
||||
* @param salt optionally used by the implementation to "salt" the raw password before encoding. A
|
||||
* <code>null</code> value is legal.
|
||||
*
|
||||
* @return true if the password is valid , false otherwise
|
||||
* @return DOCUMENT ME!
|
||||
*
|
||||
* @throws DataAccessException DOCUMENT ME!
|
||||
*/
|
||||
|
||||
@@ -30,7 +30,6 @@ import javax.security.auth.login.LoginContext;
|
||||
public class JaasAuthenticationToken extends UsernamePasswordAuthenticationToken {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private transient LoginContext loginContext = null;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
@@ -32,7 +32,6 @@ import java.security.Principal;
|
||||
public class JaasGrantedAuthority extends GrantedAuthorityImpl {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private Principal principal;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
+10
-37
@@ -120,47 +120,25 @@ public class LdapAuthenticationProvider extends AbstractUserDetailsAuthenticatio
|
||||
|
||||
private LdapAuthenticator authenticator;
|
||||
private LdapAuthoritiesPopulator authoritiesPopulator;
|
||||
private boolean includeDetailsObject = true;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
/**
|
||||
* Create an initialized instance to the values passed as arguments
|
||||
*
|
||||
* @param authenticator
|
||||
* @param authoritiesPopulator
|
||||
*/
|
||||
public LdapAuthenticationProvider(LdapAuthenticator authenticator, LdapAuthoritiesPopulator authoritiesPopulator) {
|
||||
this.setAuthenticator(authenticator);
|
||||
this.setAuthoritiesPopulator(authoritiesPopulator);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
private void setAuthenticator(LdapAuthenticator authenticator) {
|
||||
Assert.notNull(authenticator, "An LdapAuthenticator must be supplied");
|
||||
this.authenticator = authenticator;
|
||||
}
|
||||
|
||||
private LdapAuthenticator getAuthenticator() {
|
||||
return authenticator;
|
||||
}
|
||||
|
||||
private void setAuthoritiesPopulator(LdapAuthoritiesPopulator authoritiesPopulator) {
|
||||
Assert.notNull(authoritiesPopulator, "An LdapAuthoritiesPopulator must be supplied");
|
||||
|
||||
this.authenticator = authenticator;
|
||||
this.authoritiesPopulator = authoritiesPopulator;
|
||||
}
|
||||
|
||||
protected LdapAuthoritiesPopulator getAuthoritiesPopulator() {
|
||||
return authoritiesPopulator;
|
||||
}
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
protected void additionalAuthenticationChecks(UserDetails userDetails,
|
||||
UsernamePasswordAuthenticationToken authentication)
|
||||
throws AuthenticationException {
|
||||
if (!userDetails.getPassword().equals(authentication.getCredentials().toString())) {
|
||||
throw new BadCredentialsException(messages.getMessage(
|
||||
"AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"), includeDetailsObject ? userDetails : null);
|
||||
"AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"), userDetails);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,7 +161,7 @@ public class LdapAuthenticationProvider extends AbstractUserDetailsAuthenticatio
|
||||
user.setUsername(username);
|
||||
user.setPassword(password);
|
||||
|
||||
GrantedAuthority[] extraAuthorities = getAuthoritiesPopulator().getGrantedAuthorities(ldapUser);
|
||||
GrantedAuthority[] extraAuthorities = authoritiesPopulator.getGrantedAuthorities(ldapUser);
|
||||
|
||||
for (int i = 0; i < extraAuthorities.length; i++) {
|
||||
user.addAuthority(extraAuthorities[i]);
|
||||
@@ -192,6 +170,10 @@ public class LdapAuthenticationProvider extends AbstractUserDetailsAuthenticatio
|
||||
return user.createUserDetails();
|
||||
}
|
||||
|
||||
protected LdapAuthoritiesPopulator getAuthoritiesPoulator() {
|
||||
return authoritiesPopulator;
|
||||
}
|
||||
|
||||
protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)
|
||||
throws AuthenticationException {
|
||||
if (!StringUtils.hasLength(username)) {
|
||||
@@ -213,7 +195,7 @@ public class LdapAuthenticationProvider extends AbstractUserDetailsAuthenticatio
|
||||
}
|
||||
|
||||
try {
|
||||
LdapUserDetails ldapUser = getAuthenticator().authenticate(username, password);
|
||||
LdapUserDetails ldapUser = authenticator.authenticate(username, password);
|
||||
|
||||
return createUserDetails(ldapUser, username, password);
|
||||
|
||||
@@ -221,13 +203,4 @@ public class LdapAuthenticationProvider extends AbstractUserDetailsAuthenticatio
|
||||
throw new AuthenticationServiceException(ldapAccessFailure.getMessage(), ldapAccessFailure);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isIncludeDetailsObject() {
|
||||
return includeDetailsObject;
|
||||
}
|
||||
|
||||
public void setIncludeDetailsObject(boolean includeDetailsObject) {
|
||||
this.includeDetailsObject = includeDetailsObject;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+8
-23
@@ -70,29 +70,7 @@ public abstract class AbstractLdapAuthenticator implements LdapAuthenticator, In
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
/**
|
||||
* Create an initialized instance to the {@link InitialDirContextFactory} provided.
|
||||
*
|
||||
* @param initialDirContextFactory
|
||||
*/
|
||||
public AbstractLdapAuthenticator(InitialDirContextFactory initialDirContextFactory) {
|
||||
this.setInitialDirContextFactory(initialDirContextFactory);
|
||||
}
|
||||
|
||||
// ~ Methods
|
||||
// ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.isTrue((userDnFormat != null) || (userSearch != null),
|
||||
"Either an LdapUserSearch or DN pattern (or both) must be supplied.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link InitialDirContextFactory} and initialize this instance from its data.
|
||||
*
|
||||
* @param initialDirContextFactory
|
||||
*/
|
||||
private void setInitialDirContextFactory(InitialDirContextFactory initialDirContextFactory) {
|
||||
protected AbstractLdapAuthenticator(InitialDirContextFactory initialDirContextFactory) {
|
||||
Assert.notNull(initialDirContextFactory, "initialDirContextFactory must not be null.");
|
||||
this.initialDirContextFactory = initialDirContextFactory;
|
||||
|
||||
@@ -103,6 +81,13 @@ public abstract class AbstractLdapAuthenticator implements LdapAuthenticator, In
|
||||
}
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.isTrue((userDnFormat != null) || (userSearch != null),
|
||||
"Either an LdapUserSearch or DN pattern (or both) must be supplied.");
|
||||
}
|
||||
|
||||
protected InitialDirContextFactory getInitialDirContextFactory() {
|
||||
return initialDirContextFactory;
|
||||
}
|
||||
|
||||
+8
-19
@@ -26,7 +26,6 @@ import org.acegisecurity.userdetails.ldap.LdapUserDetailsImpl;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import javax.naming.NamingException;
|
||||
import java.util.Iterator;
|
||||
|
||||
|
||||
@@ -45,11 +44,6 @@ public class BindAuthenticator extends AbstractLdapAuthenticator {
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
/**
|
||||
* Create an initialized instance to the {@link InitialDirContextFactory} provided.
|
||||
*
|
||||
* @param initialDirContextFactory
|
||||
*/
|
||||
public BindAuthenticator(InitialDirContextFactory initialDirContextFactory) {
|
||||
super(initialDirContextFactory);
|
||||
}
|
||||
@@ -83,6 +77,10 @@ public class BindAuthenticator extends AbstractLdapAuthenticator {
|
||||
private LdapUserDetails bindWithDn(String userDn, String username, String password) {
|
||||
LdapTemplate template = new LdapTemplate(getInitialDirContextFactory(), userDn, password);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Attempting to bind with DN = " + userDn);
|
||||
}
|
||||
|
||||
try {
|
||||
LdapUserDetailsImpl.Essence user = (LdapUserDetailsImpl.Essence) template.retrieveEntry(userDn,
|
||||
getUserDetailsMapper(), getUserAttributes());
|
||||
@@ -91,21 +89,12 @@ public class BindAuthenticator extends AbstractLdapAuthenticator {
|
||||
return user.createUserDetails();
|
||||
} catch (BadCredentialsException e) {
|
||||
// This will be thrown if an invalid user name is used and the method may
|
||||
// be called multiple times to try different names, so we trap the exception
|
||||
// unless a subclass wishes to implement more specialized behaviour.
|
||||
handleBindException(userDn, username, e.getCause());
|
||||
// be called multiple times to try different names, so we trap the exception.
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Failed to bind as " + userDn + ": " + e.getCause());
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows subclasses to inspect the exception thrown by an attempt to bind with a particular DN.
|
||||
* The default implementation just reports the failure to the debug log.
|
||||
*/
|
||||
void handleBindException(String userDn, String username, Throwable cause) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Failed to bind as " + userDn + ": " + cause);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-37
@@ -121,8 +121,18 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
|
||||
* context factory.
|
||||
*/
|
||||
public DefaultLdapAuthoritiesPopulator(InitialDirContextFactory initialDirContextFactory, String groupSearchBase) {
|
||||
this.setInitialDirContextFactory(initialDirContextFactory);
|
||||
this.setGroupSearchBase(groupSearchBase);
|
||||
Assert.notNull(initialDirContextFactory, "InitialDirContextFactory must not be null");
|
||||
Assert.notNull(groupSearchBase, "The groupSearchBase (name to search under), must not be null.");
|
||||
this.initialDirContextFactory = initialDirContextFactory;
|
||||
this.groupSearchBase = groupSearchBase;
|
||||
|
||||
if (groupSearchBase.length() == 0) {
|
||||
logger.info("groupSearchBase is empty. Searches will be performed from the root: "
|
||||
+ initialDirContextFactory.getRootDn());
|
||||
}
|
||||
|
||||
ldapTemplate = new LdapTemplate(initialDirContextFactory);
|
||||
ldapTemplate.setSearchControls(searchControls);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
@@ -194,16 +204,16 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
|
||||
public Set getGroupMembershipRoles(String userDn, String username) {
|
||||
Set authorities = new HashSet();
|
||||
|
||||
if (getGroupSearchBase() == null) {
|
||||
if (groupSearchBase == null) {
|
||||
return authorities;
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Searching for roles for user '" + username + "', DN = " + "'" + userDn + "', with filter "
|
||||
+ groupSearchFilter + " in search base '" + getGroupSearchBase() + "'");
|
||||
+ groupSearchFilter + " in search base '" + groupSearchBase + "'");
|
||||
}
|
||||
|
||||
Set userRoles = ldapTemplate.searchForSingleAttributeValues(getGroupSearchBase(), groupSearchFilter,
|
||||
Set userRoles = ldapTemplate.searchForSingleAttributeValues(groupSearchBase, groupSearchFilter,
|
||||
new String[] {userDn, username}, groupRoleAttribute);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
@@ -244,38 +254,6 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
|
||||
return initialDirContextFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link InitialDirContextFactory}
|
||||
*
|
||||
* @param initialDirContextFactory supplies the contexts used to search for user roles.
|
||||
*/
|
||||
private void setInitialDirContextFactory(InitialDirContextFactory initialDirContextFactory) {
|
||||
Assert.notNull(initialDirContextFactory, "InitialDirContextFactory must not be null");
|
||||
this.initialDirContextFactory = initialDirContextFactory;
|
||||
|
||||
ldapTemplate = new LdapTemplate(initialDirContextFactory);
|
||||
ldapTemplate.setSearchControls(searchControls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the group search base (name to search under)
|
||||
*
|
||||
* @param groupSearchBase if this is an empty string the search will be performed from the root DN of the context
|
||||
* factory.
|
||||
*/
|
||||
private void setGroupSearchBase(String groupSearchBase) {
|
||||
Assert.notNull(groupSearchBase, "The groupSearchBase (name to search under), must not be null.");
|
||||
this.groupSearchBase = groupSearchBase;
|
||||
if (groupSearchBase.length() == 0) {
|
||||
logger.info("groupSearchBase is empty. Searches will be performed from the root: "
|
||||
+ getInitialDirContextFactory().getRootDn());
|
||||
}
|
||||
}
|
||||
|
||||
private String getGroupSearchBase() {
|
||||
return groupSearchBase;
|
||||
}
|
||||
|
||||
public void setConvertToUpperCase(boolean convertToUpperCase) {
|
||||
this.convertToUpperCase = convertToUpperCase;
|
||||
}
|
||||
|
||||
+13
-5
@@ -15,11 +15,14 @@
|
||||
|
||||
package org.acegisecurity.providers.rememberme;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.acegisecurity.GrantedAuthority;
|
||||
|
||||
import org.acegisecurity.providers.AbstractAuthenticationToken;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
* Represents a remembered <code>Authentication</code>.<p>A remembered <code>Authentication</code> must provide a
|
||||
@@ -31,13 +34,12 @@ import org.acegisecurity.providers.AbstractAuthenticationToken;
|
||||
public class RememberMeAuthenticationToken extends AbstractAuthenticationToken implements Serializable {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private Object principal;
|
||||
private int keyHash;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
/**
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param key to identify if this object made by an authorised client
|
||||
@@ -49,10 +51,16 @@ public class RememberMeAuthenticationToken extends AbstractAuthenticationToken i
|
||||
public RememberMeAuthenticationToken(String key, Object principal, GrantedAuthority[] authorities) {
|
||||
super(authorities);
|
||||
|
||||
if ((key == null) || ("".equals(key)) || (principal == null) || "".equals(principal)) {
|
||||
if ((key == null) || ("".equals(key)) || (principal == null) || "".equals(principal) || (authorities == null)
|
||||
|| (authorities.length == 0)) {
|
||||
throw new IllegalArgumentException("Cannot pass null or empty values to constructor");
|
||||
}
|
||||
|
||||
for (int i = 0; i < authorities.length; i++) {
|
||||
Assert.notNull(authorities[i],
|
||||
"Granted authority element " + i + " is null - GrantedAuthority[] cannot contain any null elements");
|
||||
}
|
||||
|
||||
this.keyHash = key.hashCode();
|
||||
this.principal = principal;
|
||||
setAuthenticated(true);
|
||||
|
||||
-132
@@ -1,132 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.acegisecurity.providers.siteminder;
|
||||
|
||||
import org.acegisecurity.AccountExpiredException;
|
||||
import org.acegisecurity.AuthenticationException;
|
||||
import org.acegisecurity.AuthenticationServiceException;
|
||||
import org.acegisecurity.CredentialsExpiredException;
|
||||
import org.acegisecurity.DisabledException;
|
||||
import org.acegisecurity.LockedException;
|
||||
import org.acegisecurity.providers.AuthenticationProvider;
|
||||
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
|
||||
import org.acegisecurity.providers.dao.AbstractUserDetailsAuthenticationProvider;
|
||||
import org.acegisecurity.userdetails.UserDetails;
|
||||
import org.acegisecurity.userdetails.UserDetailsService;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* An {@link AuthenticationProvider} implementation that retrieves user details from an {@link UserDetailsService}.
|
||||
*
|
||||
* @author Scott McCrory
|
||||
* @version $Id: SiteminderAuthenticationProvider.java 1582 2006-07-15 15:18:51Z smccrory $
|
||||
*/
|
||||
public class SiteminderAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
|
||||
|
||||
/**
|
||||
* Our logging object
|
||||
*/
|
||||
private static final Log logger = LogFactory.getLog(SiteminderAuthenticationProvider.class);
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
/**
|
||||
* Our user details service (which does the real work of checking the user against a back-end user store).
|
||||
*/
|
||||
private UserDetailsService userDetailsService;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* @see org.acegisecurity.providers.dao.AbstractUserDetailsAuthenticationProvider#additionalAuthenticationChecks(org.acegisecurity.userdetails.UserDetails, org.acegisecurity.providers.UsernamePasswordAuthenticationToken)
|
||||
*/
|
||||
protected void additionalAuthenticationChecks(final UserDetails user,
|
||||
final UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
|
||||
|
||||
// No need for password authentication checks - we only expect one identifying string
|
||||
// from the HTTP Request header (as populated by Siteminder), but we do need to see if
|
||||
// the user's account is OK to let them in.
|
||||
if (!user.isEnabled()) {
|
||||
throw new DisabledException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.disabled",
|
||||
"Account disabled"));
|
||||
}
|
||||
|
||||
if (!user.isAccountNonExpired()) {
|
||||
throw new AccountExpiredException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.expired",
|
||||
"Account expired"));
|
||||
}
|
||||
|
||||
if (!user.isAccountNonLocked()) {
|
||||
throw new LockedException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.locked",
|
||||
"Account locked"));
|
||||
}
|
||||
|
||||
if (!user.isCredentialsNonExpired()) {
|
||||
throw new CredentialsExpiredException(messages.getMessage(
|
||||
"AbstractUserDetailsAuthenticationProvider.credentialsExpired", "Credentials expired"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.acegisecurity.providers.dao.AbstractUserDetailsAuthenticationProvider#doAfterPropertiesSet()
|
||||
*/
|
||||
protected void doAfterPropertiesSet() throws Exception {
|
||||
Assert.notNull(this.userDetailsService, "A UserDetailsService must be set");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the user details service.
|
||||
* @return The user details service.
|
||||
*/
|
||||
public UserDetailsService getUserDetailsService() {
|
||||
return userDetailsService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.acegisecurity.providers.dao.AbstractUserDetailsAuthenticationProvider#retrieveUser(java.lang.String, org.acegisecurity.providers.UsernamePasswordAuthenticationToken)
|
||||
*/
|
||||
protected final UserDetails retrieveUser(final String username,
|
||||
final UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
|
||||
|
||||
UserDetails loadedUser;
|
||||
|
||||
try {
|
||||
loadedUser = this.getUserDetailsService().loadUserByUsername(username);
|
||||
} catch (DataAccessException repositoryProblem) {
|
||||
throw new AuthenticationServiceException(repositoryProblem.getMessage(), repositoryProblem);
|
||||
}
|
||||
|
||||
if (loadedUser == null) {
|
||||
throw new AuthenticationServiceException(
|
||||
"UserDetailsService returned null, which is an interface contract violation");
|
||||
}
|
||||
|
||||
return loadedUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the user details service.
|
||||
* @param userDetailsService The user details service.
|
||||
*/
|
||||
public void setUserDetailsService(final UserDetailsService userDetailsService) {
|
||||
this.userDetailsService = userDetailsService;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
A Siteminder authentication provider.
|
||||
</body>
|
||||
</html>
|
||||
@@ -31,7 +31,6 @@ import java.security.cert.X509Certificate;
|
||||
public class X509AuthenticationToken extends AbstractAuthenticationToken {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private Object principal;
|
||||
private X509Certificate credentials;
|
||||
|
||||
|
||||
+2
-2
@@ -117,7 +117,7 @@ public class DaoX509AuthoritiesPopulator implements X509AuthoritiesPopulator, In
|
||||
this.subjectDNRegex = subjectDNRegex;
|
||||
}
|
||||
|
||||
public void setUserDetailsService(UserDetailsService userDetailsService) {
|
||||
this.userDetailsService = userDetailsService;
|
||||
public void setUserDetailsService(UserDetailsService authenticationDao) {
|
||||
this.userDetailsService = authenticationDao;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ import org.acegisecurity.providers.AbstractAuthenticationToken;
|
||||
public class RunAsUserToken extends AbstractAuthenticationToken {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private Class originalAuthentication;
|
||||
private Object credentials;
|
||||
private Object principal;
|
||||
|
||||
@@ -1,223 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.acegisecurity.taglibs.authz;
|
||||
|
||||
import org.acegisecurity.acls.Acl;
|
||||
import org.acegisecurity.acls.AclService;
|
||||
import org.acegisecurity.acls.NotFoundException;
|
||||
import org.acegisecurity.acls.Permission;
|
||||
import org.acegisecurity.acls.domain.BasePermission;
|
||||
import org.acegisecurity.acls.objectidentity.ObjectIdentity;
|
||||
import org.acegisecurity.acls.objectidentity.ObjectIdentityRetrievalStrategy;
|
||||
import org.acegisecurity.acls.objectidentity.ObjectIdentityRetrievalStrategyImpl;
|
||||
import org.acegisecurity.acls.sid.Sid;
|
||||
import org.acegisecurity.acls.sid.SidRetrievalStrategy;
|
||||
import org.acegisecurity.acls.sid.SidRetrievalStrategyImpl;
|
||||
|
||||
import org.acegisecurity.context.SecurityContextHolder;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
import org.springframework.web.context.support.WebApplicationContextUtils;
|
||||
import org.springframework.web.util.ExpressionEvaluationUtils;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.jsp.JspException;
|
||||
import javax.servlet.jsp.PageContext;
|
||||
import javax.servlet.jsp.tagext.Tag;
|
||||
import javax.servlet.jsp.tagext.TagSupport;
|
||||
|
||||
|
||||
/**
|
||||
* An implementation of {@link javax.servlet.jsp.tagext.Tag} that allows its body through if some authorizations
|
||||
* are granted to the request's principal.<p>One or more comma separate numeric are specified via the
|
||||
* <code>hasPermission</code> attribute. Those permissions are then converted into {@link Permission} instances. These
|
||||
* instances are then presented as an array to the {@link Acl#isGranted(Permission[],
|
||||
* org.acegisecurity.acls.sid.Sid[], boolean)} method. The {@link Sid} presented is determined by the {@link
|
||||
* SidRetrievalStrategy}.</p>
|
||||
* <p>For this class to operate it must be able to access the application context via the
|
||||
* <code>WebApplicationContextUtils</code> and locate an {@link AclService} and {@link SidRetrievalStrategy}.
|
||||
* Application contexts must provide one and only one of these Java types.</p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class AccessControlListTag extends TagSupport {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
protected static final Log logger = LogFactory.getLog(AccessControlListTag.class);
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private AclService aclService;
|
||||
private ApplicationContext applicationContext;
|
||||
private Object domainObject;
|
||||
private ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy;
|
||||
private SidRetrievalStrategy sidRetrievalStrategy;
|
||||
private String hasPermission = "";
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public int doStartTag() throws JspException {
|
||||
initializeIfRequired();
|
||||
|
||||
if ((null == hasPermission) || "".equals(hasPermission)) {
|
||||
return Tag.SKIP_BODY;
|
||||
}
|
||||
|
||||
final String evaledPermissionsString = ExpressionEvaluationUtils.evaluateString("hasPermission", hasPermission,
|
||||
pageContext);
|
||||
|
||||
Permission[] requiredPermissions = null;
|
||||
|
||||
try {
|
||||
requiredPermissions = parsePermissionsString(evaledPermissionsString);
|
||||
} catch (NumberFormatException nfe) {
|
||||
throw new JspException(nfe);
|
||||
}
|
||||
|
||||
Object resolvedDomainObject = null;
|
||||
|
||||
if (domainObject instanceof String) {
|
||||
resolvedDomainObject = ExpressionEvaluationUtils.evaluate("domainObject", (String) domainObject,
|
||||
Object.class, pageContext);
|
||||
} else {
|
||||
resolvedDomainObject = domainObject;
|
||||
}
|
||||
|
||||
if (resolvedDomainObject == null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("domainObject resolved to null, so including tag body");
|
||||
}
|
||||
|
||||
// Of course they have access to a null object!
|
||||
return Tag.EVAL_BODY_INCLUDE;
|
||||
}
|
||||
|
||||
if (SecurityContextHolder.getContext().getAuthentication() == null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(
|
||||
"SecurityContextHolder did not return a non-null Authentication object, so skipping tag body");
|
||||
}
|
||||
|
||||
return Tag.SKIP_BODY;
|
||||
}
|
||||
|
||||
Sid[] sids = sidRetrievalStrategy.getSids(SecurityContextHolder.getContext().getAuthentication());
|
||||
ObjectIdentity oid = objectIdentityRetrievalStrategy.getObjectIdentity(resolvedDomainObject);
|
||||
|
||||
// Obtain aclEntrys applying to the current Authentication object
|
||||
try {
|
||||
Acl acl = aclService.readAclById(oid, sids);
|
||||
|
||||
if (acl.isGranted(requiredPermissions, sids, false)) {
|
||||
return Tag.EVAL_BODY_INCLUDE;
|
||||
} else {
|
||||
return Tag.SKIP_BODY;
|
||||
}
|
||||
} catch (NotFoundException nfe) {
|
||||
return Tag.SKIP_BODY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows test cases to override where application context obtained from.
|
||||
*
|
||||
* @param pageContext so the <code>ServletContext</code> can be accessed as required by Spring's
|
||||
* <code>WebApplicationContextUtils</code>
|
||||
*
|
||||
* @return the Spring application context (never <code>null</code>)
|
||||
*/
|
||||
protected ApplicationContext getContext(PageContext pageContext) {
|
||||
ServletContext servletContext = pageContext.getServletContext();
|
||||
|
||||
return WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
|
||||
}
|
||||
|
||||
public Object getDomainObject() {
|
||||
return domainObject;
|
||||
}
|
||||
|
||||
public String getHasPermission() {
|
||||
return hasPermission;
|
||||
}
|
||||
|
||||
private void initializeIfRequired() throws JspException {
|
||||
if (applicationContext == null) {
|
||||
this.applicationContext = getContext(pageContext);
|
||||
|
||||
Map map = applicationContext.getBeansOfType(AclService.class);
|
||||
|
||||
if (map.size() != 1) {
|
||||
throw new JspException(
|
||||
"Found incorrect number of AclService instances in application context - you must have only have one!");
|
||||
}
|
||||
|
||||
aclService = (AclService) map.values().iterator().next();
|
||||
|
||||
map = applicationContext.getBeansOfType(SidRetrievalStrategy.class);
|
||||
|
||||
if (map.size() == 0) {
|
||||
sidRetrievalStrategy = new SidRetrievalStrategyImpl();
|
||||
} else if (map.size() == 1) {
|
||||
sidRetrievalStrategy = (SidRetrievalStrategy) map.values().iterator().next();
|
||||
} else {
|
||||
throw new JspException(
|
||||
"Found incorrect number of SidRetrievalStrategy instances in application context - you must have only have one!");
|
||||
}
|
||||
|
||||
map = applicationContext.getBeansOfType(ObjectIdentityRetrievalStrategy.class);
|
||||
|
||||
if (map.size() == 0) {
|
||||
objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl();
|
||||
} else if (map.size() == 1) {
|
||||
objectIdentityRetrievalStrategy = (ObjectIdentityRetrievalStrategy) map.values().iterator().next();
|
||||
} else {
|
||||
throw new JspException(
|
||||
"Found incorrect number of ObjectIdentityRetrievalStrategy instances in application context - you must have only have one!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Permission[] parsePermissionsString(String integersString)
|
||||
throws NumberFormatException {
|
||||
final Set permissions = new HashSet();
|
||||
final StringTokenizer tokenizer;
|
||||
tokenizer = new StringTokenizer(integersString, ",", false);
|
||||
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
String integer = tokenizer.nextToken();
|
||||
permissions.add(BasePermission.buildFromMask(new Integer(integer).intValue()));
|
||||
}
|
||||
|
||||
return (Permission[]) permissions.toArray(new Permission[] {});
|
||||
}
|
||||
|
||||
public void setDomainObject(Object domainObject) {
|
||||
this.domainObject = domainObject;
|
||||
}
|
||||
|
||||
public void setHasPermission(String hasPermission) {
|
||||
this.hasPermission = hasPermission;
|
||||
}
|
||||
}
|
||||
@@ -150,7 +150,7 @@ public class AuthorizeTag extends TagSupport {
|
||||
|
||||
// Remove the role's whitespace characters without depending on JDK 1.4+
|
||||
// Includes space, tab, new line, carriage return and form feed.
|
||||
String role = authority.trim(); // trim, don't use spaces, as per SEC-378
|
||||
String role = StringUtils.replace(authority, " ", "");
|
||||
role = StringUtils.replace(role, "\t", "");
|
||||
role = StringUtils.replace(role, "\r", "");
|
||||
role = StringUtils.replace(role, "\n", "");
|
||||
|
||||
@@ -313,13 +313,13 @@ public abstract class AbstractProcessingFilter implements Filter, InitializingBe
|
||||
return uri.endsWith(request.getContextPath() + filterProcessesUrl);
|
||||
}
|
||||
|
||||
protected void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url)
|
||||
protected void sendRedirect(HttpServletRequest request, HttpServletResponse response, String failureUrl)
|
||||
throws IOException {
|
||||
if (!url.startsWith("http://") && !url.startsWith("https://")) {
|
||||
url = request.getContextPath() + url;
|
||||
if (!failureUrl.startsWith("http://") && !failureUrl.startsWith("https://")) {
|
||||
failureUrl = request.getContextPath() + failureUrl;
|
||||
}
|
||||
|
||||
response.sendRedirect(response.encodeRedirectURL(url));
|
||||
response.sendRedirect(response.encodeRedirectURL(failureUrl));
|
||||
}
|
||||
|
||||
public void setAlwaysUseDefaultTargetUrl(boolean alwaysUseDefaultTargetUrl) {
|
||||
@@ -348,8 +348,6 @@ public abstract class AbstractProcessingFilter implements Filter, InitializingBe
|
||||
}
|
||||
|
||||
public void setDefaultTargetUrl(String defaultTargetUrl) {
|
||||
Assert.isTrue(defaultTargetUrl.startsWith("/") | defaultTargetUrl.startsWith("http"),
|
||||
"defaultTarget must start with '/' or with 'http(s)'");
|
||||
this.defaultTargetUrl = defaultTargetUrl;
|
||||
}
|
||||
|
||||
@@ -381,11 +379,14 @@ public abstract class AbstractProcessingFilter implements Filter, InitializingBe
|
||||
logger.debug("Updated SecurityContextHolder to contain the following Authentication: '" + authResult + "'");
|
||||
}
|
||||
|
||||
// Don't attempt to obtain the url from the saved request if alwaysUsedefaultTargetUrl is set
|
||||
String targetUrl = alwaysUseDefaultTargetUrl ? null : obtainFullRequestUrl(request);
|
||||
String targetUrl = obtainFullRequestUrl(request);
|
||||
|
||||
if (alwaysUseDefaultTargetUrl) {
|
||||
targetUrl = null;
|
||||
}
|
||||
|
||||
if (targetUrl == null) {
|
||||
targetUrl = getDefaultTargetUrl();
|
||||
targetUrl = request.getContextPath() + getDefaultTargetUrl();
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
@@ -401,7 +402,7 @@ public abstract class AbstractProcessingFilter implements Filter, InitializingBe
|
||||
eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authResult, this.getClass()));
|
||||
}
|
||||
|
||||
sendRedirect(request, response, targetUrl);
|
||||
response.sendRedirect(response.encodeRedirectURL(targetUrl));
|
||||
}
|
||||
|
||||
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
|
||||
@@ -428,9 +429,4 @@ public abstract class AbstractProcessingFilter implements Filter, InitializingBe
|
||||
|
||||
sendRedirect(request, response, failureUrl);
|
||||
}
|
||||
|
||||
public AuthenticationDetailsSource getAuthenticationDetailsSource() {
|
||||
// Required due to SEC-310
|
||||
return authenticationDetailsSource;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,13 +62,21 @@ public class AccessDeniedHandlerImpl implements AccessDeniedHandler {
|
||||
|
||||
// Perform RequestDispatcher "forward"
|
||||
RequestDispatcher rd = request.getRequestDispatcher(errorPage);
|
||||
rd.forward(request, response);
|
||||
|
||||
try {
|
||||
rd.forward(request, response);
|
||||
((HttpServletResponse) response).setStatus(HttpServletResponse.SC_FORBIDDEN);
|
||||
|
||||
return;
|
||||
} catch (Exception responseCommitted) {
|
||||
if (logger.isErrorEnabled()) {
|
||||
logger.error("Error processing " + request.toString(), responseCommitted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!response.isCommitted()) {
|
||||
// Send 403 (we do this after response has been written)
|
||||
((HttpServletResponse) response).sendError(HttpServletResponse.SC_FORBIDDEN, accessDeniedException.getMessage());
|
||||
}
|
||||
// Send 403 (we do this after response has been written)
|
||||
((HttpServletResponse) response).sendError(HttpServletResponse.SC_FORBIDDEN, accessDeniedException.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,6 +15,27 @@
|
||||
|
||||
package org.acegisecurity.ui.basicauth;
|
||||
|
||||
import org.acegisecurity.Authentication;
|
||||
import org.acegisecurity.AuthenticationException;
|
||||
import org.acegisecurity.AuthenticationManager;
|
||||
|
||||
import org.acegisecurity.context.SecurityContextHolder;
|
||||
|
||||
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
|
||||
|
||||
import org.acegisecurity.ui.AuthenticationDetailsSource;
|
||||
import org.acegisecurity.ui.AuthenticationDetailsSourceImpl;
|
||||
import org.acegisecurity.ui.AuthenticationEntryPoint;
|
||||
import org.acegisecurity.ui.rememberme.RememberMeServices;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
@@ -26,21 +47,6 @@ import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.acegisecurity.Authentication;
|
||||
import org.acegisecurity.AuthenticationException;
|
||||
import org.acegisecurity.AuthenticationManager;
|
||||
import org.acegisecurity.context.SecurityContextHolder;
|
||||
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
|
||||
import org.acegisecurity.ui.AuthenticationDetailsSource;
|
||||
import org.acegisecurity.ui.AuthenticationDetailsSourceImpl;
|
||||
import org.acegisecurity.ui.AuthenticationEntryPoint;
|
||||
import org.acegisecurity.ui.rememberme.RememberMeServices;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* Processes a HTTP request's BASIC authorization headers, putting the result into the
|
||||
@@ -129,10 +135,7 @@ public class BasicProcessingFilter implements Filter, InitializingBean {
|
||||
// Only reauthenticate if username doesn't match SecurityContextHolder and user isn't authenticated (see SEC-53)
|
||||
Authentication existingAuth = SecurityContextHolder.getContext().getAuthentication();
|
||||
|
||||
// Limit username comparison to providers which user usernames (ie UsernamePasswordAuthenticationToken) (see SEC-348)
|
||||
if ((existingAuth == null)
|
||||
|| (existingAuth instanceof UsernamePasswordAuthenticationToken && !existingAuth.getName().equals(username))
|
||||
|| !existingAuth.isAuthenticated()) {
|
||||
if ((existingAuth == null) || !existingAuth.getName().equals(username) || !existingAuth.isAuthenticated()) {
|
||||
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username,
|
||||
password);
|
||||
authRequest.setDetails(authenticationDetailsSource.buildDetails((HttpServletRequest) request));
|
||||
|
||||
@@ -431,7 +431,7 @@ public class DigestProcessingFilter implements Filter, InitializingBean, Message
|
||||
this.userCache = userCache;
|
||||
}
|
||||
|
||||
public void setUserDetailsService(UserDetailsService userDetailsService) {
|
||||
this.userDetailsService = userDetailsService;
|
||||
public void setUserDetailsService(UserDetailsService authenticationDao) {
|
||||
this.userDetailsService = authenticationDao;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,8 +94,10 @@ public class LogoutFilter implements Filter {
|
||||
logger.debug("Logging out user '" + auth + "' and redirecting to logout page");
|
||||
}
|
||||
|
||||
for (int i = 0; i < handlers.length; i++) {
|
||||
handlers[i].logout(httpRequest, httpResponse, auth);
|
||||
if (auth != null) {
|
||||
for (int i = 0; i < handlers.length; i++) {
|
||||
handlers[i].logout(httpRequest, httpResponse, auth);
|
||||
}
|
||||
}
|
||||
|
||||
sendRedirect(httpRequest, httpResponse, logoutSuccessUrl);
|
||||
|
||||
@@ -18,60 +18,28 @@ package org.acegisecurity.ui.logout;
|
||||
import org.acegisecurity.Authentication;
|
||||
|
||||
import org.acegisecurity.context.SecurityContextHolder;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
|
||||
/**
|
||||
* Performs a logout by modifying the {@link org.acegisecurity.context.SecurityContextHolder}.
|
||||
*
|
||||
* <p>Will also invalidate the {@link HttpSession} if {@link #isInvalidateHttpSession()} is
|
||||
* <code>true</code> and the session is not <code>null</code>.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class SecurityContextLogoutHandler implements LogoutHandler {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
private boolean invalidateHttpSession = true;
|
||||
|
||||
/**
|
||||
* Requires the request to be passed in.
|
||||
* Does not use any arguments. They can all be <code>null</code>.
|
||||
*
|
||||
* @param request from which to obtain a HTTP session (cannot be null)
|
||||
* @param request not used (can be <code>null</code>)
|
||||
* @param response not used (can be <code>null</code>)
|
||||
* @param authentication not used (can be <code>null</code>)
|
||||
*/
|
||||
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
|
||||
Assert.notNull(request, "HttpServletRequest required");
|
||||
if (invalidateHttpSession) {
|
||||
HttpSession session = request.getSession(false);
|
||||
if (session != null) {
|
||||
session.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
SecurityContextHolder.clearContext();
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
public boolean isInvalidateHttpSession() {
|
||||
return invalidateHttpSession;
|
||||
}
|
||||
|
||||
/**
|
||||
* Causes the {@link HttpSession} to be invalidated when this
|
||||
* {@link LogoutHandler} is invoked. Defaults to true.
|
||||
*
|
||||
* @param invalidateHttpSession true if you wish the session to be
|
||||
* invalidated (default) or false if it should not be
|
||||
*/
|
||||
public void setInvalidateHttpSession(boolean invalidateHttpSession) {
|
||||
this.invalidateHttpSession = invalidateHttpSession;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+5
-22
@@ -90,7 +90,6 @@ public class TokenBasedRememberMeServices implements RememberMeServices, Initial
|
||||
private String parameter = DEFAULT_PARAMETER;
|
||||
private UserDetailsService userDetailsService;
|
||||
private long tokenValiditySeconds = 1209600; // 14 days
|
||||
private boolean alwaysRemember = false;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
@@ -239,18 +238,10 @@ public class TokenBasedRememberMeServices implements RememberMeServices, Initial
|
||||
cancelCookie(request, response, "Interactive authentication attempt was unsuccessful");
|
||||
}
|
||||
|
||||
protected boolean rememberMeRequested(HttpServletRequest request, String parameter) {
|
||||
if (alwaysRemember) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return RequestUtils.getBooleanParameter(request, parameter, false);
|
||||
}
|
||||
|
||||
public void loginSuccess(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication successfulAuthentication) {
|
||||
// Exit if the principal hasn't asked to be remembered
|
||||
if (!rememberMeRequested(request, parameter)) {
|
||||
if (!RequestUtils.getBooleanParameter(request, parameter, false)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Did not send remember-me cookie (principal did not set parameter '" + this.parameter
|
||||
+ "')");
|
||||
@@ -298,7 +289,7 @@ public class TokenBasedRememberMeServices implements RememberMeServices, Initial
|
||||
protected Cookie makeCancelCookie(HttpServletRequest request) {
|
||||
Cookie cookie = new Cookie(ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY, null);
|
||||
cookie.setMaxAge(0);
|
||||
cookie.setPath(StringUtils.hasLength(request.getContextPath()) ? request.getContextPath() : "/");
|
||||
cookie.setPath(request.getContextPath());
|
||||
|
||||
return cookie;
|
||||
}
|
||||
@@ -306,7 +297,7 @@ public class TokenBasedRememberMeServices implements RememberMeServices, Initial
|
||||
protected Cookie makeValidCookie(long expiryTime, String tokenValueBase64, HttpServletRequest request) {
|
||||
Cookie cookie = new Cookie(ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY, tokenValueBase64);
|
||||
cookie.setMaxAge(60 * 60 * 24 * 365 * 5); // 5 years
|
||||
cookie.setPath(StringUtils.hasLength(request.getContextPath()) ? request.getContextPath() : "/");
|
||||
cookie.setPath(request.getContextPath());
|
||||
|
||||
return cookie;
|
||||
}
|
||||
@@ -328,15 +319,7 @@ public class TokenBasedRememberMeServices implements RememberMeServices, Initial
|
||||
this.tokenValiditySeconds = tokenValiditySeconds;
|
||||
}
|
||||
|
||||
public void setUserDetailsService(UserDetailsService userDetailsService) {
|
||||
this.userDetailsService = userDetailsService;
|
||||
public void setUserDetailsService(UserDetailsService authenticationDao) {
|
||||
this.userDetailsService = authenticationDao;
|
||||
}
|
||||
|
||||
public boolean isAlwaysRemember() {
|
||||
return alwaysRemember;
|
||||
}
|
||||
|
||||
public void setAlwaysRemember(boolean alwaysRemember) {
|
||||
this.alwaysRemember = alwaysRemember;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,11 +25,11 @@ import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
|
||||
/**
|
||||
@@ -55,8 +55,8 @@ public class SavedRequest implements java.io.Serializable {
|
||||
|
||||
private ArrayList cookies = new ArrayList();
|
||||
private ArrayList locales = new ArrayList();
|
||||
private Map headers = new TreeMap(String.CASE_INSENSITIVE_ORDER);
|
||||
private Map parameters = new TreeMap(String.CASE_INSENSITIVE_ORDER);
|
||||
private HashMap headers = new HashMap();
|
||||
private HashMap parameters = new HashMap();
|
||||
private String contextPath;
|
||||
private String method;
|
||||
private String pathInfo;
|
||||
@@ -110,15 +110,8 @@ public class SavedRequest implements java.io.Serializable {
|
||||
|
||||
while (paramNames.hasNext()) {
|
||||
String paramName = (String) paramNames.next();
|
||||
Object o = parameters.get(paramName);
|
||||
if (o instanceof String[]) {
|
||||
String[] paramValues = (String[]) o;
|
||||
this.addParameter(paramName, paramValues);
|
||||
} else {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("ServletRequest.getParameterMap() returned non-String array");
|
||||
}
|
||||
}
|
||||
String[] paramValues = (String[]) parameters.get(paramName);
|
||||
this.addParameter(paramName, paramValues);
|
||||
}
|
||||
|
||||
// Primitives
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
package org.acegisecurity.ui.switchuser;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.acegisecurity.Authentication;
|
||||
import org.acegisecurity.GrantedAuthority;
|
||||
import org.acegisecurity.userdetails.UserDetails;
|
||||
|
||||
/**
|
||||
* Allows subclasses to modify the {@link GrantedAuthority} list that will be assigned to the principal
|
||||
* when they assume the identity of a different principal.
|
||||
*
|
||||
* <p>Configured against the {@link SwitchUserProcessingFilter}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*
|
||||
*/
|
||||
public interface SwitchUserAuthorityChanger {
|
||||
|
||||
/**
|
||||
* Allow subclasses to add or remove authorities that will be granted when in switch user mode.
|
||||
*
|
||||
* @param targetUser the UserDetails representing the identity being switched to
|
||||
* @param currentAuthentication the current Authentication of the principal performing the switching
|
||||
* @param authoritiesToBeGranted all {@link GrantedAuthority} instances to be granted to the user,
|
||||
* excluding the special "switch user" authority that is used internally (guaranteed never null)
|
||||
*/
|
||||
public void modifyGrantedAuthorities(UserDetails targetUser, Authentication currentAuthentication, List authoritiesToBeGranted);
|
||||
}
|
||||
@@ -31,7 +31,6 @@ import org.acegisecurity.GrantedAuthorityImpl;
|
||||
public class SwitchUserGrantedAuthority extends GrantedAuthorityImpl {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private Authentication source;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
@@ -115,7 +115,6 @@ public class SwitchUserProcessingFilter implements Filter, InitializingBean, App
|
||||
private String exitUserUrl = "/j_acegi_exit_user";
|
||||
private String switchUserUrl = "/j_acegi_switch_user";
|
||||
private String targetUrl;
|
||||
private SwitchUserAuthorityChanger switchUserAuthorityChanger;
|
||||
|
||||
// ~ Instance fields
|
||||
// ========================================================
|
||||
@@ -278,11 +277,6 @@ public class SwitchUserProcessingFilter implements Filter, InitializingBean, App
|
||||
// get the original authorities
|
||||
List orig = Arrays.asList(targetUser.getAuthorities());
|
||||
|
||||
// Allow subclasses to change the authorities to be granted
|
||||
if (switchUserAuthorityChanger != null) {
|
||||
switchUserAuthorityChanger.modifyGrantedAuthorities(targetUser, currentAuth, orig);
|
||||
}
|
||||
|
||||
// add the new switch user authority
|
||||
List newAuths = new ArrayList(orig);
|
||||
newAuths.add(switchAuthority);
|
||||
@@ -445,8 +439,8 @@ public class SwitchUserProcessingFilter implements Filter, InitializingBean, App
|
||||
*
|
||||
* @param authenticationDao The authentication dao
|
||||
*/
|
||||
public void setUserDetailsService(UserDetailsService userDetailsService) {
|
||||
this.userDetailsService = userDetailsService;
|
||||
public void setUserDetailsService(UserDetailsService authenticationDao) {
|
||||
this.userDetailsService = authenticationDao;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -466,12 +460,4 @@ public class SwitchUserProcessingFilter implements Filter, InitializingBean, App
|
||||
|
||||
return uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param switchUserAuthorityChanger to use to fine-tune the authorities granted to subclasses (may be null if
|
||||
* SwitchUserProcessingFilter shoudl not fine-tune the authorities)
|
||||
*/
|
||||
public void setSwitchUserAuthorityChanger(SwitchUserAuthorityChanger switchUserAuthorityChanger) {
|
||||
this.switchUserAuthorityChanger = switchUserAuthorityChanger;
|
||||
}
|
||||
}
|
||||
|
||||
+5
-64
@@ -33,7 +33,6 @@ import org.springframework.util.Assert;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
@@ -67,7 +66,6 @@ public class AuthenticationProcessingFilterEntryPoint implements AuthenticationE
|
||||
private PortResolver portResolver = new PortResolverImpl();
|
||||
private String loginFormUrl;
|
||||
private boolean forceHttps = false;
|
||||
private boolean serverSideRedirect = false;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
@@ -90,69 +88,27 @@ public class AuthenticationProcessingFilterEntryPoint implements AuthenticationE
|
||||
|
||||
boolean includePort = true;
|
||||
|
||||
String redirectUrl = null;
|
||||
boolean doForceHttps = false;
|
||||
Integer httpsPort = null;
|
||||
|
||||
if (inHttp && (serverPort == 80)) {
|
||||
includePort = false;
|
||||
} else if (inHttps && (serverPort == 443)) {
|
||||
includePort = false;
|
||||
}
|
||||
|
||||
String redirectUrl = scheme + "://" + serverName + ((includePort) ? (":" + serverPort) : "") + contextPath
|
||||
+ loginFormUrl;
|
||||
|
||||
if (forceHttps && inHttp) {
|
||||
httpsPort = (Integer) portMapper.lookupHttpsPort(new Integer(serverPort));
|
||||
|
||||
Integer httpsPort = (Integer) portMapper.lookupHttpsPort(new Integer(serverPort));
|
||||
|
||||
if (httpsPort != null) {
|
||||
doForceHttps = true;
|
||||
if (httpsPort.intValue() == 443) {
|
||||
includePort = false;
|
||||
} else {
|
||||
includePort = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( serverSideRedirect ) {
|
||||
|
||||
if ( doForceHttps ) {
|
||||
|
||||
// before doing server side redirect, we need to do client redirect to https.
|
||||
|
||||
String servletPath = req.getServletPath();
|
||||
String pathInfo = req.getPathInfo();
|
||||
String query = req.getQueryString();
|
||||
|
||||
redirectUrl = "https://" + serverName + ((includePort) ? (":" + httpsPort) : "") + contextPath
|
||||
+ servletPath + (pathInfo == null ? "" : pathInfo ) + (query == null ? "" : "?"+query );
|
||||
|
||||
} else {
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Server side forward to: " + loginFormUrl);
|
||||
}
|
||||
|
||||
RequestDispatcher dispatcher = req.getRequestDispatcher( loginFormUrl );
|
||||
|
||||
dispatcher.forward( request, response );
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if ( doForceHttps ) {
|
||||
|
||||
redirectUrl = "https://" + serverName + ((includePort) ? (":" + httpsPort) : "") + contextPath
|
||||
+ loginFormUrl;
|
||||
|
||||
} else {
|
||||
|
||||
redirectUrl = scheme + "://" + serverName + ((includePort) ? (":" + serverPort) : "") + contextPath
|
||||
+ loginFormUrl;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,10 +135,6 @@ public class AuthenticationProcessingFilterEntryPoint implements AuthenticationE
|
||||
return portResolver;
|
||||
}
|
||||
|
||||
public boolean isServerSideRedirect() {
|
||||
return serverSideRedirect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true to force login form access to be via https. If this value is ture (the default is false),
|
||||
* and the incoming request for the protected resource which triggered the interceptor was not already
|
||||
@@ -211,15 +163,4 @@ public class AuthenticationProcessingFilterEntryPoint implements AuthenticationE
|
||||
public void setPortResolver(PortResolver portResolver) {
|
||||
this.portResolver = portResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if we are to do a server side include of the <code>loginFormUrl</code> instead of a 302
|
||||
* redirect.
|
||||
*
|
||||
* @param serverSideRedirect
|
||||
*/
|
||||
public void setServerSideRedirect(boolean serverSideRedirect) {
|
||||
this.serverSideRedirect = serverSideRedirect;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
Authenticates users via HTTP properties, headers and session.
|
||||
Authenticates users via a standard web form and <code>HttpSession</code>.
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -31,7 +31,6 @@ import org.springframework.util.Assert;
|
||||
public class User implements UserDetails {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private String password;
|
||||
private String username;
|
||||
private GrantedAuthority[] authorities;
|
||||
|
||||
@@ -38,12 +38,6 @@ import java.io.Serializable;
|
||||
* {@link org.acegisecurity.userdetails.User} for a
|
||||
* reference implementation (which you might like to extend).
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Concrete implementations should be immutable (value object semantics,
|
||||
* like a String). This is because the <code>UserDetails</code> will be
|
||||
* stored in caches and as such multiple threads may use the same instance.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
|
||||
@@ -41,7 +41,6 @@ import javax.naming.ldap.Control;
|
||||
public class LdapUserDetailsImpl implements LdapUserDetails {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final GrantedAuthority[] NO_AUTHORITIES = new GrantedAuthority[0];
|
||||
private static final Control[] NO_CONTROLS = new Control[0];
|
||||
|
||||
@@ -110,7 +109,7 @@ public class LdapUserDetailsImpl implements LdapUserDetails {
|
||||
* Variation of essence pattern. Used to create mutable intermediate object
|
||||
*/
|
||||
public static class Essence {
|
||||
LdapUserDetailsImpl instance = createTarget();
|
||||
LdapUserDetailsImpl instance = new LdapUserDetailsImpl();
|
||||
List mutableAuthorities = new ArrayList();
|
||||
|
||||
public Essence() {}
|
||||
@@ -128,10 +127,6 @@ public class LdapUserDetailsImpl implements LdapUserDetails {
|
||||
setAuthorities(copyMe.getAuthorities());
|
||||
}
|
||||
|
||||
LdapUserDetailsImpl createTarget() {
|
||||
return new LdapUserDetailsImpl();
|
||||
}
|
||||
|
||||
public Essence addAuthority(GrantedAuthority a) {
|
||||
mutableAuthorities.add(a);
|
||||
|
||||
|
||||
@@ -58,7 +58,14 @@ public class LdapUserDetailsMapper implements LdapEntryMapper {
|
||||
Attribute passwordAttribute = attributes.get(passwordAttributeName);
|
||||
|
||||
if (passwordAttribute != null) {
|
||||
essence.setPassword(mapPassword(passwordAttribute));
|
||||
Object retrievedPassword = passwordAttribute.get();
|
||||
|
||||
if (!(retrievedPassword instanceof String)) {
|
||||
// Assume it's binary
|
||||
retrievedPassword = new String((byte[]) retrievedPassword);
|
||||
}
|
||||
|
||||
essence.setPassword((String) retrievedPassword);
|
||||
}
|
||||
|
||||
// Map the roles
|
||||
@@ -86,25 +93,6 @@ public class LdapUserDetailsMapper implements LdapEntryMapper {
|
||||
return essence;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extension point to allow customized creation of the user's password from
|
||||
* the attribute stored in the directory.
|
||||
*
|
||||
* @param passwordAttribute the attribute instance containing the password
|
||||
* @return a String representation of the password.
|
||||
*/
|
||||
protected String mapPassword(Attribute passwordAttribute) throws NamingException {
|
||||
Object retrievedPassword = passwordAttribute.get();
|
||||
|
||||
if (!(retrievedPassword instanceof String)) {
|
||||
// Assume it's binary
|
||||
retrievedPassword = new String((byte[]) retrievedPassword);
|
||||
}
|
||||
|
||||
return (String) retrievedPassword;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a GrantedAuthority from a role attribute. Override to customize
|
||||
* authority object creation.
|
||||
|
||||
@@ -18,8 +18,6 @@ package org.acegisecurity.userdetails.memory;
|
||||
import org.acegisecurity.GrantedAuthority;
|
||||
import org.acegisecurity.GrantedAuthorityImpl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
@@ -55,32 +53,6 @@ public class UserAttribute {
|
||||
return (GrantedAuthority[]) this.authorities.toArray(toReturn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set all authorities for this user.
|
||||
*
|
||||
* @param authorities {@link List} <{@link GrantedAuthority}>
|
||||
* @since 1.1
|
||||
*/
|
||||
public void setAuthorities(List authorities) {
|
||||
this.authorities = authorities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set all authorities for this user from String values.
|
||||
* It will create the necessary {@link GrantedAuthority} objects.
|
||||
*
|
||||
* @param authoritiesAsString {@link List} <{@link String}>
|
||||
* @since 1.1
|
||||
*/
|
||||
public void setAuthoritiesAsString(List authoritiesAsString) {
|
||||
setAuthorities(new ArrayList(authoritiesAsString.size()));
|
||||
Iterator it = authoritiesAsString.iterator();
|
||||
while (it.hasNext()) {
|
||||
GrantedAuthority grantedAuthority = new GrantedAuthorityImpl((String) it.next());
|
||||
addAuthority(grantedAuthority);
|
||||
}
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
@@ -15,12 +15,13 @@
|
||||
|
||||
package org.acegisecurity.userdetails.memory;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.acegisecurity.GrantedAuthorityImpl;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
|
||||
|
||||
/**
|
||||
* Property editor that creates a {@link UserAttribute} from a comma separated list of values.
|
||||
*
|
||||
@@ -34,8 +35,6 @@ public class UserAttributeEditor extends PropertyEditorSupport {
|
||||
if (StringUtils.hasText(s)) {
|
||||
String[] tokens = StringUtils.commaDelimitedListToStringArray(s);
|
||||
UserAttribute userAttrib = new UserAttribute();
|
||||
|
||||
List authoritiesAsString = new ArrayList();
|
||||
|
||||
for (int i = 0; i < tokens.length; i++) {
|
||||
String currentToken = tokens[i].trim();
|
||||
@@ -48,11 +47,10 @@ public class UserAttributeEditor extends PropertyEditorSupport {
|
||||
} else if (currentToken.toLowerCase().equals("disabled")) {
|
||||
userAttrib.setEnabled(false);
|
||||
} else {
|
||||
authoritiesAsString.add(currentToken);
|
||||
userAttrib.addAuthority(new GrantedAuthorityImpl(currentToken));
|
||||
}
|
||||
}
|
||||
}
|
||||
userAttrib.setAuthoritiesAsString(authoritiesAsString);
|
||||
|
||||
if (userAttrib.isValid()) {
|
||||
setValue(userAttrib);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user