.NET - Acessando o Active Directory
Antes de iniciar o artigo é bom rever alguns conceitos básicos como Active Directory, LDAP, domínio,etc. Vamos lá...
O Active Directory (AD) é uma implementação de serviço de diretório no protocolo LDAP (Lightweight Directory Access Protocol) que armazena informações sobre objetos em uma rede e disponibiliza essas informações a usuários e administradores desta rede. (Pense no AD como um banco de dados hierárquico orientado a objetos que representa todos os seus recursos de rede.)
O LDAP é um protocolo para atualizar e pesquisar diretórios rodando sobre TCP/IP e segue o modelo de árvore de nós, onde cada nó representa um conjunto de atributo com seus valores. O LDAP é uma alternativa ao DAP - Directory Access Protocol .
Um Serviço de Diretório é um serviço de rede que identifica todos os recursos disponíveis em uma rede e mantém informações sobre estes dispositivos (contas de usuários, grupos, computadores, recursos, políticas de segurança etc.) em um banco de dados tornando estes recursos disponíveis para usuários e aplicações.
Um diretório é um banco de dados com informações sobre usuários, senhas, recursos e outros elementos necessários ao funcionamento de um sistema.
Um domínio pode ser visto como um conjunto de servidores, estações de trabalho, bem como as informações do diretório. Todos os servidores que contém uma cópia da base de dados do Active Directory fazem parte do domínio.
Desta forma, se o seu servidor Web é um membro de um domínio de um Active Directory você pode obter e até atualizar suas informações no Active Directory via código.
A plataforma .NET possui um diversas classes no namespace System.DirecotryServices (Active Directory Services Interfaces - ADSI) que fornecem acesso aos diretórios usando um dos seguintes protocolos:
Veremos a seguir alguns exemplos de como acessar o AD e em para que tudo funcione corretamente a conta da ASP.NET que estiver em execução deve possuir permissão para acessar o Active Directory. Se você estiver usando o Visual Studio ou o Visual Web Developer e testando as páginas usando o servidor web embutido provavelmente terá esse acesso habilitado, de outra forma tente efetuar o login na sua máquina com uma conta que possui permissão de administrador neste domínio.
Se você deseja acessar o AD a partir de uma aplicação rodando sob o IIS , você deverá desabilitar o acesso anônimo para a aplicação no Internet Services Manager, desta forma que os usuários tenham que fornecer credenciais do domínio quando forem acessar a aplicação. (Tome cuidado ao alterar a alocação da conta anônima IUSR ou ao alterar permissões ASP .NET para o AD. Se for efetuar restrições faça-as restringindo o mínimo necessário.)
As principais classes no namespace System.DirecotoryServices são :
O primeiro passo a ser dado para usar o ADSI é fazer uma conexão com o recurso que você deseja acessar (o nó específico da árvore). Para procurar por recursos de todo o domínio você deve se conectar ao topo do nó e assim obter uma referência a raiz do diretório, e, para fazer isso você precisa especificar o URI no formato LDAP correto.
Para acessar o Active Directory local usamos a sintaxe : "LDAP://domain/name" . Exemplo:
Dim recurso as new DirectoryEntry("LDAP://macoratti.net") Obs: A definição do protocolo deve estar em letras maiúsculas: LDAP.
Após inicializar o recurso desejado (o nó da árvore) você precisa especificar uma string de consulta na classe DirectorySearcher. (Você pode definir diversos valores de parâmetros deste objeto para refinar a sua pesquisa). Assim, se você quer obter informações sobre o usuário Macoratti pode definir na propriedade Filter uma string de consulta como (cn=Macoratti) desta forma:
Dim busca As
New DirectorySearcher(recurso)
busca.Filter = "(cn=Macoratti)"
Nota:
Ao definir
a propriedade Filter você deve seguir as seguintes regras:
|
em seguida você deve iniciar a busca chamando os seguintes métodos da classe DirectorySearcher:
O retorno é do tipo SearchResultCollection.
Outra propriedade que vale a pena citar é a PropertiesToLoad que permite a você especificar os valores que você deseja retornar na sua busca. Se você não especificar nada a busca irá retornar todas as propriedades, e , este é o valor padrão. Então se você tiver interesse somente em alguns valores defina os valores que você deseja usando esta propriedade; você faz isso incluindo as propriedades a esta coleção antes de iniciar a busca. Exemplo:
searcher.PropertiesToLoad.Add("nome") irá incluir a propriedade nome a lista de propriedades para retornar na busca.
Com isso você evita que todos as propriedades sejam carregadas na memória.
Após isto você pode executar a busca da seguinte forma:
Dim resultados as
SearchResultCollection
resultados = busca.FindAll()
Após realizar a busca você pode iterar sobre cada entrada SearchResult na coleção SearchResultCollection.
A classe SearchResult possui a propriedade Properties que retorna um objeto ResultPropertyCollection que contém todas as propriedades que você especificou. Ex:
For Each resultado
As SearchResult In resultados
Dim propColl As ResultPropertyCollection = resultado.Properties
Next
Onde ResultPropertyCollection expõe a propriedade PropertyNames que retorna uma coleção contendo nomes de todas as propriedades retornadas pela busca. Assim você pode percorrer esta coleção para obter os nomes. Ex:
For Each strKey As
String In propColl.PropertyNames
For Each obProp As Object In propColl(strKey)
Me.AppendPropertyNode(obTopNode,
strKey, obProp)
Next
Next
Finalizando você pode usar a propriedade PropertyNames para extrair valores específicos do coleção ResultPropertyCollection.
Vejamos a seguir algumas tarefas usando o Active Directory
Você pode criar os exemplos abaixo no Visual Basic 2005 Express ou Visual Studio 2005.
Crie um novo projeto do tipo Windows Application e utilize os seguintes namespaces:
Imports
system.textInclua no formulário o controle ListBox e o controle Button.
Obs: Se for necessário inclua uma referência a System.DirectoryServices clicando com o botão direito do mouse sobre o nome do projeto e selecione a opção Add Reference, em seguida na janela Add Reference , na aba .NET selecione System.DirectoryServices e clique em OK.
1- Listar os domínios de redes
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.ClickDim root As System.DirectoryServices.DirectoryEntry root = New System.DirectoryServices.DirectoryEntry("WinNT:")
ListBox1.Items.Add(dominio.Name) Next End Sub |
Acima estou apontando para o provedor ADSI WinNT: que traz os domínios da rede.
2- Listar os computadores na rede
Private Sub
Button4_Click(ByVal sender
As System.Object, ByVal
e As System.EventArgs)
Handles Button4.Click
Dim root As System.DirectoryServices.DirectoryEntry root = New System.DirectoryServices.DirectoryEntry("WinNT:") Dim dominio As System.DirectoryServices.DirectoryEntry
For Each dom In root.Children Dim computadores As System.DirectoryServices.DirectoryEntry computadores= New System.DirectoryServices.DirectoryEntry("WinNT://" + dominio.Name)
For Each comp In computers.Children If comp.SchemaClassName = "computador" Then ListBox1.Items.Add((comp.Name) End If Next Next End Sub |
3- Obtendo uma lista de usuários do Active Directory
Vamos aplicar esta teoria toda em um exemplo básico: retornar uma lista de usuários encontrados no container "Users" do Active Directory no domínio local.
O código mostrado a seguir faz exatamente isso.
Private Sub
Button1_Click(ByVal sender
As System.Object, ByVal
e As System.EventArgs)
Handles Button1.Click
' obtem uma reerencia ao Active Directory Atual ' e exibe o nome do dominioDim dominio As Domain = Domain.GetCurrentDomain() Dim nomeDominio As String = dominio.Name
Using searcher As New DirectorySearcher(root, "CN=Users") ' retorna a primeira ocorrência Dim result As SearchResult = searcher.FindOne()
builder.Append("No 'CN=Users' entry found.") Else ' obtem a entrada do diretorio para o caminho CN=Users Using entry As DirectoryEntry = result.GetDirectoryEntry() ' percorre todos as entradas filhas
Dim userEntry As String = child.Name ' remove "CN=" do nome retornado builder.Append(userEntry.Substring(userEntry.IndexOf("=") + 1) + "" & Chr(10) & "") Next End Using End If End Using End Using resultado = builder.ToString() ListBox1.Items.Add(resultado) End Sub |
A seguir temos uma função para listar todos os usuários usando o Active Directory :
Public Function ListarTodosUsuariosAD() As DataTable Dim LDAP As String = "<ValorDoWebConfig>" Dim table As DataTable = New DataTable("Resultados") table.Columns.Add("Nome") table.Columns.Add("Usuario") table.Columns.Add("Email") Dim row As DataRow Dim deRoot As DirectoryEntry = New DirectoryEntry(LDAP) Dim deSrch As DirectorySearcher = New DirectorySearcher(deRoot, "(&(objectClass=user)(objectCategory=person))") deSrch.PropertiesToLoad.Add("cn") deSrch.PropertiesToLoad.Add("userPrincipalName") deSrch.PropertiesToLoad.Add("sAMAccountName") deSrch.PropertiesToLoad.Add("mail") deSrch.Sort.PropertyName = "sAMAccountName" Dim oRes As SearchResult For Each oRes In deSrch.FindAll() row = table.NewRow() row("Nome") = oRes.Properties("cn")(0).ToString() row("usuario") = oRes.Properties("sAMAccountName")(0).ToString() If oRes.Properties.Contains("mail") Then row("Email") = oRes.Properties("mail")(0).ToString() End If table.Rows.Add(row) Next Return table End Function
|
4- Autenticação de usuários
Para autenticar usuários no AD crie um novo web site no VS ou no VWD 2005 e inclua uma classe ao seu projeto chamada Autoriza.vb; a seguir crie uma função chamada Autentica contendo o seguinte código:
Imports System.DirectoryServicesPublic Class AutorizaPublic Function Autentica(ByVal IpServer As String, ByVal User As String, ByVal Senha As String) As String Dim resutado As String = "" Try Dim oAD As DirectoryEntry = New DirectoryEntry("LDAP://" + IpServer, User, Senha) resutado = oAD.Name Catch ex As Exception Throw New Exception(ex.Message) End Try Return resutadoEnd Function End Class
|
Agora na página Default.aspx inclua dois controle TextBox : txtUsuario e txtSenha e um botão de comando Button : btnLogin;
Agora no evento Click do botão de comando inclua o seguinte código:
Protected
Sub btnLogin_Click(ByVal
sender As Object,
ByVal e As System.EventArgs)
Handles btnLogin.Click Dim oAD As Autoriza = New Autoriza Try |
Para um exemplo mais detalhado e robusto veja o link: http://www.microsoft.com/brasil/security/guidance/topics/devsec/secmod16.mspx
Na verdade o assunto sobre o Active Directory é muito amplo e o artigo pretende apenas mostrar o básico sobre este recurso mostrando algumas possibilidades de uso.
Nota: Em pesquisas que realizei na internet descobri que o Active Directory não é suportado pelo Windows XP.
Até o próximo artigo...
José Carlos Macoratti