了解 WebSphere Application Server SAML Trust Association Interceptor

IBM® WebSphere® Application Server 7.0、8.0 和 8.5 版的最新修复包包含一个新的 SAML Trust Association Interceptor (TAI),它引入了新的、高级的单点登录功能。TAI 包含许多属性,了解这些选项的用途和使用时机可能是一个挑战。本文的目的是帮助您了解 SAML TAI。 本文来自于 IBM WebSphere Developer Technical Journal 中文版

Martin Lansche, IT 咨询专家, IBM

Martin LanscheIBM WebSphere 软件服务部的一位咨询 IT 专家。他从事了 14 年的开发工作,涉及的领域包括虚拟机系统编程和 C/C++ 编译器工具。Martin 最近 8 年从事 ISSW 工作,起初从事 C++ 服务,最近重点研究自定义 WebSphere 安全解决方案,包括使用 Kerberos 和 SPNEGO 与 Active Directory 环境集成。他擅长的其他领域还包括 WebSphere 性能优化、故障排除和常规 WebSphere 系统管理。他拥有约克大学数字与计算机科学学士学位。


developerWorks 投稿作者

Paul Glezen, IT 咨询专家, IBM

Paul Glezen 是 IBM WebSphere 软件部的一名 IT 专家。他自上世纪 90 年代晚期开始担任针对 C++ 和 Java 应用服务器的应用程序开发和基础架构领域的 IBM 软件部顾问。目前他在专门研究 WebSphere Application Server 和 DataPower 设备的开发和安全配置。



2013 年 10 月 09 日

免费下载:IBM® WebSphere® Application Server 试用版
下载更多的 IBM 软件试用版,并加入 IBM 软件下载与技术交流群组,参与在线交流。

简介

IBM WebSphere Application Server(以及在 WebSphere Application Server 平台之上运行的一堆产品)自 V5.1 以来就有一个基于 Trust Association Interceptor (TAI) 接口的可自定义的身份验证框架。该接口有多种产品实现。2012 年,WebSphere Application Server 完整配置文件版本提供了一个新的 SAML(Security Assertion Markup Language,安全断言标记语言)TAI,它可用于 WebSphere Application Server 7.0、8.0 和 8.5 之上。(撰写本文之时,IBM WebSphere Application Server Liberty 配置文件还不支持 SAML。)这个 TAI 是目前最全面的 TAI。本文将介绍:

  • 如何使用 SAML TAI。
  • 何时适合使用 SAML TAI。
  • 各种 SAML TAI 属性如何配合使用。
  • SAML TAI 穿梭于 WebSphere Application Server 授权流程中时使用的错综复杂的路径。

本文假设您已牢牢掌握 WebSphere Application Server 身份验证流程(如文章 WebSphere Application Server 中的高级身份验证 中所述),而且了解:

  • 数字签名
  • 加密
  • 身份断言
  • TAI 的大体知识。

基础:Web 单点登录用例

SAML TAI 引入了对新的 Web 单点登录 (SSO) 形式的支持。正如我们在 WebSphere Application Server 安全类中所说的,术语 “SSO” 在行业中被严重过度使用,所以我们的 SSO 用例将非常严格。

SAML 多年来已发生演变。SAML 2.0 规范定义了一些配置文件和绑定:

  • SAML 配置文件描述了 SSO 交互中的各个参与方之间的不同消息交换序列。
  • SAML 绑定描述了如何将一条特定的消息绑定到某个协议。在配置文件的消息交换序列中的任意步骤中,配置文件都可以引用一个或多个绑定作为转发消息的方式选择。

SAML 配置文件包括:

  • SSO 配置文件
    • Web Browser SSO Profile
    • Enhanced Client or Proxy Profile
    • Identity Provider Discovery Profile
    • Single Logout Profile
    • Name Identity Management Profile
  • Artifact Resolution Profile
  • Assertion Query/Request Profile
  • Name Identifier Mapping Profile
  • SAML Attribute Profiles

SAML 绑定包括:

  • SAML SOAP Binding
  • Reverse SOAP Binding
  • HTTP Redirect Binding
  • HTTP Post Binding
  • HTTP Artifact Binding
  • SAML URI Binding

WebSphere Application Server 从修复包 7.0.0.7 开始支持通过 SAML SOAP Binding 来支持 SOAP。SAML TAI 是在修复包 7.0.0.23、8.0.0.5 和基础产品的 8.5.0.0 版中引入的。SAML TAI 仅支持结合使用 Web Browser SSO Profile 和 HTTP Post Binding。

可以看到,这只是许多可能的用例中的一种。事实上,确实存在两种变体。在介绍它们之前,我们先介绍一下所涉及的角色:

  • 身份提供程序 (IdP)
  • 服务提供程序 (SP) 有时称为中继方 (Relying Party) 或 RP。

IdP 的工作是验证最终用户(IdP 完成此操作的准确方式无关紧要),并生成一些关于用户的断言或声明。这些断言由 IdP 进行数字签名。SAML 规范定义了这些断言的格式。SP 接收断言,如果它对来自受信任的 IdP 的断言感到满意,则基于断言的某些部分来让用户登录。

我们还将查看一个基于真实用例的示例。Unified Assurance Company (UAC) 有许多企业客户;举例而言,Gamma Business Machine (GBM) 公司、Omicron Lumber Company 和 Purple Maple Syrup Company。我们将这 4 个(虚构的)公司视为位于一个 SSO 连锁中。在此示例中,Unified Assurance Company 了解这 3 个连锁成员的员工(UAC LDAP 中有针对外部连锁成员的员工的用户条目)。但是,UAC LDAP 中没有连锁成员的密码。

在这种情况下,Unified Assurance 希望将一个 IBM WebSphere Portal 系统提供给它的外部和内部用户。来自 GBM 的用户将向 GBM 中的一个系统进行验证,Omicron Lumber 用户向 Omicron Lumber 网络中的一个系统进行验证,而 Purple Maple Syrup 用户向 Google 托管的一个系统进行验证。(在本例中,对 WebSphere Portal 系统的使用只是偶然情况。)

图 1. SSO 连锁示例
SSO 连锁示例

该示例表明,用户登录到其 IdP 的详细信息与 United Assurance 不相关。举例而言,GBM 用户可通过一个登录表单进行登录,Omicron Lumber 用户使用 SPNEGO 身份验证自动将其凭据提供给 IdP,而 Purple Syrup 用户使用 SSL 客户端证书向其 IdP 进行验证。

另请注意,有一组彩色的私钥/公钥对。每个 IdP 都拥有自己的私钥,SP 在其 IdPTruststore 中保存了与这些私钥对应的所有相应公共证书的副本。

Web Browser SSO Profile 描述了如何通过 HTTP 重定向在用户的浏览器中传输 SAML 断言。针对 Web Browser SSO 的 HTTP Post Binding 可能有两种用例:浏览器请求首先传到 IdP,或者浏览器请求首先传到 SP。我们将前一种用例称为 IdP 发起的 Web SSO(图 2)。

图 2. IdP 发起的 Web SSO
图 2. IdP 发起的 Web SSO

IdP 发起的 Web SSO 用例中:

  1. 用户访问 IdP 上的一个 URL 链接来启动该过程。正如前面所讨论的,用户向 IdP 进行验证。
  2. 基于 IdP 中的配置和提供给 IdP 的原始 URL,创建一个 SAML 响应,并通过 HTTP Post 重定向将它发送给 SP 中的一个 Assertion Consumer Service (ACS)。这个 SAML 响应由 IdP 进行签名。
  3. SAML TAI 使用了 SAML 响应并让用户进行登录。在此示例中,用户身份存在于 UAC LDAP 中。但应注意的是,这不是 SAML Web SSO 所必需的。在内存中创建一个 JAAS 主题,还要创建各种 WebSphere Application Server 安全令牌,包括一个 SSOToken(也称为 LtpaToken2)。根据这个 SSOToken 创建一个 LtpaToken2。
  4. 在用户登录后,请求被分派到 ACS。这个应用程序的惟一用途是在使用 SAML TAI 让用户登录后,将用户重定向到正确的登录页面。ACS 定义了一个 Java™ EE 安全约束,以便调用 WebSphere Application Server 容器安全性和 SAML TAI。作为对 SAML TAI 的支持的一部分,还发布了一个 ACS 应用程序。如果愿意的话,可以将您的业务应用程序修改为包含 ACS 功能,添加一个接受 HTTP POST 的新 servlet。然后在下一步中,该 servlet 会被 “转发” 到正确的 “登录” 页面,而不是执行重定向。
  5. ACS 将用户重定向到应用程序的登录页面(可能基于请求中的某部分信息,或者基于配置)。在本示例中,这个 URL 为:https://benefits-portal.uac.com/wps/myportal。这个 HTTP 重定向包含新的 LtpaToken2 cookie。浏览器转到重定向路径,并重新发送 LtpaToken2。
  6. 然后会再次调用 SAML TAI,这一次检查请求中是否有一个 SAML 响应。如果没有,但有一个 LtpaToken2 cookie,则会执行标准的 Web Inbound 登录配置处理(稍后将介绍)。

此方法的一个限制是,用户需要调用一个由 IdP 托管的 URL 的 GET 链接。请考虑以下示例:GBM 的用户需要知道用于登录到 UAC Portal 的特定于 GBM 的 URL,Omicron 员工需要知道(不同的)Omicron URL,而 Purple Maple Syrup 员工需要知道(不同的)Purple Maple Syrup URL。在每组用户登录到 UAC Portal 后,都会登录到 https://benefits-portal.uac.com/wps/myportal

此方法的另一个限制是,一个 IdP 可用于为多个服务提供程序验证用户。GBM 用户还可以使用同一个 SSO IdP 登录到与 GBM 有业务关系的汽车租赁系统。但是,(从用户角度讲)UAC Portal 和汽车租赁系统的 URL 托管在同一个 GBM IdP 服务器上。用户可能将它们混淆。

为了解决这些限制,服务提供程序常常会开发品牌认知。无论用户来自哪个连锁合作伙伴。每个用户都可以单击一个包含 https://benefits-portal.uac.com 的链接。用户首先将浏览器定向到服务提供程序,然后服务提供程序会启动 SSO 流程。WebSphere Application Server SAML TAI 支持第二种用例;通过配置,SAML TAI 将用户重定向到 IdP。我们将此称为 SP 重定向到 IdP Web SSO 用例(图 3)。

图 3. SP 重定向到 IdP
图 3. SP 重定向到 IdP

SP 重定向到 IdP Web SSO 用例中:

  1. 用户访问 SP 上的应用程序 URL 链接来启动该过程。在此示例中,这个链接为 https://benefits-portal.uac.com/wps/myportal
  2. SAML TAI 将被调用两次。因为这个 URL 不是 ACS,所以 TAI 最初不会解释请求。Web Inbound 配置寻找一个 LtpaToken2 cookie。没有找到。第二次调用 SAML TAI。基于传入请求中的一些数据和 TAI 配置,TAI 返回一个重定向到正确 IdP 的 HTTP 302 代码(稍后将讨论如何确定任何特定请求的正确 IdP)。TAI 设置一个 cookie。这个 cookie 被设置为原始 referrer URL 的值,在本示例中为 https://benefits-portal.uac.com/wps/myportal。如上面所讨论的,用户向 IdP 进行验证。

第 3 到 7 步与 “IdP 发起的 Web SSO” 用例中第 2 到 6 步相同。


WebSphere Application Server SAML TAI

为了在 WebSphere Application Server V8.5(以及 7.0 和 8.0 版)中实现 SAML Web SSO 功能,该功能使用了一个 Trust Association Interceptor (TAI) 来实现。(这篇文章 全面讨论了 WebSphere Application Server TAI。)SAML TAI 的完整类名为 com.ibm.ws.security.web.saml.ACSTrustAssociationInterceptor。以下方面会影响 SAML Web SSO TAI:

  • 必须启用管理安全性。
  • SAML TAI 可在全局上或在其他安全域定义。
  • 配置 SAML TAI 的域必须启用应用程序安全性。它还必须启用 TAI,并配置了 SAML TAI。
  • 在用户登录到 WebSphere Application Server 期间,SAML TAI 将来自 POST 请求的 SAML 断言的副本保存在用户的主题(例如用于出站 Web 服务调用)的私有凭据中。

    Subject Attribute Propagation

    必须启用,这些(未存储在 User Registry 中的)自定义信息才能在单元中的服务器之间传播。因为这些 SAML 断言无法从 WebSphere Application Server 注册表中获得,所以为主题定义了一个适当的自定义缓存键。(主题传播、自定义缓存键和 TAI 的微妙影响不属于本文的讨论范畴。请参阅 这篇文章,了解全面的介绍。)
  • SAML TAI 支持多个应用程序,每个应用程序可以有自己的 ACS URL。
  • 每个应用程序可与多个 IdP 交互。每个 IdP 可能够以不同的方式进行配置。
  • SAML TAI 仅支持 Web SSO Profile 和 HTTP Post Binding。

重要的是全面理解最后一点,这一点的衍生结果是,仅有一个 HTTP POST 消息从 IdP 流到 WebSphere Application Server SAML TAI,该消息在 POST 正文中包含 SAML Response 对象。WebSphere Application Server SAML TAI 基于这个 SAML Response 对象来记录用户,返回一个 LtpaToken2 cookie。配置文件和绑定适合到达应用程序的经过验证的登录页面。来自浏览器的后续交互基于 HTTP 客户端(通常为用户的浏览器)返回的 LtpaToken2 cookie 来维护用户的登录上下文。

我们提出这一点是为了指出,尽管该 POST 中包含的 SAML 断言允许使用稍微 “可移植的” 令牌,但这个可移植的令牌会迅速被一个特定于 WebSphere 的 LtpaToken2 cookie 取代。这个模型通过浏览器很好地提供给用户。但它不能很好地提供给其他没有 “登录到登录页面并通过 cookie 维护登录状态” 模型的 HTTP 应用程序客户端。例如,如果某个 RESTful Web 服务应用程序想要使用所有 HTTP 方法(GET、PUT、POST 和 DELETE),那么必须构造它来实现以下操作:

  1. 确定应用程序是否有一个 LtpaToken2 cookie。
  2. 如果没有,则获取一个 SAML 响应,并跟随从定向的 POST 访问 ACS,使客户应用程序能够获得一个 LtpaToken2 cookie。
  3. 只有成功执行上述两步后,才能执行应用程序希望首先调用的真实的 Web 服务操作。

由于主题和 LtpaToken2 中的自定义缓存键,必须启用主题属性传播,以便在 WebSphere SSO “单元” 中的 JVM 之间实现完整用户身份的传播。这可包含对用户登录到的原始服务器的 JMX 回调。


SAML TAI 和 Web 入站登录配置

这篇文章中的图 20 所示的逻辑流已在图 4 中进一步完善,以支持 SAML TAI。如果用户有一个 LtpaToken2 cookie,而且浏览器使用一个新的 SAML 断言向 ACS 发出 POST 请求,那么原始 LtpaToken2 cookie 必须忽略,而且应在创建新主题时使用来自 SAML 断言的用户身份。这一行为更改受一般性的自定义属性 com.ibm.websphere.security.InvokeTAIbeforeSSO 控制,而该属性为 SAML TAI 类 (com.ibm.ws.security.web.saml.ACSTrustAssociationInterceptor) 的值。如果 SAML TAI 是在全局基础上定义的,则将这个自定义属性添加到 Global Security 页面上。如果 SAML TAI 是在一个安全域中定义的,则将这个自定义属性添加到该安全域的 Custom Properties 上。

新逻辑流的第一部分如图 4 所示。

图 4. SAML TAI 在 LtpaToken2 之前处理 SAML Tokens
图 4. SAML TAI 在 LtpaToken2 之前处理 SAML Tokens

换言之,如果正确定义了属性 InvokeTAIbeforeSSO,SAML TAI 会在检查 SSO Token (LtpaToken2 cookie) 之前被调用。

要支持 SP 重定向到 IdP Web SSO 用例,SAML TAI 可潜在地调用多次,如果没有 LtpaToken2,并且没有 SAML 断言,那么可以在执行第二个特殊安全属性 com.ibm.websphere.security.DeferTAItoSSO 时调用 SAML TAI 逻辑,该属性为 SAML TAI 类的值。此属性也被定义为 Global Security 页面上或启用了 SAML TAI 的安全域的 Custom Properties 上的一个自定义属性。

如果检查 SP 重定向到 IdP Web SSO 用例,您可看到,在一些场景中,可在初始登录时调用 SAML TAI 多次。参见图 5,了解如何为 SP 重定向到 IdP Web SSO 用例处理 SAML TAI 支持。

图 5. “SP 重定向到 IdP Web SSO” 的 SAML TAI 支持
图 5. “SP 重定向到 IdP Web SSO” 的 SAML TAI 支持

将轨迹规范设置为 com.ibm.ws.security.web.saml.*=all 时,检查轨迹可确认 SP 重定向到 IdP Web SSO 用例期间这两个流程图中的逻辑。

为了帮助完成此练习,下面这个示例中有两个 TAI:一个不会进行拦截、但会在日志中发出一条消息的 FakeTAI(清单 1)。

清单 1.
[3/20/13 16:22:49:635 EDT] 00000024 TrustAssociat A   SECJ0121I: Trust Association Init 
class com.ibm.issw.security.FakeTAI loaded successfully
[3/20/13 16:22:49:640 EDT] 00000024 TrustAssociat A   SECJ0122I: Trust Association Init 
Interceptor signature: 1.2
[3/20/13 16:22:49:642 EDT] 00000024 TrustAssociat A   SECJ0121I: Trust Association Init 
class com.ibm.ws.security.web.saml.ACSTrustAssociationInterceptor loaded successfully
[3/20/13 16:22:49:644 EDT] 00000024 ACSTrustAssoc >  initialize Entry
…
[3/20/13 16:22:49:670 EDT] 00000024 ACSTrustAssoc <  initialize Exit
[3/20/13 16:22:49:670 EDT] 00000024 TrustAssociat A   SECJ0122I: Trust Association Init 
Interceptor signature: <null>

在清单 2 中,在处理 SSO 之前调用 SAML TAI。

清单 2.
[3/20/13 16:22:49:673 EDT] 00000024 ACSTrustAssoc >  isFirstPass Entry
…
[3/20/13 16:22:49:674 EDT] 00000024 ACSTrustAssoc 3   Request does not contain 
SAMLResponse, TAI will be skipped and deferred.
[3/20/13 16:22:49:675 EDT] 00000024 ACSTrustAssoc 3   Request is scoped to this TAI.

接下来是 SSO 处理。首先调用 Fake TAI。它没有进行拦截。然后调用 SAML TAI(清单 3)。

清单 3.
[3/20/13 16:22:49:679 EDT] 00000024 SystemOut     O   FakeTAI.isTargetInterceptor() 
returns 'false' 
[3/20/13 16:22:49:680 EDT] 00000024 ACSTrustAssoc >  isFirstPass Entry	
…
[3/20/13 16:22:49:697 EDT] 00000024 SAMLTaiState  3   SAML TAI challenge login: Referer 
URL cookie set https://oc5067386220.ibm.com:9444/HitCountWeb/HitCountServlet
[3/20/13 16:22:49:697 EDT] 00000024 ACSTrustAssoc <  createTAIErrorResult Exit
[3/20/13 16:22:49:697 EDT] 00000024 ACSTrustAssoc <  invokeTAIafterSSO Exit
[3/20/13 16:22:49:698 EDT] 00000024 ACSTrustAssoc <  negotiateValidateandEstablishTrust 
Exit

该轨迹现在处理来自图 2 的第 3 条消息(清单 4)。

清单 4.
[3/20/13 16:22:56:207 EDT] 00000026 ACSTrustAssoc >  isFirstPass Entry
…
[3/20/13 16:22:56:212 EDT] 00000026 ACSTrustAssoc 3   Request contains SAMLResponse, 
TAI will be processed.
…
[3/20/13 16:22:56:484 EDT] 00000026 ACSTrustAssoc <  negotiateValidateandEstablishTrust
Exit

用户登录。将一个 LtpaToken2 cookie 发送给用户。因为您使用了内置的 ACS 应用程序,所以 ACS 会将浏览器重定向到原始 referrer URL cookie 值,也就是 https://oc5067386220.ibm.com:9444/HitCountWeb/HitCountServlet(原始 referrer URL cookie 通过 SAML TAI 来设置。)

图 2 中的第 6 条消息出现并进入轨迹。再次声明,在检查 LtpaToken2 cookie 之前调用 SAML TAI(清单 5)。

清单 5.
[3/20/13 16:22:56:774 EDT] 00000026 ServerCache   I   DYNA1071I: The cache provider 
"default" is being used.
[3/20/13 16:22:57:627 EDT] 00000025 ACSTrustAssoc >  isFirstPass Entry
…
[3/20/13 16:22:57:627 EDT] 00000025 ACSTrustAssoc 3   Request does not contain 
SAMLResponse, TAI will be skipped and deferred.
…
[3/20/13 16:22:57:628 EDT] 00000025 ACSTrustAssoc 3   Request is scoped to this TAI.

请注意,我们找到了 LtpaToken2 cookie,而且 Fake TAI 和 SAML TAI 都未被再次调用。HitCount 应用程序被调用,它报告了调用方的身份 - 从主题获取,主题是从第 3 条消息中的 SAML Response 生成的(清单 6)。

清单 6.
[3/20/13 16:22:57:632 EDT] 00000025 SystemOut     O   J2EE APIs: HitCount received 
request from Alice

SAML TAI 属性

尽管作为一个 TAI 进行实现支持将函数向后移植到更早的 WebSphere Application Server 版本中,但它导致必须正确定义许多 TAI 属性才能让 TAI 继续运行(如果熟悉 WebSphere Application Server V6.1 中的 SPNEGO TAI,您应将设置 SPNEGO TAI 属性的复杂性与 WebSphere Application Server V7.0 中的 SPNEGO Web Authenticator 中集成的等效函数进行对比,SPNEGO 配置是管理控制台中的第一个类结构。)

SAML TAI 属性记录在 信息中心 中。有一个属性分层结构,请在信息中心中查阅详细信息:

  • 全局属性适用于所有为 SAML TAI 配置的 SSO 合作伙伴(托管 IdP 的合作伙伴)。这些属性没有前缀 “sso_<id>”(其中 <id> 是一个整数)。大多数全局属性都可使用特定的 IdP 等效属性进行覆盖。
  • 服务提供程序属性适用于某个服务提供程序,针对每个 SSO 服务提供程序合作伙伴的这些属性分组到惟一的 sso_<id> 之下。
  • IdP 属性适用于为 SAML TAI 配置的身份提供程序。要分配标识每个身份提供程序合作伙伴的惟一属性名称,可将一个 idp_<id> 嵌入在属性名称中,并使用它对于每个 SSO IdP 合作伙伴有关联的属性进行分组。对于某个给定的服务提供程序,配置的 IdP 属性具有前缀 “sso_<id>.idp_<id^>”。

我们不打算解释所有属性的用途,而是将它们分组到一起,以展示如何应用它们来解决某些问题。(这里并没有解释所有属性。)

IdP 发起的 SSO:需要哪些属性才能完成 SSO?

向 IdP 验证后,IdP 将浏览器重定向到合适的 ACS URL。SAML TAI 确定向请求应用哪种(如果有)服务提供程序配置。

  • 为了确定应用何种配置,SAML TAI 将 URL 与所有 sso_<n>. sp.acsUrl 属性中定义的模式相匹配。如果找到了匹配值,则应用所有 sso_<n>(服务提供程序)属性,以及所有全局属性。
  • 一旦决定解释请求,SAML TAI 需要确保 IdP 的身份是一组受信任的 IdP 之一。这里提供了两个选项,IdP 可通过以下两种方式进行识别:
    • 区分名 (distinguished name),sso_<n>.idp_<m>.allowedIssuerDN
    • 简单名称,sso_<n>.idp_<m>.allowedIssuerName

在用户向 ACS URL 发出包含无效 SAML Response(或许由另一个 IdP 发出)的 POST 请求时,将通过重定向返回 sso_<n>.acsErrorPage 所指定的 URL。

了解如何从 SAML 响应提取用户身份,如何创建用户身份,登录成功后重定向到何处,如何信任来自某个受信任 IdP 的请求,以及如何保护来路不正的请求之前,我们首先看看 SP 重定向到 IdP Web SSO 用例的更多属性。

SP 重定向到 IdP Web SSO:完成 SSO 需要哪些属性?

考虑图 3 中所示的情形。一个 GBM 用户在浏览器中访问 https://benefits-portal.uac.com/wps/myportal。如上所述,TAI 没有立即拦截;这不是一个 ACS URL。因为这是第一个请求,所以没有 LtpaToken2 cookie。前面已经提到过,基于传入请求中的某些数据,SAML TAI 返回重定向到正确 IdP 的 HTTP 302 代码。SAML TAI 如何知道将此请求重定向到(在本例中)GBM IdP 而不是其他某个 IdP?

SAML TAI 过滤器属性 sso_<n>.sp.filter 控制了 SAML TAI 如何确定某个特定 URL 应否发起向 IdP 的服务提供程序重定向。该过滤器的功能与 SPNEGO TAI 的过滤器相同。如果缺少过滤器设置,则会拦截发送到 Java EE 保护 URL 的所有请求。

APAR PM84513 通过多种 SP 配置解决了一个问题,每种配置都有惟一的 “过滤器” 定义;发送到 SAML TAI 的第一个请求会查找匹配的 “过滤器”,以确定对第一个请求应用何种 SP 配置。如果没有这个 APAR,那么对 SAML TAI 的所有后续调用都将继续使用相同的 SP 配置;后续请求不会检查匹配的过滤器条件。强烈建议应用此修复补丁。

如果基于过滤器条件而拦截了请求,将会返回 sso_<n>.sp.login.error.page 属性指定的页面。如果只有一个 IdP,这可能是一个仅供此 IdP 使用的 URL。

如果有多个 IdP,那么 SP 配置的每个 IdP 都将有自己的 sso_<n>.idp_<m>.SingleSignOnUrl 值,并指定 SAML TAI 重定向到哪个 URL 来发起 SAML SSO。但问题仍然存在:如何确定选择哪个 “idp_<m>”?如果有多个 IdP,login.error.page 属性可指向一个包含多个 IdP 链接的 HTML 页面;在更加完善的解决方案中,该属性指向一个实现清单 7 中所示的接口的类。

清单 7. IdentityProviderMapping 接口
import javax.servlet.http.HttpServletRequest;
import java.util.String ;
import java.util.ArrayList ;
import com.ibm.websphere.security.NotImplementedException;
import com.ibm.wsspi.security.web.saml.IdentityProviderMapping;
	
public abstract interface IdentityProviderMapping {
   public abstract String getIdentityProviderOrErrorURL(
      HttpServletRequest req,
      String errMsg, 
      String acs, 
      ArrayList<String> ssoUrls) throws NotImplementedException;
}

实现此类,将 JAR 文件放在 <WAS>/lib/ext 中。可在实现中执行任何可以想到的逻辑。在清单 8 中所示的示例源代码 SampleIDPMapping.java 中,搜索一个 ?idp=<URL> 参数或(假设用户之前访问过该站点)一个名为 SAMLIDP 的持久性 cookie。

清单 8. SampleIDPMappingImpl.java 类摘录
private static final String COOKIE = "SAMLIDP";
…
// Assumes that 
//   idp_1 is configured as GBM IdP
//   idp_2 is configured as Omicron Lumber IdP
//   idp_3 is configured as Purple Maple Syrup IdP
…
// Prefer URL parameter over cookies. So only look for cookies 
// if URL parameter not set.
String idpValue = req.getParameter("idp");
if (idpValue==null) {
   log.finer("URL Parameter was not found, so looking for IDP cookie");
   Cookie[] cookies = req.getCookies();
   if (cookies != null) {
      for (Cookie cookie : cookies) {
         if (cookie.getName().equals(COOKIE)) {
           String cookieValue = cookie.getValue();
…
         }
      }
   }
}
…
if (idpValue.equalsIgnoreCase("omicron")) { 
   // We know that ssoUrls.size() < 1 here
   log.finer("Omicron IDP requested. Returning (ssoUrls.get(1))");
   idpUrl = ssoUrls.get(1);
} else if (idpValue.equalsIgnoreCase("purple")) { 
   // We know that ssoUrls.size() < 1 here
   log.finer("Purple IDP requested. Returning (ssoUrls.get(2))");
   idpUrl = ssoUrls.get(2);
} else { 
   // otherwise return ssoURL[0] - default "gbm"
   log.fine("IDP requested " + idpValue + 
            ". Default to gbm IDP (ssoUrls.get(0))");
   idpUrl = ssoUrls.get(0);
}

在此示例中,如果 cookie 和 “idp=” 参数都未提供,默认情况下会选择 GBM IdP。另一个实际示例将是,基于传入的 HttpServletRequest 来确定使用哪个 IdP。我们没有提供这个示例的代码。


SAML TAI 如何知道在登录到 WebSphere Application Server 后重定向到何处?

在 SAML TAI 处理了在 POST 中发送给 ACS 的 SAML Response 后,而且 WebSphere Application Server 安全运行时让用户登录并生成了一个 JAAS 主题后,ACS 应用程序将:

  • 对浏览器执行 HTTP 302 重定向,将它重定向到已登录的登录页面。
  • 向应用程序中的一个地址执行内部转移。为了能够使用此选项,所转移到的 URL 所在的 Web 应用程序中必须包含 ACS URL。一般的 ACS 应用程序无法执行转移操作。
  • IdP 发送的 SAML Response 可以有选择地包含一个 URL,SP 应通过一个名为 RelayState 的 SAML 属性重定向到该 URL。

为了支持上面的第一个选项,一般的 ACS 应用程序会使用 sso_<n>.sp.targetURL 属性。如果 IdP 发送 RelayState,那么默认情况下会使用第 3 个选项。要覆盖所发送的 RelayState,可使用 sso_<n>.sp.useRelayStateForTarget 属性。SP 发起的指定重定向目标的最常见方式是通过原始 referrer URL cookie 来完成的,该 cookie 也被称为 WasSamlSpReqURL cookie。


SAML TAI 为什么相信 SAML 断言?

您可能会问上面这个问题。否则,攻击者可能设计出一个格式正确的 SAML Response,通过 POST 发送到 ACS,然后以攻击者想要的任何人的身份登录。SAML TAI 必须确认请求来自一个受信任的 IdP。换言之,SAML TAI 必须向 IdP 进行验证。这通过确认 SAML Response 的数字签名来执行。

SAML Response 包含数据的数字签名。该签名包含使用 SAML Response 中通告的算法对数据计算的哈希值。这个哈希输出随后使用 IdP 所持有的私钥进行加密。要验证该签名,SP (SAML TAI) 计算相同内容的哈希值,然后解密 IdP 提供的哈希值(SAML Response 包含公共证书)。如果它们匹配,则 SP 知道该内容未被更改(这称为数据完整性),而且该内容是由与公共证书对应的私钥持有者生成的。公共证书的发行者必须值得信赖。

以下属性控制了 SAML TAI 的签名确认行为:

  • sso_<n>.sp.wantAssertionsSigned
  • sso_<n>.sp.trustAnySigner — 当然,此属性要小心使用。
  • sso_<n>.sp.trustStore — 这是一个 WebSphere Application Server 信任存储库对象的名称,该对象包含 IdP 的签名者证书。它不是文件的名称,而是在管理控制台中看到的对象名称。
  • sso_<n>.sp.X509PATH — 作为使用 WebSphere 信任存储库对象的一种替代方法,可提供一个包含签名证书的中间证书的文件的路径。
  • sso_<n>.sp.CRLPATH — 一个包含证书存储库的名称,其中包含一个证书撤销列表 (CRL)。
  • sso_<n>.sp.trustedAlias — 如果信任存储库包含多个证书,而且您希望限制信任存储库中的哪个证书可用于验证签名,那么可以使用此属性来指定。

正确设置这些属性并将签名证书保存在信任存储库中可能很困难。有一个名为 importSAMLIdpMetadata 的 wsadmin AdminTask 可帮助您完成此工作。


保护 SAML 断言

发现的特定于 ADFS 2.0 的问题

在默认情况下,ADFS 要求所有用于加密的证书包含一个证书撤销列表 (CRL) 端点。如果证书不包含 CRL 端点,则必须将 ADFS 配置为不需要 CRL。可使用 Set-ADFSRelyingPartyTrust cmdlet 的 EncryptionCertificateRevocationCheck 参数。

ADFS 通过区分名来识别发行方;这是一个字符串。如果该区分名包含一个 StateOrProvinceName 字段,则会出现问题。Microsoft® 使用了非传统的 “S=” 形式,而在 WebSphere Application Server 中,Java 要求该字段表示为 “ST=”。由于此差别,不能使用包含 StateOfProvinceName 字段的发行方证书。

对 ACS 应用程序的 HTTP POST 请求正常情况下应通过 https 连接发送。事实上,许多 IdP 都需要通过 SSL 连接。除了 SSL 连接所提供的加密之外,可能还有一个加密 SAML Response 对象的有效负载的原因。请记住,IdP 通过用户的浏览器来重定向请求。通过使用浏览器插件,用户可查看流经浏览器的 SAML Response(用户不能更改内容,因为这会导致数字签名检查失败,但他仍然可以看到内容)。如果您的使用情形不需要这种辅助加密,则不需要加密 SAML Response。

为了实现加密,SP (SAML TAI) 使用了它自己的私钥/公钥对。通过一个公共证书为 IdP 提供公钥的副本,它使用此公共证书来加密内容。只有私钥的持有者 (TAI) 可解密内容。支持 SAML Response 加密的属性包括:

  • sso_<n>.sp.keyStore — 这是包含您的 SP 的个人证书的 WebSphere Application Server 密钥存储库对象的名称。它不是文件的名称,而是在管理控制台中看到的托管的对象名称。
  • sso_<n>.sp.keyAlias — 密钥存储库中的密钥的别名。
  • sso_<n>.sp.keyPassword — 访问该密钥所需的密码。
  • sso_<n>.sp.keyName — 无需使用密钥别名,也可指定要使用的密钥的完整区分名。

IdP 需要收到公共证书(和任何签名者)。再次声明,您可以使用 wsadmin AdminTask exportSAMLSpMetadata 创建一个可由 IdP 应用程序导入的 XML 文件(依赖于您的 IdP 系统,您可能需要编辑得到的 XML,以便仅引用加密证书信息)。


如何自定义用户身份

IdP 断言一个使用 SAML TAI 的用户。根据您的具体使用情形,该用户不一定存在于 WebSphere Application Server 用户注册表中。我们假设该用户是一个本地用户或暂时的用户(一些 WebSphere 产品,比如 IBM Business Process Manager (BPM),要求所有登录的用户都存在于用户注册表中,所以他们必须是本地用户。)

要断言一个本地用户,可指定 SAML TAI 属性 sso_<n>.sp.idMap = localRealm。对于本地用户,SAML Response 中的 NameID 字段被设置为 JAAS Subject 中的 userid(下面将讨论如何通过 userMapImpl 属性来映射 userid)。WebSphere Application Server 将通过查询用户注册表来完成该主题。

临时用户是被断言为确实存在的用户,但他们不受基础用户存储库(比如 LDAP)中任何条目的实际支持。对于临时用户,principalName 从属性 sso_<n>.sp.principalName 中的属性名获取。

要断言一个临时用户,可设置属性 sso_<n>.sp.idMap = idAssertion。设置该属性(而且此属性值为默认值)时,一些 SAML TAI 属性可准确控制哪些用户身份已经登录。前两个分别标识 SAML Response 中用于填充 principalName 和 uniqueID 的元素:

  • sso_<n>.sp.principalName
  • sso_<n>.sp.uniqueId

向 userid 分配哪个域 (realm) 由以下属性确定:

  • sso_<n>>.sp.realmName
  • sso_<n>.sp.realmNameRange
  • sso_<n>.sp.defaultRealm
  • sso_<n>.sp.useRealm

如果使用 idAssertion,并且没有设置任何这些与域相关的属性,那么 SAML Response 中定义的 IssuerName 将是所使用的域名称。

除了上述属性之外,还有两种建立用户身份的混合方法。第一种混合方法使用 idMap 值 = localRealmThenAssertion。在这种模式下,将会从 SAML Response 中提取用户身份并搜索用户注册表。如果在用户注册表中找到了该用户,则将以 localRealm 用户身份继续登录。如果未找到该用户,那么登录将以 idAssertion 用户身份继续进行。

第二种混合方法使用 idMap 值 = idAssertionUsingGroups。这种方法使用 SAML Response 中断言的组信息来扩充从用户注册表返回的 localRealm 用户的组成员关系信息。(考虑使用来自用户注册表的数据来扩充临时用户的组成员关系信息是没有任何意义的,因为根据定义,临时用户不存在于用户注册表中,而且没有额外的组要添加。)

如果从 SAML Response 考虑组成员关系,SAML Response 中的组元素的名称由 sso_<n>.sp.groupName 属性指定。

从 SAML Response 获取的组成员关系可通过设置 sso_<n>.sp.groupMap=localRealm 属性来映射到用户注册表组。组成员关系也可通过设置 sso_<n>.sp.groupMap= AddGroupsFromLocalRealm 在用户的主题中断言,甚至在用户注册表中不存在组时也可以这样做。

考虑图 6 中的示例。无需断言用户是否存在于 UAC LDAP (localRealm) 中,Purple 用户是临时用户。它们的组成员关系也通过 SAML Response 断言。具体来讲,我们关注的是它们在 UACGroup 中的成员关系。其他组也会断言,但对 UAC 应用程序并不重要。用户访问的 UAC Web 应用程序有一个安全角色,该角色被明确限定为来自外部受信任域 idp.purple.com/adfs/services/trust 的 UACGroup 组。您必须将 IdP 配置为在 SAML Response 中生成合适的组成员关系声明。

图 6. 断言临时身份
图 6. 断言临时身份

最后,SAML Response 中断言的 userid/principalName/NameID 通常需要进行某种转换,随后才能向 WebSphere Application Server 断言身份。或者 SAML Response XML 文档(包含应使用的身份)中或许有不同的元素。sso_<n>.sp.userMapImpl 提供了 SAML TAI 的另一个插入点(一个接口),您可在其中实现一个自定义的用户映射类来返回所断言的用户身份。userMapImpl 的接口如清单 9 所示。

清单 9. UserMapping 接口
import java.util.String ;
import com.ibm.websphere.security.NotImplementedException;
import com.ibm.websphere.security.UserMappingException;
import com.ibm.websphere.wssecurity.wssapi.token.SAMLToken;
import com.ibm.wsspi.security.web.saml.UserMapping;

public abstract interface UserMapping {
  
 public abstract String mapSAMLAssertionToName(SAMLToken samlToken)
			throws UserMappingException, NotImplementedException;
}

在第二个自定义实现示例中,您希望忽略 SAML Response 中的 NameID 元素,从 Response 中的区分名元素来建立用户身份(清单 10)。

清单 10. SampleUserMapping.java 类的摘录片段
/** Standard ADFS name for a SAML attribute containing the DN. */
public static final String SAML_ATTR_DN = 
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/distinguishedname";
public static final String FRIENDLYNAME = "Custom User Mapping";

public String mapSAMLAssertionToName(SAMLToken samlToken)
			throws UserMappingException, NotImplementedException {
   log.entering(CLASSNAME, "mapSAMLAssertionToName");
   String result = null;
   result = getDN(samlToken);
   log.fine(FRIENDLYNAME + " mapped to user " + result);
   log.exiting(CLASSNAME, "mapSAMLAssertionToName");
   return result;
}

public static String getDN(SAMLToken token) throws UserMappingException {
   String dn = null;
   if (token != null) {
      List<SAMLAttribute< attrList =  token.getSAMLAttributes();
      if (attrList != null  && attrList.size() < 0) {
         for (SAMLAttribute attr : attrList) {
            if (attr.getName().equals(SAML_ATTR_DN)) {
               if (attr.getStringAttributeValue().length > 0) {
                  dn = attr.getStringAttributeValue()[0];
                  log.fine("User Mapping found DN: " + dn);
                  break;
               }
            }
	…// Error checking code removed.
   return dn;
}

设置 SAML TAI

下面通过一些高级架构类型问题的形式,帮助您了解设置 SAML TAI 的总体步骤:

  1. SAML TAI 要保护哪些 URL? – 您需要确定哪些 URL(应用程序,如果有)将导致 SP 重定向到 IdP Web SSO 情形。这将是过滤器属性的输入。
  2. 对于 SP,IdP 将重定向到哪个 ACS URL?
  3. 用户将以 localRealm 还是 idAssertion userid 登录?
  4. SAML Response 是否会加密?

对于每个 IdP,您需要知道:

  • IdP 供应商是谁?
  • 该供应商是否支持 RelayState?
  • IdP 接受何种格式的 SP 元数据?
  • IdP 身份 ID 是什么?
  • 您是否拥有 IdP 所使用的签名证书,包括完整的发行者链?

笼统地讲,WebSphere Application Server 管理步骤包括:

  1. 如果加密 SAML Response,则使用 WebSphere Application Server 管理工具创建一个新的密钥存储库,称为(举例而言)SPKeyStore:
    • 生成私钥/公钥和公共证书。
    • 导出公共证书,可能以 SAML 元数据形式。
  2. 使用管理工具,创建一个名为(举例而言)IdPTrustStore 的新的信任存储库。安装签名 IdP 签名证书和证书链。
  3. 添加 SAML TAI (ACSTrustAssociationInterceptor) – 还不要启用 TAI。
  4. 将 TAI 添加到 com.ibm.websphere.security.DeferTAItoSSO 自定义属性(以启用 SP 重定向到 IdP Web SSO)。
  5. 将 TAI 添加到 com.ibm.websphere.security.InvokeTAIbeforeSSO 自定义属性(以首选 SAML 令牌而不是 LtpaToken)。
  6. 配置 SAML TAI 属性。
  7. 安装 ACS 应用程序:<was>/installableApps/WebSphereSamlSP.ear。
  8. 启用 TAI。

一些与 SAML TAI 相关的有用的 AdminTask 包括:

  • AdminTask.showSAMLTAISSO()
  • AdminTask.showSAMLIdpPartner()
  • AdminTask.importSAMLIdpMetadata()
  • AdminTask.exportSAMLSpMetadata()

有用的轨迹规范:

  • com.ibm.ws.security.web.saml.*
  • com.ibm.ws.security.*

提示和技巧

不要将浏览器直接指向 ACS URL,除非发出了一个 SAML Response 供它处理。否则,您会遇到针对该应用程序的身份验证质询。对于发布的 ACS,这是一个 Basic Auth 质询。如果实现了自己的自定义 ACS 应用程序,那么这可能是一种基于表单的登录。

如果编写自己的 UserMapping 或 IdPMapping 类,如上面的代码示例中所示,那么可以使用 Java 日志将此代码与 WebSphere Application Server 轨迹基础架构相集成。这使您能够在代码中动态地启用或禁用追踪。


结束语

本文提供了一些指导信息,帮助运行在 IBM WebSphere Application Server 之上的那些系统的管理员了解新的 SAML Web TAI,了解它在 WebSphere Application Server 中的现有 Web 安全运行时内的工作原理,它如何让安全性产生细微的变化,大量自定义 TAI 属性如何彼此交互,以及何时使用这些自定义 TAI 属性(以及何时不需要它们)。我们还提供了两个样例实现,展示了如何自定义登录流程。


致谢

感谢同事 Jens Engelke、Michael Whale、Simon Kapadia、Bill O’Donnell 和 Chunlong Liang 提供宝贵的输入和帮助。

参考资料

学习

获得产品和技术

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=WebSphere
ArticleID=947711
ArticleTitle=了解 WebSphere Application Server SAML Trust Association Interceptor
publish-date=10092013