第 3 章 使用 SAML 保护应用程序和服务


本节论述了如何使用 Red Hat Single Sign-On 客户端适配器或通用 SAML 供应商库来保护应用程序和服务。

3.1. Java 适配器

Red Hat Single Sign-On 带有 Java 应用程序的不同适配器范围。选择正确的适配器取决于目标平台。

3.1.1. 常规适配器配置

Red Hat Single Sign-On 支持的每个 SAML 客户端适配器均可通过简单的 XML 文本文件配置。这种情况可能如下所示:

<keycloak-saml-adapter xmlns="urn:keycloak:saml:adapter"
                       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                       xsi:schemaLocation="urn:keycloak:saml:adapter https://www.keycloak.org/schema/keycloak_saml_adapter_1_10.xsd">
    <SP entityID="http://localhost:8081/sales-post-sig/"
        sslPolicy="EXTERNAL"
        nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
        logoutPage="/logout.jsp"
        forceAuthentication="false"
        isPassive="false"
        turnOffChangeSessionIdOnLogin="false"
        autodetectBearerOnly="false">
        <Keys>
            <Key signing="true" >
                <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
                    <PrivateKey alias="http://localhost:8080/sales-post-sig/" password="test123"/>
                    <Certificate alias="http://localhost:8080/sales-post-sig/"/>
                </KeyStore>
            </Key>
        </Keys>
        <PrincipalNameMapping policy="FROM_NAME_ID"/>
        <RoleIdentifiers>
            <Attribute name="Role"/>
        </RoleIdentifiers>
        <RoleMappingsProvider id="properties-based-role-mapper">
            <Property name="properties.resource.location" value="/WEB-INF/role-mappings.properties"/>
        </RoleMappingsProvider>
        <IDP entityID="idp"
             signaturesRequired="true">
        <SingleSignOnService requestBinding="POST"
                             bindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
                    />

            <SingleLogoutService
                    requestBinding="POST"
                    responseBinding="POST"
                    postBindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
                    redirectBindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
                    />
            <Keys>
                <Key signing="true">
                    <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
                        <Certificate alias="demo"/>
                    </KeyStore>
                </Key>
            </Keys>
        </IDP>
     </SP>
</keycloak-saml-adapter>
Copy to Clipboard Toggle word wrap

其中一些配置切换可能特定于适配器,一些配置交换机在所有适配器中都很常见。对于 Java 适配器,您可以使用 ${…​} parture 作为系统属性替换。例如: ${jboss.server.config.dir}

3.1.1.1. SP 元素

以下是 SP 元素属性的解释:

<SP entityID="sp"
    sslPolicy="ssl"
    nameIDPolicyFormat="format"
    forceAuthentication="true"
    isPassive="false"
    keepDOMAssertion="true"
    autodetectBearerOnly="false">
...
</SP>
Copy to Clipboard Toggle word wrap
entityID
这是此客户端的标识符。IdP 需要这个值来确定客户端与之通信的人员。此设置是 REQUIRED
sslPolicy
这是适配器要强制执行的 SSL 策略。有效值为: 所有EXTERNALNONE。对于 ALL,所有请求都必须通过 HTTPS。对于 EXTERNAL,只有非专用 IP 地址必须通过 HTTPS 进行线路。对于 NONE,不需要通过 HTTPS 访问请求。此设置是 OPTIONAL。默认值为 EXTERNAL
nameIDPolicyFormat
SAML 客户端可以请求特定的 NameID 主体格式。如果您希望特定格式,请填写此值。它必须是标准的 SAML 格式标识符:urn :oasis:names:tc:SAML:2.0:nameid-format:transient.此设置是 OPTIONAL。默认情况下,请求没有特殊格式。
forceAuthentication
SAML 客户端可以请求重新验证用户,即使他们已在 IdP 登录时。把它设置为 true 来启用。此设置是 OPTIONAL。默认值为 false
isPassive
SAML 客户端可能会要求用户进行身份验证,即使他们没有在 IdP 登录时也如此。如果需要这样做,则将其设置为 true。不要与 forceAuthentication 一起使用,因为它们相反。此设置是 OPTIONAL。默认值为 false
turnOffChangeSessionIdOnLogin
在某些平台上成功登录时,会话 ID 被默认更改,以插入安全攻击向量。将此更改为 true 以禁用此功能。建议您不要关闭它。默认值为 false
autodetectBearerOnly
如果您的应用程序同时充当 Web 应用程序和 Web 服务(如 SOAP 或 REST),则此项应设为 true。它允许您将 Web 应用的未经身份验证的用户重定向到 Red Hat Single Sign-On 登录页面,但向未经身份验证的 SOAP 或 REST 客户端发送 HTTP 401 状态代码,因为它们不知道到登录页面的重定向。红帽单点登录根据典型的标头(如 X-Requested-WithSOAPActionAccept )自动探测 SOAP 或 REST 客户端。默认值为 false
logoutPage
这会将页面设置为在注销后显示。如果页面是一个完整的 URL,如 http://web.example.com/logout.html,则在使用 HTTP 302 状态代码注销至该页面后,用户会被重定向到该页面。如果指定了没有方案部分的链接,如 /logout.jsp,则该页面会在注销后显示,无论它是否根据 web.xml 中的 security-constraint 声明显示在受保护区域中,并且页面会相对于部署上下文 root 解析。
keepDOMAssertion
此属性应设为 true,以便适配器将声明的 DOM 表示存储在与请求关联的 SamlPrincipal 的 SamlPrincipal 中。可以使用主体中的 getAsertionDocument 来检索 断言文档。这在重新显示签名的断言时特别有用。返回的文档是生成解析 Red Hat Single Sign-On 服务器收到的 SAML 响应的文件。此设置是 OPTIONAL,其默认值为 false (文件没有在主体内保存)。

3.1.1.2. 服务提供商密钥和关键元素

如果 IdP 需要客户端应用程序(或 SP)为其所有请求签名,或者,如果 IdP 会加密断言,则必须定义用于执行此操作的密钥。对于客户端签名文档,您必须定义用于签署文档的私钥和公钥或证书。为了进行加密,您只需要定义用于解密的私钥。

可以通过两种方式描述您的密钥。它们可存储在 Java KeyStore 中,或者您可以使用 PEM 格式直接将密钥复制到 keycloak-saml.xml 中。

        <Keys>
            <Key signing="true" >
               ...
            </Key>
        </Keys>
Copy to Clipboard Toggle word wrap

Key 元素有两个可选属性 signingencryption。当设置为 true 时,它们告诉适配器将用于什么键。如果这两个属性都设为 true,则密钥将同时用于签名文档和解密加密的断言。您必须至少将其中一个属性设置为 true。

3.1.1.2.1. keystore 元素

Key 元素中,您可以从 Java 密钥存储加载您的密钥和证书。这在 KeyStore 元素中声明。

        <Keys>
            <Key signing="true" >
                <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
                    <PrivateKey alias="myPrivate" password="test123"/>
                    <Certificate alias="myCertAlias"/>
                </KeyStore>
            </Key>
        </Keys>
Copy to Clipboard Toggle word wrap

以下是使用 KeyStore 元素定义的 XML 配置属性。

file
密钥存储的文件路径。此选项是 OPTIONAL。必须设置 file 或 resource 属性。
resource
WAR 资源路径到 KeyStore。这是对 ServletContext.getResourceAsStream()方法调用的路径。此选项是 OPTIONAL。必须设置 file 或 resource 属性。
password
KeyStore 的密码。此选项为 REQUIRED

如果要定义 SP 用于签名的密钥,还必须在 Java KeyStore 中指定您的私钥和证书的引用。上例中的 PrivateKeyCertificate 元素定义了一个 alias,指向密钥存储内密钥或证书。密钥存储需要额外密码才能访问私钥。在 PrivateKey 元素中,您必须在 password 属性中定义此密码。

3.1.1.2.2. 密钥 PEMS

Key 元素中,您可以使用子元素( PrivateKeyPemPublicKeyPemCertificatePem )来直接声明您的密钥和证书。这些元素中包含的值必须符合 PEM 密钥格式。如果您使用 openssl 或类似的命令行工具生成密钥,通常会使用这个选项。

<Keys>
   <Key signing="true">
      <PrivateKeyPem>
         2341251234AB31234==231BB998311222423522334
      </PrivateKeyPem>
      <CertificatePem>
         211111341251234AB31234==231BB998311222423522334
      </CertificatePem>
   </Key>
</Keys>
Copy to Clipboard Toggle word wrap

3.1.1.3. SP PrincipalNameMapping 元素

这个元素是可选的。创建您从 HttpServletRequest.getUserPrincipal() 等方法获取的 Java Principal 对象时,您可以定义 Principal.getName() 方法返回的名称。

<SP ...>
  <PrincipalNameMapping policy="FROM_NAME_ID"/>
</SP>

<SP ...>
  <PrincipalNameMapping policy="FROM_ATTRIBUTE" attribute="email" />
</SP>
Copy to Clipboard Toggle word wrap

policy 属性定义用于填充该值的策略。此属性的可能值有:

FROM_NAME_ID
此策略仅使用任何 SAML 主题值。这是默认设置
FROM_ATTRIBUTE
这将从服务器收到的 SAML 断言中声明的属性中拉取值。您将需要指定要在 attribute XML 属性中使用的 SAML 断言属性的名称。

3.1.1.4. RoleIdentifiers 元素

RoleIdentifiers 元素定义了从用户接收的断言中的 SAML 属性,用作用户的 Jakarta EE 安全上下文中的角色标识符。

<RoleIdentifiers>
     <Attribute name="Role"/>
     <Attribute name="member"/>
     <Attribute name="memberOf"/>
</RoleIdentifiers>
Copy to Clipboard Toggle word wrap

默认情况下,Role 属性值转换为 Jakarta EE 角色。有些 IdP 使用 membermemberOf 属性断言角色。您可以定义一个或多个 Attribute 元素,以指定哪些 SAML 属性必须转换为角色。

3.1.1.5. RoleMappingsProvider 元素

RoleMappingsProvider 是一个可选元素,它允许规范 org.keycloak.adapters.saml.RoleMappingsProvider SPI 实现,供 SAML 适配器使用。

当 Red Hat Single Sign-On 用作 IDP 时,可以使用角色映射程序中的构建来映射任何角色,然后才能将它们添加到 SAML 断言。但是,SAML 适配器可用于发送 SAML 请求到第三方 IDP,在这种情况下,可能需要将断言中提取的角色映射到 SP 需要的不同角色。RoleMappingsProvider SPI 允许配置可用来执行必要映射的可插拔角色映射程序。

供应商的配置如下所示:

...
<RoleIdentifiers>
    ...
</RoleIdentifiers>
<RoleMappingsProvider id="properties-based-role-mapper">
    <Property name="properties.resource.location" value="/WEB-INF/role-mappings.properties"/>
</RoleMappingsProvider>
<IDP>
    ...
</IDP>
Copy to Clipboard Toggle word wrap

id 属性标识要使用哪个已安装的提供程序。Property 子元素可以多次使用来为提供程序指定配置属性。

3.1.1.5.1. 基于属性的角色映射提供程序

Red Hat Single Sign-On 包括一个 RoleMappingsProvider 实现,它使用 properties 文件来执行角色映射。此提供程序由 id 属性-role-mapper 识别,并由 org.keycloak.adapters.saml.PropertiesBasedRoleMapper 类实施。

此提供程序依赖于两个配置属性,它们可用于指定要使用的 属性 文件的位置。首先,它会检查 properties.file.location 是否被设置,使用配置的值来查找文件系统中的 properties 文件。如果配置文件不位于,则提供程序会抛出 RuntimeException。以下片段演示了使用 properties.file.configuration 选项从文件系统中的 /opt/mappers/ 目录中加载 roles.properties 文件的供应商示例:

    <RoleMappingsProvider id="properties-based-role-mapper">
        <Property name="properties.file.location" value="/opt/mappers/roles.properties"/>
    </RoleMappingsProvider>
Copy to Clipboard Toggle word wrap

如果没有设置 properties.file.location,则供应商会检查 properties.resource.location 属性,使用配置的值来从 WAR 资源中加载 properties 文件。如果该配置属性也不存在,则供应商将默认尝试从 /WEB-INF/role-mappings.properties 加载该文件。无法从资源加载文件将导致提供程序引发 RuntimeException。以下片段演示了使用 properties.resource.location 从应用程序的 /WEB-INF/conf/ 目录中加载 roles.properties 文件的供应商示例:

    <RoleMappingsProvider id="properties-based-role-mapper">
        <Property name="properties.resource.location" value="/WEB-INF/conf/roles.properties"/>
    </RoleMappingsProvider>
Copy to Clipboard Toggle word wrap

属性 文件可以包含角色和主体作为键,以及以逗号分隔的零个角色列表作为值。调用后,如果存在映射,实施将迭代从断言和检查中提取的角色集合。如果角色映射到空角色,它将被丢弃。如果它映射到一个或多个不同的角色,则会在结果集中设置这些角色。如果没有为角色找到映射,则会包含在结果集中。

处理角色后,实施将检查从断言中提取的主体是否包含一个条目 属性文件。如果存在主体的映射,则所有作为值列出的角色都会添加到结果集中。这允许将额外角色分配给主体。

例如,假设供应商已经使用以下属性文件进行配置:

roleA=roleX,roleY
roleB=

kc_user=roleZ
Copy to Clipboard Toggle word wrap

如果主体 kc_user 从角色 roleAroleBroleC 中提取,则分配给主体的最终角色集将是 roleCroleXroleYroleZ,因为 roleA 被映射到 roleXroleYroleB 已映射到空角色 - 因此被丢弃,roleC 被用作,最后会添加额外的角色到 kc_user 主体(roleZ)。

注: 要在角色名称中使用空格进行映射,使用 unicode 替换空间。例如,传入"角色 A"将如下所示:

role\u0020A=roleX,roleY
Copy to Clipboard Toggle word wrap
3.1.1.5.2. 添加您自己的角色映射供应商

要添加自定义角色映射提供程序,只需实施 org.keycloak.adapters.saml.RoleMappingsProvider SPI。如需了解更多详细信息,请参阅 服务器开发者指南中的 SAML 角色映射 SPI 部分。

3.1.1.6. IDP Element

IDP 元素中的所有内容描述了 SP 通信身份提供程序(身份验证服务器)的设置。

<IDP entityID="idp"
     signaturesRequired="true"
     signatureAlgorithm="RSA_SHA1"
     signatureCanonicalizationMethod="http://www.w3.org/2001/10/xml-exc-c14n#">
...
</IDP>
Copy to Clipboard Toggle word wrap

以下是您可以在 IDP 元素声明中指定的属性配置选项。

entityID
这是 IDP 的签发者 ID。此设置是 REQUIRED
signaturesRequired
如果设置为 true,则客户端适配器都将为其发送到 IDP 的每个文档进行签名。另外,客户端会期望 IDP 将会对发送给它的所有文档进行签名。此切换为所有请求和响应类型设置默认值,但稍后您会看到您对此有非常精细的控制。此设置是 选项, 并且默认为 false
signatureAlgorithm
这是 IDP 期望签名的文档使用的签名算法。允许的值有: RSA_SHA1RSA_SHA256RSA_SHA512DSA_SHA1。此设置是 OPTIONAL,默认为 RSA_SHA256
signatureCanonicalizationMethod
这是 IDP 预期签名的文档要使用的签名规范方法。此设置是 OPTIONAL。默认值为 http://www.w3.org/2001/10/xml-exc-c14n#,它应该适用于大多数 IDP。
metadataUrl
用于检索 IDP 元数据的 URL,目前它只用来定期获取签名和加密密钥,允许循环在 IDP 上不手动更改这些密钥。

3.1.1.7. IDP AllowedClockSkew 子元素

AllowedClockSkew 可选子元素定义 IDP 和 SP 之间的允许时钟偏移。默认值为 0。

<AllowedClockSkew unit="MILLISECONDS">3500</AllowedClockSkew>
Copy to Clipboard Toggle word wrap
unit
可以定义附加到此元素值的时间范围。允许的值是 MICROSECONDS、MILLISECONDS、MINUTES、NANOSECONDS 和 SECONDS。这是 选项。默认值为 SECONDS

3.1.1.8. IDP SingleSignOnService 子元素

SingleSignOnService 子元素定义 IDP 的登录 SAML 端点。客户端适配器会在需要登录时通过此元素中的设置将请求发送到 IDP。

<SingleSignOnService signRequest="true"
                     validateResponseSignature="true"
                     requestBinding="post"
                     bindingUrl="url"/>
Copy to Clipboard Toggle word wrap

以下是您可以在此元素上定义的配置属性:

signRequest
客户端签名身份验证是否请求?此设置是 OPTIONAL。默认为 IDP 签名Required 元素值。
validateResponseSignature
客户端是否希望 IDP 签署从uhtn 请求发回的断言响应文档?此设置是 OPTIONAL。默认为 IDP 签名Required 元素值。
requestBinding
这是用于与 IDP 通信的 SAML 绑定类型。此设置是 OPTIONAL。默认值为 POST,但您也可以将其设置为 REDIRECT
responseBinding
SAML 允许客户端请求使用什么绑定类型。这个值可以是 POSTREDIRECT。此设置是 OPTIONAL。默认值是客户端不会为响应请求特定绑定类型。
assertionConsumerServiceUrl
断言使用者服务(ACS)的 URL,IDP 登录服务应向其中发送响应。此设置是 OPTIONAL。默认情况下,不设置它,它依赖于 IdP 中的配置。设置后,它必须以 /saml 结尾,例如 http://sp.domain.com/my/endpoint/for/saml。此属性的值以 SAML AuthnRequest 消息的 AssertionConsumerServiceURL 属性中发送。此属性通常由 responseBinding 属性使用。
bindingUrl
这是客户端将向其发送请求的 IDP 登录服务的 URL。此设置是 REQUIRED

3.1.1.9. IDP SingleLogoutService 子元素

SingleLogoutService 子元素定义 IDP 的注销 SAML 端点。在希望注销时,客户端适配器将通过此元素中的设置将请求发送到 IDP。

<SingleLogoutService validateRequestSignature="true"
                     validateResponseSignature="true"
                     signRequest="true"
                     signResponse="true"
                     requestBinding="redirect"
                     responseBinding="post"
                     postBindingUrl="posturl"
                     redirectBindingUrl="redirecturl">
Copy to Clipboard Toggle word wrap
signRequest
客户端注销请求是否应该进入 IDP?此设置是 OPTIONAL。默认为 IDP 签名Required 元素值。
signResponse
客户端注销响应是否应该发送到 IDP 请求?此设置是 OPTIONAL。默认为 IDP 签名Required 元素值。
validateRequestSignature
客户端是否应该从 IDP 中签署注销请求文档?此设置是 OPTIONAL。默认为 IDP 签名Required 元素值。
validateResponseSignature
客户端是否应该从 IDP 中签署注销响应文档?此设置是 OPTIONAL。默认为 IDP 签名Required 元素值。
requestBinding
这是用于向 IDP 通信 SAML 请求的 SAML 绑定类型。此设置是 OPTIONAL。默认值为 POST,但您也可以将其设置为 REDIRECT。
responseBinding
这是用于向 IDP 通信 SAML 响应的 SAML 绑定类型。这个值可以是 POSTREDIRECT。此设置是 OPTIONAL。默认值为 POST,但您也可以将其设置为 REDIRECT
postBindingUrl
这是使用 POST 绑定时 IDP 的注销服务的 URL。如果使用 POST 绑定,则此设置为 REQUIRED
redirectBindingUrl
这是使用 REDIRECT 绑定时 IDP 注销服务的 URL。如果使用 REDIRECT 绑定,则此设置为 REQUIRED

3.1.1.10. IDP Keys 子元素

IDP 的密钥子元素仅用于定义用于验证由 IDP 签署的证书或公钥。它定义方式与 SP 的 Keys 元素 相同。但是,您只需要定义一个证书或公钥引用。请注意,如果 Red Hat Single Sign-On 服务器和 adapter 分别意识到 IDP 和 SP,则不需要指定签名验证的密钥,请参阅以下。

可将 SP 配置为从已发布的证书中获取 IDP 签名验证的公钥,只要 Red Hat Single Sign-On 均实施 SP 和 IDP。这可以通过删除 Keys 子元素中的所有签名验证密钥声明来实现。如果 Keys 子元素保持为空,则可以完全省略它。然后,SP 从 SAML 描述符自动获取密钥,该位置派生自 IDP SingleSignOnService 子元素 中指定的 SAML 端点 URL。用于 SAML 描述符检索的 HTTP 客户端的设置通常需要额外的配置,但它可以在 IDP HttpClient 子元素 中配置。

也可以指定多个用于签名验证的密钥。这可以通过在 Keys 子元素内声明多个 Key 元素,并将 signing 属性设置为 true。例如,当 IDP 签名密钥被轮转时,这很有用:新的 SAML 协议消息和断言通常是一个转换周期,但仍应该接受之前密钥签名的断言。

无法将 Red Hat Single Sign-On 配置为自动获取签名验证的密钥并定义额外的静态签名验证密钥。

       <IDP entityID="idp">
            ...
            <Keys>
                <Key signing="true">
                    <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
                        <Certificate alias="demo"/>
                    </KeyStore>
                </Key>
            </Keys>
        </IDP>
Copy to Clipboard Toggle word wrap

3.1.1.11. IDP HttpClient 子元素

HttpClient 可选子元素定义了 HTTP 客户端的属性,用于在 启用时 通过 IDP 的 SAML 描述符自动获取包含 IDP 签名验证的公钥的 HTTP 客户端的属性。

<HttpClient connectionPoolSize="10"
            disableTrustManager="false"
            allowAnyHostname="false"
            clientKeystore="classpath:keystore.jks"
            clientKeystorePassword="pwd"
            truststore="classpath:truststore.jks"
            truststorePassword="pwd"
            proxyUrl="http://proxy/"
            socketTimeout="5000"
            connectionTimeout="6000"
            connectionTtl="500" />
Copy to Clipboard Toggle word wrap
connectionPoolSize
此配置选项定义应池与红帽单点登录服务器的连接数量。这是 选项。默认值为 10
disableTrustManager
如果 Red Hat Single Sign-On 服务器需要 HTTPS,且这个配置选项被设置为 true,则不需要指定信任存储。此设置应只在开发期间使用,永远不会 在生产环境中使用,因为它将禁用 SSL 证书的验证。这是 选项。默认值为 false
allowAnyHostname
如果 Red Hat Single Sign-On 服务器需要 HTTPS,且该配置选项被设置为 true,则红帽单点登录服务器的证书通过信任存储进行验证,但不会执行主机名验证。此设置只应在开发期间使用,永远不会 在生产环境中使用,因为它将部分禁用 SSL 证书的验证。这集在测试环境中可能很有用。这是 选项。默认值为 false
truststore
值是信任存储文件的文件路径。如果您使用 classpath: 前缀,则信任存储将从部署的 classpath 获取。用于向 Red Hat Single Sign-On 服务器的传出 HTTPS 通信。进行 HTTPS 请求的客户端需要一种验证它们要通信的服务器主机的方法。这就是信任者的作用。该密钥存储包含一个或多个可信主机证书或证书颁发机构。您可以通过提取红帽单点登录服务器的 SSL 密钥存储的公共证书来创建此信任存储。这是 REQUIRED,除非 disableTrustManagertrue
truststorePassword
truststore 的密码。如果设置了 truststore 且信任存储需要密码,则这是 REQUIRED
clientKeystore
这是密钥存储文件的文件路径。当适配器向 Red Hat Single Sign-On 服务器发出 HTTPS 请求时,此密钥存储包含双向 SSL 的客户端证书。这是 选项
clientKeystorePassword
客户端密钥存储的密码,以及客户端的密钥。如果设置了 clientKeystore,则这是 REQUIRED
proxyUrl
用于 HTTP 连接的 HTTP 代理服务器的 URL。这是 选项
socketTimeout
在建立连接(以毫秒为单位)后,套接字等待数据的超时。在两个数据包之间不活跃的最大时间。超时值为零将解释为无限超时。负值代表为未定义(如果适用,系统默认值)。默认值为 -1。这是 选项
connectionTimeout
与远程主机建立连接的超时(以毫秒为单位)。超时值为零将解释为无限超时。负值代表为未定义(如果适用,系统默认值)。默认值为 -1。这是 选项
connectionTtl
以毫秒为单位连接客户端到实时的连接时间。小于或等于零的值被解释为无限值。默认值为 -1。这是 选项

3.1.2. JBoss EAP 适配器

为了保护 JBoss EAP 上部署的 WAR 应用安全,您必须安装并配置 Red Hat Single Sign-On SAML Adapter subsystem。

然后,您可以在 WAR 中提供 keycloak 配置 /WEB-INF/keycloak-saml.xml 文件,并将 auth-method 更改为 web.xml 中的 KEYCLOAK-SAML。

您可以使用 ZIP 文件或 RPM 安装适配器。

3.1.3. 从 ZIP 文件安装适配器

每个适配器是在 Red Hat Single Sign-On 下载站点单独下载。

流程

  1. Downloads 网站安装适用于您的应用程序服务器的适配器。

    • 在 JBoss EAP 7.x 上安装:

      $ cd $EAP_HOME
      $ unzip rh-sso-saml-eap7-adapter.zip
      Copy to Clipboard Toggle word wrap
    • 在 JBoss EAP 6.x 上安装:

      $ cd $EAP_HOME
      $ unzip rh-sso-saml-eap6-adapter.zip
      Copy to Clipboard Toggle word wrap

      这些 ZIP 文件会创建特定于 JBoss EAP 分发中的 JBoss EAP SAML 适配器的新 JBoss 模块。

  2. 使用 CLI 脚本在应用服务器的服务器配置中启用红帽单点登录 SAML subsystem: domain.xmlstandalone.xml

    启动服务器并运行适用于您的应用服务器的脚本。

    • 对 JBoss EAP 7.1 或更新版本使用此命令

      $ cd $JBOSS_HOME
      $ ./bin/jboss-cli.sh -c --file=bin/adapter-elytron-install-saml.cli
      Copy to Clipboard Toggle word wrap
      注意

      EAP 分别支持 OpenJDK 17 和 Oracle JDK 17,自 7.4.CP7 和 7.4.CP8。请注意,新的 java 版本使 elytron 变体 compulsory,因此不要使用带有 JDK 17 的传统适配器。另外,在运行适配器 CLI 文件后,执行 EAP 提供的 enable-elytron-se17.cli 脚本。这两个脚本都需要配置 elytron 适配器并删除不兼容的 EAP 子系统。如需了解更多详细信息,请参阅此安全配置更改文章。

    • 对于 JBoss EAP 7.0 和 EAP 6.4 使用此命令

      $ cd $JBOSS_HOME
      $ ./bin/jboss-cli.sh -c --file=bin/adapter-install-saml.cli
      Copy to Clipboard Toggle word wrap
      注意

      也可以在 JBoss EAP 7.1 或更新版本中使用旧的非tron 适配器,这意味着您可以在这些版本中使用 adapter-install-saml.cli。但是,我们建议您使用较新的 Elytron 适配器。

      该脚本将添加扩展、子系统以及可选的 security-domain,如下所述。

<server xmlns="urn:jboss:domain:1.4">

    <extensions>
        <extension module="org.keycloak.keycloak-saml-adapter-subsystem"/>
          ...
    </extensions>

    <profile>
        <subsystem xmlns="urn:jboss:domain:keycloak-saml:1.1"/>
         ...
    </profile>
Copy to Clipboard Toggle word wrap

当您需要在受保护的 Web 层中创建的安全上下文被传播到您正调用的 EJB(其它 EE 组件)时,其中的 keycloak 安全域应当与 EJBs 和其他组件一起使用。否则此配置是可选的。

<server xmlns="urn:jboss:domain:1.4">
 <subsystem xmlns="urn:jboss:domain:security:1.2">
    <security-domains>
...
      <security-domain name="keycloak">
         <authentication>
           <login-module code="org.keycloak.adapters.jboss.KeycloakLoginModule"
                         flag="required"/>
          </authentication>
      </security-domain>
    </security-domains>
Copy to Clipboard Toggle word wrap

安全上下文自动传播到 EJB 层。

3.1.3.1. JBoss SSO

JBoss EAP 内置了对部署到同一 JBoss EAP 实例的 Web 应用程序的单点登录支持。使用 Red Hat Single Sign-On 时不应该启用此功能。

3.1.3.2. 为 JSESSIONID Cookie 设置 SameSite 值

浏览器计划将 Cookie 的 SameSite 属性的默认值设置为 Lax。此设置表示,仅当请求源自于同一域中时,cookies 才会发送到应用程序。这个行为可能会影响 SAML POST 绑定,这可能会变为无法正常工作。要保留 SAML 适配器的完整功能,我们建议将容器创建的 JSESSIONID cookie 的 SameSite 值设置为 None。不这样做可能会导致对每个请求重置容器的会话。

注意

要避免将 SameSite 属性设置为 None,请考虑切换到 REDIRECT 绑定(如果可接受),或者使用这个临时解决方案的 OIDC 协议。

要将 Wildfly/EAP 中的 JSESSIONID cookie 的 SameSite 值设置为 None,请在应用程序的 WEB-INF 目录中添加 file undertow-handlers.conf

samesite-cookie(mode=None, cookie-pattern=JSESSIONID)
Copy to Clipboard Toggle word wrap

对此配置的支持在 19.1.0 版本中的 Wildfly 中提供。

3.1.4. 从 RPM 安装 JBoss EAP 7 Adapter

注意

使用 Red Hat Enterprise Linux 7 时,术语频道被替换为术语仓库。这些说明中,仅使用术语库。

先决条件

您必须订阅 JBoss EAP 7 存储库,然后才能从 RPM 安装 EAP 7 适配器。

  • 确定使用 Red Hat Subscription Manager 将 Red Hat Enterprise Linux 系统注册到您的帐户。如需更多信息,请参阅 Red Hat Subscription Management 文档
  • 如果您已经订阅了另一个 JBoss EAP 存储库,必须先退出该存储库。

    对于 Red Hat Enterprise Linux 6,7:使用 Red Hat Subscription Manager,通过以下命令订阅 JBoss EAP 7.4 存储库。根据您的 Red Hat Enterprise Linux 版本,将 <RHEL_VERSION> 替换为 6 或 7。

    $ sudo subscription-manager repos --enable=jb-eap-7-for-rhel-<RHEL_VERSION>-server-rpms
    Copy to Clipboard Toggle word wrap

    对于 Red Hat Enterprise Linux 8:使用 Red Hat Subscription Manager,使用以下命令订阅 JBoss EAP 7.4 存储库:

    $ sudo subscription-manager repos --enable=jb-eap-7.4-for-rhel-8-x86_64-rpms --enable=rhel-8-for-x86_64-baseos-rpms --enable=rhel-8-for-x86_64-appstream-rpms
    Copy to Clipboard Toggle word wrap

流程

  1. 根据您的 Red Hat Enterprise Linux 版本,为 SAML 安装 EAP 7 适配器。

    • 在 Red Hat Linux 7 上安装:

      $ sudo yum install eap7-keycloak-saml-adapter-sso7_6
      Copy to Clipboard Toggle word wrap
    • 在 Red Hat Enterprise Linux 8 中安装:

      $ sudo dnf install eap7-keycloak-adapter-sso7_6
      Copy to Clipboard Toggle word wrap
      注意

      RPM 安装的默认 EAP_HOME 路径为 /opt/rh/eap7/root/usr/share/wildfly。

  2. 为 SAML 模块运行安装脚本:

    $ $EAP_HOME/bin/jboss-cli.sh -c --file=$EAP_HOME/bin/adapter-install-saml.cli
    Copy to Clipboard Toggle word wrap

您的安装已完成。

3.1.5. 从 RPM 安装 JBoss EAP 6 Adapter

注意

使用 Red Hat Enterprise Linux 7 时,术语频道被替换为术语仓库。这些说明中,仅使用术语库。

先决条件

您必须订阅 JBoss EAP 6 存储库,然后才能从 RPM 安装 EAP 6 适配器。

  • 确定使用 Red Hat Subscription Manager 将 Red Hat Enterprise Linux 系统注册到您的帐户。如需更多信息,请参阅 Red Hat Subscription Management 文档
  • 如果您已经订阅了另一个 JBoss EAP 存储库,必须先退出该存储库。
  • 使用 Red Hat Subscription Manager,使用以下命令订阅 JBoss EAP 6 存储库。根据您的 Red Hat Enterprise Linux 版本,将 <RHEL_VERSION> 替换为 6 或 7。

    $ sudo subscription-manager repos --enable=jb-eap-6-for-rhel-<RHEL_VERSION>-server-rpms
    Copy to Clipboard Toggle word wrap

流程

  1. 使用以下命令为 SAML 安装 EAP 6 适配器:

    $ sudo yum install keycloak-saml-adapter-sso7_6-eap6
    Copy to Clipboard Toggle word wrap
    注意

    RPM 安装的默认 EAP_HOME 路径为 /opt/rh/eap6/root/usr/share/wildfly。

  2. 为 SAML 模块运行安装脚本:

    $ $EAP_HOME/bin/jboss-cli.sh -c --file=$EAP_HOME/bin/adapter-install-saml.cli
    Copy to Clipboard Toggle word wrap

您的安装已完成。

3.1.5.1. 保护 WAR

这部分论述了如何通过在 WAR 软件包中添加配置和编辑文件来直接保护 WAR。

您首先在 WAR 的 WEB-INF 目录下创建一个 keycloak-saml.xml 适配器配置文件。常规 适配器配置部分描述了此配置文件的格式。

接下来,您必须在 web.xml 中将 auth-method 设置为 KEYCLOAK-SAML。您还必须使用标准 servlet 安全性为您的 URL 指定角色基础限制。以下是 web.xml 文件示例:

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
      version="3.0">

	<module-name>customer-portal</module-name>

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Admins</web-resource-name>
            <url-pattern>/admin/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>admin</role-name>
        </auth-constraint>
        <user-data-constraint>
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
    </security-constraint>
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Customers</web-resource-name>
            <url-pattern>/customers/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>user</role-name>
        </auth-constraint>
        <user-data-constraint>
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
    </security-constraint>

    <login-config>
        <auth-method>KEYCLOAK-SAML</auth-method>
        <realm-name>this is ignored currently</realm-name>
    </login-config>

    <security-role>
        <role-name>admin</role-name>
    </security-role>
    <security-role>
        <role-name>user</role-name>
    </security-role>
</web-app>
Copy to Clipboard Toggle word wrap

auth-method 设置外的所有标准 servlet 设置。

3.1.5.2. 使用红帽单点登录 SAML 子系统保护 WAR

您不必打开 WAR 才能使用 Red Hat Single Sign-On 对其进行保护。另外,您还可以通过 Red Hat Single Sign-On SAML Adapter subsystem 对外部保护。虽然您不必将 KEYCLOAK-SAML 指定为 auth-method,但您仍必须在 web.xml 中定义 security-constraints。但是,您不必创建 WEB-INF/keycloak-saml.xml 文件。这个元数据会在服务器的 domain.xmlstandalone.xml 子系统配置部分中的 XML 中定义。

<extensions>
  <extension module="org.keycloak.keycloak-saml-adapter-subsystem"/>
</extensions>

<profile>
  <subsystem xmlns="urn:jboss:domain:keycloak-saml:1.1">
    <secure-deployment name="WAR MODULE NAME.war">
      <SP entityID="APPLICATION URL">
        ...
      </SP>
    </secure-deployment>
  </subsystem>
</profile>
Copy to Clipboard Toggle word wrap

secure-deployment name 属性标识您要保护的 WAR。其值是 web.xml 中定义的 module-name,并附加 .war。其余的配置使用与 General Adapter Config 中定义的 keycloak-saml.xml 配置相同的 XML 语法。

配置示例:

<subsystem xmlns="urn:jboss:domain:keycloak-saml:1.1">
  <secure-deployment name="saml-post-encryption.war">
    <SP entityID="http://localhost:8080/sales-post-enc/"
        sslPolicy="EXTERNAL"
        nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
        logoutPage="/logout.jsp"
        forceAuthentication="false">
      <Keys>
        <Key signing="true" encryption="true">
          <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
            <PrivateKey alias="http://localhost:8080/sales-post-enc/" password="test123"/>
            <Certificate alias="http://localhost:8080/sales-post-enc/"/>
          </KeyStore>
        </Key>
      </Keys>
      <PrincipalNameMapping policy="FROM_NAME_ID"/>
      <RoleIdentifiers>
        <Attribute name="Role"/>
      </RoleIdentifiers>
      <IDP entityID="idp">
        <SingleSignOnService signRequest="true"
            validateResponseSignature="true"
            requestBinding="POST"
            bindingUrl="http://localhost:8080/auth/realms/saml-demo/protocol/saml"/>

        <SingleLogoutService
            validateRequestSignature="true"
            validateResponseSignature="true"
            signRequest="true"
            signResponse="true"
            requestBinding="POST"
            responseBinding="POST"
            postBindingUrl="http://localhost:8080/auth/realms/saml-demo/protocol/saml"
            redirectBindingUrl="http://localhost:8080/auth/realms/saml-demo/protocol/saml"/>
        <Keys>
          <Key signing="true" >
            <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
              <Certificate alias="saml-demo"/>
            </KeyStore>
          </Key>
        </Keys>
      </IDP>
    </SP>
   </secure-deployment>
</subsystem>
Copy to Clipboard Toggle word wrap

3.1.6. Java Servlet 过滤器适配器

如果要将 SAML 与不属于 servlet 平台的适配器的 Java servlet 应用程序搭配使用,您可以选择使用 Red Hat Single Sign-On 拥有的 servlet 过滤器。这个适配器的工作方式与其它适配器不同。您仍然需要指定一个 /WEB-INF/keycloak-saml.xml 文件,如 General Adapter Config 部分中定义,但您不会在 web.xml 中定义安全限制。反之,您可以使用 Red Hat Single Sign-On servlet 过滤器适配器定义一个过滤器映射来保护您要保护的 url 模式。

注意

Backchannel logout 与标准适配器不同。它而不是无效的 http 会话,而是将会话 ID 标记为已注销。不只是一个基于会话 ID 对 http 会话进行无效的方法。

警告

当您有一个使用 SAML 过滤器的集群应用程序时,恢复通道注销将无法正常工作。

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
      version="3.0">

	<module-name>customer-portal</module-name>

    <filter>
        <filter-name>Keycloak Filter</filter-name>
        <filter-class>org.keycloak.adapters.saml.servlet.SamlFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>Keycloak Filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>
Copy to Clipboard Toggle word wrap

Red Hat Single Sign-On 过滤器具有与与其他适配器相同的配置参数,但您必须将它们定义为 filter init 参数,而不是上下文参数。

如果您有不同的安全和不安全的 url 模式,可以定义多个过滤器映射。

警告

您必须有一个涵盖 /saml 的过滤器映射。此映射涵盖了所有服务器回调。

当将 SP 与 IdP 注册时,您必须将 http[s]://hostname/{context-root}/saml 注册为 Assert Consumer Service URL 和 Single Logout Service URL。

要使用此过滤器,请在 WAR poms 中包括这个 maven 工件:

<dependency>
   <groupId>org.keycloak</groupId>
   <artifactId>keycloak-saml-servlet-filter-adapter</artifactId>
   <version>18.0.18.redhat-00001</version>
</dependency>
Copy to Clipboard Toggle word wrap

要使用 Multi Tenancykeycloak.config.resolver 参数应作为过滤器参数传递。

    <filter>
        <filter-name>Keycloak Filter</filter-name>
        <filter-class>org.keycloak.adapters.saml.servlet.SamlFilter</filter-class>
        <init-param>
            <param-name>keycloak.config.resolver</param-name>
            <param-value>example.SamlMultiTenantResolver</param-value>
        </init-param>
    </filter>
Copy to Clipboard Toggle word wrap

3.1.7. 使用身份提供程序注册

对于每个基于 servlet 的适配器,您注册了 assert 使用者服务 URL 的端点必须是 servlet 应用程序的基本 URL,附加有 /saml,即 https://example.com/contextPath/saml

3.1.8. 退出

您可以通过多种方式从 web 应用程序注销。对于 Jakarta EE servlet 容器,您可以调用 HttpServletRequest.logout()。对于任何其他浏览器应用程序,您可以将浏览器指向具有安全约束的 Web 应用的任何 url,并传递查询参数 GLO,例如 http://myapp?GLO=true。如果您通过浏览器具有 SSO 会话,这将注销。

3.1.8.1. 在集群环境中注销

在内部,SAML 适配器会在 SAML 会话索引、主体名称(已知)和 HTTP 会话 ID 之间存储映射。此映射可以在 JBoss 应用服务器系列(WildFly 10/11、EAP 6/7)中维护,以供分布的应用程序使用。作为条件,需要在应用程序的 web.xml中使用 <distribut/> 标签分发 HTTP 会话(例如,应用程序标记为 <distriable /> 标签)。

要启用功能,请在 /WEB_INF/web.xml 文件中添加以下部分:

对于 EAP 7,WildFly 10/11:

<context-param>
    <param-name>keycloak.sessionIdMapperUpdater.classes</param-name>
    <param-value>org.keycloak.adapters.saml.wildfly.infinispan.InfinispanSessionCacheIdMapperUpdater</param-value>
</context-param>
Copy to Clipboard Toggle word wrap

对于 EAP 6:

<context-param>
    <param-name>keycloak.sessionIdMapperUpdater.classes</param-name>
    <param-value>org.keycloak.adapters.saml.jbossweb.infinispan.InfinispanSessionCacheIdMapperUpdater</param-value>
</context-param>
Copy to Clipboard Toggle word wrap

如果部署的会话缓存命名为 deployment-cache,用于 SAML 映射的缓存将命名为 deployment-cache.ssoCache。缓存名称可以被 context 参数 keycloak.sessionIdMapperUpdater.infinispan.cacheName 覆盖。包含缓存的 cache 容器与包含部署会话缓存的 cache 容器相同,但可以被上下文参数 keycloak.sessionIdMapperUpdater.infinispan.containerName 覆盖。

默认情况下,SAML 映射缓存的配置将派生自会话缓存。可以手动覆盖与其它缓存相同的服务器的缓存配置部分。

目前,为了提供可靠的服务,建议将复制缓存用于 SAML 会话缓存。使用分布式缓存可能会导致 SAML 注销请求进入没有访问 SAML 会话索引到 HTTP 会话映射的节点,这会导致无法注销。

3.1.8.2. 退出跨站点情境

跨站点方案仅适用于 WildFly 10 和更高版本,且 EAP 7 及更高版本。

处理跨越多个数据中心的会话需要特殊处理。考虑以下情境:

  1. 登录请求在数据中心 1 中处理。
  2. 管理员发出特定 SAML 会话的注销请求,请求进入数据中心 2。

数据中心 2 必须注销数据中心 1 中(以及共享 HTTP 会话的所有其他数据中心)存在的所有会话。

要涵盖这种情况,上述 SAML 会话缓存只需要在单个集群中复制,而是在所有数据中心复制,例如通过独立 Infinispan/JDG 服务器

  1. 缓存必须添加到独立的 Infinispan/JDG 服务器中。
  2. 必须将上一项中的缓存添加为对应 SAML 会话缓存的远程存储。

在部署期间找到了远程存储以在 SAML 会话缓存中存在后,则会监视更改,并相应地更新本地 SAML 会话缓存。

3.1.9. 获取断言属性

成功 SAML 登录后,您的应用程序代码可能希望获取通过 SAML 断言传递的属性值。HttpServletRequest.getUserPrincipal() 返回 可进入 Red Hat Single Sign-On 特定类(名为 org.keycloak.adapters.saml.SamlPrincipal )的主体对象。此对象允许您查看原始的断言,以及便利函数来查找属性值。

package org.keycloak.adapters.saml;

public class SamlPrincipal implements Serializable, Principal {
    /**
     * Get full saml assertion
     *
     * @return
     */
    public AssertionType getAssertion() {
       ...
    }

    /**
     * Get SAML subject sent in assertion
     *
     * @return
     */
    public String getSamlSubject() {
        ...
    }

    /**
     * Subject nameID format
     *
     * @return
     */
    public String getNameIDFormat() {
        ...
    }

    @Override
    public String getName() {
        ...
    }

    /**
     * Convenience function that gets Attribute value by attribute name
     *
     * @param name
     * @return
     */
    public List<String> getAttributes(String name) {
        ...

    }

    /**
     * Convenience function that gets Attribute value by attribute friendly name
     *
     * @param friendlyName
     * @return
     */
    public List<String> getFriendlyAttributes(String friendlyName) {
        ...
    }

    /**
     * Convenience function that gets first  value of an attribute by attribute name
     *
     * @param name
     * @return
     */
    public String getAttribute(String name) {
        ...
    }

    /**
     * Convenience function that gets first  value of an attribute by attribute name
     *
     *
     * @param friendlyName
     * @return
     */
    public String getFriendlyAttribute(String friendlyName) {
        ...
    }

    /**
     * Get set of all assertion attribute names
     *
     * @return
     */
    public Set<String> getAttributeNames() {
        ...
    }

    /**
     * Get set of all assertion friendly attribute names
     *
     * @return
     */
    public Set<String> getFriendlyNames() {
        ...
    }
}
Copy to Clipboard Toggle word wrap

3.1.10. 错误处理

Red Hat Single Sign-On 对基于 servlet 的客户端适配器有一些错误处理功能。在身份验证中遇到错误时,客户端适配器将调用 HttpServletResponse.sendError()。您可以在 web.xml 文件中设置一个 错误页面 来处理错误。客户端适配器可能会抛出 400、401、403 和 500 错误。

<error-page>
    <error-code>403</error-code>
    <location>/ErrorHandler</location>
</error-page>
Copy to Clipboard Toggle word wrap

客户端适配器还设置可检索的 HttpServletRequest 属性。属性名称是 org.keycloak.adapters.spi.AuthenticationError。Typecast this object to: org.keycloak.adapters.saml.SamlAuthenticationError.此类可以告诉您发生的情况。如果没有设置此属性,则适配器不负责错误代码。

public class SamlAuthenticationError implements AuthenticationError {
    public static enum Reason {
        EXTRACTION_FAILURE,
        INVALID_SIGNATURE,
        ERROR_STATUS
    }

    public Reason getReason() {
        return reason;
    }
    public StatusResponseType getStatus() {
        return status;
    }
}
Copy to Clipboard Toggle word wrap

3.1.11. 故障排除

对问题进行故障排除的最佳方式是在客户端适配器和 Red Hat Single Sign-On Server 中打开 SAML 的调试。使用您的日志记录框架,将 org.keycloak.saml 软件包的日志级别设置为 DEBUG。启用这个端口可让您看到 SAML 请求和响应文档发送到服务器以及从服务器发送。

3.1.12. 多租户

SAML 提供与 Multi Tenancy 相同的功能,这意味着单个目标应用程序(WAR)可以使用多个 Red Hat Single Sign-On 域进行保护。域可以位于同一红帽单点登录实例或不同的实例上。

要做到这一点,应用程序必须有多个 keycloak-saml.xml 适配器配置文件。

虽然您可以有多个 WAR 实例,但不同的适配器配置文件部署到不同的上下文路径,但这可能很不便,您可能还希望根据上下文路径以外的某些域选择域。

Red Hat Single Sign-On 使可以有一个自定义配置解析器,以便您可以选择每个请求使用哪些适配器配置。在 SAML 中,配置只在登录处理中非常感兴趣;一旦登录,会话会被身份验证,并且如果返回了 keycloak-saml.xml 并不重要。因此,为相同会话返回相同的配置是到达的正确方法。

为达成此目标,可创建 org.keycloak.adapters.saml.SamlConfigResolver 的实施。以下示例使用 Host 标头来定位正确的配置并加载它以及应用程序的 Java 类路径中的关联元素:

package example;

import java.io.InputStream;
import org.keycloak.adapters.saml.SamlConfigResolver;
import org.keycloak.adapters.saml.SamlDeployment;
import org.keycloak.adapters.saml.config.parsers.DeploymentBuilder;
import org.keycloak.adapters.saml.config.parsers.ResourceLoader;
import org.keycloak.adapters.spi.HttpFacade;
import org.keycloak.saml.common.exceptions.ParsingException;

public class SamlMultiTenantResolver implements SamlConfigResolver {

    @Override
    public SamlDeployment resolve(HttpFacade.Request request) {
        String host = request.getHeader("Host");
        String realm = null;
        if (host.contains("tenant1")) {
            realm = "tenant1";
        } else if (host.contains("tenant2")) {
            realm = "tenant2";
        } else {
            throw new IllegalStateException("Not able to guess the keycloak-saml.xml to load");
        }

        InputStream is = getClass().getResourceAsStream("/" + realm + "-keycloak-saml.xml");
        if (is == null) {
            throw new IllegalStateException("Not able to find the file /" + realm + "-keycloak-saml.xml");
        }

        ResourceLoader loader = new ResourceLoader() {
            @Override
            public InputStream getResourceAsStream(String path) {
                return getClass().getResourceAsStream(path);
            }
        };

        try {
            return new DeploymentBuilder().build(is, loader);
        } catch (ParsingException e) {
            throw new IllegalStateException("Cannot load SAML deployment", e);
        }
    }
}
Copy to Clipboard Toggle word wrap

您还必须配置在 web.xml 中用于 keycloak.config.resolver context-param 的 SamlConfigResolver 实现:

<web-app>
    ...
    <context-param>
        <param-name>keycloak.config.resolver</param-name>
        <param-value>example.SamlMultiTenantResolver</param-value>
    </context-param>
</web-app>
Copy to Clipboard Toggle word wrap
返回顶部
Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。 了解我们当前的更新.

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

Theme

© 2025 Red Hat