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
We need some properites of LDAP
1-host name or IP of LDAP Server and port
We should enter search criteria to LDAP, In our example we search about use in LDAP, so I used below filter
You can run below class and see the results.
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
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 belowWe 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 LDAPYou 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 DBI 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
LDAP Definition
ReplyDeleteThe 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.
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