diff --git a/changelog.txt b/changelog.txt index 2f98f29ad2..793cf542d3 100644 --- a/changelog.txt +++ b/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 diff --git a/core/src/main/java/org/acegisecurity/providers/dao/DaoAuthenticationProvider.java b/core/src/main/java/org/acegisecurity/providers/dao/DaoAuthenticationProvider.java index 0638fc3514..83e460cc5f 100644 --- a/core/src/main/java/org/acegisecurity/providers/dao/DaoAuthenticationProvider.java +++ b/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 DaoAuthenticationProvider throws a + * BadCredentialsException if a username is not found or the + * password is incorrect. Setting this property to false will + * cause UsernameNotFoundExceptions to be thrown instead for + * the former. Note this is considered less secure than throwing + * BadCredentialsException for both events. + * + * @param hideUserNotFoundExceptions set to false if you wish + * UsernameNotFoundExceptions to be thrown instead of + * the non-specific BadCredentialsException (defaults + * to true) + */ + 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); diff --git a/core/src/main/java/org/acegisecurity/providers/dao/UsernameNotFoundException.java b/core/src/main/java/org/acegisecurity/providers/dao/UsernameNotFoundException.java index 31f441508f..a0362a621f 100644 --- a/core/src/main/java/org/acegisecurity/providers/dao/UsernameNotFoundException.java +++ b/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 =========================================================== /** diff --git a/core/src/test/java/org/acegisecurity/providers/dao/DaoAuthenticationProviderTests.java b/core/src/test/java/org/acegisecurity/providers/dao/DaoAuthenticationProviderTests.java index 186e8cffe9..e57338397f 100644 --- a/core/src/test/java/org/acegisecurity/providers/dao/DaoAuthenticationProviderTests.java +++ b/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());