日期:2010-01-30  浏览次数:20621 次

联合安全的目标是提供在域间建立信任关系的机制,这样,用户通过自己所属域的身份验证后,就获得了授权可以访问其他域的应用程序和服务。 这使单一登录这样的身份验证方法成为可能,采用这种方法,无需针对多个应用程序和域为用户配置和管理重复帐户,从而显着降低将应用程序扩展到受信任方的成本。

  在联合安全模型中,身份标识提供程序 (IdP) 执行身份验证,并通过安全令牌服务 (STS) 颁发安全令牌。 这些令牌断言有关经过身份验证的用户的信息:用户身份标识和其他可能的信息(包括角色和更细粒度的访问权限)。 在联合技术领域,这些信息称为声明,基于声明的访问控制是联合安全模型的核心。 在这一模型中,应用程序和服务根据来自受信任颁发机构 (STS) 的声明,对特性和功能的访问进行授权。

  Windows Identity Foundation (WIF) 等平台工具大大降低了支持这种联合身份验证的难度。 WIF 是一个身份标识模型框架,用于构建基于声明的应用程序和服务,支持基于 SOAP(主动)和基于浏览器(被动)的联合方案。 在 MSDN 杂志 2009 年 11 月刊中的文章“通过 WIF 实现基于声明的授权”中,我重点介绍了如何在 Windows Communication Foundation (WCF) 中使用 WIF。 在这篇文章中,我介绍了如何为 WCF 服务实现基于声明的安全模型,以及如何迁移到联合身份验证。

  在本后续文章中,我将重点介绍被动联合。 我将说明被动联合的通信流程,介绍几种在 ASP.NET 应用程序中支持联合的方法,讨论基于声明的 ASP.NET 授权方法,然后介绍单一登录和单一注销方案。 同时,我将介绍支持被动联合方案的基础 WIF 功能和组件。

  被动联合基础

  被动联合方案基于 WS-Federation 规范。 该规范规定了如何请求安全令牌,如何发布和获取联合元数据文档,从而简化建立信任关系的过程。 WS-Federation 还规定了单一登录和注销过程,以及其他联合实现概念。

  WS-Federation 讨论了有关联合的诸多细节,其中有一部分专门介绍基于浏览器的联合,这种联合依靠 HTTP GET 和 POST、浏览器重定向以及 Cookie 实现目标。

  被动联合消息传递的某些方面主要基于 WS-Trust 规范。 例如,在请求 STS 的安全令牌时,被动联合采用与浏览器兼容的“请求安全令牌”(RST) 和“RST 响应”(RSTR) 形式。 在被动联合方案中,我将 RST 称为登录请求消息,将 RSTR 称为登录响应消息。 WS-Trust 规范侧重于基于 SOAP(主动)的联合,如 Windows 客户端与 WCF 服务的联合。

  图 1 是一个简单的被动联合方案。

联合身份标识:使用 WIF 实现 ASP.NET 被动身份验证

  图 1 简单被动联合方案

  用户在自己的域通过身份验证,根据其角色获得 Web 应用程序访问权限。 此身份验证方案中的参与者包括用户(主体)、Web 浏览器(请求者)、ASP.NET 应用程序(依赖方,即 RP)、负责在用户域中对用户进行身份验证的 IdP,以及属于用户域的 STS (IP-STS)。 一系列的浏览器重定向操作可以确保用户在访问 RP 之前在自己的域内通过身份验证。

  用户浏览至 RP 应用程序 (1),然后重定向到用户的 IdP 进行身份验证 (2)。 如果用户尚未在 IdP 经过身份验证,IP-STS 可能进行质询,或将用户重定向到登录页面以收集凭据 (3)。 用户提供自己的凭据 (4),然后由 IP-STS (5) 进行身份验证。 此时,IP-STS 根据登录请求颁发安全令牌,包含该令牌的登录响应通过浏览器重定向发送到 RP (6)。 RP 处理安全令牌,根据令牌携带的声明授予访问权限 (7)。 如果成功授权,则向用户显示其最初请求的页面,并且返回会话 Cookie (8)。

  使用 WIF 和 ASP.NET 实现此被动联合方案只需要几个步骤:

  建立 RP 和 IdP (IP-STS) 之间的信任关系

  对 ASP.NET 应用程序启用被动联合

  实现授权检查,以控制对应用程序功能的访问。在后面几节中,我将讨论支持被动联合的 WIF 功能,演示配置此简单方案的步骤,然后讨论此方案和其他方案在实践中应注意的事项。

  支持被动联合的 WIF 功能

  在讨论实现之前,我们回顾一下 WIF 专用于在 ASP.NET 应用程序中支持联合身份验证的功能。 首先,WIF 提供以下有用的 HTTP 模块:

  WSFederationAuthenticationModule (FAM):支持基于浏览器的联合,重定向到适当的 STS 以进行身份验证和令牌颁发,处理生成的登录响应,将已颁发安全令牌创建为 ClaimsPrincipal 以进行授权。 此模块还处理其他重要的联合消息,如注销请求。

  SessionAuthenticationModule (SAM):通过生成包含 ClaimsPrincipal 的会话安全令牌,管理经过身份验证的会话,将会话安全令牌写入 Cookie,管理会话 Cookie 的生存期,如果 Cookie 已存在,则根据 Cookie 重建 ClaimsPrincipal。 此模块还包含一个本地会话令牌缓存。

  ClaimsAuthorizatonModule:提供一个可扩展点,以便安装自定义 ClaimsAuthorizationManager,后者对于集中访问检查非常有用。

  ClaimsPrincipalHttpModule:根据附加到请求线程的当前用户身份创建 ClaimsPrincipal。 另外,该模块还提供一个可扩展点来安装自定义 ClaimsAuthenticationManager,后者用于自定义将附加到请求线程的 ClaimsPrincipal。

  ClaimsPrincipalHttpModule 最适合不使用被动联合的应用程序。 您可将该模块看作一个有用的工具,在 ASP.NET 应用程序迁移到被动联合之前,它可用来在应用程序内实现基于声明的安全模型。 我在以前的文章中讨论过这一 WCF 方法。

  其他三种模块通常一起用于被动联合 — 不过 ClaimsAuthorizationModule 是可选的。 图 2 演示这些核心模块如何构成请求管道,以及这些模块在典型的联合身份验证请求中的功能。

联合身份标识:使用 WIF 实现 ASP.NET 被动身份验证

  图 2 被动联合采用的 WIF 组件和 HTTP 模块

  请注意图 1 中的被动联合流程,当用户首先浏览至 RP 中的受保护页面时 (1),对应用程序的访问将被拒绝。 FAM 处理还未授权的请求,生成登录消息,然后将用户重定向到 IP-STS (2)。 IP-STS 验证用户身份 (3),生成登录响应(包含颁发的安全令牌),然后重定向回 RP 应用程序 (4)。

  FAM 处理登录响应(确保响应包含经过身份验证的用户的有效安全令牌),根据登录响应创建 ClaimsPrincipal (5)。 这将为请求线程和 HttpContext 设置安全主体。 然后,FAM 使用 SAM 将 ClaimsPrincipal 序列化为 HTTP Cookie (6),在浏览器会话期间用于后续请求。 如果安装了 ClaimsAuthorizationModule,该模块将调用经过配置的 ClaimsAuthorizationManager,以便在访问请求的资源之前针对 ClaimsPrincipal 执行全局访问检查 (7)。

  只要请求的资源存在,就可以实现访问控制,这一过程需要使用传统的 ASP.NET 登录控件、IsInRole 检查和其他查询用户声明的自定义代码 (8)。

  进行后续请求时,将使用该