【问题标题】:How to query Active Directory given multiple user names?如何在给定多个用户名的情况下查询 Active Directory?
【发布时间】:2013-11-06 14:13:57
【问题描述】:

我使用System.DirectoryServices.AccountManagement 查询 Active Directory 以获取单个用户信息

public UserInfo FindOne(string samUserName)
{
    using (var ctx = new PrincipalContext(ContextType.Domain, "domain.com", "Bob", "pwd"))
    {
        using (UserPrincipal user = UserPrincipal.FindByIdentity(ctx, samUserName))
        {
            if (user != null)
            {
                // get info about Alice into userInfo
                return userInfo;
            }
        }   
    }

    return null;
}

所以如果我使用var aliceInfo = search.FindOne("alice");,我会从目录中获取信息。现在我需要搜索给定多个用户登录名的目录(1000 多个用户),例如

var userInfos = search.FindMany(/* list of names: alice, jay, harry*/);

如何实现以下方法?

public List<UserInfo> FindMany(List<string> samUserNames)
{
    ...
}

【问题讨论】:

    标签: c# active-directory directoryservices


    【解决方案1】:

    试试这个:

    string query = "dc=com,dc=domainController,ou=Users"; //this is just an example query, change it to suit your needs
    
    // create your domain context and define the OU container to search in
    PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "yourDomain", query);
    
    // define a "query-by-example" principal - here, we search for a UserPrincipal (user)
    UserPrincipal qbeUser = new UserPrincipal(ctx);
    
    // create your principal searcher passing in the QBE principal    
    PrincipalSearcher srch = new PrincipalSearcher(qbeUser);
    
    return srch.FindAll().Select(p => p as UserPrincipal);
    

    这样您可以从 AD 返回所有用户,然后过滤掉您不需要的用户。 UserPrincipal 有一些与用户相关的属性,例如 Surname 和 Sid,但是如果您需要获取 UserPrincipal 没有的值,您可以创建一个扩展方法并访问任何 LDAP 属性:

        public static String GetProperty(this Principal principal, String property)
        {
            DirectoryEntry directoryEntry = principal.GetUnderlyingObject() as DirectoryEntry;
            if (directoryEntry.Properties.Contains(property))
                return directoryEntry.Properties[property].Value.ToString() ?? "";
            else
                return String.Empty;
        }
    

    这里是 LDAP 属性列表:https://fsuid.fsu.edu/admin/lib/WinADLDAPAttributes.html

    【讨论】:

    • System.DirectoryServices.AccountManagement 非常慢,所以这样做而不是逐一检查对于较长的列表会更好,但对于较短的列表会更糟。
    • 感谢您的回答,但我认为这不适用于大型广告。不幸的是,使用srch.FindAll() 转移所有用户非常慢。
    • 您可以更改 LDAP 查询以仅获取您想要的用户。您甚至可以按名称过滤,但如果您需要获得成千上万的用户,您最终会得到一个怪物查询(我不确定查询大小是否有任何限制)
    【解决方案2】:

    如果您的列表相对较小,最灵活的解决方案可能是循环并逐个查找用户。

    替代方案是:

    • 在 LDAP 查询中提供过滤器。由于您没有要过滤的通用属性,因此您需要使用所有用户名创建一个“OR”LDAP 过滤器。这并没有比循环更好地扩展到大量用户。

    • 遍历目录中的所有用户,过滤搜索结果以提取与您的列表匹配的用户。这不能很好地扩展到大型 AD,因为它没有利用 samAccountName 是索引属性这一事实。

    【讨论】:

    • 接受这个作为答案。我的情况似乎没有任何干净的 API。我不喜欢手动构建查询字符串并将其与底层 LDAP 对象一起使用。所以我决定使用单个上下文并遍历用户列表,为每个用户对域控制器进行单独的查询。此外,我会将我只需要的属性列入白名单,因此每个响应都不会附带记录碰巧存储的大量卫星数据。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-08
    • 2019-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多