GroupPrincipal.GetMembers fails when group (or child group if recursive) contains ForeignSecurityPrincipal

前端 未结 3 809
没有蜡笔的小新
没有蜡笔的小新 2021-01-04 09:53

This is not so much a question as information for anyone experiencing the same problem.

The following error occurs:

System.Directory         


        
相关标签:
3条回答
  • 2021-01-04 10:05

    The accountmanagement library has many saddening defects, this is just another of the many...

    One thing you can do to make things slightly faster would be to adjust your LDAP query so that it checks both group membership and object type at the same time as part of the query instead of in the loop. Honestly I doubt it will make much difference though.

    Most of the inspiration for the query came from How to write LDAP query to test if user is member of a group?.

    Query: (&(!objectClass=foreignSecurityPrincipal)(memberof=CN=YourGroup,OU=Users,DC=YourDomain,DC=com))

    Note: This is an untested query...

    IF there was a way to run an LDAP query in AccountManagement (another gripe of mine) then this would be the end of your troubles as you could run the query and let AccountManagement take it from there, but this option does not exist...

    Based on personal experience I don't see any other options if you stick with AccountManagement. What you could do is dump AccountManagement and use just DirectoryServices. Under the hood all AccountManagement does is wrap DirectoryEntry objects anyways, you could write a few helper classes to do similar things.

    0 讨论(0)
  • 2021-01-04 10:08

    Sure this is an old thread, but might help someone. I used the below code block the solve the problem. the Principal class exposes a property called StructuralObjectClass which tells you what is the AD Class of that principal. I used this to decide whether the object is a user. The GetMembers(true) recursively searches all nested-members in the groupPrincipal in question.

    Hope this helps someone.

        List<UserPrincipal> members = new List<UserPrincipal>();
        foreach (var principal in groupPrincipal.GetMembers(true))
        {
            var type = principal.StructuralObjectClass;
            if (type.Contains("user"))
                members.Add((UserPrincipal)principal);
        }
    

    Thanks, R

    0 讨论(0)
  • 2021-01-04 10:14

    As an alternative, you can use this code to get the members:

    var pth = "LDAP://ex.invalid/CN=grpName,OU=Groups,OU=whatever,DC=ex,DC=invalid";
    var dirEntry = new DirectoryEntry(pth);
    var members = dirEntry.Invoke("Members"); //COM object
    foreach (var member in (IEnumerable)members) {
        var userEntry = new DirectoryEntry(member); //member is COM object
        var sid = new SecurityIdentifier((byte[]) userEntry.InvokeGet("objectSid"), 0);
        var typ = typeof(System.Security.Principal.NTAccount);
        var account = (NTAccount)sid.Translate(typ);
        Console.WriteLine(account.Value);
    }
    
    0 讨论(0)
提交回复
热议问题