C# AddRequest 创建 AD 用户示例

System.DirectoryServices.Protocols.AddRequest c# 创建用户代码示例

使用 System.DirectoryServices.Protocols (S.DS.P) 命名空间是一个比传统的 System.DirectoryServices (DirectoryEntry) 更底层、更符合 LDAP 标准且性能通常更好的方法。

以下是使用 AddRequest 类在 C# 中创建 Active Directory 用户的完整代码示例。

核心步骤

  1. 建立 LdapConnection
  2. 创建 AddRequest 对象并指定 Distinguished Name (DN)
  3. 添加必要的属性(objectClass, sAMAccountName 等)。
  4. 发送请求。

代码示例

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}");
            }
        }
    }
}

关键点解析

  1. objectClass (对象类):
    Active Directory 中的用户通常需要包含以下层级:toppersonorganizationalPersonuser。不添加这些可能会导致创建的对象类型不正确。

  2. LDAP 连接与端口:
    默认情况下,LdapConnection 使用端口 389 (非加密)。

    • 如果你只创建用户对象(不设置密码),389 端口通常可以工作。
    • 如果你要设置密码 (unicodePwd):AD 默认安全策略要求连接必须加密(LDAPS,端口 636)。你需要在连接选项中设置 SecureSocketLayer = true,并确保证书受信任。
  3. userAccountControl (用户账户控制):

    • 如果不指定此属性,用户创建后默认是 禁用 (Disabled) 状态。
    • 要启用用户,通常需要设置值为 512 (NORMAL_ACCOUNT)。
    • 注意:在没有设置有效密码之前,AD 通常不允许你启用账户。
  4. 密码编码:
    unicodePwd 属性有着非常严格的格式要求:

    • 必须使用 UTF-16LE (Encoding.Unicode) 编码。
    • 密码字符串必须用双引号括起来(例如 "password")。

常见错误处理

在使用 AddRequest 时最常遇到的错误是 DirectoryOperationException

  • ObjectExists (68): DN 已经存在。
  • ConstraintViolation (19): 密码不符合复杂性要求,或者在非 SSL 连接上尝试设置密码。
  • InsufficientAccessRights (50): 绑定的账号没有在指定 OU 创建用户的权限。