Manipulating an LDAP Server using Java

Bojitha Piyathilake
5 min readApr 9, 2022
Source: https://freebiesupply.com/logos/java-logo/ and https://en.wikipedia.org/wiki/Apache_Directory

In this article I’ll show you how to connect a Java application to an LDAP server and perform your typical operations from fetching users, searching for a user, inserting and deleting users.

In my previous article I’ve written about setting up an LDAP server on Apache Directory Studio. So if you don’t know how to do that, I’d suggest you check it out real quick.

It is not required to read that blog to understand this one, but if you feel like you’re stuck on something then it could help. Alright no more beating around the bush, lets just jump right into it.

1. The Connection

public void newConnection() {
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:10389"); //Address of the LDAP server
env.put(Context.SECURITY_AUTHENTICATION, "simple"); //Authentication mechanism
env.put(Context.SECURITY_PRINCIPAL, "uid=admin,ou=system"); //credentials - admin's DN
env.put(Context.SECURITY_CREDENTIALS, "secret"); //credentials - password (it is secret by default)
try {
connection = new InitialDirContext(env);
System.out.println("Connection established. Connection Details:" + connection);
System.out.println(connection.getEnvironment());
} catch (AuthenticationNotSupportedException ex) {
System.out.println("The authentication is not supported by the server");
} catch (AuthenticationException ex) {
System.out.println("incorrect password or username");
} catch (NamingException ex) {
System.out.println("error when trying to create the context");
}
}

2. Adding a New User

public void addUser() {    Attributes attributes = new BasicAttributes();
Attribute attribute = new BasicAttribute("objectClass");
//adding values for objectClass attribute

attribute.add("inetOrgPerson");
attribute.add("person");
attribute.add("organizationalPerson");
attribute.add("top");
attributes.put(attribute);
//adding other attribute details

attributes.put("sn", "Jaeger");
attributes.put("cn", "Eren Jaeger");
attributes.put("givenName", "Eren Jaeger" );
attributes.put("uid", "Eren");
attributes.put("userPassword", "password");
attributes.put("mail", "erenye@hotmail.com");
try {
//add the path where the object needs to be created (uid vs cn) and the attributes of the object to be added.
connection.createSubcontext("uid=Erenye,ou=users,ou=system", attributes);
System.out.println("User Added Successfully");
} catch (NamingException e) {
System.out.println("error when trying to create the context");
}
}

If you’ve read my first article on LDAP, this code should be easier to understand. Very simply, we first add the object classes relevant to this entry, then we set the attributes. Then we create the entry by specifying the dn.

I personally needed to add thousands of users to the server to perform some tests. This can be done by wrapping the add user code with a loop.

public void addUsers() {    for (int x = 0; x < 1000; x++) {
Attributes attributes = new BasicAttributes();
Attribute attribute = new BasicAttribute("objectClass");
attribute.add("inetOrgPerson");
attribute.add("person");
attribute.add("organizationalPerson");
attribute.add("top");
attributes.put(attribute);
attributes.put("sn", "Tepes_" + x);
attributes.put("cn", "Alucard Tepes_" + x);
attributes.put("givenName", "Alucard Tepes_" + x);
attributes.put("uid", "Alucard_" + x);
attributes.put("userPassword", "password");
attributes.put("mail", "alucard_" + x + "@gmail.com");
try {
connection.createSubcontext("uid=Alucard_" + x + ",ou=users,ou=system", attributes);
System.out.println("User Added Successfully");
} catch (NamingException e) {
System.out.println("error when trying to create the context");
}
}
}

Do note that even when you add over 1000 users to Apache Directory Studio, the GUI will only display up to 1000, but all the entries will be available in the server, even if they’re not shown.

3. Fetch All Users

public void getAllUsers() throws NamingException {
String searchFilter = "(objectClass=Person)";
String[] requiredAttributes = {"sn", "cn"};
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
controls.setReturningAttributes(requiredAttributes);
NamingEnumeration users = connection.search("ou=users, ou=system", searchFilter, controls); SearchResult result = null; while (users.hasMore()) {
result = (SearchResult) users.next();
Attributes attr = result.getAttributes();
System.out.println(attr.get("cn") + "," + attr.get("sn"));
}
}

In my previous blog, I mentioned that every single entry should have a particular objectClass. In the searchFilter we specify that the “(objectClass=Person)”. Every user entry will have the Person class, therefore this will fetch all users from the database. We could even specify that “(objectClass=*)” as we are searching in “ou=users, ou=system” branch.

In a similar fashion, we could change the searchFilter to search for a single user.

4. Search for a User

public void searchUser(String uid) throws NamingException {
String searchFilter = "(&(objectClass=inetOrgPerson)(uid=" + uid + "))";
String[] requiredAttributes = {"sn", "cn"};
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
controls.setReturningAttributes(requiredAttributes);

NamingEnumeration users = connection.search("ou=users, ou=system", searchFilter, controls);

SearchResult result = null;

while (users.hasMore()) {
result = (SearchResult) users.next();
Attributes attr = result.getAttributes();
System.out.println(attr.get("cn") + "," + attr.get("sn"));
}
}

Pass in the uid from where you call the method to search for a user with that uid. Other types of search filters are available in my previous blog.

5. Deleting a User

public void deleteUser(String uid) {
try {
connection.destroySubcontext("uid=" + uid + ",ou=users,ou=system");
System.out.println("User " + uid + " deleted successfully");
} catch (NamingException e) {
System.out.println("error when trying to create the context");
}
}

Pass in the uid of the user whom you wish to delete and try to destroy the subcontext.

6. Adding a User to a Group

The two main types of OUs, created by default, under the DIT are users and groups. You can think of a group as a set of users. In that vein, groups should have the objectClass of “groupOfUniqueUserNames” because that is essentially what a group is. For example, we can have a group of Administrators.

public void addUserToGroup(String username, String groupname) {
ModificationItem[] mods = new ModificationItem[1];
//uniqueMember - uid=username,ou=user,ou=system --> The attribute to be added to the group

Attribute attribute = new BasicAttribute("uniqueMember", "uid=" + username + ",ou=user,ou=system");
mods[0] = new ModificationItem(DirContext.ADD_ATTRIBUTE, attribute);
try {
//groupname is the group that needs to be modified.
connection.modifyAttributes("cn=" + groupname + ",ou=groups,ou=system", mods);
System.out.println(username + " Successfully added to " + groupname + " group");
} catch (NamingException e) {
System.out.println("error when trying to create the context");
}
}

Since we know we are adding a single user we can set the modification items to an array of 1.

A group is a groupOfUniqueUserNames and a user is a uniqueMember in a group. A user can be represented with their dn, which is the complete path to uniquely identify a resource, by describing its position in the DIT.

Very simply, what is happening here is that we are copying the dn of the user and adding it as a uniqueMember attribute under the group that we pass into the method.

And with that we reach the end of this blog. I hope this helps you figure out how to use interact with an LDAP server using Java. In this article I showed you how to easily add thousands of users to your LDAP server and fetch all users. If you try this out, you will notice that this causes a lot of stress on the server and will take a bunch of time. So in my next article, as a solution to this issue, I’ll show you how to perform offset pagination with an LDAP server using a Java application. See you there!

--

--

Bojitha Piyathilake

I am an undergraduate at the University of Moratuwa following a degree in Information Technology and Management.