SEC-607: Changed NtlmUsernamePasswordAuthenticationToken to make authenticated=true the default state when an instance is created. NtlmAwareLdapAuthenticator now rejects tokens with authenticated=false (e.g. if the token has been passed remotely).
This commit is contained in:
parent
4f3a1739aa
commit
292320bd33
|
@ -20,9 +20,10 @@ import org.springframework.security.GrantedAuthority;
|
|||
|
||||
/**
|
||||
* An {@link org.springframework.security.Authentication} implementation that is designed for simple presentation of a
|
||||
* username and password.<p>The <code>principal</code> and <code>credentials</code> should be set with an
|
||||
* <code>Object</code> that provides the respective property via its <code>Object.toString()</code> method. The
|
||||
* simplest such <code>Object</code> to use is <code>String</code>.</p>
|
||||
* username and password.
|
||||
* <p>The <code>principal</code> and <code>credentials</code> should be set with an <code>Object</code> that provides
|
||||
* the respective property via its <code>Object.toString()</code> method. The simplest such <code>Object</code> to use
|
||||
* is <code>String</code>.</p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
|
@ -36,13 +37,11 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT
|
|||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
/**
|
||||
/**
|
||||
* This constructor can be safely used by any code that wishes to create a
|
||||
* <code>UsernamePasswordAuthenticationToken</code>, as the {@link
|
||||
* #isAuthenticated()} will return <code>false</code>.
|
||||
*
|
||||
* @param principal DOCUMENT ME!
|
||||
* @param credentials DOCUMENT ME!
|
||||
*/
|
||||
public UsernamePasswordAuthenticationToken(Object principal, Object credentials) {
|
||||
super(null);
|
||||
|
@ -51,12 +50,10 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT
|
|||
setAuthenticated(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* This constructor should only be used by
|
||||
* <code>AuthenticationManager</code> or
|
||||
* <code>AuthenticationProvider</code> implementations that are satisfied
|
||||
* with producing a trusted (ie {@link #isAuthenticated()} =
|
||||
* <code>true</code>) authentication token.
|
||||
/**
|
||||
* This constructor should only be used by <code>AuthenticationManager</code> or <code>AuthenticationProvider</code>
|
||||
* implementations that are satisfied with producing a trusted (ie {@link #isAuthenticated()} = <code>true</code>)
|
||||
* authentication token.
|
||||
*
|
||||
* @param principal
|
||||
* @param credentials
|
||||
|
@ -79,8 +76,7 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT
|
|||
return this.principal;
|
||||
}
|
||||
|
||||
public void setAuthenticated(boolean isAuthenticated)
|
||||
throws IllegalArgumentException {
|
||||
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
|
||||
if (isAuthenticated) {
|
||||
throw new IllegalArgumentException(
|
||||
"Cannot set this token to trusted - use constructor containing GrantedAuthority[]s instead");
|
||||
|
|
|
@ -18,32 +18,40 @@ package org.springframework.security.ui.ntlm;
|
|||
import jcifs.smb.NtlmPasswordAuthentication;
|
||||
|
||||
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.GrantedAuthority;
|
||||
import org.springframework.security.util.AuthorityUtils;
|
||||
|
||||
/**
|
||||
* An NTLM-specific {@link UsernamePasswordAuthenticationToken} that allows
|
||||
* any provider to bypass the problem of an empty password since NTLM does
|
||||
* not retrieve the user's password from the PDC.
|
||||
*
|
||||
* An NTLM-specific {@link UsernamePasswordAuthenticationToken} that allows any provider to bypass the problem of an
|
||||
* empty password since NTLM does not retrieve the user's password from the PDC.
|
||||
*
|
||||
* @author Sylvain Mougenot
|
||||
*/
|
||||
public class NtlmUsernamePasswordAuthenticationToken extends UsernamePasswordAuthenticationToken {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Spring Security often checks password ; but we do not have one. This is the replacement password
|
||||
|
||||
/**
|
||||
* Dummy authority array which is passed to the constructor of the parent class,
|
||||
* ensuring that the "authenticated" property is set to "true" by default. See SEC-609.
|
||||
*/
|
||||
private static final GrantedAuthority[] NTLM_AUTHENTICATED =
|
||||
AuthorityUtils.stringArrayToAuthorityArray(new String[] {"NTLM_AUTHENTICATED"});
|
||||
|
||||
/**
|
||||
* Spring Security often checks password ; but we do not have one. This is the replacement password
|
||||
*/
|
||||
public static final String DEFAULT_PASSWORD = "";
|
||||
|
||||
/**
|
||||
* Create an NTLM {@link UsernamePasswordAuthenticationToken} using the
|
||||
* JCIFS {@link NtlmPasswordAuthentication} object.
|
||||
*
|
||||
*
|
||||
* @param ntlmAuth The {@link NtlmPasswordAuthentication} object.
|
||||
* @param stripDomain Uses just the username if <code>true</code>,
|
||||
* otherwise use the username and domain name.
|
||||
*/
|
||||
public NtlmUsernamePasswordAuthenticationToken(final NtlmPasswordAuthentication ntlmAuth, final boolean stripDomain) {
|
||||
super((stripDomain) ? ntlmAuth.getUsername() : ntlmAuth.getName(), DEFAULT_PASSWORD);
|
||||
super((stripDomain) ? ntlmAuth.getUsername() : ntlmAuth.getName(), DEFAULT_PASSWORD, NTLM_AUTHENTICATED);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,6 +69,10 @@ public class NtlmAwareLdapAuthenticator extends BindAuthenticator {
|
|||
return super.authenticate(authentication);
|
||||
}
|
||||
|
||||
if (!authentication.isAuthenticated()) {
|
||||
throw new BadCredentialsException("Unauthenticated NTLM authentication token found");
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("authenticate(NtlmUsernamePasswordAuthenticationToken) - start"); //$NON-NLS-1$
|
||||
}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
package org.springframework.security.ui.ntlm.ldap.authenticator;
|
||||
|
||||
import org.springframework.security.BadCredentialsException;
|
||||
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
|
||||
import org.springframework.security.ui.ntlm.NtlmUsernamePasswordAuthenticationToken;
|
||||
import org.springframework.ldap.core.DirContextAdapter;
|
||||
import org.springframework.ldap.core.DirContextOperations;
|
||||
|
||||
import jcifs.smb.NtlmPasswordAuthentication;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
*/
|
||||
public class NtlmAwareLdapAuthenticatorTests {
|
||||
/**
|
||||
* See SEC-609.
|
||||
*/
|
||||
@Test(expected = BadCredentialsException.class)
|
||||
public void unauthenticatedTokenIsRejected() {
|
||||
NtlmAwareLdapAuthenticator authenticator = new NtlmAwareLdapAuthenticator(
|
||||
new DefaultSpringSecurityContextSource("ldap://blah"));
|
||||
|
||||
NtlmUsernamePasswordAuthenticationToken token = new NtlmUsernamePasswordAuthenticationToken(
|
||||
new NtlmPasswordAuthentication("blah"), false);
|
||||
token.setAuthenticated(false);
|
||||
|
||||
authenticator.authenticate(token);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticatedTokenIsAccepted() {
|
||||
NtlmAwareLdapAuthenticator authenticator = new NtlmAwareLdapAuthenticator(new DefaultSpringSecurityContextSource("ldap://blah")) {
|
||||
// mimic loading of user
|
||||
protected DirContextOperations loadUser(String aUserDn, String aUserName) {
|
||||
return new DirContextAdapter();
|
||||
}
|
||||
};
|
||||
|
||||
authenticator.setUserDnPatterns(new String[] {"somepattern"});
|
||||
|
||||
NtlmUsernamePasswordAuthenticationToken token = new NtlmUsernamePasswordAuthenticationToken(
|
||||
new NtlmPasswordAuthentication("blah"), false);
|
||||
|
||||
authenticator.authenticate(token);
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue