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

时间:2011-09-05 07:56:41

标签: c# active-directory

我想查找用户所在的组列表。我试过几个解决方案 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未处理”

4 个答案:

答案 0 :(得分:8)

在.NET 4中,您可以通过以下方式使用新的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的引用才能引入所需类型。

答案 1 :(得分: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;
        }

答案 2 :(得分:0)

您确定以上脚本是否正确并且正常运行?我认为它不会考虑嵌套的组成员资格,因此我担心您可能无法获得用户所属的所有组的完整集合。

您看,用户可以是X组的成员,而X组又可以成为Y组的成员,因此用户也可以成为Y组的成员。

我认为上面引用的脚本可能无法展开和枚举嵌套的组成员资格。

如果您有兴趣获得用户所属的全套会员资格,我建议您也考虑这个角度。

我认为还有一些与确定群组成员身份有关的其他问题。如果您有兴趣了解更多信息,请在此处进行讨论:

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

我希望它更容易,但似乎并非如此: - (

答案 3 :(得分: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;
    }