C# 检查AD组是否是另一个组的成员(递归)
想象一下我有一个结构C# 检查AD组是否是另一个组的成员(递归),c#,active-directory,active-directory-group,activedirectorymembership,C#,Active Directory,Active Directory Group,Activedirectorymembership,想象一下我有一个结构 RootGroup您最好不要为此使用GroupPrincipal。实际上,广告有一种内置的方式来进行这种搜索,比任何GroupPrincipal方法都要快得多。您可以直接使用DirectoryEntry和DirectorySearcher来使用它(这就是GroupPrincipal和PrincipalSearcher在幕后使用的内容) 我写了一篇关于计算用户是否是特定组的成员的文章,但它同样适用于组。我有一个可以用于此目的的: private static bool IsU
RootGroup您最好不要为此使用GroupPrincipal
。实际上,广告有一种内置的方式来进行这种搜索,比任何GroupPrincipal
方法都要快得多。您可以直接使用DirectoryEntry
和DirectorySearcher
来使用它(这就是GroupPrincipal
和PrincipalSearcher
在幕后使用的内容)
我写了一篇关于计算用户是否是特定组的成员的文章,但它同样适用于组。我有一个可以用于此目的的:
private static bool IsUserInGroup(DirectoryEntry user, DirectoryEntry group, bool recursive) {
//fetch the attributes we're going to need
user.RefreshCache(new [] {"distinguishedName", "objectSid"});
group.RefreshCache(new [] {"distinguishedName", "groupType"});
//This magic number tells AD to look for the user recursively through any nested groups
var recursiveFilter = recursive ? ":1.2.840.113556.1.4.1941:" : "";
var userDn = (string) user.Properties["distinguishedName"].Value;
var groupDn = (string) group.Properties["distinguishedName"].Value;
var filter = $"(member{recursiveFilter}={userDn})";
if (((int) group.Properties["groupType"].Value & 8) == 0) {
var groupDomainDn = groupDn.Substring(
groupDn.IndexOf(",DC=", StringComparison.Ordinal));
var userDomainDn = userDn.Substring(
userDn.IndexOf(",DC=", StringComparison.Ordinal));
if (groupDomainDn != userDomainDn) {
//It's a Domain Local group, and the user and group are on
//different domains, so the account might show up as a Foreign
//Security Principal. So construct a list of SID's that could
//appear in the group for this user
var fspFilters = new StringBuilder();
var userSid =
new SecurityIdentifier((byte[]) user.Properties["objectSid"].Value, 0);
fspFilters.Append(
$"(member{recursiveFilter}=CN={userSid},CN=ForeignSecurityPrincipals{groupDomainDn})");
if (recursive) {
//Any of the groups the user is in could show up as an FSP,
//so we need to check for them all
user.RefreshCache(new [] {"tokenGroupsGlobalAndUniversal"});
var tokenGroups = user.Properties["tokenGroupsGlobalAndUniversal"];
foreach (byte[] token in tokenGroups) {
var groupSid = new SecurityIdentifier(token, 0);
fspFilters.Append(
$"(member{recursiveFilter}=CN={groupSid},CN=ForeignSecurityPrincipals{groupDomainDn})");
}
}
filter = $"(|{filter}{fspFilters})";
}
}
var searcher = new DirectorySearcher {
Filter = filter,
SearchRoot = group,
PageSize = 1, //we're only looking for one object
SearchScope = SearchScope.Base
};
searcher.PropertiesToLoad.Add("cn"); //just so it doesn't load every property
return searcher.FindOne() != null;
}
此方法还处理用户
(或您的子组)位于根组的外部受信任域上的情况。这可能是你不得不担心的事情,也可能不是
只需将DirectoryEntry
作为user
参数传递给Group100
。大概是这样的:
var isMemberOf = IsUserInGroup(
new DirectoryEntry($"LDAP://{userOrGroupDistinguishedName}"),
new DirectoryEntry($"LDAP://{groupMembershipDistinguishedName}"),
true);
对于递归搜索(当您传递recursive
参数的true
时),它使用链中的LDAP\u匹配\u规则\u“匹配规则OID”(如上所述):
此规则仅限于应用于DN的筛选器。这是一个特殊的“扩展”匹配操作符,它沿着对象中的祖先链一直走到根,直到找到匹配
谢谢你的回答。。。在哪里可以找到有关这些神奇字符串的文档,如:1.2.840.113556.1.4.1941:
(在页面中搜索“LDAP\u匹配\u规则\u链”)