ASP.NET 工作原理

IIS 和 ASP.NET 处理

注意:本节中的信息适用于在 Windows 2000 上运行的 Internet 信息服务 (IIS) 5。

ASP.NET Web 应用程序和 Web 服务是由在单个 ASP.NET 辅助进程 (aspnet_wp.exe) 实例中执行的代码处理的,但是,可以在多处理器计算机上配置多个实例(每个处理器一个)。

IIS 验证调用方的身份,并为调用方创建 Windows 访问令牌。如果在 IIS 中启用了匿名访问,则 IIS 为匿名 Internet 用户帐户(通常是 IUSR_MACHINE)创建 Windows 访问令牌。

ASP.NET 文件类型请求是由 ASP.NET ISAPI 扩展 (aspnet_isapi.dll) 处理的,该扩展在 IIS (inetinfo.exe) 进程地址空间中运行。该扩展使用命名管道与 ASP.NET 辅助进程进行通信,如图 1 所示。IIS 将代表调用方的 Windows 访问令牌传递给 ASP.NET 辅助进程。ASP.NET Windows 身份验证模块使用此令牌构造一个 WindowsPrincipal 对象;而 ASP.NET 文件授权模块使用它来执行 Windows 访问检查,以确保授权调用方访问请求的文件。

IIS 和 ASP.NET 通信  

图 1
IIS 和 ASP.NET 通信

注意:访问令牌与进程有关。因此,在 inetinfo.exe 中运行的 ASP.NET ISAPI DLL 调用 DuplicateHandle 以便将令牌句柄复制到 aspnet_wp.exe 进程地址空间中,然后通过命名管道传递句柄值。

应用程序隔离

可以使用辅助进程内的不同应用程序域(每个 IIS 虚拟目录一个,换言之,每个 ASP.NET Web 应用程序或 Web 服务一个)来提供隔离。

它与传统的 ASP 不同。在传统的 ASP 中,IIS 元数据库中配置的应用程序保护级别决定了 ASP 应用程序是在 IIS 进程内 (inetinfo.exe) 执行,在进程外的 Dllhost.exe 专用实例中执行,还是在 Dllhost.exe 的共享(汇集)实例中执行。

重要说明:IIS 中的进程隔离级别设置不影响 ASP.NET Web 应用程序的处理方式。

ASP.NET ISAPI 扩展

ASP.NET ISAPI 扩展 (aspnet_isapi.dll) 在 IIS 进程地址空间 (inetinfo.exe) 中运行,并通过命名管道将 ASP.NET 文件类型请求转发给 ASP.NET 辅助进程。

可以通过 IIS 元数据库中定义的映射,将特定的 ASP.NET 文件类型映射到 ASP.NET ISAPI 扩展。在安装 .NET Framework 后,就会建立标准 ASP.NET 文件类型(包括 .aspx、.asmx、.rem 以及 .soap)的映射。 

查看应用程序映射

1.

从“管理工具”程序组中,启动 Internet 信息服务。

2.

右键单击 Web 服务器上的默认网站,然后单击“属性”。

3.

单击“主目录”选项卡,然后单击“配置”。

此时,就会显示一个映射列表。可以看到哪些文件类型被映射到了 Aspnet_isapi.dll。

IIS 6.0 和 Windows .NET Server

Windows .NET Server 上的 IIS 6.0 对当前的进程设置进行了一些重大改动。

您可以配置多个应用程序池,每个池由一个或多个进程实例 (w3wp.exe) 提供服务。这可提供额外的容错功能并简化了管理,使您可以在不同的进程中隔离不同的应用程序。

ASP.NET 与 IIS 6.0 内核模式 HTTP 侦听器集成在一起,因此,可以将请求从操作系统直接传递给 ASP.NET 辅助进程。

更多信息

有关 IIS6 的详细信息,请参见 TechNet 上的文章“IIS 6 Overview”(IIS 6 概述)(http://www.microsoft.com/technet/treeview/default.asp?url=/TechNet/prodtechnol/iis/evaluate/iis6ovw.asp)。

ASP.NET 管道处理

ASP.NET 身份验证和授权机制是使用 HTTP 模块对象实现的,HTTP 模块对象是作为标准 ASP.NET 管道处理的一部分进行调用的。各个 Web 请求和响应通过对象管道进行传递,如图 2 所示:

ASP.NET 管道处理  

图 2
ASP.NET 管道处理

ASP.NET 管道模型包括 HttpApplication 对象、各种 HTTP 模块对象和 HTTP 处理程序对象及其相关工厂对象。为清楚起见,图 2 中省略了工厂对象。HttpRuntime 对象在处理序列开始时使用;而 HttpContext 对象在整个请求过程中使用,以传送有关请求和响应的详细信息。

以下列表说明了 HTTP 处理管道相关对象的职责和所执行的操作:

HttpRuntime 对象检查从 IIS 收到的请求,并将其分配给 HttpApplication 对象的相应实例以进行处理。Aspnet_wp.exe 的每个应用程序域中都有一个 HttpApplication 对象池。应用程序域、HttpApplication 对象和 IIS 虚拟目录之间存在一一对应关系。也就是说,ASP.NET 将不同的 IIS 虚拟目录作为不同的应用程序处理。

注意:每个 Web 应用程序域中都有一个 HttpRuntime 实例。 

HttpApplication 对象控制管道处理。对于同时发生的每个 HTTP 请求,分别创建一个 HttpApplication 对象以便对它进行处理。出于性能方面的考虑,将 HttpApplication 对象汇集起来。

在管道中传递 HTTP 请求和响应消息时,可以将 HTTP 模块对象作为处理它们的筛选器。这些模块对象可以查看或修改请求和响应消息的内容。HTTP 模块是实现 IHttpModule 的类。

HTTP 处理程序对象是 HTTP 请求的终结点,并对特定文件类型的请求进行处理。例如,一个处理程序处理对 *.aspx 文件的请求,而另一个处理程序则处理对 *.asmx 文件的请求。HTTP 响应消息是由 HTTP 处理程序生成和返回的。HTTP 处理程序是实现 IHttpHandler 的类。

HttpContext 对象在整个管道中使用以代表当前的 Web 请求和响应。它可用于管道中的所有模块以及管道结束处的处理程序对象。HttpContext 对象公开各种不同的属性,其中包括 User 属性,该属性包含代表调用方的 IPrincipal 对象。

Web 请求剖析

ASP.NET ISAPI 库 (Aspnet_isapi.dll) 在 IIS 进程地址空间 (Inetinfo.exe) 中运行。它将请求分配给 ASP.NET 辅助进程 (Aspnet_wp.exe) 中的 HttpRuntime 对象。对于 ASP.NET 收到的每个 Web 请求,将执行以下一系列操作以进行响应:

HttpRuntime 对象检查请求,并将其转发给 HttpApplication 对象的实例。
每个应用程序域(对象被汇集)至少有一个 HttpApplication 对象实例;每个 IIS 虚拟目录至少有一个应用程序域。第一次请求某个虚拟目录中的文件时,会创建一个新的应用程序域和一个新的 HttpApplication 对象。

从 Machine.config 中读取 HTTP 模块列表(它们包含在 <httpModules> 元素内)。可以在某个应用程序的 Web.config 中添加其他的自定义 HTTP 模块。以下代码片段显示了 Machine.config 中的默认 <httpModules> 元素:

<httpModules>
  <add name="OutputCache" 
       type="System.Web.Caching.OutputCacheModule"/>
  <add name="Session" 
       type="System.Web.SessionState.SessionStateModule"/>
  <add name="WindowsAuthentication" 
       type="System.Web.Security.WindowsAuthenticationModule"/>
  <add name="FormsAuthentication" 
       type="System.Web.Security.FormsAuthenticationModule"/>
  <add name="PassportAuthentication" 
       type="System.Web.Security.PassportAuthenticationModule"/>
  <add name="UrlAuthorization" 
       type="System.Web.Security.UrlAuthorizationModule"/>
  <add name="FileAuthorization" 
       type="System.Web.Security.FileAuthorizationModule"/>
</httpModules>

身份验证模块与 AuthenticateRequest 事件挂钩;而授权模块与 AuthorizeRequest 事件挂钩。 

请求在传递过程中通过管道中的每一个模块,但只加载一个身份验证模块。这取决于 Web.config 中 <authentication> 元素的配置。例如,下面的 <authentication> 元素导致加载 WindowsAuthenticationModule

<authentication mode="Windows" />

激活的身份验证模块负责创建 IPrincipal 对象,并将其存储在 HttpContext.User 属性中。这是非常重要的,因为下游授权模块使用此 IPrincipal 对象来确定是否授权。 

在未进行身份验证的情况下(例如,在 IIS 中启用匿名访问并且将 ASP.NET 配置为 <authentication mode="None" />),可以使用一个特殊的不可配置模块,将默认的匿名主体放到 HttpContext.User 属性中。因此,在进行身份验证后,HttpContext.User 始终是非空的属性。

如果您实现自定义的身份验证模块,则自定义模块中的代码必须创建一个 IPrincipal 对象,并将其存储在 HttpContext.User 中。

注意:在 AuthenticateRequest 事件之后,ASP.NET 还根据 HttpContext.User 调用 Thread.CurrentPrincipal

HttpApplication 激发 AuthenticateRequest 事件,该事件可以挂钩到 global.asax 中。这样,您就可以注入自定义的处理代码以加载与当前用户关联的角色集。但要注意,WindowsAuthenticationModule 自动执行此操作。角色列表是从已验证身份的 Windows 用户所属的 Windows 组集中获取的。

在相应身份验证模块完成处理之后,如果请求未被终止,则调用授权模块。

在调用 UrlAuthorizationModule 后,它检查 Machine.config 和 Web.config 中是否存在 <authorization> 标记。如果存在,则它从 HttpContext.User 中检索 IPrincipal 对象,并使用指定的谓词(GET、POST 等等)检查是否授权用户访问请求的资源。
如果未给用户授权,则 UrlAuthorizationModule 调用 HttpApplication.CompleteRequest,这将终止正常的消息处理。UrlAuthorizationModule 返回 HTTP 401 状态代码。

然后,调用 FileAuthorizationModule。它检查 HttpContext.User.Identity 中的IIdentity 对象是否为 WindowsIdentity 类的实例。
如果 IIdentity 对象不是 WindowsIdentity,则 FileAuthorizationModule 不再执行进一步的处理。

如果 WindowsIdentity 存在,则 FileAuthorizationModule 调用 AccessCheck API(通过 P/Invoke),查看是否授权已验证身份的调用方(IIS 已将其访问令牌传递给 ASP.NET 并由 WindowsIdentity 对象公开)访问请求的文件。如果文件的安全描述符在其 DACL 中至少包含一个读取 ACE,则可以对请求继续进行处理。否则,FileAuthorizationModule 调用 HttpApplication.CompleteRequest 并返回 401 状态代码。

窗体身份验证处理

如果 Web.config 包含以下元素,就会激活 FormsAuthenticationModule

<authentication mode="Forms" />

记住,对于窗体身份验证,可以在 Global.asax 中实现 Application_Authenticate 事件。对于窗体身份验证,将发生以下事件序列:

在此代码中,您可以构造 IPrincipal 对象并将其存储在 HttpContext.User 中。通常,它包含从自定义数据存储(通常是 SQL Server 数据库或 Active Directory)中检索的角色列表。IPrincipal 对象通常是 GenericPrincipal 类的实例,但也可以是自定义的 IPrincipal 类。

FormsAuthenticationModule 检查您是否创建了 IPrincipal 对象。如果已经创建,下游授权模块就会使用该对象。如果没有创建,FormsAuthenticationModule 就会构造 GenericPrincipal(没有角色)并将其存储在上下文中。

如果没有角色信息,则任何要求角色成员身份的授权检查(例如 PrincipalPermssion 请求)都将失败。

UrlAuthorizationModule 处理 AuthorizeRequest 事件。它的授权决策基于 HttpContext.User 中包含的 IPrincipal 对象。

Windows 身份验证处理

如果 Web.config 包含以下元素,就会激活 WindowsAuthenticationModule

<authentication mode="Windows" />

对于 Windows 身份验证,将发生以下事件序列:

1.

WindowsAuthenticationModule 使用由 IIS 传递给 ASP.NET 的 Windows 访问令牌创建 WindowsPrincipal 对象。

2.

它使用 P/Invoke 调用 Win32 函数以获取用户所属的 Windows 组的列表。这些组用于填充 WindowsPrincipal 角色列表。

3.

它将 WindowsPrincipal 对象存储在 HttpContext.User 中,以便供下游授权模块使用。

事件处理

HttpApplication 对象激发一组事件,如表 1 所示。各个 HTTP 模块可以与这些事件挂钩(通过提供它们自己的事件处理程序)。

表 1:HttpApplication 对象激发的事件

事件备注

BeginRequest

在请求处理开始之前激发

AuthenticateRequest

验证调用方的身份

AuthorizeRequest

执行访问检查

ResolveRequestCache

从缓存中获取响应

AcquireRequestState

加载会话状态

PreRequestHandlerExecute

在请求即将发送到处理程序对象之前激发

PostRequestHandlerExecute

在请求刚刚发送到处理程序对象之后激发

ReleaseRequestState

存储会话状态

UpdateRequestCache

更新响应缓存

EndRequest

在处理结束后激发

PreSendRequestHeaders

在发送缓存的响应标头之前激发

PreSendRequestContent

在发送缓存的响应正文之前激发

注意:HTTP 处理程序在 PreRequestHandlerExecute 和 PostRequestHandlerExecute 事件之间执行。

最后两个事件是无法确定的,并且可能会随时发生(例如,由 Response.Flush 激发)。所有其他事件则是按顺序发生的。

不必仅仅为了与其中的某个事件挂钩而实现 HTTP 模块。您还可以向 Global.asax 中添加事件处理程序。除了表 1 中列出的事件(它们可以与不同的 HTTP 模块对象挂钩)外,HttpApplication 对象还会激发 Application_OnStart 和 Application_OnEnd 处理程序,ASP 开发人员应该对这些处理程序很熟悉。只能在 Global.asax 中对这些处理程序进行处理。最后,您还可以在 Global.asax 中为不同 HTTP 模块对象激发的事件实现自定义的事件处理程序。例如,会话状态模块激发 Session_OnStart 和 Session_OnEnd 事件。

实现自定义的 HTTP 模块

创建您自己的 HTTP 模块并将其插入到 ASP.NET 处理管道中

1.

创建一个实现 IHttpModule 的类。

2.

将包含该模块的程序集放到应用程序的 /bin 子目录中,或者将其安装到全局程序集缓存中。

3.

将 <HttpModules> 元素添加到应用程序的 web.config 中,如下所示:

<system.web>
  <httpModules>
    <add name="modulename"
         type="namespace.classname,assemblyname" />
  </httpModules>
</system.web>

实现自定义的 HTTP 处理程序

您可能需要实现自定义的 HTTP 处理程序,以便处理具有 .data 文件扩展名的文件。

实现自定义的 HTTP 处理程序

1.

向 IIS 元数据库中添加一个映射,以便将 .data 文件扩展名映射到 ASP.NET ISAPI 扩展 (Aspnet_isapi.dll) 上。
在 IIS MMC 管理单元中,右键单击应用程序的虚拟目录,单击“配置”按钮,然后单击“添加”,为 .data 文件创建到 C:/Winnt/Microsoft.NET/Framework/v1.0.3705/aspnet_isapi.dll 的新映射。

注意:如果在添加映射时选中了“检查文件是否存在”复选框,则该文件必须确实存在。除非您没有将虚拟路径映射到物理文件,否则,通常只需要满足这个条件即可。.NET Remoting 使用以 .rem 或 .soap 结尾的虚拟路径。

2.

创建一个实现 IHttpHandler(若要异步处理请求,则还可以实现 IHttpAsyncHandler)的类。

3.

将包含该处理程序的程序集放到应用程序的 /bin 子目录中,或者将其安装到全局程序集缓存中。

4.

在应用程序的 Web.config 文件中添加 <httpHandlers> 部分,以便将该处理程序添加到处理管道中。

<system.web>
  <httpHandlers>
    <add verb="*" path="*.data" type="namespace.classname, assemblyname" />
  </httpHandlers>
</system.web>
 
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值