活动目录:获取用户所属的组

3
我希望找到一个用户所属的群组列表。我尝试了来自http://www.codeproject.com/KB/system/everythingInAD.aspx的几个解决方案,但没有结果。
这段代码给了我一个“true”,表示LDAP正在运行:
public static bool Exists(string objectPath)
{
    bool found = false;
    if (DirectoryEntry.Exists("LDAP://" + objectPath))
        found = true;
    return found;
}

谢谢,
更新 1:
public ArrayList Groups(string userDn, bool recursive)
{
    ArrayList groupMemberships = new ArrayList();
    return AttributeValuesMultiString("memberOf", "LDAP-Server",
        groupMemberships, recursive);
}

public ArrayList AttributeValuesMultiString(string attributeName,
string objectDn, ArrayList valuesCollection, bool recursive)
{
    DirectoryEntry ent = new DirectoryEntry(objectDn);
    PropertyValueCollection ValueCollection = ent.Properties[attributeName];
    IEnumerator en = ValueCollection.GetEnumerator();

    while (en.MoveNext())
    {
        if (en.Current != null)
        {
            if (!valuesCollection.Contains(en.Current.ToString()))
            {
                valuesCollection.Add(en.Current.ToString());
                if (recursive)
                {
                    AttributeValuesMultiString(attributeName, "LDAP://" +
                    en.Current.ToString(), valuesCollection, true);
                }
            }
        }
    }
    ent.Close();
    ent.Dispose();
    return valuesCollection;
}

我遇到了一个异常:

PropertyValueCollection ValueCollection = ent.Properties[attributeName];

"

未处理COMException异常

"

在你提供的文章中,有一个“获取用户组成员”的部分... 你试过了吗? - Paolo Tedesco
你能否发布一下你的代码,让我们看看哪里出了问题? - bartosz.lipinski
顺便说一下,在这种情况下,true的意思是对象存在,而不是LDAP正在运行。也许你应该获取更多关于LDAP和Active Directory的基础知识。 - Paolo Tedesco
在这里你会找到一个链接,指向另一个关于同样问题的帖子 (https://dev59.com/L2025IYBdhLWcg3wChSc#6289205)。 - JPBlanc
4个回答

8
在.NET 4中,您可以通过以下方式使用新的UserPrincipal类轻松实现此操作:UserPrincipal
using (PrincipalContext context = new PrincipalContext(ContextType.Domain))
{
    UserPrincipal user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, "your_login");
    foreach (var group in user.GetGroups())
    {
        Console.WriteLine(group.Name);
    }
}

您需要添加对System.DirectoryServices.AccountManagement的引用,以引入所需的类型。


在foreach行上发生错误:“服务器不可操作” 名称:domaineName - TheBoubou
也许您没有所需的权限? - Jakob Christensen
刚刚问了系统工程师,他说“不需要特殊权限才能阅读”。 - TheBoubou
如果您尝试使用以下代码,它是否有效:UserPrincipal user = UserPrincipal.Current - Jakob Christensen
那么你的设置肯定出了些问题。这可能会解释在尝试检索“memberof”值时出现初始错误的原因。 - Jakob Christensen
发生了异常。 - york

1
我在stackoverflow上找到了解决方案。connectionString的格式应该是这样的:
LDAP://domain.subdomain.com:389/DC=domain,DC=subdomain,DC=com

代码:

  public IList<string> GetGroupsByUser(string ldapConnectionString, string username)
        {
            IList<string> groupList = new List<string>();

            var identity = WindowsIdentity.GetCurrent().User;
            var allDomains = Forest.GetCurrentForest().Domains.Cast<Domain>();

            var allSearcher = allDomains.Select(domain =>
            {
                var searcher = new DirectorySearcher(new DirectoryEntry(ldapConnectionString));

                // Apply some filter to focus on only some specfic objects
                searcher.Filter = String.Format("(&(&(objectCategory=person)(objectClass=user)(name=*{0}*)))", username);
                return searcher;
            });

            var directoryEntriesFound = allSearcher
                .SelectMany(searcher => searcher.FindAll()
                    .Cast<SearchResult>()
                    .Select(result => result.GetDirectoryEntry()));

            var memberOf = directoryEntriesFound.Select(entry =>
            {
                using (entry)
                {
                    return new
                    {
                        Name = entry.Name,
                        GroupName = ((object[])entry.Properties["MemberOf"].Value).Select(obj => obj.ToString())
                    };
                }
            });

            foreach (var item in memberOf)
                foreach (var groupName in item.GroupName)
                    groupList.Add(groupName);

            return groupList;
        }

0

使用此代码替换您的版本。这将为您提供列表。与原始代码的区别在于使用了DirectorySearcher。

    public ArrayList AttributeValuesMultiString(string attributeName,
         string objectDn, ArrayList valuesCollection, bool recursive)
    {
        using (DirectoryEntry ent = new DirectoryEntry(objectDn))
        {
            using (DirectorySearcher searcher = new DirectorySearcher(ent))
            {
                searcher.PropertiesToLoad.Add(attributeName);
                var result = searcher.FindOne();
                ResultPropertyValueCollection ValueCollection = result.Properties[attributeName];
                IEnumerator en = ValueCollection.GetEnumerator();

                while (en.MoveNext())
                {
                    if (en.Current != null)
                    {
                        if (!valuesCollection.Contains(en.Current.ToString()))
                        {
                            valuesCollection.Add(en.Current.ToString());
                            if (recursive)
                            {
                                AttributeValuesMultiString(attributeName, "LDAP://" +
                                en.Current.ToString(), valuesCollection, true);
                            }
                        }
                    }
                }
            }
        }
        return valuesCollection;
    }

0

你确定上面的脚本是正确的并且能正常工作吗?我认为它可能无法考虑嵌套组成员,因此您可能无法获取用户所属所有组的完整集合。

您知道,一个用户可以是X组的成员,而X组反过来又可以是Y组的成员,因此结果该用户也将成为Y组的成员。

我认为上面提到的脚本可能无法扩展和枚举嵌套组成员。

如果您有兴趣获取用户所属的完整成员资格集,请考虑这个角度。

我相信还有一些其他关于确定组成员身份的问题。如果您有兴趣了解更多信息,可以在这里找到很好的讨论:

http://www.activedirsec.org/t39703252/why-is-it-so-hard-to-enumerate-nested-group-memberships-in-a/

我希望它会更容易,但事实并非如此 :-(


这是在很短的时间内你第三次发布了那个网站的链接。那是你自己的网站吗? - Andrew Barber

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接