3 回答

TA贡献2021条经验 获得超8个赞
所以UserPrincipal.ChangePassword()
会打电话:
de.Invoke("ChangePassword", new object[] { oldPassword, newPassword });
它在DirectoryEntry
幕后使用。DirectoryEntry.Invoke()
用于调用“本机 Active Directory 域服务对象上的方法”,这意味着这将最终使用本机 WindowsIADsUser::ChangePassword
方法。备注说它使用 3 种方法之一:
IADsUser::ChangePassword 的功能类似于IADsUser::SetPassword,因为它将使用三种方法之一来尝试更改密码。最初,如果与服务器建立了安全的 SSL 连接,则 LDAP 提供程序将尝试 LDAP 更改密码操作。如果此尝试失败,则 LDAP 提供程序接下来将尝试使用 Kerberos(请参阅 IADsUser::SetPassword 了解在使用跨林身份验证的 Windows 上可能导致的一些问题),如果这也失败,它最终将调用 Active Directory 特定网络管理 API,NetUserChangePassword。
The RemarksIADsUser::SetPassword
说的多一点:
首先,LDAP 提供程序尝试通过 128 位 SSL 连接使用 LDAP。要使 LDAP SSL 成功运行,LDAP 服务器必须安装适当的服务器身份验证证书,并且运行 ADSI 代码的客户端必须信任颁发这些证书的机构。服务器和客户端都必须支持 128 位加密。
其次,如果 SSL 连接不成功,LDAP 提供者会尝试使用 Kerberos。
第三,如果 Kerberos 不成功,LDAP 提供程序会尝试调用NetUserSetInfo API。在以前的版本中,ADSI在线程运行的安全上下文中调用NetUserSetInfo ,而不是在调用IADsOpenDSObject::OpenDSObject或ADsOpenObject时指定的安全上下文。在以后的版本中,这已更改,以便 ADSI LDAP 提供程序在调用 NetUserSetInfo 时模拟 OpenDSObject 调用中指定的用户。
因此,如果这对您根本不起作用,则意味着所有三种方法都失败了。
我真的不知道 Kerberos 或 NetUserSetInfo 是如何工作的,但我确实知道基于 SSL 的 LDAP 是如何工作的,你可以试试看它是否适合你。
连接到 LDAPS 端口应该很容易(假设这是域的DNS名称)::636
ServerDomain
using (var context = new PrincipalContext(ContextType.Domain, $"{ServiceDomain}:636", ServiceDefaultLocation, ContextOptions.Negotiate, ServiceUser, ServicePassword))
using (var identity = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, "Jane"))
{
// identity.SetPassword("SomeNewPassword"); // also tried
identity.ChangePassword("TheOldPassword", "SomeNewPassword"); // this is the error line
identity.Save();
}
但是,如果服务器使用您运行它的计算机不信任的证书,您可能会遇到麻烦(您必须在运行它的计算机上安装根证书)。LDAPS 也有可能没有在 DC 上运行。
但值得一试。

TA贡献2019条经验 获得超9个赞
您是否尝试过 DirectoryEntry?用它来调试与连接相关的问题更容易。
var entry = new DirectoryEntry{
Path = "LDAP://yourDCname";
Username = yourUsername;
Password = yourPassword;
};
using(var searcher = new DirectorySearcher(entry))
{
searcher.Filter = "(sAMAccountName=Jane)";
var result = searcher.FindOne();
var user = result.GetDirectoryEntry();
try
{
user.Invoke("ChangePassword", new object[] { oldPassword, newPassword});
user.CommitChanges();
}
catch
{
throw;
}
}
我也曾经忘记了后台运行在谷歌浏览器中的 ZenMate VPN 插件。所以我无法连接到域控制器。

TA贡献1865条经验 获得超7个赞
我在密码重置服务器网页上遇到了类似的问题,用户可以重置自己的密码。我发现即使服务帐户被授予仅重置密码的权限,域的设置也不允许这样做。您是否尝试过授予服务帐户域管理员权限只是为了测试它不是权限问题?
- 3 回答
- 0 关注
- 483 浏览
添加回答
举报