Active Directory:在具有多个根的林中的域中获取RootDSE?

时间:2010-11-23 16:10:10

标签: c# active-directory

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

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

当我尝试检索此特定客户端的用户域时,我遇到了DirectoryServicesCOMException:登录失败:unkonwn用户名或密码错误。 当我尝试在我实例化的RootDSE DirectoryEntry对象上引用属性时抛出此异常。

此客户端有一个具有两个根的林,设置如下。

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

2 个答案:

答案 0 :(得分:2)

似乎Active Directory尝试对您进行身份验证的用户帐户不存在,因为DirectoryServicesCOMException会对其进行身份验证。

  

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

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

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

清楚,这意味着在没有模拟的情况下,您无法保证经过身份验证的用户是您的Windows服务。为了确保这一点,模仿是必须使用的。

现在,关于两个根

  1. ktregression.com;
  2. ktregression.root。
  3. 这是两个不同的独立根源。因此,我猜你应该使用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?
    在那里,我为您的关注提供了一种新的,可能更简单的解决方案。

    如果您有任何进一步的问题,请与我们联系。 =)

答案 1 :(得分:0)

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