Principios de usuario.GetAuthorizationGroups Se produjo un error (1301) al enumerar los grupos. Después de actualizar al Controlador de Dominio Server 2012


Investigación:

Problema similar con la solución alternativa, pero no la solución real al problema existente

Problema similar que apunta a Microsoft End Point update como culpable

Los enlaces anteriores son los más adecuados para mi problema, también he visto todas las preguntas similares listadas por Stack Overflow al crear este post, y solo las preguntas mencionadas anteriormente se ajustan a mi problema.

Antecedentes:

He estado usando UserPrincipal.GetAuthorizationGroups para permisos para el acceso a páginas específicas ejecutando IIS 7.5 en Server 2008 R2 en un C#.NET 4.0 web forms site durante 2 años y medio. El 15 de mayo de 2013 eliminamos un controlador de dominio principal que ejecutaba Server 2008 (no r2) y lo reemplazamos por un Controlador de Dominio Server 2012. Al día siguiente comenzamos a recibir la excepción que se indica a continuación.

Uso el Contexto Principal para la autenticación de Formularios. El nombre de usuario/handshake pass tiene éxito y la cookie de autenticación se establece correctamente, pero el Principal posterior La llamada de contexto que también llama UserPrincipal.GetAuthorizationGroups falla intermitentemente. Hemos resuelto algunos problemas de BPA que aparecieron en el Controlador de dominio Server 2012, pero esto aún no ha resuelto el problema. También instituí un cron que se ejecuta en dos servidores separados. Los dos servidores fallarán en la resolución SID del grupo en momentos diferentes aunque estén ejecutando la misma base de código. (Un entorno de desarrollo y un entorno de producción).

El problema se resuelve temporalmente al reiniciar el servidor web, y también en el dev servidor se resolverá después de 12 horas de no funcionar. El servidor de producción generalmente dejará de funcionar correctamente hasta que se reinicie sin resolverse.

En este punto estoy tratando de refinar el cron dirigido a Controladores de Dominio específicos en la red, así como el nuevo DC y el uso de la consulta LDAP estándar que actualmente no puede producir más tiempos de excepción dirigidos. Hasta ahora hemos encontrado en un servidor web que no hay un patrón en los días en que falla, pero se recuperará en aproximadamente 12 horas. Los últimos resultados muestran fallo de resolución de Grupo SID entre 8AM-8PM luego se recupera, varios días más tarde fallará a las 8pm y se recuperará a las 8am y luego funcionará bien durante otras 12 horas y fallará nuevamente. Esperamos ver si se trata solo de un problema específico de comunicación del servidor o si se trata de todo el conjunto de Controladores de dominio.

Excepción:

Exception information: 
Exception type: PrincipalOperationException 
Exception message: An error (1301) occurred while enumerating the groups.  
The group's SID could not be resolved.
at System.DirectoryServices.AccountManagement.SidList.TranslateSids(String target, IntPtr[] pSids)
at System.DirectoryServices.AccountManagement.SidList..ctor(SID_AND_ATTR[] sidAndAttr)
at System.DirectoryServices.AccountManagement.AuthZSet..ctor(Byte[] userSid, NetCred credentials, ContextOptions contextOptions, String flatUserAuthority, StoreCtx userStoreCtx, Object userCtxBase)
at System.DirectoryServices.AccountManagement.ADStoreCtx.GetGroupsMemberOfAZ(Principal p)
at System.DirectoryServices.AccountManagement.UserPrincipal.GetAuthorizationGroups()

Pregunta:

Dada la información anterior, ¿alguien tiene ¿alguna idea de por qué desactivar Windows Server 2008 (no r2) e implementar un nuevo Server 2012 DC causaría que UserPrincipal.GetAuthorizationGroups fallara con el error de resolución SID 1301? También se agradecerían ideas sobre la eliminación de posibles causas.

Descargo de responsabilidad:

Este es mi primer post para Stack Overflow, a menudo investigo aquí, pero no me he unido a las discusiones hasta ahora. Perdóneme si debería haber publicado en otro lugar y siéntase libre de señalar mejores pasos antes publicación.

ACTUALIZACIÓN 13-JUN-2013:

El 12 de junio abordé la posibilidad de que elementos no dispuestos causaran el problema. El marco de tiempo ha sido demasiado corto para determinar si el código ajustado ha solucionado el problema, pero continuaré actualizándolo a medida que trabajamos hacia una resolución tal que tal vez con un poco de suerte alguien aquí pueda echar una mano.

Código original

    public bool isGroupMember(string userName, ArrayList groupList)
    {
        bool valid = false;

            PrincipalContext ctx = new PrincipalContext(ContextType.Domain, domain_server + ".domain.org:636", null, ContextOptions.Negotiate | ContextOptions.SecureSocketLayer);

            // find the user in the identity store
            UserPrincipal user =
                UserPrincipal.FindByIdentity(
                    ctx,
                    userName);

            // get the groups for the user principal and
            // store the results in a PrincipalSearchResult object
            PrincipalSearchResult<Principal> groups =
                user.GetAuthorizationGroups();

            // display the names of the groups to which the
            // user belongs
            foreach (Principal group in groups)
            {
                foreach (string groupName in groupList)
                {
                    if (group.ToString() == groupName)
                    {
                        valid = true;
                    }
                }

            }
        return valid;
    }

Código actualizado

        public bool isGroupMember(string userName, ArrayList groupList, string domain_server)
        {
        bool valid = false;

            try
            {

                using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain, domain_server + ".domain.org:636", null, ContextOptions.Negotiate | ContextOptions.SecureSocketLayer))
                {

                    // find the user in the identity store
                    UserPrincipal user =
                        UserPrincipal.FindByIdentity(
                            ctx,
                            userName);

                    try
                    {
                        // get the groups for the user principal and
                        // store the results in a PrincipalSearchResult object
                        using (PrincipalSearchResult<Principal> groups = user.GetAuthorizationGroups())
                        {
                            // display the names of the groups to which the
                            // user belongs

                            foreach (Principal group in groups)
                            {
                                foreach (string groupName in groupList)
                                {

                                    if (group.ToString() == groupName)
                                    {
                                        valid = true;
                                    }
                                }

                                group.Dispose();

                            }
                        }//end using-2
                    }
                    catch
                    {
                        log_gen("arbitrary info");
                        return false;
                    }
                }//end using-1
            }
            catch
            {
                log_gen("arbitrary info");
                return false;
            }

        return valid;

    }
Author: Community, 2013-06-10

9 answers

Acabo de encontrar este mismo problema y la información que he logrado rastrear puede ser útil; como anteriormente hemos visto este problema donde el controlador de dominio está ejecutando Server 2012, en primer lugar con una implementación del cliente y luego replicado en nuestra propia red.

Después de un poco de experimentación, descubrimos que nuestro código se ejecutaría bien en Server 2012, pero golpeó el código de error 1301 cuando el sistema cliente estaba ejecutando Server 2008. Se encontró la información clave sobre lo que estaba sucediendo aquí:

MS blog traducido del alemán

La revisión mencionada en el siguiente enlace ha solucionado el problema en nuestro sistema de prueba

SID S-1-18-1 y SID S-1-18-2 no se puede mapear

Espero que esto sea útil para alguien! Como muchos han señalado, esta llamada al método parece bastante frágil y probablemente veremos la implementación de algún enfoque alternativo antes de llegar a otros problemas.

Gary

 18
Author: Gary Hill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-15 14:45:52

Experimentamos este problema cuando nuestro equipo de infraestructura puso en línea un Controlador de Dominio de 2012. También teníamos DCs pre-2012 en su lugar y por lo que experimentamos el problema de forma intermitente. Se nos ocurrió una solución que quería compartir-tiene 2 partes.

En primer lugar, instale el hotfix mencionado por Gary Hill. Esto resolverá el siguiente problema:

Se produjo un error (1301) al enumerar los grupos. El SID del grupo no podía ser resuelto.

Pensamos que estábamos en casa libre después de instalar este hotfix. Sin embargo, después de que se instaló, obtuvimos un error intermitente diferente. Ciertos grupos que estábamos interrogando tenían una propiedad null sAMAccountName. La propiedad real estaba poblada en Active Directory, pero la API la devolvía incorrectamente con un valor null. Supongo que esto es un error en algún lugar de la API de Active Directory, pero no sé más que eso.

Afortunadamente estábamos capaz de solucionar el problema cambiando a usar la propiedad group Name en lugar de la propiedad sAMAccountName. Esto funcionó para nosotros. Creo que sAMAccountName está efectivamente en desuso y solo existe por razones de compatibilidad con versiones anteriores. Siendo ese el caso, parecía un cambio razonable.

Adjunto una versión reducida de nuestro código GetRolesForUser para demostrar el cambio en su lugar.

using (var context = new PrincipalContext(ContextType.Domain, _domainName))
{
    try
    {
        var p = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, username);
        if (p == null) throw new NullReferenceException(string.Format("UserPrincipal.FindByIdentity returned null for user: {0}, this can indicate a problem with one or more of the AD controllers", username));

        var groups = p.GetAuthorizationGroups();
        var domain = username.Substring(0, username.IndexOf(@"\", StringComparison.InvariantCultureIgnoreCase)).ToLower();

        foreach (GroupPrincipal group in groups)
        {
            if (!string.IsNullOrEmpty(group.Name))
            {
                var domainGroup = domain + @"\" + group.Name.ToLower();

                if (_groupsToUse.Any(x => x.Equals(domainGroup, StringComparison.InvariantCultureIgnoreCase)))
                {
                    // Go through each application role defined and check if the AD domain group is part of it
                    foreach (string role in roleKeys)
                    {
                        string[] roleMembers = new [] { "role1", "role2" };

                        foreach (string member in roleMembers)
                        {
                            // Check if the domain group is part of the role
                            if (member.ToLower().Contains(domainGroup))
                            {
                                // Cache the Application Role (NOT the AD role)
                                results.Add(role);
                            }
                        }
                    }
                }
            }

            group.Dispose();
        }
    }
    catch (Exception ex)
    {
        throw new ProviderException("Unable to query Active Directory.", ex);
    }
}

Espero que eso ayude.

 4
Author: John Reilly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-20 13:16:04

Aquí está mi solución. Parece funcionar consistentemente bien. Debido a que el problema ocurre cuando se itera sobre la colección, uso un enfoque diferente cuando se itera para manejar la excepción sin bloquear la iteración real:

private string[] GetUserRoles(string Username)
{    
    List<string> roles = new List<string>();
    try
    {
        string domain = Username.Contains("\\") ? Username.Substring(0, Username.IndexOf("\\")) : string.Empty;
        string username = Username.Contains("\\") ? Username.Substring(Username.LastIndexOf("\\") + 1) : Username;
        if (!string.IsNullOrEmpty(domain) && !string.IsNullOrEmpty(username))
        {
            PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, domain);
            UserPrincipal user = UserPrincipal.FindByIdentity(principalContext, username);
            if (user != null)
            {
                PrincipalSearchResult<Principal> groups = user.GetAuthorizationGroups();
                int count = groups.Count();
                for (int i = 0; i < count; i++)
                {
                    IEnumerable<Principal> principalCollection = groups.Skip(i).Take(1);
                    Principal principal = null;
                    try
                    {
                        principal = principalCollection.FirstOrDefault();
                    }
                    catch (Exception e)
                    {
                        //Error handling...
                        //Known exception - sometimes AD can't query a particular group, requires server hotfix?
                        //http://support.microsoft.com/kb/2830145
                    }

                    if (principal!=null && principal is GroupPrincipal)
                    {
                        GroupPrincipal groupPrincipal = (GroupPrincipal)principal;
                        if (groupPrincipal != null && !string.IsNullOrEmpty(groupPrincipal.Name))
                        {
                            roles.Add(groupPrincipal.Name.Trim());
                        }
                    }
                }
            }
        }
    }
    catch (Exception e)
    {
        //Error handling...
    }
    return roles.ToArray();
}
 4
Author: AlishahNovin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-18 16:57:56

Experimenté el código de error 1301 con UserPrincipal.GetAuthorizationGroups mientras usaba un nuevo dominio de desarrollo virtual que contenía 2 estaciones de trabajo y 50 usuarios/grupos (muchos de los cuales son los integrados). Estábamos ejecutando Windows Server 2012 R2 Essentials con dos estaciones de trabajo de la empresa de Windows 8,1 unidas al dominio.

Pude obtener recursivamente una lista de miembros del grupo de un usuario usando el siguiente código:

class ADGroupSearch
{
    List<String> groupNames;

    public ADGroupSearch()
    {
        this.groupNames = new List<String>();
    }

    public List<String> GetGroups()
    {
        return this.groupNames;
    }

    public void AddGroupName(String groupName)
    {
        this.groupNames.Add(groupName);
    }

    public List<String> GetListOfGroupsRecursively(String samAcctName)
    {
        PrincipalContext ctx = new PrincipalContext(ContextType.Domain, System.Environment.UserDomainName);
        Principal principal = Principal.FindByIdentity(ctx, IdentityType.SamAccountName, samAcctName);
        if (principal == null)
        {
            return GetGroups();
        }
        else
        {
            PrincipalSearchResult<Principal> searchResults = principal.GetGroups();

            if (searchResults != null)
            {
                foreach (GroupPrincipal sr in searchResults)
                {
                    if (!this.groupNames.Contains(sr.Name))
                    {
                        AddGroupName(sr.Name);
                    }
                    Principal p = Principal.FindByIdentity(ctx, IdentityType.SamAccountName, sr.SamAccountName);

                    try
                    {
                        GetMembersForGroup(p);
                    }
                    catch (Exception ex)
                    {
                        //ignore errors and continue
                    }
                }

            }
            return GetGroups();
        }

    }



    private void GetMembersForGroup(Principal group)
    {
        if (group != null && typeof(GroupPrincipal) == group.GetType())
        {
            GetListOfGroupsRecursively(group.SamAccountName);
        } 
    }

    private bool IsGroup(Principal principal)
    {
        return principal.StructuralObjectClass.ToLower().Equals("group");
    }
}
 2
Author: TS12,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-29 19:04:48

Estoy en un entorno con múltiples bosques de dominios y confianzas. Tengo más o menos este mismo código que se ejecuta en un formulario de sitio web utilizado para realizar búsquedas de grupos de seguridad de usuarios en los diferentes dominios.

Obtengo este error exacto en uno de los dominios muy grandes donde la membresía de grupo puede incluir más de 50 grupos diferentes. Funciona bien en otros dominios bosques.

En mi investigación encontré un hilo que parece no estar relacionado, pero en realidad tiene el mismo rastro de pila. Es para un control remoto aplicación ejecutándose en SBS. El hilo menciona que el error es causado por SID irresolubles en un grupo. Creo que estos serían lo que se conoce como "tombstoned" SIDS en active directory. Ver el hilo aquí.

El hilo sugiere que encontrar las enteries sepulcrales y eliminarlas de los grupos resuelve el problema. ¿Es posible que el error que está recibiendo se deba a que los SMSL están siendo sepultados cada 12 horas por un proceso separado no relacionado? En última instancia, creo que esto es un error en el framework, y que el método no debe bloquearse debido a los SID tombstoned/irresolubles.

¡Buena suerte!

 1
Author: Bri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-23 18:13:39

Si alguien está interesado este es un VB.NET versión del mismo código. Pocas cosas que tienes que hacer antes de que este código pueda funcionar

1) Tiene que hacer referencia al Sistema de ensamblaje.DirectoryServices
2) Asegúrese de pasar la variable "theusername" sin el dominio, por lo que si su dominio es "GIS" y su nombre de usuario es "Hussein", Windows generalmente lo autentica como GIS\Hussein. Así que tienes que enviar solo el nombre de usuario "Hussein". Resolví las cosas sensibles a mayúsculas y minúsculas.
3) El método GetGroupsNew toma un nombre de usuario y devuelve una lista de grupos
4) El método isMemberofnew toma un nombre de usuario y un grupo y verifica que este usuario es parte de ese grupo o no, este es el que me interesaba.

Private Function getGroupsNew(theusername As String) As List(Of String)
    Dim lstGroups As New List(Of String)
    Try

        Dim allDomains = Forest.GetCurrentForest().Domains.Cast(Of Domain)()

        Dim allSearcher = allDomains.[Select](Function(domain)
                                                  Dim searcher As New DirectorySearcher(New DirectoryEntry("LDAP://" + domain.Name))

                                                  searcher.Filter = [String].Format("(&(&(objectCategory=person)(objectClass=user)(userPrincipalName=*{0}*)))", theusername)

                                                  Return searcher

                                              End Function)

        Dim directoryEntriesFound = allSearcher.SelectMany(Function(searcher) searcher.FindAll().Cast(Of SearchResult)().[Select](Function(result) result.GetDirectoryEntry()))

        Dim memberOf = directoryEntriesFound.[Select](Function(entry)
                                                          Using entry
                                                              Return New With { _
                                                               Key .Name = entry.Name, _
                                                               Key .GroupName = DirectCast(entry.Properties("MemberOf").Value, Object()).[Select](Function(obj) obj.ToString()) _
                                                              }
                                                          End Using

                                                      End Function)



        For Each user As Object In memberOf
            For Each groupName As Object In user.GroupName
                lstGroups.Add(groupName)
            Next
        Next

        Return lstGroups

    Catch ex As Exception
        Throw
    End Try
End Function

Private Function isMemberofGroupNew(theusername As String, thegroupname As String) As Boolean

    Try

        Dim lstGroups As List(Of String) = getGroupsNew(theusername)

        For Each sGroup In lstGroups
            If sGroup.ToLower.Contains(thegroupname.ToLower) Then Return True
        Next

        Return False


    Catch ex As Exception
        Throw
    End Try

End Function
 1
Author: Hussein Nasser,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-01 09:42:43

Tuvimos un problema similar después de actualizar el controlador de dominio a 2012. De repente mi llamada al usuario.GetAuthorizationGroups() comenzó a fallar; estaba recibiendo la misma excepción que tú (error 1301). Por lo tanto, lo cambié a usuario.GetGroups(). Eso funcionó por un tiempo, luego comenzó a fallar intermitentemente en "mal nombre de usuario o contraseña". Mi última solución parece solucionarlo, al menos por el momento. En lugar de llamar a cualquiera de ellos, después de construir el objeto user, también construyo un objeto de grupo, uno para cada grupo del que quiero ver si el usuario es miembro. es decir, " usuario.IsMemberOf(grupo)". Eso parece funcionar.

try
{
using (HostingEnvironment.Impersonate())
{
    using (var principalContext = new PrincipalContext(ContextType.Domain, "MYDOMAIN"))
    {
        using (var user = UserPrincipal.FindByIdentity(principalContext, userName))
        {
            if (user == null)
            {
                Log.Debug("UserPrincipal.FindByIdentity failed for userName = " + userName + ", thus not authorized!");
                isAuthorized = false;
            }

            if (isAuthorized)
            {
                firstName = user.GivenName;
                lastName = user.Surname;

                // so this code started failing:

                // var groups = user.GetGroups();
                // adGroups.AddRange(from @group in groups where 
                // @group.Name.ToUpper().Contains("MYSEARCHSTRING") select @group.Name);

                // so the following workaround, which calls, instead, 
                // "user.IsMemberOf(group)", 
                // appears to work (for now at least).  Will monitor for issues.

                // test membership in SuperUsers
                const string superUsersGroupName = "MyApp-SuperUsers";
                using (var superUsers = GroupPrincipal.FindByIdentity(principalContext, superUsersGroupName))
                {
                    if (superUsers != null && user.IsMemberOf(superUsers))
                        // add to the list of groups this user is a member of
                        // then do something with it later
                        adGroups.Add(superUsersGroupName);                                        
                }
 0
Author: David Barrows,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-28 13:13:44

Tuve la misma excepción. Si alguien no quiere usar "LDAP", use este código. Porque tengo grupos anidados, estoy usando GetMembers (true) y es un poco más largo en el tiempo que GetMembers ().

Https://stackoverflow.com/a/27548271/1857271

O descarga corrección desde aquí: http://support.microsoft.com/kb/2830145

 0
Author: Nazar Iaremii,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:54:24

Ante el mismo problema enumerar grupos de autorización y los parches indicados en la respuesta no se aplicaban a nuestro servidor web.

Enumerar e ignorar manualmente los grupos que causan problemas está funcionando bien, sin embargo:

private static bool UserIsMember(string usr, string grp)
{
    usr = usr.ToLower();
    grp = grp.ToLower();

    using (var pc = new PrincipalContext(ContextType.Domain, "DOMAIN_NAME"))
    {
        using (var user = UserPrincipal.FindByIdentity(pc, usr))
        {
            var isMember = false;
            var authGroups = user?.GetAuthorizationGroups().GetEnumerator();

            while (authGroups?.MoveNext() ?? false)
            {
                try
                {

                    isMember = authGroups.Current.Name.ToLower().Contains(grp);
                    if (isMember) break;
                }
                catch
                {
                    // ignored
                }
            }

            authGroups?.Dispose();
            return isMember;
        }
    }
}
 0
Author: davidmdem,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-05 18:35:07