我正在测试.net LDAP客户端的行为,当提供足够的错误密码以触发锁定时。
我看到这种奇怪的行为:似乎如果进程在任何时候成功连接,那么即使在故意触发锁定之后它也能够重新连接。
这是我的绑定方法的简写版本:
private DirectoryEntry Bind(string userId, string password)
{
var entry = new DirectoryEntry(BasePath, userId, password);
// If the password is bad, the attempt to access entry.NativeObject throws an exception.
var obj = entry.NativeObject; // causes the bind to occur
return entry;
}
我的测试进行如下:
private void TestLockout()
{
// attempt with bad pw enough times to trigger a lockout.
for (int i=0; i < 5; i++)
{
try
{
// i.ToString() is a purposefully bad pw
Bind("testuser", i.ToString());
}
catch
{
}
}
// Now make sure that an attempt with a good pw fails due to lockout
var bindSuccess = true;
try
{
Bind("testuser", "correctpassword");
}
catch
{
bindSuccess = false;
}
// the output should be "false"
Console.WriteLine("Bind result is " + bindSuccess.ToString();
}
这样可以正常工作。但是,如果在测试之前调用带有好密码的Bind(),我会得到不同的结果。
IOW,这个:
Bind("testuser", "correctpassword"); // succeeds
TestLockout(); // does not give the correct result
以下情况发生。
a)TestLockout产生错误的输出,因为最终的Bind成功而不应该 b)然而,我知道由于随后的检查,用户被锁定了。
因此,某些组件似乎正在跟踪当前进程是否已成功连接。我需要有办法清除这种情况。此身份验证代码将在长时间运行的服务进程中执行,并且在用户真正被锁定时对其进行身份验证是不可接受的。
答案 0 :(得分:1)
这与DirectoryEntry
正在使用ADSI这一事实有关。 ADSI具有基于BasePath
,Username
和Password
构建的内部LDAP连接池。
如果您在帐户被锁定之前尝试使用正确的密码绑定,则使用该正确的密码成功建立LDAP连接并在连接池中缓存。然后,您锁定了帐户并尝试使用相同的BasePath
,Username
和Password
绑定到Active Directory。此时DirectoryEntry
将不会建立新的LDAP连接,而是重用之前的连接。您可以通过查看网络跟踪来证明这一点。
要解决此问题,您可以在不需要时处置DirectoryEntry
。处置DirectoryEntry
后,ADSI应足够智能,以关闭不再需要的LDAP连接。在您的示例代码中,您似乎再也不需要它了。所以,这应该解决问题。
private void Bind(string userId, string password)
{
using (var entry = new DirectoryEntry(BasePath, userId, password))
{
// If the password is bad, the attempt to access entry.NativeObject throws an exception.
var obj = entry.NativeObject; // causes the bind to occur
}
}