【问题标题】:Slow AD group membership lookup缓慢的 AD 组成员资格查找
【发布时间】:2016-04-04 09:57:18
【问题描述】:

我有一些代码可以检查域用户是否是机器管理员组的成员:

public static bool ActiveDirectoryGroupMembershipOk(string userid, string groupName)
{
    using (PrincipalContext ctx = new PrincipalContext(ContextType.Machine, "my_pc_name"))
    {
        using (GroupPrincipal grp = GroupPrincipal.FindByIdentity(ctx, IdentityType.SamAccountName, "administrators"))
        {
            if (grp != null)
            {
                foreach (Principal p in grp.GetMembers(false))
                {
                    if (p is UserPrincipal && p.SamAccountName.Equals(userid, StringComparison.InvariantCultureIgnoreCase))
                    {
                        return true;
                    }
                }
            }
        }
    }
    return false;
}

它可以工作,但下面的代码行需要几秒钟才能完成:

using (GroupPrincipal grp = GroupPrincipal.FindByIdentity(ctx, IdentityType.SamAccountName, "administrators"))

有没有更快的方法来查找会员资格?

不知道重要不重要,但是userid是域用户,windows组在本地PC上。

【问题讨论】:

  • 根据我的经验,AD 总是很慢,所以我倾向于缓存结果。在你的情况下,我会使用一个类全局变量 grp 并调用 FindByidentity 一次
  • 我为每个用户这样做。所以这是我的第一个请求,这很慢。我刚刚阅读了一篇关于查看用户成员而不是组成员的不同帖子 - 这可能会更快。 Link 但我无法让该代码工作。

标签: c# active-directory ldap-query


【解决方案1】:

我发现不查找组中的用户而是检查用户的角色成员身份似乎更快。

这是比我的问题中的代码执行得更快的代码:

public static bool ActiveDirectoryGroupMembershipOk(string userid, string groupName)
{
    bool membershipOk = false;
    using (var pc = new PrincipalContext(ContextType.Machine, "my_pc_name"))
    {
        using (var p = Principal.FindByIdentity(pc, IdentityType.SamAccountName, userid))
        {
            // if user account exists, check the group membership
            if(p != null)
            {
                System.Security.Principal.WindowsIdentity wi = new System.Security.Principal.WindowsIdentity(userid);
                System.Security.Principal.WindowsPrincipal wp = new System.Security.Principal.WindowsPrincipal(wi);
                membershipOk = wp.IsInRole(groupName);
            }
        }
    }
    return membershipOk;
}

【讨论】:

    【解决方案2】:

    我仍然找到了一种更好的方法(假设是 AD 域),使用 Blonde 先生的部分答案:

    public static bool ActiveDirectoryGroupMembershipOk(String userid, String groupname)
    {
        PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
        UserPrincipal user = UserPrincipal.FindByIdentity(ctx, IdentityType.SamAccountName, userid);
        GroupPrincipal group = GroupPrincipal.FindByIdentity(ctx, IdentityType.SamAccountName, groupname);
    
        return user.IsMemberOf(group);
    }
    

    【讨论】: