无法在 IIS 托管应用程序上使用 System.DirectoryServices.AccountManagement 获取 LDAP 数据

Cannot get LDAP data using System.DirectoryServices.AccountManagement on IIS hosted app

我正在使用 System.DirectoryServices.AccountManagement 包从 LDAP 获取用户数据,它在我的本地机器上工作正常,但在服务器上,它给出错误提示:

**发生操作错误。

at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)
   at System.DirectoryServices.DirectoryEntry.Bind()
   at System.DirectoryServices.DirectoryEntry.get_AdsObject()
   at System.DirectoryServices.PropertyValueCollection.PopulateList()
   at System.DirectoryServices.PropertyValueCollection..ctor(DirectoryEntry entry, String propertyName)
   at System.DirectoryServices.PropertyCollection.get_Item(String propertyName)
   at System.DirectoryServices.AccountManagement.PrincipalContext.DoLDAPDirectoryInitNoContainer()
   at System.DirectoryServices.AccountManagement.PrincipalContext.DoDomainInit()
   at System.DirectoryServices.AccountManagement.PrincipalContext.Initialize()
   at System.DirectoryServices.AccountManagement.PrincipalContext.get_QueryCtx()
   at System.DirectoryServices.AccountManagement.PrincipalSearcher.SetDefaultPageSizeForContext()
   at System.DirectoryServices.AccountManagement.PrincipalSearcher..ctor(Principal queryFilter)  

**

.NET Core 版本为 3.1,System.DirectoryServices.AccountManagement 版本为 6.0,应用程序托管在 VM 上的 IIS 上(IIS 版本 8.0)。我使用的代码是:

List < ApplicationUser > users = new List < ApplicationUser > ();

using(var ctx = new PrincipalContext(ContextType.Domain, "mydomain")) {

  var userPrinciple = new UserPrincipal(ctx);
  using(var search = new PrincipalSearcher(userPrinciple)) {
    var results = search.FindAll().OrderBy(u => u.DisplayName);
    foreach(UserPrincipal domainUser in results) {
      var adUser = new ApplicationUser {
          Email = domainUser.EmailAddress,
          FirstName = domainUser.Name,
          PhoneNumber = domainUser.VoiceTelephoneNumber,
          UserName = domainUser.UserPrincipalName,
          EmployeeId = domainUser.EmployeeId
      };

      if (!String.IsNullOrWhiteSpace(adUser.Email)) {
        users.Add(adUser);
      }

    }
  }
}

到目前为止,我已尝试将应用程序池标识更改为网络服务,但没有成功。

堆栈跟踪显示异常发生在 DirectoryEntry.Bind,也就是它最初连接到 AD 时。所以你的电脑和服务器之间一定有什么不同。

服务器是否可以访问域?是否有防火墙阻止访问?

您的计算机是否加入了域,但服务器没有?如果是这种情况,请尝试在 PrincipalContext 构造函数中使用域的完整 DNS 名称,如果您还没有这样做的话(例如 mydomain.com 而不仅仅是 mydomain)。

您是否在服务器上使用模拟?如果是这样,那可能就是问题所在。看这里:

那是在解决 ASP.NET(不是核心)问题,但这可能是一个类似的问题。

经过大量搜索,我找到了一个替代解决方案:

List<ApplicationUser> users = new List<ApplicationUser>();
       
        using (var root = new DirectoryEntry(_ladapSettings.LDAPPathString, _ladapSettings.UserName, _ladapSettings.Password))
        {
            using (var searcher = new DirectorySearcher(root))
            {
                searcher.Filter = $"(&(objectCategory=person)(objectClass=user)(|(displayName=*{filter})(displayName={filter}*)))";
                var query = searcher.FindAll();

                foreach (SearchResult results in query)
                {
                    var de = results.GetDirectoryEntry();

                    if(de != null)
                    {

                        var adUser = new ApplicationUser
                        {
                            Email = de.Properties["mail"].Value?.ToString(),
                            UserName = de.Properties["mail"].Value?.ToString(),
                            FirstName = de.Properties["givenname"].Value?.ToString(),
                            LastName = de.Properties["sn"].Value?.ToString(),
                            PhoneNumber = de.Properties["telephoneNumber"].Value?.ToString(),
                            EmployeeId = de.Properties["employeeid"].Value?.ToString()
                        };

                        if (!String.IsNullOrWhiteSpace(adUser.Email))
                        {
                            users.Add(adUser);
                        }

                    }
                }
            }

这在本地机器和服务器上都能正常工作。