浏览代码

Added DaoAuthenticationProvider.hideUserNotFoundExceptions property. Defaults to true, so BadCredentialsException is thrown instead of UsernameNotFoundException if a user cannot be found.

Ben Alex 21 年之前
父节点
当前提交
aaebd3ef5a

+ 1 - 0
changelog.txt

@@ -3,6 +3,7 @@ Changes in version 0.x (2004-xx-xx)
 
 * Added additional DaoAuthenticationProvider event when user not found
 * Added Authentication.getDetails() to DaoAuthenticationProvider response
+* Added DaoAuthenticationProvider.hideUserNotFoundExceptions (default=true)
 * Extracted removeUserFromCache(String) to UserCache interface
 * Improved ConfigAttributeEditor so it trims preceding and trailing spaces
 * Fixed EH-CACHE-based caching implementation behaviour when cache exists

+ 28 - 1
core/src/main/java/org/acegisecurity/providers/dao/DaoAuthenticationProvider.java

@@ -98,6 +98,7 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
     private SaltSource saltSource;
     private UserCache userCache = new NullUserCache();
     private boolean forcePrincipalAsString = false;
+    private boolean hideUserNotFoundExceptions = true;
 
     //~ Methods ================================================================
 
@@ -126,6 +127,28 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
         return forcePrincipalAsString;
     }
 
+    /**
+     * By default the <code>DaoAuthenticationProvider</code> throws a
+     * <code>BadCredentialsException</code> if a username is not found or the
+     * password is incorrect. Setting this property to <code>false</code> will
+     * cause <code>UsernameNotFoundException</code>s to be thrown instead for
+     * the former. Note this is considered less secure than throwing
+     * <code>BadCredentialsException</code> for both events.
+     *
+     * @param hideUserNotFoundExceptions set to <code>false</code> if you wish
+     *        <code>UsernameNotFoundException</code>s to be thrown instead of
+     *        the non-specific <code>BadCredentialsException</code> (defaults
+     *        to <code>true</code>)
+     */
+    public void setHideUserNotFoundExceptions(
+        boolean hideUserNotFoundExceptions) {
+        this.hideUserNotFoundExceptions = hideUserNotFoundExceptions;
+    }
+
+    public boolean isHideUserNotFoundExceptions() {
+        return hideUserNotFoundExceptions;
+    }
+
     /**
      * Sets the PasswordEncoder instance to be used to encode and validate
      * passwords. If not set, {@link PlaintextPasswordEncoder} will be used by
@@ -335,7 +358,11 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
         try {
             return this.authenticationDao.loadUserByUsername(username);
         } catch (UsernameNotFoundException notFound) {
-            throw new BadCredentialsException("Bad credentials presented");
+            if (hideUserNotFoundExceptions) {
+                throw new BadCredentialsException("Bad credentials presented");
+            } else {
+                throw notFound;
+            }
         } catch (DataAccessException repositoryProblem) {
             throw new AuthenticationServiceException(repositoryProblem
                 .getMessage(), repositoryProblem);

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

@@ -15,7 +15,7 @@
 
 package net.sf.acegisecurity.providers.dao;
 
-import net.sf.acegisecurity.AuthenticationException;
+import net.sf.acegisecurity.BadCredentialsException;
 
 
 /**
@@ -25,7 +25,7 @@ import net.sf.acegisecurity.AuthenticationException;
  * @author Ben Alex
  * @version $Id$
  */
-public class UsernameNotFoundException extends AuthenticationException {
+public class UsernameNotFoundException extends BadCredentialsException {
     //~ Constructors ===========================================================
 
     /**

+ 19 - 1
core/src/test/java/org/acegisecurity/providers/dao/DaoAuthenticationProviderTests.java

@@ -119,11 +119,29 @@ public class DaoAuthenticationProviderTests extends TestCase {
         }
     }
 
-    public void testAuthenticateFailsWithInvalidUsername() {
+    public void testAuthenticateFailsWithInvalidUsernameAndHideUserNotFoundExceptionFalse() {
         UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("INVALID_USER",
                 "koala");
 
         DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
+        provider.setHideUserNotFoundExceptions(false); // we want UsernameNotFoundExceptions
+        provider.setAuthenticationDao(new MockAuthenticationDaoUserMarissa());
+        provider.setUserCache(new MockUserCache());
+
+        try {
+            provider.authenticate(token);
+            fail("Should have thrown UsernameNotFoundException");
+        } catch (UsernameNotFoundException expected) {
+            assertTrue(true);
+        }
+    }
+
+    public void testAuthenticateFailsWithInvalidUsernameAndHideUserNotFoundExceptionsWithDefaultOfTrue() {
+        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("INVALID_USER",
+                "koala");
+
+        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
+        assertTrue(provider.isHideUserNotFoundExceptions());
         provider.setAuthenticationDao(new MockAuthenticationDaoUserMarissa());
         provider.setUserCache(new MockUserCache());