如何使用.NET或LDAP验证过期的Active Directory密码

时间:2014-12-09 21:28:47

标签: c# .net vb.net authentication active-directory

基本问题

有没有办法在使用.NET或其他类型的LDAP查询时验证Active Directory密码是否已过期?为了清楚起见,我不是在讨论检查 密码是否已过期,而是在讨论验证过期的密码是否正确

我发现this answer解释了如何使用Win32 API的 LogonUser()功能完成此操作。我问过a separate question regarding problems with getting this to work from PowerShell。在这里,我问是否可以通过Win32 API以外的任何方式完成,最好是.NET。

进一步考虑主题

PrincipalContext.ValidateCredentials 方法和 DirectoryEntry 构造函数都返回相同的登录失败消息,无论密码是不正确,已过期还是需要在下次更改登录。没有办法区分错误的密码和正确但过期的密码。

Active Directory不公开密码哈希值,而AFAIK没有办法解决这个问题(这可能是件好事......),所以试图让脚本哈希密码并将其与目录进行比较是死路一条。

我能够使用.NET(或Win32 API之外的其他任何东西)提出的最佳解决方案就是这个愚蠢的解决方法:

  1. 检查密码是否过期(通过检查 pwdLastSet 日期与当前日期之间的差异是否大于最大密码年龄)。
  2. 如果已过期,请检查是否已锁定。如果是,请解锁。
  3. 阅读 badPwdCount 属性。
  4. 尝试通过任何方式进行身份验证 badPwdCount 如果失败( ValidateCredentials DirectoryEntry runas 命令,许多其他方式)。验证是否抛出了登录错误。
  5. 再次阅读 badPwdCount 。如果增加,则提供的密码不正确。如果没有增加,则密码不正确。
  6. (步骤2是必要的,因为如果帐户被锁定,失败的身份验证尝试不会增加 badPwdCount 。)

    但是,我发现这个计划存在一些缺点:

    • 如果在 badLogonCount 的“之前”和“之后”读数之间发生来自其他来源的身份验证尝试,或者如果 badLogonCount 被重置,则会产生错误结果管理员或锁定期限到期。
    • 脚本必须确保始终使用相同的域控制器,以避免因收敛延迟而导致的错误结果。
    • 在某些情况下,脚本必须进行更改(解锁帐户),否则无效。理想情况下,验证操作不应更改其检查的数据的任何方面。

    虽然很少会遇到这些问题,而且我可以想办法减轻这些问题,但这些方法非常混乱,而且不是100%可靠,总体而言,这远非理想的解决方案。

    是否有任何直接方法可以使用.NET或任何类型的LDAP查询进行检查 - 某些验证方法会产生错误结果,从而区分无效凭据和过期密码的有效凭据,如 LogonUser()< / strong>确实,或者其他一些创造性的方式来区分那些不会像上面概述的那样陷入困境的方式?

    类似的问题,但没有答案

    此主题之前已多次提出,但此特定问题没有答案。

    当设置“用户必须在下次登录时更改密码”标志时,此答案的两个答案都特定于验证凭据。粗略地看一下,第二个答案出现以解决密码过期的情况,因为其中一个代码分支抛出“1907密码已过期”异常,但如果您仔细阅读代码,则可以看到此错误消息具有误导性;只有在设置了“用户必须在下次登录时更改密码”标志并且凭据正确的情况下才会抛出它。

    使用 LogonUser()建议的答案链接都会回答这两个问题。

    [注意:我添加了c#vb.net标签,因为虽然这个问题与语言无关,但我相信这些标签最有可能引起人们的注意。知识渊博的人;其他标签本身的可见度非常低,前5个小时内只有7个观看次数。]

0 个答案:

没有答案