为什么Active Directory中验证最后一个密码? [英] Why does Active Directory validate last password?

查看:198
本文介绍了为什么Active Directory中验证最后一个密码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我工作的一个简单的解决方案,以更新Active Directory用户的密码。

I am working on a simple solution to update a user's password in Active Directory.

我可以成功更新用户的密码。更新密码工作正常。可以说,用户已更新从MyPass1密码为 MyPass2

I can successfully update the users password. Updating the password works fine. Lets say the user has updated the password from MyPass1 to MyPass2

现在,当我运行我的自定义code,以验证用户与凭证使用:

Now when I run my custom code to validate users credential using:

using(PrincipalContext pc = new PrincipalContext(ContextType.Domain, "TheDomain"))
{
    // validate the credentials
    bool isValid = pc.ValidateCredentials("myuser", "MyPass2");
}

//returns true - which is good

现在,当我输入一些错误的密码,它验证非常漂亮:

Now when I enter some wrong password it validates very nicely:

using(PrincipalContext pc = new PrincipalContext(ContextType.Domain, "TheDomain"))
{
    // validate the credentials
    bool isValid = pc.ValidateCredentials("myuser", "wrongPass");
}

//returns false - which is good

现在的一些奇怪的原因,它验证了previous这是MyPass1最后一个密码还记得吗?

Now for some odd reasons, it validates the previous last password which was MyPass1 remember?

using(PrincipalContext pc = new PrincipalContext(ContextType.Domain, "TheDomain"))
{
    // validate the credentials
    bool isValid = pc.ValidateCredentials("myuser", "MyPass1");
}

//returns true - but why? we have updated password to Mypass2

我是从这个code:

I got this code from:

<一个href="http://stackoverflow.com/questions/290548/c-sharp-validate-a-username-and-password-against-active-directory">Validate用户名和密码对Active Directory?

难道是与最后一个口令到期或请问这是怎么认为的验证工作?

Is it something to do with last password expiry or is this how the validation supposed to work?

推荐答案

为什么你看到这样做的原因,是因为有特殊行为具体到NTLM网络身份验证

The reason why you are seeing this has to do with special behavior specific to NTLM network authentication.

调用在 PrincipalContext 实例导致安全LDAP连接的 ValidateCredentials 法正在,然后绑定使用 ldap_bind_s 函数调用连接上正在执行的操作。

Calling the ValidateCredentials method on a PrincipalContext instance results in a secure LDAP connection being made, followed by a bind operation being performed on that connection using a ldap_bind_s function call.

在调用时 ValidateCredentials 使用的身份验证方法是 AuthType.Negotiate 。使用这将导致使用Kerberos,这(是的没有的当然NTLM)不会表现出特别的行为,上述尝试的绑定操作。然而,正在绑定尝试使用Kerberos将失败(密码是错误的,所有的),这将导致另一次尝试,这次使用NTLM。

The authentication method used when calling ValidateCredentials is AuthType.Negotiate. Using this results in the bind operation being attempted using Kerberos, which (being not NTLM of course) will not exhibit the special behavior described above. However, the bind attempt using Kerberos will fail (the password being wrong and all), which will result in another attempt being made, this time using NTLM.

您有两种方法来实现这一点:

You have two ways to approach this:

  1. 按照我联系,缩短或消除旧密码使用的 OldPasswordAllowedPeriod 注册表值的存活时间在Microsoft知识库文章中的说明。也许不是最理想的解决方案。
  2. 请不要使用 PrincipleContext 类验证凭据。现在你知道了(大约)如何 ValidateCredentials 的作品,它应该不会太难为你做手工的过程。什么,你会想要做的就是创建一个新的LDAP连接( LdapConnection ),设置其网络凭证,设置与AuthType明确地 AuthType.Kerberos ,然后调用绑定()。你会得到一个异常,如果凭据是不好的。
  1. Follow the instructions in the Microsoft KB article I linked to shorten or eliminate the lifetime period of an old password using the OldPasswordAllowedPeriod registry value. Probably not the most ideal solution.
  2. Don't use PrincipleContext class to validate credentials. Now that you know (roughly) how ValidateCredentials works, it shouldn't be too difficult for you to do the process manually. What you'll want to do is create a new LDAP connection (LdapConnection), set its network credentials, set the AuthType explicitly to AuthType.Kerberos, and then call Bind(). You'll get an exception if the credentials are bad.

下面code演示了如何使用仅Kerberos执行凭据验证。在使用的身份验证方法,将回退到NTLM在发生故障时。

The following code shows how you can perform credential validation using only Kerberos. The authentication method at use will not fall back to NTLM in the event of failure.

private const int ERROR_LOGON_FAILURE = 0x31;

private bool ValidateCredentials(string username, string password, string domain)
{
  NetworkCredential credentials
    = new NetworkCredential(username, password, domain);

  LdapDirectoryIdentifier id = new LdapDirectoryIdentifier(domain);

  using (LdapConnection connection = new LdapConnection(id, credentials, AuthType.Kerberos))
  {
    connection.SessionOptions.Sealing = true;
    connection.SessionOptions.Signing = true;

    try
    {
      connection.Bind();
    }
    catch (LdapException lEx)
    {
      if (ERROR_LOGON_FAILURE == lEx.ErrorCode)
      {
        return false;
      }
      throw;
    }
  }
  return true;
}

我尝试从来没有使用异常处理我的code中的流量控制;然而,在这个特殊的例子,来测试一个LDAP连接凭据的唯一途径似乎是试图进行绑定操作,这将抛出一个异常,如果凭据是不好的。 PrincipalContext 采用相同的方法。

这篇关于为什么Active Directory中验证最后一个密码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆