如何更改 Windows Active Directory 和 LDS 用户密码通过 LDAP

适用于: Microsoft Windows Server 2003 Enterprise Edition (32-bit x86)Microsoft Windows Server 2003 Enterprise Edition for Itanium-based SystemsMicrosoft Windows Server 2003 Enterprise x64 Edition

本文应用到 Windows 2000。在 2010 年 7 月 13 日结束的 Windows 2000 支持。Windows 2000 支持的最终解决方案中心是规划迁移策略从 Windows 2000 的起始点。有关详细信息,请参阅Microsoft 支持生命周期策略

概要


您可以设置 Windows Active Directory 和 LDS 用户密码通过轻量目录访问协议 (LDAP) 提供某些限制。本文介绍如何设置或更改密码属性。

这些步骤也适用于 ADAM 和 LDS 用户和 userProxy 对象以相同的方式为与 AD 用户完成。

详细信息


密码将存储在 AD LDS 中unicodePwd属性的用户对象的数据库和。可以在有限的情况下写入此属性,但无法读取它。只能修改特性;无法创建对象上添加或通过搜索查询。

若要修改此属性,则客户端必须 128 位传输层安全 (TLS) / 安全套接字层 (SSL) 连接到服务器。只要满足最小密钥长度,则使用 NTLM 或 Kerberos 使用 SSP 创建会话密钥加密的会话也是可接受的。

此连接可能使用 TLS/SSL:
  • 该服务器必须拥有一个 128 位的 RSA 连接的服务器证书。
  • 客户端必须信任生成服务器证书的证书颁发机构 (CA)。
  • 客户端和服务器必须能够 128 位加密。


UnicodePwd属性的语法是八位字节字符串;但是,目录服务要求 (如表示的属性的名称),八位字节字符串将包含 UNICODE 字符串。这意味着,在 LDAP 中传递此属性的任何值必须是 BER 编码 (基本编码规则) 的 UNICODE 字符串作为一个八位字节字符串。此外,UNICODE 字符串必须开始和结束报价单中未包含所需的密码。

有两种可行的方法来修改的unicodePwd属性。第一种是类似于"用户更改密码"正常操作。在这种情况下,删除和添加操作,则必须包含修改请求。删除操作必须包含用引号括起来的当前密码。添加操作必须包含用引号括起来所需的新密码。

修改此属性的第二个办法是类似于管理员重置用户的密码。为此,客户端必须具有足够的权限来修改其他用户的密码的用户绑定。此修改请求应包含单个替换操作,使用新的所需密码用引号引起来。如果客户端具有足够的权限,此密码将成为新的密码,而不考虑旧密码是什么。

以下两个功能提供这些操作的示例:
ULONG ChangeUserPassword(WCHAR* pszUserDN, WCHAR* pszOldPassword,WCHAR* pszNewPassword)
{
ULONG err = 1;
LDAPMod modNewPassword;
LDAPMod modOldPassword;
LDAPMod *modEntry[3];
BERVAL newPwdBerVal;
BERVAL oldPwdBerVal;
BERVAL *newPwd_attr[2];
BERVAL *oldPwd_attr[2];
WCHAR pszNewPasswordWithQuotes[1024];
WCHAR pszOldPasswordWithQuotes[1024];

// Build an array of LDAPMod.

// For setting unicodePwd, this MUST be a double op.
modEntry[0] = &modOldPassword;
modEntry[1] = &modNewPassword;
modEntry[2] = NULL;

// Build mod struct for unicodePwd Add.
modNewPassword.mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES;
modNewPassword.mod_type =L"unicodePwd";
modNewPassword.mod_vals.modv_bvals = newPwd_attr;

// Build mod struct for unicodePwd Delete.
modOldPassword.mod_op = LDAP_MOD_DELETE | LDAP_MOD_BVALUES;
modOldPassword.mod_type =L"unicodePwd";
modOldPassword.mod_vals.modv_bvals = oldPwd_attr;


// Password will be single valued, so we only have one element.
newPwd_attr[0] = &newPwdBerVal;
newPwd_attr[1]= NULL;
oldPwd_attr[0] = &oldPwdBerVal;
oldPwd_attr[1]= NULL;


// Surround the passwords in quotes.
wsprintf(pszNewPasswordWithQuotes,L"\"%s\"",pszNewPassword);
wsprintf(pszOldPasswordWithQuotes,L"\"%s\"",pszOldPassword);

// Build the BER structures with the UNICODE passwords w/quotes.
newPwdBerVal.bv_len = wcslen(pszNewPasswordWithQuotes) * sizeof(WCHAR);
newPwdBerVal.bv_val = (char*)pszNewPasswordWithQuotes;
oldPwdBerVal.bv_len = wcslen(pszOldPasswordWithQuotes) * sizeof(WCHAR);
oldPwdBerVal.bv_val = (char*)pszOldPasswordWithQuotes;


// Perform single modify.
err = ldap_modify_s(ldapConnection,
pszUserDN,
modEntry
);

if (err == LDAP_SUCCESS )
wprintf(L"\nPassword succesfully changed!\n");
else
wprintf(L"\nPassword change failed!\n");

return err;
}

ULONG SetUserPassword(WCHAR* pszUserDN, WCHAR* pszPassword)
{
ULONG err = 1;
LDAPMod modPassword;
LDAPMod *modEntry[2];
BERVAL pwdBerVal;
BERVAL *pwd_attr[2];
WCHAR pszPasswordWithQuotes[1024];

// Build an array of LDAPMod.
// For setting unicodePwd, this MUST be a single op.
modEntry[0] = &modPassword;
modEntry[1] = NULL;

// Build mod struct for unicodePwd.
modPassword.mod_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
modPassword.mod_type =L"unicodePwd";
modPassword.mod_vals.modv_bvals = pwd_attr;

// Password will be single valued, so we only have one element.
pwd_attr[0] = &pwdBerVal;
pwd_attr[1]= NULL;

// Surround the password in quotes.
wsprintf(pszPasswordWithQuotes,L"\"%s\"",pszPassword);

// Build the BER structure with the UNICODE password.
pwdBerVal.bv_len = wcslen(pszPasswordWithQuotes) * sizeof(WCHAR);
pwdBerVal.bv_val = (char*)pszPasswordWithQuotes;


// Perform single modify.
err = ldap_modify_s(ldapConnection,
pszUserDN,
modEntry
);

if (err == LDAP_SUCCESS )
wprintf(L"\nPassword succesfully set!\n");
else
wprintf(L"\nPassword set failed!\n");

return err;
}