如何在具有多个树的AD林中的全局编录中搜索用户

时间:2013-09-09 09:01:10

标签: c# dns active-directory userprincipal

我有以下带有两棵树的AD林:

  1. 域1。有两个子域Domain2和Domain3
  2. Domain4。没有子域名。
  3. Domain1的DNS名称是 domain1.local 。 Domain4的DNS名称是 domain4.local

    在每个域中都有一个启用了全局编录的域控制器。

    我正在尝试通过其SID从域4获取UserPrincipal。该程序从Domain2中的计算机运行。

    我使用以下代码:

    // Running on some machine from Domain2
    PrincipalContext context = new PrincipalContext(
        ContextType.Domain,
        "dc2.domain2.domain1.local:3268", // Using Global Catalog port and local domain controller
        "DC=domain1, DC=local", // I guess the problem is here
        "domain1\\super-admin", // User has all necessary rights across all domains 
        "password");
    
    UserPrincipal principal = UserPrincipal.FindByIdentity(context, "SID-OF-A-USER-FROM-DOMAIN-4");
    

    在我的情况下,principal为null(找不到用户)。

    在一个树(domain1及其子代)中搜索可以正常使用上面的代码片段,但我不知道如何修改PrincipalContext构造函数的容器参数以真正启用林范围的搜索。

    最初我认为“DC = domain1,DC = local”指向了林根,但似乎我在这里有误解。

    我知道如果我将容器路径更改为“DC = domain4,DC = local”,那么搜索将起作用,但仅适用于domain4中的用户。

    但我确实需要这样一个指向整个林的容器路径,因此我可以使用相同的PrincipalContext从林中的任何域搜索用户。

    任何帮助都表示赞赏,特别是如果有人能澄清我的要求是否可以实现。

1 个答案:

答案 0 :(得分:6)

除了切换到DirectorySearcher之外,我们找不到任何其他解决方案。所以看来PrincipalContext类并不完全支持在整个森林中进行搜索。

我不能说这个解决方案很理想。我想可以调整它以获得更好的性能。但我们真的很失望,无法使用PrincipalContext完成。

以下是我们的代码现在如何运作的粗略概念:

...

// Here is a list of SIDs of users we want to find (initialized somewhere above)
List<string> userSids;

// List of sample results.
List<string> loadedUsers = new List<string>();

using (DirectorySearcher searcher = new DirectorySearcher(new DirectoryEntry("GC://dc2.domain2.domain1.local")))
{
    StringBuilder filterStringBuilder = new StringBuilder();

    // Just create a single LDAP query for all user SIDs
    filterStringBuilder.Append("(&(objectClass=user)(|");
    foreach (string userSid in users)
    {
        filterStringBuilder.AppendFormat("({0}={1})", "objectSid", userSid);
    }

    filterStringBuilder.Append("))");

    searcher.PageSize = 1000; // Very important to have it here. Otherwise you'll get only 1000 at all. Please refere to DirectorySearcher documentation

    searcher.Filter = filterStringBuilder.ToString();

    // We do not want to go beyond GC
    searcher.ReferralChasing = ReferralChasingOption.None;

    searcher.PropertiesToLoad.AddRange(
        new[] { "DistinguishedName" });

    SearchResultCollection results = searcher.FindAll();

    foreach (SearchResult searchResult in results)
    {
        string distinguishedName = searchResult.Properties["DistinguishedName"][0].ToString();
        loadedUsers.Add(distinguishedName);
    }
}

...