Common Module Management Tasks
Besides enabling you to choose which modules
are installed on the server, IIS 7.0 enables you to further fine-tune
its functionality by selecting which modules are enabled on the server
or even for a particular application. Furthermore, you will sometimes
want to tweak other aspects of module operation, such as their relative
order, or the specific scenarios in which modules should execute. This
section will illustrate some of these common module management tasks.
Controlling What Modules Are Enabled
Despite the differences between
installation procedures for native and managed modules, the modules
configuration section provides a unified view of the enabled modules. By
manipulating the module entries in the modules section, you can control
which modules will be allowed to function on the server by default or
for a specific application:
-
Adding a module at the server level allows it
to execute by default in all applications on the server, except for
applications that specifically remove it. -
Removing a module at the server level
prevents it from executing in all applications on the server, except for
applications that specifically add it back. -
Adding a module at the application level allows it to execute in that specific application. -
Removing a server-level defined module at the
application level removes this module from the specific application,
while allowing other applications to use it.
In a nutshell, modules that are enabled on
the server level provide a default feature set for all applications on
the server. Each application can then tweak this feature set by removing
unneeded modules and then adding additional modules in its modules
section. It is important to remember that though you can add new managed
modules at the application level, new native modules must be installed
at the server level to be enabled at the application level.
This means that applications cannot introduce new native modules—they
can only remove existing ones that are enabled, or add back native
modules that are installed but not enabled by default at the server
level.
Note
You can manage the enabled modules for
your application by using the IIS Manager. After selecting your
application in the tree view and opening the Modules feature, use the
Add Managed Module action to add a new managed module, the Configure
Native Modules action to enable or disable existing native modules, or
the Edit or Remove actions to edit or remove existing module entries in
the list.
Enabling Managed Modules to Run for All Requests
The ability to extend IIS with managed modules
that execute for all content types is one of the central breakthroughs
of IIS 7.0. However, for backward compatibility reasons, all of the
built-in ASP.NET modules are configured to execute only for requests to
managed (ASP.NET) handlers. Because of this, useful ASP.NET services
such as Forms Authentication are by default available only for requests
to ASP.NET content types, and they are not applied to requests to static
content or ASP pages. The ASP.NET setup does this, adding the
"managedHandler" precondition to each ASP.NET module element when it is
added to the modules configuration section.
Because of this, it is necessary to
remove this precondition from each ASP.NET module whose service is
desired for all application content. This can be done by using Appcmd or
IIS Manager to edit the specified modules element, or by manually
removing the precondition from the module element. When this is desired
at the application level for a module element inherited from the server
level configuration, it is necessary to remove and redefine the module
element without the precondition.
<modules>
<remove name="FormsAuthentication" />
<add name="FormsAuthentication"
type="System.Web.Security.FormsAuthenticationModule" />
</modules>
This clears the default "managedHandler" value of the preCondition attribute and enables the FormsAuthentication module to run for all requests.
When
you use IIS Manager or Appcmd to edit the module element, this
configuration is automatically generated whenever you make changes at
the application level.
Note
New managed modules you add will not have the
managedHandler precondition by default and will run for all requests. If
you want to restrict the managed module to run only for requests to
managed handlers, you need to manually add the managedHandler
precondition.
Alternatively, you can configure your
application to ignore all managedHandler preconditions and effectively
always execute all managed modules for all requests without needing to
remove the precondition for each one. This is done by setting the
runAllManagedModulesForAllRequests configuration option in the modules
configuration section.
<modules runAllManagedModulesForAllRequests="true" />
Controlling Module Ordering
Due to the pipeline model of module
execution, module ordering is often important to ensure that the server
"behaves" as it should. For example, modules that attempt to determine
the authenticated user must execute before modules that verify access to
the requested resource, because the latter needs to know what the
authenticated user is. This ordering is almost always enforced by the
stages of the request processing pipeline. By doing their work during
the right stage, modules automatically avoid ordering problems. However,
in some cases, two or more modules that perform a similar task—and
therefore execute in the same stage—may have ordering dependencies. One
prominent example is built-in authentication modules. They are run
during the AuthenticateRequest stage, and to authenticate the request
with the strongest credentials available, they should be in the
strongest to weakest order. To resolve such relative ordering
dependencies, the administrator can control the relative ordering of
modules by changing the order in which they are listed in the modules
section.
This works because the server uses the order
in the modules configuration section to order module execution within
each request processing stage. By placing module A before module B in
the list, you can allow module A to execute before module B.
This also means that when an application
enables a new module (by adding a new managed module, or enabling a
native module that was not previously enabled), that module is listed
after the modules enabled by higher configuration levels due to the
configuration collection inheritance. This can sometimes be a problem if
the new module should run before an existing module defined at the
higher level, because the configuration system does not provide a way to
reorder inherited elements. In this case, the only solution is to clear
the modules collection and re-add all of the elements in the correct
order at the application level.
<modules>
<clear/>
<add name="HttpCacheModule" />
...
<add name="MyNewModule" type="Modules.MyNewModule" />
...
<modules>
Note
You
can also use IIS Manager to perform the ordering task. After selecting
your application in the tree view and opening the Modules feature,
choose the View Ordered List action and use the Move Up and Move Down
actions to adjust the sequence. If you use this feature, the tool will
use the <clear/> approach that we discussed earlier to reorder the
modules for your application.
Caution
By using the <clear/> approach,
you are effectively disconnecting the application’s module configuration
from the configuration at the server level. Therefore, any changes made
at the server level (removing or adding modules) will no longer affect
the application and will need to be manually propagated if necessary.
Though modules typically execute for all
requests so that the modules can provide a content-independent service,
some modules may opt to act as handlers. Handlers are responsible for
producing a response for a specific content type and are mapped in the
IIS 7.0 handler mapping configuration to a specific verb/extension
combination. For handlers, the server is responsible for mapping the
correct handler based on the handler mapping configuration, and they are
also responsible for invoking that handler during the ExecuteRequest
request processing stage to produce the response for this request.
Examples of handlers include StaticFileModule, which serves static
files; DirectoryListingModule, which displays directory listings; and
the ASP.NET PageHandler, which compiles and executes ASP.NET pages.
The main conceptual difference
between modules and handlers is that the server picks the handler to
produce the response for requests to a specific resource, whereas
modules typically process all requests in a resource-independent way and
typically do not produce responses. Because of this, only the one
handler mapped by the server is executed per request. If you are
familiar with IIS 6.0, this is similar to the distinction between the
ISAPI extensions, which provide processing for a specific extension, and
ISAPI filters, which intercept all requests.
Traditionally, most application
frameworks including ASP.NET, ASP, PHP, and ColdFusion are implemented
as handlers that process URLs with specific extensions.
You register a handler on the server by creating
a handler mapping entry in the collection located in the
system.webServer/handlers configuration section. This concept is similar
to the script maps configuration in previous releases of IIS, but in
IIS 7.0 it is extended to allow for more flexibility and to accommodate
more handler types. For applications using the Integrated mode, this
section also supports managed handlers that in previous IIS versions are
registered in the ASP.NET httpHandlers configuration section.
After
it receives the request, the server examines the collection of handler
mappings configured for the request URL and selects the first handler
mapping whose path mask and verb match the request. Later, during the
ExecuteRequestHandler stage, the handler mapping will be used to invoke a
module to handle the request.
Each handler mapping collection entry can specify the attributes shown in Table 5.
Table 5. Attributes Specified by Handler Mappings
Attribute |
Description |
---|
name (required) |
The name for the handler mapping. |
path (required) |
The path mask that must match the request URL so that this handler mapping can be selected. |
verb (required) |
The verb list that must match the request verb so that this handler mapping can be selected. |
resourceType |
Whether the physical resource mapped to the
request URL must be an existing file, directory, either, or unspecified
(if the physical resource does not have to exist). |
requireAccess |
The accessFlag level that is required for this handler to execute. |
precondition |
The precondition that determines if this handler mapping is considered. |
allowPathInfo |
Whether or not the PATH_INFO / PATH_TRANSLATED
server variables contain the path info segment; may cause security
vulnerabilities in some CGI programs or ISAPI extensions that handle
path info incorrectly. |
responseBufferLimit |
The maximum number of bytes of the response to
buffer for this handler mapping. Response buffering is new in IIS 7.0
and enables modules to manipulate response data before it is sent to the
client. The default is 4 MB, although ISAPI extensions installed with
legacy APIs will have it automatically set to 0 for backward
compatibility reasons. |
Modules |
List of modules that attempt to handle the request when this mapping is selected. |
scriptProcessor |
Additional information that is passed to the
module to specify how the handler mapping should behave. Used by ISAPI
extension module, CGI module, and FastCGI module. |
type |
The managed handler type that handles the request when this mapping is selected. |
The information in the handler mapping is used as follows.
-
The precondition
is first used to determine if the handler mapping is to be used in a
particular application pool. If any of the preconditions fail, the
mapping is ignored. -
The path and verb
are matched against the request URL and verb. The first mapping that
matches is chosen. If no mappings matched, a "404.4 Not Found" error is
generated. -
If the accessPolicy configuration does not meet the requireAccess requirement for the handler mapping, a "403 Access Denied" error is generated. -
If the resourceType
is set to File, Directory, or Either, the server makes sure that the
physical resource exists and is of the specified type. If not, a "404
Not Found" error is generated. Also, check that the authenticated user
is allowed to access the mapped file system resource. If resourceType is
set to Unspecified, these checks are not performed.
Note
The path attribute in IIS 7.0 enables you to
specify more complex path masks to match the request URL than previous
versions of IIS, which enable only * or .ext
where ext is the URL extension. IIS 7.0 enables you to use a path mask
that may contain multiple URL segments separated by / and to use
wildcard characters such as * or ?.
Even though the majority of IIS 7.0 handlers are
added at the server level and inherited by all applications on the
server, you can specify additional handlers at any level. Handler
mappings added at a lower level are processed first when matching
handler mappings, so new handlers may override handlers previously
declared at a higher configuration level. Because of this, if you want
to remap that path/verb pair to another handler for your application, it
is not necessary to remove a handler added at a server level—simply
adding that handler mapping in your application’s configuration does the
job.
Note
IIS 7.0 continues to support wildcard
mappings, which enable a handler to act like a filter, processing all
requests and possibly delegating request processing to another handler
by making a child request. Though the majority of such scenarios can now
be implemented with normal modules, quite a few legacy ISAPI extensions
take advantage of this model (including ASP.NET in some
configurations). To create a wildcard mapping, you need to set the path
and verb attributes to *, set the requireAccess attribute to None, and set the resourceType attribute to Either.
Types of Handler Mappings
Though it provides a standard way to map
handlers to requests, the handlers configuration also supports a number
of different types of handlers, as shown in Table 6.
Table 6. Handler Types
Handler Type |
Configuration |
IIS 7.0 Examples |
---|
Native module(s)
The module must support the ExecuteRequestHandler event |
modules specifies the list of native modules that will handle this request (typically just specifies one module) |
TraceVerbHandler, OptionsVerbHandler, StaticFileModule, DefaultDocumentModule, DirectoryBrowsingModule |
ASP.NET handler
The application must be using the Integrated ASP.NET mode |
type specifies fully qualified .NET type that implements ASP.NET handler interfaces |
ASP.NET PageHandlerFactory (aspx pages), ASP.NET WebResourceHandler |
ISAPI extension |
modules specifies the ISAPIModule; scriptProcessor specifies the path to the ISAPI extension DLL to load |
ASP.dll (asp pages) |
CGI program |
modules specifies the CGIModule; scriptProcessor specifies the path to the CGI executable |
Any CGI executable |
FastCGI program |
modules specifies the FastCGIModule; scriptProcessor specifies the path and arguments for a FastCGI executable registered in the FastCGI configuration section |
Any FastCGI executable (such as PHP-CGI.EXE) |
Unlike script maps in previous
versions of IIS, which provide hardcoded support for ISAPI extensions
and CGI programs, IIS 7.0 hardcodes nothing—all types of handlers are
implemented on top of the standard native or managed module API. IIS 7.0
supports ISAPI extensions by hosting them with the ISAPIModule,
supports CGI programs with the CGI module, and features new support for
FastCGI programs with FastCgiModule. The IsapiModule, CgiModule, and
FastCgiModule modules are all native modules, much like
StaticFileModule, except they support interfacing with external handler
frameworks to handle the request, using the ISAPI, CGI, and FastCGI
protocols respectively.
If you look at the handler mappings created by default by a full IIS 7.0 install, you will see some of the following.
<handlers accessPolicy="Read, Script">
<add name="ASPClassic" path="*.asp" verb="GET,HEAD,POST"
modules="IsapiModule" scriptProcessor="%windir%\system32\inetsrv\asp.dll"
esourceType="File" />
<add name="ISAPI-dll" path="*.dll" verb="*"
modules="IsapiModule" resourceType="File" requireAccess="Execute"
allowPathInfo="true" />
...
<add name="PageHandlerFactory-Integrated" path="*.aspx"
verb="GET,HEAD,POST,DEBUG" type="System.Web.UI.PageHandlerFactory"
preCondition="integratedMode" />
...
<add name="PageHandlerFactory-ISAPI-2.0" path="*.aspx"
verb="GET,HEAD,POST,DEBUG" modules="IsapiModule"
scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi
dll" preCondition="classicMode,runtimeVersionv2.0,bitness32"
responseBufferLimit="0" />
...
<add name="StaticFile" path="*" verb="*"
modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule"
resourceType="Either" requireAccess="Read" />
</handlers>
This
configuration fragment shows a good cross-section of the kinds of
handler mappings that you can create. First is IsapiModule handler
mapping, which enables ASP pages to be executed with the ASP.dll ISAPI
extension. Second is the IsapiModule mapping, which supports direct
requests to ISAPI extensions located in the application directories,
which require the Execute permission.
Then, you see two mappings for the
ASP.NET PageHandlerFactory, which supports the processing of ASPX pages.
The first mapping uses the aspnet_isapi.dll ISAPI extension to process
the request, and the second uses the Integrated mode for executing
ASP.NET handlers directly. Each of these mappings uses a precondition to
make sure that only one of the mappings is active in each application
pool based on the ASP.NET integration mode. Classic mode application
pools use the ISAPI mapping, and Integrated mode application pools use
the integrated mapping.
Finally, you see the static file handler mapping, designed to be a
catch-all mapping that is mapped to all requests that do not match any
of the other handler mappings by specifying "*" for both path and verb.
This is similar to previous versions of IIS where any requests not
mapped to an ISAPI extension scriptmap are handled by the static file
handler in IIS. This mapping also illustrates letting multiple modules
attempt to handle the request as part of a single handler mapping.
First, StaticFileModule attempts to serve a physical file if one is
present, then DefaultDocumentModule performs the default document
redirect, and finally DirectoryBrowsingModule attempts to serve a
directory listing.
Security Alert
The fact that the catch-all mapping uses
StaticFileModule means that requests to resources that have not yet had a
handler configured but
are not listed in the server’s MIME type configuration will result in a
"404.3 Not Found" error. This error typically indicates that either you
need to add a MIME map entry for the file’s extension to the server’s
staticContent configuration section to allow the file to be downloaded,
or you need to add a handler mapping to appropriately process the file.
This is an important security measure that prevents scripts from being
downloaded as source code on servers that do not yet have the right
handler mappings installed.
|