Login java con Active Directory

En esta entrada vamos a revisar unas clases que nos permitiran validar los datos de conexión contra un active directory. La aplicación funciona siempre y cuando se encuentre en la red a las cual pertenece dicho dominio.

La clase que vamos a emplear para que valide los datos será la siguiente:

public class ActiveDirectoryAuthentication {

    private static final String CONTEXT_FACTORY_CLASS = "com.sun.jndi.ldap.LdapCtxFactory";
    private String ldapServerUrls[];
    private int lastLdapUrlIndex;
    private final String domainName;

    public ActiveDirectoryAuthentication(String domainName) {
        this.domainName = domainName.toUpperCase();
        try {
            ldapServerUrls = nsLookup(domainName);
        } catch (Exception e) {
        }
        lastLdapUrlIndex = 0;
    }

    public boolean authenticate(String username, String password) throws LoginException {
        if (ldapServerUrls == null || ldapServerUrls.length == 0) {
            throw new AccountException("Unable to find ldap servers");
        }
        if (username == null || password == null || username.trim().length() == 0 || password.trim().length() == 0) {
            throw new FailedLoginException("Username or password is empty");
        }
        int retryCount = 0;
        int currentLdapUrlIndex = lastLdapUrlIndex;
        do {
            retryCount++;
            try {
                Hashtable<Object, Object> env = new Hashtable<Object, Object>();
                env.put(Context.INITIAL_CONTEXT_FACTORY, CONTEXT_FACTORY_CLASS);
                env.put(Context.PROVIDER_URL, ldapServerUrls[currentLdapUrlIndex]);
                env.put(Context.SECURITY_PRINCIPAL, username + "@" + domainName);
                env.put(Context.SECURITY_CREDENTIALS, password);
                DirContext ctx = new InitialDirContext(env);
                ctx.close();
                lastLdapUrlIndex = currentLdapUrlIndex;
                return true;
            } catch (CommunicationException exp) {
                // TODO you can replace with log4j or slf4j API
                exp.printStackTrace();
                // if the exception of type communication we can assume the AD
                // is not reachable hence retry can be attempted with next
                // available AD
                if (retryCount < ldapServerUrls.length) {
                    currentLdapUrlIndex++;
                    if (currentLdapUrlIndex == ldapServerUrls.length) {
                        currentLdapUrlIndex = 0;
                    }
                    continue;
                }
                return false;
            } catch (Throwable throwable) {
                throwable.printStackTrace();
                return false;
            }
        } while (true);
    }

    private static String[] nsLookup(String argDomain) throws Exception {
        try {
            Hashtable<Object, Object> env = new Hashtable<Object, Object>();
            env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.dns.DnsContextFactory");
            env.put("java.naming.provider.url", "dns:");
            DirContext ctx = new InitialDirContext(env);
            Attributes attributes = ctx
                    .getAttributes(String.format("_ldap._tcp.%s", argDomain), new String[]{"srv"});
            // try thrice to get the KDC servers before throwing error
            for (int i = 0; i < 3; i++) {
                Attribute a = attributes.get("srv");
                if (a != null) {
                    List<String> domainServers = new ArrayList<>();
                    NamingEnumeration<?> enumeration = a.getAll();
                    while (enumeration.hasMoreElements()) {
                        String srvAttr = (String) enumeration.next();
                        // the value are in space separated 0) priority 1)
                        // weight 2) port 3) server
                        String values[] = srvAttr.split(" ");
                        domainServers.add(String.format("ldap://%s:%s", values[3], values[2]));
                    }
                    String domainServersArray[] = new String[domainServers.size()];
                    domainServers.toArray(domainServersArray);
                    return domainServersArray;
                }
            }
            throw new Exception("Unable to find srv attribute for the domain " + argDomain);
        } catch (NamingException exp) {
            throw new Exception("Error while performing nslookup. Root Cause: " + exp.getMessage(), exp);
        }
    }
}

Comentarios

Entradas populares de este blog

Calculadora en Swing de NetBeans

1er Tutorial de NetBeans