Это, безусловно, ошибка в коде .NET, и я отвечу на ваш вопрос, но, как я уже упоминал в другом вашем вопросе, мартовское обновление не будет «разрешать только безопасные вызовы с использованием LDAPS». Обычный порт LDAP 389 будет работать после этого обновления. Я не видел никаких доказательств того, что они когда-либо планировали его отключить.
Но если вы хотите убедиться, что он никогда не использует порт 389, у вас не будет UserPrincipal
. Используйте DirectoryEntry
и/или DirectorySearcher
напрямую, что UserPrincipal
в любом случае использует в фоновом режиме. Это не первая обнаруженная мною ошибка в пространстве имен AccountManagement
.
Я написал статью о поиск всех групп пользователя, в котором есть пример кода для разных сценариев. Вам придется изменить любой случай, когда вы создаете новый объект DirectoryEntry
и указываете порт 636, например:
new DirectoryEntry("LDAP://example.com:636/CN=whatever,DC=example,DC=com")
На самом деле вы можете опустить доменное имя, если хотите (просто :636
вместо example.com:636
).
Один случай, который я не рассмотрел в этой статье, эквивалентен GetAuthorizationGroups
, то есть чтению атрибута tokenGroups
. Это дает вам список идентификаторов SID групп, который вы затем можете найти, чтобы найти имя группы. Вот метод, который сделает это:
private static IEnumerable<string> GetTokenGroups(DirectoryEntry de) {
var groupsFound = 0;
//retrieve only the tokenGroups attribute from the user
de.RefreshCache(new[] {"tokenGroups"});
while (true) {
var tokenGroups = de.Properties["tokenGroups"];
foreach (byte[] groupSidByte in tokenGroups) {
groupsFound++;
var groupSid = new SecurityIdentifier(groupSidByte, 0);
var groupDe = new DirectoryEntry($"LDAP://:{de.Options.PasswordPort}/<SID={groupSid}>");
groupDe.RefreshCache(new[] {"cn"});
yield return (string) groupDe.Properties["cn"].Value;
}
//AD only gives us 1000 or 1500 at a time (depending on the server version)
//so if we've hit that, go see if there are more
if (tokenGroups.Count != 1500 && tokenGroups.Count != 1000) break;
try {
de.RefreshCache(new[] {$"memberOf;range={groupsFound}-*"});
} catch (COMException e) {
if (e.ErrorCode == unchecked((int) 0x80072020)) break; //no more results
throw;
}
}
}
Это будет использовать любой порт, который вы использовали для создания объекта DirectoryEntry
, который вы передаете. Однако это прерывается, если в вашей среде более одного домена. В этом случае все может осложниться, если вы хотите всегда использовать порт 636.
person
Gabriel Luci
schedule
12.02.2020