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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1797987/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 20:55:41  来源:igfitidea点击:

Querying Active Directory with LDAP filter containing spaces

c#active-directory

提问by SamWM

I am attempting to query ActiveDirectory via LDAP, but the query may contain spaces or other characters that may cause problems (hyphens?)

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

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

It is an OR search e.g. in SQL it would be WHERE (sn LIKE 'Bloggs%' AND givenName LIKE 'Jo%') OR displayName = 'Jo Bloggs'

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

However, when I try the LDAP query, I get an error: System.ArgumentException: The (&(objectCategory=person)(objectClass=user)(|(&(sn=Bloggs*)(givenName=Jo*))(displayName=Jo Bloggs)) search filter is invalid

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

Code for performing search:

执行搜索的代码:

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

This is just a basic search, I would like to search other columns as well (Job Title, Telephone, Department etc), e.g. WHERE title LIKE '%foo%' OR telephonenumber LIKE '%foo% OR department LIKE '%foo%'

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

Also, could I cache the search, so ActiveDirectory doesn't get a lot of hits from people searching t for the same thing?

另外,我可以缓存搜索,所以 ActiveDirectory 不会从搜索相同内容的人那里获得很多点击吗?

This also only finds one entry, I would like to search and display in a repeater all results that are found.

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

采纳答案by Rubens Farias

You're missing a closing parenthesis. Try this working example:

你缺少一个右括号。试试这个工作示例:

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

EDIT:About escape sequences, you should refer to this document: Creating a Query Filter. I edit this answer to reflect that information.

编辑:关于转义序列,您应该参考此文档:创建查询过滤器。我编辑此答案以反映该信息。

If any of the following special characters must appear in the query filter as literals, they must be replaced by the listed escape sequence.

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

  ASCII     Escape sequence 
character     substitute
    *           "a"
    (           ""
    )           ""
    \           "c"
   NUL          "##代码##"

In addition, arbitrary binary data may be represented using the escape sequence syntax by encoding each byte of binary data with the backslash followed by two hexadecimal digits. For example, the four-byte value 0x00000004 is encoded as "\00\00\00\04" in a filter string.

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

回答by Unmesh Kondolikar

Why not use Linq to AD for searching - http://linqtoad.codeplex.com/

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

回答by Stephen Baker

There is also another LINQ to AD http://adlinq.codeplex.comframework which implements more of the IQueryable extension methods (Single, First, Last, SingleOrDefault and many more) and has frequent updates.

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