在 Active Directory C# 中创建用户时,哪个更好 PrincipalContext 或 DirectoryEntry

Which is better PrincipalContext or DirectoryEntry for user creation in Active Directory C#

我们需要使用 C# 在 AD 中创建批量用户。寻找具有良好性能的东西。我在 Google.

上找到了 2 种方法
  1. 使用 PrincipleContext.
  2. 使用 DirectoryEntry.

想知道我应该使用什么?

使用 DirectoryEntry 尝试了一些代码,但我发现我可以在 commitChanges() 之后设置用户密码,例如:

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

为什么我们需要提交两次?它会对性能产生一些影响吗?

此外,假设我也必须为用户分配组成员身份,并且在分配组成员身份时发生了一些异常,在这种情况下如何回滚到目前为止提交的更改(即用户创建)?

请多多指教。

所以你可以一次搞定,但是有点复杂,你不能用PrincipalContext搞定,因为那太高了水平。

用于设置密码的实际属性是unicodePwddocumentation for that表示需要如何设置,即:

  1. 连接必须安全。
  2. 密码必须是 UTF-16 格式,用引号括起来,编码为 "octet string"(基本上是字节数组)。

使用 newUser.Invoke("SetPassword", new object[] { "12345" }); 调用本机 Windows IADsUser::SetPassword 方法,它会为您处理所有这些。它会找到任何可用的安全方法并使用它来为您设置密码。但它只能在现有帐户上调用。

为避免这种情况,您必须自己处理这一切。如果您可以处理条件 1,那么一旦您知道如何去做,条件 2 就很容易了。

有几种方法可以满足 "secure" 条件:

  1. 通过使用 AuthenticationTypes.Sealing 告诉它使用 Kerberos 加密。如果您与 DC 在同一网络上,那么这是最简单的。
var ou = new DirectoryEntry("LDAP://OU=Users,DC=example,DC=com", null, null, AuthenticationTypes.Sealing);
  1. 通过使用基于 SSL 的 LDAP。为此,您只需在域名中添加 :636 即可,但它还需要 DC 使用您的计算机真正信任的 SSL 证书。如果它使用自签名证书,那么这将失败。
var ou = new DirectoryEntry("LDAP://example.com:636/OU=Users,DC=example,DC=com");

为要在其中创建帐户的 OU 获得 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,否则将创建为禁用。

这其实是我今天刚学到的东西!我本来打算告诉你这是不可能的,因为这些年来我一直分两步做。但我做了一些搜索并找到了 this,其中有密钥。它还有一个示例,说明如何使用 LdapConnection 执行此操作。使用它的唯一好处是如果您需要使用 LDAPS,但使用自签名证书,因为 LdapConnection 允许您编写自己的证书验证方法。

如果您想立即将这个新用户添加到一个组,请确保您连接到创建该用户所在的同一 DC 上的组,因为其他 DC 在复制发生之前不会知道该用户。它看起来像这样:

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();