1
0
mirror of synced 2026-07-16 16:15:12 +00:00

Compare commits

...

27 Commits

Author SHA1 Message Date
Carlos Sanchez 1bc1196baa [maven-scm] copy for tag release_1_0_1 2006-06-22 17:28:18 +00:00
Luke Taylor a2c3635d78 Moved class to test treee 2006-06-15 00:41:53 +00:00
Luke Taylor 552c275e8f Accidentally checked into source tree rather than test source 2006-06-15 00:37:18 +00:00
Luke Taylor aaf51c4bee Added test for non-String role. 2006-06-14 23:20:51 +00:00
Luke Taylor 49da801096 SEC-303: Check from null role attribute in LdapUserDetailsMapper 2006-06-14 22:44:39 +00:00
Luke Taylor eb3e954ae4 Added chained append call in toString method 2006-06-14 21:46:21 +00:00
Luke Taylor b0caa72e80 Added template method for role creation, as requested in the forum. 2006-06-13 13:18:45 +00:00
Luke Taylor 7475906218 Remove Javadoc errors 2006-06-12 22:32:59 +00:00
Luke Taylor 18680e8fab Remove Jalopy mistakes 2006-06-12 22:31:10 +00:00
Ray Krueger cada23f57d Synchronized MockFilterConfig uses for Spring 1.2.6 and 1.2.8 2006-06-11 01:20:29 +00:00
Ray Krueger fa3c61b19b Call to getCookies() should return Cookies, not SavedCookies 2006-06-11 01:19:44 +00:00
Luke Taylor 88825089a7 Removed "final" from getGroupMembershipRoles 2006-06-07 13:31:11 +00:00
Luke Taylor 2a7caff95f SEC-295: Changed to use getDefaultTargetUrl() accessor internally rather than accessing property directly. Allows for overriding method to supply different Urls. 2006-06-04 15:14:33 +00:00
Ray Krueger 9fd0bbd694 Added Serializable check just to be sure... 2006-06-03 13:40:39 +00:00
Ray Krueger 1a9629b197 http://opensource.atlassian.com/projects/spring/browse/SEC-289
Wraps disassembles cookies into a SavedCookie that is serializable
2006-06-03 13:36:51 +00:00
Ben Alex f7020755be SEC-291: Avoid unnecessary creation of SecurityContextHolderStrategy. 2006-06-01 14:02:56 +00:00
Luke Taylor da780e4567 Tidy up XML formatting in comment 2006-05-31 21:56:16 +00:00
Luke Taylor 9f41b9f470 Wrap any DataAccessExceptions thrown by the Ldaptemplate with AuthenticationServiceFailureExceptions 2006-05-31 21:46:16 +00:00
Luke Taylor 5d7a75a421 SEC-284: Removed allowEmptyPassword flag.. 2006-05-31 20:12:12 +00:00
Luke Taylor d2ee383e06 Changed to reject empty passwords by default. 2006-05-31 18:22:05 +00:00
Luke Taylor ee50d6e334 SEC-281: Modified to use Spring 1.2 compatible exception class for incorrect search results size. 2006-05-31 16:54:27 +00:00
Luke Taylor 02e7bbb982 SEC-284: added allowEmptyPasswords property with default value "true" 2006-05-31 15:00:59 +00:00
Ben Alex 7957d54d67 SEC-282: Tutorial for securing Petclinic using Acegi Security. 2006-05-31 07:40:45 +00:00
Ray Krueger 00620b6992 http://opensource.atlassian.com/projects/spring/browse/SEC-96
Refactored Digest encoding for better support of all MessageDigest algorithms, such as the SHA family.
2006-05-31 03:03:18 +00:00
Carlos Sanchez 35093e09f6 Bump version to 1.1.0-SNAPSHOT 2006-05-31 00:52:26 +00:00
Scott McCrory 0eab6903e8 SEC-280: Fixed Eclipse classpath to correctly point to Maven's Spring Framework jars 2006-05-30 22:45:22 +00:00
Luke Taylor b6282423e3 Added info on Ldap changes and fixed HTML. 2006-05-30 20:37:29 +00:00
46 changed files with 1038 additions and 438 deletions
+3 -3
View File
@@ -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"/>
+3 -6
View File
@@ -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>
+3 -6
View File
@@ -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>
+3 -6
View File
@@ -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>
+3 -6
View File
@@ -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
View File
@@ -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>
+3 -6
View File
@@ -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
View File
@@ -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
View File
@@ -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");
}
}
@@ -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/>
* &lt;bean id="passwordEncoder" class="org.acegisecurity.providers.encoding.MessageDigestPasswordEncoder"&gt;<br/>
* &nbsp;&nbsp;&lt;constructor-arg value="MD5"/><br/>
* &lt;/bean&gt;
*
*
* @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/>
* &lt;bean id="passwordEncoder" class="org.acegisecurity.providers.encoding.ShaPasswordEncoder"&gt;<br/>
* &nbsp;&nbsp;&lt;constructor-arg value="256"/><br/>
* &lt;/bean&gt;
*
*
* @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);
}
}
@@ -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>
* &lt;bean id="initialDirContextFactory" class="org.acegisecurity.providers.ldap.DefaultInitialDirContextFactory">
* &lt;constructor-arg value="ldap://monkeymachine:389/dc=acegisecurity,dc=org"/>
* &lt;property name="managerDn">&lt;value>cn=manager,dc=acegisecurity,dc=org&lt;/value>&lt;/property>
* &lt;property name="managerPassword">&lt;value>password&lt;/value>&lt;/property> &lt;/bean>
* &lt;property name="managerPassword">&lt;value>password&lt;/value>&lt;/property>
* &lt;/bean>
*
* &lt;bean id="ldapAuthProvider" class="org.acegisecurity.providers.ldap.LdapAuthenticationProvider">
* &lt;constructor-arg> &lt;bean class="org.acegisecurity.providers.ldap.authenticator.BindAuthenticator">
* &lt;constructor-arg>&lt;ref local="initialDirContextFactory"/>&lt;/constructor-arg>
* &lt;property name="userDnPatterns">&lt;list>&lt;value>uid={0},ou=people&lt;/value>&lt;/list>&lt;/property>
* &lt;/bean> &lt;/constructor-arg> &lt;constructor-arg>
* &lt;bean class="org.acegisecurity.providers.ldap.populator.DefaultLdapAuthoritiesPopulator">
* &lt;constructor-arg>&lt;ref local="initialDirContextFactory"/>&lt;/constructor-arg>
* &lt;constructor-arg>&lt;value>ou=groups&lt;/value>&lt;/constructor-arg>
* &lt;property name="groupRoleAttribute">&lt;value>ou&lt;/value>&lt;/property> &lt;/bean>
* &lt;/constructor-arg> &lt;/bean></pre><p>This would set up the provider to access an LDAP server with URL
* &lt;constructor-arg>
* &lt;bean class="org.acegisecurity.providers.ldap.authenticator.BindAuthenticator">
* &lt;constructor-arg>&lt;ref local="initialDirContextFactory"/>&lt;/constructor-arg>
* &lt;property name="userDnPatterns">&lt;list>&lt;value>uid={0},ou=people&lt;/value>&lt;/list>&lt;/property>
* &lt;/bean>
* &lt;/constructor-arg>
* &lt;constructor-arg>
* &lt;bean class="org.acegisecurity.providers.ldap.populator.DefaultLdapAuthoritiesPopulator">
* &lt;constructor-arg>&lt;ref local="initialDirContextFactory"/>&lt;/constructor-arg>
* &lt;constructor-arg>&lt;value>ou=groups&lt;/value>&lt;/constructor-arg>
* &lt;property name="groupRoleAttribute">&lt;value>ou&lt;/value>&lt;/property>
* &lt;/bean>
* &lt;/constructor-arg>
* &lt;/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=&lt;user-login-name&gt;,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=&lt;user's-DN&gt;)</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);
}
}
}
@@ -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;
* &lt;!-- the following properties are shown with their default values -->
* &lt;property name="searchSubTree">&lt;value>false&lt;/value>&lt;/property>
* &lt;property name="rolePrefix">&lt;value>ROLE_&lt;/value>&lt;/property>
* &lt;property name="convertToUpperCase">&lt;value>true&lt;/value>&lt;/property>&lt;/bean></pre>A search for
* &lt;property name="convertToUpperCase">&lt;value>true&lt;/value>&lt;/property>
* &lt;/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> &lt;property name="exceptionMappings"&gt;<br>
* * &nbsp;&nbsp;&lt;props&gt;<br>
* * &nbsp;&nbsp;&nbsp;&nbsp;&lt;prop&gt; key="org.acegisecurity.BadCredentialsException"&gt;/bad_credentials.jsp&lt;/prop&gt;<br>
* * &nbsp;&nbsp;&lt;/props&gt;<br>
* * &lt;/property&gt;<br>
* * </code><br>
* a redirection url target.
* For example:
* <pre>
* &lt;property name="exceptionMappings"&gt;
* &lt;props&gt;
* &lt;prop&gt; key="org.acegisecurity.BadCredentialsException"&gt;/bad_credentials.jsp&lt;/prop&gt;
* &lt;/props&gt;
* &lt;/property&gt;
* </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);
}
@@ -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);
@@ -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
}
}
}
@@ -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
View File
@@ -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>
+156 -83
View File
@@ -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>
&lt;filter&gt;
&lt;filter-name&gt;Acegi Filter Chain Proxy&lt;/filter-name&gt;
&lt;filter-class&gt;org.acegisecurity.util.FilterToBeanProxy&lt;/filter-class&gt;
&lt;init-param&gt;
&lt;param-name&gt;targetClass&lt;/param-name&gt;
&lt;param-value&gt;org.acegisecurity.util.FilterChainProxy&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;/filter&gt;
&lt;filter-mapping&gt;
&lt;filter-name&gt;Acegi Filter Chain Proxy&lt;/filter-name&gt;
&lt;url-pattern&gt;/*&lt;/url-pattern&gt;
&lt;/filter-mapping&gt;
</pre>
Next, locate the "contextConfigLocation" parameter, and add a new line into the existing param-value.
The resulting block will look like this:
<pre>
&lt;context-param&gt;
&lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
&lt;param-value&gt;
/WEB-INF/applicationContext-jdbc.xml
/WEB-INF/applicationContext-acegi-security.xml
&lt;/param-value&gt;
&lt;/context-param&gt;
</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>
&lt;table style="width:100%"&gt;&lt;tr&gt;
&lt;td&gt;&lt;A href="&lt;c:url value="/welcome.htm"/&gt;"&gt;Home&lt;/A&gt;&lt;/td&gt;
&lt;td&gt;&lt;A href="&lt;c:url value="/j_acegi_logout"/&gt;"&gt;Logout&lt;/A&gt;&lt;/td&gt;
&lt;td style="text-align:right;color:silver"&gt;PetClinic :: a Spring Framework demonstration&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
</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>
&lt;property name="objectDefinitionSource"&gt;
&lt;value&gt;
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/acegilogin.jsp=IS_AUTHENTICATED_ANONYMOUSLY
/**=IS_AUTHENTICATED_REMEMBERED
&lt;/value&gt;
&lt;/property&gt;
</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>
&lt;filter&gt;
&lt;filter-name&gt;Acegi Filter Chain Proxy&lt;/filter-name&gt;
&lt;filter-class&gt;org.acegisecurity.util.FilterToBeanProxy&lt;/filter-class&gt;
&lt;init-param&gt;
&lt;param-name&gt;targetClass&lt;/param-name&gt;
&lt;param-value&gt;org.acegisecurity.util.FilterChainProxy&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;/filter&gt;
&lt;filter-mapping&gt;
&lt;filter-name&gt;Acegi Filter Chain Proxy&lt;/filter-name&gt;
&lt;url-pattern&gt;/*&lt;/url-pattern&gt;
&lt;/filter-mapping&gt;
</pre>
Next, locate the "contextConfigLocation" parameter, and add a new line into the existing param-value.
The resulting block will look like this:
<pre>
&lt;context-param&gt;
&lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
&lt;param-value&gt;
/WEB-INF/applicationContext-jdbc.xml
/WEB-INF/applicationContext-acegi-security.xml
&lt;/param-value&gt;
&lt;/context-param&gt;
</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>
&lt;table style="width:100%"&gt;&lt;tr&gt;
&lt;td&gt;&lt;A href="&lt;c:url value="/welcome.htm"/&gt;"&gt;Home&lt;/A&gt;&lt;/td&gt;
&lt;td&gt;&lt;A href="&lt;c:url value="/j_acegi_logout"/&gt;"&gt;Logout&lt;/A&gt;&lt;/td&gt;
&lt;td style="text-align:right;color:silver"&gt;PetClinic :: a Spring Framework demonstration&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
</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>
&lt;property name="objectDefinitionSource"&gt;
&lt;value&gt;
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/acegilogin.jsp=IS_AUTHENTICATED_ANONYMOUSLY
/**=IS_AUTHENTICATED_REMEMBERED
&lt;/value&gt;
&lt;/property&gt;
</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>
&lt;property name="postInterceptors" ref="methodSecurityInterceptor"/&gt;
</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>
&lt;bean id="methodSecurityInterceptor" class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor"&gt;
&lt;property name="authenticationManager"&gt;&lt;ref bean="authenticationManager"/&gt;&lt;/property&gt;
&lt;property name="accessDecisionManager"&gt;
&lt;bean class="org.acegisecurity.vote.AffirmativeBased"&gt;
&lt;property name="allowIfAllAbstainDecisions" value="false"/&gt;
&lt;property name="decisionVoters"&gt;
&lt;list&gt;
&lt;bean class="org.acegisecurity.vote.RoleVoter"/&gt;
&lt;bean class="org.acegisecurity.vote.AuthenticatedVoter"/&gt;
&lt;/list&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;/property&gt;
&lt;property name="objectDefinitionSource"&gt;
&lt;value&gt;
org.springframework.samples.petclinic.Clinic.*=IS_AUTHENTICATED_REMEMBERED
org.springframework.samples.petclinic.Clinic.storeVisit=ROLE_SUPERVISOR
&lt;/value&gt;
&lt;/property&gt;
&lt;/bean&gt;
</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>
&lt;%@ taglib prefix="authz" uri="http://acegisecurity.org/authz" %&gt;
</pre>
Next, scroll down and find the link to "add visit". Modify it as follows:
<pre>
&lt;authz:authorize ifAllGranted="ROLE_SUPERVISOR"&gt;
&lt;FORM method=GET action="&lt;c:url value="/addVisit.htm"/&gt;" name="formVisitPet&lt;c:out value="${pet.id}"/&gt;"&gt;
&lt;INPUT type="hidden" name="petId" value="&lt;c:out value="${pet.id}"/&gt;"/&gt;
&lt;INPUT type="submit" value="Add Visit"/&gt;
&lt;/FORM&gt;
&lt;/authz:authorize&gt;
</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>
+106 -78
View File
@@ -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
View File
@@ -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>
+62 -16
View File
@@ -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
View File
@@ -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
View File
@@ -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>
+1 -1
View File
@@ -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>
+1 -1
View File
@@ -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>
+1 -1
View File
@@ -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>
+1 -1
View File
@@ -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
View File
@@ -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>
+11
View File
@@ -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
View File
@@ -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>