搜索

第 2 章 使用 OpenID Connect 来保护应用程序和服务

download PDF

本节介绍了如何使用 Red Hat Single Sign-On 适配器或通用 OpenID Connect 来保护使用 OpenID Connect 的应用程序和服务。

2.1. Java 适配器

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

所有 Java 适配器共享一组常见配置选项,如 Java 适配器配置 章节中所述。

2.1.1. Java adapter 配置

Red Hat Single Sign-On 支持的每个 Java 适配器都可通过简单的 JSON 文件进行配置。这种情况可能如下所示:

{
  "realm" : "demo",
  "resource" : "customer-portal",
  "realm-public-key" : "MIGfMA0GCSqGSIb3D...31LwIDAQAB",
  "auth-server-url" : "https://localhost:8443/auth",
  "ssl-required" : "external",
  "use-resource-role-mappings" : false,
  "enable-cors" : true,
  "cors-max-age" : 1000,
  "cors-allowed-methods" : "POST, PUT, DELETE, GET",
  "cors-exposed-headers" : "WWW-Authenticate, My-custom-exposed-Header",
  "bearer-only" : false,
  "enable-basic-auth" : false,
  "expose-token" : true,
  "verify-token-audience" : true,
  "credentials" : {
    "secret" : "234234-234234-234234"
  },

  "connection-pool-size" : 20,
  "socket-timeout-millis" : 5000,
  "connection-timeout-millis" : 6000,
  "connection-ttl-millis" : 500,
  "disable-trust-manager" : false,
  "allow-any-hostname" : false,
  "truststore" : "path/to/truststore.jks",
  "truststore-password" : "geheim",
  "client-keystore" : "path/to/client-keystore.jks",
  "client-keystore-password" : "geheim",
  "client-key-password" : "geheim",
  "token-minimum-time-to-live" : 10,
  "min-time-between-jwks-requests" : 10,
  "public-key-cache-ttl" : 86400,
  "redirect-rewrite-rules" : {
    "^/wsmaster/api/(.*)$" : "/api/$1"
  }
}

您可以将 ${…​} containure 用于系统属性替换。例如: ${jboss.server.config.dir} 替换为 /path/to/Red Hat Single Sign-On。也支持通过 env 前缀替换环境变量,如 ${env.MY_ENVIRONMENT_VARIABLE}

初始配置文件可以从 admin 控制台获得。这可以通过打开 admin 控制台来完成,从菜单中选择 Clients 并单击对应的客户端。打开客户端页面后,点 Installation 选项卡并选择 Keycloak OIDC JSON

以下是每个配置选项的描述:

realm
域的名称。这是 REQUIRED.
resource
应用程序的 client-id。每个应用程序都有一个用于标识应用程序的 client-id。这是 REQUIRED.
realm-public-key
realm 公钥的 PEM 格式。您可以从 Admin Console 获取它。这是选项,我们不推荐对其进行设置。如果没有设置,则适配器会从红帽单点登录下载,并在需要时总是重新下载(例如,Red Hat Single Sign-On 轮转其密钥)。但是,如果设置了 realm-public-key,则适配器永远不会从 Red Hat Single Sign-On 下载新密钥,因此当红帽单点登录轮转它的密钥时,适配器可能会中断。
auth-server-url
红帽单点登录服务器的基本 URL。所有其他红帽单点登录页面和 REST 服务端点都源自于此。它通常是 https://host:port/auth 格式。这是 REQUIRED.
ssl-required
确保所有与 Red Hat Single Sign-On 服务器的通信均通过 HTTPS。在生产环境中,这应设置为 all。这是 选项。默认值为 external。这意味着外部请求默认需要 HTTPS。有效值为 'all'、'external' 和 'none'。
confidential-port
红帽单点登录服务器用于通过 SSL/TLS 进行安全连接的机密端口。这是 选项。默认值为 8443
use-resource-role-mappings
如果设置为 true,则适配器会在令牌内部查找用户的应用程序级别的角色映射。如果为 false,它将查看用户角色映射的域级别。这是 选项。默认值为 false
public-client
如果设置为 true,则适配器不会向 Red Hat Single Sign-On 发送客户端凭证。这是 选项。默认值为 false
enable-cors
这可实现 CORS 支持。它将处理 CORS preflight 请求。它还将查看访问令牌来确定有效的来源。这是 选项。默认值为 false
cors-max-age
如果启用了 CORS,这会设置 Access-Control-Max-Age 标头的值。这是 选项。如果没有设置,则这个标头不会在 CORS 响应中返回。
cors-allowed-methods
如果启用了 CORS,这会设置 Access-Control-Allow-Methods 标头的值。这应该是一个用逗号分开的字符串。这是 选项。如果没有设置,则这个标头不会在 CORS 响应中返回。
cors-allowed-headers
如果启用了 CORS,这会设置 Access-Control-Allow-Headers 标头的值。这应该是一个用逗号分开的字符串。这是 选项。如果没有设置,则这个标头不会在 CORS 响应中返回。
cors-exposed-headers
如果启用了 CORS,这会设置 Access-Control-Expose-Headers 标头的值。这应该是一个用逗号分开的字符串。这是 选项。如果没有设置,则这个标头不会在 CORS 响应中返回。
bearer-only
对于服务,这应设为 true。如果启用适配器不会试图验证用户,但只验证 bearer 令牌。这是 选项。默认值为 false
仅自动探测器
如果您的应用程序同时充当 Web 应用程序和 Web 服务(如 SOAP 或 REST),则此项应设为 true。它允许您将 Web 应用的未经身份验证的用户重定向到 Red Hat Single Sign-On 登录页面,但向未经身份验证的 SOAP 或 REST 客户端发送 HTTP 401 状态代码,因为它们不知道到登录页面的重定向。红帽单点登录根据典型的标头(如 X-Requested-WithSOAPActionAccept )自动探测 SOAP 或 REST 客户端。默认值为 false
enable-basic-auth
这告知适配器也支持基本身份验证。如果启用了这个选项,则必须提供 secret。这是 选项。默认值为 false
expose-token
如果为 true,则经过身份验证的浏览器客户端(通过 JavaScript HTTP 调用)可以通过 URL root/k_query_bearer_token 获取签名的访问令牌。这是 选项。默认值为 false
credentials
指定应用程序的凭证。这是一个对象表示法,其中键是凭证类型,值是凭证类型的值。目前支持 password 和 jwt。这只适用于 具有 "Confidential"访问类型的客户端。
connection-pool-size
此配置选项定义应池与红帽单点登录服务器的连接数量。这是 选项。默认值为 20
socket-timeout-millis
在建立连接(以毫秒为单位)后,套接字等待数据的超时。在两个数据包之间不活跃的最大时间。超时值为零将解释为无限超时。负值代表为未定义(如果适用,系统默认值)。默认值为 -1。这是 选项
connection-timeout-millis
与远程主机建立连接的超时(以毫秒为单位)。超时值为零将解释为无限超时。负值代表为未定义(如果适用,系统默认值)。默认值为 -1。这是 选项
connection-ttl-millis
以毫秒为单位连接客户端到实时的连接时间。小于或等于零的值被解释为无限值。默认值为 -1。这是 选项
disable-trust-manager
如果 Red Hat Single Sign-On 服务器需要 HTTPS,且这个配置选项被设置为 true,则不需要指定信任存储。此设置应只在开发期间使用,永远不会 在生产环境中使用,因为它将禁用 SSL 证书的验证。这是 选项。默认值为 false
allow-any-hostname
如果 Red Hat Single Sign-On 服务器需要 HTTPS,且该配置选项被设置为 true,则红帽单点登录服务器的证书通过信任存储进行验证,但不会执行主机名验证。此设置应只在开发期间使用,永远不会 在生产环境中使用,因为它将禁用 SSL 证书的验证。此设置在测试环境中可能很有用,这是 选项。默认值为 false
proxy-url
HTTP 代理的 URL(如果使用)。
truststore
值是信任存储文件的文件路径。如果您使用 classpath: 前缀,则信任存储将从部署的 classpath 获取。用于向 Red Hat Single Sign-On 服务器的传出 HTTPS 通信。进行 HTTPS 请求的客户端需要一种验证它们要通信的服务器主机的方法。这就是信任者的作用。该密钥存储包含一个或多个可信主机证书或证书颁发机构。您可以通过提取红帽单点登录服务器的 SSL 密钥存储的公共证书来创建此信任存储。这是 REQUIRED,除非 ssl-requirednonedisable-trust-managertrue
truststore-password
truststore 的密码。如果设置了 truststore 且信任存储需要密码,则这是 REQUIRED
client-keystore
这是密钥存储文件的文件路径。当适配器向 Red Hat Single Sign-On 服务器发出 HTTPS 请求时,此密钥存储包含双向 SSL 的客户端证书。这是 选项
client-keystore-password
客户端密钥存储的密码。如果设置了 client-keystore,则这是 REQUIRED
client-key-password
客户端密钥的密码。如果设置了 client-keystore,则这是 REQUIRED
always-refresh-token
如果为 true,则适配器将在每个请求中刷新令牌。警告 - 启用后,将导致每个应用程序请求红帽单点登录请求。
register-node-at-startup
如果为 true,则适配器会向红帽单点登录发送注册请求。默认情况下为 false,仅在应用程序集群时使用。详情请参阅 应用程序集群
register-node-period
红帽单点登录重新注册适配器的时间。应用程序集群时会很有用。详情请参阅 应用程序集群
token-store
可能的值有 sessioncookie。默认为 session,这意味着适配器在 HTTP Session 中存储帐户信息。替代 Cookie 意味着在 cookie 中存储信息。详情请参阅 应用程序集群
token-cookie-path
在使用 cookie 存储时,此选项会设置用于存储帐户信息的 cookie 的路径。如果是一个相对路径,则假定应用程序在上下文根目录中运行,并相对于该上下文 root 进行解释。如果是绝对路径,则使用绝对路径来设置 Cookie 路径。默认使用相对于上下文 root 的路径。
principal-attribute
OpenID Connect ID Token 属性,用于填充 UserPrincipal 名称:如果 token 属性为空,则默认为 sub。可能的值有 sub,preferred_username,email,name,nickname,given_name,family_name
turn-off-change-session-id-on-login
在某些平台上成功登录时,会话 ID 被改变,以插入安全攻击向量。如果要关闭此操作,请将此项更改为 true。默认值为 false
token-minimum-time-to-live
在过期之前,使用 Red Hat Single Sign-On 服务器预先刷新一个活跃的访问令牌的时间(以秒为单位)。当访问令牌发送到另一个 REST 客户端(在评估之前其过期时)时特别有用。这个值不应超过 realm 的访问令牌生命周期span。这是 选项。默认值为 0 秒,因此当访问令牌已过期时,适配器才会刷新访问令牌。
min-time-between-jwks-requests
以秒为单位指定两个请求之间的最短间隔,以便检索新的公钥。默认是 10 秒。当适配器识别带有未知 kid 的令牌时,适配器会始终尝试下载新的公钥。但是,每 10 秒(默认)不会尝试一次。当攻击者使用错误的 kid 强制适配器向 Red Hat Single Sign-On 发送大量请求时,为了避免 DoS。
public-key-cache-ttl
以秒为单位,指定两个请求到红帽单点登录之间的最大间隔,以检索新的公钥。默认为 86400 秒(1 天)。当适配器识别带有未知 kid 的令牌时,适配器会始终尝试下载新的公钥。如果它通过已知 kid 识别令牌,它仅使用之前下载的公钥。但是,每个配置的时间间隔至少一次(默认为 1 天)是新的公钥,即使 kid of token 已经已知。
ignore-oauth-query-parameter
默认为 false,如果设为 true,则会关闭处理 bearer 令牌处理的 access_token 查询参数。如果用户只通过了 access_token,用户将无法验证
redirect-rewrite-rules
如果需要,指定 Redirect URI 重写规则。这是一个对象表示法,其中键是要匹配重定向 URI 的正则表达式,值是替换 String。$ 字符可用于替换 String 中的反向引用。
verify-token-audience
如果设置为 true,则在使用 bearer 令牌进行身份验证的过程中,适配器将验证令牌是否包含这个客户端名称(资源)作为使用者。选项对于服务来说,主要服务于由 bearer 令牌验证的请求。这会默认设置为 false,但为了提高安全性,建议启用它。如需了解更多有关受众支持的详细信息,请参阅受众支持

2.1.2. JBoss EAP 适配器

您可以从 ZIP 文件或从 RPM 安装这个适配器。

2.1.3. 从一个 ZIP 文件安装 JBOSS EAP 适配器

为了保护 JBoss EAP 上部署的 WAR 应用安全,您必须安装并配置 Red Hat Single Sign-On 适配器子系统。然后,有两个选项来保护 WAR。

  • 您可以在 WAR 中提供适配器配置文件,并在 web.xml 中将 auth-method 更改为 KEYCLOAK。
  • 或者,您不必修改所有 WAR,您可以通过配置文件中的 Red Hat Single Sign-On adapter 子系统配置(如 standalone.xml )来保护它。

本节都介绍这两种方法。

适配器作为单独的归档提供,具体取决于您使用的服务器版本。

流程

  1. 软件下载 站点安装适用于您的应用程序服务器的适配器。

    • 在 JBoss EAP 7 上安装:

      $ cd $EAP_HOME
      $ unzip rh-sso-7.6.9-eap7-adapter.zip

      此 ZIP 存档包含特定于 Red Hat Single Sign-On 适配器的 JBoss 模块。它还包含用于配置适配器子系统的 JBoss CLI 脚本。

  2. 要配置适配器子系统,请执行适当的命令。

    • 如果服务器 没有运行,则在 JBoss EAP 7.1 或更新版本上安装。

      $ ./bin/jboss-cli.sh --file=bin/adapter-elytron-install-offline.cli
      注意

      JBoss EAP 6.4 不可用的离线脚本

    • 如果服务器运行,则在 JBoss EAP 7.1 或更新版本上安装。

      $ ./bin/jboss-cli.sh -c --file=bin/adapter-elytron-install.cli
      注意

      在 JBoss EAP 7.1 或更新版本中可以使用旧的非 Elytron 适配器,这意味着您可以使用 adapter-install-offline.cli

      注意

      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 6.4 上安装

      $ ./bin/jboss-cli.sh -c --file=bin/adapter-install.cli

2.1.3.1. JBoss SSO

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

2.1.3.2. 保护 WAR

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

流程

  1. 在 WAR 的 WEB-INF 目录下创建一个 keycloak.json 适配器配置文件。

    这个配置文件的格式在 Java 适配器配置 部分中进行了描述。

  2. web.xml 中将 auth-method 设置为 KEYCLOAK
  3. 使用标准 servlet 安全性为您的 URL 指定角色基础限制。

    例如:

    <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>application</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</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>

2.1.3.3. 通过适配器子系统保护 WAR

您不必修改 WAR 以便使用 Red Hat Single Sign-On 对其进行保护。您也可以通过 Red Hat Single Sign-On Adapter 子系统进行外部保护。虽然您不必将 KEYCLOAK 指定为 auth-method,但您仍然必须在 web.xml 中定义 security-constraints。但是,您不必创建 WEB-INF/keycloak.json 文件。元数据改为在 Red Hat Single Sign-On 子系统定义中的服务器配置(standalone.xml)中定义。

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

<profile>
  <subsystem xmlns="urn:jboss:domain:keycloak:1.1">
     <secure-deployment name="WAR MODULE NAME.war">
        <realm>demo</realm>
        <auth-server-url>http://localhost:8081/auth</auth-server-url>
        <ssl-required>external</ssl-required>
        <resource>customer-portal</resource>
        <credential name="secret">password</credential>
     </secure-deployment>
  </subsystem>
</profile>

secure-deployment name 属性标识您要保护的 WAR。其值是 web.xml 中定义的 module-name,并附加 .war。其余的配置与在 Java 适配器配置 中定义的 keycloak.json 配置选项对应一个。

例外是 凭证 元素。

为了便于您了解,您可以进入 Red Hat Single Sign-On 管理控制台,并转至与这个 WAR 一致的应用程序的 Client/Installation 选项卡。它提供了一个可以剪切和粘贴的 XML 文件示例。

如果您有多个由同一域保护的部署,您可以在单独的元素中共享域配置。例如:

<subsystem xmlns="urn:jboss:domain:keycloak:1.1">
    <realm name="demo">
        <auth-server-url>http://localhost:8080/auth</auth-server-url>
        <ssl-required>external</ssl-required>
    </realm>
    <secure-deployment name="customer-portal.war">
        <realm>demo</realm>
        <resource>customer-portal</resource>
        <credential name="secret">password</credential>
    </secure-deployment>
    <secure-deployment name="product-portal.war">
        <realm>demo</realm>
        <resource>product-portal</resource>
        <credential name="secret">password</credential>
    </secure-deployment>
    <secure-deployment name="database.war">
        <realm>demo</realm>
        <resource>database-service</resource>
        <bearer-only>true</bearer-only>
    </secure-deployment>
</subsystem>

2.1.3.4. 安全域

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

2.1.4. 从 RPM 安装 JBoss EAP 7 适配器

注意

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

先决条件

在可以从 RPM 安装 JBoss EAP 7 适配器之前,您必须订阅 JBoss EAP 7.4 存储库。

  • 确定使用 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

    对于 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

流程

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

    • 在 Red Hat Enterprise Linux 6 上安装 7:

      $ sudo yum install eap7-keycloak-adapter-sso7_6
    • 在 Red Hat Enterprise Linux 8 中安装:

      $ sudo dnf install eap7-keycloak-adapter-sso7_6
      注意

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

  2. 为 OIDC 模块运行安装脚本。

    $ $EAP_HOME/bin/jboss-cli.sh -c --file=$EAP_HOME/bin/adapter-install.cli

您的安装已完成。

2.1.5. 从 RPM 安装 JBoss EAP 6 适配器

注意

使用 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

流程

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

    $ sudo yum install keycloak-adapter-sso7_6-eap6
    注意

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

  2. 为 OIDC 模块运行安装脚本。

    $ $EAP_HOME/bin/jboss-cli.sh -c --file=$EAP_HOME/bin/adapter-install.cli

您的安装已完成。

2.1.6. JBoss Fuse 6 adapter

Red Hat Single Sign-On 支持保护在 JBoss Fuse 6 中运行的 Web 应用程序。

警告

唯一支持的 Fuse 6 版本是最新的版本。如果您使用早期版本的 Fuse 6,则某些功能可能无法正常工作。特别是 Hawtio 集成将不适用于早期版本的 Fuse 6。

Fuse 支持以下项目的安全性:

2.1.6.1. 保护 Fuse 6 中的 Web 应用程序

您必须首先安装 Red Hat Single Sign-On Karaf 功能。接下来,您需要根据您要保护的应用程序类型执行这些步骤。所有引用的 Web 应用程序都需要将 Red Hat Single Sign-On Jetty 验证器注入底层 Jetty 服务器。实现此操作的步骤取决于应用程序类型。详情如下所述。

2.1.6.2. 安装 Keycloak 功能

您必须首先在 JBoss Fuse 环境中安装 keycloak 功能。keycloak 功能包括 Fuse 适配器和所有第三方依赖项。您可以从 Maven 存储库或从存档安装它。

2.1.6.2.1. 从 Maven 存储库安装

先决条件

  • 您必须在线,并有权访问 Maven 存储库。
  • 对于 Red Hat Single Sign-On,配置适当的 Maven 存储库,以便您可以安装工件。如需更多信息,请参阅 JBoss Enterprise Maven 存储库 页面。

    假设 Maven 存储库为 https://maven.repository.redhat.com/ga/,将以下内容添加到 $FUSE_HOME/etc/org.ops4j.pax.url.mvn.cfg 文件中,并将存储库添加到支持的存储库列表中。例如:

     org.ops4j.pax.url.mvn.repositories= \
        https://maven.repository.redhat.com/ga/@id=redhat.product.repo
        http://repo1.maven.org/maven2@id=maven.central.repo, \
        ...

流程

  1. 启动 JBoss Fuse 6.3.0 Rollup 12
  2. 在 Karaf 终端类型中:

    features:addurl mvn:org.keycloak/keycloak-osgi-features/18.0.14.redhat-00001/xml/features
    features:install keycloak
  3. 您可能还需要安装 Jetty 9 功能:

    features:install keycloak-jetty9-adapter
  4. 确保已安装功能:

    features:list | grep keycloak
2.1.6.2.2. 从 ZIP 捆绑包安装

如果您离线或者不想使用 Maven 获取 JAR 文件和其他工件,则此安装选项很有用。

流程

  1. Sotware Downloads 站点下载 Red Hat Single Sign-On Fuse adapter ZIP 存档。
  2. 将它解压缩到 JBoss Fuse 的根目录中。然后,依赖项会在 系统 目录下安装。您可以覆盖所有现有 jar 文件。

    将其用于 JBoss Fuse 6.3.0 Rollup 12:

    cd /path-to-fuse/jboss-fuse-6.3.0.redhat-254
    unzip -q /path-to-adapter-zip/rh-sso-7.6.9-fuse-adapter.zip
  3. 启动 Fuse 并在 fuse/karaf 终端中运行这些命令:

    features:addurl mvn:org.keycloak/keycloak-osgi-features/18.0.14.redhat-00001/xml/features
    features:install keycloak
  4. 安装对应的 Jetty 适配器。由于工件直接在 JBoss Fuse 系统 目录中提供,因此您不需要使用 Maven 存储库。

2.1.6.3. 保护 Classic WAR 应用程序

流程

  1. /WEB-INF/web.xml 文件中,声明必要的:

    • <security-constraint> 元素中的安全限制
    • <login-config> 元素中的登录配置
    • <security-role> 元素中的安全角色。

      例如:

      <?xml version="1.0" encoding="UTF-8"?>
      <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>
      
          <welcome-file-list>
              <welcome-file>index.html</welcome-file>
          </welcome-file-list>
      
          <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>
          </security-constraint>
      
          <login-config>
              <auth-method>BASIC</auth-method>
              <realm-name>does-not-matter</realm-name>
          </login-config>
      
          <security-role>
              <role-name>admin</role-name>
          </security-role>
          <security-role>
              <role-name>user</role-name>
          </security-role>
      </web-app>
  2. 将带有验证器的 jetty-web.xml 文件添加到 /WEB-INF/jetty-web.xml 文件。

    例如:

    <?xml version="1.0"?>
    <!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN"
     "http://www.eclipse.org/jetty/configure_9_0.dtd">
    <Configure class="org.eclipse.jetty.webapp.WebAppContext">
        <Get name="securityHandler">
            <Set name="authenticator">
                <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
                </New>
            </Set>
        </Get>
    </Configure>
  3. 在 WAR 的 /WEB-INF/ 目录中,创建一个新文件 keycloak.json。此配置文件的格式在 Java Adapters Config 部分中进行了描述。也可以使此文件在外部可用,如 配置外部适配器 中所述
  4. 确保您的 WAR 应用程序导入 org.keycloak.adapters.jetty,并在 Import-Package 标头下导入 META-INF/MANIFEST.MF 文件中的一些软件包。在项目中使用 maven-bundle-plugin 可以正确地生成清单中的 OSGI 标头。请注意,软件包的"*"解析不会导入 org.keycloak.adapters.jetty 软件包,因为它不供应用程序或 Blueprint 或 Spring 描述符使用,而是在 jetty-web.xml 文件中使用。

    要导入的软件包列表可能类似如下:

    org.keycloak.adapters.jetty;version="18.0.14.redhat-00001",
    org.keycloak.adapters;version="18.0.14.redhat-00001",
    org.keycloak.constants;version="18.0.14.redhat-00001",
    org.keycloak.util;version="18.0.14.redhat-00001",
    org.keycloak.*;version="18.0.14.redhat-00001",
    *;resolution:=optional
2.1.6.3.1. 配置外部适配器

如果您不希望 keycloak.json 适配器配置文件捆绑在 WAR 应用程序内,但根据命名约定使外部和加载可用,请使用这个配置方法。

要启用这个功能,请将本节添加到您的 /WEB_INF/web.xml 文件中:

<context-param>
    <param-name>keycloak.config.resolver</param-name>
    <param-value>org.keycloak.adapters.osgi.PathBasedKeycloakConfigResolver</param-value>
</context-param>

该组件使用 keycloak.configkaraf.etc java 属性来搜索基本文件夹来定位配置。然后,在这些文件夹中搜索一个名为 < your_web_context>-keycloak.json 的文件。

例如,如果您的 Web 应用程序具有上下文 my-portal,则您的适配器配置会从 $FUSE_HOME/etc/my-portal-keycloak.json 文件加载。

2.1.6.4. 保护部署为 OSGI 服务的 servlet

如果您在 OSGI 捆绑的项目中有一个 servlet 类,但没有部署为典型的 WAR 应用,则可以使用这个方法。Fuse 使用 Pax Web Whiteboard expansioner 来部署如 web 应用程序的 servlet。

流程

  1. Red Hat Single Sign-On 提供 org.keycloak.adapters.osgi.undertow.PaxWebIntegrationService,它允许注入 jetty-web.xml 并为应用程序配置安全限制。您需要在应用程序的 OSGI-INF/blueprint/blueprint.xml 文件中声明这些服务。请注意,您的 servlet 需要依赖于它。配置示例:

    <?xml version="1.0" encoding="UTF-8"?>
    <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0
               http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
    
        <!-- Using jetty bean just for the compatibility with other fuse services -->
        <bean id="servletConstraintMapping" class="org.eclipse.jetty.security.ConstraintMapping">
            <property name="constraint">
                <bean class="org.eclipse.jetty.util.security.Constraint">
                    <property name="name" value="cst1"/>
                    <property name="roles">
                        <list>
                            <value>user</value>
                        </list>
                    </property>
                    <property name="authenticate" value="true"/>
                    <property name="dataConstraint" value="0"/>
                </bean>
            </property>
            <property name="pathSpec" value="/product-portal/*"/>
        </bean>
    
        <bean id="keycloakPaxWebIntegration" class="org.keycloak.adapters.osgi.PaxWebIntegrationService"
              init-method="start" destroy-method="stop">
            <property name="jettyWebXmlLocation" value="/WEB-INF/jetty-web.xml" />
            <property name="bundleContext" ref="blueprintBundleContext" />
            <property name="constraintMappings">
                <list>
                    <ref component-id="servletConstraintMapping" />
                </list>
            </property>
        </bean>
    
        <bean id="productServlet" class="org.keycloak.example.ProductPortalServlet" depends-on="keycloakPaxWebIntegration">
        </bean>
    
        <service ref="productServlet" interface="javax.servlet.Servlet">
            <service-properties>
                <entry key="alias" value="/product-portal" />
                <entry key="servlet-name" value="ProductServlet" />
                <entry key="keycloak.config.file" value="/keycloak.json" />
            </service-properties>
        </service>
    
    </blueprint>
    • 您可能需要在项目中具有 WEB-INF 目录(即使您的项目不是 Web 应用程序),并创建 /WEB-INF/jetty-web.xml/WEB-INF/keycloak.json 文件,如 Classic WAR 应用 部分中所示。请注意,您不需要 web.xml 文件,因为蓝图配置文件中声明 security-constraints。
  2. META-INF/MANIFEST.MF 中的 Import-Package 必须至少包含这些导入:

    org.keycloak.adapters.jetty;version="18.0.14.redhat-00001",
    org.keycloak.adapters;version="18.0.14.redhat-00001",
    org.keycloak.constants;version="18.0.14.redhat-00001",
    org.keycloak.util;version="18.0.14.redhat-00001",
    org.keycloak.*;version="18.0.14.redhat-00001",
    *;resolution:=optional

2.1.6.5. 保护 Apache Camel 应用程序

您可以通过添加带有 KeycloakJettyAuthenticator 的 securityHandler 并注入了正确的安全限制,来保护使用 camel-jetty etty 组件实施的 Apache Camel 端点。您可以使用类似配置将 OSGI-INF/blueprint/blueprint.xml 文件添加到 Camel 应用程序。角色、安全约束映射和 Red Hat Single Sign-On 适配器配置可能会根据您的环境和需求稍有不同。

例如:

<?xml version="1.0" encoding="UTF-8"?>

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:camel="http://camel.apache.org/schema/blueprint"
           xsi:schemaLocation="
       http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
       http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd">

    <bean id="kcAdapterConfig" class="org.keycloak.representations.adapters.config.AdapterConfig">
        <property name="realm" value="demo"/>
        <property name="resource" value="admin-camel-endpoint"/>
        <property name="bearerOnly" value="true"/>
        <property name="authServerUrl" value="http://localhost:8080/auth" />
        <property name="sslRequired" value="EXTERNAL"/>
    </bean>

    <bean id="keycloakAuthenticator" class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
        <property name="adapterConfig" ref="kcAdapterConfig"/>
    </bean>

    <bean id="constraint" class="org.eclipse.jetty.util.security.Constraint">
        <property name="name" value="Customers"/>
        <property name="roles">
            <list>
                <value>admin</value>
            </list>
        </property>
        <property name="authenticate" value="true"/>
        <property name="dataConstraint" value="0"/>
    </bean>

    <bean id="constraintMapping" class="org.eclipse.jetty.security.ConstraintMapping">
        <property name="constraint" ref="constraint"/>
        <property name="pathSpec" value="/*"/>
    </bean>

    <bean id="securityHandler" class="org.eclipse.jetty.security.ConstraintSecurityHandler">
        <property name="authenticator" ref="keycloakAuthenticator" />
        <property name="constraintMappings">
            <list>
                <ref component-id="constraintMapping" />
            </list>
        </property>
        <property name="authMethod" value="BASIC"/>
        <property name="realmName" value="does-not-matter"/>
    </bean>

    <bean id="sessionHandler" class="org.keycloak.adapters.jetty.spi.WrappingSessionHandler">
        <property name="handler" ref="securityHandler" />
    </bean>

    <bean id="helloProcessor" class="org.keycloak.example.CamelHelloProcessor" />

    <camelContext id="blueprintContext"
                  trace="false"
                  xmlns="http://camel.apache.org/schema/blueprint">
        <route id="httpBridge">
            <from uri="jetty:http://0.0.0.0:8383/admin-camel-endpoint?handlers=sessionHandler&amp;matchOnUriPrefix=true" />
            <process ref="helloProcessor" />
            <log message="The message from camel endpoint contains ${body}"/>
        </route>
    </camelContext>

</blueprint>
  • META-INF/MANIFEST.MF 中的 Import-Package 需要包含以下导入:
javax.servlet;version="[3,4)",
javax.servlet.http;version="[3,4)",
org.apache.camel.*,
org.apache.camel;version="[2.13,3)",
org.eclipse.jetty.security;version="[9,10)",
org.eclipse.jetty.server.nio;version="[9,10)",
org.eclipse.jetty.util.security;version="[9,10)",
org.keycloak.*;version="18.0.14.redhat-00001",
org.osgi.service.blueprint,
org.osgi.service.blueprint.container,
org.osgi.service.event,

2.1.6.6. Camel RestDSL

Camel RestDSL 是一个 Camel 功能,用于以流畅的方式定义您的 REST 端点。但是,您仍必须使用特定的实施类,并提供了有关如何与 Red Hat Single Sign-On 集成的说明。

配置集成机制的方法取决于您为其配置 RestDSL 路由的 Camel 组件。

以下示例演示了如何使用 Jetty 组件配置集成,并引用前面 Blueprint 示例中定义的某些 Bean。

<bean id="securityHandlerRest" class="org.eclipse.jetty.security.ConstraintSecurityHandler">
    <property name="authenticator" ref="keycloakAuthenticator" />
    <property name="constraintMappings">
        <list>
            <ref component-id="constraintMapping" />
        </list>
    </property>
    <property name="authMethod" value="BASIC"/>
    <property name="realmName" value="does-not-matter"/>
</bean>

<bean id="sessionHandlerRest" class="org.keycloak.adapters.jetty.spi.WrappingSessionHandler">
    <property name="handler" ref="securityHandlerRest" />
</bean>


<camelContext id="blueprintContext"
              trace="false"
              xmlns="http://camel.apache.org/schema/blueprint">

    <restConfiguration component="jetty" contextPath="/restdsl"
                       port="8484">
        <!--the link with Keycloak security handlers happens here-->
        <endpointProperty key="handlers" value="sessionHandlerRest"></endpointProperty>
        <endpointProperty key="matchOnUriPrefix" value="true"></endpointProperty>
    </restConfiguration>

    <rest path="/hello" >
        <description>Hello rest service</description>
        <get uri="/{id}" outType="java.lang.String">
            <description>Just an helllo</description>
            <to uri="direct:justDirect" />
        </get>

    </rest>

    <route id="justDirect">
        <from uri="direct:justDirect"/>
        <process ref="helloProcessor" />
        <log message="RestDSL correctly invoked ${body}"/>
        <setBody>
            <constant>(__This second sentence is returned from a Camel RestDSL endpoint__)</constant>
        </setBody>
    </route>

</camelContext>

2.1.6.7. 在单独的 Jetty 引擎上保护 Apache CXF 端点

流程

要在单独的 Jetty 引擎上运行由 Red Hat Single Sign-On 保护的 CXF 端点,请执行以下步骤。

  1. META-INF/spring/beans.xml 添加到应用程序中,并在其中声明 httpj:engine-factory with Jetty SecurityHandler with injected KeycloakJettyAuthenticator。CFX JAX-WS 应用的配置可能类似以下:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:jaxws="http://cxf.apache.org/jaxws"
           xmlns:httpj="http://cxf.apache.org/transports/http-jetty/configuration"
           xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
            http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd
            http://cxf.apache.org/transports/http-jetty/configuration http://cxf.apache.org/schemas/configuration/http-jetty.xsd">
    
        <import resource="classpath:META-INF/cxf/cxf.xml" />
    
        <bean id="kcAdapterConfig" class="org.keycloak.representations.adapters.config.AdapterConfig">
            <property name="realm" value="demo"/>
            <property name="resource" value="custom-cxf-endpoint"/>
            <property name="bearerOnly" value="true"/>
            <property name="authServerUrl" value="http://localhost:8080/auth" />
            <property name="sslRequired" value="EXTERNAL"/>
        </bean>
    
        <bean id="keycloakAuthenticator" class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
            <property name="adapterConfig">
                <ref local="kcAdapterConfig" />
            </property>
        </bean>
    
        <bean id="constraint" class="org.eclipse.jetty.util.security.Constraint">
            <property name="name" value="Customers"/>
            <property name="roles">
                <list>
                    <value>user</value>
                </list>
            </property>
            <property name="authenticate" value="true"/>
            <property name="dataConstraint" value="0"/>
        </bean>
    
        <bean id="constraintMapping" class="org.eclipse.jetty.security.ConstraintMapping">
            <property name="constraint" ref="constraint"/>
            <property name="pathSpec" value="/*"/>
        </bean>
    
        <bean id="securityHandler" class="org.eclipse.jetty.security.ConstraintSecurityHandler">
            <property name="authenticator" ref="keycloakAuthenticator" />
            <property name="constraintMappings">
                <list>
                    <ref local="constraintMapping" />
                </list>
            </property>
            <property name="authMethod" value="BASIC"/>
            <property name="realmName" value="does-not-matter"/>
        </bean>
    
        <httpj:engine-factory bus="cxf" id="kc-cxf-endpoint">
            <httpj:engine port="8282">
                <httpj:handlers>
                    <ref local="securityHandler" />
                </httpj:handlers>
                <httpj:sessionSupport>true</httpj:sessionSupport>
            </httpj:engine>
        </httpj:engine-factory>
    
        <jaxws:endpoint
                        implementor="org.keycloak.example.ws.ProductImpl"
                        address="http://localhost:8282/ProductServiceCF" depends-on="kc-cxf-endpoint" />
    
    </beans>

    对于 CXF JAX-RS 应用程序,唯一区别可能是取决于 engine-factory 的端点的配置:

    <jaxrs:server serviceClass="org.keycloak.example.rs.CustomerService" address="http://localhost:8282/rest"
        depends-on="kc-cxf-endpoint">
        <jaxrs:providers>
            <bean class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider" />
        </jaxrs:providers>
    </jaxrs:server>
  2. META-INF/MANIFEST.MF 中的 Import-Package 必须包含这些导入:
META-INF.cxf;version="[2.7,3.2)",
META-INF.cxf.osgi;version="[2.7,3.2)";resolution:=optional,
org.apache.cxf.bus;version="[2.7,3.2)",
org.apache.cxf.bus.spring;version="[2.7,3.2)",
org.apache.cxf.bus.resource;version="[2.7,3.2)",
org.apache.cxf.transport.http;version="[2.7,3.2)",
org.apache.cxf.*;version="[2.7,3.2)",
org.springframework.beans.factory.config,
org.eclipse.jetty.security;version="[9,10)",
org.eclipse.jetty.util.security;version="[9,10)",
org.keycloak.*;version="18.0.14.redhat-00001"

2.1.6.8. 在默认的 Jetty Engine 上保护 Apache CXF 端点

某些服务在启动时自动附带部署的 servlet。一个这样的服务是在 http://localhost:8181/cxf 上下文中运行的 CXF servlet。保护此类端点可能比较复杂。目前使用 Red Hat Single Sign-On 的一种方法是 ServletReregistrationService,它在启动时取消了一个内置 servlet,可让您在 Red Hat Single Sign-On 保护的上下文上重新部署。

应用程序中的配置文件 OSGI-INF/blueprint/blueprint.xml 可能类似以下。请注意,它会添加 JAX-RS customerservice 端点,该端点特定于您的应用程序,但更重要的是,可以保护整个 /cxf 上下文。

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:jaxrs="http://cxf.apache.org/blueprint/jaxrs"
           xsi:schemaLocation="
		http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
		http://cxf.apache.org/blueprint/jaxrs http://cxf.apache.org/schemas/blueprint/jaxrs.xsd">

    <!-- JAXRS Application -->

    <bean id="customerBean" class="org.keycloak.example.rs.CxfCustomerService" />

    <jaxrs:server id="cxfJaxrsServer" address="/customerservice">
        <jaxrs:providers>
            <bean class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider" />
        </jaxrs:providers>
        <jaxrs:serviceBeans>
            <ref component-id="customerBean" />
        </jaxrs:serviceBeans>
    </jaxrs:server>


    <!-- Securing of whole /cxf context by unregister default cxf servlet from paxweb and re-register with applied security constraints -->

    <bean id="cxfConstraintMapping" class="org.eclipse.jetty.security.ConstraintMapping">
        <property name="constraint">
            <bean class="org.eclipse.jetty.util.security.Constraint">
                <property name="name" value="cst1"/>
                <property name="roles">
                    <list>
                        <value>user</value>
                    </list>
                </property>
                <property name="authenticate" value="true"/>
                <property name="dataConstraint" value="0"/>
            </bean>
        </property>
        <property name="pathSpec" value="/cxf/*"/>
    </bean>

    <bean id="cxfKeycloakPaxWebIntegration" class="org.keycloak.adapters.osgi.PaxWebIntegrationService"
          init-method="start" destroy-method="stop">
        <property name="bundleContext" ref="blueprintBundleContext" />
        <property name="jettyWebXmlLocation" value="/WEB-INF/jetty-web.xml" />
        <property name="constraintMappings">
            <list>
                <ref component-id="cxfConstraintMapping" />
            </list>
        </property>
    </bean>

    <bean id="defaultCxfReregistration" class="org.keycloak.adapters.osgi.ServletReregistrationService" depends-on="cxfKeycloakPaxWebIntegration"
          init-method="start" destroy-method="stop">
        <property name="bundleContext" ref="blueprintBundleContext" />
        <property name="managedServiceReference">
            <reference interface="org.osgi.service.cm.ManagedService" filter="(service.pid=org.apache.cxf.osgi)" timeout="5000"  />
        </property>
    </bean>

</blueprint>

因此,在默认 CXF HTTP 目标上运行的所有其他 CXF 服务也受到保护。同样,当应用程序取消部署时,整个 /cxf 上下文也会变得不安全。因此,为您的应用程序使用您自己的 Jetty 引擎,如 在单独的 Jetty Engine 上安全 CXF 应用程序 中所述,您可以更好地控制每个应用程序的安全性。

  • WEB-INF 目录可能需要位于您的项目内(即使项目不是 Web 应用)。您可能还需要以类似 Classic WAR 应用 的方式编辑 /WEB-INF/jetty-web.xml/WEB-INF/keycloak.json 文件。请注意,您不需要 web.xml 文件,因为蓝图配置文件中声明安全限制。
  • META-INF/MANIFEST.MF 中的 Import-Package 必须包含以下导入:
META-INF.cxf;version="[2.7,3.2)",
META-INF.cxf.osgi;version="[2.7,3.2)";resolution:=optional,
org.apache.cxf.transport.http;version="[2.7,3.2)",
org.apache.cxf.*;version="[2.7,3.2)",
com.fasterxml.jackson.jaxrs.json;version="[2.5,3)",
org.eclipse.jetty.security;version="[9,10)",
org.eclipse.jetty.util.security;version="[9,10)",
org.keycloak.*;version="18.0.14.redhat-00001",
org.keycloak.adapters.jetty;version="18.0.14.redhat-00001",
*;resolution:=optional

2.1.6.9. 保护 Fuse 管理服务

2.1.6.9.1. 使用 SSH 身份验证到 Fuse Terminal

Red Hat Single Sign-On 主要解决 Web 应用程序身份验证的用例;但是,如果您的其他 Web 服务和应用程序通过红帽单点登录保护,则保护非 Web 管理服务(如使用红帽单点登录凭证的 SSH)是最佳选择。您可以使用 JAAS 登录模块进行此操作,该模块允许远程连接到 Red Hat Single Sign-On,并根据 Resource Owner Password 凭据验证凭证

要启用 SSH 身份验证,请执行以下步骤。

流程

  1. 在 Red Hat Single Sign-On 中创建一个客户端(例如,ssh-jmx-admin-client),它将用于 SSH 身份验证。此客户端需要选择 Direct Access Grants Enabled to On
  2. $FUSE_HOME/etc/org.apache.karaf.shell.cfg 文件中,更新或指定此属性:

    sshRealm=keycloak
  3. 添加 $FUSE_HOME/etc/keycloak-direct-access.json 文件,其内容类似于以下内容(基于您的环境和 Red Hat Single Sign-On 客户端设置):

    {
        "realm": "demo",
        "resource": "ssh-jmx-admin-client",
        "ssl-required" : "external",
        "auth-server-url" : "http://localhost:8080/auth",
        "credentials": {
            "secret": "password"
        }
    }

    此文件指定客户端应用程序配置,供 keycloak JAAS 域中的 JAAS DirectAccessGrantsLoginModule 用于 SSH 身份验证。

  4. 启动 Fuse 并安装 keycloak JAAS 域。最简单的方法是安装 keycloak-jaas 功能,该功能已预定义了 JAAS 域。您可以使用自己的 keycloak JAAS 域覆盖功能的预定义域。详情请查看 JBoss Fuse 文档

    在 Fuse 终端中使用这些命令:

    features:addurl mvn:org.keycloak/keycloak-osgi-features/18.0.14.redhat-00001/xml/features
    features:install keycloak-jaas
  5. 在终端中输入以下内容,以 admin 用户身份使用 SSH 登录:

    ssh -o PubkeyAuthentication=no -p 8101 admin@localhost
  6. 使用密码 password 登录。
注意

在稍后的一些操作系统中,您可能还需要使用 SSH 命令的 -o 选项 -o HostKeyAlgorithms=+ssh-dss =+ssh-dss,因为之后的 SSH 客户端不允许使用 ssh-dss 算法。但是,默认情况下,它目前在 JBoss Fuse 6.3.0 Rollup 12 中使用。

请注意,用户需要具有 realm 角色 admin 来执行所有操作或其他角色才能执行操作子集(例如,viewer 角色来限制用户仅运行只读 Karaf 命令)。可用的角色在 $FUSE_HOME/etc/org.apache.karaf.shell.cfg$FUSE_HOME/etc/system.properties 中配置。

2.1.6.9.2. 使用 JMX 身份验证

如果要使用 jconsole 或其他外部工具通过 RMI 远程连接到 JMX,则可能需要使用 JMX 身份验证。否则,最好使用 hawt.io/jolokia,因为 jolokia 代理默认安装在 hawt.io 中。如需了解更多详细信息,请参阅 Hawtio 管理控制台

流程

  1. $FUSE_HOME/etc/org.apache.karaf.management.cfg 文件中,将 jmxRealm 属性更改为:

    jmxRealm=keycloak
  2. 安装 keycloak-jaas 功能并配置 $FUSE_HOME/etc/keycloak-direct-access.json 文件,如上面的 SSH 部分所述。
  3. 在 jconsole 中,您可以使用 URL,例如:
service:jmx:rmi://localhost:44444/jndi/rmi://localhost:1099/karaf-root

和凭证:admin/password (基于您环境具有管理员特权的用户)。

2.1.6.10. 保护 Hawtio 管理控制台

要使用红帽单点登录来保护 Hawtio 管理控制台,请执行以下步骤。

流程

  1. 将这些属性添加到 $FUSE_HOME/etc/system.properties 文件中:

    hawtio.keycloakEnabled=true
    hawtio.realm=keycloak
    hawtio.keycloakClientConfig=file://${karaf.base}/etc/keycloak-hawtio-client.json
    hawtio.rolePrincipalClasses=org.keycloak.adapters.jaas.RolePrincipal,org.apache.karaf.jaas.boot.principal.RolePrincipal
  2. 在域的 Red Hat Single Sign-On 管理控制台中创建客户端。例如,在 Red Hat Single Sign-On 演示 域中,创建一个客户端 hawtio-client,将 public 指定为 Access Type,并指定指向 Hawtio: http://localhost:8181/hawtio/* 的重定向 URI。您还必须配置对应的 Web Origin (本例中为 http://localhost:8181)。
  3. 使用类似以下示例的内容,在 $FUSE_HOME/etc 目录中创建 keycloak-hawtio-client.json 文件。根据您的 Red Hat Single Sign-On 环境,更改 realmresourceauth-server-url 属性。resource 属性必须指向上一步中创建的客户端。此文件供客户端(Hawtio JavaScript 应用)侧使用。
{
  "realm" : "demo",
  "resource" : "hawtio-client",
  "auth-server-url" : "http://localhost:8080/auth",
  "ssl-required" : "external",
  "public-client" : true
}
  1. 使用类似以下示例的内容,在 $FUSE_HOME/etc dicrectory 中创建 keycloak-hawtio.json 文件。根据您的 Red Hat Single Sign-On 环境更改 realmauth-server-url 属性。此文件供服务器(JAAS Login 模块)侧使用。

    {
      "realm" : "demo",
      "resource" : "jaas",
      "bearer-only" : true,
      "auth-server-url" : "http://localhost:8080/auth",
      "ssl-required" : "external",
      "use-resource-role-mappings": false,
      "principal-attribute": "preferred_username"
    }
  2. 启动 JBoss Fuse 6.3.0 Rollup 12 并安装 keycloak 功能(如果您还没有这样做)。Karaf 终端中的命令类似以下示例:

    features:addurl mvn:org.keycloak/keycloak-osgi-features/18.0.14.redhat-00001/xml/features
    features:install keycloak
  3. 进入 http://localhost:8181/hawtio,以用户从 Red Hat Single Sign-On 域登录。

    请注意,用户需要具有正确的 realm 角色才能成功向 Hawtio 进行身份验证。可用的角色在 hawtio.roles 中的 $FUSE_HOME/etc/system.properties 文件中配置。

2.1.6.10.1. 在 JBoss EAP 6.4 上保护 Hawtio

先决条件

设置 Red Hat Single Sign-On,如 保护 Hawtio 管理控制台 中所述。假设:

  • 您有一个 Red Hat Single Sign-On realm demo 和 client hawtio-client
  • 您的 Red Hat Single Sign-On 在 localhost:8080上运行
  • 带有 Hawtio 的 JBoss EAP 6.4 服务器将在 localhost:8181 上运行。此服务器的目录在后续步骤中称为 $EAP_HOME

流程

  1. hawtio-wildfly-1.4.0.redhat-630396.war 存档复制到 $EAP_HOME/standalone/configuration 目录。有关部署 Hawtio 的详情,请查看 Fuse Hawtio 文档
  2. 将带有上述内容的 keycloak-hawtio.jsonkeycloak-hawtio-client.json 文件复制到 $EAP_HOME/standalone/configuration 目录。
  3. 将 Red Hat Single Sign-On adapter 子系统安装到 JBoss EAP 6.4 服务器,如 JBoss 适配器文档 所述。
  4. $EAP_HOME/standalone/configuration/standalone.xml 文件中,配置系统属性,如下例所示:

    <extensions>
    ...
    </extensions>
    
    <system-properties>
        <property name="hawtio.authenticationEnabled" value="true" />
        <property name="hawtio.realm" value="hawtio" />
        <property name="hawtio.roles" value="admin,viewer" />
        <property name="hawtio.rolePrincipalClasses" value="org.keycloak.adapters.jaas.RolePrincipal" />
        <property name="hawtio.keycloakEnabled" value="true" />
        <property name="hawtio.keycloakClientConfig" value="${jboss.server.config.dir}/keycloak-hawtio-client.json" />
        <property name="hawtio.keycloakServerConfig" value="${jboss.server.config.dir}/keycloak-hawtio.json" />
    </system-properties>
  5. 将 Hawtio 域添加到 security-domains 部分中的同一文件中:

    <security-domain name="hawtio" cache-type="default">
        <authentication>
            <login-module code="org.keycloak.adapters.jaas.BearerTokenLoginModule" flag="required">
                <module-option name="keycloak-config-file" value="${hawtio.keycloakServerConfig}"/>
            </login-module>
        </authentication>
    </security-domain>
  6. secure-deployment 部分 hawtio 添加到 adapter 子系统。这样可确保 Hawtio WAR 可以找到 JAAS 登录模块类。

    <subsystem xmlns="urn:jboss:domain:keycloak:1.1">
        <secure-deployment name="hawtio-wildfly-1.4.0.redhat-630396.war" />
    </subsystem>
  7. 使用 Hawtio 重启 JBoss EAP 6.4 服务器:

    cd $EAP_HOME/bin
    ./standalone.sh -Djboss.socket.binding.port-offset=101
  8. access Hawtio at http://localhost:8181/hawtio.它通过 Red Hat Single Sign-On 进行保护。

2.1.7. JBoss Fuse 7 Adapter

Red Hat Single Sign-On 支持保护在 JBoss Fuse 7 中运行的 Web 应用程序。

JBoss Fuse 7 利用 Undertow 适配器,与 JBoss EAP 7 适配器相同,JBoss Fuse 7.4.0 与 Undertow HTTP 引擎捆绑在一起,而 Undertow 则用于运行各种 Web 应用。

警告

唯一支持的 Fuse 7 版本是最新的版本。如果您使用早期版本的 Fuse 7,则某些功能可能无法正常工作。特别是,集成不适用于低于 7.12.0 的 Fuse 7 版本。

Fuse 支持以下项目的安全性:

  • 使用 Pax Web War 扩展程序在 Fuse 上部署的经典 WAR 应用程序
  • 使用 Pax Web Whiteboard Extender 在 Fuse 上部署的 servlets 作为 OSGI 服务,另外通过 org.osgi.service.http.HttpService#registerServlet ()进行注册,它是标准的 OSGi Enterprise HTTP Service
  • 使用 Camel Undertow 组件运行的 Apache Camel Undertow 端点
  • 在自己的独立 Undertow 引擎上运行 Apache CXF 端点
  • CXF servlet 提供的默认引擎上运行的 Apache CXF 端点
  • SSH 和 JMX 管理访问权限
  • Hawtio 管理控制台

2.1.7.1. 在 Fuse 7 中保护您的 Web 应用程序

您必须首先安装 Red Hat Single Sign-On Karaf 功能。接下来,您需要根据您要保护的应用程序类型执行这些步骤。所有引用的 Web 应用都需要将 Red Hat Single Sign-On Undertow 身份验证机制注入底层 Web 服务器。实现此操作的步骤取决于应用程序类型。详情如下所述。

2.1.7.2. 安装 Keycloak 功能

您必须首先在 JBoss Fuse 环境中安装 keycloak-pax-http-undertowkeycloak-jaas 功能。keycloak-pax-http-undertow 功能包括 Fuse 适配器和所有第三方依赖项。keycloak-jaas 包含用于 SSH 和 JMX 身份验证的域中使用的 JAAS 模块。您可以从 Maven 存储库或从存档安装它。

2.1.7.2.1. 从 Maven 存储库安装

先决条件

  • 您必须在线,并有权访问 Maven 存储库。
  • 对于 Red Hat Single Sign-On,配置适当的 Maven 存储库,以便您可以安装工件。如需更多信息,请参阅 JBoss Enterprise Maven 存储库 页面。
  • 假设 Maven 存储库为 https://maven.repository.redhat.com/ga/,将以下内容添加到 $FUSE_HOME/etc/org.ops4j.pax.url.mvn.cfg 文件中,并将存储库添加到支持的存储库列表中。例如:

    config:edit org.ops4j.pax.url.mvn
    config:property-append org.ops4j.pax.url.mvn.repositories ,https://maven.repository.redhat.com/ga/@id=redhat.product.repo
    config:update
    
    feature:repo-refresh

流程

  1. 启动 JBoss Fuse 7.4.0
  2. 在 Karaf 终端中,键入:

    feature:repo-add mvn:org.keycloak/keycloak-osgi-features/18.0.14.redhat-00001/xml/features
    feature:install keycloak-pax-http-undertow keycloak-jaas
  3. 您可能还需要安装 Undertow 功能:

    feature:install pax-web-http-undertow
  4. 确保已安装功能:

    feature:list | grep keycloak
2.1.7.2.2. 从 ZIP 捆绑包安装

如果您离线或者不想使用 Maven 获取 JAR 文件和其他工件,这非常有用。

流程

  1. Sotware Downloads 站点下载 Red Hat Single Sign-On Fuse adapter ZIP 存档。
  2. 将它解压缩到 JBoss Fuse 的根目录中。然后,依赖项会在 系统 目录下安装。您可以覆盖所有现有 jar 文件。

    将其用于 JBoss Fuse 7.4.0 :

    cd /path-to-fuse/fuse-karaf-7.z
    unzip -q /path-to-adapter-zip/rh-sso-7.6.9-fuse-adapter.zip
  3. 启动 Fuse 并在 fuse/karaf 终端中运行这些命令:

    feature:repo-add mvn:org.keycloak/keycloak-osgi-features/18.0.14.redhat-00001/xml/features
    feature:install keycloak-pax-http-undertow keycloak-jaas
  4. 安装对应的 Undertow 适配器。由于工件直接在 JBoss Fuse 系统 目录中提供,因此您不需要使用 Maven 存储库。

2.1.7.3. 保护 Classic WAR 应用程序

流程

  1. /WEB-INF/web.xml 文件中,声明必要的:

    • <security-constraint> 元素中的安全限制
    • <login-config> 元素中的登录配置。确保 < auth-method>KEYCLOAK
    • <security-role> 元素中的安全角色

      例如:

      <?xml version="1.0" encoding="UTF-8"?>
      <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>
      
          <welcome-file-list>
              <welcome-file>index.html</welcome-file>
          </welcome-file-list>
      
          <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>
          </security-constraint>
      
          <login-config>
              <auth-method>KEYCLOAK</auth-method>
              <realm-name>does-not-matter</realm-name>
          </login-config>
      
          <security-role>
              <role-name>admin</role-name>
          </security-role>
          <security-role>
              <role-name>user</role-name>
          </security-role>
      </web-app>
  2. 在 WAR 的 /WEB-INF/ 目录中,创建一个新文件 keycloak.json。此配置文件的格式在 Java Adapters Config 部分中进行了描述。也可以使此文件在外部可用,如 配置外部适配器 中所述

    例如:

    {
        "realm": "demo",
        "resource": "customer-portal",
        "auth-server-url": "http://localhost:8080/auth",
        "ssl-required" : "external",
        "credentials": {
            "secret": "password"
        }
    }
  3. 与 Fuse 6 适配器不同,MANIFEST.MF 中不需要特殊的 OSGi 导入。
2.1.7.3.1. 配置解析器

keycloak.json 适配器配置文件可以存储在捆绑包中,该捆绑包是默认的行为,或者存储在文件系统的目录中。要指定配置文件的实际源,请将 keycloak.config.resolver 部署参数设置为所需的配置解析器类。例如,在典型的 WAR 应用程序中,在 web.xml 文件中设置 keycloak.config.resolver 上下文参数,如下所示:

<context-param>
    <param-name>keycloak.config.resolver</param-name>
    <param-value>org.keycloak.adapters.osgi.PathBasedKeycloakConfigResolver</param-value>
</context-param>

以下解析器可用于 keycloak.config.resolver

org.keycloak.adapters.osgi.BundleBasedKeycloakConfigResolver
这是默认的解析器。该配置文件预期在 OSGi 捆绑包内受到保护。默认情况下,它会加载名为 WEB-INF/keycloak.json 的文件,但可通过 configLocation 属性配置此文件名。
org.keycloak.adapters.osgi.PathBasedKeycloakConfigResolver

此解析器在由 keycloak.config 系统属性指定的文件夹中搜索名为 & lt;your_web_context>-keycloak.json 的文件。如果没有设置 keycloak.config,则会使用 karaf.etc 系统属性。

例如,如果您的 Web 应用程序部署到上下文 my-portal 中,则您的适配器配置将从 ${keycloak.config}/my-portal-keycloak.json 文件加载,或者从 ${karaf.etc}/my-portal-keycloak.json 文件加载。

org.keycloak.adapters.osgi.HierarchicalPathBasedKeycloakConfigResolver

这个解析器与上述 PathBasedKeycloakConfigResolver 类似,其中给定 URI 路径,配置位置是从最到最具体的特定检查。

例如,对于 /my/web-app/context URI,会搜索以下配置位置是否存在,直到第一个位置存在:

  • ${karaf.etc}/my-web-app-context-keycloak.json
  • ${karaf.etc}/my-web-app-keycloak.json
  • ${karaf.etc}/my-keycloak.json
  • ${karaf.etc}/keycloak.json

2.1.7.4. 保护部署为 OSGI 服务的 servlet

如果您在 OSGI 捆绑的项目中有一个 servlet 类,但没有部署为典型的 WAR 应用,则可以使用这个方法。Fuse 使用 Pax Web Whiteboard expansioner 来部署如 web 应用程序的 servlet。

流程

  1. Red Hat Single Sign-On 提供 org.keycloak.adapters.osgi.undertow.PaxWebIntegrationService,它允许为您的应用程序配置身份验证方法和安全限制。您需要在应用程序的 OSGI-INF/blueprint/blueprint.xml 文件中声明这些服务。请注意,您的 servlet 需要依赖于它。配置示例:

    <?xml version="1.0" encoding="UTF-8"?>
    <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
    
        <bean id="servletConstraintMapping" class="org.keycloak.adapters.osgi.PaxWebSecurityConstraintMapping">
            <property name="roles">
                <list>
                    <value>user</value>
                </list>
            </property>
            <property name="authentication" value="true"/>
            <property name="url" value="/product-portal/*"/>
        </bean>
    
        <!-- This handles the integration and setting the login-config and security-constraints parameters -->
        <bean id="keycloakPaxWebIntegration" class="org.keycloak.adapters.osgi.undertow.PaxWebIntegrationService"
              init-method="start" destroy-method="stop">
            <property name="bundleContext" ref="blueprintBundleContext" />
            <property name="constraintMappings">
                <list>
                    <ref component-id="servletConstraintMapping" />
                </list>
            </property>
        </bean>
    
        <bean id="productServlet" class="org.keycloak.example.ProductPortalServlet" depends-on="keycloakPaxWebIntegration" />
    
        <service ref="productServlet" interface="javax.servlet.Servlet">
            <service-properties>
                <entry key="alias" value="/product-portal" />
                <entry key="servlet-name" value="ProductServlet" />
                <entry key="keycloak.config.file" value="/keycloak.json" />
            </service-properties>
        </service>
    </blueprint>

    您可能需要在项目中具有 WEB-INF 目录(即使您的项目不是 Web 应用程序),并创建 /WEB-INF/keycloak.json 文件,如 Classic WAR application 部分所述。请注意,您不需要 web.xml 文件,因为蓝图配置文件中声明 security-constraints。

  2. 与 Fuse 6 适配器不同,MANIFEST.MF 中不需要特殊的 OSGi 导入。

2.1.7.5. 保护 Apache Camel 应用程序

您可以通过蓝图注入正确的安全限制并将已使用组件更新至 undertow-keycloak 来保护使用 camel-undertow 组件的 Apache Camel 端点。您必须使用类似配置将 OSGI-INF/blueprint/blueprint.xml 文件添加到 Camel 应用程序。角色、安全约束映射和适配器配置可能会根据您的环境和需求稍有不同。

与标准的 undertow 组件相比,undertow-keycloak 组件添加了两个新属性:

  • configResolver 是一个解析器 bean,提供 Red Hat Single Sign-On 适配器配置。可用的解析器列在 Configuration Resolvers 部分中。
  • allowedRoles 是以逗号分隔的角色列表。访问该服务的用户必须至少具有允许访问的角色。

例如:

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:camel="http://camel.apache.org/schema/blueprint"
           xsi:schemaLocation="
       http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
       http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint-2.17.1.xsd">

    <bean id="keycloakConfigResolver" class="org.keycloak.adapters.osgi.BundleBasedKeycloakConfigResolver" >
        <property name="bundleContext" ref="blueprintBundleContext" />
    </bean>

    <bean id="helloProcessor" class="org.keycloak.example.CamelHelloProcessor" />

    <camelContext id="blueprintContext"
                  trace="false"
                  xmlns="http://camel.apache.org/schema/blueprint">

        <route id="httpBridge">
            <from uri="undertow-keycloak:http://0.0.0.0:8383/admin-camel-endpoint?matchOnUriPrefix=true&amp;configResolver=#keycloakConfigResolver&amp;allowedRoles=admin" />
            <process ref="helloProcessor" />
            <log message="The message from camel endpoint contains ${body}"/>
        </route>

    </camelContext>

</blueprint>
  • META-INF/MANIFEST.MF 中的 Import-Package 需要包含以下导入:
javax.servlet;version="[3,4)",
javax.servlet.http;version="[3,4)",
javax.net.ssl,
org.apache.camel.*,
org.apache.camel;version="[2.13,3)",
io.undertow.*,
org.keycloak.*;version="18.0.14.redhat-00001",
org.osgi.service.blueprint,
org.osgi.service.blueprint.container

2.1.7.6. Camel RestDSL

Camel RestDSL 是一个 Camel 功能,用于以流畅的方式定义您的 REST 端点。但是,您仍必须使用特定的实施类,并提供了有关如何与 Red Hat Single Sign-On 集成的说明。

配置集成机制的方法取决于您为其配置 RestDSL 路由的 Camel 组件。

以下示例演示了如何使用 undertow-keycloak 组件配置集成,并引用前面 Blueprint 示例中定义的一些 Bean。

<camelContext id="blueprintContext"
              trace="false"
              xmlns="http://camel.apache.org/schema/blueprint">

    <!--the link with Keycloak security handlers happens by using undertow-keycloak component -->
    <restConfiguration apiComponent="undertow-keycloak" contextPath="/restdsl" port="8484">
        <endpointProperty key="configResolver" value="#keycloakConfigResolver" />
        <endpointProperty key="allowedRoles" value="admin,superadmin" />
    </restConfiguration>

    <rest path="/hello" >
        <description>Hello rest service</description>
        <get uri="/{id}" outType="java.lang.String">
            <description>Just a hello</description>
            <to uri="direct:justDirect" />
        </get>

    </rest>

    <route id="justDirect">
        <from uri="direct:justDirect"/>
        <process ref="helloProcessor" />
        <log message="RestDSL correctly invoked ${body}"/>
        <setBody>
            <constant>(__This second sentence is returned from a Camel RestDSL endpoint__)</constant>
        </setBody>
    </route>

</camelContext>

2.1.7.7. 在单独的 Undertow Engine 上保护 Apache CXF 端点

要在单独的 Undertow 引擎上运行由 Red Hat Single Sign-On 保护的 CXF 端点,请执行以下步骤。

流程

  1. OSGI-INF/blueprint/blueprint.xml 添加到应用程序中,并在其中添加类似于 Camel 配置的 正确配置解析器 Bean。在 httpu:engine-factory 中,使用 camel 配置声明 org.keycloak.adapters.osgi.undertow.CxfKeycloakAuthHandler 处理程序。CFX JAX-WS 应用的配置可能类似以下:

    <?xml version="1.0" encoding="UTF-8"?>
    <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:jaxws="http://cxf.apache.org/blueprint/jaxws"
               xmlns:cxf="http://cxf.apache.org/blueprint/core"
               xmlns:httpu="http://cxf.apache.org/transports/http-undertow/configuration".
               xsi:schemaLocation="
          http://cxf.apache.org/transports/http-undertow/configuration http://cxf.apache.org/schemas/configuration/http-undertow.xsd
          http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd
          http://cxf.apache.org/blueprint/jaxws http://cxf.apache.org/schemas/blueprint/jaxws.xsd">
    
        <bean id="keycloakConfigResolver" class="org.keycloak.adapters.osgi.BundleBasedKeycloakConfigResolver" >
            <property name="bundleContext" ref="blueprintBundleContext" />
        </bean>
    
        <httpu:engine-factory bus="cxf" id="kc-cxf-endpoint">
            <httpu:engine port="8282">
                <httpu:handlers>
                    <bean class="org.keycloak.adapters.osgi.undertow.CxfKeycloakAuthHandler">
                        <property name="configResolver" ref="keycloakConfigResolver" />
                    </bean>
                </httpu:handlers>
            </httpu:engine>
        </httpu:engine-factory>
    
        <jaxws:endpoint implementor="org.keycloak.example.ws.ProductImpl"
                        address="http://localhost:8282/ProductServiceCF" depends-on="kc-cxf-endpoint"/>
    
    </blueprint>

    对于 CXF JAX-RS 应用程序,唯一区别可能是取决于 engine-factory 的端点的配置:

    <jaxrs:server serviceClass="org.keycloak.example.rs.CustomerService" address="http://localhost:8282/rest"
        depends-on="kc-cxf-endpoint">
        <jaxrs:providers>
            <bean class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider" />
        </jaxrs:providers>
    </jaxrs:server>
  2. META-INF/MANIFEST.MF 中的 Import-Package 必须包含这些导入:
META-INF.cxf;version="[2.7,3.3)",
META-INF.cxf.osgi;version="[2.7,3.3)";resolution:=optional,
org.apache.cxf.bus;version="[2.7,3.3)",
org.apache.cxf.bus.spring;version="[2.7,3.3)",
org.apache.cxf.bus.resource;version="[2.7,3.3)",
org.apache.cxf.transport.http;version="[2.7,3.3)",
org.apache.cxf.*;version="[2.7,3.3)",
org.springframework.beans.factory.config,
org.keycloak.*;version="18.0.14.redhat-00001"

2.1.7.8. 在默认的 Undertow Engine 上保护 Apache CXF 端点

某些服务在启动时自动附带部署的 servlet。一个这样的服务是在 http://localhost:8181/cxf 上下文中运行的 CXF servlet。Fuse 的 Pax Web 支持通过配置管理员更改现有上下文。这可用于保护 Red Hat Single Sign-On 的端点。

应用程序中的配置文件 OSGI-INF/blueprint/blueprint.xml 可能类似以下。请注意,它会添加 JAX-RS customerservice 端点,该端点特定于您的应用。

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:jaxrs="http://cxf.apache.org/blueprint/jaxrs"
           xsi:schemaLocation="
		http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
		http://cxf.apache.org/blueprint/jaxrs http://cxf.apache.org/schemas/blueprint/jaxrs.xsd">

    <!-- JAXRS Application -->
    <bean id="customerBean" class="org.keycloak.example.rs.CxfCustomerService" />

    <jaxrs:server id="cxfJaxrsServer" address="/customerservice">
        <jaxrs:providers>
            <bean class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider" />
        </jaxrs:providers>
        <jaxrs:serviceBeans>
            <ref component-id="customerBean" />
        </jaxrs:serviceBeans>
    </jaxrs:server>
</blueprint>

此外,您必须创建 ${karaf.etc}/org.ops4j.pax.web.context-anyName.cfg 文件。它将被视为由 pax-web-runtime 捆绑包跟踪的工厂 PID 配置。这种配置可能包含与标准 web.xml 的一些属性对应的以下属性:

bundle.symbolicName = org.apache.cxf.cxf-rt-transports-http
context.id = default

context.param.keycloak.config.resolver = org.keycloak.adapters.osgi.HierarchicalPathBasedKeycloakConfigResolver

login.config.authMethod = KEYCLOAK

security.cxf.url = /cxf/customerservice/*
security.cxf.roles = admin, user

有关配置管理文件中可用属性的完整描述,请参阅 Fuse 文档。以上属性的含义如下:

bundle.symbolicName and context.id
org.ops4j.pax.web.service.WebContainer 中识别捆绑包及其部署上下文。
context.param.keycloak.config.resolver
为捆绑包提供 keycloak.config.resolver 上下文参数的值,与 web.xml 中的 classic WARs 相同。在 Configuration Resolvers 部分中描述了可用的解析器。
login.config.authMethod
身份验证方法.必须是 KEYCLOAK
security.anyName.urlsecurity.anyName.roles

单个安全约束的属性值,就像在 web.xml 中的 security-constraint/web-resource-collection/url-patternsecurity-constraint/auth-constraint/role-name 中设置一样。角色通过逗号和空格分开。anyName 标识符可以是任意的,但必须为同一安全约束的独立属性匹配。

注意

有些 Fuse 版本包含一个程序漏洞,它要求角色用 ", " (comma 和 single space)分开。确保您使用精确使用此表示法来分隔角色。

META-INF/MANIFEST.MF 中的 Import-Package 必须至少包含这些导入:

javax.ws.rs;version="[2,3)",
META-INF.cxf;version="[2.7,3.3)",
META-INF.cxf.osgi;version="[2.7,3.3)";resolution:=optional,
org.apache.cxf.transport.http;version="[2.7,3.3)",
org.apache.cxf.*;version="[2.7,3.3)",
com.fasterxml.jackson.jaxrs.json;version="${jackson.version}"

2.1.7.9. 保护 Fuse 管理服务

2.1.7.9.1. 使用 SSH 身份验证到 Fuse Terminal

Red Hat Single Sign-On 主要解决 Web 应用程序身份验证的用例;但是,如果您的其他 Web 服务和应用程序通过红帽单点登录保护,则保护非 Web 管理服务(如使用红帽单点登录凭证的 SSH)是最佳选择。您可以使用 JAAS 登录模块进行此操作,该模块允许远程连接到 Red Hat Single Sign-On,并根据 Resource Owner Password 凭据验证凭证

要启用 SSH 身份验证,请执行以下步骤。

流程

  1. 在 Red Hat Single Sign-On 中创建一个客户端(例如,ssh-jmx-admin-client),它将用于 SSH 身份验证。此客户端需要选择 Direct Access Grants Enabled to On
  2. $FUSE_HOME/etc/org.apache.karaf.shell.cfg 文件中,更新或指定此属性:

    sshRealm=keycloak
  3. 添加 $FUSE_HOME/etc/keycloak-direct-access.json 文件,其内容类似于以下内容(基于您的环境和 Red Hat Single Sign-On 客户端设置):

    {
        "realm": "demo",
        "resource": "ssh-jmx-admin-client",
        "ssl-required" : "external",
        "auth-server-url" : "http://localhost:8080/auth",
        "credentials": {
            "secret": "password"
        }
    }

    此文件指定客户端应用程序配置,供 keycloak JAAS 域中的 JAAS DirectAccessGrantsLoginModule 用于 SSH 身份验证。

  4. 启动 Fuse 并安装 keycloak JAAS 域。最简单的方法是安装 keycloak-jaas 功能,该功能已预定义了 JAAS 域。您可以使用自己的 keycloak JAAS 域覆盖功能的预定义域。详情请查看 JBoss Fuse 文档

    在 Fuse 终端中使用这些命令:

    features:addurl mvn:org.keycloak/keycloak-osgi-features/18.0.14.redhat-00001/xml/features
    features:install keycloak-jaas
  5. 在终端中输入以下内容,以 admin 用户身份使用 SSH 登录:

    ssh -o PubkeyAuthentication=no -p 8101 admin@localhost
  6. 使用密码 password 登录。
注意

在稍后的一些操作系统中,您可能还需要使用 SSH 命令的 -o 选项 -o HostKeyAlgorithms=+ssh-dss =+ssh-dss,因为之后的 SSH 客户端不允许使用 ssh-dss 算法。但是,默认情况下,它目前在 JBoss Fuse 7.4.0 中使用。

请注意,用户需要具有 realm 角色 admin 来执行所有操作或其他角色才能执行操作子集(例如,viewer 角色来限制用户仅运行只读 Karaf 命令)。可用的角色在 $FUSE_HOME/etc/org.apache.karaf.shell.cfg$FUSE_HOME/etc/system.properties 中配置。

2.1.7.9.2. 使用 JMX 身份验证

如果要使用 jconsole 或其他外部工具通过 RMI 远程连接到 JMX,则可能需要使用 JMX 身份验证。否则,最好使用 hawt.io/jolokia,因为 jolokia 代理默认安装在 hawt.io 中。如需了解更多详细信息,请参阅 Hawtio 管理控制台

要使用 JMX 身份验证,请执行以下步骤。

流程

  1. $FUSE_HOME/etc/org.apache.karaf.management.cfg 文件中,将 jmxRealm 属性更改为:

    jmxRealm=keycloak
  2. 安装 keycloak-jaas 功能并配置 $FUSE_HOME/etc/keycloak-direct-access.json 文件,如上面的 SSH 部分所述。
  3. 在 jconsole 中,您可以使用 URL,例如:
service:jmx:rmi://localhost:44444/jndi/rmi://localhost:1099/karaf-root

和凭证:admin/password (基于您环境具有管理员特权的用户)。

2.1.7.10. 保护 Hawtio 管理控制台

要使用红帽单点登录来保护 Hawtio 管理控制台,请执行以下步骤。

流程

  1. 在域的 Red Hat Single Sign-On 管理控制台中创建客户端。例如,在 Red Hat Single Sign-On 演示 域中,创建一个客户端 hawtio-client,将 public 指定为 Access Type,并指定指向 Hawtio: http://localhost:8181/hawtio/* 的重定向 URI。配置对应的 Web Origin (本例中为 http://localhost:8181)。设置客户端范围映射,以在 hawtio-client 客户端详情的 Scope 选项卡中包括 view-profile 客户端角色。
  2. 使用类似以下示例的内容,在 $FUSE_HOME/etc 目录中创建 keycloak-hawtio-client.json 文件。根据您的 Red Hat Single Sign-On 环境,更改 realmresourceauth-server-url 属性。resource 属性必须指向上一步中创建的客户端。此文件供客户端(Hawtio JavaScript 应用)侧使用。

    {
      "realm" : "demo",
      "clientId" : "hawtio-client",
      "url" : "http://localhost:8080/auth",
      "ssl-required" : "external",
      "public-client" : true
    }
  3. 使用类似以下示例的内容,在 $FUSE_HOME/etc 目录中创建 keycloak-direct-access.json 文件。根据您的红帽单点登录环境更改 realmurl 属性。此文件供 JavaScript 客户端使用。

    {
      "realm" : "demo",
      "resource" : "ssh-jmx-admin-client",
      "auth-server-url" : "http://localhost:8080/auth",
      "ssl-required" : "external",
      "credentials": {
        "secret": "password"
      }
    }
  4. 使用类似以下示例的内容,在 $FUSE_HOME/etc dicrectory 中创建 keycloak-hawtio.json 文件。根据您的 Red Hat Single Sign-On 环境更改 realmauth-server-url 属性。此文件供服务器(JAAS Login 模块)侧使用。

    {
      "realm" : "demo",
      "resource" : "jaas",
      "bearer-only" : true,
      "auth-server-url" : "http://localhost:8080/auth",
      "ssl-required" : "external",
      "use-resource-role-mappings": false,
      "principal-attribute": "preferred_username"
    }
  5. 启动 JBoss Fuse 7.4.0,安装 Keycloak 功能。然后,在 Karaf 终端中输入:

    system:property -p hawtio.keycloakEnabled true
    system:property -p hawtio.realm keycloak
    system:property -p hawtio.keycloakClientConfig file://\${karaf.base}/etc/keycloak-hawtio-client.json
    system:property -p hawtio.rolePrincipalClasses org.keycloak.adapters.jaas.RolePrincipal,org.apache.karaf.jaas.boot.principal.RolePrincipal
    restart io.hawt.hawtio-war
  6. 进入 http://localhost:8181/hawtio,以用户从 Red Hat Single Sign-On 域登录。

    请注意,用户需要具有正确的 realm 角色才能成功向 Hawtio 进行身份验证。可用的角色在 hawtio.roles 中的 $FUSE_HOME/etc/system.properties 文件中配置。

2.1.8. Spring Boot adapter

注意

Spring Boot Adapter 已被弃用,它不包括在 8.0 及更高版本和更高版本的 RH-SSO 版本中。此适配器将在 RH-SSO 7.x 生命周期中维护。用户应迁移到 Spring Security,以便将其 Spring Boot 应用程序与 RH-SSO 集成。

2.1.8.1. 安装 Spring Boot 适配器

为了保护 Spring Boot 应用程序的安全性,您必须将 Keycloak Spring Boot adapter JAR 添加到应用程序中。然后,您必须通过正常的 Spring Boot 配置(application.properties)提供一些额外的配置。

Keycloak Spring Boot 适配器利用 Spring Boot 的自动配置,因此所有您需要做的都是将这个适配器 Keycloak Spring Boot starter 添加到项目中。

流程

  1. 要使用 Maven 将初学者添加到项目中,请添加到您的依赖项中:

    <dependency>
        <groupId>org.keycloak</groupId>
        <artifactId>keycloak-spring-boot-starter</artifactId>
    </dependency>
  2. 添加 Adapter BOM 依赖项:

    <dependencyManagement>
      <dependencies>
        <dependency>
          <groupId>org.keycloak.bom</groupId>
          <artifactId>keycloak-adapter-bom</artifactId>
          <version>18.0.14.redhat-00001</version>
          <type>pom</type>
          <scope>import</scope>
        </dependency>
      </dependencies>
    </dependencyManagement>

目前,以下嵌入式容器被支持,在使用 Starter 时不需要任何额外的依赖项:

  • tomcat
  • Undertow
  • Jetty

2.1.8.2. 配置 Spring Boot Adapter

使用流程将 Spring Boot 应用程序配置为使用 Red Hat Single Sign-On。

流程

  1. 您不是 keycloak.json 文件,而是通过正常的 Spring Boot 配置为 Spring Boot 适配器配置域。例如:

    keycloak.realm = demorealm
    keycloak.auth-server-url = http://127.0.0.1:8080/auth
    keycloak.ssl-required = external
    keycloak.resource = demoapp
    keycloak.credentials.secret = 11111111-1111-1111-1111-111111111111
    keycloak.use-resource-role-mappings = true

    您可以通过设置 keycloak.enabled = false 来禁用 Keycloak Spring Boot Adapter(例如在测试中)。

  2. 要配置 Policy Enforcer,与 keycloak.json 不同,请使用 policy-enforcer-config 而不是只是 policy-enforcer
  3. 指定通常在 web.xml 中的 Jakarta EE 安全配置。

    Spring Boot Adapter 将 login-method 设置为 KEYCLOAK,并在启动时配置 security-constraints。以下是配置示例:

    keycloak.securityConstraints[0].authRoles[0] = admin
    keycloak.securityConstraints[0].authRoles[1] = user
    keycloak.securityConstraints[0].securityCollections[0].name = insecure stuff
    keycloak.securityConstraints[0].securityCollections[0].patterns[0] = /insecure
    
    keycloak.securityConstraints[1].authRoles[0] = admin
    keycloak.securityConstraints[1].securityCollections[0].name = admin stuff
    keycloak.securityConstraints[1].securityCollections[0].patterns[0] = /admin
警告

如果您计划将 Spring 应用程序部署为 WAR,则不应使用 Spring Boot Adapter,并将专用适配器用于应用服务器或 servlet 容器。您的 Spring Boot 还应包含 web.xml 文件。

2.1.9. Java servlet 过滤器适配器

如果要在没有选择使用 servlet 过滤器适配器的平台上部署 Java Servlet 应用程序。这个适配器的工作方式与其它适配器不同。您不会在 web.xml 中定义安全限制。反之,您可以使用 Red Hat Single Sign-On servlet 过滤器适配器定义一个过滤器映射来保护您要保护的 url 模式。

警告

Backchannel logout 与标准适配器不同。它将会话 ID 标记为已注销,而不是无效的 HTTP 会话。无法基于会话 ID 使 HTTP 会话无效。

<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>application</module-name>

    <filter>
        <filter-name>Keycloak Filter</filter-name>
        <filter-class>org.keycloak.adapters.servlet.KeycloakOIDCFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>Keycloak Filter</filter-name>
        <url-pattern>/keycloak/*</url-pattern>
        <url-pattern>/protected/*</url-pattern>
    </filter-mapping>
</web-app>

在上面的代码段中有两个 url-patterns。/ protected/* 是我们需要保护的文件,而 /keycloak/* url-pattern 处理来自 Red Hat Single Sign-On 服务器的回调。

如果您需要排除配置的 url-patterns 下的一些路径,您可以使用 Filter init-param keycloak.config.skipPattern 配置正则表达式,该正则表达式描述了 keycloak 过滤器应立即委派给 filter-chain。默认情况下不配置 skipPattern。

在没有 context-path 的情况下,与 requestURI 匹配模式。假定上下文路径 /myapp 是一个对 /myapp/index.html 的请求,它会根据跳过特征匹配 /index.html

<init-param>
    <param-name>keycloak.config.skipPattern</param-name>
    <param-value>^/(path1|path2|path3).*</param-value>
</init-param>

请注意,您应该在 Red Hat Single Sign-On Admin 控制台中配置您的客户端,其 Admin URL 指向过滤器的 url-pattern 所涵盖的安全部分。

Admin URL 将回调到 Admin URL,以便执行(如 backchannel logout)的操作。因此,本例中的 Admin URL 应为 http[s]://hostname/{context-root}/keycloak

如果您需要自定义会话 ID 映射器,您可以在 Filter init-param keycloak.config.idMapper 中配置类的完全限定名称。会话 ID 映射器是一个映射用户 ID 和会话 ID 的映射程序。默认配置了 org.keycloak.adapters.spi.InMemorySessionIdMapper。

<init-param>
    <param-name>keycloak.config.idMapper</param-name>
    <param-value>org.keycloak.adapters.spi.InMemorySessionIdMapper</param-value>
</init-param>

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

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

<dependency>
    <groupId>org.keycloak</groupId>
    <artifactId>keycloak-servlet-filter-adapter</artifactId>
    <version>18.0.14.redhat-00001</version>
</dependency>

2.1.10. 安全上下文

如果您需要直接访问令牌,可以使用 KeycloakSecurityContext 接口。如果您要从令牌(如用户配置集信息)检索其他详细信息,或者您想要调用受 Red Hat Single Sign-On 保护的 RESTful 服务,这可能很有用。

在 servlet 环境中,它作为 HttpServletRequest 中的属性在安全调用中可用:

httpServletRequest
    .getAttribute(KeycloakSecurityContext.class.getName());

或者,它位于 HttpSession 中不安全的请求:

httpServletRequest.getSession()
    .getAttribute(KeycloakSecurityContext.class.getName());

2.1.11. 错误处理

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

<error-page>
    <error-code>403</error-code>
    <location>/ErrorHandler</location>
</error-page>

Red Hat Single Sign-On 还设置可检索的 HttpServletRequest 属性。属性名称是 org.keycloak.adapters.spi.AuthenticationError,它应该被转换为 org.keycloak.adapters.OIDCAuthenticationError

例如:

import org.keycloak.adapters.OIDCAuthenticationError;
import org.keycloak.adapters.OIDCAuthenticationError.Reason;
...

OIDCAuthenticationError error = (OIDCAuthenticationError) httpServletRequest
    .getAttribute('org.keycloak.adapters.spi.AuthenticationError');

Reason reason = error.getReason();
System.out.println(reason.name());

2.1.12. 退出

您可以通过多种方式从 Web 应用程序注销。对于 Jakarta EE servlet 容器,您可以调用 HttpServletRequest.logout()。对于其他浏览器应用,您可以将浏览器重定向到 http://auth-server/auth/realms/{realm-name}/protocol/openid-connect/logout,如果用户使用其浏览器具有 SSO 会话,则将用户注销。当用户确认注销后,会进行实际注销。您可以选择包含 id_token_hintpost_logout_redirect_uriclient_id 等参数,如 OpenID Connect RP-Initiated Logout 中所述。因此,如果您在包含 id_token_hint 参数时,用户不需要显式确认该注销。注销后,只要提供用户,用户会自动重定向到指定的 post_logout_redirect_uri。请注意,在包含 post_logout_redirect_uri 时,您需要包含 client_idid_token_hint 参数。

如果您想避免在注销过程中注销外部身份提供程序,您可以提供 启动_idp 的参数,并成为身份提供程序的身份(别名)问题。当作为外部身份提供程序发起的单个注销端点的一部分调用时,此参数很有用。initiated ing_idp 是 Red Hat Single Sign-On logout 端点的支持参数,除了 RP-Initiated Logout 规范中描述的参数之外。

当使用 HttpServletRequest.logout() 选项时,适配器对通过刷新令牌的红帽单点登录服务器执行后端 POST 调用。如果从未保护的页面(没有检查有效令牌的页面)执行方法,则刷新令牌将不可用,在这种情况下,适配器会跳过调用。因此,建议使用一个受保护的页面来执行 HttpServletRequest.logout(),以便在需要时执行当前的令牌,并与红帽单点登录服务器交互。

2.1.13. 参数转发

Red Hat Single Sign-On 初始授权端点请求支持不同的参数。大多数参数都在 OIDC 规格 中所述。某些参数由基于适配器配置自动添加。但是,每个调用时还可添加一些参数。当您打开受保护的应用程序 URI 时,特定的参数将转发到 Red Hat Single Sign-On 授权端点。

例如,如果请求离线令牌,您可以使用 scope 参数打开受保护的应用程序 URI:

http://myappserver/mysecuredapp?scope=offline_access

参数 scope=offline_access 将自动转发到 Red Hat Single Sign-On 授权端点。

支持的参数有:

  • 范围 - 使用以空格分隔的范围列表。空格分隔的列表通常是指特定 客户端上定义的客户端范围。请注意,范围 openid 将始终添加到适配器的范围列表中。例如,如果您输入范围选项 地址电话,则到 Red Hat Single Sign-On 的请求将包含 scope 参数 scope=openid 地址电话
  • 提示 - Red Hat Single Sign-On 支持这些设置:

    • login - SSO 将会被忽略,并且始终会显示红帽单点登录登录页面,即使用户已经通过身份验证
    • consent - 只适用于带有 Consent Required 的客户端。如果使用它,则 Consent 页面将始终显示,即使用户之前授予了这个客户端的同意。
    • none - 不显示登录页面;相反,如果用户还没有通过身份验证,该用户将被重定向到应用。此设置允许您在应用程序一侧创建 filter/interceptor,并向用户显示自定义错误页面。请参阅规格中的更多详情。
  • max_age - 仅在用户已通过身份验证时才使用。指定验证可保留的最大允许时间,从用户验证身份衡量。如果用户进行身份验证的时间超过 maxAge,则 SSO 将被忽略,必须重新验证。
  • login_hint - 用来预先填充登录表单上的用户名/电子邮件字段。
  • kc_idp_hint - 用来告知 Red Hat Single Sign-On 跳过显示登录页面并自动重定向到指定的身份提供程序。身份提供程序文档中的更多信息

大多数参数都包括在 OIDC 规格。唯一的例外是参数 kc_idp_hint,它特定于 Red Hat Single Sign-On,并包含要使用的身份提供程序的名称。如需更多信息,请参阅《 服务器管理指南》 中的 Identity Brokering 章节。

警告

如果您使用附加参数打开 URL,如果应用程序中已经通过身份验证,则适配器不会重定向到 Red Hat Single Sign-On。例如,如果您已向应用程序 mysecuredapp 进行了身份验证,打开 http://myappserver/mysecuredapp?prompt=login 不会自动重定向到 Red Hat Single Sign-On 登录页面。以后可能会更改此行为。

2.1.14. 客户端身份验证

当机密 OIDC 客户端需要发送后台请求(例如,交换令牌的代码,或刷新令牌)时,它需要与红帽单点登录服务器进行身份验证。默认情况下,可以通过三种方式验证客户端:客户端 ID 和客户端 secret,使用签名 JWT 进行客户端身份验证,或者使用客户端 secret 使用签名 JWT 进行客户端身份验证。

2.1.14.1. 客户端 ID 和客户端 Secret

这是 OAuth2 规范中描述的传统方法。客户端有一个 secret,需要知道适配器(应用程序)和 Red Hat Single Sign-On 服务器。您可以在 Red Hat Single Sign-On Admin Console 中为特定客户端生成 secret,然后将此 secret 粘贴到应用程序端的 keycloak.json 文件中:

"credentials": {
    "secret": "19666a4f-32dd-4049-b082-684c74115f28"
}

2.1.14.2. 使用签名 JWT 进行客户端身份验证

这基于 RFC7523 规格。它以以下方式工作:

  • 客户端必须具有私钥和证书。对于 Red Hat Single Sign-On,可以通过传统的 密钥存储文件 提供,该文件可在客户端应用的类路径或文件系统中某一位置提供。
  • 客户端应用程序启动后,它允许使用 URL(如 http://myhost.com/myapp/k_jwks)以 JWKS 格式下载其公钥,假设 http://myhost.com/myapp 是客户端应用程序的基本 URL。红帽单点登录可以使用此 URL(请参阅以下)。
  • 在身份验证过程中,客户端会生成 JWT 令牌,并使用其私钥对其进行签名,并将其发送到特定的后端请求(如 client_assertion 参数中的代码到令牌请求)。
  • Red Hat Single Sign-On 必须具有客户端的公钥或证书,以便它能够在 JWT 上验证签名。在 Red Hat Single Sign-On 中,您需要为您的客户端配置客户端凭证。首先,您需要在管理控制台中的 凭据 中选择 Signed JWT 作为对客户端进行身份验证的方法。然后,您可以选择在 选项卡中选择:

    • 配置红帽单点登录可下载客户端公钥的 JWKS URL。这可以是一个 URL,如 http://myhost.com/myapp/k_jwks(请参阅上面的详细信息)。这个选项是最灵活的,因为客户端可以随时轮转其密钥,然后在需要时始终下载新密钥,而无需更改配置。更准确地,红帽单点登录会在看到由未知 kid (密钥 ID)签名的令牌时下载新密钥。
    • 以 PEM 格式、采用 JWK 格式或从密钥存储上传客户端的公钥或证书。使用此选项时,公钥是硬编码的,在客户端生成新密钥对时必须更改。如果没有可用的红帽单点登录管理控制台,您也可以从红帽单点登录管理控制台生成自己的密钥存储。有关如何设置红帽单点登录管理控制台的详情,请查看 服务器管理指南

要在适配器中设置,您需要在 keycloak.json 文件中具有类似如下的内容:

"credentials": {
  "jwt": {
    "client-keystore-file": "classpath:keystore-client.jks",
    "client-keystore-type": "JKS",
    "client-keystore-password": "storepass",
    "client-key-password": "keypass",
    "client-key-alias": "clientkey",
    "algorithm": "RS256",
    "token-expiration": 10
  }
}

使用这个配置,密钥存储文件 keystore-client.jks 必须在您的 WAR 中的 classpath 上可用。如果不使用前缀 classpath: 您可以指向运行客户端应用程序的文件系统中的任何文件。

algorithm 字段指定用于签名 JWT 的算法,默认为 RS256。此字段应当与密钥对同步。例如,RS256 算法需要 RSA 密钥对,而 ES256 算法需要 EC 密钥对。如需更多信息,请参阅 Cryptographic Algorithms 用于数字签名和 MAC

2.1.15. 多租户

在我们的环境中,多元意味着可以使用多个红帽单点登录域保护单一目标应用程序(WAR)。域可以位于同一红帽单点登录实例或不同的实例上。

实际上,这意味着应用程序需要有多个 keycloak.json 适配器配置文件。

您可以有多个 WAR 实例,它们不同的适配器配置文件部署到不同的上下文路径。但是,这可能很不便,您可能还希望根据上下文路径以外的其他内容选择域。

Red Hat Single Sign-On 使可以有一个自定义配置解析器,以便您可以选择每个请求的适配器配置。

要实现这一点,首先需要创建 org.keycloak.adapters.KeycloakConfigResolver 的实现。例如:

package example;

import org.keycloak.adapters.KeycloakConfigResolver;
import org.keycloak.adapters.KeycloakDeployment;
import org.keycloak.adapters.KeycloakDeploymentBuilder;

public class PathBasedKeycloakConfigResolver implements KeycloakConfigResolver {

    @Override
    public KeycloakDeployment resolve(OIDCHttpFacade.Request request) {
        if (path.startsWith("alternative")) {
            KeycloakDeployment deployment = cache.get(realm);
            if (null == deployment) {
                InputStream is = getClass().getResourceAsStream("/tenant1-keycloak.json");
                return KeycloakDeploymentBuilder.build(is);
            }
        } else {
            InputStream is = getClass().getResourceAsStream("/default-keycloak.json");
            return KeycloakDeploymentBuilder.build(is);
        }
    }

}

您还需要配置用于 web.xml 中的 keycloak.config.resolver 上下文-param 的 KeycloakConfigResolver 实现:

<web-app>
    ...
    <context-param>
        <param-name>keycloak.config.resolver</param-name>
        <param-value>example.PathBasedKeycloakConfigResolver</param-value>
    </context-param>
</web-app>

2.1.16. 应用程序集群

本章与支持部署到 JBoss EAP 的集群应用程序相关。

根据您的应用程序是可用的一些选项:

  • 无状态或有状态
  • 可分发(复制的 http 会话)或不可分发的
  • 依赖负载均衡器提供的粘性会话
  • 托管在与 Red Hat Single Sign-On 相同的域中

处理集群的过程就像常规的应用程序一样简单。主要的原因是浏览器和服务器端应用程序向红帽单点登录发送请求,因此不像在您的负载均衡器上启用粘性会话那样简单。

2.1.16.1. 无状态令牌存储

默认情况下,Red Hat Single Sign-On 保护的 Web 应用程序使用 HTTP 会话来存储安全上下文。这意味着您必须启用粘性会话或复制 HTTP 会话。

作为在 HTTP 会话中存储安全上下文的替代方法,可将适配器配置为将其存储在 cookie 中。如果您要使应用程序无状态,或者您不想将安全上下文存储在 HTTP 会话中,这很有用。

要使用 Cookie 存储来保存安全上下文,请编辑应用程序 WEB-INF/keycloak.json 并添加:

"token-store": "cookie"
注意

token-store 的默认值为 session,它将安全上下文存储在 HTTP 会话中。

使用 cookie 存储的一个限制是,整个安全性上下文将针对每个 HTTP 请求在 cookie 中传递。这可能会影响性能。

另一个较小的限制是,对单点登录的支持有限。如果您从应用程序本身发起 servlet logout(HttpServletRequest.logout),它没有问题,因为适配器将删除 KEYCLOAK_ADAPTER_STATE cookie。但是,从不同应用程序初始化的频道注销不会由 Red Hat Single Sign-On 传播到使用 cookie 存储的应用程序。因此,建议对访问令牌超时使用简短值(例如 1 分钟)。

注意

有些负载均衡器不允许配置粘性会话 Cookie 名称或内容,如 Amazon ALB。对于这些,建议将 shouldAttachRoute 选项设置为 false

2.1.16.2. 相对 URI 优化

在部署情况下,Red Hat Single Sign-On 和应用程序托管在同一域中(通过反向代理或负载均衡器),它可以方便地在客户端配置中使用相对 URI 选项。

对于相对 URI,则根据用于访问 Red Hat Single Sign-On 的 URL 解析 URI。

例如,如果您的应用程序的 URL 是 https://acme.org/myapp,Red Hat Single Sign-On 的 URL 为 https://acme.org/auth,您可以使用 redirect-uri /myapp 而不是 https://acme.org/myapp

2.1.16.3. 管理 URL 配置

可以在红帽单点登录管理控制台中配置特定客户端的管理 URL。红帽单点登录服务器用于向应用程序发送后端请求以获取各种任务,如注销用户或推送撤销策略。

例如,后端频道注销的工作方式为:

  1. 用户从一个应用程序发送注销请求
  2. 应用程序向 Red Hat Single Sign-On 发送注销请求
  3. Red Hat Single Sign-On 服务器使用户会话无效
  4. 然后,Red Hat Single Sign-On 服务器会向应用程序发送一个与会话关联的 admin url 的后方请求
  5. 当应用程序收到注销请求时,它会使对应的 HTTP 会话无效

如果 admin URL 包含 ${application.session.host},它将被替换为与 HTTP 会话关联的节点的 URL。

2.1.16.4. 注册应用程序节点

上一节中介绍了 Red Hat Single Sign-On 如何发送注销请求到与特定 HTTP 会话关联的节点。然而,在某些情况下,管理员可能希望将管理任务传播到所有注册的集群节点,而不只是其中之一。例如,在策略到应用程序之前将新版不推送到应用程序,或从应用程序注销所有用户。

在这种情况下,Red Hat Single Sign-On 需要了解所有应用程序集群节点,因此可以将事件发送到所有应用程序。要做到这一点,我们支持自动发现机制:

  1. 当新的应用程序节点加入集群时,它会向 Red Hat Single Sign-On 服务器发送注册请求
  2. 根据配置的定期间隔,请求可能会与 Red Hat Single Sign-On 重新输入
  3. 如果 Red Hat Single Sign-On 服务器没有在指定超时内收到重新注册请求,那么它会自动取消注册特定节点
  4. 当节点发送未注册或应用程序取消部署时,节点也会在 Red Hat Single Sign-On 中取消注册。如果没有调用非部署监听程序,这可能无法正常工作,这会导致自动取消注册

默认情况下,发送启动注册和定期重新注册功能会被禁用,因为它只是一些集群应用程序所需的。

要启用功能,为您的应用程序编辑 WEB-INF/keycloak.json 文件并添加:

"register-node-at-startup": true,
"register-node-period": 600,

这意味着,适配器会在启动时发送注册请求,并每 10 分钟重新注册一次。

在 Red Hat Single Sign-On Admin Console 中,您可以指定最大节点 重新注册 超时(应该大于适配器配置中注册节点)。您还可以通过 Admin Console 手动添加和删除集群节点,如果您不想依赖自动注册功能,或者想要删除过时的应用程序节点(如果不使用自动取消注册功能),这会很有用。

2.1.16.5. 每个请求中的刷新令牌

默认情况下,应用程序适配器仅在访问令牌过期时刷新访问令牌。但是,您也可以将适配器配置为在每个请求中刷新令牌。这可能会对性能产生影响,因为您的应用程序将向红帽单点登录服务器发送更多请求。

要启用功能,为您的应用程序编辑 WEB-INF/keycloak.json 文件并添加:

"always-refresh-token": true
注意

这可能会对性能有显著影响。只有您无法依赖 backchannel 消息传播注销而不是在策略前启用此功能。需要考虑的另一个因素是,默认情况下访问令牌具有较短的到期时间,因此即使注销不会传播令牌在注销后才会过期。

Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

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

让开源更具包容性

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

關於紅帽

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

© 2024 Red Hat, Inc.