Chris, very handy post.
Many who suggest a performance disadvantage infer that the code processed in a web application is some how different/inferior to code processed in the standard workflow. The base code type maybe different, and sure you'll be needing the MSIL interpreter, but MS has shown in many cases you'll actually see a performance increase in a .NET runtime over a native one.
It's also wise to consider how IIS has to be a "jack of all trades" - allowing all sorts of configuration and overrides even on static files. Some of those are designed for performance increase (caching, compression) and - indeed - will be lost unless you reimplement them in your code, but many of them are for other purposes and may not ever be used. If you build for your needs (only) you can ignore those other pieces and should be realising some kind of performance advantage, even though there's a potential ASP.NET disadvantage.
In my (non-.NET) MVC testing I'm seeing considerable (10x or more) performance benefits over webforms. Even if there was a small hit on the static content - that wouldn't be a tough pill to swallow.
I'm not surprised the difference is almost negligible in your tests, but I'm happy to see it backed up.
NOTE: You can disable wildcard mapping from static directories (I keep all static files in /static/(pics|styles|...)) in IIS. Switch the folder to an application, remove the wildcard mapping, and switch it back from an application and - voilĂ - static files are handled by IIS without pestering your ASP.NET.
This is a very good question and sadly many developers don't ask enough questions about IIS/ASP.NET security in the context of being a web developer and setting up IIS. So here goes....
To cover the identities listed:
IIS_IUSRS:
This is analogous to the old IIS6 IIS_WPG
group. It's a built-in group with it's security configured such that any member of this group can act as an application pool identity.
IUSR:
This account is analogous to the old IUSR_<MACHINE_NAME>
local account that was the default anonymous user for IIS5 and IIS6 websites (i.e. the one configured via the Directory Security tab of a site's properties).
For more information about IIS_IUSRS
and IUSR
see:
Understanding Built-In User and Group Accounts in IIS 7
DefaultAppPool:
If an application pool is configured to run using the Application Pool Identity feature then a "synthesised" account called IIS AppPool\<pool name>
will be created on the fly to used as the pool identity. In this case there will be a synthesised account called IIS AppPool\DefaultAppPool
created for the life time of the pool. If you delete the pool then this account will no longer exist. When applying permissions to files and folders these must be added using IIS AppPool\<pool name>
. You also won't see these pool accounts in your computers User Manager. See the following for more information:
Application Pool Identities
ASP.NET v4.0:
-
This will be the Application Pool Identity for the ASP.NET v4.0 Application Pool. See DefaultAppPool
above.
NETWORK SERVICE:
-
The NETWORK SERVICE
account is a built-in identity introduced on Windows 2003. NETWORK SERVICE
is a low privileged account under which you can run your application pools and websites. A website running in a Windows 2003 pool can still impersonate the site's anonymous account (IUSR_ or whatever you configured as the anonymous identity).
In ASP.NET prior to Windows 2008 you could have ASP.NET execute requests under the Application Pool account (usually NETWORK SERVICE
). Alternatively you could configure ASP.NET to impersonate the site's anonymous account via the <identity impersonate="true" />
setting in web.config
file locally (if that setting is locked then it would need to be done by an admin in the machine.config
file).
Setting <identity impersonate="true">
is common in shared hosting environments where shared application pools are used (in conjunction with partial trust settings to prevent unwinding of the impersonated account).
In IIS7.x/ASP.NET impersonation control is now configured via the Authentication configuration feature of a site. So you can configure to run as the pool identity, IUSR
or a specific custom anonymous account.
LOCAL SERVICE:
The LOCAL SERVICE
account is a built-in account used by the service control manager. It has a minimum set of privileges on the local computer. It has a fairly limited scope of use:
LocalService Account
LOCAL SYSTEM:
You didn't ask about this one but I'm adding for completeness. This is a local built-in account. It has fairly extensive privileges and trust. You should never configure a website or application pool to run under this identity.
LocalSystem Account
In Practice:
In practice the preferred approach to securing a website (if the site gets its own application pool - which is the default for a new site in IIS7's MMC) is to run under Application Pool Identity
. This means setting the site's Identity in its Application Pool's Advanced Settings to Application Pool Identity
:
In the website you should then configure the Authentication feature:
Right click and edit the Anonymous Authentication entry:
Ensure that "Application pool identity" is selected:
When you come to apply file and folder permissions you grant the Application Pool identity whatever rights are required. For example if you are granting the application pool identity for the ASP.NET v4.0
pool permissions then you can either do this via Explorer:
Click the "Check Names" button:
Or you can do this using the ICACLS.EXE
utility:
icacls c:\wwwroot\mysite /grant "IIS AppPool\ASP.NET v4.0":(CI)(OI)(M)
...or...if you site's application pool is called BobsCatPicBlog
then:
icacls c:\wwwroot\mysite /grant "IIS AppPool\BobsCatPicBlog":(CI)(OI)(M)
I hope this helps clear things up.
Update:
I just bumped into this excellent answer from 2009 which contains a bunch of useful information, well worth a read:
The difference between the 'Local System' account and the 'Network Service' account?
Best Answer
Wildcard mapping does have a huge impact on performance, mostly because it uses the app thread pool not for page request processing, but for all the content. Let's assume you have a usual page with at least 10 additional resources like images, css and javascript - then you're blocking other potential request by serving the static content directly from the pool. More info on asp.net IIS 6 threading can be found here.
One way to go over it (how i did it) is to unable wildcard mapping to the folders that hold the static content - after that you'll receive only valid app request as you would do in an ordinary situation.
The way to unmap the static directories is to create an application of each one of them and then do the unmapping, and after that to undo the application creating thing. You can find more details on Steve Sanderson's blog.