[ 
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

Reply via email to