我有两个AD域:domain1和domain2。
我在domain1内创建了组GlobalGroup,并在GlobalGroup内添加了另一个组Domain1Group。
我有两个用户:user1иuser2和domain2中的Domain2Group组。
在domain1和domain2之间设置了双向信任。并在GlobalGroup中添加了Domain2Group。
User1是Domain1Group的成员,而user2是Domain2Group的成员。
所以现在我需要检查它们是否都是GlobalGroup的成员。
Here我找到了如何从另一个域中查找用户是否是某个组的成员。
我的功能(如下)对于user1完美地工作。对于user2,它返回false。
GroupPrincipal.GetMemebers(true)将返回user2,但是它非常慢(按分钟计算),我无法使用它。
我想念什么?是在代码中还是在域设置中?
代码示例:
private static bool IsUserInGroup(UserPrincipal user, DirectoryEntry group, bool recursive)
{
group.RefreshCache(new[] {"distinguishedName", "groupType"});
var recursiveFilter = recursive ? ":1.2.840.113556.1.4.1941:" : "";
var filter = string.Format("(member{0}={1})", recursiveFilter, user.DistinguishedName);
var groupDN = (string)group.Properties["distinguishedName"].Value;
if (((int)group.Properties["groupType"].Value & 8) == 0)
{
var groupDomainDN = groupDN.Substring(groupDN.IndexOf(",DC=", StringComparison.Ordinal));
filter = string.Format("(|{0}(member{1}=CN={2}, CN=ForeignSecurityPrincipals{3}))", filter, recursiveFilter, user.Sid, groupDomainDN);
}
var searcher = new DirectorySearcher
{
Filter = filter,
SearchRoot = group,
PageSize = 1,
SearchScope = SearchScope.Base
};
searcher.PropertiesToLoad.Add("cn");
return searcher.FindOne() != null;
}
答案 0 :(得分:2)
我是您找到的那篇文章的作者。 :)
您的父组的范围是什么?您将其称为GlobalGroup
,但是全局组不能具有来自其他域的成员。因此,它必须是通用的(如果两个域在同一个AD林中)或本地的域。在每种情况下,答案都会有所不同。
我将假定两个域不在同一林中,并且该组是“本地域”。
仅当外部用户是该组的直接成员时,代码才会返回true。
如果您使用该代码检查Domain2Group
是否是GlobalGroup
的成员,它将返回true
。但是,当您使用它来检查user2
是否为成员时,它并没有在Domain2Group
内查看用户是否在那里。
这是我应该解决的问题,因此我更新了文章中的代码。我们可以使用用户的tokenGroups
属性来获取用户所在的所有组的递归列表。这将为我们提供SID列表。因此,我们可以使用它在另一个域的父组中查找那些组。
我看到您将user
对象作为UserPrincipal
。要将其传递给此方法,可以使用user.GetUnderlyingObject()
,如下所示:
IsUserInGroup((DirectoryEntry) user.GetUnderlyingObject(), group, true)
这是更新的方法:
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;
}