Что лучше PrincipalContext или DirectoryEntry для создания пользователей в Active Directory C# - PullRequest
0 голосов
/ 28 апреля 2020

Нам нужно создать массовых пользователей в AD, используя C#. Ищете что-то, что имеет хорошие показатели. Я нашел 2 способа сделать это в Google.

  1. Использование PrincipleContext.
  2. Использование DirectoryEntry.

Интересно, что я должен use?

Попробовал некоторый код, используя DirectoryEntry, но я вижу, что могу установить пароль пользователя после commitChanges(), например:

    newUser.CommitChanges();  // Commit once before setting password
    newUser.Invoke("SetPassword", new object[] { "12345" });
    newUser.CommitChanges();

Почему мы должны зафиксировать дважды? Будет ли это иметь некоторое влияние на производительность?

Также, скажем, я должен назначить членство в группе для пользователя, и при назначении членства в группе произошло некоторое исключение, в этом случае, как откатить зафиксированные изменения до сих пор (т.е. создание пользователя)?

Просьба предложить.

1 Ответ

0 голосов
/ 28 апреля 2020

Таким образом, вы можете сделать все за один выстрел, но это немного сложно, и вы не можете использовать PrincipalContext, потому что это слишком высокий уровень.

Фактический атрибут, используемый для установки пароля, unicodePwd. Документация для этого показывает, как его нужно установить, а именно:

  1. Соединение должно быть безопасным.
  2. Пароль должен быть в UTF- 16 окружен кавычками, закодированными как «строка октетов» (в основном, байтовый массив).

Использование newUser.Invoke("SetPassword", new object[] { "12345" }); вызывает собственный метод Windows IADsUser::SetPassword, который обрабатывает все это для вас. Он находит любой безопасный метод и использует его для установки пароля. Но он может быть вызван только для существующей учетной записи.

Чтобы избежать этого, вы должны справиться со всем этим самостоятельно. Если вы можете управлять условием 1, тогда условие 2 легко, если вы знаете, как это сделать.

Есть несколько способов выполнить "безопасное" условие:

  1. Используя AuthenticationTypes.Sealing, чтобы сказать ему шифровать с использованием Kerberos. Если вы находитесь в той же сети, что и D C, то это самый простой способ.
var ou = new DirectoryEntry("LDAP://OU=Users,DC=example,DC=com", null, null, AuthenticationTypes.Sealing);
При использовании LDAP через SSL. Для этого вам просто нужно добавить :636 к имени домена, но также необходимо, чтобы D C использовал сертификат SSL, которому ваш компьютер действительно доверяет. Если он использует самозаверяющий сертификат, то это не удастся.
var ou = new DirectoryEntry("LDAP://example.com:636/OU=Users,DC=example,DC=com");

Как только у вас есть объект ou для подразделения, в котором вы хотите создать учетную запись, вы можете создать его:

var newUser = ou.Children.Add("CN=MyTestUser", "user");
newUser.Properties["samAccountName"].Value = "MyTestUser";
newUser.Properties["userPrincipalName"].Value = "MyTestUser@cihs.ad.gov.on.ca";
newUser.Properties["unicodePwd"].Value = Encoding.Unicode.GetBytes("\"MyPassword2020\"");
newUser.Properties["userAccountControl"].Value = 512; //NORMAL_ACCOUNT
newUser.CommitChanges();

Это все обязательные атрибуты для учетной записи. Я уверен, что вы захотите установить больше. Обратите внимание на странную кодировку пароля и то, что он заключен в кавычки. Установка userAccountControl обязательна, иначе она будет создана как отключенная.

Это то, что я только что узнал сегодня! Первоначально я собирался сказать вам, что это было невозможно, поскольку все эти годы я делал это в два этапа. Но я провел поиск и нашел этот , в котором был ключ. Также есть пример того, как это сделать с LdapConnection. Единственным преимуществом использования этого является то, что вам нужно использовать LDAPS, но с самоподписанным сертификатом, поскольку LdapConnection позволяет вам написать свой собственный метод проверки сертификата.

Если вы хотите немедленно добавить этот новый Пользователь в группу, убедитесь, что вы подключаетесь к группе в том же D C, где вы создали пользователя, так как другие контроллеры домена не будут знать о пользователе, пока не произойдет репликация. Это будет выглядеть примерно так:

var server = newUser.Options.GetCurrentServerName();
var group = new DirectoryEntry($"LDAP://{server}/CN=MyGroup,OU=Groups,DC=example,DC=com");

group.Properties["member"].Add(newUser.Properties["distinguishedName"].Value);
group.CommitChanges();
...