Solved

How to query LDAP and authenticate users

Posted on 2004-10-27
961 Views
Last Modified: 2013-11-24
I dont have much experience in Java.
Need to write a java app to authenticate users coming into my web page by querying ldap.
I have a login.jsp that accepts username/password, need direction on writing all other classes to authenticate users and display authenticated users username on firstpage.html
Thank you!


0
Question by:makam_75
    38 Comments
     
    LVL 86

    Expert Comment

    by:CEHJ
    What container are you using?
    0
     
    LVL 86

    Expert Comment

    by:CEHJ
    0
     

    Author Comment

    by:makam_75
    SunOne is the webserver. I was looking for sample code.
    Thanks.
    0
     
    LVL 5

    Expert Comment

    by:JK2429
    0
     
    LVL 13

    Accepted Solution

    by:
    First u must have a Directory server like active Directory, or Sun One Directory Server or OpenLDAP (openldap is open source), u can download it from www.openldap.org

    then here is a sample authenticate function:

    import java.util.Hashtable;
    import java.util.Enumeration;

    import java.util.*;
    import java.io.*;
    import javax.naming.*;
    import javax.naming.directory.*;

      public boolean authenticateUser(String username, String password) throws NamingException
      {
        Hashtable env = new Hashtable(5, 0.75f);

        env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");

        /* Specify host and port to use for directory service */
        env.put(Context.PROVIDER_URL, "ldap://LDAP_SERVER:389");

        env.put(Context.SECURITY_AUTHENTICATION, Simple);
        env.put(Context.SECURITY_PRINCIPAL, "uid=" +username +", ou=users,o=myOrganization, dc=mydomain,dc=com");
        env.put(Context.SECURITY_CREDENTIALS, password);

        try
        {
            /* get a handle to an Initial DirContext */
            DirContext ctx = new InitialDirContext(env);

                //Authenticated
            return true;
        }
        catch (javax.naming.AuthenticationException ae)
        {
          //Authentication failure
            return false;
        }
        catch (NamingException e)
        {
          return false;
        }
      }
    0
     
    LVL 86

    Expert Comment

    by:CEHJ
    >>I was looking for sample code

    This kind of thing should in theory require little code since the functionality is provided declaratively. It will be more a question of putting together the right config files for your container
    0
     
    LVL 13

    Expert Comment

    by:petmagdy
    just a little correction to my code:

    this line:
      env.put(Context.SECURITY_AUTHENTICATION, Simple);

    is offcourse meant to be:

      env.put(Context.SECURITY_AUTHENTICATION, "simple");
    0
     
    LVL 86

    Expert Comment

    by:CEHJ
    >>then here is a sample authenticate function:

    That's not really right. All that context related stuff should have been set up before authentication is attempted. An authenticate function should really only get the context and do a lookup
    0
     
    LVL 13

    Expert Comment

    by:petmagdy
    CHEJ

    this is how to do LDAP programatic authentication, I meant to provide a sample not exact function implementation, althought this is code is right if the users are located at the orgainzation unit: ou=users,o=myOrganization, dc=mydomain,dc=com,

    I am not refering to the Decalarative or JAAS way
    0
     
    LVL 86

    Expert Comment

    by:CEHJ
    >>this is how to do LDAP programatic authentication

    Even then it's looking a bit iffy for the reasons i've given - the environment should already be there - even if it was done programmatically

    >>am not refering to the Decalarative or JAAS way

    The idea is to let the container do as much work as possible, declaratively. Such programmatic code that there is will simply input the credentials and receive the result
    0
     

    Author Comment

    by:makam_75
    Hello petmagdy.
    Not sure the need for setting up a directory server.
    I already have LDAP set up in my company. Eg. If I telnet to any m/c in the network, I am able to run an ldapsearch command. Does this mean the above code will compile as is?

    Or do you mean to say I need to have my own instance of directory server running on the host were I have my web page that authenticates users? Guess I am not clear on it because I do not have understanding of the whole picture.

    Like I mentioned before, I am new to this, so I will be using any code as is. I do have my organization unit as ou=users,o=myOrganization, dc=mydomain,dc=com. Please let me know if there are any other concerns.
    Thankyou!
    0
     
    LVL 86

    Expert Comment

    by:CEHJ
    You need to configure the app server to use the existing LDAP. See the container docs
    0
     
    LVL 13

    Expert Comment

    by:petmagdy
    CHEJ
    I am not in favorate of dwelling arround a point
    when refering to the programatic LDAP authenitcation the statment u say

    >> An authenticate function should really only get the context and do a lookup

    This statment is not accurate Authentication is not lookup on the user in LDAP, it is challenging the User/Password againist the Directory server this achieved by 2 ways:

    First way: lookup on the user object in the DS and if found use the DS irreversable encryption technique to decrypt the password and validate it againist the savied in database

    Second way: get an LDAP context if success then the user is authented as I provided in the sample code

    bye the way Active directory only accepts the second way
    0
     
    LVL 13

    Expert Comment

    by:petmagdy
    no I meant to use an existing available Directory server (LDAP server), so u provide the Host name of this server in the LDAP url (ldap://servername:389)

    But if the organization will not allow u to test on its running Production LDAP server u can easly make ur own instance on ur machine
    0
     
    LVL 86

    Expert Comment

    by:CEHJ
    >>This statment is not accurate Authentication is not lookup on the user in LDAP

    >>First way: lookup on the user object in the DS and if found ...

    ?

    makam_75, petmagdy's is a way of doing this programmatically although i'm not convinced it's the best way
    0
     
    LVL 13

    Expert Comment

    by:petmagdy
    CEHJ,

    I know Recently JAAS became the best way to implement J2EE application security, but as a first step for makam to understand the foundation of this is to concentrate on JNDI and LDAP concepts first that is better before going for more advanced techniques

    By the way not all cases the decalrative is the best, in one of the projects I was involved in, when users in a single ou reached more than 60K users declarative costs 4 minutes to authenticate the user while programatic did it in 3 seconds

    cheers ;)
    0
     

    Author Comment

    by:makam_75
    Hi all,
    I am not looking for the most correct solution for any generic app. I have a small and urgent requirement, and want to get to it in a most efficient time frame. As long as it works and no cons associated with the method, I am ok in hardcoding some data.  
    Petmagdy,
    I will have to find out the ldap server name (production and test) from our admin. Are there any other questions I should be asking? If you know a beginners guide for ldap, can youpass it on to me too.

    Appreciate everyones time and help here. Thank you.

    0
     
    LVL 86

    Expert Comment

    by:CEHJ
    If you're into getting something running quickly, use petmadgy's suggestion.

    >>As long as it works and no cons associated with the method

    I'll let petmadgy tell you about the pros and cons ;-)
    0
     
    LVL 13

    Expert Comment

    by:petmagdy
    do u have a user/password on this directory server?
    if no u need to get one for testing purposes, also u need to know for the users to be authenticated where r they on the Directory server hierarchy for example, their location on active directory maybe something like this:

    cn=users, dc=thedomain, dc=com

    if other may be look like this:

    ou=users, o=orgainizationName, dc=thedomain, dc=com

    and the heirarchy can be more complicated than that
    0
     
    LVL 13

    Expert Comment

    by:petmagdy
    No CHEJ, I am sure that u always has the best way ;)
    0
     

    Author Comment

    by:makam_75
    Thanks, I will try and implement this today. will let you know the status by mid day tomorrow. I hope you automatically get notification to updates to this thread.
    0
     
    LVL 86

    Expert Comment

    by:CEHJ
    We do ;-)
    0
     

    Author Comment

    by:makam_75
    OK I am getting much earlier.

    On command line, a command like this works for me
    ldapserach -h "directory.tw.com" -b "ou=people,o=tw.com" "uid=makam"
    (So I know that directory name and heirarchy structure are correct. )

    So, I tried to implement like this. I hardcoded the userid/password I use to login to our intranet(that they have set up using nsconfig) But get the message "false" which means I was not succesffuly authenticated.

    Could it be that the password is stored as encrypted, and the one I am passing is not and so they are not matching?

    public class myLDAPProg{
          public myLDAPProg() {
          }
          
          public static void main( String args[]) {
                queryLDAP q = new queryLDAP();
                try {
                            boolean value=q.doAuthenticate("myname","mypass");
                            System.out.println("val is"+ value);
                }
                catch(NamingException e) {}
          }
          
    }

          public class queryLDAP{
                public queryLDAP(){
                }
                
                public boolean doAuthenticate(String username, String password) throws NamingException
                  {
                      Hashtable env = new Hashtable(5, 0.75f);

                      env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");

                      /* Specify host and port to use for directory service */
                      env.put(Context.PROVIDER_URL, "ldap://directory.tw.com:389");

                      env.put(Context.SECURITY_AUTHENTICATION, "simple");
                      env.put(Context.SECURITY_PRINCIPAL, "uid=" +username +", ou=people,o=tw.com,");
                      env.put(Context.SECURITY_CREDENTIALS, password);

                      try
                      {
                            /* get a handle to an Initial DirContext */
                            DirContext ctx = new InitialDirContext(env);

                              //Authenticated
                            return true;
                      }
                      catch (javax.naming.AuthenticationException ae)
                      {
                        //Authentication failure
                         return false;
                      }
                      catch (NamingException e)
                      {
                        return false;
                      }
                  }
                 
          }

    0
     
    LVL 13

    Expert Comment

    by:petmagdy
    no u don't need to do thing about the password


    1- Please make sure that in ur class path u have the following jars:

    jndi.jar
    ldap.jar
    ldapbp.jar
    providerutil.jar

    also if still return false please put in the catch exceptions

    e.printStackTrace()
    0
     

    Author Comment

    by:makam_75
    If i did not have the jar files, it would not run, correct?

    Anyway , I run the program on command line. I could not locate these jar files under C:\j2sdk1.4.2_06\jre\lib

    Also, this does not compile
    catch(NamingException e) {
                      System.out.println(e.printStackTrace());
                }
    The error is The method println() in the type PrintStream is not applicable for the arguments (void)
    0
     
    LVL 86

    Expert Comment

    by:CEHJ
    >>I could not locate these jar files under C:\j2sdk1.4.2_06\jre\lib

    They won't be there. You need to install J2EE SDK too.

    >>
    catch(NamingException e) {
                   System.out.println(e.printStackTrace());
              }
    >>

    should be

    catch(NamingException e) {
        e.printStackTrace();
    }
    0
     
    LVL 86

    Expert Comment

    by:CEHJ
    >>You need to install J2EE SDK too.

    In fact they may not all be there either. petmagdy will probably know where they all are
    0
     

    Author Comment

    by:makam_75
    But I am getting a "false" as the output. So it was able to get hold of all jar files is my thinking...
    0
     

    Author Comment

    by:makam_75
    Thanks, I did  e.printStackTrace(); , but do not see any change in the output.
    My o/p is
    val isfalse

    0
     

    Author Comment

    by:makam_75
    Sorry, here is the exception.
    javax.naming.InvalidNameException: [LDAP: error code 34 - Invalid DN]
            at com.sun.jndi.ldap.LdapCtx.processReturnCode(Unknown Source)
            at com.sun.jndi.ldap.LdapCtx.processReturnCode(Unknown Source)
            at com.sun.jndi.ldap.LdapCtx.connect(Unknown Source)
            at com.sun.jndi.ldap.LdapCtx.<init>(Unknown Source)
            at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(Unknown Source)
            at javax.naming.spi.NamingManager.getInitialContext(Unknown Source)
            at javax.naming.InitialContext.getDefaultInitCtx(Unknown Source)
            at javax.naming.InitialContext.init(Unknown Source)
            at javax.naming.InitialContext.<init>(Unknown Source)
            at javax.naming.directory.InitialDirContext.<init>(Unknown Source)
            at com.synopsys.ldap.queryLDAP.doAuthenticate(queryLDAP.java:44)
            at com.synopsys.ldap.authenticateUser.main(authenticateUser.java:40)
    val isfalse

    I had'nt recreated the jar file before.
    0
     
    LVL 86

    Expert Comment

    by:CEHJ
    >>So it was able to get hold of all jar files is my thinking...

    Well if it now compiles and runs, then yes ;-)

    You'll have to check the directory / your credentials if you're getting an unexpected negative
    0
     

    Author Comment

    by:makam_75
    OK there was one extra comma, I removed it and it is working!
    Hurray!
    0
     
    LVL 86

    Expert Comment

    by:CEHJ
    Good ;-)
    0
     
    LVL 86

    Expert Comment

    by:CEHJ
    So my contribution to that was worth 0 points then makam_75?
    0
     
    LVL 13

    Expert Comment

    by:petmagdy
    LOOOLLLLL, MAKAM sorry I went to bed during the last comments, time zone difference :)
    I think MAKAM, it is time to get also idea about the declarative way of LDAP authentication, I sure CEHJ will help u great deal on that ;)
    0
     

    Author Comment

    by:makam_75
    CEHJ,
    I did value your comments very much!
    The reasoning behind my awarding points was I have taken the code from petmagdy "as is" and it is working as a complete solution to the question i listed. so i thought it will not be fair if i dont assign him the complete points.
    I appreciate your response. Thanks.

    0
     
    LVL 86

    Expert Comment

    by:CEHJ
    >>"as is" and it is working as a complete solution to the question i listed

    Err.. apart from the fact that you would not have been able to compile it without my help to the question containing the following:

    >>Also, this does not compile
    0
     

    Author Comment

    by:makam_75
    Sorry I overlooked that. I will remember to be more cautius while assigning points in future.
    0

    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone. Privacy Policy Terms of Use

    Featured Post

    Shellfire Box VPN + Lifetime Subscription

    The Shellfire Box easily connects all of your devices, even those that don't offer the possibility to establish a safe vpn connection. Access blocked content and surf safely, no matter where in the world you are located.

    Suggested Solutions

    If you have upgraded to Java2 update 10 on a Microsoft Windows client, you may have discovered that your Java application does not work as it did before.  For example, the colors of your Java2D graphic may be all wrong for no apparent reason. Aft…
    Introduction Java can be integrated with native programs using an interface called JNI(Java Native Interface). Native programs are programs which can directly run on the processor. JNI is simply a naming and calling convention so that the JVM (Java…
    Viewers learn about the third conditional statement “else if” and use it in an example program. Then additional information about conditional statements is provided, covering the topic thoroughly. Viewers learn about the third conditional statement …
    Viewers will learn one way to get user input in Java. Introduce the Scanner object: Declare the variable that stores the user input: An example prompting the user for input: Methods you need to invoke in order to properly get  user input:

    875 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    13 Experts available now in Live!

    Get 1:1 Help Now