使用包含空格的LDAP过滤器查询Active Directory

时间:2009-11-25 16:06:08

标签: c# active-directory

我试图通过LDAP查询ActiveDirectory,但查询可能包含空格或其他可能导致问题的字符(连字符?)

(&(objectCategory=person)(objectClass=user)(|(&(sn=Bloggs*)(givenName=Jo*))(displayName=Jo Bloggs))

这是一个OR搜索,例如在SQL中它将是WHERE (sn LIKE 'Bloggs%' AND givenName LIKE 'Jo%') OR displayName = 'Jo Bloggs'

但是,当我尝试LDAP查询时,出现错误:System.ArgumentException: The (&(objectCategory=person)(objectClass=user)(|(&(sn=Bloggs*)(givenName=Jo*))(displayName=Jo Bloggs)) search filter is invalid

执行搜索的代码:

string userName = "Jo Bloggs";
DirectoryEntry adroot = new DirectoryEntry("LDAP://" + Environment.UserDomainName, "user", "password", AuthenticationTypes.Secure);
DirectorySearcher search = new DirectorySearcher(adroot);
search.Filter = string.Format("(&(objectCategory=person)(objectClass=user)(|(&(sn={0}*)(givenName={1}*))(displayName={2}))", userName.Split(' ')[1], userName.Split(' ')[0], userName);

这只是一个基本搜索,我想搜索其他列(职位,电话,部门等),例如WHERE title LIKE '%foo%' OR telephonenumber LIKE '%foo% OR department LIKE '%foo%'

另外,我可以缓存搜索,因此ActiveDirectory没有从搜索相同内容的人那里得到很多点击量吗?

这也只找到一个条目,我想搜索并在转发器中显示找到的所有结果。

3 个答案:

答案 0 :(得分:2)

你错过了一个右括号。试试这个工作示例:

string userName = "Jo Bloggs";
string baseQuery =
    "(&" +
        "(objectCategory=person)" +
        "(objectClass=user)" +
        "(|" +
            "(&" +
                "(sn={0}*)" +
                "(givenName={1}*)" +
            ")" +
            "(displayName={2})" +
        ")" +
    ")"; // <<< this is missing in your original query

userName = Regex.Replace(userName, @"[\(\)\*\\]", (match) =>
                {   // escape reserved chars
                    return "\\" + ((int)match.Value[0]).ToString("x");
                }, RegexOptions.Compiled);
string query = String.Format(query, userName.Split(' ')[1], 
                                    userName.Split(' ')[0], userName);
using (DirectoryEntry entry = new DirectoryEntry(
    "LDAP://" + Environment.UserDomainName, "user", "password",
    AuthenticationTypes.Secure))
{
    using (DirectorySearcher ds = 
       new DirectorySearcher(entry, query, null, SearchScope.Subtree))
    {
        SearchResultCollection res = ds.FindAll(); // all matches
        if (res != null)
            foreach (SearchResult r in res)
                Console.WriteLine(user.Properties["displayName"].Value);
    }
}

编辑:关于转义序列,您应该参考此文档:Creating a Query Filter。我编辑这个答案以反映这些信息。

  

如果查询过滤器中必须出现以下任何特殊字符作为文字,则必须用列出的转义序列替换它们。

  ASCII     Escape sequence 
character     substitute
    *           "\2a"
    (           "\28"
    )           "\29"
    \           "\5c"
   NUL          "\00"
  

此外,可以使用转义序列语法来表示任意二进制数据,方法是使用反斜杠后跟两个十六进制数字对二进制数据的每个字节进行编码。例如,四字节值0x00000004在过滤字符串中编码为“\ 00 \ 00 \ 00 \ 04”。

答案 1 :(得分:0)

还有另一个LINQ to AD http://adlinq.codeplex.com框架,它实现了更多的IQueryable扩展方法(Single,First,Last,SingleOrDefault等等)并经常更新。

答案 2 :(得分:-1)

为什么不使用Linq进行AD搜索 - http://linqtoad.codeplex.com/