C# 如何正确设置 IIS 7 应用程序池标识?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15677156/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 17:33:03  来源:igfitidea点击:

How to set up IIS 7 application pool identity correctly?

c#asp.netasp.net-mvc-3iis-7ninject

提问by horgh

Having deployed my website to IIS7.5 I found one strange behaviour: when application pool identity is left to be ApplicationPoolIdentityby default (as recommended in IIS Application Pool Identities), Ninjectseems to be ignored, as I get the following error, while creating the very first controller:

将我的网站部署到 IIS7.5 后,我发现了一个奇怪的行为:当应用程序池标识ApplicationPoolIdentity默认保留(如IIS Application Pool Identities 中推荐的那样)时,Ninject似乎被忽略,因为我收到以下错误,同时创建非常第一个控制器:

System.InvalidOperationException: An error occurred when trying to create a controller of type '..MainController'. Make sure that the controller has a parameterless public constructor. ---> System.DirectoryServices.DirectoryServicesCOMException: An operations error occurred.

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

I tried to grant FullAccessto IIS AppPool\<MySiteAppPool>to the folder, containing the site (including all subfolders and files), but this did not change anything.

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

However, when I set the application pool identity to any domain account (even a simple one, without administrative privilages, as well as without any access to the folder with the site), it works normally.

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

Ninject is installed according to Setting up an MVC3 applicationtutorial through the NuGet package.

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

I am not sure, if it's relevant, the site is supposed to work in a domain intranet with windows authentication.

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

So, the only problem seems to be with the application pool identity. As far as I am eager to use the recommended way, I'd love to have the ApplicationPoolIdentity, not a domain account.

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

What can this be connected with? Is it possible to mix all these together?

这可以与什么有关?是否有可能将所有这些混合在一起?



Here is an SO thread with a similar issue: ASP.NET MVC 4 + Ninject MVC 3 = No parameterless constructor defined for this object. However no suitable answer there at all either.

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



As a deleted comment suggested, I tried using NetworkSeriveas the identity. And it worked properly. However, I guess this is not much better, than a non-privileged domain account.

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



EDIT

编辑

Suddenly found another dependency: the application pool identity is used for the windows authentication on sql server, though I expected the client-side user's credentials to be used there.

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

Based on comments

基于评论

Agree that a remote sql server can be accessed with the authenticated credentials via impersonation.

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



However it is still not clear what the problem is with ApplicationPoolIdentity and Ninject.

然而,目前尚不清楚 ApplicationPoolIdentity 和 Ninject 的问题是什么。

The article mentiond at the very top of this question made me suppose that this could be caused by the fact, that virtual account has no user profile. This aspect remains unclear to me, as one can still enable IIS to load the user profile with the LoadUserProfileattribute. I can't get, what is IIS going to load, if there is no profile for the virtual account?

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

It is said there:

那里说:

IIS doesn't load the Windows user profile, but certain applications might take advantage of it anyway to store temporary data. SQL Express is an example of an application that does this. However, a user profile has to be created to store temporary data in either the profile directory or in the registry hive. The user profile for the NETWORKSERVICE account was created by the system and was always available. However, with the switch to unique Application Pool identities, no user profile is created by the system. Only the standard Application Pools (DefaultAppPool and Classic .NET AppPool) have user profiles on disk. No user profile is created if the Administrator creates a new Application Pool.

However, if you want, you can configure IIS Application Pools to load the user profile by setting the "LoadUserProfile" attribute to "true".

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

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



I found the following thread on serverfault.com:

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

How can I assign active directory permission to the default app pool identity

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

There it is also stated that app pool identity is unable to work as a network service, in particular, query the AD.

那里还说明应用程序池标识无法作为网络服务工作,尤其是查询 AD。

采纳答案by Adam Rodger

From the detail in the question, it sounds a lot like a permissions problem causing a COMExceptionto be thrown, which is preventing Ninject from instantiating MainController. The exception is related to System.DirectoryServiceswhich are the classes used to query Active Directory.

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

When IIS is running under the normal app pool accounts, those accounts don't have permissions to make queries against Active Directory and a COMExceptioncan be thrown. I think the actual message in the exception (can't find a parameterless constructor) is a bit of a red herring and is Ninject trying to fall back to another constructor since the normal one didn't work.

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

That would explain why when you change the IIS app pool to run as a domain account it suddenly works, because that account does have permission to query the domain.

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

It's not clear from the question whether or not you are using System.DirectoryServicesyourself or whether Ninject/IIS/ASP is using them. If you are using them yourself though, make sure none of the constructors in your AD classes can throw exceptions (catch them and log them or something) which will prevent your app from crashing on start-up. You'll probably find out what I said above about permissions.

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

If you need IIS to run as the normal app pool account (which is a good idea) but still query AD as a domain user then you can specify the credentials to DirectoryEntryand use a DirectorySearcherto do the AD search. If you're on .Net 4 or higher then I'd recommend using the new System.DirectoryServices.AccountManagementclasses instead (which also allow you to specify credentials).

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

With that method, you won't need any impersonation for AD queries and your app pool can still run as the normal app pool accounts.

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

回答by Simon Halsey

iispool\appPoolName account are called virtual accounts & were added to Windows 2008. The idea goes that they aren't really accounts in the true sense. What they allow is enhanced security between processes using the base account.

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

Many services on your machine use networkService, a built in account with network access. Because of this, if an attacker were to exploit one of those services, any other process running under the same account would be accessible. Virtual accounts, such as those used by IIS prevent this by appearing as different accounts, whilst still being the same account - your asp.net app is still technically running as networkservice & granting this account access to things shoudl still work. This also means if you need to access network resources, the iispool accounts would do so as networkservice does & use the machines domain account.

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

If you are accessing a remote sql server, this is the account you should add to allow access from your web server. I wouldn't advise using impersonation, unless you really really need to see who the user is on the SQL server. Your app security is simpler if you leave it off.

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

as to why your injections aren't working, it could be any of your dependencies failing. if controllerA is injected with ClassB which in turn is injected with ClassC & that class fails to have ClassD injected, then the whole chain fails. I've had that happen & it took a while to realise it was something so removed from what I was looking at.

至于为什么您的注入不起作用,这可能是您的任何依赖项失败。如果 controllerA 注入了 ClassB,而 ClassB 又注入了 ClassC,并且该类没有注入 ClassD,那么整个链就会失败。我遇到过这种情况,过了一段时间才意识到它与我所看到的完全不同。