Today It's very common in most of the companies to have Microsoft Active Directory and Lotus Notes implementation together. We also use Active Directory and Lotus Notes side by side to validate Lotus Notes and SharePoint applications. Recently I've got a requirement to query Active Directory based on users profile which resides in our Lotus Notes view. I've implemented two sets of code one using Domino Java and jndi and other using Lotus Script. I've written Lotus script to those who are good in Lotus scripting and willing to perform such kind of cross implementation.By seeing the code you may realize how simple is to query Active directory from Domino using Lotus Scripting.To see the Lotus Script code , you may need to wait until it get published in Search Domino since it's already in process.So let's talk about Domino Java+JNDI.
In order to implement this code , You must need to know your Active Directory server name ( or IP address ) and make sure the port number where server is listening.
This code can be further extended to synchronized Lotus Notes address book contents in Active Directory or vice versa . Even it can be used to build Lotus Notes application which can use Active Directory for authentication.
To accomplish this, I'm using JNDI ( The Java Naming and Directory Interface ) which is an API specified in Java technology that provides naming and directory functionality to applications written in the Java programming language. It is designed especially for the Java platform using Java's object model. Using JNDI, applications based on Java technology can store and retrieve named Java objects of any type. In addition, JNDI provides methods for performing standard directory operations, such as associating attributes with objects and searching for objects using their attributes.
To start with the code ,
Step one: Include JNDI API package in your domino Java agent,
import javax.naming.*; |
Step two:
JNDI applications need a way to communicate various preferences and information that define the environment in which naming and directory services are accessed.The following code creates an environment consisting of two security-related properties and creates an initial context using that environment.
Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); //Replace with actual server name and port number env.put(Context.PROVIDER_URL, "ldap://serverName:389"); env.put(Context.SECURITY_PRINCIPAL, "CN=Rishi Sahi/OU=Development/O=Home"); env.put(Context.SECURITY_CREDENTIALS, "Password goes here"); DirContext ctx = new InitialDirContext(env); |
Step 3: Build a search scope , You need to define Active directory attributes which are going to be searched,
String[] attrIDs = {"cn","uid"}; SearchControls ctls = new SearchControls(); ctls.setReturningAttributes(attrIDs); ctls.setSearchScope(SearchControls.SUBTREE_SCOPE); |
In above code , SearchControls class encapsulates factors that determine scope of search and what gets returned as a result of the search.Next,setReturningAttributes() method specifies the attributes that will be returned as part of the search and setSearchScope() to SUBTREE_SCOPE to search the entire subtree rooted at the named object.
Step 4: Using search method of DirContext.It searches in a single context for objects that contain a specified set of attributes, and retrieves selected attributes. Note that my first argument is blank which make it search in entire scope, you can even define specific root.At the end make sure your results stored in NamingEnumeration type object.
String filter = "cn="+ searchUser; NamingEnumeration answer = ctx.search("", filter,ctls); |
Step 5: In the last step only you need to loop through your search results and retrieve attributes value.
while (answer.hasMore()) { SearchResult sr = (SearchResult)answer.next(); System.out.println("<<" + sr.getName()+">>"); Attributes attrs = sr.getAttributes(); System.out.println(attrs.get("cn").get()); isFound="1"; } |
Here is the complete code,
import javax.naming.*; import javax.naming.directory.*; import java.util.*; public class LDAPQuery { public static void ldapconnect(){ String searchUser="Rishi Sahi"; String isFound="0"; try { Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, "ldap://serverName:389"); //Replace with actual server name and port number env.put(Context.SECURITY_PRINCIPAL, "CN=Rishi Sahi/OU=Development/O=Home"); env.put(Context.SECURITY_CREDENTIALS, "Password goes here"); // Create initial context DirContext ctx = new InitialDirContext(env); // Specify the ids of the attributes to return String[] attrIDs = {"cn","uid"}; SearchControls ctls = new SearchControls(); ctls.setReturningAttributes(attrIDs); ctls.setSearchScope(SearchControls.SUBTREE_SCOPE); String filter = "cn="+ searchUser; // Search for objects that have those matching attributes NamingEnumeration answer = ctx.search("", filter,ctls); try { while (answer.hasMore()) { SearchResult sr = (SearchResult)answer.next(); System.out.println("<<" + sr.getName()+">>"); Attributes attrs = sr.getAttributes(); System.out.println(attrs.get("cn").get()); isFound="1"; } if ( isFound=="1") { System.out.println("User found in Active Directory!"); } else { System.out.println("Opps ! User not found in Active Directory!"); } answer.close(); }catch(PartialResultException e) { e.printStackTrace(); } // Close the context when we're done ctx.close(); } catch (Exception e) { e.printStackTrace(); } } public LDAPQuery() { // Don't think I'm doing anything here } } |
To call this routine,
import lotus.domino.*; public class JavaAgent extends AgentBase { public void NotesMain() { try { Session session = getSession(); AgentContext agentContext = session.getAgentContext(); LDAPQuery objQuery = new LDAPQuery(); objQuery.ldapconnect(); } catch(Exception e) {e.printStackTrace();} } } |
Reference : Java Naming and Directory Interface
So thought of the day
"I love Lotus Notes because I don't see anything which is not possible in Domino."
March 9, 2011 at 3:43 PM
Thanks for this Rishi, I have searched high and low and this is one of the most useful resources I have found.
Do you have any further hints about how to synchronise directories -0 I am not worried about passwords but I would like to extract all of the user names and emails from AD into a Notes database
Thanks, Sean
March 9, 2011 at 3:44 PM
p.s. LS would be preferable over Java but either would do ( I need to get better at Java in any case ! )
June 1, 2011 at 4:22 AM
Dear Rishi,
great code... Like sean said, it would be perfect if you also could post the code to save the persons from the AD into a Notes database
June 28, 2011 at 2:08 PM
Here is the Search Domino URL http://searchdomino.techtarget.com/tip/Search-Microsoft-Active-Directory-with-LotusScript