对 Active Directory 进行身份验证一次计为两次无效登录

use*_*170 2 c# kerberos active-directory

给定以下代码,密码不正确

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

如果我们然后检查

var user = UserPrincipal.FindByIdentity(
                           principalContext, 
                           IdentityType.SamAccountName, 
                           request.LoginName);
var invalidAttempts = user.BadLogonCount;
Run Code Online (Sandbox Code Playgroud)

的值为invalidAttempts2。换言之,验证凭据的单次尝试消耗 2 次登录计数。我假设发生这种情况是因为在 Kerberos 失败后它回退到 NTLM。

所以问题是 - 有没有一种方法可以使用 仅针对 Active Directory 进行验证PrincipalContext,并且每次仅将错误登录计数增加 1?

use*_*170 5

我想通了,看起来向该方法传递任何参数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;
Run Code Online (Sandbox Code Playgroud)

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

所以解决方案是调用

response.IsAuthenticated = principalContext.ValidateCredentials(
                                        request.LoginName, 
                                        request.Password,
                                        ContextOptions.Negotiate |
                                        ContextOptions.Signing | 
                                        ContextOptions.Sealing);
Run Code Online (Sandbox Code Playgroud)

因为我不需要回退到SimpleBind.