ASP.NET Windows 身份验证
IIS 向 ASP.NET 传递代表经过身份验证的用户或匿名用户帐户的令牌。该令牌在一个包含在 IPrincipal 对象中的 IIdentity 对象中维护,IPrincipal 对象进而附加到当前 Web 请求线程。可以通过 HttpContext.User 属性访问 IPrincipal 和 IIdentity 对象。这些对象和该属性由身份验证模块设置,这些模块作为 HTTP 模块实现并作为 ASP.NET 管道的一个标准部分进行调用,如图 3 所示。
图 3. ASP.NET 管道
ASP.NET 管道模型包含一个 HttpApplication 对象、多个 HTTP 模块对象,以及一个 HTTP 处理程序对象及其相关的工厂对象。HttpRuntime 对象用于处理序列的开头。在整个请求生命周期中,HttpContext 对象用于传递有关请求和响应的详细信息。
身份验证模块
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 对象作出授权决定。
如果 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 事件之后进行此操作。 |
授权模块
WindowsAuthenticationModule 类完成其处理之后,如果未拒绝请求,则调用授权模块。授权模块也在计算机级别的 Web.config 文件中的 httpModules 元素中定义,如下所示:
<httpModules> <add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" /> <add name="FileAuthorization" type="System.Web.Security.FileAuthorizationModule" /> <add name="AnonymousIdentification" type="System.Web.Security.AnonymousIdentificationModule" /> </httpModules>
UrlAuthorizationModule
调用 UrlAuthorizationModule 类时,它在计算机级别或应用程序特定的 Web.config 文件中查找 authorization 元素。如果存在该元素,则 UrlAuthorizationModule 类从 HttpContext.User 属性检索 IPrincipal 对象,然后使用指定的动词(GET、POST 等)来确定是否授权该用户访问请求的资源。
FileAuthorizationModule
接下来,调用 FileAuthorizationModule 类。它检查 HttpContext.User.Identity 属性中的 IIdentity 对象是否是 WindowsIdentity 类的一个实例。如果 IIdentity 对象不是 WindowsIdentity 类的一个实例,则 FileAuthorizationModule 类停止处理。
如果存在 WindowsIdentity 类的一个实例,则 FileAuthorizationModule 类调用 AccessCheck Win32 函数(通过 P/Invoke)来确定是否授权经过身份验证的客户端访问请求的文件。如果该文件的安全描述符的随机访问控制列表 (DACL) 中至少包含一个 Read 访问控制项 (ACE),则允许该请求继续。否则,FileAuthorizationModule 类调用 HttpApplication.CompleteRequest 方法并将状态码 401 返回到客户端。
安全上下文
.NET Framework 使用以下两个接口封装 Windows 令牌和登录会话:
• |
System.Security.Principal.IPrincipal |
• |
System.Security.Principal.IIdentity(它公开为 IPrincipal 接口中的一个属性。) |
HttpContext.User
在 ASP.NET 中,用 WindowsPrincipal 和 WindowsIdentity 类表示使用 Windows 身份验证进行身份验证的用户的安全上下文。使用 Windows 身份验证的 ASP.NET 应用程序可以通过 HttpContext.User 属性访问 WindowsPrincipal 类。
要检索启动当前请求的 Windows 经过身份验证的用户的安全上下文,使用以下代码:
using System.Security.Principal; ... // Obtain the authenticated user's Identity WindowsPrincipal winPrincipal = (WindowsPrincipal)HttpContext.Current.User;
WindowsIdentity.GetCurrent
WindowsIdentity.GetCurrent 方法可用于获得当前运行的 Win32 线程的安全上下文的标识。如果不使用模拟,线程继承 IIS 6.0(默认情况下的 NetworkService 帐户)上进程的安全上下文。
该安全上下文在访问本地资源时使用。通过使用经过身份验证的初始用户的安全上下文或使用固定标识,您可以使用模拟重写该安全上下文。
要检索运行应用程序的安全上下文,使用以下代码:
using System.Security.Principal; ... // Obtain the authenticated user's identity. WindowsIdentity winId = WindowsIdentity.GetCurrent(); WindowsPrincipal winPrincipal = new WindowsPrincipal(winId);
Thread.CurrentPrincipal
ASP.NET 应用程序中的每个线程公开一个 CurrentPrincipal 对象,该对象保存经过身份验证的初始用户的安全上下文。该安全上下文可用于基于角色的授权。
要检索线程的当前原则,使用以下代码:
using System.Security.Principal; ... // Obtain the authenticated user's identity WindowsPrincipal winPrincipal = (WindowsPrincipal) Thread.CurrentPrincipal();
表 1 显示从各种标识属性获得的结果标识,当您的应用程序使用 Windows 身份验证且 IIS 配置为使用集成 Windows 身份验证时,可以从 ASP.NET 应用程序使用这些标识属性。
表 1:线程公开的 CurrentPrincipal Object | ||
Web.config 设置 | 变量位置 | 结果标识 |
<identity impersonate="true"/> |
HttpContext |
Domain\UserName |
<identity impersonate="false"/> |
HttpContext |
Domain\UserName |
<identity impersonate="true"/> |
HttpContext |
用户提供的名称 |
<identity impersonate="false"/> |
HttpContext |
用户提供的名称 |