将我的网站部署到IIS7.5后,我发现了一个奇怪的行为:默认情况下,当应用程序池标识为ApplicationPoolIdentity
时(按照IIS Application Pool Identities中的建议), {{1}似乎被忽略了,因为我在创建第一个控制器时遇到以下错误:
System.InvalidOperationException:尝试时发生错误 创建一个类型的控制器 '..MainController'。确保 控制器有一个无参数的公共构造函数。 ---> System.DirectoryServices.DirectoryServicesCOMException:一个操作 发生了错误。
我尝试将Ninject
授予FullAccess
到包含该网站的文件夹(包括所有子文件夹和文件),但这并没有改变任何内容。
但是,当我将应用程序池标识设置为任何域帐户(即使是简单的帐户,没有管理权限,也没有对该站点的文件夹的任何访问权限)时,它可以正常工作。
Ninject是根据Setting up an MVC3 application教程通过NuGet包安装的。
我不确定,如果相关,该网站应该在域内网中使用Windows身份验证。
因此,唯一的问题似乎是应用程序池标识。至于我渴望使用推荐的方式,我希望拥有IIS AppPool\<MySiteAppPool>
,而不是域帐户。
这可以与之相关联?是否可以将所有这些混合在一起?
这是一个有类似问题的SO主题:ASP.NET MVC 4 + Ninject MVC 3 = No parameterless constructor defined for this object。但是根本没有合适的答案。
如建议删除的评论,我尝试使用ApplicationPoolIdentity
作为身份。它运作正常。但是,我想这并不比非特权域帐户好得多。
修改
突然发现另一个依赖:应用程序池标识用于sql server上的Windows身份验证,但我希望在那里使用客户端用户的凭据。
基于评论
同意通过模拟可以使用经过身份验证的凭据访问远程sql server。
然而,仍然不清楚ApplicationPoolIdentity和Ninject的问题是什么。
在这个问题的最上面提到的文章让我想到这可能是因为虚拟帐户没有用户个人资料这一事实。这个方面对我来说仍然不清楚,因为仍然可以使IIS加载具有NetworkSerive
属性的用户配置文件。如果虚拟帐户没有配置文件,我无法获取,IIS将加载什么?
据说:
IIS不会加载Windows用户配置文件,但会加载某些应用程序 无论如何都可以利用它来存储临时数据。 SQL Express 是执行此操作的应用程序的示例。但是,一个用户 必须创建配置文件以将临时数据存储在 配置文件目录或注册表配置单元。用户配置文件 NETWORKSERVICE帐户由系统创建,始终是 可用。但是,切换到唯一的应用程序池 身份,系统不会创建用户配置文件。只有 标准应用程序池(DefaultAppPool和Classic .NET AppPool) 在磁盘上有用户配置文件。如果没有创建用户配置文件 管理员创建一个新的应用程序池。
但是,如果需要,可以配置要加载的IIS应用程序池 通过将“LoadUserProfile”属性设置为“true”来设置用户配置文件。
我在serverfault.com上找到了以下主题:
How can I assign active directory permission to the default app pool identity
还指出,应用程序池标识无法用作网络服务,尤其是查询AD。
答案 0 :(得分:9)
iispool \ appPoolName帐户被称为虚拟帐户&amp;已添加到Windows 2008.这个想法认为它们并不是真正意义上的真实帐户。他们允许的是增强使用基本帐户的流程之间的安全性。
您计算机上的许多服务都使用networkService,这是一个具有网络访问权限的内置帐户。因此,如果攻击者要利用其中一种服务,则可以访问在同一帐户下运行的任何其他进程。虚拟帐户,例如IIS使用的虚拟帐户,通过显示为不同的帐户来防止这种情况,同时仍然是同一个帐户 - 您的asp.net应用程序在技术上仍然作为网络服务运行。授予此帐户访问权限shoudl仍然有效。这也意味着如果您需要访问网络资源,iispool帐户将这样做,因为网络服务和&amp;使用机器域帐户。
如果要访问远程sql server,则应添加此帐户以允许从Web服务器进行访问。我不建议使用模拟,除非你真的需要查看用户在SQL服务器上的用户。如果您将其关闭,您的应用安全性会更加简单。
为什么你的注射不起作用,可能是你的任何依赖都失败了。如果控制器A注入ClassB,而ClassB又注入ClassC&amp;那个类没有注入ClassD,那么整个链就失败了。我已经发生了这种情况我花了一段时间才意识到它已经从我所看到的东西中消失了。
答案 1 :(得分:2)
从问题中的细节来看,这听起来很像是导致COMException
被抛出的权限问题,这阻止了Ninject实例化MainController
。该异常与System.DirectoryServices
相关,COMException
是用于查询Active Directory的类。
当IIS在正常的应用程序池帐户下运行时,这些帐户无权对Active Directory进行查询,并且可以抛出System.DirectoryServices
。我认为异常中的实际消息(找不到无参数构造函数)有点像红色鲱鱼,并且Ninject试图回退到另一个构造函数,因为正常的消息不起作用。
这可以解释为什么当您更改IIS应用程序池以作为域帐户运行时,它突然起作用,因为该帐户确实有权查询域。
从问题中你是否自己使用DirectorySearcher
或者Ninject / IIS / ASP是否正在使用它们并不清楚。如果您自己使用它们,请确保AD类中的任何构造函数都不会抛出异常(捕获它们并记录它们或其他东西),这将阻止您的应用程序在启动时崩溃。你可能会发现我上面谈到的关于权限的内容。
如果您需要IIS作为普通应用程序池帐户运行(这是一个好主意),但仍然将AD作为域用户进行查询,那么您可以将凭据指定为DirectoryEntry
并使用{{1}}进行AD搜索。如果您使用的是.Net 4或更高版本,那么我建议您使用新的System.DirectoryServices.AccountManagement
类(这也允许您指定凭据)。
使用该方法,您不需要对AD查询进行任何模拟,您的应用程序池仍可以作为普通的应用程序池帐户运行。