/** **************************************************************************** * * Copyright (c) 2001-2004 Tortuga Technologies Pty Ltd. All rights reserved. * * This is unpublished proprietary source code of Tortuga Technologies Pty Ltd. * The copyright notice above does not evidence any actual or intended * publication of such source code. * ******************************************************************************* * * File: au.com.tortuga.ozibug.auth.example.LDAPAuthenticationHandler.java * * Description: Example LDAP Authentication handler * **************************************************************************** */ package au.com.tortuga.ozibug.auth.example; // application specific imports import au.com.tortuga.ozibug.auth.AuthenticationHandler; import au.com.tortuga.ozibug.util.LifeCycle; // external imports import org.apache.log4j.Category; // ldap imports import com.novell.ldap.LDAPAttribute; import com.novell.ldap.LDAPConnection; import com.novell.ldap.LDAPEntry; import com.novell.ldap.LDAPException; import com.novell.ldap.LDAPSearchResults; // servlet imports import javax.servlet.http.HttpServletRequest; // java imports import java.util.Iterator; import java.util.Map; import java.text.MessageFormat; /** **************************************************************************** * * This example Authentication Handler uses an LDAP server * to verify the details of the user attempting access against. * The user id and password are obtained from the HttpServletRequest and then * the password verified against the plain text password retrieved * from the LDAP Server. *

* Note: this is an example which doesn't include * handling failed, dropped or broken connections to the LDAP server. * nor does it terminate and release any resources through * its destroy() method. *

*

* The following properties must be configured in the properties file as * they configure the details of the LDAP server and the searches carried * out against it. *

*
 * authentication.handler.1=au.com.tortuga.ozibug.auth.example.LDAPAuthenticationHandler
 * authentication.handler.1.parameter.1=ldap.host=ldap-host.yourdomain.com
 * authentication.handler.1.parameter.2=ldap.port=389
 * authentication.handler.1.parameter.3=ldap.bind.dn=cn=Manager,o=Your Company
 * authentication.handler.1.parameter.4=ldap.bind.passwd=bindPassword
 * authentication.handler.1.parameter.5=ldap.search.base=o=Your Company
 * authentication.handler.1.parameter.6=ldap.search.filter=(&(uid={0})(objectclass=inetorgperson))
 * 
* * @author Tortuga Technologies * **************************************************************************** */ public class LDAPAuthenticationHandler implements AuthenticationHandler,LifeCycle { /** ************************************************************************** * * Class (static) variables - public/protected/package/private * ************************************************************************** */ /** logging category */ private static final Category log = Category.getInstance( "au.com.tortuga.ozibug.auth.example.LDAPAuthenticationHandler" ); /** the name of this handler (LDAP) */ private static final String NAME = "LDAP"; /** * a description of how this handler authenticates (name/password in * http request against LDAP database) */ private static final String DESCRIPTION = "uses name/password in http request against LDAP database"; /** LDAP host property name */ public static final String LDAP_HOST = "ldap.host"; /** LDAP port property name */ public static final String LDAP_PORT = "ldap.port"; /** LDAP bind dn property name */ public static final String LDAP_BIND_DN = "ldap.bind.dn"; /** LDAP bind password property name */ public static final String LDAP_BIND_PASSWD = "ldap.bind.passwd"; /** LDAP search base property name */ public static final String LDAP_SEARCH_BASE = "ldap.search.base"; /** LDAP search filter property name */ public static final String LDAP_SEARCH_FILTER = "ldap.search.filter"; /** ************************************************************************** * * Instance variables - public/protected/package/private * ************************************************************************** */ /** holds the configuration information passed in at initialization time */ private Map ldapDetails = null; /** the connection to the LDAP server */ private LDAPConnection lc = null; /** the scope of the search to carry out on the server for each user */ private int searchScope = 0; /** the base that we will search from */ private String searchBase = null; /** the LDAP search filter which will return the user's details given the id */ private String searchFilter = null; /** ************************************************************************** * * Called on initialization this method stores the LDAP configuration and * then uses it to connect to the LDAP Server. * * @param handlerInfo configuration information * @see LifeCycle#init * ************************************************************************** */ public void init( Map handlerInfo ) throws Exception { String logId = "init"; // log the configuration parameters Iterator it = handlerInfo.keySet().iterator(); while ( it.hasNext() ) { String name = (String) it.next(); String value = (String) handlerInfo.get( name ); log.debug( logId + ": " + name + " = " + (name.equals(LDAP_BIND_PASSWD) ? "******" : value) ); } // save the configuration this.ldapDetails = handlerInfo; // and connect to the LDAP server connectLDAP(); // and we're initialized log.info( logId + ": done" ); } // init /** ************************************************************************** * * Called when the Ozibug servlet is terminated by the container. * * @see LifeCycle#destroy * ************************************************************************** */ public void destroy() { String logId = "destroy"; // free resources here ... // and we're done log.info( logId + ": done" ); } // destroy /** ************************************************************************** * * Returns the name of this Authentication Handler. * * @return the name of this authentication handler * @see AuthenticationHandler#getName * ************************************************************************** */ public String getName() { return NAME; } // getName /** ************************************************************************** * * Returns a description of this Authentiction Handler. * * @return a brief description of how this authentication handler works * @see AuthenticationHandler#getDescription * ************************************************************************** */ public String getDescription() { return DESCRIPTION; } // getDescription /** ************************************************************************** * * Compares the given user information against that stored on an LDAP Server; * Note: doesn't take into account encrypted passwords. * * @param context the context used to pass objects between handlers * @return true if an authentication was achieved; false otherwise * @see AuthenticationHandler#authenticate * ************************************************************************** */ public boolean authenticate( Map context ) { String logId = "authenticate"; boolean result = false; try { // get the HttpServletRequest from the context HttpServletRequest req = (HttpServletRequest) context.get( HTTP_REQUEST ); // get the users' parameters from the request String id = req.getParameter( "user" ); String passwd = req.getParameter( "password" ); // the password from the ldap server, we will compare against String ldapPasswd = null; // without these there's no point in continuing ! if ( (id == null) || (passwd == null) ) { // return quietly return result; } // carry out a search for the specified user (id) in the LDAP server LDAPSearchResults searchResults = null; try { searchResults = lc.search( searchBase, searchScope, MessageFormat.format( searchFilter, new Object[] { id } ), null, // return all attributes false // return attributes and values ); } catch ( Exception e ) { // search failed, log an informative message log.debug( logId +": LDAP search(" + id + ") failed, " + e, e ); // return false, the authentication failed return false; } // process the search results (hopefully only one) while ( searchResults.hasMore() ) { // get the LDAP database entry LDAPEntry nextEntry = null; try { nextEntry = searchResults.next(); } catch( LDAPException e ) { // something wrong with this one, move on to the next continue; } // get the LDAP password attribute LDAPAttribute attribute = nextEntry.getAttribute( "userPassword" ); ldapPasswd = attribute.getStringValue(); // print some useful debugging log.debug( logId + ": retrieved details of " + nextEntry.getDN() + ", id = " + id ); break; } // check the password from LDAP against the supplied password if ( passwd.equals(ldapPasswd) ) { // passwords match, set the return result to true result = true; // set the authenticated user id into the context context.put( USER_NAME, id ); } } catch ( Exception e ) { // unexpected exception while processing, log it and continue log.error( logId + ": failed, " + e, e ); } // return the status of this authentication attempt return result; } // authenticate /** ************************************************************************** * * Connect to the LDAP server using the parameters in the * handlerInfo map * which was passed in the init() method. * * @throws Exception if the connection or bind failed * ************************************************************************** */ private void connectLDAP() throws Exception { String logId = "connectLDAP"; // extract the details int ldapPort = LDAPConnection.DEFAULT_PORT; try { ldapPort = Integer.parseInt( (String) this.ldapDetails.get(LDAP_PORT) ); } catch ( Exception ignored ) {} searchScope = LDAPConnection.SCOPE_SUB; int ldapVersion = LDAPConnection.LDAP_V3; String ldapHost = (String) this.ldapDetails.get( LDAP_HOST ); String loginDN = (String) this.ldapDetails.get( LDAP_BIND_DN ); String password = (String) this.ldapDetails.get( LDAP_BIND_PASSWD ); searchBase = (String) this.ldapDetails.get( LDAP_SEARCH_BASE ); searchFilter = (String) this.ldapDetails.get( LDAP_SEARCH_FILTER ); // make a connection lc = new LDAPConnection(); // connect to the server lc.connect( ldapHost, ldapPort ); log.debug( logId + ": connecting to ldap://" + ldapHost + ":" + ldapPort + "/" ); // bind to the server lc.bind( ldapVersion, loginDN, password.getBytes("UTF8") ); log.debug( logId + ": bound as \"" + loginDN + "\"" ); } // connectLDAP } // LDAPAuthenticationHandler