[今天早上,我发现了一个不错的方法(DirectoryEntry.Exists),该方法应该能够检查服务器上是否存在Active Directory对象。因此,我尝试了一个简单的方法:
if (DirectoryEntry.Exists(path)) {}
当然,它没有提供任何凭证的重载。因为,如果未提供凭据,则会出现此异常:
登录失败:未知的用户名或密码错误。(System.DirectoryServices.DirectoryServicesCOMException)
还有其他选择可以使我在AD服务器上验证我的代码吗?还是检查对象是否存在?
在这种情况下,您不能使用您所说的静态方法Exists:
DirectoryEntry directoryEntry = new DirectoryEntry(path);
directoryEntry.Username = "username";
directoryEntry.Password = "password";
bool exists = false;
// Validate with Guid
try
{
var tmp = directoryEntry.Guid;
exists = true;
}
catch (COMException)
{
exists = false;
}
没有办法做到,我已经写了一个连接问题以希望解决它。
所以回答这个问题:不可能。
最后编写一个自己的方法,以可分辨的名称获得DirectoryEntry,并指定凭据。在两种存在/不存在的情况下,我都有一个DirectoryEntry实例。要检查返回的对象是否有效,我执行一个简单的try ... catch来查看它是否导致异常。如果是这样,则无效。
讨厌的检查,但是可以。太糟糕了,默认的.net方法DirectoryEntry.Exists不能像DirectoryEntry构造函数一样提供重载来提供凭据...
我知道这是一个古老的问题,但是source code is now available因此您可以仅通过Steal and Modify™来制作接受凭证的版本:
public static bool Exists(string path, string username, string password)
{
DirectoryEntry entry = new DirectoryEntry(path, username, password);
try
{
_ = entry.NativeObject; // throws exceptions (possibly can break applications)
return true;
}
catch (System.Runtime.InteropServices.COMException e)
{
if (e.ErrorCode == unchecked((int)0x80072030) ||
e.ErrorCode == unchecked((int)0x80070003) || // ERROR_DS_NO_SUCH_OBJECT and path not found (not found in strict sense)
e.ErrorCode == unchecked((int)0x800708AC)) // Group name could not be found
return false;
throw;
}
finally
{
entry.Dispose();
}
}
您必须进行的一项更改是更改Bind
的用法,因为这是internal
方法,不能被像我们这样的凡人使用。相反,我只是获得了NativeObject
属性,即NativeObject
。
您可以这样使用:
calls Bind()
for us
如果运行该过程的用户没有调用DirectoryEntry.Exists的权限,则可以使用模拟。
这可能有帮助(在AD上下文中讨论模拟):Bind()
顺便说一句,如果您已经拥有有权访问所需所有内容的用户的凭据,为什么不仅仅使用该用户的过程(例如/ runas)?