none
Sistema lento ao autenticar pelo Active Directory RRS feed

  • Pergunta

  • Boa tarde pessoal.
    Tenho um sistema de dashboard que usa login do AD e está muito lento ao efetuar login no primeiro login.
    Depois que loga o sistema fica rápido.
    Se eu trabalhar com o login padrão do Membership provider, o sistema irá ficar rápido.
    Acredito que ao logar, o sistema deve estar consultando o banco do AD inteiro.

    Alguém sabe como devo proceder?
    Grato.

    segunda-feira, 29 de julho de 2013 19:23

Todas as Respostas

  • Olá,

    Em geral a consulta ao AD não é muito performática.

    Veja a seguinte classe para consultas no AD ela tem me atendido bem:

    public class LdapAuthentication
        {
            public string LdapPath { get; set; }
            public string FilterAtribute { get; set; }

            /// <summary>
            /// Construtor para receber o caminho Ldap
            /// </summary>
            /// <param name="ldapPath">Caminho LDAP do AD</param>
            public LdapAuthentication(string ldapPath)
            {
                this.LdapPath = ldapPath;
            }

            /// <summary>
            /// Verificar se usuário está autenticado ou pode ser autenticado no AD segundo o caminho LDAP fornecido na propriedade <paramref name="LdapPath"/>.
            /// </summary>
            /// <param name="domain">Domínio</param>
            /// <param name="username">Login do usuário</param>
            /// <param name="pwd">Password do usuário</param>
            /// <returns>Verdadeiro se usuário for autenticável.</returns>
            public bool IsAuthenticated(string domain, string username, string pwd)
            {
                string domainAndUsername = domain + @"\" + username;

                DirectoryEntry entry = new DirectoryEntry(LdapPath, domainAndUsername, pwd);

                try
                {
                    // Bind to the native AdsObject to force authentication. 
                    //Object obj = entry.NativeObject;
                    DirectorySearcher search = new DirectorySearcher(entry);
                    search.Filter = "(SAMAccountName=" + username + ")";
                    search.PropertiesToLoad.Add("cn");
                    SearchResult result = search.FindOne();

                    if (null == result)
                    {
                        return false;
                    }

                    // Update the new path to the user in the directory
                    LdapPath = result.Path;
                    FilterAtribute = (String)result.Properties["cn"][0];
                }
                catch (Exception ex)
                {
                    throw new Exception("Erro na autenticação do usuário. Descrição: " + ex.Message);
                }
                return true;
            }

            /// <summary>
            /// Buscar os grupos que o usuário é menbro
            /// </summary>
            /// <returns></returns>
            public string GetGroups()
            {
                DirectorySearcher search = new DirectorySearcher(LdapPath);
                search.Filter = "(cn=" + FilterAtribute + ")";
                search.PropertiesToLoad.Add("memberOf");
                StringBuilder groupNames = new StringBuilder();

                try
                {
                    SearchResult result = search.FindOne();
                    int propertyCount = result.Properties["memberOf"].Count;
                    String dn;
                    int equalsIndex, commaIndex;

                    for (int propertyCounter = 0; propertyCounter < propertyCount;
                         propertyCounter++)
                    {
                        dn = (String)result.Properties["memberOf"][propertyCounter];

                        equalsIndex = dn.IndexOf("=", 1, System.StringComparison.Ordinal);
                        commaIndex = dn.IndexOf(",", 1, System.StringComparison.Ordinal);
                        if (-1 == equalsIndex)
                        {
                            return null;
                        }
                        groupNames.Append(dn.Substring((equalsIndex + 1),
                                          (commaIndex - equalsIndex) - 1));
                        groupNames.Append("|");
                    }
                }
                catch (Exception ex)
                {
                    throw new Exception("Erro ao obter os grupos do usuário. Descrição: " + ex.Message);
                }
                return groupNames.ToString();
            }

            /// <summary>
            /// Buscar o e-mail do usuário configurado no Active Directory.
            /// </summary>
            /// <param name="domain">Domínio</param>
            /// <param name="username">Login do usuário</param>
            /// <param name="pwd">Password do usuário</param>
            /// <returns>E-mail do usuário</returns>
            public string GetUserEmail(string domain, string username, string pwd)
            {
                string email = string.Empty;

                string domainAndUsername = domain + @"\" + username;

                DirectoryEntry directoryEntry = new DirectoryEntry(LdapPath, domainAndUsername, pwd);
                DirectorySearcher directorySearcher = new DirectorySearcher(directoryEntry);
                directorySearcher.Filter = String.Format("(&(objectClass=user)(SAMAccountName=*{0}*))", username);
                SearchResultCollection searchResults = directorySearcher.FindAll();

                try
                {
                    if (searchResults.Count > 0 && searchResults[0].Properties["mail"][0] != null)
                        email = searchResults[0].Properties["mail"][0].ToString();
                }
                catch
                {
                    //Se não encontrar e-mail vai gerar erro.
                }

                return email;

            }

            /// <summary>
            /// Buscar o display name (nome completo) do usuário no  Active Directory.
            /// </summary>
            /// <param name="domain">Domínio</param>
            /// <param name="username">Login do usuário</param>
            /// <param name="pwd">Password do usuário</param>
            /// <returns>Nome do usuário</returns>
            public string GetUserDisplayName(string domain, string username, string pwd)
            {
                string displayName = string.Empty;

                string domainAndUsername = domain + @"\" + username;

                DirectoryEntry directoryEntry = new DirectoryEntry(LdapPath, domainAndUsername, pwd);
                DirectorySearcher directorySearcher = new DirectorySearcher(directoryEntry);
                directorySearcher.Filter = String.Format("(&(objectClass=user)(SAMAccountName=*{0}*))", username);
                SearchResultCollection searchResults = directorySearcher.FindAll();

                try
                {
                    if (searchResults.Count > 0 && searchResults[0].Properties["mail"][0] != null)
                        displayName = searchResults[0].Properties["displayName"][0].ToString();
                }
                catch (Exception)
                {
                }

                return displayName;

            }

            /// <summary>
            /// Buscar todos os grupos que usuário pertence mesmo quando o grupo estiver dentro de outros grupos (recursivo).
            /// </summary>
            /// <param name="userDn">Path do AD com atributo DN do usuário</param>
            /// <param name="recursive">Se deve ser recursivo (grupos dentro de grupos)</param>
            /// <returns>Lista de todos os grupos do usuário</returns>
            public ArrayList GroupsRecursive(string userDn, bool recursive)
            {
                ArrayList groupMemberships = new ArrayList();

                var groupsNested = AttributeValuesMultiString("memberOf", userDn, groupMemberships, recursive);

                var arrayGroups = new ArrayList();
                foreach (string groupName in groupsNested)
                {
                    string[] groupsSplit = groupName.Replace(",", "=").Split('=');

                    arrayGroups.Add(groupsSplit[1]);
                }

                return arrayGroups;
            }

            /// <summary>
            /// Buscar os atributos para possível conexão e pesquisa em grupos do Active Directory.
            /// </summary>
            /// <param name="attributeName">Nome do atributo</param>
            /// <param name="objectDn">Objeto Dn</param>
            /// <param name="valuesCollection">Array</param>
            /// <param name="recursive">Se deve ser recursivo</param>
            /// <returns>Lista de atributos</returns>
            private ArrayList AttributeValuesMultiString(string attributeName, string objectDn,
                                                      ArrayList valuesCollection, bool recursive)
            {
                DirectoryEntry ent = new DirectoryEntry(objectDn);
                PropertyValueCollection propertyValueCollection = ent.Properties[attributeName];
                IEnumerator en = propertyValueCollection.GetEnumerator();

                while (en.MoveNext())
                {
                    if (en.Current != null)
                    {
                        if (!valuesCollection.Contains(en.Current.ToString()))
                        {
                            valuesCollection.Add(en.Current.ToString());
                            if (recursive)
                            {
                                AttributeValuesMultiString(attributeName, "LDAP://" + en.Current, valuesCollection, true);
                            }
                        }
                    }
                }

                ent.Close();
                ent.Dispose();

                return valuesCollection;
            }
        }

    Att
    _______________________________________________________________________________________________________________________

    Luciano Rieth


    quinta-feira, 1 de agosto de 2013 17:36
  • Obrigado Luciano.
    Me parece que isso irá me ajudar, mas me tira uma duvida por favor.
    É que eu não tenho muita experiência, mas estou aprendendo.
    Eu devo criar uma classe (Botão direito, criar arquivo LDap.cs e etc)?
    Qual são as namespaces que eu vou precisar além de:

    using System.Web.Security;
    using System.Security.Permissions;

    Grato.

     

    sexta-feira, 2 de agosto de 2013 11:47