Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1bc1196baa | |||
| 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 |
+3
-3
@@ -33,8 +33,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 +76,7 @@
|
||||
<classpathentry kind="var" path="MAVEN_REPO/org.apache.directory.shared/jars/shared-ldap-0.9.5.jar"/>
|
||||
<classpathentry kind="var" path="MAVEN_REPO/antlr/jars/antlr-2.7.2.jar"/>
|
||||
<classpathentry kind="var" path="MAVEN_REPO/ldapsdk/jars/ldapsdk-4.1.jar"/>
|
||||
<classpathentry 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.0.1</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.0.1</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.0.1</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.0.1</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>
|
||||
+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.0.1</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>
|
||||
@@ -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.0.1</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>
|
||||
+15
-7
@@ -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.0.1</version>
|
||||
</parent>
|
||||
<artifactId>acegi-security-tiger</artifactId>
|
||||
<name>Acegi Security System for Spring - Java 5 (Tiger)</name>
|
||||
@@ -19,7 +16,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>1.2.6</version>
|
||||
<version>1.2.7</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
@@ -34,4 +31,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>
|
||||
+6
-9
@@ -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.0.1</version>
|
||||
</parent>
|
||||
<artifactId>acegi-security</artifactId>
|
||||
<name>Acegi Security System for Spring</name>
|
||||
@@ -14,17 +11,17 @@
|
||||
<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>
|
||||
@@ -129,4 +126,4 @@
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
</project>
|
||||
@@ -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;
|
||||
|
||||
@@ -287,8 +283,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();
|
||||
|
||||
@@ -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;
|
||||
@@ -234,8 +233,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 +243,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+70
-28
@@ -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$
|
||||
@@ -103,7 +134,7 @@ public class LdapAuthenticationProvider extends AbstractUserDetailsAuthenticatio
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
protected void additionalAuthenticationChecks(UserDetails userDetails,
|
||||
UsernamePasswordAuthenticationToken authentication)
|
||||
UsernamePasswordAuthenticationToken authentication)
|
||||
throws AuthenticationException {
|
||||
if (!userDetails.getPassword().equals(authentication.getCredentials().toString())) {
|
||||
throw new BadCredentialsException(messages.getMessage(
|
||||
@@ -157,8 +188,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 = authenticator.authenticate(username, password);
|
||||
|
||||
return createUserDetails(ldapUser, username, password);
|
||||
|
||||
} catch (DataAccessException ldapAccessFailure) {
|
||||
throw new AuthenticationServiceException(ldapAccessFailure.getMessage(), ldapAccessFailure);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
-11
@@ -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>
|
||||
*
|
||||
@@ -203,7 +201,7 @@ 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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -377,7 +386,7 @@ public abstract class AbstractProcessingFilter implements Filter, InitializingBe
|
||||
}
|
||||
|
||||
if (targetUrl == null) {
|
||||
targetUrl = request.getContextPath() + defaultTargetUrl;
|
||||
targetUrl = request.getContextPath() + getDefaultTargetUrl();
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
|
||||
@@ -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,12 +17,12 @@ 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;
|
||||
@@ -31,18 +31,15 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
|
||||
/**
|
||||
* Represents central information from a <code>HttpServletRequest</code>.<p>This class is used by {@link
|
||||
* 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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.acegisecurity.userdetails.ldap;
|
||||
|
||||
import org.acegisecurity.GrantedAuthorityImpl;
|
||||
import org.acegisecurity.GrantedAuthority;
|
||||
|
||||
import org.acegisecurity.ldap.LdapEntryMapper;
|
||||
|
||||
@@ -71,20 +72,20 @@ public class LdapUserDetailsMapper implements LdapEntryMapper {
|
||||
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 +93,28 @@ public class LdapUserDetailsMapper implements LdapEntryMapper {
|
||||
return essence;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
+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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+20
-6
@@ -34,8 +34,7 @@ import javax.naming.directory.BasicAttributes;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
DOCUMENT ME!
|
||||
* Tests {@link LdapAuthenticationProvider}.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
@@ -86,6 +85,15 @@ 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());
|
||||
@@ -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.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
package org.acegisecurity.ui;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.acegisecurity.AccountExpiredException;
|
||||
import org.acegisecurity.Authentication;
|
||||
import org.acegisecurity.AuthenticationException;
|
||||
@@ -24,24 +23,15 @@ import org.acegisecurity.BadCredentialsException;
|
||||
import org.acegisecurity.GrantedAuthority;
|
||||
import org.acegisecurity.GrantedAuthorityImpl;
|
||||
import org.acegisecurity.MockAuthenticationManager;
|
||||
|
||||
import org.acegisecurity.context.SecurityContextHolder;
|
||||
|
||||
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
|
||||
|
||||
import org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices;
|
||||
import org.acegisecurity.ui.savedrequest.SavedRequest;
|
||||
|
||||
import org.acegisecurity.util.PortResolverImpl;
|
||||
|
||||
import org.springframework.mock.web.MockFilterConfig;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
@@ -50,6 +40,8 @@ import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
|
||||
/**
|
||||
@@ -154,7 +146,7 @@ public class AbstractProcessingFilterTests extends TestCase {
|
||||
MockHttpServletRequest request = createMockRequest();
|
||||
|
||||
// Setup our filter configuration
|
||||
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 authenticationFailureUrl
|
||||
MockFilterChain chain = new MockFilterChain(false);
|
||||
@@ -194,7 +186,7 @@ public class AbstractProcessingFilterTests extends TestCase {
|
||||
request.setRequestURI("/mycontext/j_OTHER_LOCATION");
|
||||
|
||||
// Setup our filter configuration
|
||||
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 defaultTargetUrl
|
||||
MockFilterChain chain = new MockFilterChain(false);
|
||||
@@ -242,7 +234,7 @@ public class AbstractProcessingFilterTests extends TestCase {
|
||||
request.setRequestURI("/mycontext/some.file.html");
|
||||
|
||||
// Setup our filter configuration
|
||||
MockFilterConfig config = new MockFilterConfig(null);
|
||||
MockFilterConfig config = new MockFilterConfig(null, null);
|
||||
|
||||
// Setup our expectation that the filter chain will be invoked, as our request is for a page the filter isn't monitoring
|
||||
MockFilterChain chain = new MockFilterChain(true);
|
||||
@@ -261,7 +253,7 @@ public class AbstractProcessingFilterTests extends TestCase {
|
||||
MockHttpServletRequest request = createMockRequest();
|
||||
|
||||
// Setup our filter configuration
|
||||
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 defaultTargetUrl
|
||||
MockFilterChain chain = new MockFilterChain(false);
|
||||
@@ -349,7 +341,7 @@ public class AbstractProcessingFilterTests extends TestCase {
|
||||
MockHttpServletRequest request = createMockRequest();
|
||||
|
||||
// Setup our filter configuration
|
||||
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 defaultTargetUrl
|
||||
MockFilterChain chain = new MockFilterChain(false);
|
||||
@@ -389,7 +381,7 @@ public class AbstractProcessingFilterTests extends TestCase {
|
||||
request.getSession().setAttribute(AbstractProcessingFilter.ACEGI_SAVED_REQUEST_KEY, makeSavedRequestForUrl());
|
||||
|
||||
// Setup our filter configuration
|
||||
MockFilterConfig config = new MockFilterConfig(null);
|
||||
MockFilterConfig config = new MockFilterConfig(null, null);
|
||||
|
||||
// Setup our expectation that the filter chain will be invoked, as we want to go to the location requested in the session
|
||||
MockFilterChain chain = new MockFilterChain(true);
|
||||
@@ -416,7 +408,7 @@ public class AbstractProcessingFilterTests extends TestCase {
|
||||
request.getSession().setAttribute(AbstractProcessingFilter.ACEGI_SAVED_REQUEST_KEY, makeSavedRequestForUrl());
|
||||
|
||||
// Setup our filter configuration
|
||||
MockFilterConfig config = new MockFilterConfig(null);
|
||||
MockFilterConfig config = new MockFilterConfig(null, null);
|
||||
|
||||
// Setup our expectation that the filter chain will be invoked, as we want to go to the location requested in the session
|
||||
MockFilterChain chain = new MockFilterChain(true);
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package org.acegisecurity.ui.savedrequest;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import java.io.Serializable;
|
||||
|
||||
public class SavedCookieTest extends TestCase {
|
||||
|
||||
Cookie cookie;
|
||||
SavedCookie savedCookie;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
cookie = new Cookie("name", "value");
|
||||
cookie.setComment("comment");
|
||||
cookie.setDomain("domain");
|
||||
cookie.setMaxAge(100);
|
||||
cookie.setPath("path");
|
||||
cookie.setSecure(true);
|
||||
cookie.setVersion(11);
|
||||
savedCookie = new SavedCookie(cookie);
|
||||
}
|
||||
|
||||
public void testGetName() throws Exception {
|
||||
assertEquals(cookie.getName(), savedCookie.getName());
|
||||
}
|
||||
|
||||
public void testGetValue() throws Exception {
|
||||
assertEquals(cookie.getValue(), savedCookie.getValue());
|
||||
}
|
||||
|
||||
public void testGetComment() throws Exception {
|
||||
assertEquals(cookie.getComment(), savedCookie.getComment());
|
||||
}
|
||||
|
||||
public void testGetDomain() throws Exception {
|
||||
assertEquals(cookie.getDomain(), savedCookie.getDomain());
|
||||
}
|
||||
|
||||
public void testGetMaxAge() throws Exception {
|
||||
assertEquals(cookie.getMaxAge(), savedCookie.getMaxAge());
|
||||
}
|
||||
|
||||
public void testGetPath() throws Exception {
|
||||
assertEquals(cookie.getPath(), savedCookie.getPath());
|
||||
}
|
||||
|
||||
public void testGetVersion() throws Exception {
|
||||
assertEquals(cookie.getVersion(), savedCookie.getVersion());
|
||||
}
|
||||
|
||||
public void testGetCookie() throws Exception {
|
||||
Cookie other = savedCookie.getCookie();
|
||||
assertEquals(cookie.getComment(), other.getComment());
|
||||
assertEquals(cookie.getDomain(), other.getDomain());
|
||||
assertEquals(cookie.getMaxAge(), other.getMaxAge());
|
||||
assertEquals(cookie.getName(), other.getName());
|
||||
assertEquals(cookie.getPath(), other.getPath());
|
||||
assertEquals(cookie.getSecure(), other.getSecure());
|
||||
assertEquals(cookie.getValue(), other.getValue());
|
||||
assertEquals(cookie.getVersion(), other.getVersion());
|
||||
}
|
||||
|
||||
public void testSerializable() throws Exception {
|
||||
assertTrue(savedCookie instanceof Serializable);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/* 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.userdetails.ldap;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import javax.naming.directory.BasicAttributes;
|
||||
import javax.naming.directory.BasicAttribute;
|
||||
|
||||
import org.acegisecurity.GrantedAuthorityImpl;
|
||||
|
||||
/**
|
||||
* Tests {@link LdapUserDetailsMapper}.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
*/
|
||||
public class LdapUserDetailsMapperTests extends TestCase {
|
||||
|
||||
|
||||
public void testMultipleRoleAttributeValuesAreMappedToAuthorities() throws Exception {
|
||||
LdapUserDetailsMapper mapper = new LdapUserDetailsMapper();
|
||||
mapper.setConvertToUpperCase(false);
|
||||
mapper.setRolePrefix("");
|
||||
|
||||
mapper.setRoleAttributes(new String[] {"userRole"});
|
||||
|
||||
BasicAttributes attrs = new BasicAttributes();
|
||||
BasicAttribute roleAttribute = new BasicAttribute("userRole");
|
||||
roleAttribute.add("X");
|
||||
roleAttribute.add("Y");
|
||||
roleAttribute.add("Z");
|
||||
attrs.put(roleAttribute);
|
||||
|
||||
LdapUserDetailsImpl.Essence user = (LdapUserDetailsImpl.Essence) mapper.mapAttributes("cn=someName", attrs);
|
||||
|
||||
assertEquals(3, user.getGrantedAuthorities().length);
|
||||
}
|
||||
|
||||
/**
|
||||
* SEC-303. Non-retrieved role attribute causes NullPointerException
|
||||
*/
|
||||
public void testNonRetrievedRoleAttributeIsIgnored() throws Exception {
|
||||
LdapUserDetailsMapper mapper = new LdapUserDetailsMapper();
|
||||
|
||||
mapper.setRoleAttributes(new String[] {"userRole", "nonRetrievedAttribute"});
|
||||
|
||||
BasicAttributes attrs = new BasicAttributes();
|
||||
attrs.put(new BasicAttribute("userRole", "x"));
|
||||
|
||||
LdapUserDetailsImpl.Essence user = (LdapUserDetailsImpl.Essence) mapper.mapAttributes("cn=someName", attrs);
|
||||
|
||||
assertEquals(1, user.getGrantedAuthorities().length);
|
||||
assertEquals("ROLE_X", user.getGrantedAuthorities()[0].getAuthority());
|
||||
}
|
||||
|
||||
public void testNonStringRoleAttributeIsIgnoredByDefault() throws Exception {
|
||||
LdapUserDetailsMapper mapper = new LdapUserDetailsMapper();
|
||||
|
||||
mapper.setRoleAttributes(new String[] {"userRole"});
|
||||
|
||||
BasicAttributes attrs = new BasicAttributes();
|
||||
attrs.put(new BasicAttribute("userRole", new GrantedAuthorityImpl("X")));
|
||||
|
||||
LdapUserDetailsImpl.Essence user = (LdapUserDetailsImpl.Essence) mapper.mapAttributes("cn=someName", attrs);
|
||||
|
||||
assertEquals(0, user.getGrantedAuthorities().length);
|
||||
}
|
||||
}
|
||||
+9
-1
@@ -6,9 +6,17 @@
|
||||
<parent>
|
||||
<groupId>org.acegisecurity</groupId>
|
||||
<artifactId>acegi-security-parent</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<version>1.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>acegi-security-doc</artifactId>
|
||||
|
||||
<!-- repeated here to avoid appending the artifactId -->
|
||||
<scm>
|
||||
<connection>scm:svn:https://svn.sourceforge.net/svnroot/acegisecurity/trunk/acegisecurity</connection>
|
||||
<developerConnection>scm:svn:https://svn.sourceforge.net/svnroot/acegisecurity/trunk/acegisecurity</developerConnection>
|
||||
<url>http://svn.sourceforge.net/viewcvs.cgi/acegisecurity/trunk/acegisecurity/</url>
|
||||
</scm>
|
||||
|
||||
<dependencies>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
|
||||
<body>
|
||||
<h1>Tutorial: Adding Security to Spring Petclinic</h1>
|
||||
<h2>Background requirements</h2>
|
||||
|
||||
<h2>Preparation</h2>
|
||||
|
||||
<p>To complete this tutorial, you will require a servlet container (such as Tomcat)
|
||||
and a general understanding of using Spring without Acegi Security. The Petclinic
|
||||
@@ -14,11 +15,13 @@ only try to learn one thing at a time, and start with Spring/Petclinic before
|
||||
Acegi Security.
|
||||
</p>
|
||||
|
||||
<h2>Download</h2>
|
||||
<p>
|
||||
You will also need to download:
|
||||
<ul>
|
||||
<li>Spring 2.0 M4 with dependencies ZIP file</li>
|
||||
<li>Acegi Security 1.0.0</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Unzip both files. After unzipping Acegi Security, you'll need to unzip the
|
||||
@@ -29,7 +32,83 @@ unzipped WAR, not the original ZIP). There is no need to setup any environment
|
||||
variables to complete the tutorial.
|
||||
</p>
|
||||
|
||||
<h2>Setup database</h2>
|
||||
<h2>Add required Acegi Security files to Petclinic</h2>
|
||||
|
||||
<p>
|
||||
We now need to put some extra files into Petclinic. The following commands should work:
|
||||
<pre>
|
||||
mkdir %spring%\samples\petclinic\war\WEB-INF\lib
|
||||
copy %acegi%\acegilogin.jsp %spring%\samples\petclinic\war
|
||||
copy %acegi%\accessDenied.jsp %spring%\samples\petclinic\war
|
||||
copy %acegi%\WEB-INF\users.properties %spring%\samples\petclinic\war\WEB-INF
|
||||
copy %acegi%\WEB-INF\applicationContext-acegi-security.xml %spring%\samples\petclinic\war\WEB-INF
|
||||
copy %acegi%\WEB-INF\lib\acegi-security-1.0.0.jar %spring%\samples\petclinic\war\WEB-INF\lib
|
||||
copy %acegi%\WEB-INF\lib\oro-2.0.8.jar %spring%\samples\petclinic\war\WEB-INF\lib
|
||||
copy %acegi%\WEB-INF\lib\commons-codec-1.3.jar %spring%\samples\petclinic\war\WEB-INF\lib
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<h2>Configure Petclinic's files</h2>
|
||||
|
||||
<p>Edit %spring%\samples\petclinic\war\WEB-INF\web.xml and insert the following block of code.
|
||||
<pre>
|
||||
<filter>
|
||||
<filter-name>Acegi Filter Chain Proxy</filter-name>
|
||||
<filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
|
||||
<init-param>
|
||||
<param-name>targetClass</param-name>
|
||||
<param-value>org.acegisecurity.util.FilterChainProxy</param-value>
|
||||
</init-param>
|
||||
</filter>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>Acegi Filter Chain Proxy</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
</pre>
|
||||
Next, locate the "contextConfigLocation" parameter, and add a new line into the existing param-value.
|
||||
The resulting block will look like this:
|
||||
<pre>
|
||||
<context-param>
|
||||
<param-name>contextConfigLocation</param-name>
|
||||
<param-value>
|
||||
/WEB-INF/applicationContext-jdbc.xml
|
||||
/WEB-INF/applicationContext-acegi-security.xml
|
||||
</param-value>
|
||||
</context-param>
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To make it easier to experiment with the application, now edit
|
||||
%spring%\samples\petclinic\war\WEB-INF\jsp\footer.jsp. Add a new "logout" link, as shown:
|
||||
<pre>
|
||||
<table style="width:100%"><tr>
|
||||
<td><A href="<c:url value="/welcome.htm"/>">Home</A></td>
|
||||
<td><A href="<c:url value="/j_acegi_logout"/>">Logout</A></td>
|
||||
<td style="text-align:right;color:silver">PetClinic :: a Spring Framework demonstration</td>
|
||||
</tr></table>
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Our last step is to specify which URLs require authorization and which do not. Let's
|
||||
edit %spring%\samples\petclinic\war\WEB-INF\applicationContext-acegi-security.xml.
|
||||
Locate the bean definition for FilterSecurityInterceptor. Edit its objectDefinitionSource
|
||||
property so that it reflects the following:
|
||||
<pre>
|
||||
<property name="objectDefinitionSource">
|
||||
<value>
|
||||
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
|
||||
PATTERN_TYPE_APACHE_ANT
|
||||
/acegilogin.jsp=IS_AUTHENTICATED_ANONYMOUSLY
|
||||
/**=IS_AUTHENTICATED_REMEMBERED
|
||||
</value>
|
||||
</property>
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<h2>Start Petclinic's database</h2>
|
||||
|
||||
<p>Start the Hypersonic server (this is just normal Petclinic configuration):
|
||||
<pre>
|
||||
@@ -46,88 +125,11 @@ build setupDB
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<h2>Setup Petclinic's web.xml</h2>
|
||||
|
||||
<p>Edit %spring%\samples\petclinic\war\WEB-INF\web.xml and insert the following block of code.
|
||||
<pre>
|
||||
<filter>
|
||||
<filter-name>Acegi Filter Chain Proxy</filter-name>
|
||||
<filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
|
||||
<init-param>
|
||||
<param-name>targetClass</param-name>
|
||||
<param-value>org.acegisecurity.util.FilterChainProxy</param-value>
|
||||
</init-param>
|
||||
</filter>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>Acegi Filter Chain Proxy</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
</pre>
|
||||
Next, locate the "contextConfigLocation" parameter, and add a new line into the existing param-value.
|
||||
The resulting block will look like this:
|
||||
<pre>
|
||||
<context-param>
|
||||
<param-name>contextConfigLocation</param-name>
|
||||
<param-value>
|
||||
/WEB-INF/applicationContext-jdbc.xml
|
||||
/WEB-INF/applicationContext-acegi-security.xml
|
||||
</param-value>
|
||||
</context-param>
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<h2>Add the necessary files</h2>
|
||||
|
||||
<p>
|
||||
We now need to put some extra files into Petclinic. The following commands should work:
|
||||
<pre>
|
||||
copy %acegi%\acegilogin.jsp %spring%\samples\petclinic\war
|
||||
copy %acegi%\WEB-INF\users.properties %spring%\samples\petclinic\war\WEB-INF
|
||||
copy %acegi%\WEB-INF\applicationContext-acegi-security.xml %spring%\samples\petclinic\war\WEB-INF
|
||||
copy %acegi%\WEB-INF\lib\acegi-security-1.0.0.jar %spring%\samples\petclinic\war\WEB-INF\lib
|
||||
copy %acegi%\WEB-INF\lib\oro-2.0.8.jar %spring%\samples\petclinic\war\WEB-INF\lib
|
||||
copy %acegi%\WEB-INF\lib\commons-codec-1.3.jar %spring%\samples\petclinic\war\WEB-INF\lib
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To make it easier to experiment with the application, let's edit
|
||||
%spring%\samples\petclinic\war\WEB-INF\jsp\footer.jsp. Add a new "logout" link, as shown:
|
||||
<pre>
|
||||
<table style="width:100%"><tr>
|
||||
<td><A href="<c:url value="/welcome.htm"/>">Home</A></td>
|
||||
<td><A href="<c:url value="/j_acegi_logout"/>">Logout</A></td>
|
||||
<td style="text-align:right;color:silver">PetClinic :: a Spring Framework demonstration</td>
|
||||
</tr></table>
|
||||
|
||||
</pre>
|
||||
|
||||
</p>
|
||||
|
||||
<h2>Modify the allowed URLs</h2>
|
||||
|
||||
<p>
|
||||
Our last step is to specify which URLs require authorization and which do not. Let's
|
||||
edit %spring%\samples\petclinic\war\WEB-INF\applicationContext-acegi-security.xml.
|
||||
Scroll to the bottom and locate the bean definition for FilterSecurityInterceptor.
|
||||
Edit its objectDefinitionSource property so that it reflects the following:
|
||||
<pre>
|
||||
<property name="objectDefinitionSource">
|
||||
<value>
|
||||
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
|
||||
PATTERN_TYPE_APACHE_ANT
|
||||
/acegilogin.jsp=IS_AUTHENTICATED_ANONYMOUSLY
|
||||
/**=IS_AUTHENTICATED_REMEMBERED
|
||||
</value>
|
||||
</property>
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<h2>Build and deploy the Petclinic WAR file</h2>
|
||||
|
||||
<p>
|
||||
Use the Ant build and deploy to your servlet container:
|
||||
Use Petclinic's Ant build script and deploy to your servlet container:
|
||||
<pre>
|
||||
cd %spring%\samples\petclinic
|
||||
build warfile
|
||||
@@ -138,12 +140,83 @@ copy dist\petclinic.war %TOMCAT_HOME%\webapps
|
||||
<p>Finally, start your container and try to visit the home page.
|
||||
Your request should be intercepted and you will be forced to login.</p>
|
||||
|
||||
<h2>Optional Bonus: Securing the Middle Tier</h2>
|
||||
<p>
|
||||
Whilst you've now secured your web requests, you might want to stop users
|
||||
from being able to add clinic visits unless authorized. We'll make it so
|
||||
you need to hold ROLE_SUPERVISOR to add a clinic visit.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In %spring%\samples\petclinic\war\WEB-INF\applicationContext-jdbc.xml, locate
|
||||
the TransactionProxyFactoryBean definition. Add an additional property after
|
||||
the existing "preInterceptors" property:
|
||||
<pre>
|
||||
<property name="postInterceptors" ref="methodSecurityInterceptor"/>
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Finally, we need to add in the referred-to "methodSecurityInterceptor" bean definition.
|
||||
So pop an extra bean definition in, as shown below:
|
||||
<pre>
|
||||
<bean id="methodSecurityInterceptor" class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
|
||||
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
|
||||
<property name="accessDecisionManager">
|
||||
<bean class="org.acegisecurity.vote.AffirmativeBased">
|
||||
<property name="allowIfAllAbstainDecisions" value="false"/>
|
||||
<property name="decisionVoters">
|
||||
<list>
|
||||
<bean class="org.acegisecurity.vote.RoleVoter"/>
|
||||
<bean class="org.acegisecurity.vote.AuthenticatedVoter"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="objectDefinitionSource">
|
||||
<value>
|
||||
org.springframework.samples.petclinic.Clinic.*=IS_AUTHENTICATED_REMEMBERED
|
||||
org.springframework.samples.petclinic.Clinic.storeVisit=ROLE_SUPERVISOR
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Redeploy your web application. Use the earlier process to do that. Be careful to
|
||||
ensure that the old Petclinic WAR is replaced by the new Petclinic WAR in your
|
||||
servlet container. Login as "marissa", who has ROLE_SUPERVISOR. You will be able to
|
||||
then view a customer and add a visit. Logout, then login as anyone other than Marissa.
|
||||
You will receive an access denied error when you attempt to add a visit.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To clean things up a bit, you might want to wrap up by hiding the "add visit" link
|
||||
unless you are authorized to use it. Acegi Security provides a tag library to help
|
||||
you do that. Edit %spring%\samples\petclinic\war\WEB-INF\jsp\owner.jsp. Add
|
||||
the following line to the top of the file:
|
||||
<pre>
|
||||
<%@ taglib prefix="authz" uri="http://acegisecurity.org/authz" %>
|
||||
</pre>
|
||||
Next, scroll down and find the link to "add visit". Modify it as follows:
|
||||
<pre>
|
||||
<authz:authorize ifAllGranted="ROLE_SUPERVISOR">
|
||||
<FORM method=GET action="<c:url value="/addVisit.htm"/>" name="formVisitPet<c:out value="${pet.id}"/>">
|
||||
<INPUT type="hidden" name="petId" value="<c:out value="${pet.id}"/>"/>
|
||||
<INPUT type="submit" value="Add Visit"/>
|
||||
</FORM>
|
||||
</authz:authorize>
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<h2>What now?</h2>
|
||||
<p>
|
||||
These steps can be applied to your own application. Although we do suggest
|
||||
that you visit <a href="http://acegisecurity.org">http://acegisecurity.org</a>
|
||||
and in particular review the "Suggested Steps" for getting started with Acegi
|
||||
Security.</p>
|
||||
|
||||
Security. The suggested steps are optimized for learning Acegi Security quickly
|
||||
and applying it to your own projects. It also includes realistic time estimates
|
||||
for each step so you can plan your integration activities.</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,4 +1,8 @@
|
||||
<html>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
<title>Acegi Security - Upgrading from version 0.8.0 to 1.0.0</title>
|
||||
</head>
|
||||
@@ -8,86 +12,110 @@
|
||||
<p>
|
||||
The following should help most casual users of the project update their
|
||||
applications:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
|
||||
<h1>Changes 0.9.0 to RC1</h1>
|
||||
<h1>Changes 0.9.0 to RC1</h1>
|
||||
|
||||
<li>The top level package name has changed. Simply find "net.sf.acegisecurity" and replace with
|
||||
"org.acegisecurity".</li>
|
||||
|
||||
<li>
|
||||
DaoAuthenticationProvider has a property, authenticationDao. This property should now be renamed to
|
||||
userDetailsService.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
In JSPs, each "authz" taglib prefix must be changed from uri="http://acegisecurity.sf.net/authz"
|
||||
to uri="http://acegisecurity.org/authz".
|
||||
</li>
|
||||
|
||||
<li>net.sf.acegisecurity.providers.dao.AuthenticationDao is now org.acegisecurity.userdetails.UserDetailsService.
|
||||
The interface signature has not changed. Similarly, User and UserDetails have moved into the latter's package as well.
|
||||
If you've implemented your own AuthenticationDao, you'll need to change the class it's implementing and quite likely
|
||||
the import packages for User and UserDetails. In addition, if using JdbcDaoImpl or InMemoryDaoImpl please
|
||||
note they have moved to this new package.</li>
|
||||
|
||||
<li>Acegi Security is now localised. In net.sf.acegisecurity you will find a messages.properties. It is
|
||||
suggested to register this in your application context, perhaps using ReloadableResourceBundleMessageSource.
|
||||
If you do not do this, the default messages included in the source code will be used so this change is
|
||||
not critical. The Spring LocaleContextHolder class is used to determine the locale of messages included in
|
||||
exceptions. At present only the default messages.properties is included (which is in English). If
|
||||
you localise this file to another language, please consider attaching it to a
|
||||
<a href="http://opensource2.atlassian.com/projects/spring/secure/BrowseProject.jspa?id=10040">new JIRA task</a>
|
||||
so that we can include it in future Acegi Security releases.</li>
|
||||
|
||||
<h1>Changes RC1 to RC2</h1>
|
||||
|
||||
<li>
|
||||
org.acegisecurity.ui.rememberme.RememberMeProcessingFilter now requires an authenticationManager property. This will generally
|
||||
point to an implementation of org.acegisecurity.providers.ProviderManager.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
org.acegisecurity.intercept.web.AuthenticationEntryPoint has moved to a new location,
|
||||
org.acegisecurity.ui.AuthenticationEntryPoint.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
org.acegisecurity.intercept.web.SecurityEnforcementFilter has moved to a new location and name,
|
||||
org.acegisecurity.ui.ExceptionTranslationFilter. In addition, the "filterSecurityInterceptor"
|
||||
property on the old SecurityEnforcementFilter class has been removed. This is because
|
||||
SecurityEnforcementFilter will no longer delegate to FilterSecurityInterceptor as it has in the
|
||||
past. Because this delegation feature has been removed (see SEC-144 for a background as to why),
|
||||
please add a new filter definition for FilterSecurityInterceptor to the end of your
|
||||
FilterChainProxy. Generally you'll also rename the old SecurityEnforcementFilter entry in your
|
||||
FilterChainProxy to ExceptionTranslationFilter, more accurately reflecting its purpose.
|
||||
If you are not using FilterChainProxy (although we recommend that you do), you will need to add
|
||||
an additional filter entry to web.xml and use FilterToBeanProxy to access the FilterSecurityInterceptor.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
If you are directly using SecurityContextHolder.setContext(SecurityContext) - which is not
|
||||
very common - please not that best practise is now to call SecurityContextHolder.clearContext()
|
||||
if you wish to erase the contents of the SecurityContextHolder. Previously code such as
|
||||
SecurityContextHolder.setContext(new SecurityContextImpl()) would have been used. The revised
|
||||
method internally stores null, which helps avoids redeployment issue caused by the previous
|
||||
approaches (see SEC-159 for further details).
|
||||
</li>
|
||||
<ul>
|
||||
|
||||
<h1>Changes RC2 to Final</h1>
|
||||
|
||||
<li>
|
||||
AbstractProcessingFilter.onUnsuccessfulAuthentication(HttpServletRequest, HttpServletResponse)
|
||||
has changed it signature (SEC-238). If subclassing, please override the new signature.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
ExceptionTranslationFilter no longer provides a sendAccessDenied() method. Use the
|
||||
new AccessDeniedHandler instead if custom handling is required.
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
<li>The top level package name has changed. Simply find "net.sf.acegisecurity" and replace with
|
||||
"org.acegisecurity".</li>
|
||||
|
||||
<li>
|
||||
DaoAuthenticationProvider has a property, authenticationDao. This property should now be renamed to
|
||||
userDetailsService.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
In JSPs, each "authz" taglib prefix must be changed from uri="http://acegisecurity.sf.net/authz"
|
||||
to uri="http://acegisecurity.org/authz".
|
||||
</li>
|
||||
|
||||
<li>net.sf.acegisecurity.providers.dao.AuthenticationDao is now org.acegisecurity.userdetails.UserDetailsService.
|
||||
The interface signature has not changed. Similarly, User and UserDetails have moved into the latter's package as well.
|
||||
If you've implemented your own AuthenticationDao, you'll need to change the class it's implementing and quite likely
|
||||
the import packages for User and UserDetails. In addition, if using JdbcDaoImpl or InMemoryDaoImpl please
|
||||
note they have moved to this new package.</li>
|
||||
|
||||
<li>Acegi Security is now localised. In net.sf.acegisecurity you will find a messages.properties. It is
|
||||
suggested to register this in your application context, perhaps using ReloadableResourceBundleMessageSource.
|
||||
If you do not do this, the default messages included in the source code will be used so this change is
|
||||
not critical. The Spring LocaleContextHolder class is used to determine the locale of messages included in
|
||||
exceptions. At present only the default messages.properties is included (which is in English). If
|
||||
you localise this file to another language, please consider attaching it to a
|
||||
<a href="http://opensource2.atlassian.com/projects/spring/secure/BrowseProject.jspa?id=10040">new JIRA task</a>
|
||||
so that we can include it in future Acegi Security releases.</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
<h1>Changes RC1 to RC2</h1>
|
||||
|
||||
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
org.acegisecurity.ui.rememberme.RememberMeProcessingFilter now requires an authenticationManager property. This will generally
|
||||
point to an implementation of org.acegisecurity.providers.ProviderManager.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
org.acegisecurity.intercept.web.AuthenticationEntryPoint has moved to a new location,
|
||||
org.acegisecurity.ui.AuthenticationEntryPoint.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
org.acegisecurity.intercept.web.SecurityEnforcementFilter has moved to a new location and name,
|
||||
org.acegisecurity.ui.ExceptionTranslationFilter. In addition, the "filterSecurityInterceptor"
|
||||
property on the old SecurityEnforcementFilter class has been removed. This is because
|
||||
SecurityEnforcementFilter will no longer delegate to FilterSecurityInterceptor as it has in the
|
||||
past. Because this delegation feature has been removed (see SEC-144 for a background as to why),
|
||||
please add a new filter definition for FilterSecurityInterceptor to the end of your
|
||||
FilterChainProxy. Generally you'll also rename the old SecurityEnforcementFilter entry in your
|
||||
FilterChainProxy to ExceptionTranslationFilter, more accurately reflecting its purpose.
|
||||
If you are not using FilterChainProxy (although we recommend that you do), you will need to add
|
||||
an additional filter entry to web.xml and use FilterToBeanProxy to access the FilterSecurityInterceptor.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
If you are directly using SecurityContextHolder.setContext(SecurityContext) - which is not
|
||||
very common - please not that best practise is now to call SecurityContextHolder.clearContext()
|
||||
if you wish to erase the contents of the SecurityContextHolder. Previously code such as
|
||||
SecurityContextHolder.setContext(new SecurityContextImpl()) would have been used. The revised
|
||||
method internally stores null, which helps avoids redeployment issue caused by the previous
|
||||
approaches (see SEC-159 for further details).
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
<h1>Changes RC2 to Final</h1>
|
||||
|
||||
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
AbstractProcessingFilter.onUnsuccessfulAuthentication(HttpServletRequest, HttpServletResponse)
|
||||
has changed it signature (SEC-238). If subclassing, please override the new signature.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
ExceptionTranslationFilter no longer provides a sendAccessDenied() method. Use the
|
||||
new AccessDeniedHandler instead if custom handling is required.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
There have been some changes to the LDAP provider APIs to allow for future improvements, as detailed in
|
||||
<a href="http://opensource.atlassian.com/projects/spring/browse/SEC-264">SEC-264</a>. These
|
||||
should only affect users who have written their own extensions to the provider. The general LDAP
|
||||
classes are now in the packages org.acegisecurity.ldap and the org.acegisecurity.userdetails.ldap
|
||||
package has been introduced. The search and authentication classes now return an
|
||||
<a href="../multiproject/acegi-security/apidocs/org/acegisecurity/userdetails/ldap/LdapUserDetails.html">LdapUserDetails</a>
|
||||
instance. The LdapAuthoritiesPopulator interface and its default implementation now both make use of
|
||||
LdapUserDetails. Any customized versions should be updated to use the new method signatures.
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+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.0.1</version>
|
||||
</parent>
|
||||
<artifactId>acegi-security-domain</artifactId>
|
||||
<name>Acegi Security System for Spring - Domain Object Support</name>
|
||||
@@ -44,4 +41,4 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
</project>
|
||||
@@ -1,11 +1,8 @@
|
||||
<?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>
|
||||
<groupId>org.acegisecurity</groupId>
|
||||
<artifactId>acegi-security-parent</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<version>1.0.1</version>
|
||||
<name>Acegi Security System for Spring - Parent</name>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
@@ -35,9 +32,9 @@
|
||||
</licenses>
|
||||
|
||||
<scm>
|
||||
<connection>scm:svn:https://svn.sourceforge.net/svnroot/acegisecurity/trunk/acegisecurity</connection>
|
||||
<developerConnection>scm:svn:https://svn.sourceforge.net/svnroot/acegisecurity/trunk/acegisecurity</developerConnection>
|
||||
<url>http://svn.sourceforge.net/viewcvs.cgi/acegisecurity/trunk/acegisecurity/</url>
|
||||
<connection>scm:svn:https://svn.sourceforge.net/svnroot/acegisecurity/tags/release_1_0_1</connection>
|
||||
<developerConnection>scm:svn:https://svn.sourceforge.net/svnroot/acegisecurity/tags/release_1_0_1</developerConnection>
|
||||
<url>https://svn.sourceforge.net/svnroot/acegisecurity/tags/release_1_0_1</url>
|
||||
</scm>
|
||||
|
||||
<!--
|
||||
@@ -49,18 +46,19 @@
|
||||
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>acegi-sourceforge-releases</id>
|
||||
<id>acegi.sourceforge.releases</id>
|
||||
<name>Acegi Releases Repository at Sourceforge</name>
|
||||
<url>scp://shell.sourceforge.net/home/groups/a/ac/acegisecurity/htdocs/repository/releases</url>
|
||||
</repository>
|
||||
<snapshotRepository>
|
||||
<id>acegi-sourceforge-snapshots</id>
|
||||
<id>acegi.sourceforge.snapshots</id>
|
||||
<name>Acegi Snapshots Repository at Sourceforge</name>
|
||||
<url>scp://shell.sourceforge.net/home/groups/a/ac/acegisecurity/htdocs/repository/snapshots</url>
|
||||
</snapshotRepository>
|
||||
<site>
|
||||
<id>website</id>
|
||||
<url>scp://shell.sourceforge.net/home/groups/a/ac/acegisecurity/htdocs</url>
|
||||
<id>acegi.sourceforge.site</id>
|
||||
<name>Acegi Website at Sourceforge</name>
|
||||
<url>scp://shell.sourceforge.net/home/groups/a/ac/acegisecurity/htdocs/maven2</url>
|
||||
</site>
|
||||
</distributionManagement>
|
||||
|
||||
@@ -225,11 +223,18 @@
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<includes>
|
||||
<include implementation="java.lang.String">**/*Tests.class</include>
|
||||
<include>**/*Tests.class</include>
|
||||
</includes>
|
||||
<excludes>
|
||||
<exclude implementation="java.lang.String">**/Abstract*</exclude>
|
||||
<exclude>**/Abstract*</exclude>
|
||||
</excludes>
|
||||
<forkMode>once</forkMode>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-release-plugin</artifactId>
|
||||
<configuration>
|
||||
<tagBase>https://svn.sourceforge.net/svnroot/acegisecurity/tags</tagBase>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
@@ -241,9 +246,50 @@
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-report-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jxr-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-pmd-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>jxr-maven-plugin</artifactId>
|
||||
<artifactId>cobertura-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<configuration>
|
||||
<links>
|
||||
<link>http://java.sun.com/j2se/1.5.0/docs/api</link>
|
||||
<link>http://jakarta.apache.org/commons/dbcp/apidocs/</link>
|
||||
<link>http://jakarta.apache.org/commons/fileupload/apidocs/</link>
|
||||
<link>http://jakarta.apache.org/commons/httpclient/apidocs/</link>
|
||||
<link>http://jakarta.apache.org/commons/logging/api/</link>
|
||||
<link>http://jakarta.apache.org/commons/pool/apidocs/</link>
|
||||
<link>http://www.junit.org/junit/javadoc/</link>
|
||||
<link>http://logging.apache.org/log4j/docs/api/</link>
|
||||
<link>http://jakarta.apache.org/regexp/apidocs/</link>
|
||||
<link>http://jakarta.apache.org/velocity/api/</link>
|
||||
<link>http://www.springframework.org/docs/api/</link>
|
||||
<link>http://jakarta.apache.org/commons/lang/api/</link>
|
||||
<link>http://developer.ja-sig.org/projects/cas/multiproject/cas-server/apidocs/</link>
|
||||
<link>http://jakarta.apache.org/commons/codec/apidocs/</link>
|
||||
<link>http://jakarta.apache.org/commons/collections/api/</link>
|
||||
<link>http://jakarta.apache.org/commons/logging/apidocs/</link>
|
||||
<link>http://tomcat.apache.org/tomcat-5.0-doc/servletapi/</link>
|
||||
</links>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>taglist-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</reporting>
|
||||
@@ -264,4 +310,4 @@
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
</project>
|
||||
</project>
|
||||
+1
-1
@@ -18,7 +18,7 @@ maven.compile.source=1.3
|
||||
|
||||
maven.javadoc.links=http://java.sun.com/j2se/1.5.0/docs/api/,http://www.springframework.org/docs/api/,http://jakarta.apache.org/commons/lang/api/,http://developer.ja-sig.org/projects/cas/multiproject/cas-server/apidocs/,http://jakarta.apache.org/commons/codec/apidocs/,http://jakarta.apache.org/commons/collections/api/,http://jakarta.apache.org/commons/logging/apidocs/,http://tomcat.apache.org/tomcat-5.0-doc/servletapi/
|
||||
|
||||
maven.repo.remote=http://www.ibiblio.org/maven,http://acegisecurity.sourceforge.net/maven,http://svn.apache.org/repository/
|
||||
maven.repo.remote=http://www.ibiblio.org/maven,http://acegisecurity.sourceforge.net/maven,http://people.apache.org/repository/
|
||||
|
||||
# Site generation properties
|
||||
maven.xdoc.date = left
|
||||
|
||||
+3
-3
@@ -21,7 +21,7 @@
|
||||
<project>
|
||||
<pomVersion>3</pomVersion>
|
||||
<groupId>org.acegisecurity</groupId>
|
||||
<currentVersion>1.0.0</currentVersion>
|
||||
<currentVersion>1.0.1</currentVersion>
|
||||
<package>org.acegisecurity</package>
|
||||
<description>Acegi Security System for Spring</description>
|
||||
<shortDescription>Acegi Security System for Spring</shortDescription>
|
||||
@@ -278,7 +278,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring</artifactId>
|
||||
<version>2.0-m2</version>
|
||||
<version>1.2.7</version>
|
||||
<type>jar</type>
|
||||
<url>http://www.springframework.org</url>
|
||||
<properties>
|
||||
@@ -288,7 +288,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-mock</artifactId>
|
||||
<version>2.0-m2</version>
|
||||
<version>1.2.7</version>
|
||||
<type>jar</type>
|
||||
<url>http://www.springframework.org</url>
|
||||
</dependency>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>org.acegisecurity</groupId>
|
||||
<artifactId>acegi-security-samples</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<version>1.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>acegi-security-sample-annotations</artifactId>
|
||||
<name>Acegi Security System for Spring - Annotations sample</name>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>org.acegisecurity</groupId>
|
||||
<artifactId>acegi-security-samples</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<version>1.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>acegi-security-sample-attributes</artifactId>
|
||||
<name>Acegi Security System for Spring - Attributes sample</name>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>org.acegisecurity</groupId>
|
||||
<artifactId>acegi-security-samples</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<version>1.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>acegi-security-sample-contacts-tiger</artifactId>
|
||||
<name>Acegi Security System for Spring - Contacts sample</name>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>org.acegisecurity</groupId>
|
||||
<artifactId>acegi-security-samples</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<version>1.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>acegi-security-sample-contacts</artifactId>
|
||||
<name>Acegi Security System for Spring - Contacts sample</name>
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>org.acegisecurity</groupId>
|
||||
<artifactId>acegi-security-parent</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<version>1.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>acegi-security-samples</artifactId>
|
||||
<name>Acegi Security System for Spring - Samples</name>
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
set spring=C:\dev\spring-framework-2.0-m4
|
||||
set acegi=C:\dev\eclipse\workspaces\acegi\acegisecurity\samples\tutorial\target\acegi-security-sample-tutorial
|
||||
mkdir %spring%\samples\petclinic\war\WEB-INF\lib
|
||||
copy %acegi%\acegilogin.jsp %spring%\samples\petclinic\war
|
||||
copy %acegi%\accessDenied.jsp %spring%\samples\petclinic\war
|
||||
copy %acegi%\WEB-INF\users.properties %spring%\samples\petclinic\war\WEB-INF
|
||||
copy %acegi%\WEB-INF\applicationContext-acegi-security.xml %spring%\samples\petclinic\war\WEB-INF
|
||||
copy %acegi%\WEB-INF\lib\acegi-security-1.0.0.jar %spring%\samples\petclinic\war\WEB-INF\lib
|
||||
copy %acegi%\WEB-INF\lib\oro-2.0.8.jar %spring%\samples\petclinic\war\WEB-INF\lib
|
||||
copy %acegi%\WEB-INF\lib\commons-codec-1.3.jar %spring%\samples\petclinic\war\WEB-INF\lib
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>org.acegisecurity</groupId>
|
||||
<artifactId>acegi-security-parent</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<version>1.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>acegi-security-sandbox</artifactId>
|
||||
<name>Acegi Security System for Spring - Sandbox</name>
|
||||
|
||||
Reference in New Issue
Block a user