Anyway, a central source for authentication credentials also helps with web applications on that network, because now we no longer need to worry about password management, or user registration. That can reduce the project schedule by a week or two, depending on how strict your organization's password and user registration requirements are.
So, how do we do it? Well, it is actually pretty simple. Like I said, AD is basically another version of LDAP, so in Java you can use the Java Naming and Directory Interface (JNDI). There are a bunch of LDAP classes in the javax.naming.ldap package that can help. And because the Java API is so robust, it gives you a ton of flexibility to customize your code as much as possible. At the same time, it can seem a bit intimidating. Sun has some pretty good information on their website about LDAP authentication, which can also be used for AD Authentication. Lets take a look at some code.
Hashtable env = null; DirContext ctx = null; boolean isAuthenticated = false; try { try { String loginId = "yourdomain\\avgwebgeek"; env = new Hashtable(); // hash table for your LDAP properties // set up the LDAP properties env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, "ldap://myadserver.mydomain.com:389"); // Set the authentication mechanism to be simple env.put(Context.SECURITY_AUTHENTICATION, "simple"); // login credentials env.put(Context.SECURITY_PRINCIPAL, loginId); env.put(Context.SECURITY_CREDENTIALS, password); // the following is helpful in debugging errors from the // AD server side of things //env.put("com.sun.jndi.ldap.trace.ber", System.err); // Create the initial directory context ctx = new InitialDirContext(env); isAuthenticated = true; } catch (AuthenticationException e) { // this exception is typically found with incorrect credentials e.printStackTrace(); } catch (NamingException e) { e.printStackTrace(); } } catch (Exception e) { e.printStackTrace(); } finally { try { ctx.close(); }catch (NamingException e) { e.printStackTrace(); } } if (isAuthenticated) { System.out.println("I am authenticated."); } else { System.out.println("I am not authenticated."); }
This is a very simple application. It does the job, however, it is not very secure. The problem is that I am setting the Context.SECURITY_AUTHENTICATION to "simple". What this means is that your password is being sent over the network through clear text. If someone is running a network sniffer, they can read your password from your IP packets. One way around this is to make sure that your LDAP connection is handled over SSL. In other words, use "ldaps://" with port 636, and not "ldap://" on port 389.
If your server is not setup to handle SSL, or you just want a little extra security, you can change the Context.SECURITY_AUTHENTICATION to "DIGEST-MD5". However, as I found out, AD treats this a little differently. The concept of using "yourdomain\\yourusername" needs to be reduced to just "yourusername". It has something to do with how AD 2003 sets up the HASH for the MD5. This method will use a Hashing algorithm to be verified with the server, that you indeed know your password.
So, that's it for AD authentication. Like I said, the Java API can let you do a lot more. You can set up controls to do searches, find specific user information, and find groups assigned to users. AD groups can be used to help with the Authorization portion of your apps. Take a look at the javax.naming.ldap API, there is a lot there, but it isn't too hard to follow.