2010-02-03 58 views

Respuesta

1

puede probar con el siguiente código:

public bool Check_If_Member_Of_AD_Group(string username, string grouptoCheck, string domain, string ADlogin, string ADpassword) 
{ 
    
    try { 
        
        string EntryString = null; 
        EntryString = "LDAP://" + domain; 
        
        DirectoryEntry myDE = default(DirectoryEntry); 
        
        grouptoCheck = grouptoCheck.ToLower(); 
        
        
        myDE = new DirectoryEntry(EntryString, ADlogin, ADpassword); 
        
        DirectorySearcher myDirectorySearcher = new DirectorySearcher(myDE); 
        
        myDirectorySearcher.Filter = "sAMAccountName=" + username; 
        
        myDirectorySearcher.PropertiesToLoad.Add("MemberOf"); 
        
        SearchResult myresult = myDirectorySearcher.FindOne(); 
        
        int NumberOfGroups = 0; 
        
        NumberOfGroups = myresult.Properties["memberOf"].Count - 1; 
        
        string tempString = null; 
        
        while ((NumberOfGroups >= 0)) { 
            
            tempString = myresult.Properties["MemberOf"].Item[NumberOfGroups]; 
            tempString = tempString.Substring(0, tempString.IndexOf(",", 0)); 
            
            tempString = tempString.Replace("CN=", ""); 
            
            tempString = tempString.ToLower(); 
            tempString = tempString.Trim(); 
            
            if ((grouptoCheck == tempString)) { 
                
                    
                return true; 
            } 
            
                
            NumberOfGroups = NumberOfGroups - 1; 
        } 
        
            
        return false; 
    } 
    catch (Exception ex) { 
        
        System.Diagnostics.Debugger.Break(); 
    } 
    //HttpContext.Current.Response.Write("Error: <br><br>" & ex.ToString) 
} 
+2

Al igual que con la respuesta de BC, el código anterior no probará la membresía anidada –

+0

Este código ni siquiera se compila en 3.5 C#, ¿cuál es el problema? – Justin

38

con 3.5 y System.DirectoryServices.AccountManagement esto es un poco más limpia: solución

public List<string> GetGroupNames(string userName) 
{ 
    var pc = new PrincipalContext(ContextType.Domain); 
    var src = UserPrincipal.FindByIdentity(pc, userName).GetGroups(pc); 
    var result = new List<string>(); 
    src.ToList().ForEach(sr => result.Add(sr.SamAccountName)); 
    return result; 
} 
+0

Aparece este error en el código enumerado: Error desconocido (0x80005000) Descripción: Se produjo una excepción no controlada durante la ejecución de la solicitud web actual. Revise el seguimiento de la pila para obtener más información sobre el error y dónde se originó en el código. Detalles de excepciones: System.Runtime.InteropServices.COMException: error desconocido (0x80005000) La línea haciendo que es: ".GetGroups (PC) var src = UserPrincipal.FindByIdentity (pc, nombre de usuario);" ¿Alguna sugerencia sobre cuál podría ser el problema? Copié la función como está de tu ejemplo. – Ben

+1

@Ben ¿estás seguro de que la cuenta que estás utilizando tiene permisos para consultar AD? Muchos lugares tienen enlaces anónimos deshabilitados –

+10

Estoy usando .NET 4.0 y tuve que cambiar esta línea, 'var pc = new PrincipalContext (ContextType.Domain);' to 'var pc = new PrincipalContext (ContextType.Domain," MyDomainHere "); 'Para deshacerse de la excepción. Después de eso funciona perfectamente. – Dan

19

de Nick Craver no funciona para mí en .NET 4.0. Aparece un error sobre un AppDomain descargado. En lugar de usar eso, utilicé esto (solo tenemos un dominio). Esto verificará grupos de grupos así como la membresía directa del grupo.

using System.DirectoryServices.AccountManagement; 
using System.Linq; 

... 

using (var ctx = new PrincipalContext(ContextType.Domain, yourDomain)) { 
    using (var grp = GroupPrincipal.FindByIdentity(ctx, IdentityType.Name, yourGroup)) { 
     bool isInRole = grp != null && 
      grp 
      .GetMembers(true) 
      .Any(m => m.SamAccountName == me.Identity.Name.Replace(yourDomain + "\\", "")); 
    } 
} 
+0

Mientras uso este código, obtengo un error de compilación en el método .Any() que dice que no hay método de extensión. ¿Debo agregar cualquier otro uso o referencia? – Antoops

+1

@Antoops - necesita agregar una instrucción using para System.Linq –

+0

+1 para mostrar cómo usar GetMembers (true), que era exactamente lo que necesitaba para verificar de forma recursiva a los miembros del grupo. –

15

El código siguiente funcionará en .NET 4,0

private static string[] GetGroupNames(string userName) 
{ 
    List<string> result = new List<string>(); 

    using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, "YOURDOMAIN")) 
    { 
     using (PrincipalSearchResult<Principal> src = UserPrincipal.FindByIdentity(pc, userName).GetGroups(pc)) 
     { 
      src.ToList().ForEach(sr => result.Add(sr.SamAccountName)); 
     } 
    } 

    return result.ToArray(); 
} 
+1

Buena respuesta. Gracias. Unas correcciones muy pequeñas: inicializar el resultado al tipo que desea devolver, es decir, lista o matriz. reemplace esta línea: src.ToList(). ForEach (sr => result.Add (sr.SamAccountName)); con esto: result = src.Select (x => x.SamAccountName) .ToList(); // ToArray si prefieres – Sam

1

Brandon Johnson, me encantó, me utilizado lo que tenía, pero hizo el siguiente cambio:

private static string[] GetGroupNames(string domainName, string userName) 
{ 
    List<string> result = new List<string>(); 

    using (PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, domainName)) 
    { 
     using (PrincipalSearchResult<Principal> src = UserPrincipal.FindByIdentity(principalContext, userName).GetGroups(principalContext)) 
     { 
      src.ToList().ForEach(sr => result.Add(sr.SamAccountName)); 
     } 
    } 

    return result.ToArray(); 
} 
4

Depende en lo que quieres decir con si un usuario está en un grupo de AD. En AD, los grupos pueden ser un grupo de seguridad o un grupo de distribución. Incluso para grupos de seguridad, depende de si grupos como "Usuarios del dominio" o "Usuarios" deben incluirse en la verificación de membresía.

IsUserInSecurityGroup solo buscará grupos de seguridad y funcionará para grupos de grupos primarios como "Usuarios de dominio" y "Usuarios", y no para grupos de distribución. También resolverá el problema con grupos anidados. IsUserInAllGroup también buscará grupos de distribución, pero no estoy seguro de si se encontrarán con problemas de permisos. Si lo hace, use una cuenta de servicio que esté en WAAG (See MSDN)

La razón por la que no utilizo UserPrincipal.GetAuthorizedGroups() es porque tiene muchos problemas, como requerir que la cuenta de llamada esté en WAAG y requiriendo que no hay una entrada en SidHistory (See David Thomas' comment)

public bool IsUserInSecurityGroup(string user, string group) 
    { 
     return IsUserInGroup(user, group, "tokenGroups"); 
    } 
    public bool IsUserInAllGroup(string user, string group) 
    { 
     return IsUserInGroup(user, group, "tokenGroupsGlobalAndUniversal"); 
    } 

    private bool IsUserInGroup(string user, string group, string groupType) 
    { 
     var userGroups = GetUserGroupIds(user, groupType); 
     var groupTokens = ParseDomainQualifiedName(group, "group"); 
     using (var groupContext = new PrincipalContext(ContextType.Domain, groupTokens[0])) 
     { 
      using (var identity = GroupPrincipal.FindByIdentity(groupContext, IdentityType.SamAccountName, groupTokens[1])) 
      { 
       if (identity == null) 
        return false; 

       return userGroups.Contains(identity.Sid); 
      } 
     } 
    } 
    private List<SecurityIdentifier> GetUserGroupIds(string user, string groupType) 
    { 
     var userTokens = ParseDomainQualifiedName(user, "user"); 
     using (var userContext = new PrincipalContext(ContextType.Domain, userTokens[0])) 
     { 
      using (var identity = UserPrincipal.FindByIdentity(userContext, IdentityType.SamAccountName, userTokens[1])) 
      { 
       if (identity == null) 
        return new List<SecurityIdentifier>(); 

       var userEntry = identity.GetUnderlyingObject() as DirectoryEntry; 
       userEntry.RefreshCache(new[] { groupType }); 
       return (from byte[] sid in userEntry.Properties[groupType] 
         select new SecurityIdentifier(sid, 0)).ToList(); 
      } 
     } 
    } 
    private static string[] ParseDomainQualifiedName(string name, string parameterName) 
    { 
     var groupTokens = name.Split(new[] {"\\"}, StringSplitOptions.RemoveEmptyEntries); 
     if (groupTokens.Length < 2) 
      throw new ArgumentException(Resources.Exception_NameNotDomainQualified + name, parameterName); 
     return groupTokens; 
    } 
+0

Todas las demás respuestas son incorrectas porque no se ocupan de los grupos anidados. Gracias. –

10

solución más simple

PrincipalContext pc = new PrincipalContext((Environment.UserDomainName == Environment.MachineName ? ContextType.Machine : ContextType.Domain), Environment.UserDomainName); 

GroupPrincipal gp = GroupPrincipal.FindByIdentity(pc, "{GroupName}"); 
UserPrincipal up = UserPrincipal.FindByIdentity(pc, Environment.UserName); 
up.IsMemberOf(gp); 
7

Este método podría ser útil si usted está tratando de determinar si Windows autenticado el usuario actual está en una determinada papel.

public static bool CurrentUserIsInRole(string role) 
{ 
    try 
    { 
     return System.Web.HttpContext.Current.Request 
        .LogonUserIdentity 
        .Groups 
        .Any(x => x.Translate(typeof(NTAccount)).ToString() == role); 
     } 
     catch (Exception) { return false; } 
    } 
2

Aquí están mis 2 centavos.

static void CheckUserGroup(string userName, string userGroup) 
    { 
     var wi = new WindowsIdentity(userName); 
     var wp = new WindowsPrincipal(wi); 

     bool inRole = wp.IsInRole(userGroup); 

     Console.WriteLine("User {0} {1} member of {2} AD group", userName, inRole ? "is" : "is not", userGroup); 
    } 
3

esto parece mucho más simple:

public bool IsInRole(string groupname) 
{ 
    var myIdentity = WindowsIdentity.GetCurrent(); 
    if (myIdentity == null) return false; 

    var myPrincipal = new WindowsPrincipal(myIdentity); 
    var result = myPrincipal.IsInRole(groupname); 

    return result; 
} 
0
var context = new PrincipalContext(ContextType.Domain, {ADDomain}, {ADContainer}); 
var group = GroupPrincipal.FindByIdentity(context, IdentityType.Name, {AD_GROUP_NAME}); 
var user = UserPrincipal.FindByIdentity(context, {login}); 
bool result = user.IsMemberOf(group); 
0

Si desea comprobar el número de miembros de grupos de usuarios incluyendo los grupos anidados que se vinculan indirectamente al grupo principal de usuario puede intentar utilizar el " tokenGroups "propiedades de la siguiente manera:

 
Using System.DirectoryServices 

public static bool IsMemberOfGroupsToCheck(string DomainServer, string LoginID, string LoginPassword) 
     { 
      string UserDN = "CN=John.Doe-A,OU=Administration Accounts,OU=User Directory,DC=ABC,DC=com" 
      string ADGroupsDNToCheck = "CN=ADGroupTocheck,OU=Administration Groups,OU=Group Directory,DC=ABC,DC=com"; 

      byte[] sid, parentSID; 
      bool check = false; 
      DirectoryEntry parentEntry; 
      DirectoryEntry basechildEntry; 
      string octetSID; 

       basechildEntry = new DirectoryEntry("LDAP://" + DomainServer + "/" + UserDN, LoginID, LoginPassword); 
       basechildEntry.RefreshCache(new String[] { "tokenGroups" }); 

       parentEntry = new DirectoryEntry("LDAP://" + DomainServer + "/" + ADGroupsDNToCheck, LoginID, LoginPassword); 
       parentSID = (byte[])parentEntry.Properties["objectSID"].Value; 
       octetSID = ConvertToOctetString(parentSID, false, false); 

       foreach(Object GroupSid in basechildEntry.Properties["tokenGroups"]) 
       { 
        sid = (byte[])GroupSid; 
        if (ConvertToOctetString(sid,false,false) == octetSID) 
        { 
         check = true; 
         break; 
        } 
       } 

       basechildEntry.Dispose(); 
       parentEntry.Dispose(); 

       return check; 
     } 
Cuestiones relacionadas