在Active Directory中使用登录名查找用户

时间:2020-03-06 15:00:56  来源:igfitidea点击:

我可能只是愚蠢,但是我试图使用登录名(" domain \ user")从C#中找到Active Directory中的用户。

我的"骨架"广告搜索功能通常如下所示:

de = new DirectoryEntry(string.Format("LDAP://{0}", ADSearchBase), null, null, AuthenticationTypes.Secure);
ds = new DirectorySearcher(de);
ds.SearchScope = SearchScope.Subtree;
ds.PropertiesToLoad.Add("directReports");
ds.PageSize = 10;
ds.ServerPageTimeLimit = TimeSpan.FromSeconds(2);
SearchResult sr = ds.FindOne();

现在,如果我具有用户的完整DN(ADSearchBase通常指向Active Directory中的"我们的用户" OU),那将起作用,但是我根本不知道如何基于" domain \ user"语法查找用户。

有指针吗?

解决方案

我们需要设置类似以下内容的过滤器(DirectorySearcher.Filter):

"(&&(objectCategory = person)(objectClass = user)(sAMAccountName = {0}))"

请注意,我们仅为属性sAMAccountName指定用户名(不包含域)。要搜索域\用户,请首先找到所需域的命名上下文,然后在其中搜索sAMAccountName。

顺便说一句,当使用String.Format构建LDAP查询字符串时,通常应小心转义任何特殊字符。帐户名称可能不是必需的,但是如果要通过其他属性(例如用户的名字(givenName属性)或者姓氏(sn属性))进行搜索,则可能是必需的。我有一个实用程序方法EscapeFilterLiteral来做到这一点:我们可以像这样构建字符串:

String.Format("(&(objectCategory=person)(objectClass=user)(sn={0}))", 
              EscapeFilterLiteral(lastName, false));

EscapeFilterLiteral的实现方式如下:

public static string EscapeFilterLiteral(string literal, bool escapeWildcards)
{
    if (literal == null) throw new ArgumentNullException("literal");

    literal = literal.Replace("\", "\5c");
    literal = literal.Replace("(", "\28");
    literal = literal.Replace(")", "\29");
    literal = literal.Replace("##代码##", "\00");
    literal = literal.Replace("/", "\2f");
    if (escapeWildcards) literal = literal.Replace("*", "\2a");
    return literal;
}

此实现允许我们将*字符视为文字的一部分(escapeWildcard = true)或者作为通配符(escapeWildcard = false)。

更新:这与问题无关,但是我们发布的示例并未在其使用的一次性对象上调用Dispose。像所有一次性对象一样,这些对象(DirectoryEntry,DirectorySearcher,SearchResultCollection)通常应使用using语句进行处理。有关更多信息,请参见此帖子。

谢谢。我认为我可以通过指定" LDAP:// {0} .somedomain.com / DC = {0},DC = somedomain,DC = com"(至少用我的广告)来获得域,用{0}该域,至少在我们的环境中有效。

但是,一个问题是:sAMAccountName似乎已被淘汰:登录名用于支持运行较早版本操作系统(例如Windows NT 4.0,Windows 95,Windows 98和LAN Manager)的客户端和服务器。此属性必须少于20个字符以支持较旧的客户端。

这仍然是最好的方法吗?还是有一个更"现代"的字段可以查询? (Windows 2003 Active Directory,Windows XP或者2003客户端,.net 3.0)

编辑:再次感谢。我们的结构有点复杂:我们有一个很大的" domain.com"林,其中有多个用于区域办事处的域。本质上:登录名是" something \ username",完整的域是something.domain.com,邮件是[email protected](不含something),但是主体名称是[email protected]。我将手动将" "用户名"翻译"为[email protected],因为这似乎是最可靠的方法。特别是因为我想保留自动发现功能。