Authenticating with LDAP Server in Enterprise Java Apps
Creating a new user with password is easy for application developers, but not so convenient for the users. Increasingly we have more passwords to remember than we should. It’s now a common practice to authenticate users with LDAP or ActiveDirectory. If a user changes her password in LDAP server, she doesn’t need to do anything in the app.
Required by a new server product, I just wrote a simple code to authenticate with a LDAP server. Because I didn’t have a LDAP server already installed, I installed the LDAP server and clients. To make it easier, I also install jXplorer which is a GUI front end for the LDAP server. Before jumping onto the product, it’s worthwhile to read a few pages on the LDAP itself from here.
Time to learn how to "Google" and manage your VMware and clouds in a fast and secure
HTML5 AppWhile installing the LDAP server is not hard, configuring it did take some time and efforts (checkout this blog). Luckily I found an online read-only LDAP server (see the code for the URL) for testing my Java program from this blog. Although I cannot add a new user, it’s good enough to verify the code.
Here is the running demo code on how to use the related APIs. The code actually does more than authentication – it can also retrieve some attributes from the record for the user. So far they are just mail and cn, but you can add more by yourselves.
The code is just for trying out the APIs, but it’s pretty easy to adapt it into your Java applications, for example, the Java servlet login filter.
package org.doublecloud.ldapapp; import java.util.Hashtable; import javax.naming.Context; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.directory.Attributes; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; public class MainApp { static String LDAP_SERVER_URL = "ldap://ldap.forumsys.com:389"; static String USER_CONTEXT = "dc=example,dc=com"; public static void main(String[] args) { verifyUser("riemann", "password"); verifyUser("gauss", "password"); } public static void verifyUser(String userName, String password) { DirContext ctx = null; try { // creating environment for initial context Hashtable<String, String> env = new Hashtable<String, String>(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, LDAP_SERVER_URL); env.put(Context.SECURITY_AUTHENTICATION, "simple"); env.put(Context.SECURITY_PRINCIPAL, "uid=" + userName + "," + USER_CONTEXT); env.put(Context.SECURITY_CREDENTIALS, password); // Create the initial context ctx = new InitialDirContext(env); System.out.println("Authenticated: " + (ctx != null)); // get more attributes about this user SearchControls scs = new SearchControls(); scs.setSearchScope(SearchControls.SUBTREE_SCOPE); String[] attrNames = { "mail", "cn" }; scs.setReturningAttributes(attrNames); NamingEnumeration nes = ctx.search(USER_CONTEXT, "uid=" + userName, scs); if(nes.hasMore()) { Attributes attrs = ((SearchResult) nes.next()).getAttributes(); System.out.println("mail: " + attrs.get("mail").get()); System.out.println("cn: " + attrs.get("cn").get()); } } catch (NamingException e) { e.printStackTrace(); } finally { if (ctx != null) try { ctx.close(); } catch (NamingException ex) {} } } } |
Thank you. Very useful.