使用PrincipalSearcher查找具有"或"参数的用户

doo*_*ist 26 .net c# active-directory

是否可以System.DirectoryServices.AccountManagement.PrincipalSearcher使用"或"(不是"和")来基于多个参数进行搜索.

// This uses an and
//(&(objectCategory=person)(!UserAccountControl:1.2.840.113556.1.4.803:=2)(&(SAMAccountName=tom*)(DisplayName=tom*)))
var searchPrinciple = new UserPrincipal(context);
searchPrinciple.DisplayName =  "tom*";
searchPrinciple.SamAccountName = "tom*";

var searcher = new PrincipalSearcher();
searcher.QueryFilter = searchPrinciple;

var results = searcher.FindAll();
Run Code Online (Sandbox Code Playgroud)

我希望使用PrincipalSearcher(不是DirectorySearcher)类似于此(在LDAP中)的搜索

// (&(objectCategory=person)(!UserAccountControl:1.2.840.113556.1.4.803:=2)(|(SAMAccountName=tom*)(DisplayName=tom*)))
Run Code Online (Sandbox Code Playgroud)

Bed*_*uin 21

这显然是不可能的,这是一个解决方法:

List<UserPrincipal> searchPrinciples = new List<UserPrincipal>();
searchPrinciples.Add(new UserPrincipal(context) { DisplayName="tom*"});
searchPrinciples.Add(new UserPrincipal(context) { SamAccountName = "tom*" });
searchPrinciples.Add(new UserPrincipal(context) { MiddleName = "tom*" });
searchPrinciples.Add(new UserPrincipal(context) { GivenName = "tom*" });

List<Principal> results = new List<Principal>();
var searcher = new PrincipalSearcher();
foreach (var item in searchPrinciples)
{
    searcher = new PrincipalSearcher(item);
    results.AddRange(searcher.FindAll());
}
Run Code Online (Sandbox Code Playgroud)

  • 您将不得不使用此处理重复项.如果显示名称,给定名称和帐户名称都包含名称"tom",则您将具有重复项. (4认同)

Aer*_*roX 5

不一定像其他一些答案一样干净,但这里是我在我正在研究的项目中实现这一点的方法.我希望两个搜索都运行异步,以尝试减少由于运行两个AD查询导致的任何减速.

public async static Task<List<ADUserEntity>> FindUsers(String searchString)
{
    searchString = String.Format("*{0}*", searchString);
    List<ADUserEntity> users = new List<ADUserEntity>();

    using (UserPrincipal searchMaskDisplayname = new UserPrincipal(domainContext) { DisplayName = searchString })
    using (UserPrincipal searchMaskUsername = new UserPrincipal(domainContext) { SamAccountName = searchString })
    using (PrincipalSearcher searcherDisplayname = new PrincipalSearcher(searchMaskDisplayname))
    using (PrincipalSearcher searcherUsername = new PrincipalSearcher(searchMaskUsername))
    using (Task<PrincipalSearchResult<Principal>> taskDisplayname = Task.Run<PrincipalSearchResult<Principal>>(() => searcherDisplayname.FindAll()))
    using (Task<PrincipalSearchResult<Principal>> taskUsername = Task.Run<PrincipalSearchResult<Principal>>(() => searcherUsername.FindAll()))
    {
        foreach (UserPrincipal userPrincipal in (await taskDisplayname).Union(await taskUsername))
            using (userPrincipal)
            {
                users.Add(new ADUserEntity(userPrincipal));
            }
    }

    return users.Distinct().ToList();
}
Run Code Online (Sandbox Code Playgroud)

我的ADUserEntity类具有基于SID的相等性检查.我试图将两个搜索者的结果添加Distinct()到其中Union(),但这不起作用.

我欢迎对我的答案提出任何建设性的批评,因为我想知道是否有任何方法可以改进它.

  • 要仅返回不同的用户,您可以使用 LINQ 按标识符(例如 SID)进行分组:将 `return users.Distinct().ToList();` 替换为 `return users.GroupBy(user =&gt; user.Sid)。 Select(group =&gt; group.First()).ToList();` (2认同)

Ala*_*aya -3

FindAll 方法在主体上下文中指定的域中搜索与查询过滤器上设置的属性具有相同属性的对象。FindAll 方法返回与所提供的对象匹配的所有对象,而 FindOne 方法仅返回单个匹配的主体对象。 http://msdn.microsoft.com/en-us/library/bb384378(v=vs.90).aspx

我不知道你需要什么,但你可以按 1 个属性和 1 个其他属性进行搜索,然后在列表上使用 LINQ 进行合并、过滤等...