It is very common for many applications to have to authenticate its users (or login). At the
It is very common for many applications to have to authenticate its users (or login). At the same time, these users’ information is often stored in servers. In this particular case, we’ll see how to authenticate a user – with its password – and how to get data from users or groups to a Lightweight Directory Access Protocol (LDAP) server with Java.
How to get connected?
First, one must know which libraries have to be imported, or if any of these libraries must be installed. To use the LDAP server, only the following libraries are needed:
import javax.naming.Context; import javax.naming.NamingException; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext;
To connect to the server, one must load into a Hashtable all the fields we want to send (URL for the connection, user credentials, authentication type, and others that may be necessary), for example:
public static DirContext connectToLDAP(String url, String user, String password) throws NamingException{ Hashtable<String, String> env = new Hashtable<String, String>(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, url); env.put(Context.SECURITY_AUTHENTICATION,"simple"); env.put(Context.SECURITY_PRINCIPAL, user); env.put(Context.SECURITY_CREDENTIALS,password); //Conseguimos contexto de conexion DirContext ctx = InitialDirContext(env); return ctx; }
In case of not being able to connect to the server with user credentials, an exception will appear (NamingException).
Once connected to the server, we can get the context that allows us to make inquiries, information, authenticate, etc. To log off, one must simply type:
public static void closeConnectionToLDAP(DirContext ctx) { try { ctx.close(); } catch (NamingException e) { // No se habia podido conectar, ya se habia cerrado la conexion, etc.. e.printStackTrace(); } }
Authenticating a user (with its password)
In order to do so, all one must do is log oneself in a similar manner to that discussed in the previous example, but indicating the corresponding username and password. Note that it is necessary to write the full path (for example, if the username is “john”, it is not enough to simply write as a user “john”), for example: “CN=nombre_usuario,OU=Unidad,DC=dominio”.
If you are able to get connected, you can obtain the context, and if you do not have the correct username or password, the same exception as before will appear:
public boolean correctLogin(username, password) { //El usuario ya viene con toda la ruta try { 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_URL); env.put(Context.SECURITY_AUTHENTICATION,"simple"); env.put(Context.SECURITY_PRINCIPAL, username); env.put(Context.SECURITY_CREDENTIALS,password); //Conseguimos contexto de conexion DirContext ctx = InitialDirContext(env); ctx.close(); return true; } catch (NamingException e) { return false; } }
Obtaining a user’s or group’s attributes
To do so, one must first get the connection context as indicated above (either as an administrator or common user, but it may depend on the LDAP server).
Then, we need to indicate how many and what are the names of the attributes we want (which could, potentially, be none, if we just want to check whether a user who meets the conditions exists), and the filtering conditions (which are always important although they might be random).
First, we include the following libraries:
import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult;
For example, we obtain the attributes “field1 ” and ” field2 ” of a given user:
public void search (String username) throws NamingException{ //Recordar que el username tiene que tener toda la ruta de OUs/DCs/CNs DirContext context = connectToLDAP(URL, ADMIN, PASS); SearchControls ctls = new SearchControls(); ctls. setReturningObjFlag (true); // Para que devuelva los elementos que buscamos String returning[] = new String[2]; returnings[0] = "field1"; returnings[1] = "fields2"; //Asignamos los atributos a devolver ctls.setReturningAttributes(returning); ctls.setSearchScope(SearchControls.OBJECT_SCOPE); String search = username; // Search es "en donde buscar" de los directorios del servidor String filter = "name=" + username; // filtro trivial NamingEnumeration answer = ctx.search(search,filter, ctls); SearchResult result = (SearchResult) answer.next(); // Sabemos que habra un solo resultado String field1 = result.getAttributes().get("field1").get().toString(); String field1 = result.getAttributes().get("field2").get().toString(); System.out.println(username + ": " + fields1 + ", " + fields2); }
The variants that can be sought are enormous, therefore, we propose a more general example of how to perform a search:
public void search (String search, String filter, String[] returningAtts) throws NamingException{ DirContext context = connectToLDAP(URL, ADMIN, PASS); SearchControls ctls = new SearchControls(); ctls. setReturningObjFlag (true); // Para que devuelva los elementos que buscamos //Asignamos los atributos a devolver ctls.setReturningAttributes(returningAtts); ctls.setSearchScope(SearchControls.OBJECT_SCOPE); NamingEnumeration answer = ctx.search(search,filter, ctls); while (answer.hasNext()){ SearchResult result = (SearchResult) answer.next(); HashMap map = new HashMap(); for (String returning : returningAtts){ map.put(returning, result.getAttributes().get("returning").get().toString()); } doSomething(map); } }
Example of use:
search("DC=dominio_general,OU=org", "userType=Admin", {"username", "mail"});
Conclusions
It is very easy to authenticate and inquire information from a LDAP server in Java, and the code can be relatively simple and easy to understand (although as the query becomes more complex, so does the code).
On the downside, we can see that it is necessary to indicate where we want the query to inquire the information (knowing the whole structure of LDAP), but more importantly, it must be given in the correct order; otherwise the query will fail.
Are you searching for the best technical solution for your company? Do not hesitate to Contact us for more information. ¡We will get back to you!