如何向 DirectoryEntry.Exists 提供凭据?

发布于 2024-10-04 12:18:54 字数 494 浏览 5 评论 0 原文

今天早上我发现了一个很好的方法(DirectoryEntry.Exists),应该能够检查服务器上是否存在 Active Directory 对象。所以我尝试了一个简单的方法:

if (DirectoryEntry.Exists(path)) {}

当然它没有任何重载来提供凭据。因为,如果未提供凭据,我会收到此异常:

登录失败:未知的用户名或 密码错误。 (系统.DirectoryServices.DirectoryServicesCOMException)

是否有其他选项可以让我在 AD 服务器上验证我的代码?或者检查一个对象是否存在?

This morning I discovered a nice method (DirectoryEntry.Exists), that should be able to check whether an Active Directory object exists on the server. So I tried with a simple:

if (DirectoryEntry.Exists(path)) {}

Of course it lacks any overloads to provide credentials with it. Because, if credentials are not provided I get this Exception:

Logon failure: unknown user name or
bad password.
(System.DirectoryServices.DirectoryServicesCOMException)

Is there any other option that gives me the possibility to authenticate my code at the AD server? Or to check the existence of an object?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

月下伊人醉 2024-10-11 12:18:55

我知道这是一个老问题,但是 源代码现已可用,因此您可以直接窃取和修改™ 来制作接受凭据的版本:

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,因为这是一个内部方法,不能被像我们这样的凡人使用。相反,我只是得到 NativeObject 属性,其中 为我们调用 Bind()

你可以像这样使用它:

var ouExists = Exists("LDAP://hadoop.com/OU=Students,DC=hadoop,DC=com", "username", "password");

I know this is an old question, but the source code is now available so you can just Steal and Modify™ to make a version that accepts credentials:

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();
    }
}

The one change you must make is changing the use of Bind, since that's an internal method and can't be used by mere mortals like us. Instead, I just get the NativeObject property, which calls Bind() for us.

You can use that like this:

var ouExists = Exists("LDAP://hadoop.com/OU=Students,DC=hadoop,DC=com", "username", "password");
左耳近心 2024-10-11 12:18:55

没有办法做到这一点,我已经编写了一个连接问题来希望解决它。

DirectoryEntry.Exists 不接受凭据

There is no way to do this and I have written a connect issue to hopefully resolve it.

DirectoryEntry.Exists Does Not Accept Credentials

埋情葬爱 2024-10-11 12:18:55

所以回答这个问题:不可能。

最后编写一个自己的方法来通过可分辨名称获取 DirectoryEntry,并指定凭据。在存在/不存在的两种情况下,我都得到了 DirectoryEntry 的实例。为了检查它是否是返回的有效对象,我做了一个简单的 try...catch 来查看它是否导致异常。如果是这样,则无效。

令人讨厌的检查,但它有效。太糟糕了,默认的 .net 方法 DirectoryEntry.Exists 没有提供重载来提供凭据,就像 DirectoryEntry 构造函数一样......

So answer to the question: impossible.

Finally write an own method to get the DirectoryEntry by distinguised name, with credentials specified. In both cases of existence/inexistence I got an instance of DirectoryEntry. To check whether it's a valid object returned I do a simple try...catch to see if it results in an Exception. If so, it's invalid.

Nasty check, but it works. Too bad the default .net method DirectoryEntry.Exists doesn't provide an overload to provide credentials just like the DirectoryEntry constructor...

鱼忆七猫命九 2024-10-11 12:18:55

如果运行该进程的用户没有调用 DirectoryEntry.Exists 的权限,则您可以使用模拟。

这可能会有所帮助(讨论 AD 上下文中的模拟):http://www.codeproject。 com/KB/system/everythingInAD.aspx

顺便说一句,如果您已经拥有可以访问您需要的所有内容的用户的凭据,为什么不只使用该用户的进程(例如/runas)?

If the user who ran the process doesn't have permissions to call DirectoryEntry.Exists, then you can use impersonation.

This may be helpful (discusses impersonation in an AD context): http://www.codeproject.com/KB/system/everythingInAD.aspx

Btw, if you already have credentials of a user who has access to everything you need, why not just the process with that user (e.g. /runas)?

谎言 2024-10-11 12:18:54

在这种情况下,您不能像您所说的那样使用静态方法 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; 
}

In this case you can't use the static method Exists as you said :

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; 
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文