Autenticação e obtenção de dados via LDAP
02/setembro/2008 - Java, Tutoriais
Olá!
O LDAP (Lightweight Directory Access Protocol) é um protocolo de padrão aberto e multiplataforma muito usado em empresas nos serviços de autenticação e autorização a sistemas operacionais e aplicativos. Existem vários softwares que implementam esse protocolo, o OpenLDAP é um exemplo open source e o Windows Server 2003 Active Directory é um exemplo pago.
Podemos imaginar um servidor LDAP como um banco de dados, mas um banco de dados que não tem SQL, transação, commit e etc. e que os dados são organizados na forma de árvore (igual a árvore genealógica ou a árvore de diretórios que você tem no seu computador) dessa forma os dados podem ser organizados e agrupados mais facilmente.
As informações só podem ser armazenadas de forma não-normalizada, ou seja os dados de um item é um único registro. Exemplo: Para armazenar os dados de um usuário [nome, email e departamento] em um banco de dados relacional com certeza você criaria um cadastro de departamentos e amarraria o usuário com o ID do departamento, usando LDAP isso não é possível, todos esses dados ficarão em uma única “tabela“. Por isso eu usei o termo não-normalizada no início do parágrafo.
Um dos motivos mais comuns para implantar um servidor LDAP é para o login único para todos os aplicativos, facilitando a vida dos usuários que não precisam mais decorar uma senha para acessar cada aplicação. Esse login unificado ou único também é conhecido como Single SignOn
Nesse link você pode aprender mais sobre LDAP.
Abaixo veremos como acessar um servidor LDAP para buscar algumas informações de um usuário, o exemplo serve para validar a senha e trazer dados do servidor, mas não serve para apagar um registro ou atualizar um registro.
Classe TesteLDAP – Essa classe verifica se o usuário e a senha estão corretos, se estiverem exibe os dados retornados
package br.com.furutani.ldap.cliente; import javax.naming.NamingEnumeration; import javax.naming.directory.Attribute; import javax.naming.directory.Attributes; import javax.naming.directory.BasicAttribute; import javax.naming.directory.BasicAttributes; import javax.naming.directory.DirContext; import javax.naming.directory.SearchResult; import br.com.furutani.ldap.servicelocator.LDAPParametrosConfig; import br.com.furutani.ldap.servicelocator.LDAPServiceLocator; /** * Classe de teste que efetua um busca simples em um repositório LDAP * */ public class TesteLDAP { public static void main(String[] args) { // //////////////////// // Inicialmente há apenas esse usuario String login = "desenvolvedor"; String senha = "desenv"; // /////////// DirContext ctx = LDAPServiceLocator.getInstance().getContext(); Attributes matchAttrs = new BasicAttributes(false); // Array de atributos que deseja retornar do LDAP String[] atributosRetorno = new String[] { "mail", "cn" , "userPassword"}; // Parametros de busca matchAttrs.put(new BasicAttribute("uid", login)); matchAttrs.put(new BasicAttribute("userPassword", senha)); System.out.println("Buscando..."); try { // Efetua a busca NamingEnumeration resultado = ctx.search( LDAPParametrosConfig.SEARCHBASE, matchAttrs, atributosRetorno); // Exibindo o resultado, se houver while (resultado.hasMore()) { SearchResult sr = (SearchResult) resultado.next(); // Obtem os atributos Attributes atributos = sr.getAttributes(); for (NamingEnumeration todosAtributos = atributos.getAll(); todosAtributos .hasMore();) { Attribute attrib = (Attribute) todosAtributos.next(); String nomeAtributo = attrib.getID(); System.out.println("Atributo:" + nomeAtributo); // Exibe todos os valores do atributo for (NamingEnumeration e = attrib.getAll(); e.hasMore();) { System.out.println("\tvalor:" + e.next()); } } } } catch (Exception e) { e.printStackTrace(); } System.out.println("Busca finalizada."); } }
Classe LDAPServiceLocator – Localiza o servidor LDAP
package br.com.furutani.ldap.servicelocator; import java.util.Hashtable; import javax.naming.Context; import javax.naming.NamingException; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; /** * Classe responsavel por localizar um contexto de diretório LDAP */ public class LDAPServiceLocator { protected static LDAPServiceLocator instance; private LDAPServiceLocator() { super(); } /** * Obtem a mesma instancia de LDAPServiceLocator para todas as chamadas * (Classe singleton) * * @return um objeto LDAPServiceLocator */ public static LDAPServiceLocator getInstance() { if (instance == null) { instance = new LDAPServiceLocator(); } return instance; } public DirContext getContext() { Hashtable env = new Hashtable(2); // Especifica a fabrica de INITIAL CONTEXT env.put(Context.INITIAL_CONTEXT_FACTORY, LDAPParametrosConfig.INITIAL_CTX); // Especifica o IP/Nome e a porta do servidor LDAP env.put(Context.PROVIDER_URL, LDAPParametrosConfig.SERVIDOR); // As linhas abaixo são usadas quando o servidor LDAP não permite busca como anonymous //env.put(Context.SECURITY_PRINCIPAL, LDAPParametrosConfig.ADMIN_DN ); //env.put(Context.SECURITY_CREDENTIALS, LDAPParametrosConfig.ADMIN_PW ); DirContext ctx = null; try { // Obtem um Initial Context ctx = new InitialDirContext(env); } catch (NamingException e) { System.out.println("Não foi possivel obter um contexto LDAP"); e.printStackTrace(); } return ctx; } }
Classe LDAPParametrosConfig – Possuí constantes de configuração.
package br.com.furutani.ldap.servicelocator; /** * Paramêtros de configuração do LDAP * */ public class LDAPParametrosConfig { /* * Implementação do Initial context para LDAP */ public static final String INITIAL_CTX = "com.sun.jndi.ldap.LdapCtxFactory"; /* * Servidor LDAP */ public static final String SERVIDOR = "ldap://172.31.1.165:389"; /* * Base de busca */ public static final String SEARCHBASE = "ou=users, dc=furutani, dc=com, dc=br"; /* * Nome do usuário do admin */ public static final String ADMIN_DN = "dc=furutani, dc=com, dc=br"; /* * Senha */ public static final String ADMIN_PW = "123456"; /* * “top level” do diretório (base DN) */ public static final String BASE_DN = "dc=furutani, dc=com, dc=br"; }
Espero ter ajudado.
Até mais,
Roberto