繁体   English   中英

通过C#ASP.NET更改Active Directory LDAP密码:无法读取配置

[英]Active Directory LDAP password change via C# ASP.NET: Cannot read configuration

我们正在尝试通过C#ASP.NET 4.5应用程序更改Active Directory中的用户密码(我们将使用“ Jane”作为示例用户),尽管我们收到以下错误消息。

Configuration information could not be read from the domain controller, either because the machine is unavailable, or access has been denied. (Exception from HRESULT: 0x80070547)

可以与远程(第3方)AD服务器建立连接,而不会出现问题,并且我们的服务用户已通过身份验证。 还可以毫无问题地检索Jane的目录条目。

我们已经尝试过更改/设置密码,同时已被Jane和我们的服务用户认证,但都产生相同的错误(上述)。

下面是正在使用的代码的示例。

using (var context = new PrincipalContext(ContextType.Domain, ServiceDomain, 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();
}

系统事件日志指示更改/设置密码上的“审核失败”,其原因列为“登录期间发生错误”。 身份验证包列出了“ MICROSOFT_AUTHENTICATION_PACKAGE_V1_0”。 在此之前,我们有一个针对服务用户的“审核成功”事件。

值得注意的是大约。 在收到错误前20秒钟,这表明可能是连接/超时问题,但是传出连接不受限制,并且我们的IP已在远程端列入白名单(同样,我们可以连接并检索用户条目)。 不过,也需要花费很长时间才能作为用户身份验证(仍然可以成功运行)。

我们的服务用户有权更改/设置其他用户的密码,但不能直接更改用户属性,因此建议您。

如果还有其他信息可以帮助诊断问题,请告诉我。

您是否尝试过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;
        }

    }

我也曾经忘记在后台运行Google Chrome的ZenMate VPN插件。 所以我无法连接到域控制器。

我在密码重设服务器网页上遇到了类似的问题,用户可以重设自己的密码。 我发现,即使授予服务帐户仅重置密码的权限,该域的设置也不允许这样做。 您是否尝试过授予服务帐户域管理员权限,以证明这不是权限问题?

因此UserPrincipal.ChangePassword()调用

de.Invoke("ChangePassword", new object[] { oldPassword, newPassword });

它在幕后使用的DirectoryEntry DirectoryEntry.Invoke()用于调用“本机Active Directory域服务对象上的方法”,这意味着将使用本机Windows IADsUser::ChangePassword方法结束此操作。 备注说明它使用以下三种方法之一:

IADsUser :: ChangePassword的功能类似于IADsUser :: SetPassword ,因为它将使用三种方法之一尝试更改密码。 最初,如果建立了到服务器的安全SSL连接,则LDAP提供程序将尝试LDAP更改密码操作。 如果此尝试失败,则LDAP提供程序接下来将尝试使用Kerberos(有关在跨林身份验证的Windows上可能导致的某些问题,请参阅IADsUser :: SetPassword),如果这也失败,则它将最终调用Active Directory特定的网络。管理API NetUserChangePassword

IADsUser::SetPassword备注多说了一点:

  • 首先,LDAP提供程序尝试通过128位SSL连接使用LDAP。 为了使LDAP SSL成功运行,LDAP服务器必须安装适当的服务器身份验证证书,并且运行ADSI代码的客户端必须信任颁发这些证书的权限。 服务器和客户端都必须支持128位加密。
  • 其次,如果SSL连接失败,则LDAP提供程序尝试使用Kerberos。
  • 第三,如果Kerberos不成功,则LDAP提供程序将尝试NetUserSetInfo API调用。 在以前的版本中,ADSI在运行线程的安全上下文中调用NetUserSetInfo ,而不是在对IADsOpenDSObject :: OpenDSObjectADsOpenObject的调用中指定的安全上下文。 在更高的版本中,此更改已更改,以便ADSI LDAP提供程序在调用NetUserSetInfo时可以模拟OpenDSObject调用中指定的用户。

因此,如果这对您根本不起作用,则意味着这三种方法都失败了。

我真的不知道Kerberos或NetUserSetInfo的工作方式,但是我确实知道LDAP over SSL的工作方式,这是您的事,然后尝试看看它是否对您有用。

应该是那么容易,因为投入:636在你结束ServerDomain连接到LDAPS端口(假设这是该域的DNS名称):

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上运行。

但这值得一试。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM