IBM® WebSphere® Application Server(以及在此平台上运行的产品栈)自 V5.1 开始拥有一个可自定义的身份验证框架。该框架基于信任关联拦截器 (TAI) 接口,此接口有多种产品实现。2012 年,WebSphere Application Server Full Profile 版本包含了一种新的安全断言标记语言 (SAML) TAI。WebSphere Application Server 7.0、8.0 和 8.5 版提供了此接口。(截至编写本文时,IBM WebSphere Application Server Liberty Profile 版本不支持 SAML。)SAML TAI 是目前可用的最全面的 TAI。
在本文中,将了解如何使用 SAML TAI 和何时适合使用 SAML TAI。还将了解各种 SAML TAI 属性如何协同发挥作用。此外,您还将看到 SAML TAI 实现 WebSphere Application Server 授权流程的复杂路径。
阅读本文之前,必须非常了解 WebSphere Application Server 身份验证流程(如文章 WebSphere Application Server 中的高级身份验证 中所述)。您还必须理解以下概念:
SAML TAI 引入了对一种新形式的 Web 单点登录 (SSO) 的支持。我们在 WebSphere Application Server 安全课程中已说过,术语 SSO 在业界被大量过度使用,所以我们必须严格准备我们的 SSO 用例。
SAML 已发展了多年。SAML 2.0 规范定义了多种配置文件和绑定:
SAML 配置文件包括:
SAML 绑定包括:
WebSphere Application Server 自升级包 7.0.0.7 开始为基于 SOAP 的 Web 服务器提供 SAML SOAP Binding 支持。SAML TAI 是在升级包 7.0.0.23、8.0.0.5 中和 8.5.0.0 版的基础产品中引入的。SAML TAI 仅支持组合 Web Browser SSO Profile 与 HTTP Post Binding。
您可以看到,此用例只是许多可能的用例中的一个。事实上,还有两种变体。但首先,您需要了解涉及的一些角色:
IdP 的职责是验证用户(IdP 的验证方式无关紧要)和生成一些有关用户的断言或声明。这些断言由 IdP 进行数字签名。SAML 规范定义了这些断言的格式。SP 接收断言。如果 SP 对来自某个受信任 IdP 的断言感到满意,它会基于该断言的部分信息来登录该用户。
考虑一个基于真实用例的示例。一家虚构的保险公司(UAC,Unified Assurance Company)有多个虚构的企业客户,其中包括:Gamma Business Machine (GBM) 公司、Omicron Lumber 公司和 Purple Maple Syrup 公司。这 4 家公司属于一个 SSO 联邦。在此示例中,Unified Assurance Company 拥有这 3 个联邦成员的员工信息。也就是说,Unified Assurance Company LDAP 中存在外部联邦的员工的用户条目,但没有联邦成员的密码。
在这种情况下,Unified Assurance Company 希望将一个 IBM WebSphere Portal 系统提供给它的外部和内部用户。来自 Gamma Business Machine 的用户向 Gamma Business Machine 内的一个系统执行身份验证。Omicron Lumber 用户向 Omicron Lumber 网络内的一个系统执行身份验证。Purple Maple Syrup 用户向 Google 托管的一个系统执行身份验证。(此示例中,对 WebSphere Portal 系统的使用是附带性的。)
图 1 演示了登录到其 IdP 的用户与 United Assurance 没有关联。例如,Gamma Business Machine 用户可使用一个登录表单来登录。Omicron Lumber 用户使用 SPNEGO 身份验证自动将其凭证提供给 IdP。Purple Syrup 用户使用 SSL 客户端证书向其 IdP 执行身份验证。
另外,请注意不同颜色的公钥/私钥对。每个 IdP 都有自己的私钥。SP 在其 IdP 信任库中保留与这些私钥对应的所有公共证书的副本。
点击查看大图
Web Browser SSO Profile 将描述如何使用 HTTP 重定向,通过用户的浏览器路由 SAML 断言。针对 Web Browser SSO 的 HTTP Post Binding 可以有两种用例:
我们将 IdP 用例称为 IdP 发起的 Web SSO(图 2)。
点击查看大图
在 IdP 发起的 Web SSO 用例中:
这个 HTTP 重定向包含新的 LtpaToken2 cookie。浏览器访问重定向链接并重新发送 LtpaToken2。
- https://benefits-portal.uac.com/wps/myportal
此方法的一个限制是,用户必须向 IdP 托管的 URL 发出一个 GET 请求。考虑上面的示例,每个客户公司的用户都需要知道各自的 URL 才能登录到
Unified Assurance Company
门户。当每个小组登录时,他们都会登录到:
- https://benefits-portal.uac.com/wps/myportal
此方法的另一个限制是,只能将一个 IdP 用于多个服务提供者的验证用户。Gamma Business Machine 用户也可以使用同一个 SSO IdP 登录到与其公司关联的租车系统。而 (从用户角度讲)Unified Assurance Company 门户和租车系统的 URL 托管在同一个 Gamma Business Machine IdP (GBM IdP) 服务器上,这可能让用户产生混淆。
为了消除这些限制,服务提供者通常会开发识别功能,无论用户来自哪个联邦合作伙伴。每个用户单击一个包含以下 URL
的链接:
- https://benefits-portal.uac.com
用户的浏览器首先访问服务提供者,然后服务提供者启动 SSO 流程。WebSphere Application Server SAML TAI 支持第二种用例。SAML TAI 被配置为将用户重定向到 IdP。此用例称为 SP 重定向到 IdP Web SSO 用例(图 3)。
点击查看大图
在 SP 重定向到 IdP Web SSO 用例中:
- https://benefits-portal.uac.com/wps/myportal
- https://benefits-portal.uac.com/wps/myportal
根据之前的介绍,用户向 IdP 执行身份验证。
第 3 到 7 步与 IdP 发起的 Web SSO 用例中的第 2 到 6 步相同。
OASIS 标准 的 4.1.2 小节给出了使用 Web POST Binding 的 SSO 的基本模板。第 1 到 4 步是可选的。模板中从第 5 步开始的步骤就是我们所称的 IdP 发起的 Web SSO 用例。WebSphere Application Server 允许一个流从服务提供者 (WebSphere Application Server) 处开始,而不实现第 1 到 4 步中定义的 SP 发起的 SSO 标准流。
为了支持这些这些 SP 发起 SSO 标准步骤,TAI 需要生成一个 SAML 请求,然后将用户重定向到 IdP。IdP 然后发回一个 SAMLResponse,该响应被视为恳求 (solicited) 响应。在升级包 8.0.0.12/8.5.5.6 之前,WebSphere Application Server SAML TAI 不支持 SP 发起的标准流。SAML TAI 不会恳求发回响应。它将用户重定向到 IdP 的登录页面。用户登录后,IdP 生成一个 SAMLResponse。因为这个 SAMLResponse 不是基于 SAMLRequest 而回复的,所以它被视为非恳求 (unsolicited) 响应。这个非恳求用例被称为 SP 重定向到 IdP Web SSO 用例。
升级包 8.0.0.12 和 8.5.5.7 现在通过使用 AuthnRequestProvider SPI 来支持 SP 发起的流。要实现此支持,必须编写代码来实现此 SPI。实现此 SPI 必须在一个 HashMap 中填入 4 个字符串。请记住以下技巧:
已定义此方法或要求此方法存在,但从未调用它。
- public String getIdentityProviderOrErrorURL(HttpServletRequest arg0,
- String arg1, String arg2, ArrayList<String> arg3)
- throws NotImplementedException;
当实现这样一个解决方案时(细节不属于本文的讨论范围),使用
类和 Base64 编码来对 AuthnRequest 执行签名,方法是:
- javax.xml.crypto.dsig.*
- // Base64 encode the signed message
- byte[] bytes = signedAuthnMessage.getBytes();
- String encodedAuthnMessage = new String(com.ibm.ws.security.util.Base64Coder.base64Encode(bytes));
对于要调用的自定义 SPI 实现,SAML TAI 必须:
中引用完整的类名。
- sso_<n>.sp.login.error.page
目录中。
- <WAS>/lib/ext
IBM 知识中心中的 WebSphere Application Server 的 SAML 单点登录方案、功能和局限性 主题中已记录此行为。
要在 WebSphere Application Server V8.5(以及 7.0 和 8.0 版)中使用 SAML Web SSO 功能,需要在一个 信任关联拦截器 中实现这些功能。SAML TAI 的完整类名为
。以下重要因素会影响 SAML Web SSO TAI:
- com.ibm.ws.security.web.saml.ACSTrustAssociationInterceptor
必须启用 Subject Attribute Propagation(在 User Registry 中未找到),这部分自定义信息才能从在单元中的服务器之间传播。因为这些 SAML 断言无法从 WebSphere Application Server 注册表获得,所以需要为该 Subject 定义一个合适的自定义缓存密钥。(Subject 传播、自定义缓存密钥和 TAI 的细微影响不属于本文的介绍范畴。)
重要事项:在从 IdP 流到 WebSphere Application Server SAML TAI 的 HTTP POST 消息中,只有一条消息的 POST 正文中包含 SAML Response 对象。WebSphere Application Server SAML TAI 基于该 SAML Response 对象来登录该用户,并返回一个 LtpaToken2 cookie。该配置文件和绑定适合传到应用程序的经验证登录页面上。来自浏览器的后续交互基于 HTTP 客户端返回的 LtpaToken2 cookie 而保留用户的登录上下文,该客户端通常是用户的浏览器。
尽管该 POST 中的 SAML 断言允许 “可移植” 的令牌,但这个可移植的令牌会立即被一个特定于 WebSphere 的 LtpaToken2 cookie 取代。此模型非常适合使用浏览器的用户。它不太适合其他没有 “登录到登录页面并使用 cookie 保留登录状态” 的模型的 HTTP 应用程序客户端。例如,一个期望使用全部 HTTP 方法(GET、PUT、POST 和 DELETE)的 RESTful Web 服务应用程序的设计必须:
由于 Subject 和 LtpaToken2 中的自定义缓存密钥,必须启用 Subject 属性,以便允许在 WebSphere SSO 单元中的 JVM 之间传播完整的用户身份。此方法可包含对用户要登录到的原始服务器的 JMX 回调。
图 4 中细化了 逻辑流 来支持 SAML TAI。这适合以下情形:用户拥有 LtpaToken2 cookie,而且浏览器通过一次新的 SAML 断言向断言使用者服务发出 POST。在这种情况下,必须忽略原始 LtpaToken2 cookie,而且在创建新 Subject 时必须使用来自 SAML 断言的用户身份。此行为变化通过常规自定义属性
进行控制,该属性具有 SAML TAI 类的值 (
- com.ibm.websphere.security.InvokeTAIbeforeSSO
):
- com.ibm.ws.security.web.saml.ACSTrustAssociationInterceptor
图 4 给出了新逻辑流的第一部分。
点击查看大图
如果正确定义了
属性,则会在检查 SSO 令牌 (LtpaToken2 cookie) 之前调用 SAML TAI。稍后将解释图 4 中的 checkSubject? 步骤。
- InvokeTAIbeforeSSO
要支持 SP 重定向到 IdP Web SSO 用例,可能需要多次调用 SAML TAI。也就是说,如果 LtpaToken2 和 SAML 断言都不存在,那么在为第二个特殊安全属性
赋予 SAML TAI 类的值时,可能会调用 SAML TAI 逻辑。此属性在 Global Security 页面上也被定义为自定义属性,或在启用 SAML TAI 的安全域中,被定义为该域的自定义属性。
- com.ibm.websphere.security.DeferTAItoSSO
查看 SP 重定向到 IdP Web SSO 用例时,可能会看到在初始登录时多次调用 SAML TAI 的场景。图 5 演示了 SP 重定向到 IdP Web SSO 用例 的 SAML TAI 支持流程。
点击查看大图
在将跟踪轨迹规范设置为
后,只需检查跟踪轨迹,即可在执行一个 SP 重定向到 IdP Web SSO 用例期间确认这两个流程图中的逻辑。
- com.ibm.ws.security.web.saml.*=all
为了帮助完成此试验,此示例提供了两个 TAI。第一个 TAI 是一个 FakeTAI,它不会拦截,但会在日志中记录一条消息,如下面的代码清单所示。
- [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>
第二个 TAI 是 SAML TAI,会在 SSO 处理之前调用,如下面的代码清单所示。
- [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/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,如下面的代码清单所示。
- [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
被发送到浏览器。因为使用了内置的断言使用者服务应用程序,所以断言使用者服务将浏览器重定向到原始引用者 URL cookie
值,也就是:
- https://oc5067386220.ibm.com:9444/HitCountWeb/HitCountServlet
原始引用者 URL cookie 使用 SAML TAI 设置。
图 2 中的消息 6 出现并到达跟踪轨迹中的下一步。同样地,在检查 LtpaToken2 cookie 之前调用 SAML TAI,如下面的代码清单所示。
- [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 应用程序被调用并报告了调用方的身份。该身份是从 Subject 获取的,在消息 3 中的 SAML Response 中生成,如下面的代码清单所示。
- [3/20/13 16:22:57:632 EDT] 00000025 SystemOut O J2EE APIs: HitCount received
- request from Alice
该属性被实现为一个 TAI,使得某些功能能够向后移植到 WebSphere Application Server 的更低版本中。但是,它会导致必须正确定义多个 TAI 属性,TAI 才能继续发挥作用。
SAML TAI 属性被划分为 3 个类别,如 SAML Web SSO TAI 自定义属性 中所述。除了该 IBM 知识中心主题中的这些细节,还要记住以下几点:
(其中
- sso_<id>
是一个整数)。大多数全局属性都可被特定于 IdP 的等效属性覆盖。
- <id>
下。
- sso_<id>
。然后使用它对与每个 SSO IdP 合作伙伴关联的属性进行分组。对于特定的服务提供者,配置的 IdP 属性以
- idp_<id>
为前缀。
- sso_<id>.idp_<id^>
我们不会解释所有这些属性,而是将它们分组到一起,以展示如何应用它们来解决某些问题。(这里不会解释所有属性。)
向 IdP 执行身份验证后,IdP 将浏览器重定向到合适的断言使用者服务 URL。SAML TAI 确定向请求应用何种(如果有)服务提供者配置。
为了确定应用何种配置,SAML TAI 使用所有
属性中定义的模式来与该 URL 匹配。如果找到匹配项,则应用所有
- sso_<n>. sp.acsUrl
(服务提供者)属性,以及任何全局属性。
- sso_<n>
在处理对断言使用者服务应用程序的 SAMLResponse 时,SAML TAI 将 SAMLResponse 中的 AudienceRestriction 元素与
属性相匹配。如果未设置,这个 EntityID 属性将从
- sso_<n>.sp.EntityID
属性获取它的值。
- sso_<n>.sp.acsURL
如果用户通过 POST 向断言使用者服务 URL 发送一个有效的 SAML Response(可能由另一个 IdP 发放),则重定向会返回
属性所指定的 URL。
- sso_<n>.acsErrorPage
接下来,我们将考虑 SP 重定向到 IdP Web SSO 用例的其他属性。
考虑图 3 中所示的案例。一个 Gamma Business Machine 用户打开浏览器访问以下 URL:
- https://benefits-portal.uac.com/wps/myportal
如上所述,TAI 不会立即拦截,因为该 URL 不是断言使用者服务 URL。因为此请求是第一个,所以没有 LtpaToken2 cookie。前面已经提到,基于传入请求中的一些数据,SAML TAI 返回一个向正确 IdP 的 HTTP 302 重定向。SAML TAI 是如何知道将此请求重定向到(在本例中) GBM IdP,而不是其他任何 IdP?
SAML TAI 过滤器属性
控制着 SAML TAI 如何确定一个特定 URL 是否必须发起向该 IdP 的服务提供者重定向。该过滤器的功能与 SPNEGO TAI 的过滤器相同。如果缺少过滤器设置,将拦截对 Java EE 受保护 URL 的所有请求。
- sso_<n>.sp.filter
您必须应用 APAR PM84513 中的修复程序。这个 APAR 使用多种 SP 配置解决了一个问题,为每种配置提供了一个唯一的 “过滤器” 定义。对 SAML TAI 的第一条请求找到匹配的 “过滤器”,以确定对该请求应该使用哪种 SP 配置。如果没有这个 APAR,对 SAML TAI 的所有后续调用将继续使用同一种 SP 配置。后续请求不会检查匹配的过滤器条件。
如果基于过滤器来拦截请求,将返回
属性指定的页面。如果仅存在一个 IdP,那么该页面可能是可供这个 IdP 使用的 URL。如果存在多个 IdP,SP 配置的每个 IdP 将有自己的
- sso_<n>.sp.login.error.page
值。要发起 SAML SSO,每个值都会指定 SAML TAI 将要重定向到的 URL。
- sso_<n>.idp_<m>.SingleSignOnUrl
但问题仍然存在:如何确定选择哪个
?如果存在多个 IdP,
- idp_<m>
属性可指向一个包含多个 IdP 链接的 HTML 页面。一个更完善的解决方案是,该属性引用一个类,该类实现下面的代码清单中所示的接口。
- login.error.page
- 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 文件放在
目录中。您可以在实现中执行您能想到的任何逻辑。在 SampleIDPMapping.java 示例源代码中(参见下面的清单),您搜索
- <WAS>/lib/ext
参数,或者,如果用户之前访问过该网站,可以搜索一个名为 SAMLIDP 的持久化 cookie。
- idp=<URL>
- 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 和
参数均未提供,那么默认情况下将会使用 GBM IdP。另一个实际的示例是,基于传入 HttpServletRequest 的客户端 IP 地址(这有时可能是有意义的数据)来确定使用哪个 IdP。我们没有提供这个示例的代码。
- idp=
现在,SAML TAI 已在 POST 到断言使用者服务时处理了 SAML Response,而且 WebSphere Application Server 安全运行时已让用户登录并生成一个 JAAS Subject。断言使用者服务应用程序将会完成以下操作之一:
为了支持这些选项中的第一个,这个普通的断言使用者服务应用程序使用了
- sso_<n>.sp.targetU
属性。如果 IdP 发送 RelayState,则默认情况下会使用第三个选项。要覆盖发送的 RelayState,可以使用
- rl
属性。指定重定向到何处的最常见的 SP 发起方式是,通过名为 WasSamlSpReqURL cookie 的原始引用者 URL cookie。
- sso_<n>.sp.useRelayStateForTarget
您可能会问,为什么 SAML TAI 相信 SAML 断言。如果它不相信,攻击者就有可能破坏格式正确的 SAML Response,向断言使用者服务发送 POST 请求,然后以攻击者选择的任何身份登录。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
- 包含您的 IdP 的签名者证书的 WebSphere Application Server 信任库对象名称。此名称不是文件名,而是管理控制台中显示的对象名。默认设置是使用服务器的默认 SSL 配置,该配置通常引用CellDefaultTrustStore。此默认设置不是一个好的选择,因为向 CellDefaultTrustStore 添加签名者会破坏该单元的信任空间。相反,定义一个包含必要证书的不同的IdpTrustStore对象。
- sso_<n>.sp.trustStore
- 作为使用 WebSphere 信任库对象的替代方案,您可以提供一个包含签名证书的中介证书的文件的路径。
- sso_<n>.sp.X509PATH
- 包含一个证书撤销列表 (CRL) 的证书库的名称。
- sso_<n>.sp.CRLPATH
- 如果您的信任库包含多个证书,而且您想限制使用信任库中的哪个证书来验证签名, 使用此属性进行指定。
- sso_<n>.sp.trustedAlias
在 SAML TAI 确定拦截请求后,它需要确保 IdP 的身份包含在一组受信任的 IdP 中。可通过以下选项之一来确定 IdP:
- sso_<n>.idp_<m>.allowedIssuerDN
- sso_<n>.idp_<m>.allowedIssuerName
通过使用这些属性之一,可以避免一个常见的陷阱,那就是接受的 SAML 断言是使用信任库中一个签名者颁发的任何证书签名的。这些属性可确保断言是由该 IdP 签名的。它们也可以避免基于 PKI 的解决方案所固有的证书管理问题。也就是说,如果您将 IdP 证书保存在信任库中,在该证书在过期前被续订时,您必须更新存储它的所有信任库。
正确设置这些属性并将签名证书放入信任库中可能很困难。名为
的 wsadmin 管理任务可帮助您完成此工作。
- importSAMLIdpMetadata
用户登录后,登录会话由一个 LtpaToken2 cookie 维护,必须仔细检查这个 cookie。考虑这样一个示例:/app1 由 SAML TAI 保护,而 /app0 不是。用户登录时的期望行为是什么,首先在不使用 SAML 的情况下访问 /app0,然后访问 /app1?
根据 SAML TAI
属性,可能采用 3 种操作模式:
- sso_<n>.sp.enforceTaiCookie
,则所有 Lightweight Third Party Authentication (LTPA) 令牌都是 “等效的”。也就是说,未使用基于 SAML 的登录来登录到 WebSphere Application Server 单元中的另一个应用程序的用户,可以为 SAML TAI 受保护应用程序重用该 LtpaToken2 cookie。在这种情况下,不会在该 Subject 的内容中检查 SAMLResponse,而针对 /app1 验证用户。
- sso_<n>.sp.enforceTaiCookie=false
(如果已定义)覆盖对任何 SAMLResponse 的这种自由接受行为。可为 cookieGroup 属性分配一个添加到 WebSphere Application Server Subject 的字符串。为了简便起见,我们将该字符串命名为
- sso_<n>.sp.cookieGroup 属性
。
- Saml20TaiSsoPartners
考虑以下这样一个示例:
和
- sso_1.sp.cookieGroup=app1
。用户登录到 /app1。在与 /app1 的所有交互中,运行时确保 Subject 包含一个 SAMLResponse,Saml20TaiSsoPartners 包含 “app1”。接下来,用户尝试访问 /app2 并发送 LtpaToken2 cookie。WebSphere Application Server 安全运行时确保关联的 Subject 包含一个 SAMLResponse,并通过检查确认 Saml20TaiSsoPartners 包含 “app2”。因为它不包含 “app2”,所以用户被重定向到为
- sso_2.sp.cookieGroup=app2
配置的 IdP。
- sso_2
在图 4 中,对 checkSubject? 的调用展示了实现此方法的逻辑。
通常应通过 HTTPS 连接向断言使用者服务应用程序发出 HTTP POST。事实上,许多 IdP 都需要通过 SSL 进行连接。除了 SSL 连接提供了加密功能,加密 SAML Response 对象的有效负载可能还有一个原因。请记住,IdP 通过用户的浏览器重定向该请求。通过使用浏览器插件,用户可以查看通过浏览器传入的 SAML Response。(用户无法更改内容,因为这会导致数字签名检查失败,但用户仍能看到内容。)如果您的用例不需要这种辅助加密,则不需要加密 SAML Response。
为了实现加密,SP (SAML TAI) 使用了它自己的公/私钥对。使用公共证书为 IdP 提供公钥的副本,IdP 使用该公共证书加密内容。只有私钥持有者 (TAI) 可以解密该内容。以下属性为 SAML Response 加密提供支持:
- 包含您的 SP 的个人证书的 WebSphere Application Server 密钥库对象的名称。它不是文件名,而是管理控制台中显示的管理对象的名称。
- sso_<n>.sp.keyStore
- 密钥库中的密钥的别名。
- sso_<n>.sp.keyAlias
- 访问该密钥所需的密码。
- sso_<n>.sp.keyPassword
- 您指定使用的密钥的完整 DN。
- sso_<n>.sp.keyName
IdP 需要收到公共证书(和任何签名者信息)。同样地,您可以使用 wsadmin 管理任务
创建一个可被 IdP 应用程序导入的 XML 文件。根据您的 IdP 系统,您可能需要编辑结果 XML,以便仅引用加密证书信息。
- exportSAMLSpMetadata
IdP 向 SAML TAI 断言一个用户身份。根据您的用例,此用户可能存在于 WebSphere Application Server 用户注册表中。该用户是本地用户或临时用户。一些 WebSphere 产品(比如 IBM Business Process Manager (BPM))需要所有登录的用户都存在于用户注册表中。因此,它们必须是本地用户。
要断言为本地用户,可指定 SAML TAI 属性
。对于本地用户,可将 SAML Response 中的 NameID 字段设置为 JAAS Subject 中的用户 ID。WebSphere Application Server 通过查询用户注册表来完成该 Subject。
- sso_<n>.sp.idMap = localRealm
临时用户尽管被断言为存在,但不受底层用户存储(比如 LDAP)中的任何条目支持。对于临时用户,principalName 从
属性中的指定属性获取。
- sso_<n>.sp.principalName
要断言为临时用户,需要设置
属性。设置此属性(默认值)后,您可以选择多个 SAML TAI 属性来控制使用哪个用户身份登录。前两个属性识别 SAML Response 中用于填充 principalName 和 uniqueID 的元素。
- sso_<n>.sp.idMap = idAssertion
- sso_<n>.sp.principalName
- sso_<n>.sp.uniqueId
分配给用户 ID 的范围由以下属性决定:
- sso_<n>.sp.realmName
- sso_<n>.sp.realmNameRange
- sso_<n>.sp.defaultRealm
- sso_<n>.sp.useRealm
如果使用了 idAssertion,而且未设置任何这些与范围相关的属性,则 SAML Response 中定义的 IssuerName 就是使用的范围名称。
此外,您可以选择两种混合方法之一来建立用户身份。第一种混合方法使用 idMap 值
。在这种模式下,将从 SAML Response 中提取用户身份,并搜索用户注册表。如果在用户注册表中找到了该用户,则继续以 localRealm 用户身份登录。如果未找到该用户,则以 idAssertion 用户身份继续登录。
- localRealmThenAssertion
第二种混合方法要求 idMap 值为
。它使用了 SAML Response 中断言的组信息,扩充从一个 localRealm 用户的用户注册表返回的组成员信息。对第二种混合方法使用
- localRealm
属性。在此方法中,SAML Response 中断言的组必须存在于用户注册表中,但该用户未列为该组的成员。此选项动态使用 SAML 断言将登录的用户显示为该注册表组的成员。
- sso_<n>.sp.groupMap=addGroupsFromLocalRealm
在两种情况下,在实现 WebSphere 授权时,都会忽略用户注册表中未找到的断言组。但是,SAML Assertion 保存在用户的 Subject 中,而且可用于下游断言,这些断言可能在下游有用。
考虑图 6 中的示例。无需断言 Unified Assurance Company LDAP (localRealm) 中包含的用户,Purple 用户是临时的。它们的组成员关系也使用 SAML Response 断言。具体来讲,我们关注的是它们在 UACGroup 中的成员关系。还断言了其他组,但它们对 Unified Assurance Company 应用程序无关紧要。用户访问的 Unified Assurance Company Web 应用程序有一个安全角色,该角色被显式绑定到来自某个外部受信任范围
的 Group UACGroup。您必须配置您的 IdP,以便在 SAML Response 中生成合适的组成员关系声明。
- idp.purple.com/adfs/services/trust
点击查看大图
最后,在向 WebSphere Application Server 断言身份之前,对 SAML Response 中断言的用户 ID、principalName 和 NameID 执行转换。也可以考虑使用 SAML Response XML 文档中的一个不同元素的身份(如果可用)。
属性为 SAML TAI 提供了第二个插入点(一个接口),您可以在这里实现自定义的用户映射类来返回所断言的用户身份。下面的代码清单给出了 userMapImpl 接口。
- sso_<n>.sp.userMapImpl
- 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 中的 DN 元素建立用户身份,如下面的清单所示。
- /** 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,请自问以下总体架构类型问题:
对于您的每个 IdP,您需要知道:
对 WebSphere Application Server 执行以下总体管理步骤:
(举例而言):
- SPKeyStore
(举例而言)的新信任库。安装 IdP 签名证书和颁发者链。
- IdPTrustStore
自定义属性,以便启用SP 重定向到 IdP Web SSO。
- com.ibm.websphere.security.DeferTAItoSSO
自定义属性,以便引用一个基于 LtpaToken 的 SAML 令牌。
- com.ibm.websphere.security.InvokeTAIbeforeSSO
- <was>/installableApps/WebSphereSamlSP.ear
以下与 SAML TAI 相关的 wsadmin 管理任务很有用:
- AdminTask.showSAMLTAISSO()
- AdminTask.showSAMLIdpPartner()
- AdminTask.importSAMLIdpMetadata()
- AdminTask.exportSAMLSpMetadata()
有用的跟踪轨迹规范:
- com.ibm.ws.security.web.saml.*
- com.ibm.ws.security.*
(WebSphere 支持人员通常会请求跟踪轨迹。)
- com.ibm.ws.security.web.*=all:com.ibm.ws.wssecurity.saml.*=all
使用 SAML TAI 时,请记住以下指导原则:
本文提供了一些指南,以帮助运行 IBM WebSphere Application Server 的系统管理员理解 SAML Web TAI。您了解了它在 WebSphere Application Server 内的现有 Web 安全运行时中的工作原理,以及它在安全性方面带来的一些细微变化。您还了解了大量自定义 TAI 属性如何相互交互,以及何时使用这些自定义 TAI 属性(和何时不需要它们)。您还查看了两个类实现示例,它们展示了如何自定义登录流程。
感谢同事 Jens Engelke、Barbara Jensen、Michael Whale、Simon Kapadia、Bill O'Donnell 和 Chunlong Liang 提供的宝贵建议和帮助。
来源: http://www.ibm.com/developerworks/cn/middleware/library/mw-1612-lansche-trs/index.html