Active Directory group lookup function failing

后端 未结 3 1617
天涯浪人
天涯浪人 2021-01-15 15:29

Help! I\'ve been trying to write a function that will confirm a user\'s membership in an Active Directory group, and while it works if the member happens to be in the group,

相关标签:
3条回答
  • 2021-01-15 16:00

    A minor modification top the code from marc_s, I have:

    using (var ctx = new PrincipalContext(ContextType.Domain)) 
    using (var userPrincipal = UserPrincipal.FindByIdentity(ctx, user)) 
    using (var groupPrincipal = GroupPrincipal.FindByIdentity(ctx, group))
    {
         if (userPrincipal == null) return false;
         if (groupPrincipal == null) return false;
    
         PrincipalSearchResult<Principal> result = userPrincipal.GetGroups(); 
         Principal grp = result.Where(g => g.Sid == groupPrincipal.Sid).FirstOrDefault(); 
         return (grp != null);
    }
    

    Comparing Sid seems to work more reliably than comparing SamAccountName.

    0 讨论(0)
  • 2021-01-15 16:01

    We had a bit of a poison group in our setup which caused this to fail for some users but not others. The "FirstOrDefault" logic in the other suggested answers MIGHT have helped us dodge the poison group, but that is no guarantee.

    We have two suggestions for others with this problem. First check if you have any groups with a forward slash in the group name (the actual group name, not the "pre-windows 2000" name which will replace it with an underscore). If you can rename all such groups that might fix your problem ... it worked for us.

    This workaround also was working for us:

    /// <summary>
    /// This does a recursive group search for the given user or computer principal.
    /// </summary>
    public IEnumerable<Principal> GetGroups(Principal principal)
    {
        return GetGroups(null, principal);
    }
    
    private IEnumerable<Principal> GetGroups(HashSet<SecurityIdentifier> ancestorPrincipalSids, Principal parentPrincipal)
    {
        try
        {
            //enumerate this here so errors are thrown now and not later
            //if the current group name has a forward-slash, I think this 
            //will always error here
            var groups = parentPrincipal.GetGroups().ToArray();
            if (groups == null)
            {
                return Enumerable.Empty<Principal>();
            }
    
            //keep track of all ancestors in the group hierarchy to this point
            //so that we can handle circular references below
            var newAncestors = new HashSet<SecurityIdentifier>(ancestorPrincipalSids ?? Enumerable.Empty<SecurityIdentifier>());
            newAncestors.Add(parentPrincipal.Sid);
    
            return groups
                .Concat(groups
                    .Where(g => !newAncestors.Contains(g.Sid)) //handle circular references
                    .SelectMany(g => GetGroups(newAncestors, g)));
        }
        catch
        {
            return Enumerable.Empty<Principal>();
        }
    }
    
    0 讨论(0)
  • 2021-01-15 16:04

    I think you could simplify things a bit:

    private bool IsUserMemberOfGroup(string user, string group)
    {
      using (var ctx = new PrincipalContext(ContextType.Domain))
      using (var userPrincipal = UserPrincipal.FindByIdentity(ctx, user))
      {
          PrincipalSearchResult<Principal> result = userPrincipal.GetGroups();
    
          GroupPrincipal groupPrincipal = 
               result.Where(g => g.SamAccountName == groupName).FirstOrDefault();
    
          return (groupPrincipal != null);
      }
    }
    

    The userPrincipal.GetGroups() will give you a definitive list of all group memberships (including primary group and nested group memberships) for that user; then search that list for the group you're interested in, e.g. by samACcountName or some other property.

    If you find the group you're looking for in the PrincipalSearchResult<Principal> returned by GetGroups(), then your user is a member of that group.

    You can save yourself at least one "FindByIdentity" call with this.

    0 讨论(0)
提交回复
热议问题