9

将我的网站部署到 IIS7.5 后,我发现了一种奇怪的行为:当应用程序池标识ApplicationPoolIdentity默认保留时(如IIS 应用程序池标识中所建议的那样),Ninject似乎被忽略了,因为我在创建非常第一个控制器:

System.InvalidOperationException:尝试创建类型为“..MainController”的控制器时发生错误。确保控制器有一个无参数的公共构造函数。---> System.DirectoryServices.DirectoryServicesCOMException:发生操作错误。

我试图授予FullAccess包含IIS AppPool\<MySiteAppPool>站点(包括所有子文件夹和文件)的文件夹,但这并没有改变任何东西。

但是,当我将应用程序池标识设置为任何域帐户时(即使是一个简单的帐户,没有管理权限,也没有对站点文件夹的任何访问权限),它可以正常工作。

根据通过 NuGet 包设置 MVC3 应用程序教程安装 Ninject。

我不确定,如果相关,该站点应该在具有 Windows 身份验证的域 Intranet 中工作。

因此,唯一的问题似乎是应用程序池标识。就我渴望使用推荐的方式而言,我希望拥有ApplicationPoolIdentity,而不是域帐户。

这可以与什么联系起来?是否可以将所有这些混合在一起?


这是一个具有类似问题的 SO 线程:ASP.NET MVC 4 + Ninject MVC 3 = No parameterless constructor defined for this object。然而,那里也没有合适的答案。


正如已删除的评论所建议的那样,我尝试使用NetworkSerive作为身份。它工作正常。但是,我想这并不比非特权域帐户好多少。


编辑

突然发现另一个依赖关系:应用程序池标识用于 sql server 上的 windows 身份验证,尽管我希望客户端用户的凭据在那里使用。

根据评论

同意可以通过模拟使用经过身份验证的凭据访问远程 sql 服务器。


但是,仍然不清楚 ApplicationPoolIdentity 和 Ninject 的问题是什么。

这个问题最开头提到的文章让我认为这可能是由于虚拟帐户没有用户个人资料这一事实造成的。这方面对我来说仍然不清楚,因为仍然可以使 IIS 加载具有该LoadUserProfile属性的用户配置文件。我不明白,如果没有虚拟帐户的配置文件,IIS 将加载什么?

那里说:

IIS 不加载 Windows 用户配置文件,但某些应用程序可能会利用它来存储临时数据。SQL Express 是执行此操作的应用程序示例。但是,必须创建用户配置文件以将临时数据存储在配置文件目录或注册表配置单元中。NETWORKSERVICE 帐户的用户配置文件由系统创建并且始终可用。但是,切换到唯一的应用程序池身份后,系统不会创建任何用户配置文件。只有标准应用程序池(DefaultAppPool 和 Classic .NET AppPool)在磁盘上有用户配置文件。如果管理员创建新的应用程序池,则不会创建用户配置文件。

但是,如果需要,您可以通过将“LoadUserProfile”属性设置为“true”来配置 IIS 应用程序池以加载用户配置文件。


我在 serverfault.com 上找到了以下线程:

如何将活动目录权限分配给默认应用程序池标识

那里还指出,应用程序池身份无法作为网络服务工作,特别是查询 AD。

4

2 回答 2

9

iispool\appPoolName 帐户被称为虚拟帐户并被添加到 Windows 2008。他们的想法是它们并不是真正意义上的帐户。它们允许的是使用基本帐户增强进程之间的安全性。

您机器上的许多服务都使用 networkService,这是一个具有网络访问权限的内置帐户。因此,如果攻击者要利用其中一项服务,则可以访问在同一帐户下运行的任何其他进程。虚拟帐户(例如 IIS 使用的帐户)通过显示为不同的帐户来防止这种情况发生,同时仍然是同一个帐户 - 从技术上讲,您的 asp.net 应用程序仍然作为网络服务运行,并且授予该帐户对应该仍然有效的事物的访问权限。这也意味着如果您需要访问网络资源,iispool 帐户将像 networkservice 一样使用机器域帐户。

如果您正在访问远程 sql 服务器,则应添加此帐户以允许从您的 Web 服务器进行访问。我不建议使用模拟,除非您真的需要查看 SQL 服务器上的用户是谁。如果您将其关闭,您的应用程序安全性会更简单。

至于为什么您的注入不起作用,可能是您的任何依赖项失败。如果 controllerA 被注入 ClassB,而 ClassB 又被注入 ClassC 并且该类未能注入 ClassD,那么整个链都会失败。我已经发生过这种情况,并且花了一段时间才意识到它与我所看到的东西如此相去甚远。

于 2013-04-06T00:04:37.143 回答
2

从问题的细节来看,这听起来很像导致 aCOMException被抛出的权限问题,这阻止了 Ninject 实例化MainController. 异常与System.DirectoryServices用于查询 Active Directory 的类有关。

当 IIS 在普通应用程序池帐户下运行时,这些帐户无权对 Active Directory 进行查询,并且COMException可以抛出 a。我认为异常中的实际消息(找不到无参数的构造函数)有点像红鲱鱼,Ninject 试图回退到另一个构造函数,因为正常的构造函数不起作用。

这可以解释为什么当您将 IIS 应用程序池更改为作为域帐户运行时,它会突然起作用,因为该帐户确实有权查询域。

从问题中不清楚您是在使用System.DirectoryServices自己还是 Ninject/IIS/ASP 是否在使用它们。如果您自己使用它们,请确保您的 AD 类中的任何构造函数都不会抛出异常(捕获它们并记录它们或其他东西),这将防止您的应用程序在启动时崩溃。您可能会发现我上面所说的关于权限的内容。

如果您需要 IIS 作为普通应用程序池帐户运行(这是一个好主意),但仍以域用户身份查询 AD,那么您可以指定凭据DirectoryEntry并使用 aDirectorySearcher进行 AD 搜索。如果您使用的是 .Net 4 或更高版本,那么我建议您改用新System.DirectoryServices.AccountManagement类(这也允许您指定凭据)。

使用该方法,您不需要任何模拟 AD 查询,并且您的应用程序池仍可以作为普通应用程序池帐户运行。

于 2013-04-05T15:13:30.693 回答