检查Active Directory组成员身份

时间:2010-02-01 19:09:04

标签: spec#

如何重复群组以确定某个用户是否是某个群组的成员?

我知道我可以在WindowsPrincipal对象上使用IsInRole但由于某种原因它并不总是对我有用,它不会出错或抛出异常但只返回false。

我已将来自网络的代码放在一起,可以帮助我在可靠性方面改进它,它在3周的测试中没有给出任何错误的结果。

附注:1:我无法访问AD用户名和密码,因此使用GC。 2:可以在任何域中创建组,但在同一个林中。 3:群组可以拥有来自不同领域和群组的用户。

感谢

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>

2 个答案:

答案 0 :(得分:2)

您使用的是.NET 3.5吗?如果是这样,请查看MSDN杂志文章Managing Directory Security Principals in the .NET Framework 3.5。它显示了AD中的用户和群组变得容易多了。

至于你的要求 - 你可以

  • 找到有问题的小组
  • 枚举其所有成员
  • 查找您的指定用户是否是该群组中的成员

所有这一切都可以在System.DirectoryServices.AccountManagement命名空间的帮助下轻松完成:

// 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
}

答案 1 :(得分:0)

我尝试将上面的代码片段用于3.5框架,而我的编译器认为这行不正确:

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

具体来说就是result.FirstOfDefault,它说这不是一个有效的选项。

谢谢!