Я автор той статьи, которую вы нашли.:)
Каков охват вашей родительской группы?Вы называете это GlobalGroup
, но у глобальных групп не может быть участников из других доменов.Таким образом, он должен быть универсальным (если два домена находятся в одном лесу AD) или локальным.Ответ будет отличаться в каждом случае.
Я предполагаю, что два домена не находятся в одном и том же лесу, а группа - Локальный домен.
Код вернет только значение true, если внешний пользовательявляется прямым членом группы.
Если вы используете этот код, чтобы проверить, является ли Domain2Group
членом GlobalGroup
, он вернет true
.Но когда вы используете его, чтобы проверить, является ли user2
членом, он не заглядывает внутрь Domain2Group
, чтобы увидеть, есть ли там пользователь.
Это то, к чему я должен обратиться, поэтому я обновил код вмоя статьяМы можем использовать атрибут tokenGroups
пользователя, чтобы получить рекурсивный список всех групп, в которых он находится. Это дает нам список идентификаторов безопасности.Таким образом, мы можем использовать это для поиска любой из этих групп в нашей родительской группе в другом домене.
Я вижу, что у вас есть 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;
}