the*_*eos 33 c# active-directory
我正在研究一种在Active Directory中更新用户密码的简单解决方案.
我可以成功更新用户密码.更新密码工作正常.假设用户已将密码从MyPass1更新为MyPass2
现在,当我运行自定义代码以验证用户凭据时使用:
using(PrincipalContext pc = new PrincipalContext(ContextType.Domain, "TheDomain"))
{
// validate the credentials
bool isValid = pc.ValidateCredentials("myuser", "MyPass2");
}
//returns true - which is good
Run Code Online (Sandbox Code Playgroud)
现在,当我输入一些错误的密码时,它会很好地验证:
using(PrincipalContext pc = new PrincipalContext(ContextType.Domain, "TheDomain"))
{
// validate the credentials
bool isValid = pc.ValidateCredentials("myuser", "wrongPass");
}
//returns false - which is good
Run Code Online (Sandbox Code Playgroud)
现在由于一些奇怪的原因,它验证了以前的最后一个密码是MyPass1还记得吗?
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
Run Code Online (Sandbox Code Playgroud)
我从以下代码获得此代码:
它与上次密码到期有关,或者这是验证应该如何工作?
小智 52
您看到这一点的原因与特定于NTLM网络身份验证的特殊行为有关.
ValidateCredentials在PrincipalContext实例上调用该方法会导致建立安全的LDAP连接,然后使用ldap_bind_s函数调用对该连接执行绑定操作.
打电话时使用的身份验证方法ValidateCredentials是AuthType.Negotiate.使用此结果会导致使用Kerberos尝试绑定操作,而Kerberos(当然不是 NTLM)将不会显示上述特殊行为.但是,使用Kerberos的绑定尝试将失败(密码错误和全部),这将导致另一次尝试,这次使用NTLM.
你有两种方法来解决这个问题:
PrincipleContext类来验证凭据.既然您已经(大致)知道如何ValidateCredentials工作,那么您手动执行此过程应该不会太困难.您要做的是创建一个新的LDAP连接(LdapConnection),设置其网络凭据,显式设置AuthType AuthType.Kerberos,然后调用Bind().如果凭据不好,您将收到异常.以下代码显示了如何仅使用Kerberos执行凭据验证.如果发生故障,正在使用的身份验证方法将不会回退到NTLM.
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;
}
Run Code Online (Sandbox Code Playgroud)
我尝试永远不会使用异常来处理我的代码的流控制; 但是,在此特定实例中,在LDAP连接上测试凭据的唯一方法似乎是尝试绑定操作,如果凭据不正确,则会抛出异常.PrincipalContext采取相同的方法.