System.DirectoryServices.Protocols.AddRequest c# 创建用户代码示例
使用 System.DirectoryServices.Protocols (S.DS.P) 命名空间是一个比传统的 System.DirectoryServices (DirectoryEntry) 更底层、更符合 LDAP 标准且性能通常更好的方法。
以下是使用 AddRequest 类在 C# 中创建 Active Directory 用户的完整代码示例。
核心步骤
- 建立
LdapConnection。 - 创建
AddRequest对象并指定 Distinguished Name (DN)。 - 添加必要的属性(
objectClass,sAMAccountName等)。 - 发送请求。
代码示例
using System;
using System.Net;
using System.Text;
using System.DirectoryServices.Protocols;
namespace LdapUserCreation
{
class Program
{
static void Main(string[] args)
{
// 配置信息
string ldapServer = "192.168.1.100"; // 域控制器 IP 或域名
string domain = "example.com";
string adminUser = "Administrator";
string adminPassword = "YourAdminPassword";
// 新用户的 Distinguished Name (DN) - 请根据实际 OU 结构修改
string newUserDN = "CN=John Doe,OU=Employees,DC=example,DC=com";
try
{
// 1. 设置连接凭据
var credential = new NetworkCredential(adminUser, adminPassword, domain);
var serverId = new LdapDirectoryIdentifier(ldapServer);
using (var connection = new LdapConnection(serverId, credential))
{
// 设置 LDAP 版本为 3 (现代标准)
connection.SessionOptions.ProtocolVersion = 3;
// 如果要设置密码,通常需要 SSL (端口 636)
// connection.SessionOptions.SecureSocketLayer = true;
connection.Bind(); // 绑定/登录
Console.WriteLine("已连接到 LDAP 服务器。");
// 2. 创建 AddRequest
var addRequest = new AddRequest(newUserDN);
// 3. 添加必要的属性
// objectClass: 定义这是一个用户对象
addRequest.Attributes.Add(new DirectoryAttribute("objectClass", new string[] { "top", "person", "organizationalPerson", "user" }));
// sAMAccountName: 旧版登录名 (必填)
addRequest.Attributes.Add(new DirectoryAttribute("sAMAccountName", "jdoe"));
// userPrincipalName: UPN 登录名 (建议填写)
addRequest.Attributes.Add(new DirectoryAttribute("userPrincipalName", "[email protected]"));
// givenName & sn: 名和姓
addRequest.Attributes.Add(new DirectoryAttribute("givenName", "John"));
addRequest.Attributes.Add(new DirectoryAttribute("sn", "Doe"));
addRequest.Attributes.Add(new DirectoryAttribute("displayName", "John Doe"));
// --- 密码与账户激活 (高级选项) ---
// 注意:Active Directory 通常要求在 SSL/TLS (LDAPS) 连接下才能设置 unicodePwd。
// 此外,为了启用账户,需要设置 userAccountControl。
// 设置密码 (必须是 Unicode 且包含双引号)
/*
string password = "\"NewUserPassword123!\"";
byte[] passwordBytes = Encoding.Unicode.GetBytes(password);
addRequest.Attributes.Add(new DirectoryAttribute("unicodePwd", passwordBytes));
// 启用账户 (NORMAL_ACCOUNT = 512)
// 默认创建的用户是禁用的,如果设置了密码,可以将此值设为 512
addRequest.Attributes.Add(new DirectoryAttribute("userAccountControl", "512"));
*/
// -------------------------------------
// 4. 发送请求
Console.WriteLine($"正在创建用户: {newUserDN} ...");
AddResponse response = (AddResponse)connection.SendRequest(addRequest);
if (response.ResultCode == ResultCode.Success)
{
Console.WriteLine("用户创建成功!");
}
else
{
Console.WriteLine($"创建虽然完成,但返回代码为: {response.ResultCode}");
}
}
}
catch (DirectoryOperationException ex)
{
// 捕获 LDAP 特定错误 (如用户已存在、权限不足)
Console.WriteLine($"LDAP 错误: {ex.Message}");
if (ex.Response != null)
{
Console.WriteLine($"服务器返回代码: {ex.Response.ResultCode}");
Console.WriteLine($"错误消息: {ex.Response.ErrorMessage}");
}
}
catch (Exception ex)
{
Console.WriteLine($"发生常规错误: {ex.Message}");
}
}
}
}
关键点解析
-
objectClass (对象类):
Active Directory 中的用户通常需要包含以下层级:top→person→organizationalPerson→user。不添加这些可能会导致创建的对象类型不正确。 -
LDAP 连接与端口:
默认情况下,LdapConnection使用端口 389 (非加密)。- 如果你只创建用户对象(不设置密码),389 端口通常可以工作。
- 如果你要设置密码 (
unicodePwd):AD 默认安全策略要求连接必须加密(LDAPS,端口 636)。你需要在连接选项中设置SecureSocketLayer = true,并确保证书受信任。
-
userAccountControl (用户账户控制):
- 如果不指定此属性,用户创建后默认是 禁用 (Disabled) 状态。
- 要启用用户,通常需要设置值为
512(NORMAL_ACCOUNT)。 - 注意:在没有设置有效密码之前,AD 通常不允许你启用账户。
-
密码编码:
unicodePwd属性有着非常严格的格式要求:- 必须使用 UTF-16LE (
Encoding.Unicode) 编码。 - 密码字符串必须用双引号括起来(例如
"password")。
- 必须使用 UTF-16LE (
常见错误处理
在使用 AddRequest 时最常遇到的错误是 DirectoryOperationException:
- ObjectExists (68): DN 已经存在。
- ConstraintViolation (19): 密码不符合复杂性要求,或者在非 SSL 连接上尝试设置密码。
- InsufficientAccessRights (50): 绑定的账号没有在指定 OU 创建用户的权限。