Compare commits
139 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 459b1d1cde | |||
| bcd1c3eeef | |||
| 23e2338800 | |||
| d150b1aad2 | |||
| 21dd050d7b | |||
| ab7816db41 | |||
| d2fb473a4e | |||
| 49a2de8f0f | |||
| cc03675776 | |||
| db96650d99 | |||
| ef6d6cd03e | |||
| 2fdf96e7cf | |||
| 558fd5d75d | |||
| 0c7a342fdf | |||
| c5aa605068 | |||
| 55b7b2129d | |||
| b0056568f0 | |||
| 7313d5def0 | |||
| 324789d544 | |||
| 9e3ce85dd5 | |||
| f0b259a32e | |||
| 58d3f0c56f | |||
| 5364db2c27 | |||
| 53beadb7bf | |||
| 03df6a90eb | |||
| e0108f3982 | |||
| d4b4cd68d2 | |||
| 1292420476 | |||
| cf91104b69 | |||
| 6779d97546 | |||
| 757062e8f9 | |||
| 5e56d6f6ea | |||
| 30f6871124 | |||
| e8de53b87c | |||
| 6c0ddbfa9d | |||
| 881d50e2a6 | |||
| 87c1117b47 | |||
| 1554ae4cc6 | |||
| 3226a90fcd | |||
| 73cea493c6 | |||
| d88adf3f9e | |||
| 3c223fd193 | |||
| 4d070eab25 | |||
| 000f9ab7ac | |||
| 9769394c92 | |||
| a33ce2e7f0 | |||
| e5fd83624d | |||
| 265b719a39 | |||
| 557cf75745 | |||
| 4e65b24253 | |||
| 1149da6137 | |||
| 5b414ddef5 | |||
| e2a83b6822 | |||
| 308212febc | |||
| 760a858be6 | |||
| 139d8c2f65 | |||
| 1b66467f70 | |||
| 54fb402e60 | |||
| 57a8d2adb3 | |||
| dc13f25dee | |||
| 8dd1177c02 | |||
| 92dcf694b4 | |||
| b5cbc977e1 | |||
| 3889894d16 | |||
| 67fcf426eb | |||
| e96fee6ec1 | |||
| 27d2db9e22 | |||
| 38ec0f0d30 | |||
| 69ec903088 | |||
| 0298851ca3 | |||
| 3487da0e85 | |||
| 773a0d6969 | |||
| 3498b36c14 | |||
| 5de0939b03 | |||
| 8d3a2b42d9 | |||
| 52a167acfa | |||
| 1f89d153b2 | |||
| f7cb31a301 | |||
| 9a337d2fea | |||
| 85a67c6b7c | |||
| 4930657e57 | |||
| 442c51bb30 | |||
| d485e30fd5 | |||
| ca863ce4f7 | |||
| 91799c9290 | |||
| 156af5b8b6 | |||
| e5c2ef2d98 | |||
| 5d15856ccc | |||
| 288fdb3df8 | |||
| 94a9acedad | |||
| 488abe58fb | |||
| 80c1ae3bde | |||
| 00b73e8331 | |||
| 46af400466 | |||
| 9e87bd6789 | |||
| aa52124d72 | |||
| 9560636380 | |||
| 9d539a13d9 | |||
| 0edb75d4aa | |||
| 41f7bb3755 | |||
| 27de814d54 | |||
| d847772c81 | |||
| ae55e04522 | |||
| 55f7960e5c | |||
| 2c1ba76027 | |||
| 18c6838bec | |||
| c7bcbe1b35 | |||
| f2ff448071 | |||
| 4a48cd4425 | |||
| d332b5ce18 | |||
| e9b961d0f8 | |||
| 9255004495 | |||
| 4e612922ac | |||
| a2c3635d78 | |||
| 552c275e8f | |||
| aaf51c4bee | |||
| 49da801096 | |||
| eb3e954ae4 | |||
| b0caa72e80 | |||
| 7475906218 | |||
| 18680e8fab | |||
| cada23f57d | |||
| fa3c61b19b | |||
| 88825089a7 | |||
| 2a7caff95f | |||
| 9fd0bbd694 | |||
| 1a9629b197 | |||
| f7020755be | |||
| da780e4567 | |||
| 9f41b9f470 | |||
| 5d7a75a421 | |||
| d2ee383e06 | |||
| ee50d6e334 | |||
| 02e7bbb982 | |||
| 7957d54d67 | |||
| 00620b6992 | |||
| 35093e09f6 | |||
| 0eab6903e8 | |||
| b6282423e3 |
+4
-5
@@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="samples/attributes/src/main/java"/>
|
||||
<classpathentry kind="src" path="sandbox/other/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"/>
|
||||
@@ -17,8 +18,6 @@
|
||||
<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"/>
|
||||
@@ -33,8 +32,8 @@
|
||||
<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 sourcepath="/MAVEN_REPO/springframework/src/spring-2.0-m2.zip" kind="var" path="MAVEN_REPO/springframework/jars/spring-2.0-m2.jar"/>
|
||||
<classpathentry sourcepath="/MAVEN_REPO/springframework/src/spring-2.0-m2.zip" kind="var" path="MAVEN_REPO/springframework/jars/spring-mock-2.0-m2.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"/>
|
||||
@@ -76,7 +75,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 sourcepath="/MAVEN_REPO/springframework/src/spring-2.0-m2.zip" kind="var" path="MAVEN_REPO/springframework/jars/spring-hibernate3-2.0-m2.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"/>
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<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-adapters</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<version>1.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>acegi-security-cas</artifactId>
|
||||
<name>Acegi Security System for Spring - CAS adapter</name>
|
||||
@@ -22,4 +19,4 @@
|
||||
<version>2.0.12</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
</project>
|
||||
@@ -1,12 +1,9 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<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-adapters</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<version>1.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>acegi-security-catalina</artifactId>
|
||||
<name>Acegi Security System for Spring - Catalina adapter</name>
|
||||
@@ -17,4 +14,4 @@
|
||||
<version>4.1.9</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
</project>
|
||||
@@ -1,12 +1,9 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<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-adapters</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<version>1.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>acegi-security-jboss</artifactId>
|
||||
<name>Acegi Security System for Spring - JBoss adapter</name>
|
||||
@@ -23,4 +20,4 @@
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
</project>
|
||||
@@ -1,12 +1,9 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<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-adapters</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<version>1.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>acegi-security-jetty</artifactId>
|
||||
<name>Acegi Security System for Spring - Jetty adapter</name>
|
||||
@@ -17,4 +14,4 @@
|
||||
<version>4.2.22</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
</project>
|
||||
@@ -31,6 +31,7 @@ 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;
|
||||
|
||||
|
||||
+3
-6
@@ -1,12 +1,9 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<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.0.0</version>
|
||||
<version>1.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>acegi-security-adapters</artifactId>
|
||||
<name>Acegi Security System for Spring - Adapters</name>
|
||||
@@ -30,4 +27,4 @@
|
||||
<module>jetty</module>
|
||||
<module>resin</module>
|
||||
</modules>
|
||||
</project>
|
||||
</project>
|
||||
@@ -13,7 +13,7 @@
|
||||
<dependency>
|
||||
<groupId>org.acegisecurity</groupId>
|
||||
<artifactId>acegi-security</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<version>1.0.2</version>
|
||||
<type>jar</type>
|
||||
<url>http://acegisecurity.org</url>
|
||||
<properties>
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<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-adapters</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<version>1.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>acegi-security-resin</artifactId>
|
||||
<name>Acegi Security System for Spring - Resin adapter</name>
|
||||
@@ -23,4 +20,4 @@
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
</project>
|
||||
+23
-7
@@ -1,15 +1,19 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<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.0.0</version>
|
||||
<version>1.1-SNAPSHOT</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>
|
||||
@@ -19,9 +23,10 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>1.2.6</version>
|
||||
<version>1.2.7</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
@@ -34,4 +39,15 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
<reporting>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-pmd-plugin</artifactId>
|
||||
<configuration>
|
||||
<targetJdk>1.5</targetJdk>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</reporting>
|
||||
</project>
|
||||
@@ -14,7 +14,7 @@
|
||||
<dependency>
|
||||
<groupId>org.acegisecurity</groupId>
|
||||
<artifactId>acegi-security</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<version>1.0.2</version>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
+45
-22
@@ -1,30 +1,36 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
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.0.0</version>
|
||||
<version>1.1-SNAPSHOT</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>2.0-m2</version>
|
||||
<version>1.2.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
<version>2.0-m2</version>
|
||||
<version>1.2.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-support</artifactId>
|
||||
<version>2.0-m2</version>
|
||||
<version>1.2.7</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -54,11 +60,6 @@
|
||||
<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>
|
||||
@@ -101,19 +102,13 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.server</groupId>
|
||||
<artifactId>apacheds-core</artifactId>
|
||||
<version>1.0-RC1</version>
|
||||
<version>1.0-RC3</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-rc5</version>
|
||||
<version>1.0.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -126,7 +121,35 @@
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
<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>
|
||||
@@ -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,6 +15,8 @@
|
||||
|
||||
package org.acegisecurity;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Represents an authority granted to an {@link Authentication} object.
|
||||
*
|
||||
@@ -27,7 +29,7 @@ package org.acegisecurity;
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public interface GrantedAuthority {
|
||||
public interface GrantedAuthority extends Serializable {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,6 +28,7 @@ import java.io.Serializable;
|
||||
public class GrantedAuthorityImpl implements GrantedAuthority, Serializable {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private String role;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
@@ -35,10 +35,6 @@ 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,7 +18,6 @@ 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.
|
||||
*
|
||||
@@ -45,14 +44,18 @@ 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[] validPermissions = {
|
||||
private static final int[] VALID_PERMISSIONS = {
|
||||
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>.
|
||||
*
|
||||
@@ -71,8 +74,11 @@ 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 validPermissions;
|
||||
return (int[]) VALID_PERMISSIONS.clone();
|
||||
}
|
||||
|
||||
public String printPermissionsBlock(int i) {
|
||||
@@ -110,4 +116,35 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ 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;
|
||||
|
||||
+11
-1
@@ -211,6 +211,16 @@ 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;
|
||||
@@ -332,7 +342,7 @@ class CollectionFilterer implements Filterer {
|
||||
* @see org.acegisecurity.afterinvocation.Filterer#remove(java.lang.Object)
|
||||
*/
|
||||
public void remove(Object object) {
|
||||
collectionIter.remove();
|
||||
removeList.add(object);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-1
@@ -39,7 +39,6 @@ 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>
|
||||
@@ -187,6 +186,16 @@ 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;
|
||||
|
||||
+4
-8
@@ -71,16 +71,12 @@ import javax.servlet.http.HttpSession;
|
||||
public class HttpSessionContextIntegrationFilter implements InitializingBean, Filter {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
// ~ Static fields/initializers
|
||||
// =============================================
|
||||
protected static final Log logger = LogFactory.getLog(HttpSessionContextIntegrationFilter.class);
|
||||
private static final String FILTER_APPLIED = "__acegi_session_integration_filter_applied";
|
||||
public static final String ACEGI_SECURITY_CONTEXT_KEY = "ACEGI_SECURITY_CONTEXT";
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
// ~ Instance fields
|
||||
// ========================================================
|
||||
private Class context = SecurityContextImpl.class;
|
||||
private Object contextObject;
|
||||
|
||||
@@ -104,6 +100,10 @@ public class HttpSessionContextIntegrationFilter implements InitializingBean, Fi
|
||||
*/
|
||||
private boolean forceEagerSessionCreation = false;
|
||||
|
||||
public HttpSessionContextIntegrationFilter() throws ServletException {
|
||||
this.contextObject = generateNewContext();
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
@@ -117,8 +117,6 @@ public class HttpSessionContextIntegrationFilter implements InitializingBean, Fi
|
||||
throw new IllegalArgumentException(
|
||||
"If using forceEagerSessionCreation, you must set allowSessionCreation to also be true");
|
||||
}
|
||||
|
||||
this.contextObject = generateNewContext();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -287,8 +285,6 @@ public class HttpSessionContextIntegrationFilter implements InitializingBean, Fi
|
||||
return allowSessionCreation;
|
||||
}
|
||||
|
||||
// ~ Methods
|
||||
// ================================================================
|
||||
public boolean isForceEagerSessionCreation() {
|
||||
return forceEagerSessionCreation;
|
||||
}
|
||||
|
||||
@@ -30,11 +30,11 @@ import java.lang.reflect.Constructor;
|
||||
* three valid <code>MODE_</code> settings defined as <code>static final</code> fields, or a fully qualified classname
|
||||
* to a concrete implementation of {@link org.acegisecurity.context.SecurityContextHolderStrategy} that provides a
|
||||
* public no-argument constructor.</p>
|
||||
* <p>There are two ways to specify the desired mode <code>String</code>. The first is to specify it via the
|
||||
* system property keyed on {@link #SYSTEM_PROPERTY}. The second is to call {@link #setStrategyName(String)} before
|
||||
* using the class. If neither approach is used, the class will default to using {@link #MODE_THREADLOCAL}, which is
|
||||
* backwards compatible, has fewer JVM incompatibilities and is appropriate on servers (whereas {@link #MODE_GLOBAL}
|
||||
* is not).</p>
|
||||
* <p>There are two ways to specify the desired strategy mode <code>String</code>. The first is to specify it via
|
||||
* the system property keyed on {@link #SYSTEM_PROPERTY}. The second is to call {@link #setStrategyName(String)}
|
||||
* before using the class. If neither approach is used, the class will default to using {@link #MODE_THREADLOCAL},
|
||||
* which is backwards compatible, has fewer JVM incompatibilities and is appropriate on servers (whereas {@link
|
||||
* #MODE_GLOBAL} is definitely inappropriate for server use).</p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
@@ -49,8 +49,12 @@ public class SecurityContextHolder {
|
||||
public static final String MODE_GLOBAL = "MODE_GLOBAL";
|
||||
public static final String SYSTEM_PROPERTY = "acegi.security.strategy";
|
||||
private static String strategyName = System.getProperty(SYSTEM_PROPERTY);
|
||||
private static Constructor customStrategy;
|
||||
private static SecurityContextHolderStrategy strategy;
|
||||
private static int initializeCount = 0;
|
||||
|
||||
static {
|
||||
initialize();
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
@@ -58,7 +62,6 @@ public class SecurityContextHolder {
|
||||
* Explicitly clears the context value from the current thread.
|
||||
*/
|
||||
public static void clearContext() {
|
||||
initialize();
|
||||
strategy.clearContext();
|
||||
}
|
||||
|
||||
@@ -68,11 +71,20 @@ public class SecurityContextHolder {
|
||||
* @return the security context (never <code>null</code>)
|
||||
*/
|
||||
public static SecurityContext getContext() {
|
||||
initialize();
|
||||
|
||||
return strategy.getContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Primarily for troubleshooting purposes, this method shows how many times the class has reinitialized its
|
||||
* <code>SecurityContextHolderStrategy</code>.
|
||||
*
|
||||
* @return the count (should be one unless you've called {@link #setStrategyName(String)} to switch to an alternate
|
||||
* strategy.
|
||||
*/
|
||||
public static int getInitializeCount() {
|
||||
return initializeCount;
|
||||
}
|
||||
|
||||
private static void initialize() {
|
||||
if ((strategyName == null) || "".equals(strategyName)) {
|
||||
// Set default
|
||||
@@ -88,16 +100,15 @@ public class SecurityContextHolder {
|
||||
} else {
|
||||
// Try to load a custom strategy
|
||||
try {
|
||||
if (customStrategy == null) {
|
||||
Class clazz = Class.forName(strategyName);
|
||||
customStrategy = clazz.getConstructor(new Class[] {});
|
||||
}
|
||||
|
||||
Class clazz = Class.forName(strategyName);
|
||||
Constructor customStrategy = clazz.getConstructor(new Class[] {});
|
||||
strategy = (SecurityContextHolderStrategy) customStrategy.newInstance(new Object[] {});
|
||||
} catch (Exception ex) {
|
||||
ReflectionUtils.handleReflectionException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
initializeCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,7 +117,6 @@ public class SecurityContextHolder {
|
||||
* @param context the new <code>SecurityContext</code> (may not be <code>null</code>)
|
||||
*/
|
||||
public static void setContext(SecurityContext context) {
|
||||
initialize();
|
||||
strategy.setContext(context);
|
||||
}
|
||||
|
||||
@@ -122,6 +132,6 @@ public class SecurityContextHolder {
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "SecurityContextHolder[strategy='" + strategyName + "']";
|
||||
return "SecurityContextHolder[strategy='" + strategyName + "'; initializeCount=" + initializeCount + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ public class SecurityContextImpl implements SecurityContext {
|
||||
if (this.authentication == null) {
|
||||
sb.append(": Null authentication");
|
||||
} else {
|
||||
sb.append(": Authentication: " + this.authentication);
|
||||
sb.append(": Authentication: ").append(this.authentication);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
|
||||
@@ -41,6 +41,7 @@ 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;
|
||||
@@ -276,7 +277,7 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, A
|
||||
} catch (AccessDeniedException accessDeniedException) {
|
||||
AuthorizationFailureEvent event = new AuthorizationFailureEvent(object, attr, authenticated,
|
||||
accessDeniedException);
|
||||
this.eventPublisher.publishEvent(event);
|
||||
publishEvent(event);
|
||||
|
||||
throw accessDeniedException;
|
||||
}
|
||||
@@ -286,7 +287,7 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, A
|
||||
}
|
||||
|
||||
AuthorizedEvent event = new AuthorizedEvent(object, attr, authenticated);
|
||||
this.eventPublisher.publishEvent(event);
|
||||
publishEvent(event);
|
||||
|
||||
// Attempt to run as a different user
|
||||
Authentication runAs = this.runAsManager.buildRunAs(authenticated, object, attr);
|
||||
@@ -311,7 +312,7 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, A
|
||||
logger.debug("Public object - authentication not attempted");
|
||||
}
|
||||
|
||||
this.eventPublisher.publishEvent(new PublicInvocationEvent(object));
|
||||
publishEvent(new PublicInvocationEvent(object));
|
||||
|
||||
return null; // no further work post-invocation
|
||||
}
|
||||
@@ -330,7 +331,7 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, A
|
||||
|
||||
AuthenticationCredentialsNotFoundEvent event = new AuthenticationCredentialsNotFoundEvent(secureObject,
|
||||
configAttribs, exception);
|
||||
this.eventPublisher.publishEvent(event);
|
||||
publishEvent(event);
|
||||
|
||||
throw exception;
|
||||
}
|
||||
@@ -431,4 +432,10 @@ 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,6 +17,7 @@ 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;
|
||||
@@ -232,4 +233,25 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-9
@@ -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,20 +56,24 @@ public class MethodDefinitionSourceEditor extends PropertyEditorSupport {
|
||||
Properties props = (Properties) propertiesEditor.getValue();
|
||||
|
||||
// Now we have properties, process each one individually
|
||||
ConfigAttributeEditor configAttribEd = new ConfigAttributeEditor();
|
||||
List mappings = new ArrayList();
|
||||
|
||||
for (Iterator iter = props.keySet().iterator(); iter.hasNext();) {
|
||||
String name = (String) iter.next();
|
||||
String value = props.getProperty(name);
|
||||
|
||||
// Convert value to series of security configuration attributes
|
||||
configAttribEd.setAsText(value);
|
||||
MethodDefinitionSourceMapping mapping = new MethodDefinitionSourceMapping();
|
||||
mapping.setMethodName(name);
|
||||
|
||||
ConfigAttributeDefinition attr = (ConfigAttributeDefinition) configAttribEd.getValue();
|
||||
String[] tokens = StringUtils.commaDelimitedListToStringArray(value);
|
||||
|
||||
// Register name and attribute
|
||||
source.addSecureMethod(name, attr);
|
||||
for (int i = 0; i < tokens.length; i++) {
|
||||
mapping.addConfigAttribute(tokens[i].trim());
|
||||
}
|
||||
|
||||
mappings.add(mapping);
|
||||
}
|
||||
source.setMappings(mappings);
|
||||
}
|
||||
|
||||
setValue(source);
|
||||
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
/* 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);
|
||||
}
|
||||
|
||||
}
|
||||
+8
-18
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
/* 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.
|
||||
@@ -13,25 +13,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.acegisecurity.providers.smb;
|
||||
|
||||
import org.acegisecurity.AuthenticationException;
|
||||
|
||||
package org.acegisecurity.intercept.web;
|
||||
|
||||
/**
|
||||
* Thrown if
|
||||
*
|
||||
* @author Davide Baroncelli
|
||||
* Interface to join {@link FilterInvocationDefinitionMap} and
|
||||
* {@link FilterInvocationDefinitionSource}.
|
||||
*
|
||||
* @author <a href="mailto:carlos@apache.org">Carlos Sanchez</a>
|
||||
* @version $Id$
|
||||
* @since 1.1
|
||||
*/
|
||||
public class ChallengeExpiredException extends AuthenticationException {
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public ChallengeExpiredException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public ChallengeExpiredException(String msg, Throwable t) {
|
||||
super(msg, t);
|
||||
}
|
||||
public interface FilterInvocationDefinition extends FilterInvocationDefinitionMap, FilterInvocationDefinitionSource {
|
||||
}
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
+19
-13
@@ -15,9 +15,6 @@
|
||||
|
||||
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;
|
||||
@@ -27,6 +24,8 @@ import java.beans.PropertyEditorSupport;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
@@ -50,14 +49,15 @@ public class FilterInvocationDefinitionSourceEditor extends PropertyEditorSuppor
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void setAsText(String s) throws IllegalArgumentException {
|
||||
FilterInvocationDefinitionMap source = new RegExpBasedFilterInvocationDefinitionMap();
|
||||
FilterInvocationDefinitionDecorator source = new FilterInvocationDefinitionDecorator();
|
||||
source.setDecorated(new RegExpBasedFilterInvocationDefinitionMap());
|
||||
|
||||
if ((s == null) || "".equals(s)) {
|
||||
// Leave target object empty
|
||||
} else {
|
||||
// Check if we need to override the default definition map
|
||||
if (s.lastIndexOf(DIRECTIVE_PATTERN_TYPE_APACHE_ANT) != -1) {
|
||||
source = new PathBasedFilterInvocationDefinitionMap();
|
||||
source.setDecorated(new PathBasedFilterInvocationDefinitionMap());
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(("Detected " + DIRECTIVE_PATTERN_TYPE_APACHE_ANT
|
||||
@@ -77,6 +77,8 @@ public class FilterInvocationDefinitionSourceEditor extends PropertyEditorSuppor
|
||||
BufferedReader br = new BufferedReader(new StringReader(s));
|
||||
int counter = 0;
|
||||
String line;
|
||||
|
||||
List mappings = new ArrayList();
|
||||
|
||||
while (true) {
|
||||
counter++;
|
||||
@@ -138,7 +140,7 @@ public class FilterInvocationDefinitionSourceEditor extends PropertyEditorSuppor
|
||||
|
||||
// Attempt to detect malformed lines (as per SEC-204)
|
||||
if (source.isConvertUrlToLowercaseBeforeComparison()
|
||||
&& source instanceof PathBasedFilterInvocationDefinitionMap) {
|
||||
&& source.getDecorated() 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++) {
|
||||
@@ -153,17 +155,21 @@ public class FilterInvocationDefinitionSourceEditor extends PropertyEditorSuppor
|
||||
}
|
||||
}
|
||||
|
||||
// Convert value to series of security configuration attributes
|
||||
ConfigAttributeEditor configAttribEd = new ConfigAttributeEditor();
|
||||
configAttribEd.setAsText(value);
|
||||
FilterInvocationDefinitionSourceMapping mapping = new FilterInvocationDefinitionSourceMapping();
|
||||
mapping.setUrl(name);
|
||||
|
||||
ConfigAttributeDefinition attr = (ConfigAttributeDefinition) configAttribEd.getValue();
|
||||
String[] tokens = org.springframework.util.StringUtils
|
||||
.commaDelimitedListToStringArray(value);
|
||||
|
||||
// Register the regular expression and its attribute
|
||||
source.addSecureUrl(name, attr);
|
||||
for (int i = 0; i < tokens.length; i++) {
|
||||
mapping.addConfigAttribute(tokens[i].trim());
|
||||
}
|
||||
|
||||
mappings.add(mapping);
|
||||
}
|
||||
source.setMappings(mappings);
|
||||
}
|
||||
|
||||
setValue(source);
|
||||
setValue(source.getDecorated());
|
||||
}
|
||||
}
|
||||
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
/* 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 FilterInvocationDefinitionMap {
|
||||
implements FilterInvocationDefinition {
|
||||
//~ 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.
|
||||
int firstQuestionMarkIndex = url.lastIndexOf("?");
|
||||
// Strip anything after a question mark symbol, as per SEC-161. See also SEC-321
|
||||
int firstQuestionMarkIndex = url.indexOf("?");
|
||||
|
||||
if (firstQuestionMarkIndex != -1) {
|
||||
url = url.substring(0, firstQuestionMarkIndex);
|
||||
}
|
||||
|
||||
if (convertUrlToLowercaseBeforeComparison) {
|
||||
if (isConvertUrlToLowercaseBeforeComparison()) {
|
||||
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 FilterInvocationDefinitionMap {
|
||||
implements FilterInvocationDefinition {
|
||||
//~ 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 (convertUrlToLowercaseBeforeComparison) {
|
||||
if (isConvertUrlToLowercaseBeforeComparison()) {
|
||||
url = url.toLowerCase();
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
|
||||
@@ -34,6 +34,8 @@ 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;
|
||||
|
||||
@@ -104,13 +106,32 @@ 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.providerUrl = 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;
|
||||
|
||||
StringTokenizer st = new StringTokenizer(providerUrl);
|
||||
|
||||
// Work out rootDn from the first URL and check that the other URLs (if any) match
|
||||
@@ -131,7 +152,14 @@ public class DefaultInitialDirContextFactory implements InitialDirContextFactory
|
||||
//Assert.isTrue(uri.getScheme().equals("ldap"), "Ldap URL must start with 'ldap://'");
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
/**
|
||||
* Get the LDAP url
|
||||
*
|
||||
* @return the url
|
||||
*/
|
||||
private String getProviderUrl() {
|
||||
return providerUrl;
|
||||
}
|
||||
|
||||
private InitialDirContext connect(Hashtable env) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
@@ -145,17 +173,22 @@ public class DefaultInitialDirContextFactory implements InitialDirContextFactory
|
||||
}
|
||||
|
||||
try {
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
|
||||
throw new LdapDataAccessException(messages.getMessage(
|
||||
"DefaultIntitalDirContextFactory.unexpectedException",
|
||||
"Failed to obtain InitialDirContext due to unexpected exception"), nx);
|
||||
"Failed to obtain InitialDirContext due to unexpected exception"), ne);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,7 +202,7 @@ public class DefaultInitialDirContextFactory implements InitialDirContextFactory
|
||||
|
||||
env.put(Context.SECURITY_AUTHENTICATION, authenticationType);
|
||||
env.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactory);
|
||||
env.put(Context.PROVIDER_URL, providerUrl);
|
||||
env.put(Context.PROVIDER_URL, getProviderUrl());
|
||||
|
||||
if (useConnectionPool) {
|
||||
env.put(CONNECTION_POOL_KEY, "true");
|
||||
@@ -280,4 +313,8 @@ public class DefaultInitialDirContextFactory implements InitialDirContextFactory
|
||||
public void setUseConnectionPool(boolean useConnectionPool) {
|
||||
this.useConnectionPool = useConnectionPool;
|
||||
}
|
||||
|
||||
public void setUseLdapContext(boolean useLdapContext) {
|
||||
this.useLdapContext = useLdapContext;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
package org.acegisecurity.ldap;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
@@ -28,6 +27,7 @@ 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,17 +133,21 @@ public class LdapTemplate {
|
||||
|
||||
public boolean nameExists(final String dn) {
|
||||
Boolean exists = (Boolean) execute(new LdapCallback() {
|
||||
public Object doInDirContext(DirContext ctx)
|
||||
throws NamingException {
|
||||
try {
|
||||
ctx.lookup(LdapUtils.getRelativeName(dn, ctx));
|
||||
} catch (NameNotFoundException nnfe) {
|
||||
return Boolean.FALSE;
|
||||
public Object doInDirContext(DirContext ctx)
|
||||
throws NamingException {
|
||||
try {
|
||||
Object obj = ctx.lookup(LdapUtils.getRelativeName(dn, ctx));
|
||||
if (obj instanceof Context) {
|
||||
LdapUtils.closeContext((Context) obj);
|
||||
}
|
||||
|
||||
return Boolean.TRUE;
|
||||
} catch (NameNotFoundException nnfe) {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
});
|
||||
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
});
|
||||
|
||||
return exists.booleanValue();
|
||||
}
|
||||
@@ -234,8 +238,7 @@ public class LdapTemplate {
|
||||
*
|
||||
* @return the object created by the mapper from the matching entry
|
||||
*
|
||||
* @throws EmptyResultDataAccessException if no results are found.
|
||||
* @throws IncorrectResultSizeDataAccessException if the search returns more than one result.
|
||||
* @throws IncorrectResultSizeDataAccessException if no results are found or the search returns more than one result.
|
||||
*/
|
||||
public Object searchForSingleEntry(final String base, final String filter, final Object[] params,
|
||||
final LdapEntryMapper mapper) {
|
||||
@@ -245,13 +248,14 @@ public class LdapTemplate {
|
||||
NamingEnumeration results = ctx.search(base, filter, params, searchControls);
|
||||
|
||||
if (!results.hasMore()) {
|
||||
throw new EmptyResultDataAccessException(1);
|
||||
throw new IncorrectResultSizeDataAccessException(1, 0);
|
||||
}
|
||||
|
||||
SearchResult searchResult = (SearchResult) results.next();
|
||||
|
||||
if (results.hasMore()) {
|
||||
throw new IncorrectResultSizeDataAccessException(1);
|
||||
// We don't know how many results but set to 2 which is good enough
|
||||
throw new IncorrectResultSizeDataAccessException(1, 2);
|
||||
}
|
||||
|
||||
// Work out the DN of the matched entry
|
||||
|
||||
@@ -27,7 +27,7 @@ import org.acegisecurity.userdetails.ldap.LdapUserDetailsMapper;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -123,8 +123,12 @@ public class FilterBasedLdapUserSearch implements LdapUserSearch {
|
||||
user.setUsername(username);
|
||||
|
||||
return user.createUserDetails();
|
||||
} catch (EmptyResultDataAccessException notFound) {
|
||||
throw new UsernameNotFoundException("User " + username + " not found in directory.");
|
||||
} catch (IncorrectResultSizeDataAccessException notFound) {
|
||||
if(notFound.getActualSize() == 0) {
|
||||
throw new UsernameNotFoundException("User " + username + " not found in directory.");
|
||||
}
|
||||
// Search should never return multiple results if properly configured, so just rethrow
|
||||
throw notFound;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ 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;
|
||||
@@ -95,6 +96,7 @@ 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 ================================================================================================
|
||||
|
||||
@@ -102,36 +104,39 @@ public class ProviderManager extends AbstractAuthenticationManager implements In
|
||||
private ConcurrentSessionController sessionController = new NullConcurrentSessionController();
|
||||
private List providers;
|
||||
protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor();
|
||||
private Properties exceptionMappings;
|
||||
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);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
checkIfValidList(this.providers);
|
||||
Assert.notNull(this.messages, "A message source must be set");
|
||||
|
||||
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);
|
||||
}
|
||||
doAddExtraDefaultExceptionMappings(DEFAULT_EXCEPTION_MAPPINGS);
|
||||
}
|
||||
|
||||
private void checkIfValidList(List listToCheck) {
|
||||
@@ -189,7 +194,7 @@ public class ProviderManager extends AbstractAuthenticationManager implements In
|
||||
|
||||
if (result != null) {
|
||||
sessionController.registerSuccessfulAuthentication(result);
|
||||
applicationEventPublisher.publishEvent(new AuthenticationSuccessEvent(result));
|
||||
publishEvent(new AuthenticationSuccessEvent(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -222,7 +227,7 @@ public class ProviderManager extends AbstractAuthenticationManager implements In
|
||||
}
|
||||
|
||||
if (event != null) {
|
||||
applicationEventPublisher.publishEvent(event);
|
||||
publishEvent(event);
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("No event was found for the exception " + lastException.getClass().getName());
|
||||
@@ -273,6 +278,7 @@ public class ProviderManager extends AbstractAuthenticationManager implements In
|
||||
try {
|
||||
currentObject = iter.next();
|
||||
|
||||
//TODO bad idea, should use assignable from or instance of
|
||||
AuthenticationProvider attemptToCast = (AuthenticationProvider) currentObject;
|
||||
} catch (ClassCastException cce) {
|
||||
throw new IllegalArgumentException("AuthenticationProvider " + currentObject.getClass().getName()
|
||||
@@ -292,4 +298,10 @@ 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,6 +28,7 @@ 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,6 +30,7 @@ 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,6 +31,7 @@ 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,6 +35,7 @@ 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 authenticationDao) {
|
||||
this.userDetailsService = authenticationDao;
|
||||
public void setUserDetailsService(UserDetailsService userDetailsService) {
|
||||
this.userDetailsService = userDetailsService;
|
||||
}
|
||||
}
|
||||
|
||||
+9
-4
@@ -145,10 +145,15 @@ public abstract class AbstractUserDetailsAuthenticationProvider implements Authe
|
||||
try {
|
||||
additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication);
|
||||
} catch (AuthenticationException 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(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;
|
||||
}
|
||||
}
|
||||
|
||||
if (!user.isCredentialsNonExpired()) {
|
||||
|
||||
@@ -63,7 +63,7 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
|
||||
}
|
||||
|
||||
protected void doAfterPropertiesSet() throws Exception {
|
||||
Assert.notNull(this.userDetailsService, "An Authentication DAO must be set");
|
||||
Assert.notNull(this.userDetailsService, "A UserDetailsService must be set");
|
||||
}
|
||||
|
||||
public PasswordEncoder getPasswordEncoder() {
|
||||
@@ -90,7 +90,7 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
|
||||
|
||||
if (loadedUser == null) {
|
||||
throw new AuthenticationServiceException(
|
||||
"AuthenticationDao returned null, which is an interface contract violation");
|
||||
"UserDetailsService returned null, which is an interface contract violation");
|
||||
}
|
||||
|
||||
return loadedUser;
|
||||
@@ -117,7 +117,7 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
|
||||
this.saltSource = saltSource;
|
||||
}
|
||||
|
||||
public void setUserDetailsService(UserDetailsService authenticationDao) {
|
||||
this.userDetailsService = authenticationDao;
|
||||
public void setUserDetailsService(UserDetailsService userDetailsService) {
|
||||
this.userDetailsService = userDetailsService;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,42 +12,25 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.acegisecurity.providers.encoding;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
|
||||
|
||||
/**
|
||||
* <p>MD5 implementation of PasswordEncoder.</p>
|
||||
* <p>If a <code>null</code> password is presented, it will be treated as an empty <code>String</code> ("")
|
||||
* <p>If a <code>null</code> password is presented, it will be treated as an empty <code>String</code> ("")
|
||||
* password.</p>
|
||||
* <P>As MD5 is a one-way hash, the salt can contain any characters.</p>
|
||||
* <P>As MD5 is a one-way hash, the salt can contain any characters.</p>
|
||||
*
|
||||
* This is a convenience class that extends the
|
||||
* {@link MessageDigestPasswordEncoder} and passes MD5 as the algorithm to use.
|
||||
*
|
||||
* @author Ray Krueger
|
||||
* @author colin sampaleanu
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class Md5PasswordEncoder extends BaseDigestPasswordEncoder implements PasswordEncoder {
|
||||
//~ Methods ========================================================================================================
|
||||
public class Md5PasswordEncoder extends MessageDigestPasswordEncoder {
|
||||
|
||||
public String encodePassword(String rawPass, Object salt) {
|
||||
String saltedPass = mergePasswordAndSalt(rawPass, salt, false);
|
||||
|
||||
if (!getEncodeHashAsBase64()) {
|
||||
return DigestUtils.md5Hex(saltedPass);
|
||||
}
|
||||
|
||||
byte[] encoded = Base64.encodeBase64(DigestUtils.md5(saltedPass));
|
||||
|
||||
return new String(encoded);
|
||||
}
|
||||
|
||||
public boolean isPasswordValid(String encPass, String rawPass, Object salt) {
|
||||
String pass1 = "" + encPass;
|
||||
String pass2 = encodePassword(rawPass, salt);
|
||||
|
||||
return pass1.equals(pass2);
|
||||
public Md5PasswordEncoder() {
|
||||
super("MD5");
|
||||
}
|
||||
}
|
||||
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
package org.acegisecurity.providers.encoding;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
* <p>Base for digest password encoders.</p>
|
||||
* This class can be used stand-alone, or one of the subclasses can be used for compatiblity and convenience
|
||||
* <p>When using this class directly you must specify a
|
||||
* <a href="http://java.sun.com/j2se/1.4.2/docs/guide/security/CryptoSpec.html#AppA">
|
||||
* Message Digest Algorithm</a> to use as a constructor arg</p>
|
||||
*
|
||||
* The encoded password hash is normally returned as Hex (32 char) version of the hash bytes. Setting the encodeHashAsBase64
|
||||
* property to true will cause the encoded pass to be returned as Base64 text, which will consume 24 characters. See {@link BaseDigestPasswordEncoder#setEncodeHashAsBase64(boolean)}
|
||||
* <br/>
|
||||
* This PasswordEncoder can be used directly as in the following example:<br/>
|
||||
* <bean id="passwordEncoder" class="org.acegisecurity.providers.encoding.MessageDigestPasswordEncoder"><br/>
|
||||
* <constructor-arg value="MD5"/><br/>
|
||||
* </bean>
|
||||
*
|
||||
*
|
||||
* @author Ray Krueger
|
||||
* @since 1.0.1
|
||||
*/
|
||||
public class MessageDigestPasswordEncoder extends BaseDigestPasswordEncoder {
|
||||
|
||||
private final String algorithm;
|
||||
|
||||
/**
|
||||
* The digest algorithm to use
|
||||
* Supports the named <a href="http://java.sun.com/j2se/1.4.2/docs/guide/security/CryptoSpec.html#AppA">
|
||||
* Message Digest Algorithms</a> in the Java environment.
|
||||
*
|
||||
* @param algorithm
|
||||
*/
|
||||
public MessageDigestPasswordEncoder(String algorithm) {
|
||||
this(algorithm, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience constructor for specifying the algorithm and whether or not to enable base64 encoding
|
||||
*
|
||||
* @param algorithm
|
||||
* @param encodeHashAsBase64
|
||||
* @throws IllegalArgumentException if an unknown
|
||||
*/
|
||||
public MessageDigestPasswordEncoder(String algorithm, boolean encodeHashAsBase64) throws IllegalArgumentException {
|
||||
this.algorithm = algorithm;
|
||||
setEncodeHashAsBase64(encodeHashAsBase64);
|
||||
//Validity Check
|
||||
getMessageDigest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the rawPass using a MessageDigest.
|
||||
* If a salt is specified it will be merged with the password before encoding.
|
||||
*
|
||||
* @param rawPass The plain text password
|
||||
* @param salt The salt to sprinkle
|
||||
* @return Hex string of password digest (or base64 encoded string if encodeHashAsBase64 is enabled.
|
||||
*/
|
||||
public String encodePassword(String rawPass, Object salt) {
|
||||
String saltedPass = mergePasswordAndSalt(rawPass, salt, false);
|
||||
|
||||
MessageDigest messageDigest = getMessageDigest();
|
||||
|
||||
byte[] digest = messageDigest.digest(saltedPass.getBytes());
|
||||
|
||||
if (getEncodeHashAsBase64()) {
|
||||
return new String(Base64.encodeBase64(digest));
|
||||
} else {
|
||||
return new String(Hex.encodeHex(digest));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a MessageDigest instance for the given algorithm.
|
||||
* Throws an IllegalArgumentException if <i>algorithm</i> is unknown
|
||||
*
|
||||
* @return MessageDigest instance
|
||||
* @throws IllegalArgumentException if NoSuchAlgorithmException is thrown
|
||||
*/
|
||||
protected final MessageDigest getMessageDigest() throws IllegalArgumentException {
|
||||
try {
|
||||
return MessageDigest.getInstance(algorithm);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new IllegalArgumentException("No such algorithm [" +
|
||||
algorithm + "]");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a previously encoded password and compares it with a rawpassword after mixing in the salt and
|
||||
* encoding that value
|
||||
*
|
||||
* @param encPass previously encoded password
|
||||
* @param rawPass plain text password
|
||||
* @param salt salt to mix into password
|
||||
* @return true or false
|
||||
*/
|
||||
public boolean isPasswordValid(String encPass, String rawPass, Object salt) {
|
||||
String pass1 = "" + encPass;
|
||||
String pass2 = encodePassword(rawPass, salt);
|
||||
|
||||
return pass1.equals(pass2);
|
||||
}
|
||||
|
||||
public String getAlgorithm() {
|
||||
return algorithm;
|
||||
}
|
||||
}
|
||||
@@ -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 DOCUMENT ME!
|
||||
* @return encoded password
|
||||
*
|
||||
* @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 DOCUMENT ME!
|
||||
* @return true if the password is valid , false otherwise
|
||||
*
|
||||
* @throws DataAccessException DOCUMENT ME!
|
||||
*/
|
||||
|
||||
@@ -12,42 +12,44 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.acegisecurity.providers.encoding;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
|
||||
|
||||
/**
|
||||
* <p>SHA implementation of PasswordEncoder.</p>
|
||||
* <p>If a <code>null</code> password is presented, it will be treated as an empty <code>String</code> ("")
|
||||
* <p>If a <code>null</code> password is presented, it will be treated as an empty <code>String</code> ("")
|
||||
* password.</p>
|
||||
* <P>As SHA is a one-way hash, the salt can contain any characters.</p>
|
||||
* <P>As SHA is a one-way hash, the salt can contain any characters.</p>
|
||||
*
|
||||
* The default strength for the SHA encoding is SHA-1. If you wish to use higher strengths use the argumented constructor.
|
||||
* {@link #ShaPasswordEncoder(int strength)}
|
||||
* <br/>
|
||||
* The applicationContext example... <br/>
|
||||
* <bean id="passwordEncoder" class="org.acegisecurity.providers.encoding.ShaPasswordEncoder"><br/>
|
||||
* <constructor-arg value="256"/><br/>
|
||||
* </bean>
|
||||
*
|
||||
*
|
||||
* @author Ray Krueger
|
||||
* @author colin sampaleanu
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ShaPasswordEncoder extends BaseDigestPasswordEncoder implements PasswordEncoder {
|
||||
//~ Methods ========================================================================================================
|
||||
public class ShaPasswordEncoder extends MessageDigestPasswordEncoder {
|
||||
|
||||
public String encodePassword(String rawPass, Object salt) {
|
||||
String saltedPass = mergePasswordAndSalt(rawPass, salt, false);
|
||||
|
||||
if (!getEncodeHashAsBase64()) {
|
||||
return DigestUtils.shaHex(saltedPass);
|
||||
}
|
||||
|
||||
byte[] encoded = Base64.encodeBase64(DigestUtils.sha(saltedPass));
|
||||
|
||||
return new String(encoded);
|
||||
/**
|
||||
* Initializes the ShaPasswordEncoder for SHA-1 strength
|
||||
*/
|
||||
public ShaPasswordEncoder() {
|
||||
this(1);
|
||||
}
|
||||
|
||||
public boolean isPasswordValid(String encPass, String rawPass, Object salt) {
|
||||
String pass1 = "" + encPass;
|
||||
String pass2 = encodePassword(rawPass, salt);
|
||||
|
||||
return pass1.equals(pass2);
|
||||
/**
|
||||
* Initialize the ShaPasswordEncoder with a given SHA stength as supported by the JVM
|
||||
* EX: <code>ShaPasswordEncoder encoder = new ShaPasswordEncoder(256);</code> initializes with SHA-256
|
||||
*
|
||||
* @param strength EX: 1, 256, 384, 512
|
||||
*/
|
||||
public ShaPasswordEncoder(int strength) {
|
||||
super("SHA-" + strength);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ 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,6 +32,7 @@ import java.security.Principal;
|
||||
public class JaasGrantedAuthority extends GrantedAuthorityImpl {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private Principal principal;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
+97
-38
@@ -18,6 +18,7 @@ package org.acegisecurity.providers.ldap;
|
||||
import org.acegisecurity.AuthenticationException;
|
||||
import org.acegisecurity.BadCredentialsException;
|
||||
import org.acegisecurity.GrantedAuthority;
|
||||
import org.acegisecurity.AuthenticationServiceException;
|
||||
|
||||
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
|
||||
import org.acegisecurity.providers.dao.AbstractUserDetailsAuthenticationProvider;
|
||||
@@ -31,48 +32,78 @@ import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
|
||||
|
||||
/**
|
||||
* An {@link org.acegisecurity.providers.AuthenticationProvider} implementation that provides integration with an
|
||||
* LDAP server.<p>There are many ways in which an LDAP directory can be configured so this class delegates most of
|
||||
* its responsibilites to two separate strategy interfaces, {@link LdapAuthenticator} and {@link
|
||||
* LdapAuthoritiesPopulator}.</p>
|
||||
* <h3>LdapAuthenticator</h3>This interface is responsible for performing the user authentication and retrieving
|
||||
* LDAP server.
|
||||
*
|
||||
* <p>There are many ways in which an LDAP directory can be configured so this class delegates most of
|
||||
* its responsibilites to two separate strategy interfaces, {@link LdapAuthenticator}
|
||||
* and {@link LdapAuthoritiesPopulator}.</p>
|
||||
*
|
||||
* <h3>LdapAuthenticator</h3>
|
||||
* This interface is responsible for performing the user authentication and retrieving
|
||||
* the user's information from the directory. Example implementations are {@link
|
||||
* org.acegisecurity.providers.ldap.authenticator.BindAuthenticator BindAuthenticator} which authenticates the user by
|
||||
* "binding" as that user, and {@link org.acegisecurity.providers.ldap.authenticator.PasswordComparisonAuthenticator
|
||||
* PasswordComparisonAuthenticator} which performs a comparison of the supplied password with the value stored in the
|
||||
* directory, either by retrieving the password or performing an LDAP "compare" operation.<p>The task of retrieving
|
||||
* the user attributes is delegated to the authenticator because the permissions on the attributes may depend on the
|
||||
* type of authentication being used; for example, if binding as the user, it may be necessary to read them with the
|
||||
* user's own permissions (using the same context used for the bind operation).</p>
|
||||
* <h3>LdapAuthoritiesPopulator</h3>Once the user has been authenticated, this interface is called to obtain the
|
||||
* set of granted authorities for the user. The {@link
|
||||
* org.acegisecurity.providers.ldap.populator.DefaultLdapAuthoritiesPopulator DefaultLdapAuthoritiesPopulator} can be
|
||||
* configured to obtain user role information from the user's attributes and/or to perform a search for "groups" that
|
||||
* the user is a member of and map these to roles.<p>A custom implementation could obtain the roles from a
|
||||
* completely different source, for example from a database.</p>
|
||||
* <h3>Configuration</h3>A simple configuration might be as follows:<pre>
|
||||
* directory, either by retrieving the password or performing an LDAP "compare" operation.
|
||||
* <p>The task of retrieving the user attributes is delegated to the authenticator because the permissions on the
|
||||
* attributes may depend on the type of authentication being used; for example, if binding as the user, it may be
|
||||
* necessary to read them with the user's own permissions (using the same context used for the bind operation).</p>
|
||||
*
|
||||
* <h3>LdapAuthoritiesPopulator</h3>
|
||||
* Once the user has been authenticated, this interface is called to obtain the set of granted authorities for the
|
||||
* user.
|
||||
* The
|
||||
* {@link org.acegisecurity.providers.ldap.populator.DefaultLdapAuthoritiesPopulator DefaultLdapAuthoritiesPopulator}
|
||||
* can be configured to obtain user role information from the user's attributes and/or to perform a search for
|
||||
* "groups" that the user is a member of and map these to roles.
|
||||
*
|
||||
* <p>A custom implementation could obtain the roles from a completely different source, for example from a database.
|
||||
* </p>
|
||||
*
|
||||
* <h3>Configuration</h3>A simple configuration might be as follows:
|
||||
* <pre>
|
||||
* <bean id="initialDirContextFactory" class="org.acegisecurity.providers.ldap.DefaultInitialDirContextFactory">
|
||||
* <constructor-arg value="ldap://monkeymachine:389/dc=acegisecurity,dc=org"/>
|
||||
* <property name="managerDn"><value>cn=manager,dc=acegisecurity,dc=org</value></property>
|
||||
* <property name="managerPassword"><value>password</value></property> </bean>
|
||||
* <property name="managerPassword"><value>password</value></property>
|
||||
* </bean>
|
||||
*
|
||||
* <bean id="ldapAuthProvider" class="org.acegisecurity.providers.ldap.LdapAuthenticationProvider">
|
||||
* <constructor-arg> <bean class="org.acegisecurity.providers.ldap.authenticator.BindAuthenticator">
|
||||
* <constructor-arg><ref local="initialDirContextFactory"/></constructor-arg>
|
||||
* <property name="userDnPatterns"><list><value>uid={0},ou=people</value></list></property>
|
||||
* </bean> </constructor-arg> <constructor-arg>
|
||||
* <bean class="org.acegisecurity.providers.ldap.populator.DefaultLdapAuthoritiesPopulator">
|
||||
* <constructor-arg><ref local="initialDirContextFactory"/></constructor-arg>
|
||||
* <constructor-arg><value>ou=groups</value></constructor-arg>
|
||||
* <property name="groupRoleAttribute"><value>ou</value></property> </bean>
|
||||
* </constructor-arg> </bean></pre><p>This would set up the provider to access an LDAP server with URL
|
||||
* <constructor-arg>
|
||||
* <bean class="org.acegisecurity.providers.ldap.authenticator.BindAuthenticator">
|
||||
* <constructor-arg><ref local="initialDirContextFactory"/></constructor-arg>
|
||||
* <property name="userDnPatterns"><list><value>uid={0},ou=people</value></list></property>
|
||||
* </bean>
|
||||
* </constructor-arg>
|
||||
* <constructor-arg>
|
||||
* <bean class="org.acegisecurity.providers.ldap.populator.DefaultLdapAuthoritiesPopulator">
|
||||
* <constructor-arg><ref local="initialDirContextFactory"/></constructor-arg>
|
||||
* <constructor-arg><value>ou=groups</value></constructor-arg>
|
||||
* <property name="groupRoleAttribute"><value>ou</value></property>
|
||||
* </bean>
|
||||
* </constructor-arg>
|
||||
* </bean></pre>
|
||||
*
|
||||
* <p>This would set up the provider to access an LDAP server with URL
|
||||
* <tt>ldap://monkeymachine:389/dc=acegisecurity,dc=org</tt>. Authentication will be performed by attempting to bind
|
||||
* with the DN <tt>uid=<user-login-name>,ou=people,dc=acegisecurity,dc=org</tt>. After successful
|
||||
* authentication, roles will be assigned to the user by searching under the DN
|
||||
* <tt>ou=groups,dc=acegisecurity,dc=org</tt> with the default filter <tt>(member=<user's-DN>)</tt>. The role
|
||||
* name will be taken from the "ou" attribute of each match.</p>
|
||||
* <p>
|
||||
* The authenticate method will reject empty passwords outright. LDAP servers may allow an anonymous
|
||||
* bind operation with an empty password, even if a DN is supplied. In practice this means that if
|
||||
* the LDAP directory is configured to allow unauthenitcated access, it might be possible to
|
||||
* authenticate as <i>any</i> user just by supplying an empty password.
|
||||
* More information on the misuse of unauthenticated access can be found in
|
||||
* <a href="http://www.ietf.org/internet-drafts/draft-ietf-ldapbis-authmeth-19.txt">
|
||||
* draft-ietf-ldapbis-authmeth-19.txt</a>.
|
||||
* </p>
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
@@ -92,18 +123,39 @@ public class LdapAuthenticationProvider extends AbstractUserDetailsAuthenticatio
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
/**
|
||||
* Create an initialized instance to the values passed as arguments
|
||||
*
|
||||
* @param authenticator
|
||||
* @param authoritiesPopulator
|
||||
*/
|
||||
public LdapAuthenticationProvider(LdapAuthenticator authenticator, LdapAuthoritiesPopulator authoritiesPopulator) {
|
||||
Assert.notNull(authenticator, "An LdapAuthenticator must be supplied");
|
||||
Assert.notNull(authoritiesPopulator, "An LdapAuthoritiesPopulator must be supplied");
|
||||
|
||||
this.authenticator = authenticator;
|
||||
this.authoritiesPopulator = 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.authoritiesPopulator = authoritiesPopulator;
|
||||
}
|
||||
|
||||
protected LdapAuthoritiesPopulator getAuthoritiesPopulator() {
|
||||
return authoritiesPopulator;
|
||||
}
|
||||
|
||||
protected void additionalAuthenticationChecks(UserDetails userDetails,
|
||||
UsernamePasswordAuthenticationToken authentication)
|
||||
UsernamePasswordAuthenticationToken authentication)
|
||||
throws AuthenticationException {
|
||||
if (!userDetails.getPassword().equals(authentication.getCredentials().toString())) {
|
||||
throw new BadCredentialsException(messages.getMessage(
|
||||
@@ -130,7 +182,7 @@ public class LdapAuthenticationProvider extends AbstractUserDetailsAuthenticatio
|
||||
user.setUsername(username);
|
||||
user.setPassword(password);
|
||||
|
||||
GrantedAuthority[] extraAuthorities = authoritiesPopulator.getGrantedAuthorities(ldapUser);
|
||||
GrantedAuthority[] extraAuthorities = getAuthoritiesPopulator().getGrantedAuthorities(ldapUser);
|
||||
|
||||
for (int i = 0; i < extraAuthorities.length; i++) {
|
||||
user.addAuthority(extraAuthorities[i]);
|
||||
@@ -139,10 +191,6 @@ 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)) {
|
||||
@@ -157,8 +205,19 @@ public class LdapAuthenticationProvider extends AbstractUserDetailsAuthenticatio
|
||||
String password = (String) authentication.getCredentials();
|
||||
Assert.notNull(password, "Null password was supplied in authentication token");
|
||||
|
||||
LdapUserDetails ldapUser = authenticator.authenticate(username, password);
|
||||
if (password.length() == 0) {
|
||||
logger.debug("Rejecting empty password for user " + username);
|
||||
throw new BadCredentialsException(messages.getMessage("LdapAuthenticationProvider.emptyPassword",
|
||||
"Empty Password"));
|
||||
}
|
||||
|
||||
return createUserDetails(ldapUser, username, password);
|
||||
try {
|
||||
LdapUserDetails ldapUser = getAuthenticator().authenticate(username, password);
|
||||
|
||||
return createUserDetails(ldapUser, username, password);
|
||||
|
||||
} catch (DataAccessException ldapAccessFailure) {
|
||||
throw new AuthenticationServiceException(ldapAccessFailure.getMessage(), ldapAccessFailure);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+23
-8
@@ -70,7 +70,29 @@ public abstract class AbstractLdapAuthenticator implements LdapAuthenticator, In
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
protected AbstractLdapAuthenticator(InitialDirContextFactory initialDirContextFactory) {
|
||||
/**
|
||||
* 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) {
|
||||
Assert.notNull(initialDirContextFactory, "initialDirContextFactory must not be null.");
|
||||
this.initialDirContextFactory = initialDirContextFactory;
|
||||
|
||||
@@ -81,13 +103,6 @@ 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;
|
||||
}
|
||||
|
||||
+19
-8
@@ -26,6 +26,7 @@ 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;
|
||||
|
||||
|
||||
@@ -44,6 +45,11 @@ public class BindAuthenticator extends AbstractLdapAuthenticator {
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
/**
|
||||
* Create an initialized instance to the {@link InitialDirContextFactory} provided.
|
||||
*
|
||||
* @param initialDirContextFactory
|
||||
*/
|
||||
public BindAuthenticator(InitialDirContextFactory initialDirContextFactory) {
|
||||
super(initialDirContextFactory);
|
||||
}
|
||||
@@ -77,10 +83,6 @@ 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());
|
||||
@@ -89,12 +91,21 @@ 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.
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Failed to bind as " + userDn + ": " + e.getCause());
|
||||
}
|
||||
// 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());
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+46
-26
@@ -40,23 +40,19 @@ import javax.naming.directory.SearchControls;
|
||||
|
||||
/**
|
||||
* The default strategy for obtaining user role information from the directory.<p>It obtains roles by
|
||||
* <ul>
|
||||
* <li>Reading the values of the roles specified by the attribute names in the <tt>userRoleAttributes</tt></li>
|
||||
* <li>Performing a search for "groups" the user is a member of and adding those to the list of roles.</li>
|
||||
* </ul>
|
||||
* performing a search for "groups" the user is a member of.
|
||||
* </p>
|
||||
* <p>If the <tt>userRolesAttributes</tt> property is set, any matching attributes amongst those retrieved for the
|
||||
* user will have their values added to the list of roles. If <tt>userRolesAttributes</tt> is null, no attributes will
|
||||
* be mapped to roles.</p>
|
||||
* <p>A typical group search scenario would be where each group/role is specified using the <tt>groupOfNames</tt>
|
||||
* (or <tt>groupOfUniqueNames</tt>) LDAP objectClass and the user's DN is listed in the <tt>member</tt> (or
|
||||
* <tt>uniqueMember</tt>) attribute to indicate that they should be assigned that role. The following LDIF sample has
|
||||
* the groups stored under the DN <tt>ou=groups,dc=acegisecurity,dc=org</tt> and a group called "developers" with
|
||||
* "ben" and "marissa" as members:<pre>dn: ou=groups,dc=acegisecurity,dc=orgobjectClass: top
|
||||
* "ben" and "marissa" as members:
|
||||
* <pre>dn: ou=groups,dc=acegisecurity,dc=orgobjectClass: top
|
||||
* objectClass: organizationalUnitou: groupsdn: cn=developers,ou=groups,dc=acegisecurity,dc=org
|
||||
* objectClass: groupOfNamesobjectClass: topcn: developersdescription: Acegi Security Developers
|
||||
* member: uid=ben,ou=people,dc=acegisecurity,dc=orgmember: uid=marissa,ou=people,dc=acegisecurity,dc=orgou: developer
|
||||
* </pre></p>
|
||||
* </pre>
|
||||
* </p>
|
||||
* <p>The group search is performed within a DN specified by the <tt>groupSearchBase</tt> property, which should
|
||||
* be relative to the root DN of its <tt>InitialDirContextFactory</tt>. If the search base is null, group searching is
|
||||
* disabled. The filter used in the search is defined by the <tt>groupSearchFilter</tt> property, with the filter
|
||||
@@ -70,7 +66,9 @@ import javax.naming.directory.SearchControls;
|
||||
* <!-- the following properties are shown with their default values -->
|
||||
* <property name="searchSubTree"><value>false</value></property>
|
||||
* <property name="rolePrefix"><value>ROLE_</value></property>
|
||||
* <property name="convertToUpperCase"><value>true</value></property></bean></pre>A search for
|
||||
* <property name="convertToUpperCase"><value>true</value></property>
|
||||
* </bean>
|
||||
* </pre>A search for
|
||||
* roles for user "uid=ben,ou=people,dc=acegisecurity,dc=org" would return the single granted authority
|
||||
* "ROLE_DEVELOPER".</p>
|
||||
*
|
||||
@@ -123,18 +121,8 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
|
||||
* context factory.
|
||||
*/
|
||||
public DefaultLdapAuthoritiesPopulator(InitialDirContextFactory initialDirContextFactory, String 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);
|
||||
this.setInitialDirContextFactory(initialDirContextFactory);
|
||||
this.setGroupSearchBase(groupSearchBase);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
@@ -203,19 +191,19 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
|
||||
// }
|
||||
|
||||
|
||||
public final Set getGroupMembershipRoles(String userDn, String username) {
|
||||
public Set getGroupMembershipRoles(String userDn, String username) {
|
||||
Set authorities = new HashSet();
|
||||
|
||||
if (groupSearchBase == null) {
|
||||
if (getGroupSearchBase() == null) {
|
||||
return authorities;
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Searching for roles for user '" + username + "', DN = " + "'" + userDn + "', with filter "
|
||||
+ groupSearchFilter + " in search base '" + groupSearchBase + "'");
|
||||
+ groupSearchFilter + " in search base '" + getGroupSearchBase() + "'");
|
||||
}
|
||||
|
||||
Set userRoles = ldapTemplate.searchForSingleAttributeValues(groupSearchBase, groupSearchFilter,
|
||||
Set userRoles = ldapTemplate.searchForSingleAttributeValues(getGroupSearchBase(), groupSearchFilter,
|
||||
new String[] {userDn, username}, groupRoleAttribute);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
@@ -256,6 +244,38 @@ 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;
|
||||
}
|
||||
|
||||
+6
-14
@@ -15,14 +15,11 @@
|
||||
|
||||
package org.acegisecurity.providers.rememberme;
|
||||
|
||||
import org.acegisecurity.GrantedAuthority;
|
||||
|
||||
import org.acegisecurity.providers.AbstractAuthenticationToken;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.acegisecurity.GrantedAuthority;
|
||||
import org.acegisecurity.providers.AbstractAuthenticationToken;
|
||||
|
||||
|
||||
/**
|
||||
* Represents a remembered <code>Authentication</code>.<p>A remembered <code>Authentication</code> must provide a
|
||||
@@ -34,12 +31,13 @@ import java.io.Serializable;
|
||||
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
|
||||
@@ -51,16 +49,10 @@ 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) || (authorities == null)
|
||||
|| (authorities.length == 0)) {
|
||||
if ((key == null) || ("".equals(key)) || (principal == null) || "".equals(principal)) {
|
||||
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
@@ -0,0 +1,132 @@
|
||||
/* 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
A Siteminder authentication provider.
|
||||
</body>
|
||||
</html>
|
||||
@@ -31,6 +31,7 @@ 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 authenticationDao) {
|
||||
this.userDetailsService = authenticationDao;
|
||||
public void setUserDetailsService(UserDetailsService userDetailsService) {
|
||||
this.userDetailsService = userDetailsService;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ 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;
|
||||
|
||||
@@ -81,14 +81,15 @@ import javax.servlet.http.HttpServletResponse;
|
||||
* <p>To configure this filter to redirect to specific pages as the result of specific {@link
|
||||
* AuthenticationException}s you can do the following. Configure the <code>exceptionMappings</code> property in your
|
||||
* application xml. This property is a java.util.Properties object that maps a fully-qualified exception class name to
|
||||
* a redirection url target.<br>
|
||||
* For example:<br>
|
||||
* <code> <property name="exceptionMappings"><br>
|
||||
* * <props><br>
|
||||
* * <prop> key="org.acegisecurity.BadCredentialsException">/bad_credentials.jsp</prop><br>
|
||||
* * </props><br>
|
||||
* * </property><br>
|
||||
* * </code><br>
|
||||
* a redirection url target.
|
||||
* For example:
|
||||
* <pre>
|
||||
* <property name="exceptionMappings">
|
||||
* <props>
|
||||
* <prop> key="org.acegisecurity.BadCredentialsException">/bad_credentials.jsp</prop>
|
||||
* </props>
|
||||
* </property>
|
||||
* </pre>
|
||||
* The example above would redirect all {@link org.acegisecurity.BadCredentialsException}s thrown, to a page in the
|
||||
* web-application called /bad_credentials.jsp.</p>
|
||||
* <p>Any {@link AuthenticationException} thrown that cannot be matched in the <code>exceptionMappings</code> will
|
||||
@@ -122,7 +123,7 @@ public abstract class AbstractProcessingFilter implements Filter, InitializingBe
|
||||
private String authenticationFailureUrl;
|
||||
|
||||
/**
|
||||
* Where to redirect the browser to if authentication is successful but ACEGI_SECURITY_TARGET_URL_KEY is
|
||||
* Where to redirect the browser to if authentication is successful but ACEGI_SAVED_REQUEST_KEY is
|
||||
* <code>null</code>
|
||||
*/
|
||||
private String defaultTargetUrl;
|
||||
@@ -134,7 +135,7 @@ public abstract class AbstractProcessingFilter implements Filter, InitializingBe
|
||||
private String filterProcessesUrl = getDefaultFilterProcessesUrl();
|
||||
|
||||
/**
|
||||
* If <code>true</code>, will always redirect to {@link #defaultTargetUrl} upon successful authentication,
|
||||
* If <code>true</code>, will always redirect to the value of {@link #getDefaultTargetUrl} upon successful authentication,
|
||||
* irrespective of the page that caused the authentication request (defaults to <code>false</code>).
|
||||
*/
|
||||
private boolean alwaysUseDefaultTargetUrl = false;
|
||||
@@ -231,6 +232,14 @@ public abstract class AbstractProcessingFilter implements Filter, InitializingBe
|
||||
*/
|
||||
public abstract String getDefaultFilterProcessesUrl();
|
||||
|
||||
/**
|
||||
* Supplies the default target Url that will be used if no saved request is found or the
|
||||
* <tt>alwaysUseDefaultTargetUrl</tt> propert is set to true.
|
||||
* Override this method of you want to provide a customized default Url (for example if you want different Urls
|
||||
* depending on the authorities of the user who has just logged in).
|
||||
*
|
||||
* @return the defaultTargetUrl property
|
||||
*/
|
||||
public String getDefaultTargetUrl() {
|
||||
return defaultTargetUrl;
|
||||
}
|
||||
@@ -304,13 +313,13 @@ public abstract class AbstractProcessingFilter implements Filter, InitializingBe
|
||||
return uri.endsWith(request.getContextPath() + filterProcessesUrl);
|
||||
}
|
||||
|
||||
protected void sendRedirect(HttpServletRequest request, HttpServletResponse response, String failureUrl)
|
||||
protected void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url)
|
||||
throws IOException {
|
||||
if (!failureUrl.startsWith("http://") && !failureUrl.startsWith("https://")) {
|
||||
failureUrl = request.getContextPath() + failureUrl;
|
||||
if (!url.startsWith("http://") && !url.startsWith("https://")) {
|
||||
url = request.getContextPath() + url;
|
||||
}
|
||||
|
||||
response.sendRedirect(response.encodeRedirectURL(failureUrl));
|
||||
response.sendRedirect(response.encodeRedirectURL(url));
|
||||
}
|
||||
|
||||
public void setAlwaysUseDefaultTargetUrl(boolean alwaysUseDefaultTargetUrl) {
|
||||
@@ -339,6 +348,8 @@ 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;
|
||||
}
|
||||
|
||||
@@ -370,14 +381,11 @@ public abstract class AbstractProcessingFilter implements Filter, InitializingBe
|
||||
logger.debug("Updated SecurityContextHolder to contain the following Authentication: '" + authResult + "'");
|
||||
}
|
||||
|
||||
String targetUrl = obtainFullRequestUrl(request);
|
||||
|
||||
if (alwaysUseDefaultTargetUrl) {
|
||||
targetUrl = null;
|
||||
}
|
||||
// Don't attempt to obtain the url from the saved request if alwaysUsedefaultTargetUrl is set
|
||||
String targetUrl = alwaysUseDefaultTargetUrl ? null : obtainFullRequestUrl(request);
|
||||
|
||||
if (targetUrl == null) {
|
||||
targetUrl = request.getContextPath() + defaultTargetUrl;
|
||||
targetUrl = getDefaultTargetUrl();
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
@@ -393,7 +401,7 @@ public abstract class AbstractProcessingFilter implements Filter, InitializingBe
|
||||
eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authResult, this.getClass()));
|
||||
}
|
||||
|
||||
response.sendRedirect(response.encodeRedirectURL(targetUrl));
|
||||
sendRedirect(request, response, targetUrl);
|
||||
}
|
||||
|
||||
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
|
||||
|
||||
@@ -62,21 +62,13 @@ public class AccessDeniedHandlerImpl implements AccessDeniedHandler {
|
||||
|
||||
// Perform RequestDispatcher "forward"
|
||||
RequestDispatcher rd = request.getRequestDispatcher(errorPage);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
rd.forward(request, response);
|
||||
}
|
||||
|
||||
// Send 403 (we do this after response has been written)
|
||||
((HttpServletResponse) response).sendError(HttpServletResponse.SC_FORBIDDEN, accessDeniedException.getMessage());
|
||||
if (!response.isCommitted()) {
|
||||
// Send 403 (we do this after response has been written)
|
||||
((HttpServletResponse) response).sendError(HttpServletResponse.SC_FORBIDDEN, accessDeniedException.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,27 +15,6 @@
|
||||
|
||||
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;
|
||||
@@ -47,6 +26,21 @@ 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
|
||||
@@ -135,7 +129,10 @@ 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();
|
||||
|
||||
if ((existingAuth == null) || !existingAuth.getName().equals(username) || !existingAuth.isAuthenticated()) {
|
||||
// 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()) {
|
||||
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 authenticationDao) {
|
||||
this.userDetailsService = authenticationDao;
|
||||
public void setUserDetailsService(UserDetailsService userDetailsService) {
|
||||
this.userDetailsService = userDetailsService;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,28 +18,60 @@ 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;
|
||||
|
||||
/**
|
||||
* Does not use any arguments. They can all be <code>null</code>.
|
||||
* Requires the request to be passed in.
|
||||
*
|
||||
* @param request not used (can be <code>null</code>)
|
||||
* @param request from which to obtain a HTTP session (cannot be null)
|
||||
* @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) {
|
||||
SecurityContextHolder.clearContext();
|
||||
Assert.notNull(request, "HttpServletRequest required");
|
||||
if (invalidateHttpSession) {
|
||||
HttpSession session = request.getSession(false);
|
||||
if (session != null) {
|
||||
session.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -319,7 +319,7 @@ public class TokenBasedRememberMeServices implements RememberMeServices, Initial
|
||||
this.tokenValiditySeconds = tokenValiditySeconds;
|
||||
}
|
||||
|
||||
public void setUserDetailsService(UserDetailsService authenticationDao) {
|
||||
this.userDetailsService = authenticationDao;
|
||||
public void setUserDetailsService(UserDetailsService userDetailsService) {
|
||||
this.userDetailsService = userDetailsService;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
package org.acegisecurity.ui.savedrequest;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Stores off the values of a cookie in a serializable holder
|
||||
*
|
||||
* @author Ray Krueger
|
||||
*/
|
||||
public class SavedCookie implements Serializable {
|
||||
private java.lang.String name;
|
||||
private java.lang.String value;
|
||||
private java.lang.String comment;
|
||||
private java.lang.String domain;
|
||||
private int maxAge;
|
||||
private java.lang.String path;
|
||||
private boolean secure;
|
||||
private int version;
|
||||
|
||||
public SavedCookie(String name, String value, String comment, String domain, int maxAge, String path, boolean secure, int version) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
this.comment = comment;
|
||||
this.domain = domain;
|
||||
this.maxAge = maxAge;
|
||||
this.path = path;
|
||||
this.secure = secure;
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public SavedCookie(Cookie cookie) {
|
||||
this(cookie.getName(), cookie.getValue(), cookie.getComment(),
|
||||
cookie.getDomain(), cookie.getMaxAge(), cookie.getPath(), cookie.getSecure(), cookie.getVersion());
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String getComment() {
|
||||
return comment;
|
||||
}
|
||||
|
||||
public String getDomain() {
|
||||
return domain;
|
||||
}
|
||||
|
||||
public int getMaxAge() {
|
||||
return maxAge;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public boolean isSecure() {
|
||||
return secure;
|
||||
}
|
||||
|
||||
public int getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public Cookie getCookie() {
|
||||
Cookie c = new Cookie(getName(), getValue());
|
||||
|
||||
if (getComment() != null)
|
||||
c.setComment(getComment());
|
||||
|
||||
if (getDomain() != null)
|
||||
c.setDomain(getDomain());
|
||||
|
||||
if (getPath() != null)
|
||||
c.setPath(getPath());
|
||||
|
||||
c.setVersion(getVersion());
|
||||
c.setMaxAge(getMaxAge());
|
||||
c.setSecure(isSecure());
|
||||
return c;
|
||||
}
|
||||
}
|
||||
@@ -17,22 +17,19 @@ package org.acegisecurity.ui.savedrequest;
|
||||
|
||||
import org.acegisecurity.util.PortResolver;
|
||||
import org.acegisecurity.util.UrlUtils;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
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 javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.TreeMap;
|
||||
|
||||
|
||||
/**
|
||||
@@ -40,9 +37,9 @@ import javax.servlet.http.HttpServletRequest;
|
||||
* org.acegisecurity.ui.AbstractProcessingFilter} and {@link org.acegisecurity.wrapper.SavedRequestAwareWrapper} to
|
||||
* reproduce the request after successful authentication. An instance of this class is stored at the time of an
|
||||
* authentication exception by {@link org.acegisecurity.ui.ExceptionTranslationFilter}.</p>
|
||||
* <p><em>IMPLEMENTATION NOTE</em>: It is assumed that this object is accessed only from the context of a single
|
||||
* <p><em>IMPLEMENTATION NOTE</em>: It is assumed that this object is accessed only from the context of a single
|
||||
* thread, so no synchronization around internal collection classes is performed.</p>
|
||||
* <p>This class is based on code in Apache Tomcat.</p>
|
||||
* <p>This class is based on code in Apache Tomcat.</p>
|
||||
*
|
||||
* @author Craig McClanahan
|
||||
* @author Andrey Grebnev
|
||||
@@ -58,8 +55,8 @@ public class SavedRequest implements java.io.Serializable {
|
||||
|
||||
private ArrayList cookies = new ArrayList();
|
||||
private ArrayList locales = new ArrayList();
|
||||
private HashMap headers = new HashMap();
|
||||
private HashMap parameters = new HashMap();
|
||||
private Map headers = new TreeMap(String.CASE_INSENSITIVE_ORDER);
|
||||
private Map parameters = new TreeMap(String.CASE_INSENSITIVE_ORDER);
|
||||
private String contextPath;
|
||||
private String method;
|
||||
private String pathInfo;
|
||||
@@ -133,7 +130,7 @@ public class SavedRequest implements java.io.Serializable {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
private void addCookie(Cookie cookie) {
|
||||
cookies.add(cookie);
|
||||
cookies.add(new SavedCookie(cookie));
|
||||
}
|
||||
|
||||
private void addHeader(String name, String value) {
|
||||
@@ -161,7 +158,6 @@ public class SavedRequest implements java.io.Serializable {
|
||||
*
|
||||
* @param request DOCUMENT ME!
|
||||
* @param portResolver DOCUMENT ME!
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*/
|
||||
public boolean doesRequestMatch(HttpServletRequest request, PortResolver portResolver) {
|
||||
@@ -180,7 +176,8 @@ public class SavedRequest implements java.io.Serializable {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!propertyEquals("serverPort", new Integer(this.serverPort), new Integer(portResolver.getServerPort(request)))) {
|
||||
if (!propertyEquals("serverPort", new Integer(this.serverPort), new Integer(portResolver.getServerPort(request))))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -212,7 +209,12 @@ public class SavedRequest implements java.io.Serializable {
|
||||
}
|
||||
|
||||
public List getCookies() {
|
||||
return cookies;
|
||||
List cookieList = new ArrayList(cookies.size());
|
||||
for (Iterator iterator = cookies.iterator(); iterator.hasNext();) {
|
||||
SavedCookie savedCookie = (SavedCookie) iterator.next();
|
||||
cookieList.add(savedCookie.getCookie());
|
||||
}
|
||||
return cookieList;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.acegisecurity.GrantedAuthorityImpl;
|
||||
public class SwitchUserGrantedAuthority extends GrantedAuthorityImpl {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private Authentication source;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
@@ -439,8 +439,8 @@ public class SwitchUserProcessingFilter implements Filter, InitializingBean, App
|
||||
*
|
||||
* @param authenticationDao The authentication dao
|
||||
*/
|
||||
public void setUserDetailsService(UserDetailsService authenticationDao) {
|
||||
this.userDetailsService = authenticationDao;
|
||||
public void setUserDetailsService(UserDetailsService userDetailsService) {
|
||||
this.userDetailsService = userDetailsService;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
Authenticates users via a standard web form and <code>HttpSession</code>.
|
||||
Authenticates users via HTTP properties, headers and session.
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -31,6 +31,7 @@ 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;
|
||||
|
||||
@@ -41,6 +41,7 @@ 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];
|
||||
|
||||
@@ -109,7 +110,7 @@ public class LdapUserDetailsImpl implements LdapUserDetails {
|
||||
* Variation of essence pattern. Used to create mutable intermediate object
|
||||
*/
|
||||
public static class Essence {
|
||||
LdapUserDetailsImpl instance = new LdapUserDetailsImpl();
|
||||
LdapUserDetailsImpl instance = createTarget();
|
||||
List mutableAuthorities = new ArrayList();
|
||||
|
||||
public Essence() {}
|
||||
@@ -127,6 +128,10 @@ public class LdapUserDetailsImpl implements LdapUserDetails {
|
||||
setAuthorities(copyMe.getAuthorities());
|
||||
}
|
||||
|
||||
LdapUserDetailsImpl createTarget() {
|
||||
return new LdapUserDetailsImpl();
|
||||
}
|
||||
|
||||
public Essence addAuthority(GrantedAuthority a) {
|
||||
mutableAuthorities.add(a);
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.acegisecurity.userdetails.ldap;
|
||||
|
||||
import org.acegisecurity.GrantedAuthorityImpl;
|
||||
import org.acegisecurity.GrantedAuthority;
|
||||
|
||||
import org.acegisecurity.ldap.LdapEntryMapper;
|
||||
|
||||
@@ -57,34 +58,27 @@ public class LdapUserDetailsMapper implements LdapEntryMapper {
|
||||
Attribute passwordAttribute = attributes.get(passwordAttributeName);
|
||||
|
||||
if (passwordAttribute != null) {
|
||||
Object retrievedPassword = passwordAttribute.get();
|
||||
|
||||
if (!(retrievedPassword instanceof String)) {
|
||||
// Assume it's binary
|
||||
retrievedPassword = new String((byte[]) retrievedPassword);
|
||||
}
|
||||
|
||||
essence.setPassword((String) retrievedPassword);
|
||||
essence.setPassword(mapPassword(passwordAttribute));
|
||||
}
|
||||
|
||||
// Map the roles
|
||||
for (int i = 0; (roleAttributes != null) && (i < roleAttributes.length); i++) {
|
||||
Attribute roleAttribute = attributes.get(roleAttributes[i]);
|
||||
|
||||
if(roleAttribute == null) {
|
||||
logger.debug("Couldn't read role attribute '" + roleAttributes[i] + "' for user " + dn);
|
||||
continue;
|
||||
}
|
||||
|
||||
NamingEnumeration attributeRoles = roleAttribute.getAll();
|
||||
|
||||
while (attributeRoles.hasMore()) {
|
||||
Object role = attributeRoles.next();
|
||||
GrantedAuthority authority = createAuthority(attributeRoles.next());
|
||||
|
||||
// We only handle Strings for the time being
|
||||
if (role instanceof String) {
|
||||
if (convertToUpperCase) {
|
||||
role = ((String) role).toUpperCase();
|
||||
}
|
||||
|
||||
essence.addAuthority(new GrantedAuthorityImpl(rolePrefix + role));
|
||||
if(authority != null) {
|
||||
essence.addAuthority(authority);
|
||||
} else {
|
||||
logger.warn("Non-String value found for role attribute " + roleAttribute.getID());
|
||||
logger.debug("Failed to create an authority value from attribute with Id: " + roleAttribute.getID());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -92,6 +86,47 @@ 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.
|
||||
* <p>
|
||||
* The default implementation converts string attributes to roles, making use of the <tt>rolePrefix</tt>
|
||||
* and <tt>convertToUpperCase</tt> properties. Non-String attributes are ignored.
|
||||
* </p>
|
||||
*
|
||||
* @param role the attribute returned from
|
||||
* @return the authority to be added to the list of authorities for the user, or null
|
||||
* if this attribute should be ignored.
|
||||
*/
|
||||
protected GrantedAuthority createAuthority(Object role) {
|
||||
if (role instanceof String) {
|
||||
if (convertToUpperCase) {
|
||||
role = ((String) role).toUpperCase();
|
||||
}
|
||||
return new GrantedAuthorityImpl(rolePrefix + role);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether role field values will be converted to upper case when loaded.
|
||||
* The default is true.
|
||||
|
||||
@@ -18,6 +18,8 @@ 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;
|
||||
|
||||
@@ -53,6 +55,32 @@ 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,13 +15,12 @@
|
||||
|
||||
package org.acegisecurity.userdetails.memory;
|
||||
|
||||
import org.acegisecurity.GrantedAuthorityImpl;
|
||||
import java.beans.PropertyEditorSupport;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
|
||||
|
||||
/**
|
||||
* Property editor that creates a {@link UserAttribute} from a comma separated list of values.
|
||||
*
|
||||
@@ -35,6 +34,8 @@ 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();
|
||||
@@ -47,10 +48,11 @@ public class UserAttributeEditor extends PropertyEditorSupport {
|
||||
} else if (currentToken.toLowerCase().equals("disabled")) {
|
||||
userAttrib.setEnabled(false);
|
||||
} else {
|
||||
userAttrib.addAuthority(new GrantedAuthorityImpl(currentToken));
|
||||
authoritiesAsString.add(currentToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
userAttrib.setAuthoritiesAsString(authoritiesAsString);
|
||||
|
||||
if (userAttrib.isValid()) {
|
||||
setValue(userAttrib);
|
||||
|
||||
@@ -15,18 +15,15 @@
|
||||
|
||||
package org.acegisecurity.userdetails.memory;
|
||||
|
||||
import org.acegisecurity.userdetails.User;
|
||||
import org.acegisecurity.userdetails.UserDetails;
|
||||
import org.acegisecurity.userdetails.UsernameNotFoundException;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.acegisecurity.userdetails.UserDetails;
|
||||
import org.acegisecurity.userdetails.UsernameNotFoundException;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* Used by {@link InMemoryDaoImpl} to store a list of users and their corresponding granted authorities.
|
||||
@@ -68,8 +65,8 @@ public class UserMap {
|
||||
*
|
||||
* @throws UsernameNotFoundException if the user could not be found
|
||||
*/
|
||||
public User getUser(String username) throws UsernameNotFoundException {
|
||||
User result = (User) this.userMap.get(username.toLowerCase());
|
||||
public UserDetails getUser(String username) throws UsernameNotFoundException {
|
||||
UserDetails result = (UserDetails) this.userMap.get(username.toLowerCase());
|
||||
|
||||
if (result == null) {
|
||||
throw new UsernameNotFoundException("Could not find user: " + username);
|
||||
@@ -86,4 +83,14 @@ public class UserMap {
|
||||
public int getUserCount() {
|
||||
return this.userMap.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the users in this {@link UserMap}. Overrides previously added users.
|
||||
*
|
||||
* @param users {@link Map} <{@link String}, {@link UserDetails}> with pairs (username, userdetails)
|
||||
* @since 1.1
|
||||
*/
|
||||
public void setUsers(Map users) {
|
||||
this.userMap = users;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
/* 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.util;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.spec.KeySpec;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.spec.DESedeKeySpec;
|
||||
|
||||
import org.acegisecurity.AcegiSecurityException;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A static utility class that can encrypt and decrypt text.
|
||||
*
|
||||
* <p>This class is useful if you have simple needs and wish to use the DESede
|
||||
* encryption cipher. More sophisticated requirements will need to use the
|
||||
* Java crypto libraries directly.
|
||||
*
|
||||
* @author Alan Stewart
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class EncryptionUtils {
|
||||
|
||||
/**
|
||||
* This is a static class that should not be instantiated.
|
||||
*/
|
||||
private EncryptionUtils() {}
|
||||
|
||||
/**
|
||||
* Converts a String into a byte array using UTF-8, falling back to the
|
||||
* platform's default character set if UTF-8 fails.
|
||||
*
|
||||
* @param input the input (required)
|
||||
* @return a byte array representation of the input string
|
||||
*/
|
||||
public static byte[] stringToByteArray(String input) {
|
||||
Assert.hasLength(input, "Input required");
|
||||
try {
|
||||
return input.getBytes("UTF-8");
|
||||
} catch (UnsupportedEncodingException fallbackToDefault) {
|
||||
return input.getBytes();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a byte array into a String using UTF-8, falling back to the
|
||||
* platform's default character set if UTF-8 fails.
|
||||
*
|
||||
* @param byteArray the byte array to convert (required)
|
||||
* @return a string representation of the byte array
|
||||
*/
|
||||
public static String byteArrayToString(byte[] byteArray) {
|
||||
Assert.notNull(byteArray, "ByteArray required");
|
||||
Assert.isTrue(byteArray.length > 0, "ByteArray cannot be empty");
|
||||
try {
|
||||
return new String(byteArray, "UTF8");
|
||||
} catch (final UnsupportedEncodingException e) {
|
||||
return new String(byteArray);
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] cipher(String key, byte[] passedBytes, int cipherMode) throws EncryptionException {
|
||||
try {
|
||||
final KeySpec keySpec = new DESedeKeySpec(stringToByteArray(key));
|
||||
final SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
|
||||
final Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
|
||||
final SecretKey secretKey = keyFactory.generateSecret(keySpec);
|
||||
cipher.init(cipherMode, secretKey);
|
||||
return cipher.doFinal(passedBytes);
|
||||
} catch (final Exception e) {
|
||||
throw new EncryptionException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts the inputString using the key.
|
||||
*
|
||||
* @param key at least 24 character long key (required)
|
||||
* @param inputString the string to encrypt (required)
|
||||
* @return the encrypted version of the inputString
|
||||
* @throws EncryptionException in the event of an encryption failure
|
||||
*/
|
||||
public static String encrypt(String key, String inputString) throws EncryptionException {
|
||||
isValidKey(key);
|
||||
final byte[] cipherText = cipher(key, stringToByteArray(inputString), Cipher.ENCRYPT_MODE);
|
||||
return byteArrayToString(Base64.encodeBase64(cipherText));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts the inputString using the key.
|
||||
*
|
||||
* @param key the key used to originally encrypt the string (required)
|
||||
* @param inputString the encrypted string (required)
|
||||
* @return the decrypted version of inputString
|
||||
* @throws EncryptionException in the event of an encryption failure
|
||||
*/
|
||||
public static String decrypt(String key, String inputString) throws EncryptionException {
|
||||
Assert.hasText(key, "A key is required to attempt decryption");
|
||||
final byte[] cipherText = cipher(key, Base64.decodeBase64(stringToByteArray(inputString)), Cipher.DECRYPT_MODE);
|
||||
return byteArrayToString(cipherText);
|
||||
}
|
||||
|
||||
private static void isValidKey(String key) {
|
||||
Assert.hasText(key, "A key to perform the encryption is required");
|
||||
Validate.isTrue(key.length() >= 24, "Key must be at least 24 characters long");
|
||||
}
|
||||
|
||||
public static class EncryptionException extends AcegiSecurityException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public EncryptionException(String message, Throwable t) {
|
||||
super(message, t);
|
||||
}
|
||||
|
||||
public EncryptionException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,32 +28,40 @@ import java.util.Map;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
|
||||
|
||||
/**
|
||||
* Delegates <code>Filter</code> requests to a Spring-managed bean.<p>This class acts as a proxy on behalf of a
|
||||
* <p>Delegates <code>Filter</code> requests to a Spring-managed bean.</p>
|
||||
*
|
||||
* <p>This class acts as a proxy on behalf of a
|
||||
* target <code>Filter</code> that is defined in the Spring bean context. It is necessary to specify which target
|
||||
* <code>Filter</code> should be proxied as a filter initialization parameter.</p>
|
||||
* <p>On filter initialisation, the class will use Spring's {@link
|
||||
*
|
||||
* <p>On filter initialisation, the class will use Spring's {@link
|
||||
* WebApplicationContextUtils#getWebApplicationContext(ServletContext sc)} method to obtain an
|
||||
* <code>ApplicationContext</code> instance. It will expect to find the target <code>Filter</code> in this
|
||||
* <code>ApplicationContext</code>.</p>
|
||||
* <p>To use this filter, it is necessary to specify <b>one</b> of the following filter initialization parameters:</p>
|
||||
*
|
||||
* <p>To use this filter, it is necessary to specify <b>one</b> of the following filter initialization parameters:
|
||||
* <ul>
|
||||
* <li><code>targetClass</code> indicates the class of the target <code>Filter</code> defined in the bean
|
||||
* context. The only requirements are that this target class implements the <code>javax.servlet.Filter</code>
|
||||
* interface and at least one instance is available in the <code>ApplicationContext</code>.</li>
|
||||
* <li><code>targetBean</code> indicates the bean name of the target class.</li>
|
||||
* </ul>
|
||||
* If both initialization parameters are specified, <code>targetBean</code> takes priority.<P>An additional
|
||||
* If both initialization parameters are specified, <code>targetBean</code> takes priority.</p>
|
||||
*
|
||||
* <p>An additional
|
||||
* initialization parameter, <code>init</code>, is also supported. If set to "<code>lazy</code>" the initialization
|
||||
* will take place on the first HTTP request, rather than at filter creation time. This makes it possible to use
|
||||
* <code>FilterToBeanProxy</code> with the Spring <code>ContextLoaderServlet</code>. Where possible you should not use
|
||||
* this initialization parameter, instead using <code>ContextLoaderListener</code>.</p>
|
||||
* <p>A final optional initialization parameter, <code>lifecycle</code>, determines whether the servlet container
|
||||
*
|
||||
* <p>A final optional initialization parameter, <code>lifecycle</code>, determines whether the servlet container
|
||||
* or the IoC container manages the lifecycle of the proxied filter. When possible you should write your filters to be
|
||||
* managed via the IoC container interfaces such as {@link org.springframework.beans.factory.InitializingBean} and
|
||||
* {@link org.springframework.beans.factory.DisposableBean}. If you cannot control the filters you wish to proxy (eg
|
||||
|
||||
@@ -72,7 +72,7 @@ public class MethodInvocationUtils {
|
||||
classArgs = (Class[]) list.toArray(new Class[] {});
|
||||
}
|
||||
|
||||
return createFromClass(object.getClass(), methodName, classArgs);
|
||||
return createFromClass(object.getClass(), methodName, classArgs, args);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,7 +84,7 @@ public class MethodInvocationUtils {
|
||||
* @return a <code>MethodInvocation</code>, or <code>null</code> if there was a problem
|
||||
*/
|
||||
public static MethodInvocation createFromClass(Class clazz, String methodName) {
|
||||
return createFromClass(clazz, methodName, null);
|
||||
return createFromClass(clazz, methodName, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,18 +93,18 @@ public class MethodInvocationUtils {
|
||||
*
|
||||
* @param clazz the class of object that will be used to find the relevant <code>Method</code>
|
||||
* @param methodName the name of the method to find
|
||||
* @param args arguments that are required as part of the method signature
|
||||
*
|
||||
* @param classArgs arguments that are required to locate the relevant method signature
|
||||
* @param args the actual arguments that should be passed to SimpleMethodInvocation
|
||||
* @return a <code>MethodInvocation</code>, or <code>null</code> if there was a problem
|
||||
*/
|
||||
public static MethodInvocation createFromClass(Class clazz, String methodName, Class[] args) {
|
||||
public static MethodInvocation createFromClass(Class clazz, String methodName, Class[] classArgs, Object[] args) {
|
||||
Assert.notNull(clazz, "Class required");
|
||||
Assert.hasText(methodName, "MethodName required");
|
||||
|
||||
Method method;
|
||||
|
||||
try {
|
||||
method = clazz.getMethod(methodName, args);
|
||||
method = clazz.getMethod(methodName, classArgs);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.acegisecurity.ConfigAttributeDefinition;
|
||||
import org.acegisecurity.acl.AclEntry;
|
||||
import org.acegisecurity.acl.AclManager;
|
||||
import org.acegisecurity.acl.basic.BasicAclEntry;
|
||||
import org.acegisecurity.acl.basic.SimpleAclEntry;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -143,6 +144,16 @@ public class BasicAclEntryVoter extends AbstractAclVoter implements Initializing
|
||||
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().startsWith(getProcessConfigAttribute())) {
|
||||
return true;
|
||||
|
||||
@@ -38,6 +38,7 @@ SwitchUserProcessingFilter.expired=User account has expired
|
||||
SwitchUserProcessingFilter.credentialsExpired=User credentials have expired
|
||||
AbstractAccessDecisionManager.accessDenied=Access is denied
|
||||
LdapAuthenticationProvider.emptyUsername=Empty username not allowed
|
||||
LdapAuthenticationProvider.emptyPassword=Bad credentials
|
||||
DefaultIntitalDirContextFactory.communicationFailure=Unable to connect to LDAP server
|
||||
DefaultIntitalDirContextFactory.badCredentials=Bad credentials
|
||||
DefaultIntitalDirContextFactory.unexpectedException=Failed to obtain InitialDirContext due to unexpected exception
|
||||
|
||||
@@ -66,8 +66,9 @@ public class SecurityConfigTests extends TestCase {
|
||||
SecurityConfig security2 = new SecurityConfig("TEST");
|
||||
assertEquals(security1, security2);
|
||||
|
||||
// SEC-311: Must observe symmetry requirement of Object.equals(Object) contract
|
||||
String securityString1 = "TEST";
|
||||
assertEquals(security1, securityString1);
|
||||
assertNotSame(security1, securityString1);
|
||||
|
||||
String securityString2 = "NOT_EQUAL";
|
||||
assertTrue(!security1.equals(securityString2));
|
||||
|
||||
@@ -17,7 +17,6 @@ package org.acegisecurity.acl.basic;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link SimpleAclEntry}.
|
||||
*
|
||||
@@ -171,4 +170,38 @@ public class SimpleAclEntryTests extends TestCase {
|
||||
acl.addPermissions(new int[] {SimpleAclEntry.READ, SimpleAclEntry.WRITE, SimpleAclEntry.CREATE});
|
||||
assertTrue(acl.toString().endsWith("marissa=-RWC- ............................111. (14)]"));
|
||||
}
|
||||
|
||||
public void testParsePermission() {
|
||||
assertPermission("NOTHING", SimpleAclEntry.NOTHING);
|
||||
assertPermission("ADMINISTRATION", SimpleAclEntry.ADMINISTRATION);
|
||||
assertPermission("READ", SimpleAclEntry.READ);
|
||||
assertPermission("WRITE", SimpleAclEntry.WRITE);
|
||||
assertPermission("CREATE", SimpleAclEntry.CREATE);
|
||||
assertPermission("DELETE", SimpleAclEntry.DELETE);
|
||||
assertPermission("READ_WRITE_DELETE", SimpleAclEntry.READ_WRITE_DELETE);
|
||||
}
|
||||
|
||||
public void testParsePermissionWrongValues() {
|
||||
try {
|
||||
SimpleAclEntry.parsePermission("X");
|
||||
fail(IllegalArgumentException.class.getName() + " must have been thrown.");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
private void assertPermission(String permission, int value) {
|
||||
assertEquals(value, SimpleAclEntry.parsePermission(permission));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the value returned by {@link SimpleAclEntry#getValidPermissions()} is not modifiable.
|
||||
*/
|
||||
public void testGetPermissions() {
|
||||
SimpleAclEntry acl = new SimpleAclEntry("", new NamedEntityObjectIdentity("x", "x"), null, 0);
|
||||
int[] permissions = acl.getValidPermissions();
|
||||
int i = permissions[0];
|
||||
permissions[0] -= 100;
|
||||
assertEquals("Value returned by getValidPermissions can be modified", i, acl.getValidPermissions()[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,22 +16,19 @@
|
||||
package org.acegisecurity.concurrent;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.mock.web.MockFilterConfig;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
@@ -72,7 +69,7 @@ public class ConcurrentSessionFilterTests extends TestCase {
|
||||
request.setSession(session);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
MockFilterConfig config = new MockFilterConfig(null);
|
||||
MockFilterConfig config = new MockFilterConfig(null, null);
|
||||
|
||||
// Setup our expectation that the filter chain will not be invoked, as we redirect to expiredUrl
|
||||
MockFilterChain chain = new MockFilterChain(false);
|
||||
@@ -122,7 +119,7 @@ public class ConcurrentSessionFilterTests extends TestCase {
|
||||
request.setSession(session);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
MockFilterConfig config = new MockFilterConfig(null);
|
||||
MockFilterConfig config = new MockFilterConfig(null, null);
|
||||
|
||||
// Setup our expectation that the filter chain will be invoked, as our session hasn't expired
|
||||
MockFilterChain chain = new MockFilterChain(true);
|
||||
|
||||
+2
-1
@@ -190,7 +190,8 @@ public class HttpSessionContextIntegrationFilterTests extends TestCase {
|
||||
// Prepare filter
|
||||
HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter();
|
||||
filter.setContext(SecurityContextImpl.class);
|
||||
filter.afterPropertiesSet();
|
||||
// don't call afterPropertiesSet to test case when not instantiated by Spring
|
||||
//filter.afterPropertiesSet();
|
||||
|
||||
// Execute filter
|
||||
executeFilterInContainerSimulator(new MockFilterConfig(), filter, request, response, chain);
|
||||
|
||||
@@ -240,8 +240,8 @@ public class SecurityContextHolderTests extends TestCase {
|
||||
|
||||
public void testSynchronizationCustomStrategyLoading() {
|
||||
SecurityContextHolder.setStrategyName(InheritableThreadLocalSecurityContextHolderStrategy.class.getName());
|
||||
assertEquals("SecurityContextHolder[strategy='org.acegisecurity.context.InheritableThreadLocalSecurityContextHolderStrategy']",
|
||||
new SecurityContextHolder().toString());
|
||||
assertTrue(new SecurityContextHolder().toString()
|
||||
.lastIndexOf("SecurityContextHolder[strategy='org.acegisecurity.context.InheritableThreadLocalSecurityContextHolderStrategy'") != -1);
|
||||
loadStartAndWaitForThreads(true, "Main_", 10, false, true);
|
||||
assertEquals("Thread errors detected; review log output for details", 0, errors);
|
||||
}
|
||||
|
||||
+2
-2
@@ -89,7 +89,7 @@ public class MethodInvocationPrivilegeEvaluatorTests extends TestCase {
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_LOWER")});
|
||||
MethodInvocation mi = MethodInvocationUtils.createFromClass(ITargetObject.class, "makeLowerCase",
|
||||
new Class[] {String.class});
|
||||
new Class[] {String.class}, new Object[] {"Hello world"});
|
||||
MethodSecurityInterceptor interceptor = makeSecurityInterceptor();
|
||||
|
||||
MethodInvocationPrivilegeEvaluator mipe = new MethodInvocationPrivilegeEvaluator();
|
||||
@@ -118,7 +118,7 @@ public class MethodInvocationPrivilegeEvaluatorTests extends TestCase {
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_NOT_HELD")});
|
||||
MethodInvocation mi = MethodInvocationUtils.createFromClass(ITargetObject.class, "makeLowerCase",
|
||||
new Class[] {String.class});
|
||||
new Class[] {String.class}, new Object[] {"helloWorld"});
|
||||
MethodSecurityInterceptor interceptor = makeSecurityInterceptor();
|
||||
|
||||
MethodInvocationPrivilegeEvaluator mipe = new MethodInvocationPrivilegeEvaluator();
|
||||
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
/* 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.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.acegisecurity.ConfigAttributeDefinition;
|
||||
import org.acegisecurity.SecurityConfig;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Test for {@link FilterInvocationDefinitionDecorator}
|
||||
*
|
||||
* @author <a href="mailto:carlos@apache.org">Carlos Sanchez</a>
|
||||
* @version $Id$
|
||||
*/
|
||||
public class FilterInvocationDefinitionDecoratorTest extends TestCase {
|
||||
|
||||
private FilterInvocationDefinitionDecorator decorator;
|
||||
|
||||
private FilterInvocationDefinition decorated;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
decorated = new MockFilterInvocationDefinition();
|
||||
decorator = new FilterInvocationDefinitionDecorator(decorated);
|
||||
}
|
||||
|
||||
public void testFilterInvocationDefinitionMapDecorator() {
|
||||
decorator = new FilterInvocationDefinitionDecorator();
|
||||
decorator.setDecorated(decorated);
|
||||
assertEquals(decorated, decorator.getDecorated());
|
||||
}
|
||||
|
||||
public void testSetMappings() {
|
||||
List roles = new ArrayList();
|
||||
roles.add("ROLE_USER");
|
||||
roles.add("ROLE_ADMIN");
|
||||
|
||||
FilterInvocationDefinitionSourceMapping mapping = new FilterInvocationDefinitionSourceMapping();
|
||||
mapping.setUrl("/secure/**");
|
||||
mapping.setConfigAttributes(roles);
|
||||
|
||||
List mappings = new ArrayList();
|
||||
mappings.add(mapping);
|
||||
|
||||
decorator.setMappings(mappings);
|
||||
|
||||
ConfigAttributeDefinition configDefinition = new ConfigAttributeDefinition();
|
||||
Iterator it = roles.iterator();
|
||||
while (it.hasNext()) {
|
||||
String role = (String) it.next();
|
||||
configDefinition.addConfigAttribute(new SecurityConfig(role));
|
||||
}
|
||||
|
||||
it = decorator.getConfigAttributeDefinitions();
|
||||
int i = 0;
|
||||
while (it.hasNext()) {
|
||||
i++;
|
||||
assertEquals(configDefinition, it.next());
|
||||
}
|
||||
assertEquals(1, i);
|
||||
|
||||
assertEquals(mappings, decorator.getMappings());
|
||||
}
|
||||
}
|
||||
+29
-3
@@ -30,17 +30,16 @@ import org.acegisecurity.MockAuthenticationManager;
|
||||
import org.acegisecurity.MockRunAsManager;
|
||||
import org.acegisecurity.RunAsManager;
|
||||
import org.acegisecurity.SecurityConfig;
|
||||
|
||||
import org.acegisecurity.context.SecurityContextHolder;
|
||||
|
||||
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
@@ -231,6 +230,33 @@ public class FilterSecurityInterceptorTests extends TestCase {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
public void testNotLoadedFromApplicationContext() throws Exception {
|
||||
FilterInvocationDefinitionSourceMapping mapping = new FilterInvocationDefinitionSourceMapping();
|
||||
mapping.setUrl("/secure/**");
|
||||
mapping.addConfigAttribute("ROLE_USER");
|
||||
|
||||
List mappings = new ArrayList(1);
|
||||
mappings.add(mapping);
|
||||
|
||||
PathBasedFilterInvocationDefinitionMap filterInvocationDefinitionSource = new PathBasedFilterInvocationDefinitionMap();
|
||||
filterInvocationDefinitionSource
|
||||
.setConvertUrlToLowercaseBeforeComparison(true);
|
||||
FilterInvocationDefinitionDecorator decorator = new FilterInvocationDefinitionDecorator(
|
||||
filterInvocationDefinitionSource);
|
||||
decorator.setMappings(mappings);
|
||||
|
||||
FilterSecurityInterceptor filter = new FilterSecurityInterceptor();
|
||||
filter.setObjectDefinitionSource(filterInvocationDefinitionSource);
|
||||
|
||||
MockFilterChain filterChain = new MockFilterChain();
|
||||
filterChain.expectToProceed = true;
|
||||
|
||||
FilterInvocation fi = new FilterInvocation(
|
||||
new MockHttpServletRequest(), new MockHttpServletResponse(),
|
||||
filterChain);
|
||||
filter.invoke(fi);
|
||||
}
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
private class MockFilterChain implements FilterChain {
|
||||
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/* 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.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.acegisecurity.ConfigAttributeDefinition;
|
||||
|
||||
/**
|
||||
* Mock for {@link FilterInvocationDefinitionMap}
|
||||
*
|
||||
* @author <a href="mailto:carlos@apache.org">Carlos Sanchez</a>
|
||||
* @version $Id: MockFilterInvocationDefinitionSource.java 1496 2006-05-23
|
||||
* 13:38:33Z benalex $
|
||||
*/
|
||||
public class MockFilterInvocationDefinition implements FilterInvocationDefinition {
|
||||
|
||||
private Map secureUrls = new HashMap();
|
||||
|
||||
private boolean convertUrlToLowercaseBeforeComparison = false;
|
||||
|
||||
public void addSecureUrl(String expression, ConfigAttributeDefinition attr) {
|
||||
secureUrls.put(expression, attr);
|
||||
}
|
||||
|
||||
public boolean isConvertUrlToLowercaseBeforeComparison() {
|
||||
return convertUrlToLowercaseBeforeComparison;
|
||||
}
|
||||
|
||||
public void setConvertUrlToLowercaseBeforeComparison(boolean convertUrlToLowercaseBeforeComparison) {
|
||||
this.convertUrlToLowercaseBeforeComparison = convertUrlToLowercaseBeforeComparison;
|
||||
}
|
||||
|
||||
public ConfigAttributeDefinition getSecureUrl(String expression) {
|
||||
return (ConfigAttributeDefinition) secureUrls.get(expression);
|
||||
}
|
||||
|
||||
public ConfigAttributeDefinition getAttributes(Object object) throws IllegalArgumentException {
|
||||
return (ConfigAttributeDefinition) secureUrls.get(object);
|
||||
}
|
||||
|
||||
public Iterator getConfigAttributeDefinitions() {
|
||||
return secureUrls.values().iterator();
|
||||
}
|
||||
|
||||
public boolean supports(Class clazz) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -24,7 +24,7 @@ import java.util.Vector;
|
||||
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
* Mock for {@link FilterInvocationDefinitionSource}
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
|
||||
+33
-40
@@ -45,14 +45,6 @@ public class PathBasedFilterDefinitionMapTests extends TestCase {
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(PathBasedFilterDefinitionMapTests.class);
|
||||
}
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public void testConvertUrlToLowercaseIsFalseByDefault() {
|
||||
PathBasedFilterInvocationDefinitionMap map = new PathBasedFilterInvocationDefinitionMap();
|
||||
assertFalse(map.isConvertUrlToLowercaseBeforeComparison());
|
||||
@@ -73,14 +65,7 @@ public class PathBasedFilterDefinitionMapTests extends TestCase {
|
||||
def.addConfigAttribute(new SecurityConfig("ROLE_ONE"));
|
||||
map.addSecureUrl("/secure/super/**", def);
|
||||
|
||||
// Build a HTTP request
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI(null);
|
||||
|
||||
MockHttpServletRequest req = request;
|
||||
req.setServletPath("/SeCuRE/super/somefile.html");
|
||||
|
||||
FilterInvocation fi = new FilterInvocation(req, new MockHttpServletResponse(), new MockFilterChain());
|
||||
FilterInvocation fi = createFilterinvocation("/SeCuRE/super/somefile.html");
|
||||
|
||||
ConfigAttributeDefinition response = map.lookupAttributes(fi.getRequestUrl());
|
||||
assertEquals(def, response);
|
||||
@@ -94,14 +79,7 @@ public class PathBasedFilterDefinitionMapTests extends TestCase {
|
||||
def.addConfigAttribute(new SecurityConfig("ROLE_ONE"));
|
||||
map.addSecureUrl("/secure/super/**", def);
|
||||
|
||||
// Build a HTTP request
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI(null);
|
||||
|
||||
MockHttpServletRequest req = request;
|
||||
req.setServletPath("/SeCuRE/super/somefile.html");
|
||||
|
||||
FilterInvocation fi = new FilterInvocation(req, new MockHttpServletResponse(), new MockFilterChain());
|
||||
FilterInvocation fi = createFilterinvocation("/SeCuRE/super/somefile.html");
|
||||
|
||||
ConfigAttributeDefinition response = map.lookupAttributes(fi.getRequestUrl());
|
||||
assertEquals(null, response);
|
||||
@@ -115,14 +93,7 @@ public class PathBasedFilterDefinitionMapTests extends TestCase {
|
||||
def.addConfigAttribute(new SecurityConfig("ROLE_ONE"));
|
||||
map.addSecureUrl("/secure/super/**", def);
|
||||
|
||||
// Build a HTTP request
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI(null);
|
||||
|
||||
MockHttpServletRequest req = request;
|
||||
req.setServletPath("/secure/super/somefile.html");
|
||||
|
||||
FilterInvocation fi = new FilterInvocation(req, new MockHttpServletResponse(), new MockFilterChain());
|
||||
FilterInvocation fi = createFilterinvocation("/secure/super/somefile.html");
|
||||
|
||||
ConfigAttributeDefinition response = map.lookupAttributes(fi.getRequestUrl());
|
||||
assertEquals(def, response);
|
||||
@@ -136,16 +107,38 @@ public class PathBasedFilterDefinitionMapTests extends TestCase {
|
||||
def.addConfigAttribute(new SecurityConfig("ROLE_ONE"));
|
||||
map.addSecureUrl("/someAdminPage.html**", def);
|
||||
|
||||
// Build a HTTP request
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI(null);
|
||||
|
||||
MockHttpServletRequest req = request;
|
||||
req.setServletPath("/someAdminPage.html?a=/test");
|
||||
|
||||
FilterInvocation fi = new FilterInvocation(req, new MockHttpServletResponse(), new MockFilterChain());
|
||||
FilterInvocation fi = createFilterinvocation("/someAdminPage.html?a=/test");
|
||||
|
||||
ConfigAttributeDefinition response = map.lookupAttributes(fi.getRequestUrl());
|
||||
assertEquals(def, response); // see SEC-161 (it should truncate after ? sign)
|
||||
}
|
||||
|
||||
/** Check fixes for SEC-321 */
|
||||
public void testExtraQuestionMarkStillMatches() {
|
||||
PathBasedFilterInvocationDefinitionMap map = new PathBasedFilterInvocationDefinitionMap();
|
||||
assertFalse(map.isConvertUrlToLowercaseBeforeComparison());
|
||||
|
||||
ConfigAttributeDefinition def = new ConfigAttributeDefinition();
|
||||
def.addConfigAttribute(new SecurityConfig("ROLE_ONE"));
|
||||
map.addSecureUrl("/someAdminPage.html*", def);
|
||||
|
||||
FilterInvocation fi = createFilterinvocation("/someAdminPage.html?x=2/aa?y=3");
|
||||
|
||||
ConfigAttributeDefinition response = map.lookupAttributes(fi.getRequestUrl());
|
||||
assertEquals(def, response);
|
||||
|
||||
fi = createFilterinvocation("/someAdminPage.html??");
|
||||
|
||||
response = map.lookupAttributes(fi.getRequestUrl());
|
||||
assertEquals(def, response);
|
||||
}
|
||||
|
||||
private FilterInvocation createFilterinvocation(String path) {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI(null);
|
||||
|
||||
request.setServletPath(path);
|
||||
|
||||
return new FilterInvocation(request, new MockHttpServletResponse(), new MockFilterChain());
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -341,7 +341,7 @@ public class DaoAuthenticationProviderTests extends TestCase {
|
||||
provider.authenticate(token);
|
||||
fail("Should have thrown AuthenticationServiceException");
|
||||
} catch (AuthenticationServiceException expected) {
|
||||
assertEquals("AuthenticationDao returned null, which is an interface contract violation",
|
||||
assertEquals("UserDetailsService returned null, which is an interface contract violation",
|
||||
expected.getMessage());
|
||||
}
|
||||
}
|
||||
@@ -417,10 +417,10 @@ public class DaoAuthenticationProviderTests extends TestCase {
|
||||
|
||||
public void testStartupSuccess() throws Exception {
|
||||
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
|
||||
UserDetailsService dao = new MockAuthenticationDaoUserMarissa();
|
||||
provider.setUserDetailsService(dao);
|
||||
UserDetailsService userDetailsService = new MockAuthenticationDaoUserMarissa();
|
||||
provider.setUserDetailsService(userDetailsService);
|
||||
provider.setUserCache(new MockUserCache());
|
||||
assertEquals(dao, provider.getUserDetailsService());
|
||||
assertEquals(userDetailsService, provider.getUserDetailsService());
|
||||
provider.afterPropertiesSet();
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
+10
-3
@@ -23,6 +23,7 @@ import junit.framework.TestCase;
|
||||
*
|
||||
* @author colin sampaleanu
|
||||
* @author Ben Alex
|
||||
* @author Ray Krueger
|
||||
* @version $Id$
|
||||
*/
|
||||
public class Md5PasswordEncoderTests extends TestCase {
|
||||
@@ -36,11 +37,17 @@ public class Md5PasswordEncoderTests extends TestCase {
|
||||
String encoded = pe.encodePassword(raw, salt);
|
||||
assertTrue(pe.isPasswordValid(encoded, raw, salt));
|
||||
assertFalse(pe.isPasswordValid(encoded, badRaw, salt));
|
||||
assertTrue(encoded.length() == 32);
|
||||
assertEquals("a68aafd90299d0b137de28fb4bb68573", encoded);
|
||||
assertEquals("MD5", pe.getAlgorithm());
|
||||
}
|
||||
|
||||
// now try Base64
|
||||
public void testBase64() throws Exception {
|
||||
Md5PasswordEncoder pe = new Md5PasswordEncoder();
|
||||
pe.setEncodeHashAsBase64(true);
|
||||
encoded = pe.encodePassword(raw, salt);
|
||||
String raw = "abc123";
|
||||
String badRaw = "abc321";
|
||||
String salt = "THIS_IS_A_SALT";
|
||||
String encoded = pe.encodePassword(raw, salt);
|
||||
assertTrue(pe.isPasswordValid(encoded, raw, salt));
|
||||
assertFalse(pe.isPasswordValid(encoded, badRaw, salt));
|
||||
assertTrue(encoded.length() != 32);
|
||||
|
||||
+27
-3
@@ -23,6 +23,7 @@ import junit.framework.TestCase;
|
||||
*
|
||||
* @author colin sampaleanu
|
||||
* @author Ben Alex
|
||||
* @author Ray Krueger
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ShaPasswordEncoderTests extends TestCase {
|
||||
@@ -36,13 +37,36 @@ public class ShaPasswordEncoderTests extends TestCase {
|
||||
String encoded = pe.encodePassword(raw, salt);
|
||||
assertTrue(pe.isPasswordValid(encoded, raw, salt));
|
||||
assertFalse(pe.isPasswordValid(encoded, badRaw, salt));
|
||||
assertTrue(encoded.length() == 40);
|
||||
assertEquals("b2f50ffcbd3407fe9415c062d55f54731f340d32", encoded);
|
||||
|
||||
// now try Base64
|
||||
}
|
||||
|
||||
public void testBase64() throws Exception {
|
||||
ShaPasswordEncoder pe = new ShaPasswordEncoder();
|
||||
pe.setEncodeHashAsBase64(true);
|
||||
encoded = pe.encodePassword(raw, salt);
|
||||
String raw = "abc123";
|
||||
String badRaw = "abc321";
|
||||
String salt = "THIS_IS_A_SALT";
|
||||
String encoded = pe.encodePassword(raw, salt);
|
||||
assertTrue(pe.isPasswordValid(encoded, raw, salt));
|
||||
assertFalse(pe.isPasswordValid(encoded, badRaw, salt));
|
||||
assertTrue(encoded.length() != 40);
|
||||
}
|
||||
|
||||
public void test256() throws Exception {
|
||||
ShaPasswordEncoder pe = new ShaPasswordEncoder(256);
|
||||
String encoded = pe.encodePassword("abc123", null);
|
||||
assertEquals("6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090", encoded);
|
||||
String encodedWithSalt = pe.encodePassword("abc123", "THIS_IS_A_SALT");
|
||||
assertEquals("4b79b7de23eb23b78cc5ede227d532b8a51f89b2ec166f808af76b0dbedc47d7", encodedWithSalt);
|
||||
}
|
||||
|
||||
public void testInvalidStrength() throws Exception {
|
||||
try {
|
||||
new ShaPasswordEncoder(666);
|
||||
fail("IllegalArgumentException expected");
|
||||
} catch (IllegalArgumentException e) {
|
||||
//expected
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+21
-7
@@ -34,8 +34,7 @@ import javax.naming.directory.BasicAttributes;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
DOCUMENT ME!
|
||||
* Tests {@link LdapAuthenticationProvider}.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
@@ -86,11 +85,20 @@ public class LdapAuthenticationProviderTests extends TestCase {
|
||||
} catch (BadCredentialsException expected) {}
|
||||
}
|
||||
|
||||
public void testEmptyPasswordIsRejected() {
|
||||
LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider(new MockAuthenticator(),
|
||||
new MockAuthoritiesPopulator());
|
||||
try {
|
||||
ldapProvider.retrieveUser("jen", new UsernamePasswordAuthenticationToken("jen", ""));
|
||||
fail("Expected BadCredentialsException for empty password");
|
||||
} catch (BadCredentialsException expected) {}
|
||||
}
|
||||
|
||||
public void testNormalUsage() {
|
||||
LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider(new MockAuthenticator(),
|
||||
new MockAuthoritiesPopulator());
|
||||
|
||||
assertNotNull(ldapProvider.getAuthoritiesPoulator());
|
||||
assertNotNull(ldapProvider.getAuthoritiesPopulator());
|
||||
|
||||
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken("bob", "bobspassword");
|
||||
UserDetails user = ldapProvider.retrieveUser("bob", authRequest);
|
||||
@@ -114,17 +122,23 @@ public class LdapAuthenticationProviderTests extends TestCase {
|
||||
Attributes userAttributes = new BasicAttributes("cn", "bob");
|
||||
|
||||
public LdapUserDetails authenticate(String username, String password) {
|
||||
LdapUserDetailsImpl.Essence userEssence = new LdapUserDetailsImpl.Essence();
|
||||
userEssence.setPassword("{SHA}anencodedpassword");
|
||||
userEssence.setAttributes(userAttributes);
|
||||
|
||||
if (username.equals("bob") && password.equals("bobspassword")) {
|
||||
LdapUserDetailsImpl.Essence userEssence = new LdapUserDetailsImpl.Essence();
|
||||
userEssence.setDn("cn=bob,ou=people,dc=acegisecurity,dc=org");
|
||||
userEssence.setPassword("{SHA}anencodedpassword");
|
||||
userEssence.setAttributes(userAttributes);
|
||||
userEssence.addAuthority(new GrantedAuthorityImpl("ROLE_FROM_ENTRY"));
|
||||
|
||||
return userEssence.createUserDetails();
|
||||
} else if (username.equals("jen") && password.equals("")) {
|
||||
userEssence.setDn("cn=jen,ou=people,dc=acegisecurity,dc=org");
|
||||
userEssence.addAuthority(new GrantedAuthorityImpl("ROLE_FROM_ENTRY"));
|
||||
|
||||
return userEssence.createUserDetails();
|
||||
}
|
||||
|
||||
throw new BadCredentialsException("Authentication of Bob failed.");
|
||||
throw new BadCredentialsException("Authentication failed.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-14
@@ -70,26 +70,12 @@ public class RememberMeAuthenticationTokenTests extends TestCase {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
try {
|
||||
new RememberMeAuthenticationToken("key", "Test", null);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
try {
|
||||
new RememberMeAuthenticationToken("key", "Test", new GrantedAuthority[] {null});
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
try {
|
||||
new RememberMeAuthenticationToken("key", "Test", new GrantedAuthority[] {});
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testEqualsWhenEqual() {
|
||||
|
||||
+430
@@ -0,0 +1,430 @@
|
||||
/* 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 java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.acegisecurity.AccountExpiredException;
|
||||
import org.acegisecurity.Authentication;
|
||||
import org.acegisecurity.AuthenticationServiceException;
|
||||
import org.acegisecurity.BadCredentialsException;
|
||||
import org.acegisecurity.CredentialsExpiredException;
|
||||
import org.acegisecurity.DisabledException;
|
||||
import org.acegisecurity.GrantedAuthority;
|
||||
import org.acegisecurity.GrantedAuthorityImpl;
|
||||
import org.acegisecurity.LockedException;
|
||||
import org.acegisecurity.providers.TestingAuthenticationToken;
|
||||
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
|
||||
import org.acegisecurity.providers.dao.UserCache;
|
||||
import org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache;
|
||||
import org.acegisecurity.providers.dao.cache.NullUserCache;
|
||||
import org.acegisecurity.userdetails.User;
|
||||
import org.acegisecurity.userdetails.UserDetails;
|
||||
import org.acegisecurity.userdetails.UserDetailsService;
|
||||
import org.acegisecurity.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataRetrievalFailureException;
|
||||
|
||||
/**
|
||||
* Tests {@link SiteminderAuthenticationProvider}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id: SiteminderAuthenticationProviderTests.java 1582 2006-07-15 15:18:51Z smccrory $
|
||||
*/
|
||||
public class SiteminderAuthenticationProviderTests extends TestCase {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(SiteminderAuthenticationProviderTests.class);
|
||||
}
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public void testAuthenticateFailsIfAccountExpired() {
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("peter", "opal");
|
||||
|
||||
SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
|
||||
provider.setUserDetailsService(new MockUserDetailsServiceUserPeterAccountExpired());
|
||||
provider.setUserCache(new MockUserCache());
|
||||
|
||||
try {
|
||||
provider.authenticate(token);
|
||||
fail("Should have thrown AccountExpiredException");
|
||||
} catch (AccountExpiredException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testAuthenticateFailsIfAccountLocked() {
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("peter", "opal");
|
||||
|
||||
SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
|
||||
provider.setUserDetailsService(new MockUserDetailsServiceUserPeterAccountLocked());
|
||||
provider.setUserCache(new MockUserCache());
|
||||
|
||||
try {
|
||||
provider.authenticate(token);
|
||||
fail("Should have thrown LockedException");
|
||||
} catch (LockedException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testAuthenticateFailsIfCredentialsExpired() {
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("peter", "opal");
|
||||
|
||||
SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
|
||||
provider.setUserDetailsService(new MockUserDetailsServiceUserPeterCredentialsExpired());
|
||||
provider.setUserCache(new MockUserCache());
|
||||
|
||||
try {
|
||||
provider.authenticate(token);
|
||||
fail("Should have thrown CredentialsExpiredException");
|
||||
} catch (CredentialsExpiredException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void testAuthenticateFailsIfUserDisabled() {
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("peter", "opal");
|
||||
|
||||
SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
|
||||
provider.setUserDetailsService(new MockUserDetailsServiceUserPeter());
|
||||
provider.setUserCache(new MockUserCache());
|
||||
|
||||
try {
|
||||
provider.authenticate(token);
|
||||
fail("Should have thrown DisabledException");
|
||||
} catch (DisabledException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testAuthenticateFailsWhenUserDetailsServiceHasBackendFailure() {
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa", "koala");
|
||||
|
||||
SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
|
||||
provider.setUserDetailsService(new MockUserDetailsServiceSimulateBackendError());
|
||||
provider.setUserCache(new MockUserCache());
|
||||
|
||||
try {
|
||||
provider.authenticate(token);
|
||||
fail("Should have thrown AuthenticationServiceException");
|
||||
} catch (AuthenticationServiceException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testAuthenticateFailsWithEmptyUsername() {
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(null, "koala");
|
||||
|
||||
SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
|
||||
provider.setUserDetailsService(new MockUserDetailsServiceUserMarissa());
|
||||
provider.setUserCache(new MockUserCache());
|
||||
|
||||
try {
|
||||
provider.authenticate(token);
|
||||
fail("Should have thrown BadCredentialsException");
|
||||
} catch (BadCredentialsException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testAuthenticateFailsWithInvalidUsernameAndHideUserNotFoundExceptionFalse() {
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("INVALID_USER", "koala");
|
||||
|
||||
SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
|
||||
provider.setHideUserNotFoundExceptions(false); // we want UsernameNotFoundExceptions
|
||||
provider.setUserDetailsService(new MockUserDetailsServiceUserMarissa());
|
||||
provider.setUserCache(new MockUserCache());
|
||||
|
||||
try {
|
||||
provider.authenticate(token);
|
||||
fail("Should have thrown UsernameNotFoundException");
|
||||
} catch (UsernameNotFoundException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testAuthenticateFailsWithInvalidUsernameAndHideUserNotFoundExceptionsWithDefaultOfTrue() {
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("INVALID_USER", "koala");
|
||||
|
||||
SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
|
||||
assertTrue(provider.isHideUserNotFoundExceptions());
|
||||
provider.setUserDetailsService(new MockUserDetailsServiceUserMarissa());
|
||||
provider.setUserCache(new MockUserCache());
|
||||
|
||||
try {
|
||||
provider.authenticate(token);
|
||||
fail("Should have thrown BadCredentialsException");
|
||||
} catch (BadCredentialsException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testAuthenticateFailsWithMixedCaseUsernameIfDefaultChanged() {
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("MaRiSSA", "koala");
|
||||
|
||||
SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
|
||||
provider.setUserDetailsService(new MockUserDetailsServiceUserMarissa());
|
||||
provider.setUserCache(new MockUserCache());
|
||||
|
||||
try {
|
||||
provider.authenticate(token);
|
||||
fail("Should have thrown BadCredentialsException");
|
||||
} catch (BadCredentialsException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testAuthenticates() {
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa", "koala");
|
||||
token.setDetails("192.168.0.1");
|
||||
|
||||
SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
|
||||
provider.setUserDetailsService(new MockUserDetailsServiceUserMarissa());
|
||||
provider.setUserCache(new MockUserCache());
|
||||
|
||||
Authentication result = provider.authenticate(token);
|
||||
|
||||
if (!(result instanceof UsernamePasswordAuthenticationToken)) {
|
||||
fail("Should have returned instance of UsernamePasswordAuthenticationToken");
|
||||
}
|
||||
|
||||
UsernamePasswordAuthenticationToken castResult = (UsernamePasswordAuthenticationToken) result;
|
||||
assertEquals(User.class, castResult.getPrincipal().getClass());
|
||||
assertEquals("koala", castResult.getCredentials());
|
||||
assertEquals("ROLE_ONE", castResult.getAuthorities()[0].getAuthority());
|
||||
assertEquals("ROLE_TWO", castResult.getAuthorities()[1].getAuthority());
|
||||
assertEquals("192.168.0.1", castResult.getDetails());
|
||||
}
|
||||
|
||||
public void testAuthenticatesASecondTime() {
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa", "koala");
|
||||
|
||||
SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
|
||||
provider.setUserDetailsService(new MockUserDetailsServiceUserMarissa());
|
||||
provider.setUserCache(new MockUserCache());
|
||||
|
||||
Authentication result = provider.authenticate(token);
|
||||
|
||||
if (!(result instanceof UsernamePasswordAuthenticationToken)) {
|
||||
fail("Should have returned instance of UsernamePasswordAuthenticationToken");
|
||||
}
|
||||
|
||||
// Now try to authenticate with the previous result (with its UserDetails)
|
||||
Authentication result2 = provider.authenticate(result);
|
||||
|
||||
if (!(result2 instanceof UsernamePasswordAuthenticationToken)) {
|
||||
fail("Should have returned instance of UsernamePasswordAuthenticationToken");
|
||||
}
|
||||
|
||||
assertEquals(result.getCredentials(), result2.getCredentials());
|
||||
}
|
||||
|
||||
public void testAuthenticatesWithForcePrincipalAsString() {
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa", "koala");
|
||||
|
||||
SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
|
||||
provider.setUserDetailsService(new MockUserDetailsServiceUserMarissa());
|
||||
provider.setUserCache(new MockUserCache());
|
||||
provider.setForcePrincipalAsString(true);
|
||||
|
||||
Authentication result = provider.authenticate(token);
|
||||
|
||||
if (!(result instanceof UsernamePasswordAuthenticationToken)) {
|
||||
fail("Should have returned instance of UsernamePasswordAuthenticationToken");
|
||||
}
|
||||
|
||||
UsernamePasswordAuthenticationToken castResult = (UsernamePasswordAuthenticationToken) result;
|
||||
assertEquals(String.class, castResult.getPrincipal().getClass());
|
||||
assertEquals("marissa", castResult.getPrincipal());
|
||||
}
|
||||
|
||||
public void testDetectsNullBeingReturnedFromUserDetailsService() {
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa", "koala");
|
||||
|
||||
SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
|
||||
provider.setUserDetailsService(new MockUserDetailsServiceReturnsNull());
|
||||
|
||||
try {
|
||||
provider.authenticate(token);
|
||||
fail("Should have thrown AuthenticationServiceException");
|
||||
} catch (AuthenticationServiceException expected) {
|
||||
assertEquals("UserDetailsService returned null, which is an interface contract violation", expected
|
||||
.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testGettersSetters() {
|
||||
SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
|
||||
|
||||
provider.setUserCache(new EhCacheBasedUserCache());
|
||||
assertEquals(EhCacheBasedUserCache.class, provider.getUserCache().getClass());
|
||||
|
||||
assertFalse(provider.isForcePrincipalAsString());
|
||||
provider.setForcePrincipalAsString(true);
|
||||
assertTrue(provider.isForcePrincipalAsString());
|
||||
}
|
||||
|
||||
public void testStartupFailsIfNoUserDetailsService() throws Exception {
|
||||
SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
|
||||
|
||||
try {
|
||||
provider.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testStartupFailsIfNoUserCacheSet() throws Exception {
|
||||
SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
|
||||
provider.setUserDetailsService(new MockUserDetailsServiceUserMarissa());
|
||||
assertEquals(NullUserCache.class, provider.getUserCache().getClass());
|
||||
provider.setUserCache(null);
|
||||
|
||||
try {
|
||||
provider.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testStartupSuccess() throws Exception {
|
||||
SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
|
||||
UserDetailsService userDetailsService = new MockUserDetailsServiceUserMarissa();
|
||||
provider.setUserDetailsService(userDetailsService);
|
||||
provider.setUserCache(new MockUserCache());
|
||||
assertEquals(userDetailsService, provider.getUserDetailsService());
|
||||
provider.afterPropertiesSet();
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
public void testSupports() {
|
||||
SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
|
||||
assertTrue(provider.supports(UsernamePasswordAuthenticationToken.class));
|
||||
assertTrue(!provider.supports(TestingAuthenticationToken.class));
|
||||
}
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
private class MockUserDetailsServiceReturnsNull implements UserDetailsService {
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private class MockUserDetailsServiceSimulateBackendError implements UserDetailsService {
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
|
||||
throw new DataRetrievalFailureException("This mock simulator is designed to fail");
|
||||
}
|
||||
}
|
||||
|
||||
private class MockUserDetailsServiceUserMarissa implements UserDetailsService {
|
||||
private String password = "koala";
|
||||
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
|
||||
if ("marissa".equals(username)) {
|
||||
return new User("marissa", password, true, true, true, true, new GrantedAuthority[] {
|
||||
new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO") });
|
||||
} else {
|
||||
throw new UsernameNotFoundException("Could not find: " + username);
|
||||
}
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
}
|
||||
|
||||
private class MockUserDetailsServiceUserMarissaWithSalt implements UserDetailsService {
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
|
||||
if ("marissa".equals(username)) {
|
||||
return new User("marissa", "koala{SYSTEM_SALT_VALUE}", true, true, true, true, new GrantedAuthority[] {
|
||||
new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO") });
|
||||
} else {
|
||||
throw new UsernameNotFoundException("Could not find: " + username);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MockUserDetailsServiceUserPeter implements UserDetailsService {
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
|
||||
if ("peter".equals(username)) {
|
||||
return new User("peter", "opal", false, true, true, true, new GrantedAuthority[] {
|
||||
new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO") });
|
||||
} else {
|
||||
throw new UsernameNotFoundException("Could not find: " + username);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MockUserDetailsServiceUserPeterAccountExpired implements UserDetailsService {
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
|
||||
if ("peter".equals(username)) {
|
||||
return new User("peter", "opal", true, false, true, true, new GrantedAuthority[] {
|
||||
new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO") });
|
||||
} else {
|
||||
throw new UsernameNotFoundException("Could not find: " + username);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MockUserDetailsServiceUserPeterAccountLocked implements UserDetailsService {
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
|
||||
if ("peter".equals(username)) {
|
||||
return new User("peter", "opal", true, true, true, false, new GrantedAuthority[] {
|
||||
new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO") });
|
||||
} else {
|
||||
throw new UsernameNotFoundException("Could not find: " + username);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MockUserDetailsServiceUserPeterCredentialsExpired implements UserDetailsService {
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
|
||||
if ("peter".equals(username)) {
|
||||
return new User("peter", "opal", true, true, false, true, new GrantedAuthority[] {
|
||||
new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO") });
|
||||
} else {
|
||||
throw new UsernameNotFoundException("Could not find: " + username);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MockUserCache implements UserCache {
|
||||
private Map cache = new HashMap();
|
||||
|
||||
public UserDetails getUserFromCache(String username) {
|
||||
return (User) cache.get(username);
|
||||
}
|
||||
|
||||
public void putUserInCache(UserDetails user) {
|
||||
cache.put(user.getUsername(), user);
|
||||
}
|
||||
|
||||
public void removeUserFromCache(String username) {
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -197,13 +197,13 @@ public class ChannelDecisionManagerImplTests extends TestCase {
|
||||
Iterator iter = config.getConfigAttributes();
|
||||
|
||||
if (failIfCalled) {
|
||||
fail("Should not have called this channel processor");
|
||||
fail("Should not have called this channel processor: " + configAttribute);
|
||||
}
|
||||
|
||||
while (iter.hasNext()) {
|
||||
ConfigAttribute attr = (ConfigAttribute) iter.next();
|
||||
|
||||
if (attr.equals(configAttribute)) {
|
||||
if (attr.getAttribute().equals(configAttribute)) {
|
||||
invocation.getHttpResponse().sendRedirect("/redirected");
|
||||
|
||||
return;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user