문제

How do i go about iterating a group to find out if a given user is a member of a group?

I know i can use IsInRole on WindowsPrincipal object but for some reason it don't always work for me, it doesn't error out or throw exception but just return false.

i have put together following code from web, can some help me improve it in terms of reliability, it hasn't gave any wrong result in 3 weeks of testing.

Side notes: 1: I don't have access to AD username and password hence using GC. 2: Groups can be created in any domain but with in same forest. 3: Group can have users from various domains as well as groups.

thanks

KA

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
    static extern int CheckTokenMembership(int TokenHandle, byte[] PSID, out bool IsMember);

   [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
    static extern bool IsValidSid(byte[] PSID);


private bool Authenticate(XmlNodeList XmlNodeGroups)
    {
        bool result = false;
        try
        {
            Dictionary<string, List<string>> Groups = GetGroups(XmlNodeGroups);
            //search global catalog and get SID of the group
            Byte[] sid = null;
            foreach (string groupName in Groups.Keys)
            {
                using (DirectoryEntry entry = new DirectoryEntry("GC:"))
                {
                    IEnumerator ie = entry.Children.GetEnumerator();
                    ie.MoveNext();
                    using (DirectorySearcher ds = new DirectorySearcher((DirectoryEntry)ie.Current))
                    {
                        ds.Filter = string.Format("(&(|(sAMAccountName={0}))(objectClass=group))", groupName);  
                        using (SearchResultCollection resColl = ds.FindAll())
                        {
                            if (resColl.Count > 0)
                            {
                                ResultPropertyCollection resultPropColl = resColl[0].Properties;
                                sid = (byte[])resultPropColl["objectsid"][0];
                                if (sid == null || !IsValidSid(sid))
                                {
                                    // log message and continue to next group                                        continue;
                                }
                            }
                            else
                            {
                                  // log message and continue to next group                                    continue;
                            }
                        }

                        bool bIsMember = false;
                        if (CheckTokenMembership(0, sid, out bIsMember) == 0)
                        {
                               // log message and initiate fall back....... use Legacy
                            result = CheckMemberOf(XmlNodeGroups, _CurrentIdentity);
                            break;
                        }
                        else
                        {
                            result = bIsMember ? true : false;
                            if (result)
                            {
                                // debug message                                    break;
                            }
                            else
                            {
                               // debug message
                            }
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            // log exception message and initiate fall back....... use Legacy
            result = CheckMemberOf(XmlNodeGroups, _CurrentIdentity);
        }
        return result;
    }</code>
도움이 되었습니까?

해결책

Are you on .NET 3.5 ? If so, check out the MSDN magazine article Managing Directory Security Principals in the .NET Framework 3.5. It shows just how much easier things have become when it comes to users and groups in AD.

As for your requirement - you could

  • find the group in question
  • enumerate all its members
  • find if your given user is a member in that group

and all this can be done quite easily with the help of the System.DirectoryServices.AccountManagement namespace:

// establish a context - define a domain (NetBIOS style name),  
// or use the current one, when not specifying a specific domain
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);

// find the group in question
GroupPrincipal theGroup = GroupPrincipal.FindByIdentity(ctx, "nameOfGroup");

// recursively enumerate the members of the group; making the search
// recursive will also enumerate the members of any nested groups
PrincipalSearchResult<Principal> result = theGroup.GetMembers(true);

// find the user in the list of group members
UserPrincipal user = (result.FirstOrDefault(p => p.DisplayName == "Some Name") as UserPrincipal);

// if found --> user is member of this group, either directly or recursively
if(user != null)
{
     // do something with the user
}

다른 팁

I tried to use your code snippet above for the 3.5 framework and this line my compiler says it's incorrect:

    // find the user in the list of group members
    UserPrincipal user = (result.FirstOrDefault(p => p.DisplayName == adUser) as UserPrincipal);

Specifically the result.FirstOfDefault, it says that's not a valid option.

Thanks!

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top