You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Python在Microsoft AD中创建有效用户遇阻求助

Python 创建 Microsoft Active Directory 用户失败问题排查与解决

问题描述

尝试使用python-ldap模块创建AD用户,执行conn.add_s()时出现错误:

"errorMessage": "{'msgtype': 105, 'msgid': 2, 'result': 53, 'desc': 'Server is unwilling to perform', 'ctrls': [], 'info': '00000529: SvcErr: DSID-031A124C, problem 5003 (WILL_NOT_PERFORM), data 0\n'}", "errorType": "UNWILLING_TO_PERFORM"

原代码如下:

conn = ldap.initialize('ldap://' + ldap_hostname)
conn.protocol_version = 3 
conn.set_option(ldap.OPT_REFERRALS, 0)
conn.simple_bind_s(ldap_admin_dn, ldap_admin_pw)

attrs = {}
attrs['objectClass'] = ['top'.encode('utf-8'), 'person'.encode('utf-8'), 'organizationalPerson'.encode('utf-8'), 'user'.encode('utf-8')]
attrs['cn'] = "Test User".encode("utf-8")
attrs['userPrincipalName'] = "testuser@domain.com".encode("utf-8")
attrs['displayName'] = "Test User".encode("utf-8")
attrs['givenName'] = "Test".encode("utf-8")
attrs['sn'] = "User".encode("utf-8")
attrs['sAMAccountName'] = "testuser".encode("utf-8")
attrs['mail'] = "testuser@domain.com".encode("utf-8")
attrs['primaryGroupID'] = "513".encode("utf-8")

# Convert our dict to nice syntax for the add-function using
ldif = modlist.addModlist(attrs)

# Set up user dn
user_cn = "Test User"
user_dn = "CN={},{}".format(user_cn, ldap_users_ou_dn)

# Create user
conn.add_s(user_dn, ldif)

# Set initial password
password_value = "LaLaLaLaLa123123123!".encode('utf-16-le')

add_pass = [(ldap.MOD_REPLACE, 'unicodePwd', [password_value])]
conn.modify_s(user_dn, add_pass)

# Set user account control
mod_acct = [(ldap.MOD_REPLACE, 'userAccountControl', '66048')]
conn.modify_s(user_dn, mod_acct)

问题根源

  1. 连接方式错误:Microsoft AD要求敏感操作(如设置密码、写入用户数据)必须通过LDAPS(ldaps://)连接,非LDAPS连接会被服务器拒绝。
  2. 属性编码冗余:python-ldap会自动处理字符串的UTF-8编码,手动调用.encode('utf-8')会导致属性值格式异常,触发服务器校验失败。
  3. 密码格式错误:设置unicodePwd时,密码必须用双引号包裹后再编码为UTF-16-LE,原代码缺少双引号,后续修改密码也会失败。
  4. 冗余属性设置:primaryGroupID默认值就是513(Domain Users),无需手动指定;userAccountControl可以在创建用户时直接设置,无需后续修改。

修复后的可运行代码

import ldap
from ldap import modlist

# 配置参数
ldap_hostname = "your-ad-server.domain.com"
ldap_admin_dn = "CN=Admin User,OU=Admins,DC=domain,DC=com"
ldap_admin_pw = "AdminPassword123!"
ldap_users_ou_dn = "OU=Users,DC=domain,DC=com"

# 初始化LDAPS连接
conn = ldap.initialize(f'ldaps://{ldap_hostname}:636')
conn.protocol_version = ldap.VERSION3
conn.set_option(ldap.OPT_REFERRALS, 0)
# 测试环境临时禁用证书验证,生产环境请配置可信SSL证书
conn.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
conn.start_tls_s()

# 绑定管理员账号
conn.simple_bind_s(ldap_admin_dn, ldap_admin_pw)

# 构造用户属性(无需手动编码)
user_attrs = {
    'objectClass': ['top', 'person', 'organizationalPerson', 'user'],
    'cn': 'Test User',
    'userPrincipalName': 'testuser@domain.com',
    'displayName': 'Test User',
    'givenName': 'Test',
    'sn': 'User',
    'sAMAccountName': 'testuser',
    'mail': 'testuser@domain.com',
    # 创建时直接设置用户为启用状态(66048 = NORMAL_ACCOUNT + DONT_EXPIRE_PASSWORD)
    'userAccountControl': '66048'
}

# 转换为LDAP添加格式
ldif = modlist.addModlist(user_attrs)

# 构造用户DN
user_dn = f'CN=Test User,{ldap_users_ou_dn}'

# 创建用户
conn.add_s(user_dn, ldif)

# 设置用户密码:必须用双引号包裹,再转UTF-16-LE
password = '"LaLaLaLaLa123123123!"'
unicode_pwd = password.encode('utf-16-le')
mod_pwd = [(ldap.MOD_REPLACE, 'unicodePwd', unicode_pwd)]
conn.modify_s(user_dn, mod_pwd)

# 解绑连接
conn.unbind_s()

关键修改说明

  • 改用LDAPS连接:使用ldaps://并指定默认端口636,确保安全连接;生产环境需配置合法SSL证书,移除证书禁用选项。
  • 移除手动编码:所有属性值直接传入字符串,由python-ldap自动处理编码逻辑。
  • 修正密码格式:密码用双引号包裹后再编码为UTF-16-LE,完全符合AD的unicodePwd格式要求。
  • 优化属性设置:创建用户时直接指定userAccountControl为启用状态,省略冗余的primaryGroupID配置。

内容的提问来源于stack exchange,提问作者Marius Mitrofan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 15:40:00