如何获取特定用户的所有AD组?
我已经检查了这篇文章。但这并不能回答我的问题。我想要获取特定用户所属的所有活动目录组。
我编写了以下代码。但我无法继续进行,因为我不知道如何提供过滤器以及如何访问属性。
class Program
{
static void Main(string[] args)
{
DirectoryEntry de = new DirectoryEntry("LDAP://mydomain.com");
DirectorySearcher searcher = new DirectorySearcher(de);
searcher.Filter = "(&(ObjectClass=group))";
searcher.PropertiesToLoad.Add("distinguishedName");
searcher.PropertiesToLoad.Add("sAMAccountName");
searcher.PropertiesToLoad.Add("name");
searcher.PropertiesToLoad.Add("objectSid");
SearchResultCollection results = searcher.FindAll();
int i = 1;
foreach (SearchResult res in results)
{
Console.WriteLine("Result" + Convert.ToString(i++));
DisplayProperties("distinguishedName", res);
DisplayProperties("sAMAccouontName", res);
DisplayProperties("name", res);
DisplayProperties("objectSid", res);
Console.WriteLine();
}
Console.ReadKey();
}
private static void DisplayProperties(string property, SearchResult res)
{
Console.WriteLine("\t" + property);
ResultPropertyValueCollection col = res.Properties[property];
foreach (object o in col)
{
Console.WriteLine("\t\t" + o.ToString());
}
}
}
有什么想法吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
您应该使用 System.DirectoryServices.AccountManagement。这容易多了。这是一个很好的代码项目文章,为您提供了所有内容的概述该 DLL 中的类。
正如您所指出的,您当前的方法没有找到主要群体。事实上,情况比你想象的要糟糕得多。还有一些情况不起作用,例如来自另一个域的域本地组。您可以在此处查看详细信息。如果您切换到使用 System.DirectoryServices.AccountManagement,代码如下所示。以下代码可以找到该用户分配到的直接组,其中包括主要组。
You should use System.DirectoryServices.AccountManagement. It's much easier. Here is a nice code project article giving you an overview on all the classes in this DLL.
As you pointed out, your current approach doesn't find out the primary group. Actually, it's much worse than you thought. There are some more cases that it doesn't work, like the domain local group from another domain. You can check here for details. Here is how the code looks like if you switch to use System.DirectoryServices.AccountManagement. The following code can find the immediate groups this user assigned to, which includes the primary group.
使用 tokenGroups:
注意:这只能获取安全组
Use tokenGroups:
Note: this only gets security groups
只需查询“memberOf”属性并迭代返回,例如:
这只是将组名称填充到 groupNames 字符串中,以管道分隔,但是当您旋转时,您可以对它们执行任何您想要的操作
Just query the "memberOf" property and iterate though the return, example:
This just stuffs the group names into the groupNames string, pipe delimited, but when you spin through you can do whatever you want with them
这是我列出特定可分辨名称的所有组(直接和间接)的方式:
字符串 1.2.840.113556.1.4.1941 指定 LDAP_MATCHING_RULE_IN_CHAIN。
此规则仅限于应用于 DN 的过滤器。这是一个特殊的“扩展”匹配运算符,它沿着对象中的祖先链一直走到根,直到找到匹配项。
此方法比 UserPrincipal.GetGroups() 方法在我的测试中。
注意:此方法或 GetGroups() 方法不会返回主要组(通常是域用户)。为了也获取主要组名称,我已经确认此方法有效。
此外,我发现了这个 列表LDAP 过滤器非常有用。
This is how I list all the groups (direct and indirect) for a specific Distinguished Name:
The string 1.2.840.113556.1.4.1941 specifies LDAP_MATCHING_RULE_IN_CHAIN.
This rule is limited to filters that apply to the DN. This is a special "extended" match operator that walks the chain of ancestry in objects all the way to the root until it finds a match.
This method is 25 times faster than the UserPrincipal.GetGroups() method in my testing.
Note: The primary group (typically Domain Users) is not returned by this or GetGroups() method. To get the primary group name too, I've confirmed this method works.
Additionally, I found this list of LDAP filters extremely useful.
这段代码运行得更快(比我以前的版本快两个 1.5):
This code works even faster (two 1.5 faster than my previous version):
以下示例来自代码项目文章,(几乎)通过 C# 实现 Active Directory 中的所有内容:
只需使用 调用 Groups 方法即可用户的专有名称,并传入 bool 标志来指示是否要在生成的 ArrayList 中包含嵌套/子组成员身份:
如果您需要在 .NET 中进行任何严格级别的 Active Directory 编程,我强烈建议推荐书签&回顾我上面提到的代码项目文章。
The following example is from the Code Project article, (Almost) Everything In Active Directory via C#:
Just call the Groups method with the Distinguished Name for the user, and pass in the bool flag to indicate if you want to include nested / child groups memberships in your resulting ArrayList:
If you need to do any serious level of Active Directory programming in .NET I highly recommend bookmarking & reviewing the Code Project article I mentioned above.
以下是对我有用的代码:
我在 200 次循环中针对使用 AttributeValuesMultiString 递归方法的代码测量了它的性能;并且运行速度提高了 1.3 倍。
可能是因为我们的 AD 设置。不过,两个片段给出了相同的结果。
Here is the code that worked for me:
I measured it's performance in a loop of 200 runs against the code that uses the
AttributeValuesMultiString
recursive method; and it worked 1.3 times faster.It might be so because of our AD settings. Both snippets gave the same result though.
我想说的是,Microsoft LDAP 有一些特殊的方法来递归搜索用户的所有成员资格。
您可以为“成员”属性指定的匹配规则。特别是,使用 Microsoft 专有的 LDAP_MATCHING_RULE_IN_CHAIN “member”属性的规则允许递归/嵌套成员资格搜索。当您将其添加到成员属性之后时,将使用该规则。前任。 (member:1.2.840.113556.1.4.1941:= XXXXX)
对于与帐户相同的域,过滤器可以使用而不是 Accounts DistinguishedName 属性,如果需要,可以非常方便地使用跨域。然而,您似乎需要使用ForeignSecurityPrincipal ;因为它不会解析您的 SID,因为它显示为 标记不考虑ForeignSecurityPrincipal 对象类型。您也可以使用ForeignSecurityPrincipal DistinguishedName。
利用这些知识,您可以通过 LDAP 查询那些难以获取成员资格的成员,例如帐户所属的“域本地”组,但除非您查看该组的成员,否则您不会知道用户是否是成员。
替换您想要检索其所有组成员身份的用户的 SID 后,请随意尝试这些 LDAP 查询。我认为这与 PowerShell 命令 Get-ADPrincipalGroupMembership 在幕后使用。该命令指出“如果要搜索另一个域中的本地组,请使用 ResourceContextServer 参数指定另一个域中的备用服务器。”
如果您足够熟悉 C# 和 Active Directory,您应该知道如何使用提供的 LDAP 查询执行 LDAP 搜索。
其他文档:
I would like to say that Microsoft LDAP has some special ways to search recursively for all of memberships of a user.
The Matching Rule you can specify for the "member" attribute. In particular, using the Microsoft Exclusive LDAP_MATCHING_RULE_IN_CHAIN rule for "member" attribute allows recursive/nested membership searching. The rule is used when you add it after the member attribute. Ex. (member:1.2.840.113556.1.4.1941:= XXXXX )
For the same Domain as the Account, The filter can use <SID=S-1-5-21-XXXXXXXXXXXXXXXXXXXXXXX> instead of an Accounts DistinguishedName attribute which is very handy to use cross domain if needed. HOWEVER it appears you need to use the ForeignSecurityPrincipal <GUID=YYYY> as it will not resolve your SID as it appears the <SID=> tag does not consider ForeignSecurityPrincipal object type. You can use the ForeignSecurityPrincipal DistinguishedName as well.
Using this knowledge, you can LDAP query those hard to get memberships, such as the "Domain Local" groups an Account is a member of but unless you looked at the members of the group, you wouldn't know if user was a member.
Feel free to try these LDAP queries after substituting the SID of a user you want to retrieve all group memberships of. I figure this is similiar if not the same query as what the PowerShell Command Get-ADPrincipalGroupMembership uses behind the scenes. The command states "If you want to search for local groups in another domain, use the ResourceContextServer parameter to specify the alternate server in the other domain."
If you are familiar enough with C# and Active Directory, you should know how to perform an LDAP search using the LDAP queries provided.
Additional Documentation:
如果您有一个带有用户名和密码的 LDAP 连接来连接到 Active Directory,以下是我用于正确连接的代码:
If you have a LDAP connection with a username and password to connect to Active Directory, here is the code I used to connect properly:
有一个基于 curtisk 响应的助手类:
there is a helpers class based in curtisk response: