IIS 向 ASP.NET 传递代表经过身份验证的用户或匿名用户帐户的令牌。该令牌在一个包含在 IPrincipal 对象中的 IIdentity 对象中维护,IPrincipal对象进而附加到当前 Web 请求线程。可以通过 HttpContext.User 属性访问 IPrincipal 和 IIdentity 对象。这些对象和该属性由身份验证模块设置,这些模块作为 HTTP 模块实现并作为 ASP.NET 管道的一个标准部分进行调用,如图 3 所示。
ASP.NET 管道模型包含一个 HttpApplication 对象、多个 HTTP 模块对象,以及一个 HTTP 处理程序对象及其相关的工厂对象。HttpRuntime 对象用于处理序列的开头。在整个请求生命周期中,HttpContext 对象用于传递有关请求和响应的详细信息。
有关 ASP.NET 请求生命周期的详细信息,请参阅"ASP.NET Life Cycle",网址是 http://msdn2.microsoft.com/library/ms227435(en-US,VS.80).aspx。
身份验证模块
ASP.NET 2.0 在计算机级别的 Web.config 文件中定义一组 HTTP 模块。其中包括大量身份验证模块,如下所示:
<httpModules> <add name="WindowsAuthentication" type="System.Web.Security.WindowsAuthenticationModule" /> <add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" /> <add name="PassportAuthentication" type="System.Web.Security.PassportAuthenticationModule" /> </httpModules>
只加载一个身份验证模块,这取决于该配置文件的 authentication 元素中指定了哪种身份验证模式。该身份验证模块创建一个 IPrincipal 对象并将它存储在 HttpContext.User 属性中。这是很关键的,因为其他授权模块使用该 IPrincipal 对象作出授权决定。
当 IIS 中启用匿名访问且 authentication 元素的 mode 属性设置为 none 时,有一个特殊模块将默认的匿名原则添加到 HttpContext.User 属性中。因此,在进行身份验证之后,HttpContext.User 绝不是一个空引用(在 Visual Basic 中为 Nothing)。
WindowsAuthenticationModule
如果 Web.config 文件包含以下元素,则激活 WindowsAuthenticationModule 类。
<authentication mode="Windows" />
WindowsAuthenticationModule 类负责创建 WindowsPrincipal 和 WindowsIdentity 对象来表示经过身份验证的用户,并且负责将这些对象附加到当前 Web 请求。
对于 Windows 身份验证,遵循以下步骤:
-
WindowsAuthenticationModule 使用从 IIS 传递到 ASP.NET 的 Windows 访问令牌创建一个 WindowsPrincipal 对象。该令牌包装在HttpContext 类的 WorkerRequest 属性中。引发 AuthenticateRequest 事件时,WindowsAuthenticationModule 从 HttpContext类检索该令牌并创建 WindowsPrincipal 对象。HttpContext.User 用该 WindowsPrincipal 对象进行设置,它表示所有经过身份验证的模块和 ASP.NET 页的经过身份验证的用户的安全上下文。
-
WindowsAuthenticationModule 类使用 P/Invoke 调用 Win32 函数并获得该用户所属的 Windows 组的列表。这些组用于填充WindowsPrincipal 角色列表。
-
WindowsAuthenticationModule 类将 WindowsPrincipal 对象存储在 HttpContext.User 属性中。随后,授权模块用它对经过身份验证的用户授权。
注: DefaultAuthenticationModule 类(也是 ASP.NET 管道的一部分)将 Thread.CurrentPrincipal 属性设置为与 HttpContext.User属性相同的值。它在处理 AuthenticateRequest 事件之后进行此操作。