DirectorySearcher / LDAP查找从IIS部署环境失败,从同一台计算机上的控制台工作

时间:2013-09-20 21:10:57

标签: c# iis active-directory ldap iis-8

我们在ASP.NET MVC 4应用程序中执行了一些代码。该应用程序托管在Windows Server 2012上的IIS中。应用程序池的标识不是标准的,而是特定的用户,例如iis-appPool-username如下所述。该应用程序在.NET 4.0中运行,并为Managed Pipeline设置了集成模式。

  • 无论是否在DirectoryEntry对象中指定了用户名,我都尝试了它。
  • 我可以运行一个控制台应用程序来执行相同的操作,就像在同一台机器上的同一个用户(command.exe作为同一个用户运行)一样,并且它可以工作。
  • 应该注意的是,在我手动指定LDAP路径 AuthenticationTypes.ReadonlyServer之前,控制台应用工作,因为它是只读的域控制器。在我指定LDAP路径和Readonly类型之前,它为控制台应用程序提供了相同的错误。但是,虽然控制台应用程序现在可以使用,但IIS应用程序却没有。

代码如下。

// also tried: var searchRoot = new DirectoryEntry(@"LDAP://DC=subdom,DC=ourdomain,DC=com");
var searchRoot = new DirectoryEntry(@"LDAP://DC=subdom,DC=ourdomain,DC=com", @"domain\iis-appPool-username", "password");
searchRoot.AuthenticationType = AuthenticationTypes.ReadonlyServer;

using (var searcher = new DirectorySearcher(searchRoot))
{
    searcher.Filter = string.Format("(&(objectClass=group)(sAMAccountName={0}))", "someGroupName");
    searcher.PropertiesToLoad.Add("distinguishedName");

    // This is where the failure happens
    var result = searcher.FindOne();
}

堆栈跟踪的错误如下所示:

System.Runtime.InteropServices.COMException (0x8007054B): 
The specified domain either does not exist or could not be contacted.

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.DirectorySearcher.get_SearchRoot()
at System.DirectoryServices.DirectorySearcher.FindAll(Boolean findMoreThanOne)
at System.DirectoryServices.DirectorySearcher.FindOne()

编辑:此外,如果我明确使用错误的用户名和密码,则会出现同样的错误。从我的本地机器,如果我使用错误的用户名和密码,我得到一个auth错误。但是,从IIS,用户名和密码错误,它甚至都没有那么远。

编辑:我在web.config中指定以完全信任的方式运行:

<securityPolicy>
    <trustLevel name="Full" policyFile="internal"/>
</securityPolicy>

我们还在框中为用户提供了管理员权限。继续收到同样的错误:System.Runtime.InteropServices.COMException: The specified domain either does not exist or could not be contacted.

更新:所以,这最终是两个问题的组合。

1)正如下面提到的@Hans,我最初错过了DirectoryEntry DirectorySearcher参数。在我尝试不同的可能性,组合的过程中,当我有一个工作的控制台应用程序并且正在更新应用程序代码以反映它时,我设法错过了这个更改。

2)当我将参数添加到DirectorySearcher时,我仍然收到错误。消息相同,堆栈跟踪几乎相同。堆栈跟踪中间有1行不同 - 对另一个需要DirectoryEntry参数的方法的辅助调用在其自己的DirectorySearcher中使用。我一直在看问题这个问题,我的眼睛只看到相同的错误信息和看起来是相同的堆栈跟踪,实际上它是一个新的。将DirectoryEntry对象传递给那些调用可以解决这个问题。

最终的解决方案要求我在路径中有一个服务器标识符(但如果您的环境无法解析域控制器,您的里程可能会有所不同。)

1 个答案:

答案 0 :(得分:5)

您必须按顺序指定DirectorySearcher类的搜索根 连接到Active Directory域控制器。 如果不这样做,您将获得 COM异常(0x8007054B) 指定DirectorySearcher类的搜索根。

请尝试以下代码行:

var searchRoot = new DirectoryEntry(@"LDAP://DC=subdom,DC=ourdomain,DC=com", @"domain\iis-appPool-username", "password");
searchRoot.AuthenticationType = AuthenticationTypes.ReadonlyServer;

using (var searcher = new DirectorySearcher(searchRoot)) // Specify the search root here
{
  searcher.Filter = string.Format("(&(objectClass=group)(sAMAccountName={0}))", "someGroupName");
  searcher.PropertiesToLoad.Add("distinguishedName");

  var result = searcher.FindOne();
}