[ http://jira.dspace.org/jira/browse/DS-50?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=10525#action_10525 ]
Van Ly edited comment on DS-50 at 9/7/09 8:33 AM: -------------------------------------------------- [14:14] <SamO> LDAPHierarchicalAuth seems to take care of issue. See also: http://wiki.dspace.org/index.php/JIRA_Cleanup#2009-08-25 was (Author: vly): [14:14] <SamO> LDAPHierarchicalAuth seems to take care of issue. > LDAP+Active Directory authentication patch - ID: 2100378 > -------------------------------------------------------- > > Key: DS-50 > URL: http://jira.dspace.org/jira/browse/DS-50 > Project: DSpace 1.x > Issue Type: Improvement > Reporter: Charles Kiplagat > > Thanks, Stuart - > I'll submit the patch to the queue. > You can grab a zip file that includes only the > changed files here: > http://erwg.lib.auburn.edu/dspace-ldap_20080828.zip > The main changes were: > *. Our A.D. setup does not allow anonymous bind, > and also has user info scattered around the LDAP tree. > To bind an arbitrary user, we pass a distinguished name > of: > DOMAIN\USER-ID > rather than some LDAP path like cn=USER&ou=People&dc=... > We detect this case by allowing the admin > to specify > windows_domain:domain-name > (something like that) as the LDAP object-context in dspace.cfg. > *. Since our user info is scattered through an LDAP tree - > I patched the "lookup user info" part of the code > to specify a recursive JNDI search. > Your last patch may have done the same thing. > *. We would like a user that successfully authenticates against A.D. > to automatically be given certain privileges. > I setup the getSpecialGroups function to accept a list of group-ids in > the > "ldap.dspace.autogroup" > dspace.cfg parameter. > *. I wanted to be able to run a standalone test case against the LDAP > authenticate and search code, so I split out the 'DataFromLDAP' > nested class to an external interface, and include a junit test case. > Also added a few lines to pom.xml to help run the test with verbose > logging, etc. > Cheers, > Reuben > >>> Stuart Lewis <s...@aber.ac.uk> 9/6/2008 7:57 AM >>> > Hi Reuben, > Thanks for getting in touch. I¹ve got that email sitting in my inbox > waiting > for me to get around to replying to it - sorry it has taken a little > while. > What changes have you made to make it work with Active Directory? > It would be great if you could formally submit your patch to the DSpace > patch queue > (http://sourceforge.net/tracker/?atid=319984&group_id=19984&func=browse). > There are a few of us working on a generic LDAP authenticator which will > hopefully work with any AD / LDAP system, so it would be good to see what > changes you¹ve made to see if we can incorporate them too. > Thanks, > Stuart > On 28/08/2008 16:14, "Reuben Pasquini" <rdp0...@auburn.edu> wrote: > > Hello! > > > > I've put together a set of patches to the LDAPAuthentication > > code to get it working against Active Directory at Auburn > > University, support implicit-group member-ids in dspace.cfg, > > and add a JUnit regression test. > > I think the changes are backward compatable and generic, > > but I've only tested the code in my environment. > > > > I hope that we can check this patch into the dspace repository. > > An overview and svn diff follow, and a zip file with > > the modified files is available here: > > http://erwg.lib.auburn.edu/dspace-ldap_20080828.zip > > Please take a look, and let me know what you think. > > > > Cheers, > > Reuben > > > > ----------------------------------- > > > > Changes under dspace-api org.dspace.authentication. > > > > *. Moved the > > LDAPAuthentication.SpeakerToLDAP > > nested class out to its own non-nested interface > > with a DefaultSpeakerToLDAP implementation. > > > > *. Refactored SpeakerToLDAP#ldapAuthenticate(...) > > to return a DataFromLDAP POJO data object > > rather than set object member variables. > > > > *. Implemented SpeakerToLDAPCase JUnit test-case > > and PackageTestSuite classes to support simple > > regression tests against SpeakerToLDAP implementations. > > Modified pom.xml so that > > 'mvn test' > > runs with a verbose log4j setting. > > > > *. Modified the way SpeakToLDAP handles the > > ldap.object_context > > dspace.cfg configuration property so that > > if the ldap.object_context matches > > 'WINDOWS_DOMAIN:DOMAIN_NAME', > > then LDAP attempts to bind with > > 'DOMAIN_NAME\NETID' > > rather than > > 'cn=NETID,ldap.object_context' > > . This change allows us to configure LDAP > > to bind with Active Directory out of the box. > > > > *. Modifed the LDAP search for user-info to take a SearchControls > > parameter that specifies a recursive tree-search under the > > ldap.search_context > > tree for a single user-object result. > > Once again - this allows LDAPAuthenticate to work > > with an Active Directory tree that has user objects > > organized into different folders under a tree. > > > > *. Modified LDAPAuthentication.getSpecialGroups > > to access the > > ldap.dspace.autogroup > > dspace.cfg configuration property > > to get the group-ids that an LDAP-authenticated > > user should be an implicit member of. > > This makes it easy to configure a system where > > every user that can authenticate can also > > submit material to some collections. > > > > *. Changed some of the if/else nesting in > > LDAPAuthentication.authenticate > > so that instead of having something like > > if () { > > ... > > return bla; > > } else { > > we have > > if () { > > ... > > return bla; > > } > > ... // no else > > and instead of > > } else { > > if () { > > return goo > > } > > } > > we just have > > } else if () { > > just to make the control flow a little > > easier to look at. > > > > ---------------------------------- > > > > $ svn diff pom.xml src/test src/main/java/org/dspace/authenticate > > > /tmp/bla > > > > Index: pom.xml > > =================================================================== > > --- pom.xml (revision 2942) > > +++ pom.xml (working copy) > > @@ -61,6 +61,7 @@ > > > > > <url>http://dspace.svn.sourceforge.net/viewvc/dspace/branches/dspace-1_5_x/ > dsp > > ace</url> > > </scm> > > > > + > > <!-- > > Runtime and Compile Time dependencies for DSpace. > > --> > > @@ -188,6 +189,23 @@ > > <groupId>com.ibm.icu</groupId> > > <artifactId>icu4j</artifactId> > > </dependency> > > + <dependency> > > + <groupId>junit</groupId> > > + <artifactId>junit</artifactId> > > + <version>3.8.1</version> > > + <scope>test</scope> > > + </dependency> > > </dependencies> > > > > -</project> > > \ No newline at end of file > > +<build> > > + <testResources> > > + <testResource> > > + <directory>src/test/resources</directory> > > + <includes> > > + <include>log4j.properties</include> > > + </includes> > > + </testResource> > > + </testResources> > > + </build> > > + > > +</project> > > Index: src/test/java/org/dspace/authenticate/SpeakerToLDAPCase.java > > =================================================================== > > --- > > src/test/java/org/dspace/authenticate/SpeakerToLDAPCase.java (revision > > 0) > > +++ > > src/test/java/org/dspace/authenticate/SpeakerToLDAPCase.java (revision > > 0) > > @@ -0,0 +1,56 @@ > > +package org.dspace.authenticate; > > + > > + > > +import junit.framework.TestCase; > > + > > +import org.apache.log4j.Logger; > > + > > +/** > > + * Generic test runner for SpeakerToLDAP implementations. > > + */ > > +public class SpeakerToLDAPCase extends TestCase { > > + private static final Logger olog = Logger.getLogger( > > SpeakerToLDAPCase.class ); > > + > > + private SpeakerToLDAP oldap; > > + private String os_netid; > > + private String os_password; > > + > > + > > + /** > > + * Inject the test dependencies - initializes test properties > > + * > > + * @param s_name of test - pass to super > > + * @param ldap instance to authenticate agains > > + * @param s_netid user-id to authenticate as > > + * @param s_password for s_netid > > + */ > > + public SpeakerToLDAPCase ( String s_name, SpeakerToLDAP ldap, > > + String s_netid, String s_password > > + ) { > > + super( s_name ); > > + oldap = ldap; > > + os_netid = s_netid; > > + os_password = s_password; > > + } > > + > > + /** > > + * Try to authenticate against the constructor-supplied > > + * (SpeakerToLDAP, s_netid, s_password) > > + */ > > + public void testAuthenticate() { > > + try { > > + DataFromLDAP ldap_info = oldap.ldapAuthenticate( os_netid, > > os_password ); > > + assertTrue( "Test user logged in ok: " + os_netid, > > + null != ldap_info > > + ); > > + // need e-mail to key into eperson database > > + olog.info( "Got e-mail for " + os_netid + ": " + > > ldap_info.getEmail () ); > > + assertTrue( "Got e-mail info for " + os_netid + " from > > ldap", > > + null != ldap_info.getEmail () > > + ); > > + } catch ( Exception e ) { > > + olog.info( "Failed to authenticate user: " + os_netid, e > > ); > > + assertTrue( "Failed to authenticate user: " + os_netid + > > ", caught: " + e, false ); > > + } > > + } > > +} > > Index: src/test/java/org/dspace/authenticate/PackageTest.java > > =================================================================== > > --- > > src/test/java/org/dspace/authenticate/PackageTest.java (revision > > 0) > > +++ > > src/test/java/org/dspace/authenticate/PackageTest.java (revision > > 0) > > @@ -0,0 +1,40 @@ > > +package org.dspace.authenticate; > > + > > + > > +import junit.framework.TestCase; > > +import junit.framework.TestSuite; > > + > > +import org.apache.log4j.Logger; > > + > > +/** > > + * Specialization of AbstactSpeakerToLDAPTest configured > > + * to run a DefaultSpeakerToLDAPTest through a test. > > + */ > > +public class PackageTest extends TestCase { > > + private static final Logger olog = Logger.getLogger( > > PackageTest.class ); > > + > > + > > + /** > > + * Build up the batch of tests to run for the > > org.dspace.authenticate > > + * package. You'll have to modify the properties injected into > > the > > + * test SpeakerToLDAP to work with your environment > > + */ > > + public static TestSuite suite () { > > + TestSuite suite = new TestSuite( PackageTest.class.getName > > () ); > > + SpeakerToLDAP ldap = new DefaultSpeakerToLDAP ( > > "ldap://ldaps.university.edu", > > + "cn", > > + > > "OU=People,OU=AUMain,DC=auburn,DC=edu", > > + > > "WINDOWS_DOMAIN:AUBURN", > > + "mail", > > + "givenName", > > + "sn", > > + > > "telephoneNumber" > > + ); > > + suite.addTest ( new SpeakerToLDAPCase( "testAuthenticate", > > ldap, > > + "USER", "PASSWORD" > > + ) > > + ); > > + return suite; > > + } > > + > > +} > > Index: src/test/resources/log4j.properties > > =================================================================== > > --- src/test/resources/log4j.properties (revision 0) > > +++ src/test/resources/log4j.properties (revision 0) > > @@ -0,0 +1,9 @@ > > +# Set root logger level to DEBUG and its only appender to A1. > > +log4j.rootLogger=DEBUG, A1 > > + > > +# A1 is set to be a ConsoleAppender. > > +log4j.appender.A1=org.apache.log4j.ConsoleAppender > > + > > +# A1 uses PatternLayout. > > +log4j.appender.A1.layout=org.apache.log4j.PatternLayout > > +log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - > > %m%n > > Index: src/main/java/org/dspace/authenticate/LDAPAuthentication.java > > =================================================================== > > --- > > src/main/java/org/dspace/authenticate/LDAPAuthentication.java (revision > > 3054) > > +++ > > src/main/java/org/dspace/authenticate/LDAPAuthentication.java (working > > copy) > > @@ -40,17 +40,11 @@ > > package org.dspace.authenticate; > > > > import java.sql.SQLException; > > +import java.util.ArrayList; > > +import java.util.List; > > import java.util.Hashtable; > > > > -import javax.naming.NamingEnumeration; > > import javax.naming.NamingException; > > -import javax.naming.directory.Attribute; > > -import javax.naming.directory.Attributes; > > -import javax.naming.directory.BasicAttribute; > > -import javax.naming.directory.BasicAttributes; > > -import javax.naming.directory.DirContext; > > -import javax.naming.directory.InitialDirContext; > > -import javax.naming.directory.SearchResult; > > import javax.servlet.http.HttpServletRequest; > > import javax.servlet.http.HttpServletResponse; > > > > @@ -60,6 +54,7 @@ > > import org.dspace.core.Context; > > import org.dspace.core.LogManager; > > import org.dspace.eperson.EPerson; > > +import org.dspace.eperson.Group; > > > > /** > > * Authentication module to authenticate against a flat LDAP tree > > where > > @@ -72,9 +67,66 @@ > > implements AuthenticationMethod { > > > > /** log4j category */ > > - private static Logger log = > > Logger.getLogger(LDAPAuthentication.class); > > + private static final Logger olog = > > Logger.getLogger(LDAPAuthentication.class); > > > > + private final SpeakerToLDAP oldap; > > + > > /** > > + * Constructor injects SpeakerToLDAP dependency > > + * > > + * @param ldap SpeakerToLDAP knows how to authenticate > > + * against and query the LDAP directory > > + * @param b_autoregister set true to auto-register an eperson > > + * for a new user that succesfully authenticates > > + * with LDAP > > + * @param v_special_group ids of user groups that an > > LDAP-authenticated > > + * user should be considered an implicit member of > > + */ > > + public LDAPAuthentication ( SpeakerToLDAP ldap, > > + boolean b_autoregister, > > + int[] v_special_group > > + ) { > > + oldap = ldap; > > + ob_autoregister = b_autoregister; > > + ov_special_group = v_special_group; > > + } > > + > > + /** > > + * Constructor invoked by dspace.cfg based configuration > > + * engine sets up DefaultSpeakerToLDAP, > > + * checks ldap.autoregister and ldap.dspace.autogroup > > + * configuration values to determine canSelfRegister > > + * and getSpecialGroups property values. > > + */ > > + public LDAPAuthentication () { > > + String s_groups = > > ConfigurationManager.getProperty("ldap.dspace.autogroup"); > > + > > + List<Integer> v_group_id = new ArrayList<Integer>(); > > + if ( null != s_groups ) { > > + String[] v_group_name = s_groups.trim ().split( > > ",\\s*" ); > > + for ( int i=0; i < v_group_name.length; ++i ) { > > + String s_group = v_group_name[i].trim (); > > + if ( s_group.length () > 0 ) { > > + try { > > + v_group_id.add ( Integer.parseInt( s_group ) > > ); > > + } catch ( Exception e ) { > > + olog.warn( "Exception parsing group " + > > s_group, e ); > > + } > > + } > > + } > > + } > > + oldap = new DefaultSpeakerToLDAP (); > > + ob_autoregister = > > ConfigurationManager.getBooleanProperty("webui.ldap.autoregister"); > > + ov_special_group = new int[ v_group_id.size () ]; > > + int i_count = 0; > > + for ( Integer i_group_id : v_group_id ) { > > + ov_special_group[ i_count ] = i_group_id; > > + ++i_count; > > + } > > + } > > + > > + private final boolean ob_autoregister; > > + /** > > * Let a real auth method return true if it wants. > > */ > > public boolean canSelfRegister(Context context, > > @@ -83,8 +135,7 @@ > > throws SQLException > > { > > // XXX might also want to check that username exists in LDAP. > > - > > - return > > ConfigurationManager.getBooleanProperty("webui.ldap.autoregister"); > > + return ob_autoregister; > > } > > > > /** > > @@ -118,12 +169,10 @@ > > return false; > > } > > > > - /* > > - * Nothing here. > > - */ > > + private final int[] ov_special_group; > > public int[] getSpecialGroups(Context context, HttpServletRequest > > request) > > { > > - return new int[0]; > > + return ov_special_group; > > } > > > > /* > > @@ -139,261 +188,140 @@ > > HttpServletRequest request) > > throws SQLException > > { > > - log.info(LogManager.getHeader(context, "auth", "attempting > > trivial auth of user="+netid)); > > + olog.info(LogManager.getHeader(context, "auth", "attempting > > auth of user="+netid)); > > > > // Skip out when no netid or password is given. > > - if (netid == null || password == null) > > - return BAD_ARGS; > > + if (netid == null || password == null) { > > + return BAD_ARGS; > > + } > > > > // Locate the eperson > > - EPerson eperson = null; > > + EPerson eperson = null; > > try > > { > > - eperson = EPerson.findByNetid(context, > > netid.toLowerCase()); > > + eperson = EPerson.findByNetid(context, > > netid.toLowerCase()); > > } > > catch (SQLException e) > > { > > } > > - boolean loggedIn = false; > > - SpeakerToLDAP ldap = new SpeakerToLDAP(log); > > > > + olog.debug( "Found eperson for " + netid ); > > + > > // if they entered a netid that matches an eperson > > if (eperson != null) > > { > > // e-mail address corresponds to active account > > - if (eperson.getRequireCertificate()) > > + if (eperson.getRequireCertificate()) { > > return CERT_REQUIRED; > > - else if (!eperson.canLogIn()) > > + } else if (!eperson.canLogIn()) { > > return BAD_ARGS; > > - { > > - if (ldap.ldapAuthenticate(netid, password, context)) > > - { > > + } > > + try { > > + // authenticate > > + olog.debug( "Attempting LDAP auth-1 for " + netid ); > > + DataFromLDAP ldap_info = oldap.ldapAuthenticate( > > netid, password ); > > + if ( null != ldap_info ) { > > context.setCurrentUser(eperson = > > EPerson.findByNetid(context, netid.toLowerCase())); > > - log.info(LogManager > > - .getHeader(context, "authenticate", > > "type=ldap")); > > + olog.info(LogManager > > + .getHeader(context, "authenticate", > > "type=ldap")); > > return SUCCESS; > > - } > > - else > > - return BAD_CREDENTIALS; > > + } > > + } catch ( NamingException e ) { > > + olog.warn( "Failed to authenticate user: " + netid, e > > ); > > } > > + //else { > > + return BAD_CREDENTIALS; > > + } > > + // eperson == null > > + if ( null != eperson ) { > > + throw new AssertionError( "eperson should be null here!" > > ); > > } > > - > > - // the user does not already exist so try and authenticate > > them > > - // with ldap and create an eperson for them > > - else > > - { > > - if (ldap.ldapAuthenticate(netid, password, context)) > > - { > > - // Register the new user automatically > > - log.info(LogManager.getHeader(context, > > - "autoregister", "netid=" + netid)); > > - > > - if > > ((ldap.ldapEmail!=null)&&(!ldap.ldapEmail.equals(""))) > > - { > > - try > > - { > > - eperson = EPerson.findByEmail(context, > > ldap.ldapEmail); > > - if (eperson!=null) > > - { > > - log.info(LogManager.getHeader(context, > > - "type=ldap-login", > > "type=ldap_but_already_email")); > > - context.setIgnoreAuthorization(true); > > - eperson.setNetid(netid); > > - eperson.update(); > > - context.commit(); > > - context.setIgnoreAuthorization(false); > > - context.setCurrentUser(eperson); > > - return SUCCESS; > > - } > > - else > > - { > > - if (canSelfRegister(context, request, > > netid)) > > - { > > - // TEMPORARILY turn off > > authorisation > > - try > > - { > > - > > context.setIgnoreAuthorization(true); > > - eperson = > > EPerson.create(context); > > - if > > ((ldap.ldapEmail!=null)&&(!ldap.ldapEmail.equals(""))) > > eperson.setEmail(ldap.ldapEmail); > > - else eperson.setEmail(netid); > > - if > > ((ldap.ldapGivenName!=null)&&(!ldap.ldapGivenName.equals(""))) > > eperson.setFirstName(ldap.ldapGivenName); > > - if > > ((ldap.ldapSurname!=null)&&(!ldap.ldapSurname.equals(""))) > > eperson.setLastName(ldap.ldapSurname); > > - if > > ((ldap.ldapPhone!=null)&&(!ldap.ldapPhone.equals(""))) > > eperson.setMetadata("phone", ldap.ldapPhone); > > - eperson.setNetid(netid); > > - eperson.setCanLogIn(true); > > - > > AuthenticationManager.initEPerson(context, request, eperson); > > - eperson.update(); > > - context.commit(); > > - context.setCurrentUser(eperson); > > - } > > - catch (AuthorizeException e) > > - { > > - return NO_SUCH_USER; > > - } > > - finally > > - { > > - > > context.setIgnoreAuthorization(false); > > - } > > - > > - > > log.info(LogManager.getHeader(context, "authenticate", > > - "type=ldap-login, > > created ePerson")); > > - return SUCCESS; > > - } > > - else > > - { > > - // No auto-registration for valid > > certs > > - > > log.info(LogManager.getHeader(context, > > - "failed_login", > > "type=ldap_but_no_record")); > > - return NO_SUCH_USER; > > - } > > - } > > - } > > - catch (AuthorizeException e) > > - { > > - eperson = null; > > - } > > - finally > > - { > > - context.setIgnoreAuthorization(false); > > - } > > - } > > - } > > + olog.debug( "Attempting LDAP auth-2 for " + netid ); > > + DataFromLDAP ldap_info = null; > > + try { > > + ldap_info = oldap.ldapAuthenticate( netid, password ); > > + } catch ( NamingException e ) { > > + olog.warn( "Failed to authenticate user: " + netid, e ); > > } > > - return BAD_ARGS; > > - } > > - > > - /** > > - * Internal class to manage LDAP query and results, mainly > > - * because there are multiple values to return. > > - */ > > - public class SpeakerToLDAP { > > - > > - private Logger log = null; > > - > > - /** ldap email result */ > > - protected String ldapEmail = null; > > - > > - /** ldap name result */ > > - protected String ldapGivenName = null; > > - protected String ldapSurname = null; > > - protected String ldapPhone = null; > > - > > - SpeakerToLDAP(Logger thelog) > > - { > > - log = thelog; > > + if ( (null == ldap_info) > > + || (ldap_info.getEmail()==null) > > + || ldap_info.getEmail().equals("") > > + ) { > > + return BAD_ARGS; // failed to authenticate or get e-mail > > address > > } > > > > - /** > > - * contact the ldap server and attempt to authenticate > > - */ > > - protected boolean ldapAuthenticate(String netid, String > > password, Context context) > > - { > > - if (!password.equals("")) > > - { > > - String ldap_provider_url = > > ConfigurationManager.getProperty("ldap.provider_url"); > > - String ldap_id_field = > > ConfigurationManager.getProperty("ldap.id_field"); > > - String ldap_search_context = > > ConfigurationManager.getProperty("ldap.search_context"); > > - String ldap_object_context = > > ConfigurationManager.getProperty("ldap.object_context"); > > - > > - // Set up environment for creating initial context > > - Hashtable env = new Hashtable(11); > > - env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, > > "com.sun.jndi.ldap.LdapCtxFactory"); > > - env.put(javax.naming.Context.PROVIDER_URL, > > ldap_provider_url); > > - > > - // Authenticate > > - env.put(javax.naming.Context.SECURITY_AUTHENTICATION, > > "simple"); > > - env.put(javax.naming.Context.SECURITY_PRINCIPAL, > > ldap_id_field+"="+netid+","+ldap_object_context); > > - env.put(javax.naming.Context.SECURITY_CREDENTIALS, > > password); > > - > > - DirContext ctx = null; > > - try > > - { > > - // Create initial context > > - ctx = new InitialDirContext(env); > > - > > - String ldap_email_field = > > ConfigurationManager.getProperty("ldap.email_field"); > > - String ldap_givenname_field = > > ConfigurationManager.getProperty("ldap.givenname_field"); > > - String ldap_surname_field = > > ConfigurationManager.getProperty("ldap.surname_field"); > > - String ldap_phone_field = > > ConfigurationManager.getProperty("ldap.phone_field"); > > - > > - Attributes matchAttrs = new > > BasicAttributes(true); > > - matchAttrs.put(new BasicAttribute(ldap_id_field, > > netid)); > > - > > - String attlist[] = {ldap_email_field, > > ldap_givenname_field, ldap_surname_field, ldap_phone_field}; > > - > > - // look up attributes > > - try > > - { > > - NamingEnumeration answer = > > ctx.search(ldap_search_context, matchAttrs, attlist); > > - while(answer.hasMore()) { > > - SearchResult sr = > > (SearchResult)answer.next(); > > - Attributes atts = sr.getAttributes(); > > - Attribute att; > > - > > - if (attlist[0]!=null) > > - { > > - att = atts.get(attlist[0]); > > - if (att != null) ldapEmail = > > (String)att.get(); > > - } > > - > > - if (attlist[1]!=null) > > - { > > - att = atts.get(attlist[1]); > > - if (att != null) ldapGivenName = > > (String)att.get(); > > - } > > - > > - if (attlist[2]!=null) > > - { > > - att = atts.get(attlist[2]); > > - if (att != null) ldapSurname = > > (String)att.get(); > > - } > > - > > - if (attlist[3]!=null) > > - { > > - att = atts.get(attlist[3]); > > - if (att != null) ldapPhone = > > (String)att.get(); > > - } > > - } > > + // > > + // autoregister the ldap-authenticated user > > + // > > + olog.info(LogManager.getHeader(context, > > + "autoregister", "netid=" + > > netid) > > + ); > > + > > + try { > > + eperson = EPerson.findByEmail(context, > > ldap_info.getEmail()); > > + if (eperson!=null) { > > + // Just need to set the netid on the eperson record > > + olog.info(LogManager.getHeader(context, > > + "type=ldap-login", > > "type=ldap_but_already_email")); > > + context.setIgnoreAuthorization(true); > > + eperson.setNetid(netid); > > + eperson.update(); > > + context.commit(); > > + context.setIgnoreAuthorization(false); > > + context.setCurrentUser(eperson); > > + return SUCCESS; > > + } else if (canSelfRegister(context, request, netid)) { > > + // TEMPORARILY turn off authorisation > > + try { > > + context.setIgnoreAuthorization(true); > > + eperson = EPerson.create(context); > > + eperson.setEmail(ldap_info.getEmail()); > > + if ((ldap_info.getGivenName()!=null) > > + &&(!ldap_info.getGivenName().equals("")) > > + ) { > > + > > eperson.setFirstName(ldap_info.getGivenName()); > > } > > - catch (NamingException e) > > - { > > - // if the lookup fails go ahead and create a > > new record for them because the authentication > > - // succeeded > > - log.warn(LogManager.getHeader(context, > > - "ldap_attribute_lookup", > > "type=failed_search "+e)); > > - return true; > > + if ((ldap_info.getSurname()!=null) > > + &&(!ldap_info.getSurname().equals("")) > > + ) { > > + eperson.setLastName(ldap_info.getSurname()); > > } > > - } > > - catch (NamingException e) > > - { > > - log.warn(LogManager.getHeader(context, > > - "ldap_authentication", > > "type=failed_auth "+e)); > > - return false; > > - } > > - finally > > - { > > - // Close the context when we're done > > - try > > - { > > - if (ctx != null) > > - ctx.close(); > > + if ((ldap_info.getPhone()!=null) > > + &&(!ldap_info.getPhone().equals("")) > > + ) { > > + eperson.setMetadata("phone", > > ldap_info.getPhone()); > > } > > - catch (NamingException e) > > - { > > - } > > + eperson.setNetid(ldap_info.getNetId()); > > + eperson.setCanLogIn(true); > > + AuthenticationManager.initEPerson(context, > > request, eperson); > > + eperson.update(); > > + context.commit(); > > + context.setCurrentUser(eperson); > > + } catch (AuthorizeException e) { > > + return NO_SUCH_USER; > > + } finally { > > + context.setIgnoreAuthorization(false); > > } > > + olog.info(LogManager.getHeader(context, > > "authenticate", > > + "type=ldap-login, > > created ePerson")); > > + return SUCCESS; > > + } else { > > + // No auto-registration for valid certs > > + olog.info(LogManager.getHeader(context, > > + "failed_login", > > "type=ldap_but_no_record")); > > + return NO_SUCH_USER; > > } > > - else > > - { > > - return false; > > - } > > - > > - return true; > > + } catch (AuthorizeException e) { > > + eperson = null; > > + // authentication failed > > + return BAD_ARGS; > > + } finally { > > + context.setIgnoreAuthorization(false); > > } > > - > > - > > + // Unreachable! > > } > > > > + > > /* > > * Returns URL to which to redirect to obtain credentials (either > > password > > * prompt or e.g. HTTPS port for client cert.); null means no > > redirect. > > @@ -430,4 +358,4 @@ > > { > > return "org.dspace.eperson.LDAPAuthentication.title"; > > } > > -} > > \ No newline at end of file > > +} > > Index: src/main/java/org/dspace/authenticate/DefaultSpeakerToLDAP.java > > =================================================================== > > --- > > src/main/java/org/dspace/authenticate/DefaultSpeakerToLDAP.java > (revision > > 0) > > +++ > > src/main/java/org/dspace/authenticate/DefaultSpeakerToLDAP.java > (revision > > 0) > > @@ -0,0 +1,183 @@ > > +package org.dspace.authenticate; > > + > > +import java.util.Hashtable; > > + > > +import javax.naming.NamingEnumeration; > > +import javax.naming.NamingException; > > +import javax.naming.directory.Attribute; > > +import javax.naming.directory.Attributes; > > +import javax.naming.directory.BasicAttribute; > > +import javax.naming.directory.BasicAttributes; > > +import javax.naming.directory.DirContext; > > +import javax.naming.directory.InitialDirContext; > > +import javax.naming.directory.SearchControls; > > +import javax.naming.directory.SearchResult; > > + > > +import org.apache.log4j.Logger; > > +import org.dspace.core.ConfigurationManager; > > + > > +/** > > + * Internal class to manage LDAP query and results, mainly > > + * because there are multiple values to return. > > + */ > > +public class DefaultSpeakerToLDAP implements SpeakerToLDAP { > > + private static final Logger olog = > > Logger.getLogger(DefaultSpeakerToLDAP.class); > > + private final String os_provider_url; > > + private final String os_id_field; > > + private final String os_search_context; > > + private final String os_object_context; > > + private final String os_email_field; > > + private final String os_givenname_field; > > + private final String os_surname_field; > > + private final String os_phone_field; > > + > > + > > + /** > > + * Constructor allows injection of > > + * configuration parameters. > > + * > > + * @param s_provider_url to the server - we assume simple > > authentication > > + * @param s_id_field attribute of user object - usually cn > > + * @param s_search_context subtree under which to search for user > > info, > > + * ex: ou=People,dc=myschool,dc=edu > > + * @param s_object_context of user bind-path - > > + * ex: ou=People,dc=myschool,dc=edu leads to bind attempt > > + * againt cn=username,ou=People,dc=myschool,dc=edu > > + * @param s_email_field in user record > > + * @param s_givenname_field in user record > > + * @param s_surname_field in user record, usually sn > > + * @param s_phone_field in user record > > + */ > > + public DefaultSpeakerToLDAP( String s_provider_url, > > + String s_id_field, > > + String s_search_context, > > + String s_object_context, > > + String s_email_field, > > + String s_givenname_field, > > + String s_surname_field, > > + String s_phone_field > > + ) > > + { > > + os_provider_url = s_provider_url; > > + os_id_field = s_id_field; > > + os_search_context = s_search_context; > > + os_object_context = s_object_context; > > + os_email_field = s_email_field; > > + os_givenname_field = s_givenname_field; > > + os_surname_field = s_surname_field; > > + os_phone_field = s_phone_field; > > + } > > + > > + /** > > + * Default constructor extracts LDAP-server parameters > > + * from ConfigurationManager (dspace.cfg): > > + * ldap.provider_url, ldap_id_field, > > + * ldap_search_contect, ldap_object_context > > + */ > > + public DefaultSpeakerToLDAP() { > > + os_provider_url = > > ConfigurationManager.getProperty("ldap.provider_url"); > > + os_id_field = > > ConfigurationManager.getProperty("ldap.id_field"); > > + os_search_context = > > ConfigurationManager.getProperty("ldap.search_context"); > > + os_object_context = > > ConfigurationManager.getProperty("ldap.object_context"); > > + os_email_field = > > ConfigurationManager.getProperty("ldap.email_field"); > > + os_givenname_field = > > ConfigurationManager.getProperty("ldap.givenname_field"); > > + os_surname_field = > > ConfigurationManager.getProperty("ldap.surname_field"); > > + os_phone_field = > > ConfigurationManager.getProperty("ldap.phone_field"); > > + } > > + > > + /** > > + * contact the ldap server and attempt to authenticate > > + */ > > + public DataFromLDAP ldapAuthenticate(String s_netid, String > > s_password ) throws NamingException > > + { > > + if (s_password.equals("")) > > + { > > + return null; > > + } > > + // Set up environment for creating initial context > > + Hashtable env = new Hashtable(11); > > + env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, > > "com.sun.jndi.ldap.LdapCtxFactory"); > > + env.put(javax.naming.Context.PROVIDER_URL, os_provider_url); > > + > > + // Authenticate > > + env.put(javax.naming.Context.SECURITY_AUTHENTICATION, > > "simple"); > > + final String s_ad_key = "WINDOWS_DOMAIN:"; > > + if ( os_object_context.toUpperCase ().startsWith( s_ad_key ) ) > > { > > + // Active Directory bind > > + String s_principal = os_object_context.substring( > > s_ad_key.length () ) + "\\" + s_netid; > > + olog.debug( "Binding principal to: " + s_principal ); > > + env.put(javax.naming.Context.SECURITY_PRINCIPAL, > > s_principal ); > > + } else { > > + env.put(javax.naming.Context.SECURITY_PRINCIPAL, > > os_id_field+"="+s_netid+","+os_object_context); > > + } > > + env.put(javax.naming.Context.SECURITY_CREDENTIALS, > > s_password); > > + > > + DirContext ctx = new InitialDirContext(env); > > + try { > > + Attributes search_attributes = new BasicAttributes(true); > > + search_attributes.put(new BasicAttribute(os_id_field, > > s_netid)); > > + > > + String[] v_result_atts = {os_email_field, > > os_givenname_field, os_surname_field, os_phone_field}; > > + > > + olog.debug( "Searching LDAP for " + os_id_field + "=" + > > s_netid > > + + " under " + os_search_context > > + ); > > + > > + NamingEnumeration answer = ctx.search(os_search_context, > > + "(" + os_id_field + > > "=" + s_netid + ")", > > + new SearchControls( > > SearchControls.SUBTREE_SCOPE, > > + > > 1, 20000, > > + > > v_result_atts, > > + > > false, false > > + > > ) > > + ); > > + if( ! answer.hasMore()) { > > + olog.info( "Able to bind as " + s_netid + ", but > > unable to find LDAP record" ); > > + return null; > > + } > > + // look up attributes > > + String ldapEmail = null; > > + String ldapGivenName = null; > > + String ldapSurname = null; > > + String ldapPhone = null; > > + SearchResult sr = (SearchResult)answer.next(); > > + Attributes atts = sr.getAttributes(); > > + Attribute att; > > + > > + if (v_result_atts[0]!=null) { > > + att = atts.get(v_result_atts[0]); > > + if (att != null) ldapEmail = (String)att.get(); > > + } > > + > > + if (v_result_atts[1]!=null) { > > + att = atts.get(v_result_atts[1]); > > + if (att != null) { > > + ldapGivenName = (String)att.get(); > > + } > > + } > > + > > + if (v_result_atts[2]!=null) { > > + att = atts.get(v_result_atts[2]); > > + if (att != null) { > > + ldapSurname = (String)att.get(); > > + } > > + } > > + > > + if (v_result_atts[3]!=null) { > > + att = atts.get(v_result_atts[3]); > > + if (att != null) { > > + ldapPhone = (String)att.get(); > > + } > > + } > > + return new SimpleDataFromLDAP( ldapEmail, ldapGivenName, > > ldapSurname, ldapPhone, s_netid ); > > + } finally { > > + // Close the context when we're done > > + try { > > + if (ctx != null) { > > + ctx.close(); > > + } > > + } catch (NamingException e) { } > > + } > > + // Unreachable > > + } > > +} > > Index: src/main/java/org/dspace/authenticate/SimpleDataFromLDAP.java > > =================================================================== > > --- > > src/main/java/org/dspace/authenticate/SimpleDataFromLDAP.java (revision > > 0) > > +++ > > src/main/java/org/dspace/authenticate/SimpleDataFromLDAP.java (revision > > 0) > > @@ -0,0 +1,48 @@ > > +package org.dspace.authenticate; > > + > > + > > +/** > > + * Simple implementation of DataFromLDAP > > + */ > > +public class SimpleDataFromLDAP implements DataFromLDAP { > > + /** > > + * Constructor injects all the property values > > + */ > > + public SimpleDataFromLDAP ( String s_email, > > + String s_given_name, > > + String s_surname, > > + String s_phone, > > + String s_netid > > + ) { > > + os_email = s_email; > > + os_given_name = s_given_name; > > + os_surname = s_surname; > > + os_phone = s_phone; > > + os_netid = s_netid; > > + } > > + > > + private final String os_email; > > + public String getEmail () { > > + return os_email; > > + } > > + > > + private final String os_given_name; > > + public String getGivenName () { > > + return os_given_name; > > + } > > + > > + private final String os_surname; > > + public String getSurname() { > > + return os_surname; > > + } > > + > > + private final String os_phone; > > + public String getPhone () { > > + return os_phone; > > + } > > + > > + private final String os_netid; > > + public String getNetId () { > > + return os_netid; > > + } > > +} > > Index: src/main/java/org/dspace/authenticate/SpeakerToLDAP.java > > =================================================================== > > --- > > src/main/java/org/dspace/authenticate/SpeakerToLDAP.java (revision > > 0) > > +++ > > src/main/java/org/dspace/authenticate/SpeakerToLDAP.java (revision > > 0) > > @@ -0,0 +1,20 @@ > > +package org.dspace.authenticate; > > + > > +import javax.naming.NamingException; > > + > > +/** > > + * Interface for LDAP interaction handler > > + */ > > +public interface SpeakerToLDAP { > > + /** > > + * Authenticate the given user with LDAP, > > + * and get some data about him/her from the directory. > > + * > > + * @param s_netid cn of the user to authenticate > > + * @param s_password > > + * @return user info > > + */ > > + public DataFromLDAP ldapAuthenticate( String s_netid, > > + String s_password > > + ) throws NamingException; > > +} > > Index: src/main/java/org/dspace/authenticate/DataFromLDAP.java > > =================================================================== > > --- > > src/main/java/org/dspace/authenticate/DataFromLDAP.java (revision > > 0) > > +++ > > src/main/java/org/dspace/authenticate/DataFromLDAP.java (revision > > 0) > > @@ -0,0 +1,15 @@ > > +package org.dspace.authenticate; > > + > > + > > +/** > > + * POJO data bucket interface for user-data obtained during > > + * LDAP authentication > > + */ > > +public interface DataFromLDAP { > > + public String getEmail (); > > + public String getGivenName (); > > + public String getSurname(); > > + public String getPhone (); > > + /** LDAP common name (cn) for the user */ > > + public String getNetId (); > > +} > > > > > > > > -- This message is automatically generated by JIRA. - If you think it was sent incorrectly contact one of the administrators: http://jira.dspace.org/jira/secure/Administrators.jspa - For more information on JIRA, see: http://www.atlassian.com/software/jira ------------------------------------------------------------------------------ Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day trial. Simplify your report design, integration and deployment - and focus on what you do best, core application coding. Discover what's new with Crystal Reports now. http://p.sf.net/sfu/bobj-july _______________________________________________ Dspace-devel mailing list Dspace-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/dspace-devel