【问题标题】:Can't query AD (get a DirectoryServicesCOMException)无法查询 AD(获取 DirectoryServicesCOMException)
【发布时间】:2023-06-04 07:22:01
【问题描述】:

我正在尝试在 Windows Server 2008 R2(安装了 IIS7)上运行的 ASP.Net (4.0) 应用程序中查询 AD。 (作为 2.0 应用程序运行时也会失败)

这对我来说并不新鲜,因为我以前做过很多次。我编写了一个小的 ASP.Net 程序,它在我自己的机器上运行良好(带有 IIS6 的 Windows XP),但在 2008 机器上运行时失败。

(结果是您在文本框中看到用户所属的组列表)

(on button_click) 
var userName = txtUserName.Text;

if (userName.Trim().Length == 0)
{
     txtResults.Text = "-- MISSING USER NAME --";
     return;
}

var entry = new DirectoryEntry("LDAP://blah.blah/DC=blah,DC=blah",
                               "cn=acct, dc=blah, dc=blah",
                               "pass");

var search = new DirectorySearcher(entry);
search.Filter = "(SAMAccountName=" + userName + ")";
search.PropertiesToLoad.Add("memberOf");

var groupsList = new StringBuilder();

var result = search.FindOne();

if (result != null)
{
   int groupCount = result.Properties["memberOf"].Count;

   for (int counter = 0; counter < groupCount; counter++)
   {
           groupsList.Append((string)result.Properties["memberOf"][counter]);
           groupsList.Append("\r\n");
    }
}

txtResults.Text = groupsList.ToString();

当我运行此代码时,我在 search.FindOne() 上收到以下错误:

System.DirectoryServices.DirectoryServicesCOMException (0x8007203B): A local error has occurred.

   at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)
   at System.DirectoryServices.DirectoryEntry.Bind()
   at System.DirectoryServices.DirectoryEntry.get_AdsObject()
   at System.DirectoryServices.DirectorySearcher.FindAll(Boolean findMoreThanOne)
   at System.DirectoryServices.DirectorySearcher.FindOne()
   at WebApplication1._Default.btnSearch_Click(Object sender, EventArgs e)

我们已经对此进行了大量研究,并调整了我们能想到的每一个 IIS7 设置,但到目前为止还没有。有什么线索吗?

【问题讨论】:

    标签: c# asp.net windows windows-server-2008 directoryservices


    【解决方案1】:

    将用户名参数从“cn=xxx, dc=yyy, dc=zzz”更改为“Domain\Username”

    【讨论】:

    • 在 Windows 7 上遇到了同样的问题,但在 WinXP 上运行良好。谢天谢地,我的同事给我发了这篇文章。谢谢。
    【解决方案2】:

    您还可以更改 IIS 应用程序池以运行具有您正在搜索的查询权限的域帐户。

    我还有一些其他的 cmets:

    1. 确保 DirectoryEntry 构造函数的第一个条目也包括用户的容器。这应该有助于 DirectorySearcher 更可靠地工作。
    2. 我认为 DirectoryEntry 构造函数中的第二个参数应该是用户名,而不是 AD 查询路径。
    3. 您还应该设置 AuthenticationType 属性。对于 Server 2008,默认情况下,这需要设置为 AuthenticationTypes.Secure | AuthenticationTypes.ServerBind | AuthenticationTypes.密封。我猜想 2008R2 也有类似的要求。

    【讨论】:

      【解决方案3】:

      我看到这个问题相当老了,但是在努力解决这个问题之后,我想提到确实可以使用用户名的 LDAP 样式(与 DNS 样式相反)。这对我很有效:

          string connString = "LDAP://MyDomain/CN=blah,DC=blah,DC=blah";
          string username = "CN=MyAdmin,CN=Users,CN=blah,DC=blah,DC=blah";
          string password = "myLittleSecret";
          DirectoryEntry root = new DirectoryEntry(
               connString, 
               username, 
               password, 
               AuthenticationTypes.None);
      

      其中MyAdminAdministrators 角色的成员。

      我花了一段时间才找到的一个小东西是AuthenticationTypes.None 参数,如果您不想通过 SSL 进行通信,则需要该参数。当然,您想在生产中执行此操作,但出于开发目的,跳过加密可能是可以的。

      环境:Windows 7

      【讨论】:

        【解决方案4】:

        我在尝试查询活动目录时也遇到了这个异常:

        SearchResult result = srch.FindOne();
        

        要解决这个问题,只需将上面的代码放入Security.RunWithElevatedPrivileges()

        最终解决方案:

        SPSecurity.RunWithElevatedPrivileges(delegate()
        {
            result = srch.FindOne();
        });
        

        【讨论】: