mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-02-28 18:39:06 +00:00
Removed old LDAP stuff.
This commit is contained in:
parent
ab05cb95ff
commit
fd1ed6bcdd
@ -1,222 +0,0 @@
|
||||
package org.acegisecurity.providers.dao.ldap;
|
||||
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.naming.AuthenticationException;
|
||||
import javax.naming.Context;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.directory.InitialDirContext;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
|
||||
/**
|
||||
* Convient base class and/or bean which can be used to create DirContext objects.
|
||||
* Many user's will only need to set to Url property.
|
||||
*
|
||||
* <p>
|
||||
* Eample: <br/>
|
||||
* <bean id="initialDirContextFactoryBean"
|
||||
* class="org.acegisecurity.providers.dao.ldap.InitialDirContextFactoryBean"> <br/>
|
||||
* <property name="url"><value>ldap://myserver.com:389/</value></property> <br/>
|
||||
* <property name="managerUser"><value>cn=UserWithSearchPermissions,dc=mycompany,dc=com</value></property> <br/>
|
||||
* <property name="managerPassword"><value>PasswordForUser</value></property> <br/>
|
||||
* </bean> <br/>
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @see http://java.sun.com/products/jndi/tutorial/ldap/connect/config.html
|
||||
*
|
||||
* @author robert.sanders
|
||||
*
|
||||
*/
|
||||
public class InitialDirContextFactoryBean {
|
||||
|
||||
/**
|
||||
* LDAP URL (with or without the port) of the LDAP server to connect to.
|
||||
* <p>Example: <br/>
|
||||
* <b>ldap://dir.mycompany.com:389/dc=mycompany,dc=com</b> <br/>
|
||||
* <small>(port 389 is the standard LDAP port). </small>
|
||||
* </p>
|
||||
*/
|
||||
private String url;
|
||||
|
||||
/** If your LDAP server does not allow anonymous searches then
|
||||
* you will need to provide a username with which to login with;
|
||||
* this is that username.
|
||||
*/
|
||||
private String managerUser;
|
||||
|
||||
/** If your LDAP server does not allow anonymous searches then
|
||||
* you will need to provide a username with which to login with;
|
||||
* this is the password of that user.
|
||||
*/
|
||||
private String managerPassword;
|
||||
|
||||
/** Type of authentication within LDAP; default is simple. */
|
||||
private String authenticationType = "simple";
|
||||
|
||||
/** The INITIAL_CONTEXT_FACTORY used to create the JNDI Factory.
|
||||
* Default is "com.sun.jndi.ldap.LdapCtxFactory"; you <b>should not</b>
|
||||
* need to set this unless you have unusual needs.
|
||||
**/
|
||||
private String initialContextFactory = "com.sun.jndi.ldap.LdapCtxFactory";
|
||||
|
||||
/** Allows extra environment variables to be added at config time. */
|
||||
private Map extraEnvVars = null;
|
||||
|
||||
/** Use the LDAP Connection pool (in SUN JVMs)?; if true, then the
|
||||
* LDAP environment property "com.sun.jndi.ldap.connect.pool" is added
|
||||
* to any other JNDI properties.
|
||||
* @see http://java.sun.com/products/jndi/tutorial/ldap/connect/pool.html
|
||||
* @see http://java.sun.com/products/jndi/tutorial/ldap/connect/config.html
|
||||
*/
|
||||
private boolean connectionPoolEnabled = true;
|
||||
|
||||
public InitialDirContext newInitialDirContext(String username, String password) throws AuthenticationException, DataAccessResourceFailureException {
|
||||
Hashtable env = getEnvironment();
|
||||
if (null != username) {
|
||||
env.put(Context.SECURITY_PRINCIPAL, username);
|
||||
}
|
||||
if (null != password) {
|
||||
env.put(Context.SECURITY_CREDENTIALS, password);
|
||||
}
|
||||
try {
|
||||
return new InitialDirContext(env);
|
||||
} catch (AuthenticationException ax) {
|
||||
throw ax; // just pass it right on.
|
||||
} catch (NamingException nx) {
|
||||
// any other JNDI exception:
|
||||
throw new DataAccessResourceFailureException("Unable to connect to LDAP Server; check managerUser and managerPassword.", nx);
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns a new InitialDirContext using the provided managerUser and managerPassword (if provided) as credentials.
|
||||
* @throws AuthenticationException */
|
||||
public InitialDirContext newInitialDirContext() throws DataAccessResourceFailureException, AuthenticationException {
|
||||
return newInitialDirContext(managerUser, managerPassword);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The Hashtable describing the base DirContext that will be created; minus the username/password if any.
|
||||
*/
|
||||
protected Hashtable getEnvironment() {
|
||||
Hashtable env = new Hashtable(11);
|
||||
env.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactory);
|
||||
env.put(Context.PROVIDER_URL, url);
|
||||
env.put(Context.SECURITY_AUTHENTICATION, authenticationType);
|
||||
if (connectionPoolEnabled) {
|
||||
env.put("com.sun.jndi.ldap.connect.pool", "true");
|
||||
}
|
||||
if ((extraEnvVars != null) && (extraEnvVars.size() > 0)) {
|
||||
env.putAll(extraEnvVars);
|
||||
}
|
||||
return env;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the authenticationType.
|
||||
*/
|
||||
public String getAuthenticationType() {
|
||||
return authenticationType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param authenticationType The authenticationType to set.
|
||||
*/
|
||||
public void setAuthenticationType(String authenticationType) {
|
||||
this.authenticationType = authenticationType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the initialContextFactory.
|
||||
*/
|
||||
public String getInitialContextFactory() {
|
||||
return initialContextFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param initialContextFactory The initialContextFactory to set.
|
||||
*/
|
||||
public void setInitialContextFactory(String initialContextFactory) {
|
||||
this.initialContextFactory = initialContextFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Password (if any) of the user named by the managerUser property.
|
||||
*/
|
||||
public String getManagerPassword() {
|
||||
return managerPassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param managerPassword Password (if any) of the user named by the managerUser property.
|
||||
*/
|
||||
public void setManagerPassword(String managerPassword) {
|
||||
this.managerPassword = managerPassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Name of the user (typically a fully qualified DN) which
|
||||
* will be used to authenticate with the LDAP server when initiating LDAP connections.
|
||||
*/
|
||||
public String getManagerUser() {
|
||||
return managerUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* For OpenLDAP this might be "cn=Manager,dc=mycompany,dc=com";
|
||||
* because this user typically <b>only</b> needs to be able to search/read
|
||||
* the contexts against which LDAP operations occur, you may wish
|
||||
* to create an account with read-only settings for this purpose.
|
||||
* <p>
|
||||
* If this property is not set, then the default behavor is
|
||||
* to connect to the LDAP server anonymously.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @param managerUser Name of the user (typically a fully qualified DN) which
|
||||
* will be used to authenticate with the LDAP server when initiating LDAP connections.
|
||||
*/
|
||||
public void setManagerUser(String managerUser) {
|
||||
this.managerUser = managerUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The URL of the LDAP host to connect to, including port (if non-default),
|
||||
* and the base DN from which other operations will be relative to.
|
||||
*/
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* LDAP URL (with or without the port) of the LDAP server to connect to.
|
||||
* <p>Example: <br/>
|
||||
* <b>ldap://dir.mycompany.com:389/dc=mycompany,dc=com</b> <br/>
|
||||
* <small>(port 389 is the standard LDAP port) </small> so the example above could also be: <br/>
|
||||
* <b>ldap://dir.mycompany.com/dc=mycompany,dc=com</b> <br/>
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @param url The URL of the LDAP host to connect to, including port (if non-default),
|
||||
* and the base DN from which other operations will be relative to.
|
||||
*/
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Allows extra environment variables to be added at config time.
|
||||
*/
|
||||
public Map getExtraEnvVars() {
|
||||
return extraEnvVars;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param extraEnvVars Allows extra environment variables to be added at config time.
|
||||
*/
|
||||
public void setExtraEnvVars(Map extraEnvVars) {
|
||||
this.extraEnvVars = extraEnvVars;
|
||||
}
|
||||
|
||||
}
|
@ -1,309 +0,0 @@
|
||||
package org.acegisecurity.providers.dao.ldap;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.naming.AuthenticationException;
|
||||
import javax.naming.NamingEnumeration;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.directory.Attribute;
|
||||
import javax.naming.directory.Attributes;
|
||||
import javax.naming.directory.DirContext;
|
||||
import javax.naming.directory.InitialDirContext;
|
||||
|
||||
import org.acegisecurity.BadCredentialsException;
|
||||
import org.acegisecurity.GrantedAuthority;
|
||||
import org.acegisecurity.GrantedAuthorityImpl;
|
||||
import org.acegisecurity.userdetails.User;
|
||||
import org.acegisecurity.userdetails.UserDetails;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
|
||||
/**
|
||||
* A much simplified (vs the 1.6 revision) LdapPasswordAuthenticationDao,
|
||||
* which should meet all 'basic' needs, leaving advanced options such as
|
||||
* multiple user and/or role contexts. This version assumes all users
|
||||
* are in one context, and roles are assigned via attributes of the user's
|
||||
* directory object. Authentication is done by creating a username for
|
||||
* <br/><br/>
|
||||
*
|
||||
* <h4>Examples:</h4>
|
||||
* <p>The following examples would be linked into the main Acegi
|
||||
* configuration by: <br/>
|
||||
* <bean id="passwordAuthenticationProvider"
|
||||
* class="org.acegisecurity.providers.dao.PasswordDaoAuthenticationProvider"> <br/>
|
||||
* <property name="passwordAuthenticationDao"> <br/>
|
||||
* <ref bean="passwordAuthenticationDao"/> <br/>
|
||||
* </property> <br/>
|
||||
* </bean> <br/>
|
||||
* </p>
|
||||
*
|
||||
* <h5 title="as seen in the Unit tests">'Standard' LDAP Settings</h5>
|
||||
* <p>
|
||||
* <bean id="passwordAuthenticationDao"
|
||||
* class="org.acegisecurity.providers.dao.ldap.LdapPasswordAuthenticationDao"> <br/>
|
||||
* <property name="url"><value>ldap://localhost:389/ou=system</value></property> <br/>
|
||||
* <property name="usernameFormat"><value>uid={0},ou=users,ou=system</value></property> <br/>
|
||||
* <property name="userLookupNameFormat"><value>uid={0},ou=users</value></property> <br/>
|
||||
* </bean> <br/>
|
||||
* </p>
|
||||
*
|
||||
* <h5>Active Directory Configuration</h5>
|
||||
* <p>
|
||||
* I haven't been able to test this directly,
|
||||
* but something like the following should do the trick: <br/>
|
||||
* <bean id="passwordAuthenticationDao"
|
||||
* class="org.acegisecurity.providers.dao.ldap.LdapPasswordAuthenticationDao"> <br/>
|
||||
* <property name="url"><value>ldap://localhost:389/ou=system</value></property> <br/>
|
||||
* <property name="usernameFormat"><value>{0}@adDomainName</value></property> <br/>
|
||||
* </bean> <br/>
|
||||
* (if anyone gets this to work please let me know so I can include it
|
||||
* in the documentation).
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @author Karel Miarka
|
||||
* @author Daniel Miller
|
||||
* @author Robert Sanders
|
||||
*/
|
||||
public class LdapPasswordAuthenticationDao extends InitialDirContextFactoryBean implements PasswordAuthenticationDao {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(LdapPasswordAuthenticationDao.class);
|
||||
|
||||
public static final String BAD_CREDENTIALS_EXCEPTION_MESSAGE = "Invalid username, password or server configuration (JNDI Context).";
|
||||
|
||||
/** Pattern used to turn the user's supplied username into the
|
||||
* username format the LDAP server expects. {0} is the username.
|
||||
*
|
||||
* <p>
|
||||
* Examples: <br/>
|
||||
* 'Normal' LDAP: "cn={0}" <br/>
|
||||
* Active Directory style LDAP: "{0}@AD_Domain"
|
||||
* </p>
|
||||
*/
|
||||
private MessageFormat usernameFormat = new MessageFormat("cn={0}");
|
||||
|
||||
/** Message format used to create the Name within the LDAP Context
|
||||
* from which role information will be retrieved.
|
||||
* {0} is the username
|
||||
* {1} is the result of usernameFormat.format(new Object[] {username})
|
||||
*
|
||||
* <p>Example: "uid={0},ou=users"</p>
|
||||
*
|
||||
*/
|
||||
private MessageFormat userLookupNameFormat = null;
|
||||
|
||||
/** List of LDAP Attributes which contian role name information. */
|
||||
private String[] roleAttributes = {"memberOf"};
|
||||
|
||||
/** The role, which if non-null, will be grated the user if the user has no other roles. */
|
||||
private String defaultRole = null;
|
||||
|
||||
public UserDetails loadUserByUsernameAndPassword(String username, String password) throws DataAccessException, BadCredentialsException {
|
||||
if ((password == null) || (password.length() == 0)) {
|
||||
throw new BadCredentialsException("Empty password");
|
||||
}
|
||||
|
||||
String ldapUsername = (null == usernameFormat) ? username : usernameFormat.format( new Object[]{username} );
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Connecting to " + this.getUrl() + " as " + ldapUsername);
|
||||
}
|
||||
|
||||
InitialDirContext dirContext = null;
|
||||
try {
|
||||
dirContext = newInitialDirContext(ldapUsername, password);
|
||||
} catch (AuthenticationException ax) {
|
||||
throw new BadCredentialsException(BAD_CREDENTIALS_EXCEPTION_MESSAGE, ax);
|
||||
}
|
||||
if (null == dirContext) {
|
||||
throw new BadCredentialsException(BAD_CREDENTIALS_EXCEPTION_MESSAGE);
|
||||
}
|
||||
|
||||
String[] roles = null;
|
||||
if (null != roleAttributes) {
|
||||
try {
|
||||
String userContextName = (null == userLookupNameFormat) ? "" :
|
||||
userLookupNameFormat.format(new Object[]{username, ldapUsername});
|
||||
roles = getRolesFromContext(dirContext, userContextName);
|
||||
} catch (NamingException e) {
|
||||
throw new DataAccessResourceFailureException("Unable to retrieve role information from LDAP Server.", e);
|
||||
}
|
||||
}
|
||||
if ((null == roles) && (null != defaultRole)) {
|
||||
roles = new String[] {defaultRole};
|
||||
}
|
||||
|
||||
return new User(username, password, true, true, true, true, toGrantedAuthority(roles) );
|
||||
}
|
||||
|
||||
/** Converts from an Array of String rolenames to an array of GrantedAuthority objects.
|
||||
* This is a possible extension point for sub-classes to enrich the behavior of how
|
||||
* the GrantedAuthority array is constucted.
|
||||
*
|
||||
* @param rolenames Array of Strings representing the names of the
|
||||
* roles that the user has been granted according to the LDAP server.
|
||||
* @return Array of GrantedAuthority objects which will be associated with the User's UserDetails.
|
||||
*/
|
||||
protected GrantedAuthority[] toGrantedAuthority(String[] rolenames) {
|
||||
if ((null == rolenames) || (rolenames.length == 0)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
GrantedAuthority[] grantedAuthorities = new GrantedAuthority[rolenames.length];
|
||||
for (int i = 0; i < rolenames.length; i++) {
|
||||
grantedAuthorities[i] = toGrantedAuthority(rolenames[i]);
|
||||
}
|
||||
|
||||
return grantedAuthorities;
|
||||
}
|
||||
|
||||
/** This is a possible extension point for sub-classes to enrich the behavior of how
|
||||
* the GrantedAuthority object is constucted.
|
||||
*
|
||||
* @param rolename Name of an LDAP role which is granted to the user.
|
||||
* @return GrantedAuthority object which represents the granted role.
|
||||
*/
|
||||
protected GrantedAuthority toGrantedAuthority(String rolename) {
|
||||
GrantedAuthority ga = new GrantedAuthorityImpl( rolename );
|
||||
return ga;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param ctx The LDAP DirContext retrieved by the user login.
|
||||
* @return An array of roles granted the user found by searching all attributes named in the roleAttributes field.
|
||||
* @throws NamingException
|
||||
*/
|
||||
protected String[] getRolesFromContext(DirContext ctx, String dnOfUser) throws NamingException {
|
||||
if (null == roleAttributes) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
String rolesString = "";
|
||||
|
||||
for (int i = 0; i < roleAttributes.length; i++) {
|
||||
rolesString += (", " + roleAttributes[i]);
|
||||
}
|
||||
|
||||
logger.debug("Searching ldap context for roles using attributes: " + rolesString.substring(1));
|
||||
}
|
||||
|
||||
ArrayList roles = new ArrayList();
|
||||
Attributes attrs = null;
|
||||
if (null == usernameFormat) {
|
||||
attrs = ctx.getAttributes("", roleAttributes);
|
||||
} else {
|
||||
attrs = ctx.getAttributes(dnOfUser, roleAttributes);
|
||||
}
|
||||
|
||||
if (null != attrs) {
|
||||
NamingEnumeration attrsEnum = attrs.getAll();
|
||||
while ((attrsEnum != null) && (attrsEnum.hasMore())) {
|
||||
Attribute attr = (Attribute)attrsEnum.next();
|
||||
if (null != attr) {
|
||||
ArrayList list = getRolesFromAttribute( attr );
|
||||
if (null != list) {
|
||||
roles.addAll( list );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (roles.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
return (String[])roles.toArray( new String[roles.size()] );
|
||||
}
|
||||
}
|
||||
|
||||
protected ArrayList getRolesFromAttribute(Attribute attr) throws NamingException {
|
||||
NamingEnumeration rolesEnum = attr.getAll();
|
||||
if (null == rolesEnum) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ArrayList roles = new ArrayList();
|
||||
while (rolesEnum.hasMore()) {
|
||||
String rolename = (String)rolesEnum.next();
|
||||
if (null != rolename) {
|
||||
roles.add( convertLdapRolename(rolename) );
|
||||
}
|
||||
}
|
||||
return roles;
|
||||
}
|
||||
|
||||
protected String convertLdapRolename(String name) {
|
||||
//System.out.println("Found LDAP UserRole = " + name);
|
||||
return name.toUpperCase();
|
||||
}
|
||||
|
||||
public String getDefaultRole() {
|
||||
return defaultRole;
|
||||
}
|
||||
|
||||
public void setDefaultRole(String defaultRole) {
|
||||
this.defaultRole = defaultRole;
|
||||
}
|
||||
|
||||
public String[] getRoleAttributes() {
|
||||
return roleAttributes;
|
||||
}
|
||||
|
||||
/** List of LDAP Attributes which contian role name information. */
|
||||
public void setRoleAttributes(String[] roleAttributes) {
|
||||
this.roleAttributes = roleAttributes;
|
||||
}
|
||||
|
||||
/** Utility method to set a single attribute which contains role information.
|
||||
* @see setRoleAttributes
|
||||
*/
|
||||
public void setRoleAttribute(String roleAttribute) {
|
||||
setRoleAttributes(new String[]{ roleAttribute });
|
||||
}
|
||||
|
||||
public String getUsernameFormat() {
|
||||
if (null == usernameFormat) {
|
||||
return null;
|
||||
} else {
|
||||
return usernameFormat.toPattern();
|
||||
}
|
||||
}
|
||||
|
||||
/** Pattern used to turn the user's supplied username into the
|
||||
* username format the LDAP server expects.
|
||||
*
|
||||
* <p>
|
||||
* Examples: <br/>
|
||||
* 'Normal' LDAP: "cn={0}" <br/>
|
||||
* Active Directory style LDAP: "{0}@AD_Domain"
|
||||
* </p>
|
||||
*/
|
||||
public void setUsernameFormat(String usernameFormat) {
|
||||
if (null == usernameFormat) {
|
||||
this.usernameFormat = null;
|
||||
} else {
|
||||
this.usernameFormat = new MessageFormat(usernameFormat);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String getUserLookupNameFormat() {
|
||||
if (null == userLookupNameFormat) {
|
||||
return null;
|
||||
} else {
|
||||
return userLookupNameFormat.toPattern();
|
||||
}
|
||||
}
|
||||
|
||||
public void setUserLookupNameFormat(String userLookupNameFormat) {
|
||||
if (null == userLookupNameFormat) {
|
||||
this.userLookupNameFormat = null;
|
||||
} else {
|
||||
this.userLookupNameFormat = new MessageFormat(userLookupNameFormat);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
/* 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 org.acegisecurity.providers.dao.ldap;
|
||||
|
||||
import org.acegisecurity.BadCredentialsException;
|
||||
import org.acegisecurity.userdetails.UserDetails;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
|
||||
|
||||
/**
|
||||
* Defines an interface for DAO implementations capable of locating and also
|
||||
* validating a password.
|
||||
*
|
||||
* <p>
|
||||
* Used with the {@link PasswordDaoAuthenticationProvider}.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* The interface requires only one read-only method, which simplifies support
|
||||
* of new data access strategies.
|
||||
* </p>
|
||||
*
|
||||
* @deprecated instead subclass {@link org.acegisecurity.providers.dao.AbstractUserDetailsAuthenticationProvider}
|
||||
* @author Karel Miarka
|
||||
*/
|
||||
public interface PasswordAuthenticationDao {
|
||||
//~ Methods ================================================================
|
||||
|
||||
/**
|
||||
* Locates the user based on the username and password. In the actual
|
||||
* implementation, the search may possibly be case sensitive, or case
|
||||
* insensitive depending on how the implementaion instance is configured.
|
||||
* In this case, the <code>UserDetails</code> object that comes back may
|
||||
* have a username that is of a different case than what was actually
|
||||
* requested.
|
||||
*
|
||||
* <p>
|
||||
* The implementation is responsible for password validation. It must throw
|
||||
* <code>BadCredentialsException</code> (or subclass of that exception if
|
||||
* desired) if the provided password is invalid.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* The implementation is responsible for filling the username and password
|
||||
* parameters into the implementation of <code>UserDetails</code>.
|
||||
* </p>
|
||||
*
|
||||
* @param username the username presented to the {@link
|
||||
* PasswordDaoAuthenticationProvider}
|
||||
* @param password the password presented to the {@link
|
||||
* PasswordDaoAuthenticationProvider}
|
||||
*
|
||||
* @return a fully populated user record
|
||||
*
|
||||
* @throws DataAccessException if user could not be found for a
|
||||
* repository-specific reason
|
||||
* @throws BadCredentialsException if the user could not be found, invalid
|
||||
* password provided or the user has no
|
||||
* <code>GrantedAuthority</code>s
|
||||
*/
|
||||
public UserDetails loadUserByUsernameAndPassword(String username,
|
||||
String password) throws DataAccessException, BadCredentialsException;
|
||||
}
|
@ -1,246 +0,0 @@
|
||||
/* Copyright 2004, 2005 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 org.acegisecurity.providers.dao.ldap;
|
||||
|
||||
import org.acegisecurity.AccountExpiredException;
|
||||
import org.acegisecurity.Authentication;
|
||||
import org.acegisecurity.AuthenticationException;
|
||||
import org.acegisecurity.AuthenticationServiceException;
|
||||
import org.acegisecurity.CredentialsExpiredException;
|
||||
import org.acegisecurity.DisabledException;
|
||||
import org.acegisecurity.LockedException;
|
||||
import org.acegisecurity.providers.AuthenticationProvider;
|
||||
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
|
||||
import org.acegisecurity.providers.dao.DaoAuthenticationProvider;
|
||||
import org.acegisecurity.providers.dao.UserCache;
|
||||
import org.acegisecurity.providers.dao.cache.NullUserCache;
|
||||
import org.acegisecurity.userdetails.UserDetails;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* An {@link AuthenticationProvider} implementation that retrieves user details
|
||||
* from a {@link PasswordAuthenticationDao}.
|
||||
*
|
||||
* <p>
|
||||
* This <code>AuthenticationProvider</code> is capable of validating {@link
|
||||
* UsernamePasswordAuthenticationToken} requests containing the correct
|
||||
* username, password and when the user is not disabled.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Unlike {@link DaoAuthenticationProvider}, the responsibility for password
|
||||
* validation is delegated to <code>PasswordAuthenticationDao</code>.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Upon successful validation, a
|
||||
* <code>UsernamePasswordAuthenticationToken</code> will be created and
|
||||
* returned to the caller. The token will include as its principal either a
|
||||
* <code>String</code> representation of the username, or the {@link
|
||||
* UserDetails} that was returned from the authentication repository. Using
|
||||
* <code>String</code> is appropriate if a container adapter is being used, as
|
||||
* it expects <code>String</code> representations of the username. Using
|
||||
* <code>UserDetails</code> is appropriate if you require access to additional
|
||||
* properties of the authenticated user, such as email addresses,
|
||||
* human-friendly names etc. As container adapters are not recommended to be
|
||||
* used, and <code>UserDetails</code> implementations provide additional
|
||||
* flexibility, by default a <code>UserDetails</code> is returned. To override
|
||||
* this default, set the {@link #setForcePrincipalAsString} to
|
||||
* <code>true</code>.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Caching is handled via the <code>UserDetails</code> object being placed in
|
||||
* the {@link UserCache}. This ensures that subsequent requests with the same
|
||||
* username and password can be validated without needing to query the {@link
|
||||
* PasswordAuthenticationDao}. It should be noted that if a user appears to
|
||||
* present an incorrect password, the {@link PasswordAuthenticationDao} will
|
||||
* be queried to confirm the most up-to-date password was used for comparison.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* If an application context is detected (which is automatically the case when
|
||||
* the bean is started within a Spring container), application events will be
|
||||
* published to the context. See {@link
|
||||
* org.acegisecurity.event.authentication.AbstractAuthenticationEvent} for
|
||||
* further information.
|
||||
* </p>
|
||||
*
|
||||
* @deprecated instead subclass {@link org.acegisecurity.providers.dao.AbstractUserDetailsAuthenticationProvider}
|
||||
* @author Karel Miarka
|
||||
*/
|
||||
public class PasswordDaoAuthenticationProvider implements AuthenticationProvider,
|
||||
InitializingBean {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private PasswordAuthenticationDao authenticationDao;
|
||||
private UserCache userCache = new NullUserCache();
|
||||
private boolean forcePrincipalAsString = false;
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void setForcePrincipalAsString(boolean forcePrincipalAsString) {
|
||||
this.forcePrincipalAsString = forcePrincipalAsString;
|
||||
}
|
||||
|
||||
public boolean isForcePrincipalAsString() {
|
||||
return forcePrincipalAsString;
|
||||
}
|
||||
|
||||
public void setPasswordAuthenticationDao(
|
||||
PasswordAuthenticationDao authenticationDao) {
|
||||
this.authenticationDao = authenticationDao;
|
||||
}
|
||||
|
||||
public PasswordAuthenticationDao getPasswordAuthenticationDao() {
|
||||
return authenticationDao;
|
||||
}
|
||||
|
||||
public void setUserCache(UserCache userCache) {
|
||||
this.userCache = userCache;
|
||||
}
|
||||
|
||||
public UserCache getUserCache() {
|
||||
return userCache;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(this.authenticationDao,
|
||||
"A Password authentication DAO must be set");
|
||||
Assert.notNull(this.userCache, "A user cache must be set");
|
||||
}
|
||||
|
||||
public Authentication authenticate(Authentication authentication)
|
||||
throws AuthenticationException {
|
||||
// Determine username
|
||||
String username = authentication.getPrincipal().toString();
|
||||
|
||||
if (authentication.getPrincipal() instanceof UserDetails) {
|
||||
username = ((UserDetails) authentication.getPrincipal())
|
||||
.getUsername();
|
||||
}
|
||||
|
||||
String password = authentication.getCredentials().toString();
|
||||
|
||||
boolean cacheWasUsed = true;
|
||||
UserDetails user = this.userCache.getUserFromCache(username);
|
||||
|
||||
// Check if the provided password is the same as the password in cache
|
||||
if ((user != null) && !password.equals(user.getPassword())) {
|
||||
user = null;
|
||||
this.userCache.removeUserFromCache(username);
|
||||
}
|
||||
|
||||
if (user == null) {
|
||||
cacheWasUsed = false;
|
||||
user = getUserFromBackend(username, password);
|
||||
}
|
||||
|
||||
if (!user.isEnabled()) {
|
||||
throw new DisabledException("User is disabled");
|
||||
}
|
||||
|
||||
if (!user.isAccountNonExpired()) {
|
||||
throw new AccountExpiredException("User account has expired");
|
||||
}
|
||||
|
||||
if (!user.isAccountNonLocked()) {
|
||||
throw new LockedException("User account is locked");
|
||||
}
|
||||
|
||||
if (!user.isCredentialsNonExpired()) {
|
||||
throw new CredentialsExpiredException(
|
||||
"User credentials have expired");
|
||||
}
|
||||
|
||||
if (!cacheWasUsed) {
|
||||
// Put into cache
|
||||
this.userCache.putUserInCache(user);
|
||||
}
|
||||
|
||||
Object principalToReturn = user;
|
||||
|
||||
if (forcePrincipalAsString) {
|
||||
principalToReturn = user.getUsername();
|
||||
}
|
||||
|
||||
return createSuccessAuthentication(principalToReturn, authentication,
|
||||
user);
|
||||
}
|
||||
|
||||
public boolean supports(Class authentication) {
|
||||
if (UsernamePasswordAuthenticationToken.class.isAssignableFrom(
|
||||
authentication)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a successful {@link Authentication} object.
|
||||
*
|
||||
* <P>
|
||||
* Protected so subclasses can override. This might be required if multiple
|
||||
* credentials need to be placed into a custom <code>Authentication</code>
|
||||
* object, such as a password as well as a ZIP code.
|
||||
* </p>
|
||||
*
|
||||
* <P>
|
||||
* Subclasses will usually store the original credentials the user supplied
|
||||
* (not salted or encoded passwords) in the returned
|
||||
* <code>Authentication</code> object.
|
||||
* </p>
|
||||
*
|
||||
* @param principal that should be the principal in the returned object
|
||||
* (defined by the {@link #isForcePrincipalAsString()} method)
|
||||
* @param authentication that was presented to the
|
||||
* <code>PasswordDaoAuthenticationProvider</code> for validation
|
||||
* @param user that was loaded by the
|
||||
* <code>PasswordAuthenticationDao</code>
|
||||
*
|
||||
* @return the successful authentication token
|
||||
*/
|
||||
protected Authentication createSuccessAuthentication(Object principal,
|
||||
Authentication authentication, UserDetails user) {
|
||||
// Ensure we return the original credentials the user supplied,
|
||||
// so subsequent attempts are successful even with encoded passwords.
|
||||
// Also ensure we return the original getDetails(), so that future
|
||||
// authentication events after cache expiry contain the details
|
||||
UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(principal,
|
||||
authentication.getCredentials(), user.getAuthorities());
|
||||
result.setDetails((authentication.getDetails() != null)
|
||||
? authentication.getDetails() : null);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private UserDetails getUserFromBackend(String username, String password) {
|
||||
try {
|
||||
return this.authenticationDao.loadUserByUsernameAndPassword(username,
|
||||
password);
|
||||
} catch (DataAccessException repositoryProblem) {
|
||||
throw new AuthenticationServiceException(repositoryProblem
|
||||
.getMessage(), repositoryProblem);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,170 +0,0 @@
|
||||
package org.acegisecurity.providers.dao.ldap.revised;
|
||||
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
import javax.naming.Context;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.directory.InitialDirContext;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
|
||||
/**
|
||||
* @see http://java.sun.com/products/jndi/tutorial/ldap/connect/config.html
|
||||
*
|
||||
* @author robert.sanders
|
||||
*
|
||||
*/
|
||||
public class InitialDirContextFactory {
|
||||
|
||||
/**
|
||||
* LDAP URL (without the port) of the LDAP server to connect to; example
|
||||
* <b>ldap://dir.mycompany.com:389/dc=mycompany,dc=com</b> (port 389 is the standard LDAP port).
|
||||
*/
|
||||
private String URL;
|
||||
|
||||
/** If your LDAP server does not allow anonymous searches then
|
||||
* you will need to provide a username with which to login with;
|
||||
* this is that username.
|
||||
*/
|
||||
private String managerUser;
|
||||
|
||||
/** If your LDAP server does not allow anonymous searches then
|
||||
* you will need to provide a username with which to login with;
|
||||
* this is the password of that user.
|
||||
*/
|
||||
private String managerPassword;
|
||||
|
||||
/** Type of authentication within LDAP; default is simple. */
|
||||
private String authenticationType = "simple";
|
||||
|
||||
/** The INITIAL_CONTEXT_FACTORY used to create the JNDI Factory.
|
||||
* Default is "com.sun.jndi.ldap.LdapCtxFactory"; you <b>should not</b>
|
||||
* need to set this unless you have unusual needs.
|
||||
**/
|
||||
private String initialContextFactory = "com.sun.jndi.ldap.LdapCtxFactory";
|
||||
|
||||
/** Allows extra environment variables to be added at config time. */
|
||||
private Map extraEnvVars = null;
|
||||
|
||||
/** Use the LDAP Connection pool (in SUN JVMs)?; if true, then the
|
||||
* LDAP environment property "com.sun.jndi.ldap.connect.pool" is added
|
||||
* to any other JNDI properties.
|
||||
* @see http://java.sun.com/products/jndi/tutorial/ldap/connect/pool.html
|
||||
* @see http://java.sun.com/products/jndi/tutorial/ldap/connect/config.html
|
||||
*/
|
||||
private boolean connectionPoolEnabled = true;
|
||||
|
||||
public InitialDirContext newInitialDirContext() throws DataAccessResourceFailureException {
|
||||
Hashtable env = getEnvironment();
|
||||
if (managerUser != null) {
|
||||
env.put(Context.SECURITY_PRINCIPAL, managerUser);
|
||||
env.put(Context.SECURITY_CREDENTIALS, managerPassword);
|
||||
}
|
||||
try {
|
||||
return new InitialDirContext(env);
|
||||
} catch (NamingException nx) {
|
||||
throw new DataAccessResourceFailureException("Unable to connect to LDAP Server; check managerUser and managerPassword.", nx);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The Hashtable describing the base DirContext that will be created; minus the username/password if any.
|
||||
*/
|
||||
protected Hashtable getEnvironment() {
|
||||
Hashtable env = new Hashtable(11);
|
||||
env.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactory);
|
||||
env.put(Context.PROVIDER_URL, URL);
|
||||
env.put(Context.SECURITY_AUTHENTICATION, authenticationType);
|
||||
if (connectionPoolEnabled) {
|
||||
env.put("com.sun.jndi.ldap.connect.pool", "true");
|
||||
}
|
||||
if ((extraEnvVars != null) && (extraEnvVars.size() > 0)) {
|
||||
env.putAll(extraEnvVars);
|
||||
}
|
||||
return env;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the authenticationType.
|
||||
*/
|
||||
public String getAuthenticationType() {
|
||||
return authenticationType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param authenticationType The authenticationType to set.
|
||||
*/
|
||||
public void setAuthenticationType(String authenticationType) {
|
||||
this.authenticationType = authenticationType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the initialContextFactory.
|
||||
*/
|
||||
public String getInitialContextFactory() {
|
||||
return initialContextFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param initialContextFactory The initialContextFactory to set.
|
||||
*/
|
||||
public void setInitialContextFactory(String initialContextFactory) {
|
||||
this.initialContextFactory = initialContextFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the managerPassword.
|
||||
*/
|
||||
public String getManagerPassword() {
|
||||
return managerPassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param managerPassword The managerPassword to set.
|
||||
*/
|
||||
public void setManagerPassword(String managerPassword) {
|
||||
this.managerPassword = managerPassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the managerUser.
|
||||
*/
|
||||
public String getManagerUser() {
|
||||
return managerUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param managerUser The managerUser to set.
|
||||
*/
|
||||
public void setManagerUser(String managerUser) {
|
||||
this.managerUser = managerUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the uRL.
|
||||
*/
|
||||
public String getURL() {
|
||||
return URL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param url The uRL to set.
|
||||
*/
|
||||
public void setURL(String url) {
|
||||
URL = url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Allows extra environment variables to be added at config time.
|
||||
*/
|
||||
public Map getExtraEnvVars() {
|
||||
return extraEnvVars;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param extraEnvVars Allows extra environment variables to be added at config time.
|
||||
*/
|
||||
public void setExtraEnvVars(Map extraEnvVars) {
|
||||
this.extraEnvVars = extraEnvVars;
|
||||
}
|
||||
|
||||
}
|
@ -1,216 +0,0 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package org.acegisecurity.providers.dao.ldap.revised;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Hashtable;
|
||||
|
||||
import javax.naming.Context;
|
||||
import javax.naming.NamingEnumeration;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.directory.Attribute;
|
||||
import javax.naming.directory.Attributes;
|
||||
import javax.naming.directory.DirContext;
|
||||
import javax.naming.directory.InitialDirContext;
|
||||
import javax.naming.directory.SearchResult;
|
||||
|
||||
import org.acegisecurity.BadCredentialsException;
|
||||
import org.acegisecurity.GrantedAuthority;
|
||||
import org.acegisecurity.GrantedAuthorityImpl;
|
||||
import org.acegisecurity.providers.dao.ldap.PasswordAuthenticationDao;
|
||||
import org.acegisecurity.userdetails.User;
|
||||
import org.acegisecurity.userdetails.UserDetails;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
|
||||
/**
|
||||
* Re-written version of the ACEGI LDAP code,
|
||||
* designed to be cleaner; it is partially based on
|
||||
* the description of the mod_auth_ldap logic: http://httpd.apache.org/docs-2.0/mod/mod_auth_ldap.html
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class LdapPassword2AuthenticationDao implements PasswordAuthenticationDao {
|
||||
|
||||
public static final String BAD_CREDENTIALS_EXCEPTION_MESSAGE = "Invalid username, password or context";
|
||||
|
||||
private static final transient Log logger = LogFactory.getLog(LdapPassword2AuthenticationDao.class);
|
||||
|
||||
/** Ldap base settings. */
|
||||
private InitialDirContextFactory initialDirContextFactory;
|
||||
|
||||
/** Array of LdapSearchBean which will be used to search the context.
|
||||
*/
|
||||
private UserSearchBean[] userSearchBeans;
|
||||
|
||||
private String defaultRole;
|
||||
|
||||
public UserDetails loadUserByUsernameAndPassword(String username, String password) throws DataAccessException, BadCredentialsException {
|
||||
if ((password == null) || (password.length() == 0)) {
|
||||
throw new BadCredentialsException("Empty password");
|
||||
}
|
||||
|
||||
UserSearchResults userSearchResults = getUserBySearch(username);
|
||||
if (null == userSearchResults) {
|
||||
throw new BadCredentialsException(BAD_CREDENTIALS_EXCEPTION_MESSAGE);
|
||||
}
|
||||
|
||||
DirContext userDirContext = null;
|
||||
try {
|
||||
userDirContext = loginToUserDirContext( userSearchResults.getUserLoginName(), password );
|
||||
if (null == userDirContext) {
|
||||
throw new BadCredentialsException(BAD_CREDENTIALS_EXCEPTION_MESSAGE);
|
||||
}
|
||||
|
||||
String[] roleAttrs = userSearchResults.getUserSearchBean().getRoleAttributes();
|
||||
GrantedAuthority[] roles = getUserRolesLdap(userDirContext, roleAttrs);
|
||||
|
||||
if ((roles == null) && (null != defaultRole)) {
|
||||
roles = new GrantedAuthority[] { new GrantedAuthorityImpl(defaultRole) };
|
||||
}
|
||||
if (null != roles) {
|
||||
return new User( userSearchResults.getUserLoginName(),
|
||||
password,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
roles);
|
||||
} else {
|
||||
logger.info("User was able to login, but had no role information; username = [" + username + "]");
|
||||
throw new BadCredentialsException(BAD_CREDENTIALS_EXCEPTION_MESSAGE);
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
if (null != userDirContext) {
|
||||
userDirContext.close();
|
||||
}
|
||||
} catch (NamingException e) {
|
||||
logger.warn("Unable to properly close userDirContext.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected UserSearchResults getUserBySearch(String username) throws DataAccessException, BadCredentialsException {
|
||||
InitialDirContext ctx = initialDirContextFactory.newInitialDirContext();
|
||||
UserSearchResults userSearchResults = null;
|
||||
try {
|
||||
for (int i = 0; (i < userSearchBeans.length) && (null == userSearchResults); i++) {
|
||||
try {
|
||||
userSearchResults = userSearchBeans[i].searchForUser(ctx, username);
|
||||
} catch (NamingException nx) {
|
||||
logger.warn(nx);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
ctx.close();
|
||||
} catch (NamingException e) {
|
||||
logger.warn("Unable to properly close JNDI LDAP connection.", e);
|
||||
}
|
||||
}
|
||||
return userSearchResults;
|
||||
}
|
||||
|
||||
|
||||
protected DirContext loginToUserDirContext(String username, String password) {
|
||||
Hashtable baseEnv = initialDirContextFactory.getEnvironment();
|
||||
baseEnv.put(Context.SECURITY_PRINCIPAL, username);
|
||||
baseEnv.put(Context.SECURITY_CREDENTIALS, password);
|
||||
try {
|
||||
return new InitialDirContext(baseEnv);
|
||||
} catch (NamingException e) {
|
||||
throw new BadCredentialsException(BAD_CREDENTIALS_EXCEPTION_MESSAGE, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected GrantedAuthority[] getUserRolesLdap(DirContext ctx, String[] roleAttrs) {
|
||||
try {
|
||||
NamingEnumeration enm = ctx.search("", null, roleAttrs);
|
||||
if (!enm.hasMore()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// LDAP Search result which SHOULD contain the user's roles
|
||||
SearchResult searchResult = (SearchResult)enm.next();
|
||||
Attributes attrs = searchResult.getAttributes();
|
||||
|
||||
ArrayList roleList = new ArrayList(attrs.size());
|
||||
NamingEnumeration attrEnm = attrs.getAll();
|
||||
while (attrEnm.hasMore()) {
|
||||
Attribute attr = (Attribute)attrEnm.next();
|
||||
for (int i = 0; i < attr.size(); i++) {
|
||||
roleList.add( new GrantedAuthorityImpl((String)attr.get(i)) );
|
||||
}
|
||||
}
|
||||
|
||||
GrantedAuthorityImpl[] roles = new GrantedAuthorityImpl[ roleList.size() ];
|
||||
return (GrantedAuthorityImpl[])roleList.toArray(roles);
|
||||
} catch (NamingException e) {
|
||||
// TODO Convert to authentication exception
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the defaultRole.
|
||||
*/
|
||||
public String getDefaultRole() {
|
||||
return defaultRole;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param defaultRole The defaultRole to set.
|
||||
*/
|
||||
public void setDefaultRole(String defaultRole) {
|
||||
this.defaultRole = defaultRole;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the userSearchBeans.
|
||||
*/
|
||||
public UserSearchBean[] getUserSearchBeans() {
|
||||
return userSearchBeans;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param userSearchBeans The userSearchBeans to set.
|
||||
*/
|
||||
public void setUserSearchBeans(UserSearchBean[] userSearchBeans) {
|
||||
this.userSearchBeans = userSearchBeans;
|
||||
}
|
||||
|
||||
/** Convience method to set only one userSearchBean.
|
||||
* <b>NOTE:</b> this method resets the entire userSearchBeans array,
|
||||
* and can therefore not be used to append entries to the array.
|
||||
*
|
||||
* @param userSearchBean
|
||||
*/
|
||||
public void setUserSearchBean(UserSearchBean userSearchBean) {
|
||||
this.userSearchBeans = new UserSearchBean[]{userSearchBean};
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the ldapSupport.
|
||||
*/
|
||||
public InitialDirContextFactory getInitialDirContextFactory() {
|
||||
return initialDirContextFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ldapSupport The ldapSupport to set.
|
||||
*/
|
||||
public void setInitialDirContextFactory(InitialDirContextFactory initialDirContextFactory) {
|
||||
this.initialDirContextFactory = initialDirContextFactory;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@ -1,171 +0,0 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package org.acegisecurity.providers.dao.ldap.revised;
|
||||
|
||||
|
||||
import javax.naming.directory.SearchControls;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
/**
|
||||
* Used to specify properties which are used to
|
||||
* construct JNDI SearchControls instances.
|
||||
*
|
||||
* @see javax.naming.directory.SearchControls
|
||||
*
|
||||
*/
|
||||
public class SearchControlsFactory {
|
||||
|
||||
private static final transient Log logger = LogFactory.getLog(SearchControlsFactory.class);
|
||||
|
||||
/** Name, which when combined with the rootContext of the DirContext
|
||||
* being searched will resolve to the DN that the search should be performed in.
|
||||
*/
|
||||
private String searchContextName;
|
||||
|
||||
/** Names of the attributes to return from the search;
|
||||
* default is null in which case ALL attributes will be returned.
|
||||
*/
|
||||
private String[] returnAttrNames;
|
||||
|
||||
/**
|
||||
* One of the 3 possible scope values as specified in SearchControles. <br/>
|
||||
* <ul>
|
||||
* <li>SearchControls.OBJECT_SCOPE = Search the attributes associated with the object specified by searchContextName.
|
||||
* <li>SearchControls.ONELEVEL_SCOPE = Search the objects contained within the searchContextName.
|
||||
* <li>SearchControls.SUBTREE_SCOPE = Recursivly search the objects contained within the searchContextName and any child context's it may contain.
|
||||
* </ul>
|
||||
*
|
||||
*/
|
||||
private int searchScope = SearchControls.ONELEVEL_SCOPE;
|
||||
|
||||
/** Number of milliseconds to wait before a timeout error is triggered. */
|
||||
private int timeout = 10000;
|
||||
|
||||
/** Maximum number of objects to return. Defauts to zero == no limit. */
|
||||
private int countLimit = 0;
|
||||
|
||||
/** If set to true then links will be followed,
|
||||
* if left at the default of false then links will be returned (not followed).
|
||||
*/
|
||||
private boolean followLinks = false;
|
||||
|
||||
/** If set to true (the default) then objects can be returned from the LDAP server. */
|
||||
private boolean returnObjects = true;
|
||||
|
||||
/** Given the settings for this LdapSearchCriteria,
|
||||
* use it to create a new instance of SearchControls with matching settings.
|
||||
*
|
||||
* @return A new instance of SearchControls.
|
||||
*/
|
||||
public SearchControls newSearchControls() {
|
||||
SearchControls controls =
|
||||
new SearchControls(searchScope, countLimit, timeout, returnAttrNames, returnObjects, followLinks);
|
||||
return controls;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the countLimit.
|
||||
*/
|
||||
public int getCountLimit() {
|
||||
return countLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param countLimit The countLimit to set.
|
||||
*/
|
||||
public void setCountLimit(int countLimit) {
|
||||
this.countLimit = countLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the followLinks.
|
||||
*/
|
||||
public boolean isFollowLinks() {
|
||||
return followLinks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param followLinks The followLinks to set.
|
||||
*/
|
||||
public void setFollowLinks(boolean followLinks) {
|
||||
this.followLinks = followLinks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the returnAttrNames.
|
||||
*/
|
||||
public String[] getReturnAttrNames() {
|
||||
return returnAttrNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param returnAttrNames The returnAttrNames to set.
|
||||
*/
|
||||
public void setReturnAttrNames(String[] returnAttrNames) {
|
||||
this.returnAttrNames = returnAttrNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the searchContextName.
|
||||
*/
|
||||
public String getSearchContextName() {
|
||||
return searchContextName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param searchContextName The searchContextName to set.
|
||||
*/
|
||||
public void setSearchContextName(String searchContextName) {
|
||||
this.searchContextName = searchContextName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the searchScope.
|
||||
*/
|
||||
public int getSearchScope() {
|
||||
return searchScope;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param searchScope The searchScope to set.
|
||||
*/
|
||||
public void setSearchScope(int searchScope) {
|
||||
this.searchScope = searchScope;
|
||||
}
|
||||
|
||||
/** Set the searchScope using a string, should be one of:
|
||||
* OBJECT_SCOPE, ONELEVEL_SCOPE, or SUBTREE_SCOPE (you probably want ONELEVEL_SCOPE).
|
||||
*
|
||||
* @param scope
|
||||
*/
|
||||
public void setSearchScope(String scope) {
|
||||
if ("OBJECT_SCOPE".equals(scope)) {
|
||||
setSearchScope( SearchControls.OBJECT_SCOPE );
|
||||
} else if ("ONELEVEL_SCOPE".equals(scope)) {
|
||||
setSearchScope( SearchControls.ONELEVEL_SCOPE );
|
||||
} else if ("SUBTREE_SCOPE".equals(scope)) {
|
||||
setSearchScope( SearchControls.SUBTREE_SCOPE );
|
||||
} else {
|
||||
logger.warn("Scope '" + scope + "' not recognized, setting to ONELEVEL_SCOPE");
|
||||
setSearchScope( SearchControls.ONELEVEL_SCOPE );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the timeout.
|
||||
*/
|
||||
public int getTimeout() {
|
||||
return timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param timeout The timeout to set.
|
||||
*/
|
||||
public void setTimeout(int timeout) {
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,208 +0,0 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package org.acegisecurity.providers.dao.ldap.revised;
|
||||
|
||||
import javax.naming.NamingEnumeration;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.directory.DirContext;
|
||||
import javax.naming.directory.SearchControls;
|
||||
import javax.naming.directory.SearchResult;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
/**
|
||||
* @author robert.sanders
|
||||
*
|
||||
*/
|
||||
public class UserSearchBean implements InitializingBean {
|
||||
|
||||
/** Context relative to the rootContext to which the directory is connected. */
|
||||
private String subContext;
|
||||
|
||||
/** If true then searches the entire subtree as idenified by context,
|
||||
* if false (the default) then only search the level identified by the context.
|
||||
*/
|
||||
private boolean searchSubtree = false;
|
||||
|
||||
/** The name and any associate information of the
|
||||
* ldap attribute used to match the username.
|
||||
* Expected in the form "uid={0}", or "uid={0}@company.com"
|
||||
* where {0} is the username that the user attempted to login with.
|
||||
*/
|
||||
private String usernameFilter;
|
||||
|
||||
/** LDAP Search Filter (@see 'RFC 2255'). NOTE: you can
|
||||
* use <b>either</b> searchFilter <b>or</b> filters, but <b>not</b>
|
||||
* both in a given LdapSearchBean.
|
||||
*/
|
||||
private String searchFilter = "objectClass=*";
|
||||
|
||||
/** The attribute used when attempting to log the
|
||||
* user in to the LDAP server, if not set it defaults
|
||||
* to the attribute identified by usernameAttr.
|
||||
* For some LDAP systems this may need to be something like "sAMAccountName" (MS ActiveDirectory).
|
||||
*/
|
||||
private String loginAttr;
|
||||
|
||||
/** The time (in milliseconds) which to wait before the search fails;
|
||||
* the default is zero, meaning forever.
|
||||
*/
|
||||
private int searchTimeLimit = 0;
|
||||
|
||||
/** Attributes of the User's LDAP Object that contain role name information. */
|
||||
private String[] roleAttributes;
|
||||
|
||||
/** Internal state - initialized at startup by combining the base searchFilter with the usernameFilter. */
|
||||
private String searchFilterInternal;
|
||||
|
||||
/** Internal state - initialized at startup based on the values of the JavaBean properties. */
|
||||
private SearchControls searchControls;
|
||||
|
||||
/** Return the JNDI SearchResult containing the user's information, or null if no SearchResult is found.
|
||||
*
|
||||
* @param ctx The context in which the search will be based (note that subContext property refines this).
|
||||
* @param username The username to search for.
|
||||
* @return The JNDI SearchResult containing the user's information, or null if no SearchResult is found.
|
||||
* @throws NamingException Passes on the Exception if a JNDI Exception occurs.
|
||||
*/
|
||||
public UserSearchResults searchForUser(DirContext ctx, String username) throws NamingException {
|
||||
//System.out.println("searchFilterInternal [" + searchFilterInternal + "]");
|
||||
NamingEnumeration enm = ctx.search(subContext, searchFilterInternal, new String[]{username}, searchControls);
|
||||
if (!enm.hasMore()) {
|
||||
return null; // user not found.
|
||||
}
|
||||
SearchResult searchResult = (SearchResult)enm.next();
|
||||
UserSearchResults userSearchResults = new UserSearchResults(searchResult);
|
||||
userSearchResults.setUserSearchBean(this);
|
||||
|
||||
String userDN = searchResult.getName();
|
||||
if (searchResult.isRelative()) {
|
||||
userDN = userDN + "," + subContext + "," + ctx.getNameInNamespace();
|
||||
}
|
||||
userSearchResults.setLdapName( userDN );
|
||||
|
||||
String loginName;
|
||||
if (null != loginAttr) {
|
||||
loginName = (String)userSearchResults.getAttributes().get(loginAttr).get();
|
||||
} else {
|
||||
loginName = userDN;
|
||||
}
|
||||
userSearchResults.setUserLoginName(loginName);
|
||||
|
||||
return userSearchResults;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
searchControls = new SearchControls();
|
||||
if (searchSubtree) {
|
||||
searchControls.setSearchScope( SearchControls.SUBTREE_SCOPE );
|
||||
} else {
|
||||
searchControls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
|
||||
}
|
||||
searchControls.setTimeLimit( searchTimeLimit );
|
||||
|
||||
String baseFilter = (null != searchFilter) ? searchFilter : "";
|
||||
searchFilterInternal = "(&(" + baseFilter + ")(" + usernameFilter + "))";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the loginAttr.
|
||||
*/
|
||||
public String getLoginAttr() {
|
||||
return loginAttr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param loginAttr The loginAttr to set.
|
||||
*/
|
||||
public void setLoginAttr(String loginAttr) {
|
||||
this.loginAttr = loginAttr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the roleAttributes.
|
||||
*/
|
||||
public String[] getRoleAttributes() {
|
||||
return roleAttributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param roleAttributes The roleAttributes to set.
|
||||
*/
|
||||
public void setRoleAttributes(String[] roleAttributes) {
|
||||
this.roleAttributes = roleAttributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the searchFilter.
|
||||
*/
|
||||
public String getSearchFilter() {
|
||||
return searchFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param searchFilter The searchFilter to set.
|
||||
*/
|
||||
public void setSearchFilter(String searchFilter) {
|
||||
this.searchFilter = searchFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the searchSubtree.
|
||||
*/
|
||||
public boolean isSearchSubtree() {
|
||||
return searchSubtree;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param searchSubtree The searchSubtree to set.
|
||||
*/
|
||||
public void setSearchSubtree(boolean searchSubtree) {
|
||||
this.searchSubtree = searchSubtree;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the searchTimeLimit.
|
||||
*/
|
||||
public int getSearchTimeLimit() {
|
||||
return searchTimeLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param searchTimeLimit The searchTimeLimit to set.
|
||||
*/
|
||||
public void setSearchTimeLimit(int searchTimeLimit) {
|
||||
this.searchTimeLimit = searchTimeLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the subContext.
|
||||
*/
|
||||
public String getSubContext() {
|
||||
return subContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param subContext The subContext to set.
|
||||
*/
|
||||
public void setSubContext(String subContext) {
|
||||
this.subContext = subContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the usernameFilter.
|
||||
*/
|
||||
public String getUsernameFilter() {
|
||||
return usernameFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param usernameFilter The usernameFilter to set.
|
||||
*/
|
||||
public void setUsernameFilter(String usernameFilter) {
|
||||
this.usernameFilter = usernameFilter;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package org.acegisecurity.providers.dao.ldap.revised;
|
||||
|
||||
import javax.naming.directory.Attributes;
|
||||
import javax.naming.directory.SearchResult;
|
||||
|
||||
/**
|
||||
* Encapsulates the information returned by a successful UserSearchBean
|
||||
*
|
||||
*/
|
||||
public class UserSearchResults {
|
||||
|
||||
private Attributes attributes;
|
||||
|
||||
/** The full DN of the user. */
|
||||
private String ldapName;
|
||||
|
||||
/** The name that should be used to log the user into the LDAP server (to test authentication). */
|
||||
private String userLoginName;
|
||||
|
||||
/** Internal state: the UserSearchBean which yeilded the results. */
|
||||
private UserSearchBean userSearchBean;
|
||||
|
||||
public UserSearchResults() {
|
||||
super();
|
||||
}
|
||||
|
||||
public UserSearchResults(SearchResult searchResult) {
|
||||
super();
|
||||
setAttributes( searchResult.getAttributes() );
|
||||
}
|
||||
|
||||
public UserSearchResults(SearchResult searchResult, UserSearchBean userSearchBean) {
|
||||
super();
|
||||
this.userSearchBean = userSearchBean;
|
||||
setAttributes( searchResult.getAttributes() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the attributes.
|
||||
*/
|
||||
public Attributes getAttributes() {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param attributes The attributes to set.
|
||||
*/
|
||||
public void setAttributes(Attributes attributes) {
|
||||
this.attributes = attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the name.
|
||||
*/
|
||||
public String getLdapName() {
|
||||
return ldapName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name The name to set.
|
||||
*/
|
||||
public void setLdapName(String name) {
|
||||
this.ldapName = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the userLoginName.
|
||||
*/
|
||||
public String getUserLoginName() {
|
||||
return userLoginName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param userLoginName The userLoginName to set.
|
||||
*/
|
||||
public void setUserLoginName(String userLoginName) {
|
||||
this.userLoginName = userLoginName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the userSearchBean.
|
||||
*/
|
||||
public UserSearchBean getUserSearchBean() {
|
||||
return userSearchBean;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param userSearchBean The userSearchBean to set.
|
||||
*/
|
||||
public void setUserSearchBean(UserSearchBean userSearchBean) {
|
||||
this.userSearchBean = userSearchBean;
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user