(这是一个关于模糊问题的问题。我尝试提供所有相关数据,希望有人能提供有用的信息;对冗长的描述表示歉意。)
我们的网络应用程序
我们有一个在 IIS 7.5 中运行的 .NET 4 Web 应用程序,用于访问 Active Directory 和 SQL Server 数据库。
此 Web 应用程序在虚拟“应用程序池身份”下运行,通过将应用程序的应用程序池的身份设置为应用程序池身份 http://msdn.microsoft.com/en-us/library/bb386459.aspx。虚拟身份的简明描述可以在StackOverflow 的答案 https://stackoverflow.com/a/3680803,以及它所引用的博客文章:应用程序池标识只是添加到作为“网络服务”运行的 Web 应用程序的工作进程中的附加组。然而,一个来源 http://forums.iis.net/p/1171701/1957045.aspx#1957045含糊地暗示“网络服务和 ApplicationPoolIdentity 确实存在 IIS.net 站点文档未发布的差异”。因此,虚拟身份可能不仅仅是一个额外的群体。
我们选择使用 ApplicationPoolIdentity,而不是 NetworkService,因为它成为 IIS 7.5 中的默认设置(例如,请参阅here http://msdn.microsoft.com/en-us/library/bb386459.aspx#attributesAndElementsToggle),并根据 Microsoft 的建议:“此身份允许管理员指定仅与应用程序池运行所在的身份相关的权限,从而提高服务器安全性。” (从用于为 applicationPools 添加的 processModel 元素 [IIS 7 设置架构] http://msdn.microsoft.com/en-us/library/bb386459.aspx#attributesAndElementsToggle)“应用程序池身份是一项强大的新隔离功能”,它“使运行的 IIS 应用程序更加安全可靠。”(来自IIS.net 文章“应用程序池标识” http://learn.iis.net/page.aspx/624/application-pool-identities/)
该应用程序使用集成 Windows 身份验证,但使用<identity impersonate="false"/> http://msdn.microsoft.com/en-us/library/72wdk8cc.aspx,这样就不会使用最终用户的身份,而是使用虚拟应用程序池身份来运行我们的代码。
此应用程序使用以下方式查询 Active Directory系统目录服务 http://msdn.microsoft.com/en-us/library/system.directoryservices.aspx类,即 ADSI API。在大多数地方,这是在不指定额外的用户名/密码或其他凭据的情况下完成的。
该应用程序还使用以下方式连接到 SQL Server 数据库Integrated Security=true
在连接字符串中。如果数据库是本地的,那么我们会看到IIS APPPOOL\OurAppPoolName
用于连接数据库;如果数据库是远程的,则机器帐户OURDOMAIN\ourwebserver$
用来。
我们的问题
我们经常遇到工作安装因以下方式之一开始失败的问题。
当数据库位于远程系统上时,数据库连接开始失败:“用户‘NT AUTHORITY\ANONYMOUS LOGON’登录失败。原因:基于令牌的服务器访问验证因基础结构错误而失败。检查以前的错误。”上一个错误是“错误:18456,严重性:14,状态:11”。所以看来现在OURDOMAIN\ourwebserver$
不再使用,而是尝试匿名访问。 (我们有轶事证据表明,这个问题在 UAC 关闭时发生,并且在打开 UAC 后消失。但请注意,更改 UAC 需要重新启动...)报告了类似的问题IIS.net 线程“使用 ApplicationPoolIdentity 连接到 SQL” http://forums.iis.net/t/1181039.aspx,特别是在一个回复 http://forums.iis.net/p/1181039/2010748.aspx#2010748.
通过 ADSI (System.DirectoryServices) 的 Active Directory 操作开始失败,并出现错误 0x8000500C(“未知错误”)、0x80072020(“发生操作错误。”)或 0x200B(“指定的目录服务属性或值不存在”) 。
从 Internet Explorer 登录应用程序开始失败,并出现 HTTP 401 错误。但如果在 IIS 中我们将 NTLM 放在 Negotiate 之前,那么它会再次起作用。 (请注意,Kerberos 需要访问 AD,但 NTLM 不需要。)在IIS.net 线程“Windows 身份验证因 AppPool Identity 失败” http://forums.iis.net/t/1171701.aspx.
我们的假设和解决方法
至少,当将应用程序池从 ApplicationPoolIdentity 切换到 NetworkService 时,AD 和登录问题似乎总是消失。 (我们发现一份报告 http://forums.iis.net/p/1181039/2010748.aspx#2010748证实了这一点。)
Page “解决 ASP 页面上的身份验证问题” http://msdn.microsoft.com/en-us/library/ms180891.aspx有一些与主要和次要令牌相关的建议,我发现令人鼓舞的是它链接了我们的前两个错误:它提到NT AUTHORITY\ANONYMOUS LOGON
访问,AD 错误 0x8000500C 和“指定的目录服务属性或值不存在”。
(同一页面还提到了 ADSI 架构缓存问题,但我们在该主题上找到的所有内容都是旧的。目前我们认为这是不相关的。)
综上所述,我们目前的工作假设就是,仅当在虚拟应用程序池身份下运行时,我们的 Web 应用程序(IIS?工作进程?)突然丢失了其主令牌,这样IIS只有一个辅助令牌,这样所有对Active Directory和SQL Server的访问都是匿名完成的,从而导致上述所有错误。
现在我们打算从 ApplicationPoolIdentity 切换到 NetworkService。希望这能让上述所有问题消失。但我们不确定;如果可能的话我们想切换回来。
我们的问题
上述假设是否正确?如果正确,这是 IIS/Windows/.NET 中的错误吗?在什么情况下会发生这种主要代币损失?