mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-07-08 03:32:39 +00:00
SEC-985: Added hideUsernameNotFoundException property to LdapAuthenticationProvider and set default to true.
This commit is contained in:
parent
4d81d750cd
commit
843d0e6910
@ -16,6 +16,7 @@
|
|||||||
package org.springframework.security.ldap;
|
package org.springframework.security.ldap;
|
||||||
|
|
||||||
import org.springframework.ldap.core.DirContextOperations;
|
import org.springframework.ldap.core.DirContextOperations;
|
||||||
|
import org.springframework.security.userdetails.UsernameNotFoundException;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,6 +39,7 @@ public interface LdapUserSearch {
|
|||||||
* @param username the login name supplied to the authentication service.
|
* @param username the login name supplied to the authentication service.
|
||||||
*
|
*
|
||||||
* @return a DirContextOperations object containing the user's full DN and requested attributes.
|
* @return a DirContextOperations object containing the user's full DN and requested attributes.
|
||||||
|
* @throws UsernameNotFoundException if no user with the supplied name could be located by the search.
|
||||||
*/
|
*/
|
||||||
DirContextOperations searchForUser(String username);
|
DirContextOperations searchForUser(String username) throws UsernameNotFoundException;
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ import org.springframework.security.ldap.populator.DefaultLdapAuthoritiesPopulat
|
|||||||
import org.springframework.security.providers.AuthenticationProvider;
|
import org.springframework.security.providers.AuthenticationProvider;
|
||||||
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
|
||||||
import org.springframework.security.userdetails.UserDetails;
|
import org.springframework.security.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.userdetails.UsernameNotFoundException;
|
||||||
import org.springframework.security.userdetails.ldap.LdapUserDetailsMapper;
|
import org.springframework.security.userdetails.ldap.LdapUserDetailsMapper;
|
||||||
import org.springframework.security.userdetails.ldap.UserDetailsContextMapper;
|
import org.springframework.security.userdetails.ldap.UserDetailsContextMapper;
|
||||||
import org.springframework.security.util.AuthorityUtils;
|
import org.springframework.security.util.AuthorityUtils;
|
||||||
@ -137,6 +138,7 @@ public class LdapAuthenticationProvider implements AuthenticationProvider {
|
|||||||
private LdapAuthoritiesPopulator authoritiesPopulator;
|
private LdapAuthoritiesPopulator authoritiesPopulator;
|
||||||
private UserDetailsContextMapper userDetailsContextMapper = new LdapUserDetailsMapper();
|
private UserDetailsContextMapper userDetailsContextMapper = new LdapUserDetailsMapper();
|
||||||
private boolean useAuthenticationRequestCredentials = true;
|
private boolean useAuthenticationRequestCredentials = true;
|
||||||
|
private boolean hideUserNotFoundExceptions = true;
|
||||||
|
|
||||||
//~ Constructors ===================================================================================================
|
//~ Constructors ===================================================================================================
|
||||||
|
|
||||||
@ -193,6 +195,10 @@ public class LdapAuthenticationProvider implements AuthenticationProvider {
|
|||||||
return userDetailsContextMapper;
|
return userDetailsContextMapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setHideUserNotFoundExceptions(boolean hideUserNotFoundExceptions) {
|
||||||
|
this.hideUserNotFoundExceptions = hideUserNotFoundExceptions;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines whether the supplied password will be used as the credentials in the successful authentication
|
* Determines whether the supplied password will be used as the credentials in the successful authentication
|
||||||
* token. If set to false, then the password will be obtained from the UserDetails object
|
* token. If set to false, then the password will be obtained from the UserDetails object
|
||||||
@ -236,7 +242,13 @@ public class LdapAuthenticationProvider implements AuthenticationProvider {
|
|||||||
UserDetails user = userDetailsContextMapper.mapUserFromContext(userData, username, extraAuthorities);
|
UserDetails user = userDetailsContextMapper.mapUserFromContext(userData, username, extraAuthorities);
|
||||||
|
|
||||||
return createSuccessfulAuthentication(userToken, user);
|
return createSuccessfulAuthentication(userToken, user);
|
||||||
|
} catch (UsernameNotFoundException notFound) {
|
||||||
|
if (hideUserNotFoundExceptions) {
|
||||||
|
throw new BadCredentialsException(messages.getMessage(
|
||||||
|
"LdapAuthenticationProvider.badCredentials", "Bad credentials"));
|
||||||
|
} else {
|
||||||
|
throw notFound;
|
||||||
|
}
|
||||||
} catch (NamingException ldapAccessFailure) {
|
} catch (NamingException ldapAccessFailure) {
|
||||||
throw new AuthenticationServiceException(ldapAccessFailure.getMessage(), ldapAccessFailure);
|
throw new AuthenticationServiceException(ldapAccessFailure.getMessage(), ldapAccessFailure);
|
||||||
}
|
}
|
||||||
|
@ -15,24 +15,28 @@
|
|||||||
|
|
||||||
package org.springframework.security.providers.ldap;
|
package org.springframework.security.providers.ldap;
|
||||||
|
|
||||||
import org.springframework.security.Authentication;
|
import static org.junit.Assert.*;
|
||||||
import org.springframework.security.BadCredentialsException;
|
|
||||||
import org.springframework.security.GrantedAuthority;
|
|
||||||
import org.springframework.security.GrantedAuthorityImpl;
|
|
||||||
import org.springframework.security.ldap.LdapAuthoritiesPopulator;
|
|
||||||
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
|
|
||||||
import org.springframework.security.userdetails.UserDetails;
|
|
||||||
import org.springframework.security.userdetails.ldap.LdapUserDetailsMapper;
|
|
||||||
import org.springframework.security.util.AuthorityUtils;
|
|
||||||
import org.springframework.ldap.core.DirContextAdapter;
|
|
||||||
import org.springframework.ldap.core.DirContextOperations;
|
|
||||||
import org.springframework.ldap.core.DistinguishedName;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jmock.Expectations;
|
||||||
|
import org.jmock.Mockery;
|
||||||
|
import org.jmock.integration.junit4.JUnit4Mockery;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.ldap.core.DirContextAdapter;
|
||||||
|
import org.springframework.ldap.core.DirContextOperations;
|
||||||
|
import org.springframework.ldap.core.DistinguishedName;
|
||||||
|
import org.springframework.security.Authentication;
|
||||||
|
import org.springframework.security.BadCredentialsException;
|
||||||
|
import org.springframework.security.GrantedAuthority;
|
||||||
|
import org.springframework.security.ldap.LdapAuthoritiesPopulator;
|
||||||
|
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.userdetails.UsernameNotFoundException;
|
||||||
|
import org.springframework.security.userdetails.ldap.LdapUserDetailsMapper;
|
||||||
|
import org.springframework.security.util.AuthorityUtils;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests {@link LdapAuthenticationProvider}.
|
* Tests {@link LdapAuthenticationProvider}.
|
||||||
@ -40,19 +44,12 @@ import java.util.List;
|
|||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class LdapAuthenticationProviderTests extends TestCase {
|
public class LdapAuthenticationProviderTests {
|
||||||
//~ Constructors ===================================================================================================
|
Mockery jmock = new JUnit4Mockery();
|
||||||
|
|
||||||
public LdapAuthenticationProviderTests(String string) {
|
|
||||||
super(string);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LdapAuthenticationProviderTests() {
|
|
||||||
}
|
|
||||||
|
|
||||||
//~ Methods ========================================================================================================
|
//~ Methods ========================================================================================================
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testSupportsUsernamePasswordAuthenticationToken() {
|
public void testSupportsUsernamePasswordAuthenticationToken() {
|
||||||
LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider(new MockAuthenticator(),
|
LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider(new MockAuthenticator(),
|
||||||
new MockAuthoritiesPopulator());
|
new MockAuthoritiesPopulator());
|
||||||
@ -60,6 +57,7 @@ public class LdapAuthenticationProviderTests extends TestCase {
|
|||||||
assertTrue(ldapProvider.supports(UsernamePasswordAuthenticationToken.class));
|
assertTrue(ldapProvider.supports(UsernamePasswordAuthenticationToken.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testDefaultMapperIsSet() {
|
public void testDefaultMapperIsSet() {
|
||||||
LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider(new MockAuthenticator(),
|
LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider(new MockAuthenticator(),
|
||||||
new MockAuthoritiesPopulator());
|
new MockAuthoritiesPopulator());
|
||||||
@ -67,6 +65,7 @@ public class LdapAuthenticationProviderTests extends TestCase {
|
|||||||
assertTrue(ldapProvider.getUserDetailsContextMapper() instanceof LdapUserDetailsMapper);
|
assertTrue(ldapProvider.getUserDetailsContextMapper() instanceof LdapUserDetailsMapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testEmptyOrNullUserNameThrowsException() {
|
public void testEmptyOrNullUserNameThrowsException() {
|
||||||
LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider(new MockAuthenticator(),
|
LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider(new MockAuthenticator(),
|
||||||
new MockAuthoritiesPopulator());
|
new MockAuthoritiesPopulator());
|
||||||
@ -82,15 +81,46 @@ public class LdapAuthenticationProviderTests extends TestCase {
|
|||||||
} catch (BadCredentialsException expected) {}
|
} catch (BadCredentialsException expected) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testEmptyPasswordIsRejected() {
|
@Test(expected=BadCredentialsException.class)
|
||||||
|
public void emptyPasswordIsRejected() {
|
||||||
LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider(new MockAuthenticator());
|
LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider(new MockAuthenticator());
|
||||||
try {
|
|
||||||
ldapProvider.authenticate(new UsernamePasswordAuthenticationToken("jen", ""));
|
ldapProvider.authenticate(new UsernamePasswordAuthenticationToken("jen", ""));
|
||||||
fail("Expected BadCredentialsException for empty password");
|
|
||||||
} catch (BadCredentialsException expected) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNormalUsage() {
|
@Test
|
||||||
|
public void usernameNotFoundExceptionIsHiddenByDefault() {
|
||||||
|
final LdapAuthenticator authenticator = jmock.mock(LdapAuthenticator.class);
|
||||||
|
final UsernamePasswordAuthenticationToken joe = new UsernamePasswordAuthenticationToken("joe", "password");
|
||||||
|
jmock.checking(new Expectations() {{
|
||||||
|
oneOf(authenticator).authenticate(joe); will(throwException(new UsernameNotFoundException("nobody")));
|
||||||
|
}});
|
||||||
|
|
||||||
|
LdapAuthenticationProvider provider = new LdapAuthenticationProvider(authenticator);
|
||||||
|
try {
|
||||||
|
provider.authenticate(joe);
|
||||||
|
fail();
|
||||||
|
} catch (BadCredentialsException expected) {
|
||||||
|
if (expected instanceof UsernameNotFoundException) {
|
||||||
|
fail("Exception should have been hidden");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected=UsernameNotFoundException.class)
|
||||||
|
public void usernameNotFoundExceptionIsNotHiddenIfConfigured() {
|
||||||
|
final LdapAuthenticator authenticator = jmock.mock(LdapAuthenticator.class);
|
||||||
|
final UsernamePasswordAuthenticationToken joe = new UsernamePasswordAuthenticationToken("joe", "password");
|
||||||
|
jmock.checking(new Expectations() {{
|
||||||
|
oneOf(authenticator).authenticate(joe); will(throwException(new UsernameNotFoundException("nobody")));
|
||||||
|
}});
|
||||||
|
|
||||||
|
LdapAuthenticationProvider provider = new LdapAuthenticationProvider(authenticator);
|
||||||
|
provider.setHideUserNotFoundExceptions(false);
|
||||||
|
provider.authenticate(joe);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void normalUsage() {
|
||||||
MockAuthoritiesPopulator populator = new MockAuthoritiesPopulator();
|
MockAuthoritiesPopulator populator = new MockAuthoritiesPopulator();
|
||||||
LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider(new MockAuthenticator(), populator);
|
LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider(new MockAuthenticator(), populator);
|
||||||
LdapUserDetailsMapper userMapper = new LdapUserDetailsMapper();
|
LdapUserDetailsMapper userMapper = new LdapUserDetailsMapper();
|
||||||
@ -116,7 +146,8 @@ public class LdapAuthenticationProviderTests extends TestCase {
|
|||||||
assertTrue(authorities.contains("ROLE_FROM_POPULATOR"));
|
assertTrue(authorities.contains("ROLE_FROM_POPULATOR"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testPasswordIsSetFromUserDataIfUseAuthenticationRequestCredentialsIsFalse() {
|
@Test
|
||||||
|
public void passwordIsSetFromUserDataIfUseAuthenticationRequestCredentialsIsFalse() {
|
||||||
LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider(new MockAuthenticator(),
|
LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider(new MockAuthenticator(),
|
||||||
new MockAuthoritiesPopulator());
|
new MockAuthoritiesPopulator());
|
||||||
ldapProvider.setUseAuthenticationRequestCredentials(false);
|
ldapProvider.setUseAuthenticationRequestCredentials(false);
|
||||||
@ -127,7 +158,8 @@ public class LdapAuthenticationProviderTests extends TestCase {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testUseWithNullAuthoritiesPopulatorReturnsCorrectRole() {
|
@Test
|
||||||
|
public void useWithNullAuthoritiesPopulatorReturnsCorrectRole() {
|
||||||
LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider(new MockAuthenticator());
|
LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider(new MockAuthenticator());
|
||||||
LdapUserDetailsMapper userMapper = new LdapUserDetailsMapper();
|
LdapUserDetailsMapper userMapper = new LdapUserDetailsMapper();
|
||||||
userMapper.setRoleAttributes(new String[] {"ou"});
|
userMapper.setRoleAttributes(new String[] {"ou"});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user