【问题标题】:c# Change AD password Directoryservicesc#更改AD密码Directoryservices
【发布时间】:2016-08-16 07:45:52
【问题描述】:

我试图让下面的代码工作,问题是,有时它会,有时它不会。 当它失败时,它会给出错误 0x800704F1“系统无法联系域控制器来服务身份验证请求” 我会说大约 90% 的时间它都失败了。 我已经尝试通过在 contexttype 后面添加它来给它一个静态 DC,这很遗憾没有帮助。 在管理员用户上它始终有效.. 但是我相信用户应该能够更改自己的密码。 错误是在 user.changepassword 行上触发的

我希望其他人有一个好主意。

        using (var context = new PrincipalContext(ContextType.Domain))
        {
            using (var user = UserPrincipal.Current)
            {
                try
                {
                    user.ChangePassword(txt_old.Text, txt_new.Text);
                    user.Save();

                }
                catch(Exception p)
                {
                    if (p.HResult.Equals("0x800708C5"))//Not secure enough according to password policy
                    {
                        MessageBox.Show("Volgens het systeem is uw nieuwe wachtwoord niet veilig genoeg, voldoet het aan alle eisen?", "Niet gelukt", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        return;
                    }
                    else if (p.HResult.Equals("0x80070056")) //Wrong current password
                    {
                        MessageBox.Show("U heeft een verkeerd huidig wachtwoord ingevult, probeer het nogmaals", "Verkeerd wachtwoord", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        return;
                    }
                    else if (p.InnerException.ToString().Contains("0x80070775")) //Temporarly locked out.
                    {
                        MessageBox.Show("Uw account is tijdelijk vergrendeld door te veel pogingen tot in te loggen met een foutief wachtwoord. Probeer het over 15minuten nogmaals of neem contact op met de helpdesk.", "vergrendeld.", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        return;
                    }
                    else
                    {
                        MessageBox.Show(System.Security.Principal.WindowsIdentity.GetCurrent().Name + Environment.NewLine + p.HResult + Environment.NewLine + p.Message);
                        return;
                    }
                }
            }
        }

【问题讨论】:

    标签: c# active-directory


    【解决方案1】:

    这两个 Windows 更新 3177108 和 3167679 改变了 ChangePassword 的行为。

    这里有一个关于这个问题的帖子:https://social.msdn.microsoft.com/Forums/vstudio/en-US/77dc733e-a13d-4349-9088-8065b85d5c3f/userprincipalchangepassword-stops-working-after-windows-updates-3177108-and-3167679?forum=netfxbcl

    看来,您现在必须在创建 PrincipalContext 时指定一个有效的 UPN。

    在创建上下文时可以使用 IP 作为端点之前,现在看来它也必须是正确的域名。

    此外,您现在在发生错误时总是会收到相同的异常 - 我们曾经收到用户选择密码不足的密码策略异常,现在我们得到:

    System.DirectoryServices.AccountManagement.PrincipalOperationException: 系统无法联系域控制器来服务 身份验证请求。请稍后再试。 (例外来自 HRESULT: 0x800704F1)

    2016 年 4 月 10 日更新: 上面显示的异常实际上是在更新后调用 ChangePassword 时收到的几乎所有内容的一般/一般错误。 例如,如果协议中涉及的某些端口被防火墙阻止,您也会得到这个端口(适用于从未加入域的服务器/机器调用)。

    所需端口的良好资源:https://technet.microsoft.com/en-us/library/dd772723(v=ws.10).aspx 请注意,动态范围也是必需的。

    如果不允许用户更改密码(域策略,通过设置 MUST CHANGE AT NEXT LOGON FLAG 来规避),您也会收到此异常。

    【讨论】:

      【解决方案2】:

      您的问题可能是发生了密码策略违规。也就是说,例如,如果您有一个密码策略,其中用户不能将他们的密码更改为他们最后 5 个密码之一,例如,如果他们尝试更改为他们最后 5 个密码之一,您会看到这个我的经验中抛出的错误。

      您报告的异常之前的错误(在我的情况下)如下所示: TargetInvocationException:尝试更改 Active Directory 密码的 COM 错误..

      所以我会检查您的密码政策并确保您的用户在这些情况下没有违反它。

      【讨论】:

      • 在我们的例子中,密码历史没有启用。密码的最短使用期限为 0 天。除了这样的问题是否会出现“系统无法联系域控制器来服务身份验证请求”异常?
      • 此外,还没有用户使用它。我刚刚成功,目前正在测试它。
      • 我听到你在说什么,并且理解这不是这种情况下的政策。我知道我收到错误“系统无法联系域控制器以服务身份验证请求”,这与系统是否可以找到域控制器无关并且密码更改因其他原因失败。您还有其他错误信息吗? (内部异常,更多异常细节?)您可以通过管理员更改的事实当然表明存在权限问题。
      【解决方案3】:

      更新:2016 年 10 月 12 日: 微软更新了这篇文章:https://support.microsoft.com/en-us/kb/3177108。在这里,他们为我们提供了由原始“修复”造成的问题,以及使用 Kerberos 和自助密码重置的一些技巧。

      自 2016 年 10 月 11 日起,Microsoft 重新发布了与 https://technet.microsoft.com/en-us/library/security/ms16-101.aspx 相关的补丁,以解决由原始更新引起的问题(您可以在 https://support.microsoft.com/en-us/kb/3177108 中阅读,包括您无法再更改本地帐户密码的事实)。


      我相信我有答案。微软最近对 Windows 进行了修补,使 NTLM 不能再用于更改密码。

      解决方案 #1(“锤子”): 尝试在运行代码的服务器上删除其中一个或两个 KB 更新。

      https://support.microsoft.com/en-us/kb/3177108

      https://support.microsoft.com/en-us/kb/3167679

      当您说您可以以管理员身份更改密码时,您的意思是仅当您的表单应用程序在管理员的计算机上运行时?当应用程序在非管理员的机器上运行时会遇到挑战吗?

      我能够获取您的代码并使其按原样工作并更改以下内容:

      using (var user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, "test.user0001"))
      

      using (var user = UserPrincipal.FindByIdentity(context, IdentityType.UserPrincipalName, "test.user0001@webactivedirectory.com"))
      

      使用这些行中的任何一行以及您的行(获取当前用户),我都能够更改管理员和非管理员密码。我的问题是当您在非管理员机器上运行表单应用程序时是否会发生错误。

      【讨论】:

      • 我确实可以使用示例,但这不是一个 aspx 应用程序:o 它的 windows 窗体,那么我将如何设置它以使用 kerberos?
      • 我在 Windows 窗体应用程序中测试您的代码后编辑了答案。
      • 该应用程序始终在我的管理员机器上运行,但是当我以普通用户身份在常规终端服务器上尝试时,它会出现问题。我也试过你放在那里的变体,但两者都有问题。也许它的某种活动目录权限是错误的?
      【解决方案4】:

      我在两个不同的场合从系统管理员那里目睹了这一点:两个具有密码管理功能的应用程序必须安装在两个新部署的服务器上,当然这些服务器已经完全修补;在这两种情况下,更改密码都失败,并显示应用程序无法联系域控制器的错误(当然,域控制器确实存在并且可用)。

      一个应用程序是由供应商提供的闭源应用程序 (CyberArk's Privileged Session Manager),而另一个是由我目前工作的客户开发的内部应用程序;在第二种情况下,我可以看一下代码,这确实与原始问题中使用的代码相似。

      遗憾的是,实际上修复代码在这两种情况下都不是一种选择:对于第一个应用程序,我们必须向应用程序供应商报告错误,而对于第二个应用程序,我们必须向正在开发的内部开发团队报告错误应用程序,在这两种情况下我们都无法立即修复。管理层希望这两个应用程序现在都可以运行,因此我们必须删除有问题的更新(我知道,这很糟糕,不是解决方案,而是一种懒惰且危险的解决方法,我尽我所能避免这种情况;但是管理就是管理,所以……嗯)。

      无论如何,我回答这个问题的原因是:除了删除KB3177108KB3167679,就我而言(两种情况),我们还必须删除KB3175024KB3174644;虽然安装了这两个更新,但密码更改功能仍然无法工作,即使删除了前两个更新。

      因此,如果您发现自己无法修复代码,并且删除 KB3177108 和 KB3167679 并不能解决问题,那么您可以尝试同时删除 KB3175024 和 KB3174644。

      【讨论】:

        猜你喜欢
        • 2015-09-09
        • 1970-01-01
        • 2018-01-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多