【问题标题】:Active Directory: Get RootDSE in domain residing in Forest with multiple roots?Active Directory:在具有多个根的 Forest 域中获取 RootDSE?
【发布时间】:2011-05-14 13:45:59
【问题描述】:

我有一个使用我编写的 Windows 服务的客户端,该服务轮询指定的活动目录 LDAP 服务器,以查找该 LDAP 服务器中指定组中的用户。

一旦找到用户,它就会填写用户信息(即用户名、电子邮件等)并尝试在该 LDAP 服务器中检索用户的域。

当我尝试为此特定客户端检索用户的域时,我遇到了 DirectoryServicesCOMException: Logon failure: unkonwn user name or bad password。 当我尝试引用我实例化的 RootDSE DirectoryEntry 对象上的属性时,将引发此异常。

这个客户端有一个有两个根的 Forest,设置如下。

Active Directory 域和信任

  • ktregression.com

  • ktregression.root

我认为这是问题所在。 有没有办法解决?有什么方法可以在不遇到此异常的情况下仍然检索特定域对象的 netbiosname?

这里是一些示例代码,指向之前记录的测试 AD 服务器设置:

        string domainNameLdap = "dc=tempe,dc=ktregression,dc=com";

        DirectoryEntry RootDSE = new DirectoryEntry (@"LDAP://10.32.16.6/RootDSE");
        DirectoryEntry servers2 = new DirectoryEntry (@"LDAP://cn=Partitions," + RootDSE.Properties["configurationNamingContext"].Value ); //*****THIS IS WHERE THE EXCEPTION IS THROWN********

        //Iterate through the cross references collection in the Partitions container
        DirectorySearcher clsDS = new DirectorySearcher(servers2);
        clsDS.Filter = "(&(objectCategory=crossRef)(ncName=" + domainNameLdap + "))";
        clsDS.SearchScope = SearchScope.Subtree;
        clsDS.PropertiesToLoad.Add("nETBIOSName");

        List<string> bnames = new List<string>();

        foreach (SearchResult result in clsDS.FindAll() )
            bnames.Add(result.Properties["nETBIOSName"][0].ToString());

【问题讨论】:

  • 您是否确定RootDSE.Properties["configurationNamingContext"].Value 返回的值实际上不为空,或者遵守LDAP://CN=Partitions,DC=ktregression,DC=com 等的LDAP 命名法?
  • 你看过我为你昨天的其他类似问题提供的代码示例吗?
  • @Will,是的,我看了一下并试了一下。我实际上用另一个问题回答了这个问题。我想我实际上有两个不同的问题,这也是我开始这个问题的原因。我在一个森林中有两个根的实例的问题。
  • 至于确保 RootDSE.Properties["configurationNamingContext"].Value 返回一个值并且不为空,我无法进行该检查,因为第二次我尝试检索它是否具有值,抛出异常。
  • @Micheal:我明白你的意思。请你清楚地解释你的目标是什么,忘记代码和其他一切,只是告诉你需要完成什么,以便我下定决心。在过去的几周里,我做了很多工作,但仍然使用 Active Directory。我希望我能进一步帮助你。再想一想,鉴于您有两个不同的根,为什么不简单地创建两个独立的 DirectoryEntry 类实例来代表您的每个根,并使用它们?

标签: c# active-directory


【解决方案1】:

Active Directory 尝试对“您”进行身份验证的用户帐户似乎不存在,因为您的 DirectoryServicesCOMException 报告了它。

DirectoryServicesCOMException:登录失败:未知用户名或密码错误。

查看您的代码示例,您似乎没有使用模拟,因此 Active Directory 的安全协议考虑了当前经过身份验证的用户。自己创建这个用户,然后如果你碰巧没有在你的两个域根上定义,其中一个不认识你,这会引发这种异常。

另一方面,使用模拟可能会解决这里的问题,因为您说您的 Windows 服务帐户有权查询同一林下的两个根,那么您必须确保经过身份验证的用户是您的Windows 服务。

很明显,这意味着如果没有模拟,您无法保证经过身份验证的用户就是您的 Windows 服务。为了确保这一点,模仿是必须使用的。

现在,关于两个根

  1. ktregression.com;
  2. ktregression.root.

这是两个不同且独立的根。因此,我想您应该使用两个 DirectoryEntry 类实例,每个根对应一个。

实例化根后,您需要搜索要查找的用户,该用户应与被模拟的用户不同userName

我们现在必须说明是否可以在两个根上定义用户。如果是这样,您将需要知道何时选择一个比另一个更好。这是另一个问题。

注意
为了简单起见,我认为两个根的名称都是完整的/完整的,正如你提到的那样。

private string _dotComRootPath = "LDAP://ktregression.com";
private string _dotRootRootPath = "LDAP://ktregression.root";
private string _serviceAccountLogin = "MyWindowsServiceAccountLogin";
private string _serviceAccountPwd = "MyWindowsServiceAccountPassword";

public string GetUserDomain(string rootPath, string login) {
    string userDomain = null;

    using (DirectoryEntry root = new DirectoryEntry(rootPath, _serviceAccountLogin, _serviceAccountPwd)) 
        using (DirectorySearcher searcher = new DirectorySearcher()) {
            searcher.SearchRoot = root;
            searcher.SearchScope = SearchScope.Subtree;
            searcher.PropertiesToLoad.Add("nETBIOSName");
            searcher.Filter = string.Format("(&(objectClass=user)(sAMAccountName={0}))", login);

            SearchResult result = null;

            try {
                result = searcher.FindOne();

                if (result != null) 
                    userDomain = (string)result.GetDirectoryEntry()
                                    .Properties("nETBIOSName").Value;                                     
            } finally {
                dotComRoot.Dispose();
                dotRootRoot.Dispose();
                if (result != null) result.Dispose();
            }
        }            

    return userDomain;
}

并使用它:

string userDomain = (GetUserDomain(_dotComRoot, "searchedLogin") 
                        ?? GetUserDomain(_dotRootRoot, "searchedLogin")) 
                    ?? "Unknown user";

您的异常仅在第二次 DirectoryEntry 初始化时引发,这表明您的默认当前用户没有在此根目录上定义帐户。

编辑#1

请在下面查看我对您的其他 NetBIOS 名称相关问题的回答:
C# Active Directory: Get domain name of user?
在这里,我为您的问题提供了一个新的、可能更简单的解决方案。

如果您还有其他问题,请告诉我。 =)

【讨论】:

    【解决方案2】:

    我相信 DirectoryEntry 具有为 AD 帐户指定可以执行 LDAP 查询或更新的属性,您也可以从您的父域委派该控制权。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-04
      • 2011-05-14
      • 1970-01-01
      相关资源
      最近更新 更多