Browse Source

more final version of the various PasswordEncoder implementations.
add unit tests for PasswordEncoder implementations.
remove ignore password case and ignore username case flags and handling from DaoAuthenticationProvider.
remove requirement described in JavaDoc for AuthenticationDao that it ignore case when returning a user by username. Implementations may still do so if configured as such.

Colin Sampaleanu 21 years ago
parent
commit
5d9d734735
22 changed files with 276 additions and 152 deletions
  1. 44 0
      core/src/main/java/org/acegisecurity/providers/dao/BaseDigestPasswordEncoder.java
  2. 2 42
      core/src/main/java/org/acegisecurity/providers/dao/DaoAuthenticationProvider.java
  3. 28 22
      core/src/main/java/org/acegisecurity/providers/dao/MD5PasswordEncoder.java
  4. 2 2
      core/src/main/java/org/acegisecurity/providers/dao/PasswordEncoder.java
  5. 22 3
      core/src/main/java/org/acegisecurity/providers/dao/PlaintextPasswordEncoder.java
  6. 17 13
      core/src/main/java/org/acegisecurity/providers/dao/SHAPasswordEncoder.java
  7. 5 3
      core/src/main/java/org/acegisecurity/userdetails/UserDetailsService.java
  8. 0 2
      core/src/main/resources/org/acegisecurity/adapters/acegisecurity.xml
  9. 0 2
      core/src/main/resources/org/acegisecurity/providers/dao/jdbc/acegisecurity-jdbc.xml
  10. 0 2
      core/src/test/java/org/acegisecurity/adapters/adaptertest-valid.xml
  11. 0 2
      core/src/test/java/org/acegisecurity/intercept/web/securityfiltertest-valid.xml
  12. 2 41
      core/src/test/java/org/acegisecurity/providers/dao/DaoAuthenticationProviderTests.java
  13. 47 0
      core/src/test/java/org/acegisecurity/providers/dao/MD5PasswordEncoderTest.java
  14. 59 0
      core/src/test/java/org/acegisecurity/providers/dao/PlaintextPasswordEncoderTest.java
  15. 47 0
      core/src/test/java/org/acegisecurity/providers/dao/SHAPasswordEncoderTest.java
  16. 0 2
      core/src/test/java/org/acegisecurity/ui/webapp/filtertest-valid.xml
  17. 0 7
      docs/reference/src/index.xml
  18. 0 2
      samples/contacts/etc/ca/applicationContext.xml
  19. 0 2
      samples/contacts/etc/ca/resin-acegisecurity.xml
  20. 0 2
      samples/contacts/etc/filter/applicationContext.xml
  21. 0 2
      samples/contacts/etc/filter/web-filters-acegisecurity.xml
  22. 1 1
      test/acegisecuritytest.properties

+ 44 - 0
core/src/main/java/org/acegisecurity/providers/dao/BaseDigestPasswordEncoder.java

@@ -0,0 +1,44 @@
+/* Copyright 2004 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.acegisecurity.providers.dao;
+
+/**
+ * <p>
+ * Convenience base for Digest password encoders
+ * </p>
+ *
+ * @author colin sampaleanu
+ * @version $Id$
+ */
+public abstract class BaseDigestPasswordEncoder implements PasswordEncoder {
+  
+  //~ Instance fields ========================================================
+  private boolean encodeHashAsBase64 = false;
+
+  //~ Methods ================================================================
+  
+  /**
+   * The encoded password is normally returned as Hex (32 char) version of the
+   * hash bytes. Setting this property to true will cause the encoded pass to
+   * be returned as Base64 text, which will consume 24 characters.
+   */
+  public void setEncodeHashAsBase64(boolean encodeHashAsBase64) {
+    this.encodeHashAsBase64 = encodeHashAsBase64;
+  }
+  public boolean getEncodeHashAsBase64() {
+    return encodeHashAsBase64;
+  }
+
+}

+ 2 - 42
core/src/main/java/org/acegisecurity/providers/dao/DaoAuthenticationProvider.java

@@ -47,8 +47,6 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
 
 
     private AuthenticationDao authenticationDao;
     private AuthenticationDao authenticationDao;
     private PasswordEncoder passwordEncoder = new PlaintextPasswordEncoder();
     private PasswordEncoder passwordEncoder = new PlaintextPasswordEncoder();
-    private boolean ignorePasswordCase = false;
-    private boolean ignoreUsernameCase = true;
 
 
     //~ Methods ================================================================
     //~ Methods ================================================================
 
 
@@ -60,36 +58,6 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
         return authenticationDao;
         return authenticationDao;
     }
     }
 
 
-    /**
-     * Indicates whether the password comparison is case sensitive. Defaults to
-     * <code>false</code>, meaning an exact case match is required.
-     *
-     * @param ignorePasswordCase set to <code>true</code> for less stringent
-     *        comparison
-     */
-    public void setIgnorePasswordCase(boolean ignorePasswordCase) {
-        this.ignorePasswordCase = ignorePasswordCase;
-    }
-
-    public boolean isIgnorePasswordCase() {
-        return ignorePasswordCase;
-    }
-
-    /**
-     * Indicates whether the username search is case sensitive. Default to
-     * <code>true</code>, meaning an exact case match is not  required.
-     *
-     * @param ignoreUsernameCase set to <code>false</code> for more stringent
-     *        comparison
-     */
-    public void setIgnoreUsernameCase(boolean ignoreUsernameCase) {
-        this.ignoreUsernameCase = ignoreUsernameCase;
-    }
-
-    public boolean isIgnoreUsernameCase() {
-        return ignoreUsernameCase;
-    }
-
     /**
     /**
      * Sets the PasswordEncoder instance to be used to encode and validate
      * Sets the PasswordEncoder instance to be used to encode and validate
      * passwords. If not set, {@link PlaintextPasswordEncoder} will be used by
      * passwords. If not set, {@link PlaintextPasswordEncoder} will be used by
@@ -123,20 +91,12 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
             throw new BadCredentialsException("Bad credentials presented");
             throw new BadCredentialsException("Bad credentials presented");
         } catch (DataAccessException repositoryProblem) {
         } catch (DataAccessException repositoryProblem) {
             throw new AuthenticationServiceException(repositoryProblem
             throw new AuthenticationServiceException(repositoryProblem
-                .getMessage());
-        }
-
-        if ((!this.ignoreUsernameCase)
-            && (!user.getUsername().equals(authentication.getPrincipal()
-                                                         .toString()))) {
-            throw new BadCredentialsException("Bad credentials presented");
+                .getMessage(), repositoryProblem);
         }
         }
 
 
         if (!passwordEncoder.isPasswordValid(user.getPassword(),
         if (!passwordEncoder.isPasswordValid(user.getPassword(),
-                authentication.getCredentials().toString(), user,
-                ignorePasswordCase)) {
+                authentication.getCredentials().toString(), user))
             throw new BadCredentialsException("Bad credentials presented");
             throw new BadCredentialsException("Bad credentials presented");
-        }
 
 
         if (!user.isEnabled()) {
         if (!user.isEnabled()) {
             throw new DisabledException("User is disabled");
             throw new DisabledException("User is disabled");

+ 28 - 22
core/src/main/java/org/acegisecurity/providers/dao/MD5PasswordEncoder.java

@@ -15,6 +15,7 @@
 
 
 package net.sf.acegisecurity.providers.dao;
 package net.sf.acegisecurity.providers.dao;
 
 
+import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.codec.digest.DigestUtils;
 import org.apache.commons.codec.digest.DigestUtils;
 
 
 
 
@@ -24,34 +25,39 @@ import org.apache.commons.codec.digest.DigestUtils;
  * </p>
  * </p>
  * 
  * 
  * <p>
  * <p>
- * The ignorePasswordCase parameter is not used for this implementation.
- * </p>
- * 
- * <p>
  * A null password is encoded to the same value as an empty ("") password.
  * A null password is encoded to the same value as an empty ("") password.
  * </p>
  * </p>
  *
  *
  * @author colin sampaleanu
  * @author colin sampaleanu
  * @version $Id$
  * @version $Id$
  */
  */
-public class MD5PasswordEncoder implements PasswordEncoder {
+public class MD5PasswordEncoder extends BaseDigestPasswordEncoder implements PasswordEncoder {
     //~ Methods ================================================================
     //~ Methods ================================================================
 
 
-    /* (non-Javadoc)
-     * @see net.sf.acegisecurity.providers.dao.PasswordEncoder#isPasswordValid(net.sf.acegisecurity.providers.dao.User, java.lang.String, boolean)
-     */
-    public boolean isPasswordValid(String encPass, String rawPass,
-        Object saltSource, boolean ignorePasswordCase) {
-        String pass1 = "" + encPass;
-        String pass2 = DigestUtils.md5Hex("" + rawPass);
-
-        return pass1.equals(pass2);
-    }
-
-    /* (non-Javadoc)
-     * @see net.sf.acegisecurity.providers.dao.PasswordEncoder#encodePassword(java.lang.String, java.lang.Object)
-     */
-    public String encodePassword(String rawPass, Object saltSource) {
-        return DigestUtils.md5Hex("" + rawPass);
-    }
+  /* (non-Javadoc)
+   * @see net.sf.acegisecurity.providers.dao.PasswordEncoder#isPasswordValid(java.lang.String, java.lang.String, java.lang.Object)
+   */
+  public boolean isPasswordValid(String encPass, String rawPass, Object saltSource) {
+
+      String pass1 = "" + encPass;
+      String pass2 = encodeInternal("" + rawPass);
+
+      return pass1.equals(pass2);
+  }
+
+  /* (non-Javadoc)
+   * @see net.sf.acegisecurity.providers.dao.PasswordEncoder#encodePassword(java.lang.String, java.lang.Object)
+   */
+  public String encodePassword(String rawPass, Object saltSource) {
+      return encodeInternal("" + rawPass);
+  }
+  
+  private String encodeInternal(String input) {
+    
+    if (!getEncodeHashAsBase64())
+      return DigestUtils.md5Hex(input);
+    
+    byte[] encoded = Base64.encodeBase64(DigestUtils.md5(input));
+    return new String(encoded);
+  }
 }
 }

+ 2 - 2
core/src/main/java/org/acegisecurity/providers/dao/PasswordEncoder.java

@@ -31,8 +31,8 @@ public interface PasswordEncoder {
     //~ Methods ================================================================
     //~ Methods ================================================================
 
 
     public boolean isPasswordValid(String encPass, String rawPass,
     public boolean isPasswordValid(String encPass, String rawPass,
-        Object saltSource, boolean ignorePasswordCase)
+        Object saltSource)
         throws DataAccessException;
         throws DataAccessException;
 
 
-    public String encodePassword(String rawPass, Object saltSource);
+    public String encodePassword(String rawPass, Object saltSource) throws DataAccessException;
 }
 }

+ 22 - 3
core/src/main/java/org/acegisecurity/providers/dao/PlaintextPasswordEncoder.java

@@ -24,13 +24,32 @@ package net.sf.acegisecurity.providers.dao;
  * @version $Id$
  * @version $Id$
  */
  */
 public class PlaintextPasswordEncoder implements PasswordEncoder {
 public class PlaintextPasswordEncoder implements PasswordEncoder {
+  
+    //~ Instance fields ========================================================
+    private boolean ignorePasswordCase = false;
+  
     //~ Methods ================================================================
     //~ Methods ================================================================
+    
+    /**
+     * Indicates whether the password comparison is case sensitive. Defaults to
+     * <code>false</code>, meaning an exact case match is required.
+     *
+     * @param ignorePasswordCase set to <code>true</code> for less stringent
+     *        comparison
+     */
+    public void setIgnorePasswordCase(boolean ignorePasswordCase) {
+        this.ignorePasswordCase = ignorePasswordCase;
+    }
+
+    public boolean isIgnorePasswordCase() {
+        return ignorePasswordCase;
+    }
 
 
     /* (non-Javadoc)
     /* (non-Javadoc)
-     * @see net.sf.acegisecurity.providers.dao.PasswordEncoder#isPasswordValid(net.sf.acegisecurity.providers.dao.User, java.lang.String, boolean)
+     * @see net.sf.acegisecurity.providers.dao.PasswordEncoder#isPasswordValid(java.lang.String, java.lang.String, java.lang.Object)
      */
      */
-    public boolean isPasswordValid(String encPass, String rawPass,
-        Object saltSource, boolean ignorePasswordCase) {
+    public boolean isPasswordValid(String encPass, String rawPass, Object saltSource) {
+      
         String pass1 = "" + encPass;
         String pass1 = "" + encPass;
         String pass2 = "" + rawPass;
         String pass2 = "" + rawPass;
 
 

+ 17 - 13
core/src/main/java/org/acegisecurity/providers/dao/SHAPasswordEncoder.java

@@ -15,35 +15,30 @@
 
 
 package net.sf.acegisecurity.providers.dao;
 package net.sf.acegisecurity.providers.dao;
 
 
+import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.codec.digest.DigestUtils;
 import org.apache.commons.codec.digest.DigestUtils;
 
 
-
 /**
 /**
  * <p>
  * <p>
  * SHA implementation of PasswordEncoder.
  * SHA implementation of PasswordEncoder.
  * </p>
  * </p>
  * 
  * 
  * <p>
  * <p>
- * The ignorePasswordCase parameter is not used for this implementation.
- * </p>
- * 
- * <p>
  * A null password is encoded to the same value as an empty ("") password.
  * A null password is encoded to the same value as an empty ("") password.
  * </p>
  * </p>
  *
  *
  * @author colin sampaleanu
  * @author colin sampaleanu
  * @version $Id$
  * @version $Id$
  */
  */
-public class SHAPasswordEncoder implements PasswordEncoder {
-    //~ Methods ================================================================
-
+public class SHAPasswordEncoder extends BaseDigestPasswordEncoder implements PasswordEncoder {
+  
     /* (non-Javadoc)
     /* (non-Javadoc)
-     * @see net.sf.acegisecurity.providers.dao.PasswordEncoder#isPasswordValid(net.sf.acegisecurity.providers.dao.User, java.lang.String, boolean)
+     * @see net.sf.acegisecurity.providers.dao.PasswordEncoder#isPasswordValid(java.lang.String, java.lang.String, java.lang.Object)
      */
      */
-    public boolean isPasswordValid(String encPass, String rawPass,
-        Object saltSource, boolean ignorePasswordCase) {
+    public boolean isPasswordValid(String encPass, String rawPass, Object saltSource) {
+
         String pass1 = "" + encPass;
         String pass1 = "" + encPass;
-        String pass2 = DigestUtils.shaHex("" + rawPass);
+        String pass2 = encodeInternal("" + rawPass);
 
 
         return pass1.equals(pass2);
         return pass1.equals(pass2);
     }
     }
@@ -52,6 +47,15 @@ public class SHAPasswordEncoder implements PasswordEncoder {
      * @see net.sf.acegisecurity.providers.dao.PasswordEncoder#encodePassword(java.lang.String, java.lang.Object)
      * @see net.sf.acegisecurity.providers.dao.PasswordEncoder#encodePassword(java.lang.String, java.lang.Object)
      */
      */
     public String encodePassword(String rawPass, Object saltSource) {
     public String encodePassword(String rawPass, Object saltSource) {
-        return DigestUtils.shaHex("" + rawPass);
+        return encodeInternal("" + rawPass);
+    }
+    
+    private String encodeInternal(String input) {
+      
+      if (!getEncodeHashAsBase64())
+        return DigestUtils.shaHex(input);
+      
+      byte[] encoded = Base64.encodeBase64(DigestUtils.sha(input));
+      return new String(encoded);
     }
     }
 }
 }

+ 5 - 3
core/src/main/java/org/acegisecurity/userdetails/UserDetailsService.java

@@ -34,9 +34,11 @@ public interface AuthenticationDao {
     //~ Methods ================================================================
     //~ Methods ================================================================
 
 
     /**
     /**
-     * Locates the user based on the username. The search is case insensitive,
-     * meaning the implementation must return any matching object irrespective
-     * of the mixture of uppercase and lowercase characters in the username.
+     * Locates the user based on the username. In the actual implementation,
+     * the search may possibly be case insensitive, or case insensitive
+     * depending on how the implementaion instance is configured. In this case,
+     * the User object that comes back may have a username that is of a different
+     * case than what was actually requested..
      *
      *
      * @param username the username presented to the {@link
      * @param username the username presented to the {@link
      *        DaoAuthenticationProvider}
      *        DaoAuthenticationProvider}

+ 0 - 2
core/src/main/resources/org/acegisecurity/adapters/acegisecurity.xml

@@ -36,8 +36,6 @@
 	<!-- Authentication provider that queries our data access object  -->
 	<!-- Authentication provider that queries our data access object  -->
 	<bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
 	<bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
      	<property name="authenticationDao"><ref bean="inMemoryDaoImpl"/></property>
      	<property name="authenticationDao"><ref bean="inMemoryDaoImpl"/></property>
- 		<property name="ignorePasswordCase"><value>false</value></property>
- 		<property name="ignoreUsernameCase"><value>true</value></property>
 	</bean>
 	</bean>
 
 
 	<!-- The authentication manager that iterates through our only authentication provider -->
 	<!-- The authentication manager that iterates through our only authentication provider -->

+ 0 - 2
core/src/main/resources/org/acegisecurity/providers/dao/jdbc/acegisecurity-jdbc.xml

@@ -25,8 +25,6 @@
 	<!-- Authentication provider that queries our data access object  -->
 	<!-- Authentication provider that queries our data access object  -->
 	<bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
 	<bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
      	<property name="authenticationDao"><ref bean="jdbcDaoImpl"/></property>
      	<property name="authenticationDao"><ref bean="jdbcDaoImpl"/></property>
- 		<property name="ignorePasswordCase"><value>false</value></property>
- 		<property name="ignoreUsernameCase"><value>true</value></property>
 	</bean>
 	</bean>
 
 
 	<!-- The authentication manager that iterates through our only authentication provider -->
 	<!-- The authentication manager that iterates through our only authentication provider -->

+ 0 - 2
core/src/test/java/org/acegisecurity/adapters/adaptertest-valid.xml

@@ -36,8 +36,6 @@
 	<!-- Authentication provider that queries our data access object  -->
 	<!-- Authentication provider that queries our data access object  -->
 	<bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
 	<bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
      	<property name="authenticationDao"><ref bean="inMemoryDaoImpl"/></property>
      	<property name="authenticationDao"><ref bean="inMemoryDaoImpl"/></property>
- 		<property name="ignorePasswordCase"><value>false</value></property>
- 		<property name="ignoreUsernameCase"><value>true</value></property>
 	</bean>
 	</bean>
 
 
 	<!-- The authentication manager that iterates through our only authentication provider -->
 	<!-- The authentication manager that iterates through our only authentication provider -->

+ 0 - 2
core/src/test/java/org/acegisecurity/intercept/web/securityfiltertest-valid.xml

@@ -34,8 +34,6 @@
 	
 	
 	<bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
 	<bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
      	<property name="authenticationDao"><ref bean="inMemoryDaoImpl"/></property>
      	<property name="authenticationDao"><ref bean="inMemoryDaoImpl"/></property>
- 		<property name="ignorePasswordCase"><value>false</value></property>
- 		<property name="ignoreUsernameCase"><value>true</value></property>
 	</bean>
 	</bean>
 
 
 	<bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager">
 	<bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager">

+ 2 - 41
core/src/test/java/org/acegisecurity/providers/dao/DaoAuthenticationProviderTests.java

@@ -37,15 +37,6 @@ import org.springframework.dao.DataRetrievalFailureException;
  * @version $Id$
  * @version $Id$
  */
  */
 public class DaoAuthenticationProviderTests extends TestCase {
 public class DaoAuthenticationProviderTests extends TestCase {
-    //~ Constructors ===========================================================
-
-    public DaoAuthenticationProviderTests() {
-        super();
-    }
-
-    public DaoAuthenticationProviderTests(String arg0) {
-        super(arg0);
-    }
 
 
     //~ Methods ================================================================
     //~ Methods ================================================================
 
 
@@ -63,7 +54,6 @@ public class DaoAuthenticationProviderTests extends TestCase {
 
 
         DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
         DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
         provider.setAuthenticationDao(new MockAuthenticationDaoUserMarissa());
         provider.setAuthenticationDao(new MockAuthenticationDaoUserMarissa());
-        assertTrue(!provider.isIgnorePasswordCase()); // default
 
 
         try {
         try {
             provider.authenticate(token);
             provider.authenticate(token);
@@ -139,9 +129,6 @@ public class DaoAuthenticationProviderTests extends TestCase {
 
 
         DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
         DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
         provider.setAuthenticationDao(new MockAuthenticationDaoUserMarissa());
         provider.setAuthenticationDao(new MockAuthenticationDaoUserMarissa());
-        assertTrue(provider.isIgnoreUsernameCase()); // default
-        provider.setIgnoreUsernameCase(false);
-        assertTrue(!provider.isIgnoreUsernameCase()); // changed
 
 
         try {
         try {
             provider.authenticate(token);
             provider.authenticate(token);
@@ -151,32 +138,6 @@ public class DaoAuthenticationProviderTests extends TestCase {
         }
         }
     }
     }
 
 
-    public void testAuthenticateSuccessfulWithMixedCaseIfDefaultChanged() {
-        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa",
-                "KOAla");
-
-        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
-        provider.setAuthenticationDao(new MockAuthenticationDaoUserMarissa());
-        assertTrue(!provider.isIgnorePasswordCase()); // default
-        provider.setIgnorePasswordCase(true);
-        assertTrue(provider.isIgnorePasswordCase()); // changed
-
-        Authentication result = provider.authenticate(token);
-        assertEquals("marissa", result.getPrincipal().toString());
-    }
-
-    public void testAuthenticateSuccessfulWithMixedCaseUsername() {
-        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("MaRiSSA",
-                "koala");
-
-        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
-        provider.setAuthenticationDao(new MockAuthenticationDaoUserMarissa());
-        assertTrue(provider.isIgnoreUsernameCase()); // default
-
-        Authentication result = provider.authenticate(token);
-        assertEquals("marissa", result.getPrincipal().toString());
-    }
-
     public void testAuthenticates() {
     public void testAuthenticates() {
         UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa",
         UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa",
                 "koala");
                 "koala");
@@ -239,7 +200,7 @@ public class DaoAuthenticationProviderTests extends TestCase {
     private class MockAuthenticationDaoUserMarissa implements AuthenticationDao {
     private class MockAuthenticationDaoUserMarissa implements AuthenticationDao {
         public User loadUserByUsername(String username)
         public User loadUserByUsername(String username)
             throws UsernameNotFoundException, DataAccessException {
             throws UsernameNotFoundException, DataAccessException {
-            if ("marissa".equals(username.toLowerCase())) {
+            if ("marissa".equals(username)) {
                 return new User("marissa", "koala", true,
                 return new User("marissa", "koala", true,
                     new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
                     new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
                             "ROLE_TWO")});
                             "ROLE_TWO")});
@@ -253,7 +214,7 @@ public class DaoAuthenticationProviderTests extends TestCase {
     private class MockAuthenticationDaoUserPeter implements AuthenticationDao {
     private class MockAuthenticationDaoUserPeter implements AuthenticationDao {
         public User loadUserByUsername(String username)
         public User loadUserByUsername(String username)
             throws UsernameNotFoundException, DataAccessException {
             throws UsernameNotFoundException, DataAccessException {
-            if ("peter".equals(username.toLowerCase())) {
+            if ("peter".equals(username)) {
                 return new User("peter", "opal", false,
                 return new User("peter", "opal", false,
                     new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
                     new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
                             "ROLE_TWO")});
                             "ROLE_TWO")});

+ 47 - 0
core/src/test/java/org/acegisecurity/providers/dao/MD5PasswordEncoderTest.java

@@ -0,0 +1,47 @@
+/* Copyright 2004 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.acegisecurity.providers.dao;
+
+import junit.framework.TestCase;
+
+/**
+ * <p>
+ * TestCase for PlaintextPasswordEncoder.
+ * </p>
+ *
+ * @author colin sampaleanu
+ * @version $Id$
+ */
+public class MD5PasswordEncoderTest extends TestCase {
+
+  public void testBasicFunctionality() {
+    
+    MD5PasswordEncoder pe = new MD5PasswordEncoder();
+    String raw = "abc123";
+    String badRaw = "abc321";
+    String encoded = pe.encodePassword(raw, null);   // no SALT source
+    assertTrue(pe.isPasswordValid(encoded, raw, null));
+    assertFalse(pe.isPasswordValid(encoded, badRaw, null));
+    assertTrue(encoded.length() == 32);
+    
+    // now try Base64
+    pe.setEncodeHashAsBase64(true);
+    encoded = pe.encodePassword(raw, null);   // no SALT source
+    assertTrue(pe.isPasswordValid(encoded, raw, null));
+    assertFalse(pe.isPasswordValid(encoded, badRaw, null));
+    assertTrue(encoded.length() != 32);
+  }
+
+}

+ 59 - 0
core/src/test/java/org/acegisecurity/providers/dao/PlaintextPasswordEncoderTest.java

@@ -0,0 +1,59 @@
+/* Copyright 2004 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.acegisecurity.providers.dao;
+
+import junit.framework.TestCase;
+
+/**
+ * <p>
+ * TestCase for PlaintextPasswordEncoder.
+ * </p>
+ *
+ * @author colin sampaleanu
+ * @version $Id$
+ */
+public class PlaintextPasswordEncoderTest extends TestCase {
+
+  public void testBasicFunctionality() {
+    PlaintextPasswordEncoder pe = new PlaintextPasswordEncoder();
+
+    String raw = "abc123";
+    String rawDiffCase = "AbC123";
+    String badRaw = "abc321";
+    // should be able to validate even without encoding
+    String encoded = raw;
+    assertTrue(pe.isPasswordValid(encoded, raw, null));   // no SALT source
+    assertFalse(pe.isPasswordValid(encoded, badRaw, null));
+
+    // now make sure encoded version it gives us back is comparable as well
+    encoded = pe.encodePassword(raw, null);
+    assertTrue(pe.isPasswordValid(encoded, raw, null));   // no SALT source
+    assertFalse(pe.isPasswordValid(encoded, badRaw, null));
+    
+    // make sure default is not to ignore password case
+    encoded = pe.encodePassword(rawDiffCase, null);
+    assertFalse(pe.isPasswordValid(encoded, raw, null));
+    
+    // now check for ignore password case
+    pe = new PlaintextPasswordEncoder();
+    pe.setIgnorePasswordCase(true);
+
+    // should be able to validate even without encoding
+    encoded = pe.encodePassword(rawDiffCase, null);
+    assertTrue(pe.isPasswordValid(encoded, raw, null));
+    assertFalse(pe.isPasswordValid(encoded, badRaw, null));
+  }
+
+}

+ 47 - 0
core/src/test/java/org/acegisecurity/providers/dao/SHAPasswordEncoderTest.java

@@ -0,0 +1,47 @@
+/* Copyright 2004 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.acegisecurity.providers.dao;
+
+import junit.framework.TestCase;
+
+/**
+ * <p>
+ * TestCase for SHAPasswordEncoder.
+ * </p>
+ *
+ * @author colin sampaleanu
+ * @version $Id$
+ */
+public class SHAPasswordEncoderTest extends TestCase {
+
+  public void testBasicFunctionality() {
+    
+    SHAPasswordEncoder pe = new SHAPasswordEncoder();
+    String raw = "abc123";
+    String badRaw = "abc321";
+    String encoded = pe.encodePassword(raw, null);   // no SALT source
+    assertTrue(pe.isPasswordValid(encoded, raw, null));
+    assertFalse(pe.isPasswordValid(encoded, badRaw, null));
+    assertTrue(encoded.length() == 40);
+    
+    // now try Base64
+    pe.setEncodeHashAsBase64(true);
+    encoded = pe.encodePassword(raw, null);   // no SALT source
+    assertTrue(pe.isPasswordValid(encoded, raw, null));
+    assertFalse(pe.isPasswordValid(encoded, badRaw, null));
+    assertTrue(encoded.length() != 40);
+    
+  }
+}

+ 0 - 2
core/src/test/java/org/acegisecurity/ui/webapp/filtertest-valid.xml

@@ -36,8 +36,6 @@
 	<!-- Authentication provider that queries our data access object  -->
 	<!-- Authentication provider that queries our data access object  -->
 	<bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
 	<bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
      	<property name="authenticationDao"><ref bean="inMemoryDaoImpl"/></property>
      	<property name="authenticationDao"><ref bean="inMemoryDaoImpl"/></property>
- 		<property name="ignorePasswordCase"><value>false</value></property>
- 		<property name="ignoreUsernameCase"><value>true</value></property>
 	</bean>
 	</bean>
 
 
 	<!-- The authentication manager that iterates through our only authentication provider -->
 	<!-- The authentication manager that iterates through our only authentication provider -->

+ 0 - 7
docs/reference/src/index.xml

@@ -850,15 +850,8 @@
 
 
         <para><programlisting>&lt;bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider"&gt;
         <para><programlisting>&lt;bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider"&gt;
   &lt;property name="authenticationDao"&gt;&lt;ref bean="inMemoryDaoImpl"/&gt;&lt;/property&gt;
   &lt;property name="authenticationDao"&gt;&lt;ref bean="inMemoryDaoImpl"/&gt;&lt;/property&gt;
-  &lt;property name="ignorePasswordCase"&gt;&lt;value&gt;false&lt;/value&gt;&lt;/property&gt;
-  &lt;property name="ignoreUsernameCase"&gt;&lt;value&gt;true&lt;/value&gt;&lt;/property&gt;
 &lt;/bean&gt;</programlisting></para>
 &lt;/bean&gt;</programlisting></para>
 
 
-        <para>By default the <literal>DaoAuthenticationProvider</literal> does
-        not require an exact match on usernames, but it does require an exact
-        match on passwords. This behavior can be configured with the optional
-        properties shown above.</para>
-
         <para>For a class to be able to provide the
         <para>For a class to be able to provide the
         <literal>DaoAuthenticationProvider</literal> with access to an
         <literal>DaoAuthenticationProvider</literal> with access to an
         authentication repository, it must implement the
         authentication repository, it must implement the

+ 0 - 2
samples/contacts/etc/ca/applicationContext.xml

@@ -48,8 +48,6 @@
 	
 	
 	<bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
 	<bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
      	<property name="authenticationDao"><ref bean="inMemoryDaoImpl"/></property>
      	<property name="authenticationDao"><ref bean="inMemoryDaoImpl"/></property>
- 		<property name="ignorePasswordCase"><value>false</value></property>
- 		<property name="ignoreUsernameCase"><value>true</value></property>
 	</bean>
 	</bean>
 
 
 	<!-- ~~~~~~~~~~~~~~~~~~~~ AUTHORIZATION DEFINITIONS ~~~~~~~~~~~~~~~~~~~ -->
 	<!-- ~~~~~~~~~~~~~~~~~~~~ AUTHORIZATION DEFINITIONS ~~~~~~~~~~~~~~~~~~~ -->

+ 0 - 2
samples/contacts/etc/ca/resin-acegisecurity.xml

@@ -33,8 +33,6 @@
 	<!-- Authentication provider that queries our data access object  -->
 	<!-- Authentication provider that queries our data access object  -->
 	<bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
 	<bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
      	<property name="authenticationDao"><ref bean="inMemoryDaoImpl"/></property>
      	<property name="authenticationDao"><ref bean="inMemoryDaoImpl"/></property>
- 		<property name="ignorePasswordCase"><value>false</value></property>
- 		<property name="ignoreUsernameCase"><value>true</value></property>
 	</bean>
 	</bean>
 
 
 	<!-- The authentication manager that iterates through our only authentication provider -->
 	<!-- The authentication manager that iterates through our only authentication provider -->

+ 0 - 2
samples/contacts/etc/filter/applicationContext.xml

@@ -43,8 +43,6 @@
 	
 	
 	<bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
 	<bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
      	<property name="authenticationDao"><ref bean="inMemoryDaoImpl"/></property>
      	<property name="authenticationDao"><ref bean="inMemoryDaoImpl"/></property>
- 		<property name="ignorePasswordCase"><value>false</value></property>
- 		<property name="ignoreUsernameCase"><value>true</value></property>
 	</bean>
 	</bean>
 
 
 	<!-- ~~~~~~~~~~~~~~~~~~~~ AUTHORIZATION DEFINITIONS ~~~~~~~~~~~~~~~~~~~ -->
 	<!-- ~~~~~~~~~~~~~~~~~~~~ AUTHORIZATION DEFINITIONS ~~~~~~~~~~~~~~~~~~~ -->

+ 0 - 2
samples/contacts/etc/filter/web-filters-acegisecurity.xml

@@ -40,8 +40,6 @@
 	<!-- Authentication provider that queries our data access object  -->
 	<!-- Authentication provider that queries our data access object  -->
 	<bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
 	<bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
      	<property name="authenticationDao"><ref bean="inMemoryDaoImpl"/></property>
      	<property name="authenticationDao"><ref bean="inMemoryDaoImpl"/></property>
- 		<property name="ignorePasswordCase"><value>false</value></property>
- 		<property name="ignoreUsernameCase"><value>true</value></property>
 	</bean>
 	</bean>
 
 
 	<!-- The authentication manager that iterates through our only authentication provider -->
 	<!-- The authentication manager that iterates through our only authentication provider -->

+ 1 - 1
test/acegisecuritytest.properties

@@ -1,5 +1,5 @@
 #HSQL database
 #HSQL database
-#Wed Apr 14 23:23:24 EDT 2004
+#Thu Apr 15 12:20:59 EDT 2004
 sql.strict_fk=true
 sql.strict_fk=true
 readonly=false
 readonly=false
 sql.strong_fk=true
 sql.strong_fk=true