18 February, 2012

ADF Integration With LDAP

I received last week in my work new requirement to make signing in application single sign on(sso) through active directory.
So I have a lot of solution
1- Use ADF Security and integrate with active directory LDAP from weblogic server
     This solution is declarative but customization is hard

2- Use custom java code to integrate with LDAP directly.
     This solution is good but what if I change UI development by another tool? I will redevelop again in new   framework
3- Create database package to integrate with LDAP
     I prefer this solution as I use DB to integrate with LDAP and it is unit of later maintenance and applicable for other application.


I will illustrate the last two solution

Use Custom Java Code to Integrate with LDAP
I create class for this purpose for test as below
We need some properites of LDAP
1-host name or IP of LDAP Server and port
       protected static String MY_HOST = "ldap://10.32.209.230:389";
2-Search base in LDAP
       protected static String MY_SEARCHBASE = "DC=MCIT,DC=LOCAL";
3- User in LDAP to connect by it in LDAP
       protected static String MGR_DN = "crmtest";
4-password of user which we connect by it.
       protected static String MGR_PW = "mcit@****";

We should enter search criteria to LDAP, In our example we search about use in LDAP, so I used below filter
    protected static String MY_FILTER = "sAMAccountName=mmahmoud";
as in previous example mmahmoud is user id which  I search about it in LDAP

You can run below class and see the results.


   package view;  
   
   import java.util.Hashtable;  
   import javax.naming.*;  
   import javax.naming.directory.*;  
   public class LdapTest {  
     protected static String INITCTX = "com.sun.jndi.ldap.LdapCtxFactory";  
     protected static String MY_HOST = "ldap://10.32.209.230:389";  
     protected static String MY_SEARCHBASE = "DC=MCIT,DC=LOCAL";  
     protected static String MY_FILTER = "sAMAccountName=mmahmoud";  
     protected static String MGR_DN = "crmtest";  
     protected static String MGR_PW = "mcit@****";  
     public static void main(String[] args) {  
       try {  
         Hashtable params = new Hashtable();    
         params.put(Context.INITIAL_CONTEXT_FACTORY, INITCTX);  
         params.put(Context.PROVIDER_URL, MY_HOST);  
         params.put(Context.SECURITY_AUTHENTICATION, "simple");  
         params.put(Context.SECURITY_PRINCIPAL, MGR_DN);  
         params.put(Context.SECURITY_CREDENTIALS, MGR_PW);  
   
         DirContext ctx = new InitialDirContext(params);  
   
         SearchControls constraints = new SearchControls();  
   
         constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);  
   
         NamingEnumeration results = ctx.search(MY_SEARCHBASE, MY_FILTER, constraints);  
   
         if (results != null && results.hasMore()) {  
           SearchResult sr = (SearchResult)results.next();  
           String dn = sr.getName();  
           System.out.println("Desc name is " + dn);  
           Attributes attrs = sr.getAttributes();  
           System.out.println(attrs.get("sAMAccountName"));  
         } else {  
           System.out.println("Not exist User");  
         }  
       } catch (AuthenticationException e) {  
         System.out.println("You aren't authenticated on LDAP");  
       } catch (PartialResultException e) {  
         System.out.println(MY_FILTER + " Not exists in LDAP");  
       } catch (NamingException e) {  
         e.printStackTrace();  
       }  
     }  
   }  
Create database package to integrate with LDAP
I used predefined package developed by oracle DBMS_LDAP to integrate with LDAP through DB
I created my custom package as below ldap_integration

CREATE OR REPLACE PACKAGE  ldap_integration
IS
   PROCEDURE init (p_ldap_host    VARCHAR2,
                   p_ldap_port    NUMBER,
                   p_ldap_user    VARCHAR2,
                   p_ldap_pwd     VARCHAR2,
                   p_ldap_base    VARCHAR2);

   FUNCTION search_user (p_user IN VARCHAR2, p_pwd IN VARCHAR2 DEFAULT ' ')
      RETURN VARCHAR2;
END ldap_integration;
/

CREATE OR REPLACE PACKAGE BODY  ldap_integration
IS
   -- globale variables --
   GC$ldap_host   VARCHAR2 (256) ;
   GC$ldap_port   VARCHAR2 (256) ;
   GC$ldap_user   VARCHAR2 (256) ;
   GC$ldap_pwd    VARCHAR2 (256);
   GC$ldap_base   VARCHAR2 (256);

   PROCEDURE init (p_ldap_host    VARCHAR2,
                   p_ldap_port    NUMBER,
                   p_ldap_user    VARCHAR2,
                   p_ldap_pwd     VARCHAR2,
                   p_ldap_base    VARCHAR2)
   IS
   BEGIN
      GC$ldap_host := p_ldap_host;
      GC$ldap_port := p_ldap_port;
      GC$ldap_user := p_ldap_user;
      GC$ldap_pwd := p_ldap_pwd;
      GC$ldap_base := p_ldap_base;
   END init;

   FUNCTION search_user (p_user IN VARCHAR2, p_pwd IN VARCHAR2 DEFAULT ' ')
      RETURN VARCHAR2
   IS
      l_retval      PLS_INTEGER;
      l_session     DBMS_LDAP.session;
      l_attrs       DBMS_LDAP.string_collection;
      l_message     DBMS_LDAP.MESSAGE;

      l_ret_value   VARCHAR2 (500);
   BEGIN
      DBMS_LDAP.USE_EXCEPTION := TRUE;
      -- Connect to the LDAP server.
      l_session :=
         DBMS_LDAP.init (hostname => GC$ldap_host, portnum => GC$ldap_port);

      l_retval :=
         DBMS_LDAP.
         simple_bind_s (ld       => l_session,
                        dn       => GC$ldap_user,
                        passwd   => GC$ldap_pwd);


      -- Get all attributes
      l_attrs (1) := '*';                           -- retrieve all attributes
      l_retval :=
         DBMS_LDAP.search_s (ld         => l_session,
                             base       => GC$ldap_base,
                             scope      => DBMS_LDAP.SCOPE_SUBTREE,
                             filter     => 'sAMAccountName=' || p_user,
                             attrs      => l_attrs,
                             attronly   => 0,
                             res        => l_message);

      IF DBMS_LDAP.count_entries (ld => l_session, msg => l_message) > 0
      THEN
         l_ret_value := 'OK';
      ELSE
         l_ret_value := 'FALSE';
      END IF;

      -- Disconnect from the LDAP server.
      l_retval := DBMS_LDAP.unbind_s (ld => l_session);

      RETURN l_ret_value;
   EXCEPTION
      WHEN OTHERS
      THEN
         DBMS_OUTPUT.
         put_line (' sql error  : ' || SQLCODE || ' sql msg : ' || SQLERRM);

         IF l_session IS NOT NULL
         THEN
            l_retval := DBMS_LDAP.unbind_s (ld => l_session);
         END IF;

         RETURN ' sql error  : ' || SQLCODE || ' sql msg : ' || SQLERRM;
   END search_user;
END ldap_integration;
/

After creating previous package you can call it as below script
you must assign that variables to procedure INTEGRATION.INIT
1-LDAP_Host
2-LDAP Port
3-LDAP user name
4-LDAP user password
5-LDAP Base( Which base we use to search about entered user)

Then pass search user id to function LDAP_INTEGRATION.search_user that will return "OK" if user exists in LDAP otherwise It will return "FALSE".

DECLARE
   P_LDAP_HOST   VARCHAR2 (512);
   P_LDAP_PORT   NUMBER;
   P_LDAP_USER   VARCHAR2 (512);
   P_LDAP_PWD    VARCHAR2 (512);
   P_LDAP_BASE   VARCHAR2 (512);
   P_userid      VARCHAR2 (200);
BEGIN
   P_LDAP_HOST := '10.32.209.230';
   P_LDAP_PORT := 389;
   P_LDAP_USER := 'crmtest';
   P_LDAP_PWD := 'mcit@****';
   P_LDAP_BASE := 'DC=MCIT,DC=LOCAL';
   P_userid := 'mmahmoud';

   MCIT_CMS.LDAP_INTEGRATION.INIT (P_LDAP_HOST,
                                   P_LDAP_PORT,
                                   P_LDAP_USER,
                                   P_LDAP_PWD,
                                   P_LDAP_BASE);
   DBMS_OUTPUT.put_line (MCIT_CMS.LDAP_INTEGRATION.search_user (P_userid));
END;

Because I haven't a lot of time, I wrote this article quickly and briefly.
If you have any query, don't hesitate to contact me.

Thanks
Mahmoud A. El-Sayed

2 comments:

  1. LDAP Definition
    The primary access protocol for Active Directory. LDAP is an industry-standard protocol, established by the Internet Engineering Task Force (IETF), that allows users to query and update information in a directory service. Active Directory supports both LDAP version 2 and LDAP version 3.

    ReplyDelete
  2. Nice post. Sometime back I have also shared my experience on using Spring Security for LDAP authentication in Active directory on Java application. let me know how do you find it.

    ReplyDelete

How to Pass Parameters to ActionListener in ADF

In some cases, it is required to pass a value to ActionListener of ADF Button. The method that can be invoked by actionListeners has only...