针对Active Directory的身份验证一次算作两次无效登录

本文关键字:两次 无效 登录 一次 Directory 身份验证 针对 Active | 更新日期: 2023-09-27 18:02:17

给定以下代码,其中密码不正确:

var principalContext = new PrincipalContext(
                           ContextType.Domain, 
                           ConfigurationManager.AppSettings["UPN"], 
                           ConfigurationManager.AppSettings["LDAPUsers"]);
response.IsAuthenticated = principalContext.ValidateCredentials(
                                            request.LoginName, 
                                            request.Password);

检查

var user = UserPrincipal.FindByIdentity(
                           principalContext, 
                           IdentityType.SamAccountName, 
                           request.LoginName);
var invalidAttempts = user.BadLogonCount;

invalidAttempts的值为2。换句话说,一次验证凭证的尝试消耗了2次登录计数。我假设发生这种情况是因为Kerberos失败后它会退回到NTLM。

那么问题来了——是否有一种方法可以只使用PrincipalContext对Active Directory进行验证,并且每次只增加错误登录计数1 ?

针对Active Directory的身份验证一次算作两次无效登录

我弄清楚了,看起来传递任何参数到ValidateCredentials方法将解决这个问题。我研究了程序集的反编译,它显示了当您不传递任何上下文选项时会发生什么:

    try
    {
        this.BindLdap(creds, ContextOptions.Negotiate | ContextOptions.Signing | ContextOptions.Sealing);
        this.lastBindMethod = CredentialValidator.AuthMethod.Negotiate;
        return true;
    }
    catch (LdapException ex)
    {
    }
    this.BindLdap(creds, ContextOptions.SimpleBind | ContextOptions.SecureSocketLayer);
    this.lastBindMethod = CredentialValidator.AuthMethod.Simple;
    return true;

根据我的理解,如果我没有传递上下文选项,它将默认为Negotiate | Singing | Sealing(如文档中提到的),但如果失败,它将尝试SimpleBind | SecureSocketLayer(未在文档中提到)。此计数为2次错误密码尝试。

所以解决方法是调用

response.IsAuthenticated = principalContext.ValidateCredentials(
                                        request.LoginName, 
                                        request.Password,
                                        ContextOptions.Negotiate |
                                        ContextOptions.Signing | 
                                        ContextOptions.Sealing);

因为我不需要回到SimpleBind .