保护应用程序和服务指南
用于 Red Hat Single Sign-On 7.5
摘要
使开源包含更多
红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。我们从这四个术语开始:master、slave、黑名单和白名单。由于此项工作十分艰巨,这些更改将在即将推出的几个发行版本中逐步实施。有关更多详情,请参阅我们的首席技术官 Chris Wright 提供的消息。
第 1 章 规划保护应用程序和服务的安全
Red Hat Single Sign-On 支持 OpenID Connect (对 OAuth 2.0 的扩展)和 SAML 2.0。在保护客户端和服务时,您需要决定您要使用哪两个内容。如果也可以选择使用 SAML 保护某些 OpenID Connect 和其他人。
为了保护客户端和服务,您还需要一个适配器或库来用于您选择的协议。Red Hat Single Sign-On 附带了自己的适配器用于所选平台,但也可以使用通用 OpenID Connect 重新使用 party 和 SAML Service Provider 库。
1.1. 客户端适配器
红帽单点登录客户端适配器是库,使红帽单点登录的应用程序和服务变得非常容易。我们致电适配器而不是库,因为它们提供了对底层平台和框架的紧密集成。这使得适配器易于使用,它们需要比库通常需要较少的样板代码。
1.2. 支持的平台
Red Hat Single Sign-On 可让您保护在不同平台中运行的应用程序,并使用 OpenID Connect 和 SAML 协议的不同技术堆栈。
1.2.1. OpenID Connect
1.2.1.1. Java
1.2.1.2. JavaScript (client-side)
1.2.1.3. Node.js (服务器侧)
1.2.2. SAML
1.2.2.1. Java
1.2.2.2. Apache HTTP 服务器
1.3. 支持的协议
红帽单点登录支持 OpenID Connect 和 SAML 协议。
1.3.1. OpenID Connect
OpenID Connect (OIDC)是一个身份验证协议,它是 OAuth 2.0 的扩展。虽然 OAuth 2.0 只是用于构建授权协议的框架,但 OIDC 是一个完整的验证和授权协议。OIDC 还利用了一组标准的 Json Web 令牌 (JWT)。这些标准定义了身份令牌 JSON 格式,以及以紧凑和 Web 友好的方式对这些数据进行数字签名的方法。
使用 OIDC 时真正有两种类型的用例。第一个是要求红帽单点登录服务器为其验证用户的应用程序。成功登录后,应用将收到 身份 令牌和 访问令牌。身份令牌 包含有关用户的信息,如用户名、电子邮件和其他配置集信息。访问令牌 由域进行数字签名,包含应用可以使用的访问信息(如用户角色映射)来确定允许用户在应用上能够访问哪些资源。
第二种用例是希望获得远程服务的客户端。在这种情况下,客户端会要求 Red Hat Single Sign-On 获取可用于代表用户在其他远程服务上调用的访问令牌。Red Hat Single Sign-On 对用户进行身份验证,然后询问用户同意其请求客户端的权限。然后,客户端会接收 访问令牌。此 访问令牌 由域进行数字签名。客户端可以使用此 访问令牌 在远程服务上进行 REST 调用。REST 服务提取 访问令牌,验证令牌的签名,然后根据令牌中的访问信息决定是否处理请求。
1.3.2. SAML 2.0
SAML 2.0 与 OIDC 类似,但存在比较陈旧且比较成熟。它在 SOAP 和 plethora 的 WS-* 规格中有根,因此它往往比 OIDC 更详细。SAML 2.0 主要用于身份验证协议,可在身份验证服务器和应用程序间交换 XML 文档。XML 签名和加密用于验证请求和响应。
在 Red Hat Single Sign-On SAML 中,提供两种用例:浏览器应用程序和 REST 调用。
使用 SAML 时真正有两种类型的用例。第一个是要求红帽单点登录服务器为其验证用户的应用程序。成功登录后,应用程序将收到 XML 文档,其中包含名为 SAML 断言的内容,该文档指定了用户的各种属性。此 XML 文档由域进行数字签名,包含应用可以使用的访问信息(如用户角色映射),决定允许用户在应用上访问哪些资源。
第二种用例是希望获得远程服务的客户端。在这种情况下,客户端会要求红帽单点登录以获取 SAML 断言,它可用于代表用户对其他远程服务调用。
1.3.3. OpenID Connect 与.SAML
在 OpenID Connect 和 SAML 之间选择不仅仅是使用较新的协议(OIDC),而不是旧的更成熟的协议(SAML)。
在大多数情况下,Red Hat Single Sign-On 建议使用 OIDC。
SAML 往往比 OIDC 更详细。
除交换数据的详细程度外,如果您比较了 OIDC 设计为与 web 配合使用的规格,SAML 被重新引入在 web 上工作。例如,OIDC 也更适用于 HTML5/JavaScript 应用程序,因为它比 SAML 更容易实现。因为令牌采用 JSON 格式,所以 JavaScript 更易于使用。您还会找到一些可更轻松地在 web 应用程序中实施安全性的 nice 功能。例如,请查看规格用于轻松地确定用户是否仍然在登录或未登录的 iframe 诀窍。
SAML 具有其使用性。随着您看到的 OIDC 规格不断发展,他们认为,这些规范的实施更为多,以及 SAML 多年的功能。我们通常会看到人们通过 OIDC 选择 SAML,因为它具有更加成熟的,而且因为它们已经拥有了对其安全保护的现有应用程序。
1.4. 术语
本指南使用以下术语:
-
客户端是与红帽单点登录交互的实体,用于验证用户并获取令牌。通常,客户端是代表用户提供单点登录体验的应用程序和服务,以及使用服务器发布的令牌访问其他服务。客户端也可以仅有兴趣获取令牌并代表其访问其他服务而具有的实体。 -
应用程序包括用于每个协议特定平台的各种应用程序 -
客户端适配器是让红帽单点登录轻松保护应用程序和服务的库。
它们提供了一个到底层平台和框架的紧密集成。 -
创建客户端和是相同的操作。注册客户端创建客户端是使用管理控制台创建客户端的术语。注册客户端是一个术语,用于使用红帽单点登录客户端注册服务来注册客户端。 -
服务帐户是一种客户端类型,能够代表自己获取令牌。
1.5. 保护应用程序和服务的基本步骤
以下是在 Red Hat Single Sign-On 中保护应用程序或服务的基本步骤。
使用以下选项之一配置客户端:
- Red Hat Single Sign-On adapter
- 通用 OpenID 连接或 SAML 库
使用以下选项之一注册客户端:
- Red Hat Single Sign-On Admin Console
- 客户端注册服务
- CLI
其他资源
- 本指南详细介绍了这些步骤。《 服务器管理指南 》中存在相关信息。本指南提供了使用管理控制台创建客户端的说明。创建客户端是使用红帽单点登录客户端注册服务注册客户端相同的任务。
第 2 章 使用 OpenID Connect 保护应用程序和服务
本节论述了如何使用 Red Hat Single Sign-On 适配器或通用 OpenID Connect 重新授权库在 OpenID Connect 中保护应用程序和服务。
2.1. Java 适配器
Red Hat Single Sign-On 附带了一系列不同的 Java 应用程序适配器。选择正确的适配器取决于目标平台。
所有 Java 适配器共享一组在 Java 适配器 配置章节中描述的通用配置选项。
2.1.1. Java 适配器配置
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"
}
}
您可以使用 ${…} 213ure 进行系统属性替换。例如,${jboss.server.config.dir} 替换为 /path/to/Red Hat Single Sign-On。也支持通过 env 前缀替换环境变量,如 ${env.MY_ENVIRONMENT_VARIABLE}。
初始配置文件可以从管理控制台获取。这可以通过打开 admin 控制台来完成,从菜单中选择 Clients,再单击对应的客户端。打开客户端的页面后,点 Installation 选项卡并选择 Keycloak OIDC JSON。
下面是每个配置选项的描述:
- realm
- realm 的名称。这是 REQUIRED。
- resource
- 应用程序的 client-id。每个应用程序都有一个客户端 ID,用于识别应用程序。这是 REQUIRED。
- realm-public-key
- realm 公钥的 PEM 格式。您可以从 Admin Console 获取它。这是 OPTIONAL,我们不推荐设置它。如果没有设置,适配器将从 Red Hat Single Sign-On 下载它,并将在需要时始终重新下载它(例如 Red Hat Single Sign-On 将其密钥轮转)。但是,如果设置了 realm-public-key,则适配器永远不会从 Red Hat Single Sign-On 下载新密钥,因此当 Red Hat Single Sign-On 将其密钥轮转时,适配器将中断。
- auth-server-url
-
Red Hat Single Sign-On 服务器的基本 URL。所有其他 Red Hat Single Sign-On 页面和 REST 服务端点都来自于此目的。它通常是
https://host:port/auth的格式。这是 REQUIRED。 - SSL-required
-
确保与 Red Hat Single Sign-On 服务器的所有通信都是通过 HTTPS。在生产环境中,这应设置为
所有。这是 选项。默认值为 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。
- autodetect-bearer-only
-
如果您的应用程序同时为 Web 应用程序和 Web 服务(如 SOAP 或 REST)提供,则此项应设为 true。它允许您将 Web 应用的未经身份验证的用户重定向到 Red Hat Single Sign-On 登录页面,但向未经身份验证的 SOAP 或 REST 客户端发送 HTTP
401状态代码,而不是将它们了解到登录页面。Red Hat Single Sign-On auto-detects SOAP 或 REST 客户端基于X-Requested-With、SOAPAction或Accept等典型标头。默认值为 false。 - enable-basic-auth
- 这告知适配器也支持基本身份验证。如果启用了这个选项,则必须提供 secret。这是 选项。默认值为 false。
- expose-token
-
如果为
true,则经过身份验证的用户客户端(通过 JavaScript HTTP 调用)可以通过 URLroot/k_query_bearer_token获取签名的访问令牌。这是 选项。默认值为 false。 - credentials
- 指定应用程序的凭证。这是一个对象表示法,其中键是凭证类型,值是凭证类型的值。目前支持密码和 jwt。这只适用于 带有 "Confidential"访问类型的客户端。
- connection-pool-size
-
此配置选项定义了与 Red Hat Single Sign-On 服务器的连接数量。这是 选项。默认值为
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,Red Hat Single Sign-On 服务器的证书通过 truststore 验证,但没有进行主机名验证。此设置仅应在开发期间使用,且不应 在生产环境中使用,因为它将禁用 SSL 证书的验证。在测试环境中,这种设置 可能很有用。默认值为false。 - proxy-url
- 如果使用 HTTP 代理的 URL。
- truststore
-
该值是 truststore 文件的文件路径。如果您为带有
classpath 的路径添加前缀:,则信任存储将从部署的类路径中获取。用于向 Red Hat Single Sign-On 服务器的外向 HTTPS 通信。进行 HTTPS 请求的客户端需要一种方式来验证所讨论的服务器主机。这是信任者的作用。密钥存储包含一个或多个可信主机证书或证书颁发机构。您可以通过提取红帽单点登录服务器 SSL 密钥存储的公共证书来创建此信任存储。这是 REQUIRED,除非ssl-required为none或disable-trust-manager为true。 - truststore-password
-
truststore 的密码。如果设置了
truststore,则 REQUIRED 为 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,适配器会在每个请求中刷新令牌。警告 - 启用时,每次请求您的应用程序都会请求 Red Hat Single Sign-On。
- register-node-at-startup
- 如果为 true,则适配器将为 Red Hat Single Sign-On 发送注册请求。默认设置为 false,且仅在应用程序集群时才有用。详情请参阅 应用程序集群
- register-node-period
- 在 Red Hat Single Sign-On 中重新注册适配器的周期。当应用程序被集群时,非常有用。详情请参阅 应用程序集群
- token-store
- 可能的值有 session 和 cookie。默认为 session,这意味着适配器将帐户信息存储在 HTTP Session 中。另一种 Cookie 意味着在 Cookie 中存储信息。详情请参阅 应用程序集群
- token-cookie-path
- 在使用 Cookie 存储时,此选项设定用于存储帐户信息的 Cookie 路径。如果是相对路径,则假定应用程序在上下文 root 中运行,并且相对于该上下文 root。如果它是绝对路径,则使用绝对路径来设置 Cookie 路径。默认为使用相对于上下文 root 的路径。
- principal-attribute
-
OpenID Connect ID Token 属性,使用.如果令牌属性为空,则默认为
sub。可能的值有sub,preferred_username,email,name,nickname,given_name,family_name。 - turn-off-change-session-id-on-login
- 在某些平台上成功登录时,会话 ID 被修改,以插入安全攻击向量。如果您想要关闭该选项为 OPTIONAL,则将此更改为 true。默认值为 false。
- token-minimum-time-to-live
-
在 Red Hat Single Sign-On 服务器到期前,可以预先使用 Red Hat Single Sign-On 服务器刷新活跃的访问令牌的时间(以秒为单位)。这在将访问令牌发送到另一个 REST 客户端(在评估之前过期)时特别有用。这个值永不会超过 realm 的访问令牌期限。这是 选项。默认值为
0秒,因此适配器仅在过期时刷新访问令牌。 - min-time-between-jwks-requests
-
以秒为单位,指定对红帽单点登录的两个请求之间的最短间隔,以检索新的公钥。默认为 10 秒。当它识别了带有 unknown
kid的令牌时,适配器始终会尝试下载新公钥。但是,它不会每 10 秒尝试一次(默认为 )。这是当攻击者利用错误的kid强制适配器发送大量令牌时,为了避免 DoS 向红帽单点登录发送大量请求。 - public-key-cache-ttl
-
以秒为单位,指定对红帽单点登录的两个请求之间的最大间隔,以检索新的公钥。默认为 86400 秒(1 天)。当它识别了带有 unknown
kid的令牌时,适配器始终会尝试下载新公钥。如果它识别了具有已知kid的令牌,则只使用之前下载的公钥。但是,每个配置的时间间隔(默认为 1 天)将始终下载新公钥,即使已经知道了令牌的kid。 - ignore-oauth-query-parameter
-
默认值为
false,如果设为true,则会为 bearer 令牌处理access_token查询参数关闭处理。如果用户只在access_token中传递时,用户将无法进行身份验证 - redirect-rewrite-rules
-
如果需要,指定 Redirect URI 重写规则。这是一个对象表示法,键是要匹配的 Redirect URI 的正则表达式,值是替换 String。
$字符可用于替换字符串中的反向引用。 - verify-token-audience
-
如果设置为
true,则在使用 bearer 令牌进行身份验证时,适配器将验证令牌是否包含此客户端名称(资源)作为受众。选项对于服务特别有用,主要提供由 bearer 令牌身份验证的请求。默认设置为false,但为了提高安全性,建议启用它。有关 受众支持 的更多详情,请参阅 Audience 支持。
2.1.2. JBoss EAP 适配器
您可以从 ZIP 文件或从 RPM 安装此适配器。
2.1.3. 从 ZIP 文件安装 JBOSS EAP 适配器
为了保护在 JBoss EAP 上部署的 WAR 应用,您必须安装并配置 Red Hat Single Sign-On adapter 子系统。然后有两个选项来保护您的 WAR。
- 您可以在 WAR 中提供适配器配置文件,并将 auth-method 更改为 web.xml 中的 KEYCLOAK。
-
另外,您根本不需要修改 WAR,而且您可以通过配置文件中的 Red Hat Single Sign-On adapter 子系统配置保护它,如
standalone.xml。
本节中描述了这两种方法。
适配器作为单独的存档提供,具体取决于您使用的服务器版本。
流程
从 Sotware Downloads 站点安装适用于您的应用程序服务器的适配器。
在 JBoss EAP 7 上安装:
$ cd $EAP_HOME $ unzip rh-sso-7.5.3-eap7-adapter.zip
在 JBoss EAP 6 上安装:
$ cd $EAP_HOME $ unzip rh-sso-7.5.3-eap6-adapter.zip
此 ZIP 存档包含特定于 Red Hat Single Sign-On 适配器的 JBoss 模块。它还包含用于配置适配器子系统的 JBoss CLI 脚本。
要配置适配器子系统,请执行适当的命令。
如果服务器 未在运行,请在 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在 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 的安全。
流程
在 WAR 的
WEB-INF目录中创建一个keycloak.json适配器配置文件。此配置文件的格式在 Java 适配器配置 部分描述。
-
在
web.xml中将auth-method设置为KEYCLOAK。 使用标准 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 Admin Console,并转至此 WAR 与应用程序的客户端/安装选项卡。它提供了一个 XML 文件示例,您可以剪切和粘贴。
如果您有多个部署由同一域保护,您可以在单独的元素中共享 realm 配置。例如:
<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 系统已注册到您的帐户。如需更多信息,请参阅 红帽订阅管理文档。
如果您已订阅了另一个 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
流程
根据您的 Red Hat Enterprise Linux 版本,为 OIDC 安装 JBoss EAP 7 适配器。
Install on Red Hat Enterprise Linux 6, 7:
$ sudo yum install eap7-keycloak-adapter-sso7_5
在 Red Hat Enterprise Linux 8 中安装:
$ sudo dnf install eap7-keycloak-adapter-sso7_5
注意RPM 安装的默认 EAP_HOME 路径为 /opt/rh/eap7/root/usr/share/wildfly。
为 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 系统已注册到您的帐户。如需更多信息,请参阅 红帽订阅管理文档。
如果您已订阅了另一个 JBoss EAP 存储库,必须先退订该存储库。
使用以下命令,使用红帽订阅管理器订阅 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
流程
使用以下命令为 OIDC 安装 EAP 6 适配器:
$ sudo yum install keycloak-adapter-sso7_5-eap6
注意RPM 安装的默认 EAP_HOME 路径为 /opt/rh/eap6/root/usr/share/wildfly。
为 OIDC 模块运行安装脚本。
$ $EAP_HOME/bin/jboss-cli.sh -c --file=$EAP_HOME/bin/adapter-install.cli
您的安装已完成。
2.1.6. JBoss Fuse 6 适配器
红帽单点登录支持保护您的 Web 应用程序在 JBoss Fuse 6 中。
唯一支持的 Fuse 6 版本是最新的版本。如果您使用旧版本的 Fuse 6,则某些功能可能无法正常工作。特别是,Hawtio 集成不适用于早期版本的 Fuse 6。
Fuse 支持以下项目的安全性:
- 使用 Pax Web War 扩展器在 Fuse 上部署的经典 WAR 应用程序
- 使用 Pax Web Whiteboard Extender 在 Fuse 上部署的 Servlets 作为 OSGI 服务
- 使用 Camel Jetty 组件运行的 Apache Camel Jetty 端点
- 在其自己的独立 Jetty 引擎上运行的 Apache CXF 端点
- 在 CXF servlet 提供的默认引擎上运行的 Apache CXF 端点
- SSH 和 JMX 管理员访问权限
- Hawtio 管理控制台
2.1.6.1. 在 Fuse 6 中保护您的 Web 应用程序
您必须首先安装 Red Hat Single Sign-On Karaf 功能。接下来,您将需要根据您要保护的应用程序类型执行这些步骤。所有引用的 web 应用程序都需要将 Red Hat Single Sign-On Jetty authenticator 注入底层 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, \ ...
流程
- 启动 JBoss Fuse 6.3.0 Rollup 12
在 Karaf 终端中键入:
features:addurl mvn:org.keycloak/keycloak-osgi-features/15.0.8.redhat-00001/xml/features features:install keycloak
您可能还需要安装 Jetty 9 功能:
features:install keycloak-jetty9-adapter
确定安装了功能:
features:list | grep keycloak
2.1.6.2.2. 从 ZIP 捆绑包安装
如果您离线,或者不想使用 Maven 获取 JAR 文件和其他工件,这个安装选项很有用。
流程
- 从 Sotware Downloads 站点下载 Red Hat Single Sign-On Fuse adapter ZIP 归档。
将它解压缩到 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.5.3-fuse-adapter.zip
启动 Fuse 并在 fuse/karaf 终端中运行这些命令:
features:addurl mvn:org.keycloak/keycloak-osgi-features/15.0.8.redhat-00001/xml/features features:install keycloak
-
安装对应的 Jetty 适配器。由于工件直接在 JBoss Fuse
系统目录中可用,因此您不需要使用 Maven 存储库。
2.1.6.3. 保护经典 WAR 应用程序
流程
在
/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>
使用 authenticator 将
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>-
在 WAR
/WEB-INF/目录中,创建一个新文件 keycloak.json。此配置文件的格式在 Java Adapters Config 部分中描述。另外,还可以使此文件在外部可用,如 配置外部适配器 中所述。 确保您的 WAR 应用程序导入
org.keycloak.adapters.jetty,可能META-INF/MANIFEST.MF文件,位于Import-Package标头下。在项目中使用maven-bundle-plugin,在清单中可以正确地生成 OSGI 标头。请注意,软件包的"*"解析不会导入org.keycloak.adapters.jetty软件包,因为它不被应用程序或 Blueprint 或 Spring 描述符使用,而是在jetty-web.xml文件中使用。要导入的软件包列表可能类似如下:
org.keycloak.adapters.jetty;version="15.0.8.redhat-00001", org.keycloak.adapters;version="15.0.8.redhat-00001", org.keycloak.constants;version="15.0.8.redhat-00001", org.keycloak.util;version="15.0.8.redhat-00001", org.keycloak.*;version="15.0.8.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.config 或 karaf.etc java 属性搜索基本文件夹以查找配置。然后,在其中一个文件夹中搜索名为 < your_web_context>-keycloak.json 的文件。
因此,如果您的 web 应用程序具有上下文 my-portal,则您的适配器配置会从 $FUSE_HOME/etc/my-portal-keycloak.json 文件载入。
2.1.6.4. 保护部署为 OSGI 服务的 servlet
如果您在 OSGI 捆绑项目中具有不部署为经典 WAR 应用的 servlet 类,您可以使用此方法。Fuse 使用 Pax Web Whiteboard 扩展器来部署此类 servlet,如 Web 应用程序。
流程
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 在蓝图配置文件中声明。
-
您可能需要在项目内具有
META-INF/MANIFEST.MF中的Import-Package必须至少包含这些导入:org.keycloak.adapters.jetty;version="15.0.8.redhat-00001", org.keycloak.adapters;version="15.0.8.redhat-00001", org.keycloak.constants;version="15.0.8.redhat-00001", org.keycloak.util;version="15.0.8.redhat-00001", org.keycloak.*;version="15.0.8.redhat-00001", *;resolution:=optional
2.1.6.5. 保护 Apache Camel 应用程序
您可以通过使用 KeycloakJettyAuthenticator 添加 securityHandler 以及注入了正确的安全限制,保护通过 camel-jetty 组件实施的 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&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="15.0.8.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 端点
流程
要运行由 Red Hat Single Sign-On 在单独的 Jetty 引擎上保护的 CXF 端点,请执行以下步骤:
将
META-INF/spring/beans.xml添加到您的应用中,并通过注入KeycloakJettyAuthenticator的 Jetty SecurityHandler 声明httpj:engine-factory。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>-
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="15.0.8.redhat-00001"
2.1.6.8. 保护默认 Jetty Engine 上的 Apache CXF 端点
一些服务会在启动时自动附带部署的 servlet。其中一个服务是在 http://localhost:8181/cxf 上下文中运行的 CXF servlet。保护此类端点可能会比较复杂。红帽单点登录当前正在使用的方法之一是 ServletReregistrationService,它在启动时取消部署内置的 servlet,可让您在 Red Hat Single Sign-On 的安全上下文中重新部署它。
应用程序中的配置文件 OSGI-INF/blueprint/blueprint.xml 可能类似如下。请注意,它添加了 JAX-RS 的客户服务端点,该端点特定于您的应用,但更重要的是,可保护整个 /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 上的 Secure 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="15.0.8.redhat-00001", org.keycloak.adapters.jetty;version="15.0.8.redhat-00001", *;resolution:=optional
2.1.6.9. 保护 Fuse 管理服务
2.1.6.9.1. 使用 SSH 身份验证到 Fuse 终端
Red Hat Single Sign-On 主要解决了用于 Web 应用程序身份验证的用例;但是,如果您的其他 Web 服务和应用程序受 Red Hat Single Sign-On 保护,使用 Red Hat Single Sign-On 凭证保护非 Web 管理服务(如使用 Red Hat Single Sign-On 凭证的 SSH)是一个最好的 pcrice。您可以使用 JAAS 登录模块进行此操作,它允许远程连接 Red Hat Single Sign-On,并根据 Resource Owner Password Credentials 来验证凭据。
要启用 SSH 身份验证,请执行以下步骤。
流程
-
在 Red Hat Single Sign-On 中,创建一个客户端(例如
ssh-jmx-admin-client),它将用于 SSH 身份验证。此客户端需要在上选择直接访问 Grants Enabled。 在
$FUSE_HOME/etc/org.apache.karaf.shell.cfg文件中,更新或指定此属性:sshRealm=keycloak
添加
$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" } }此文件指定客户端应用配置,供 JAAS DirectAccessGrantsLoginModule 从
keycloakJAAS 域用于 SSH 身份验证。启动 Fuse 并安装
keycloakJAAS 域。最简单的方法是安装keycloak-jaas功能,它预定义了 JAAS 域。您可以使用您自己的keycloakJAAS 域覆盖功能的预定义域,并具有更高等级的等级。详情请查看 JBoss Fuse 文档。在 Fuse 终端中使用这些命令:
features:addurl mvn:org.keycloak/keycloak-osgi-features/15.0.8.redhat-00001/xml/features features:install keycloak-jaas
以
admin用户身份使用 SSH 登录,在终端中输入以下内容:ssh -o PubkeyAuthentication=no -p 8101 admin@localhost
-
使用密码登录。
在一些后续的操作系统中,您可能需要默认使用 SSH 命令的 -o 选项 -o HostKeyAlgorithms=+ssh-dss,因为稍后的 SSH 客户端不允许使用 ssh-dss 算法。但是,默认情况下,它目前在 JBoss Fuse 6.3.0 Rollup 12 中使用。
请注意,用户需要具有 realm 角色 admin 来执行所有操作或另一个角色,以执行一系列操作(例如,查看器 角色),可限制用户仅运行只读 Karaf 命令。可用的角色在 $FUSE_HOME/etc/org.apache.karaf.shell.cfg 或 $FUSE_HOME/system.properties 中进行配置。
2.1.6.9.2. 使用 JMX 验证
如果要使用 jconsole 或其他外部工具通过 RMI 远程连接到 JMX,则可能需要 JMX 身份验证。否则,最好使用 hawt.io/jolokia,因为 jolokia 代理默认安装在 hawt.io 中。如需了解更多详细信息,请参阅 海军管理员管理员控制台。
流程
在
$FUSE_HOME/etc/org.apache.karaf.management.cfg文件中,将 jmxRealm 属性更改为:jmxRealm=keycloak
-
安装
keycloak-jaas功能并配置$FUSE_HOME/etc/keycloak-direct-access.json文件,如上面的 SSH 部分所述。 - 在 jconsole 中,您可以使用以下 URL:
service:jmx:rmi://localhost:44444/jndi/rmi://localhost:1099/karaf-root
and credentials: admin/password (基于您的环境具有 admin 权限的用户)。
2.1.6.10. 保护 Hawtio 管理控制台
要使用 Red Hat Single Sign-On 保护 Hawtio 管理控制台,请执行以下步骤:
流程
在
$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-
在您的域中,在 Red Hat Single Sign-On Admin Console 中创建客户端。例如,在 Red Hat Single Sign-On
demorealm 中,创建一个客户端hawtio-client,将public指定为 Access Type,并指定指向 Hawtio 的重定向 URI:您还必须配置对应的 Web Origin (本例中为 http://localhost:8181)。 -
使用以下示例中所示的内容,在
$FUSE_HOME/etc目录中创建keycloak-hawtio-client.json文件。根据您的 Red Hat Single Sign-On 环境,更改realm、资源和auth-server-url属性。resource属性必须指向上一步中创建的客户端。此文件供客户端(Hawtio JavaScript 应用)侧使用。
{
"realm" : "demo",
"resource" : "hawtio-client",
"auth-server-url" : "http://localhost:8080/auth",
"ssl-required" : "external",
"public-client" : true
}使用以下示例中所示的内容,在
$FUSE_HOME/etcdicrectory 中创建keycloak-hawtio.json文件。根据您的红帽单点登录环境,更改realm和auth-server-url属性。此文件供服务器(JAAS 登录模块)中的适配器使用。{ "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" }启动 JBoss Fuse 6.3.0 Rollup 12 并安装 keycloak 功能(如果您还没有这么做)。Karaf 终端中的命令与此示例类似:
features:addurl mvn:org.keycloak/keycloak-osgi-features/15.0.8.redhat-00001/xml/features features:install keycloak
进入 http://localhost:8181/hawtio,并以 Red Hat Single Sign-On 域的用户身份登录。
请注意,用户需要适当的域角色才能成功向 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和 clienthawtio-client -
您的 Red Hat Single Sign-On 正在
localhost:8080上运行 -
部署了 Hawtio 的 JBoss EAP 6.4 服务器将在
localhost:8181上运行。此服务器的目录在接下来的步骤中被称为$EAP_HOME。
流程
-
将
hawtio-wildfly-1.4.0.redhat-630396.war归档复制到$EAP_HOME/standalone/configuration目录。有关部署 Hawtio 的详情,请参阅 Fuse Hawtio 文档。 -
将
keycloak-hawtio.json和keycloak-hawtio-client.json文件复制到$EAP_HOME/standalone/configuration目录。 - 按照 JBoss 适配器 文档 中所述,将 Red Hat Single Sign-On adapter 子系统安装到您的 JBoss EAP 6.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>在
security-domains部分将 Hawtio 域添加到同一文件中:<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>将
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>使用 Hawtio 重新启动 JBoss EAP 6.4 服务器:
cd $EAP_HOME/bin ./standalone.sh -Djboss.socket.binding.port-offset=101
- 访问地址为 http://localhost:8181/hawtio.它受 Red Hat Single Sign-On 的安全。
2.1.7. JBoss Fuse 7 Adapter
红帽单点登录支持在 JBoss Fuse 7 中运行 Web 应用程序的安全。
JBoss Fuse 7 使用 Undertow 适配器,它与 JBoss Fuse 7 适配器 和 JBoss Fuse 7.4.0 捆绑在一起,在 covers 和 Undertow 下用于运行各种 Web 应用。
唯一支持的 Fuse 7 版本是最新的版本。如果您使用较早版本的 Fuse 7,则某些功能可能无法正常工作。特别是,对于低于 7.0.1 的 Fuse 7 版本,集成不能在所有这些工作。
Fuse 支持以下项目的安全性:
- 使用 Pax Web War 扩展器在 Fuse 上部署的经典 WAR 应用程序
- 在 Fuse 上部署的 OSGI 服务时带有 Pax Web Whiteboard 扩展器,另外还通过 org.osgi.service.http.HttpService#registerServlet ()(标准 OSGi 企业 HTTP 服务)注册的 servlet
- 使用 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-undertow 和 keycloak-jaas 功能。keycloak-pax-http-undertow 功能包括 Fuse 适配器和所有第三方依赖项。keycloak-jaas 包含 realm 用于 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
流程
- 启动 JBoss Fuse 7.4.0
在 Karaf 终端中,键入:
feature:repo-add mvn:org.keycloak/keycloak-osgi-features/15.0.8.redhat-00001/xml/features feature:install keycloak-pax-http-undertow keycloak-jaas
您可能还需要安装 Undertow 功能:
feature:install pax-http-undertow
确定安装了功能:
feature:list | grep keycloak
2.1.7.2.2. 从 ZIP 捆绑包安装
如果您离线,或者不想使用 Maven 获取 JAR 文件和其他工件,这将非常有用。
流程
- 从 Sotware Downloads 站点下载 Red Hat Single Sign-On Fuse adapter ZIP 归档。
将它解压缩到 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.5.3-fuse-adapter.zip
启动 Fuse 并在 fuse/karaf 终端中运行这些命令:
feature:repo-add mvn:org.keycloak/keycloak-osgi-features/15.0.8.redhat-00001/xml/features feature:install keycloak-pax-http-undertow keycloak-jaas
-
安装对应的 Undertow 适配器。由于工件直接在 JBoss Fuse
系统目录中可用,因此您不需要使用 Maven 存储库。
2.1.7.3. 保护经典 WAR 应用程序
流程
在
/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>
在 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" } }- 与 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系统属性指定的文件夹中搜索名为 <your_web_context>-keycloak.jsonkeycloak.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/contextURI,则会搜索以下配置位置是否存在,直到第一个配置位置存在:-
${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 捆绑项目中具有不部署为经典 WAR 应用的 servlet 类,您可以使用此方法。Fuse 使用 Pax Web Whiteboard 扩展器来部署此类 servlet,如 Web 应用程序。
流程
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 应用 部分中所述。请注意,您不需要web.xml文件作为 security-constraints 在蓝图配置文件中声明。- 与 Fuse 6 适配器不同,MANIFEST.MF 中不需要特殊的 OSGi 导入。
2.1.7.5. 保护 Apache Camel 应用程序
您可以通过蓝图注入正确的安全限制,使用 camel-undertow 组件实施 Apache Camel 端点,并将使用的组件更新为 undertow-keycloak。您必须使用类似配置在 Camel 应用程序中添加 OSGI-INF/blueprint/blueprint.xml 文件。角色、安全约束映射和适配器配置可能会根据您的环境和需求稍有不同。
与标准的 undertow 组件相比,undertow-keycloak 组件会添加两个新属性:
-
configResolver是一个提供 Red Hat Single Sign-On 适配器配置的解析器 Bean。可用解析器会在 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&configResolver=#keycloakConfigResolver&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="15.0.8.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 引擎上运行红帽单点登录保护的 CXF 端点,请执行以下步骤:
流程
将
OSGI-INF/blueprint/blueprint.xml添加到您的应用中,然后添加正确的配置解析器与 Camel 配置 类似。在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>-
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="15.0.8.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 客户服务端点,该端点特定于您的应用。
<?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.symbolicNameandcontext.id-
识别
org.ops4j.pax.web.service.WebContainer中的捆绑包及其部署上下文。 context.param.keycloak.config.resolver-
为捆绑包提供
keycloak.config.resolver上下文参数的值,与适用于典型 WAR 的 web.xml 中的web.xml相同。在 Configuration Resolvers 部分中介绍了可用的解析器。 login.config.authMethod-
身份验证方法.必须为
KEYCLOAK。 security.anyName.url和security.anyName.roles单个安全约束的属性值正如分别在
security-constraint/web-resource-collection/url-pattern和security-constraint/auth-constraint/role-name中设置。角色用逗号和空格分开。anyName标识符可以是任意名称,但必须匹配同一安全约束的独立属性。注意某些 Fuse 版本包含一个错误,需要由
"、"(comma 和单个空格)分隔角色。确保使用精确此表示法来分隔角色。
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 终端
Red Hat Single Sign-On 主要解决了用于 Web 应用程序身份验证的用例;但是,如果您的其他 Web 服务和应用程序受 Red Hat Single Sign-On 保护,使用 Red Hat Single Sign-On 凭证保护非 Web 管理服务(如使用 Red Hat Single Sign-On 凭证的 SSH)是一个最好的 pcrice。您可以使用 JAAS 登录模块进行此操作,它允许远程连接 Red Hat Single Sign-On,并根据 Resource Owner Password Credentials 来验证凭据。
要启用 SSH 身份验证,请执行以下步骤。
流程
-
在 Red Hat Single Sign-On 中,创建一个客户端(例如
ssh-jmx-admin-client),它将用于 SSH 身份验证。此客户端需要在上选择直接访问 Grants Enabled。 在
$FUSE_HOME/etc/org.apache.karaf.shell.cfg文件中,更新或指定此属性:sshRealm=keycloak
添加
$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" } }此文件指定客户端应用配置,供 JAAS DirectAccessGrantsLoginModule 从
keycloakJAAS 域用于 SSH 身份验证。启动 Fuse 并安装
keycloakJAAS 域。最简单的方法是安装keycloak-jaas功能,它预定义了 JAAS 域。您可以使用您自己的keycloakJAAS 域覆盖功能的预定义域,并具有更高等级的等级。详情请查看 JBoss Fuse 文档。在 Fuse 终端中使用这些命令:
features:addurl mvn:org.keycloak/keycloak-osgi-features/15.0.8.redhat-00001/xml/features features:install keycloak-jaas
以
admin用户身份使用 SSH 登录,在终端中输入以下内容:ssh -o PubkeyAuthentication=no -p 8101 admin@localhost
-
使用密码登录。
在一些后续的操作系统中,您可能需要默认使用 SSH 命令的 -o 选项 -o HostKeyAlgorithms=+ssh-dss,因为稍后的 SSH 客户端不允许使用 ssh-dss 算法。但是,默认情况下,它目前在 JBoss Fuse 7.4.0 中使用。
请注意,用户需要具有 realm 角色 admin 来执行所有操作或另一个角色,以执行一系列操作(例如,查看器 角色),可限制用户仅运行只读 Karaf 命令。可用的角色在 $FUSE_HOME/etc/org.apache.karaf.shell.cfg 或 $FUSE_HOME/system.properties 中进行配置。
2.1.7.9.2. 使用 JMX 验证
如果要使用 jconsole 或其他外部工具通过 RMI 远程连接到 JMX,则可能需要 JMX 身份验证。否则,最好使用 hawt.io/jolokia,因为 jolokia 代理默认安装在 hawt.io 中。如需了解更多详细信息,请参阅 海军管理员管理员控制台。
要使用 JMX 身份验证,请执行以下步骤:
流程
在
$FUSE_HOME/etc/org.apache.karaf.management.cfg文件中,将 jmxRealm 属性更改为:jmxRealm=keycloak
-
安装
keycloak-jaas功能并配置$FUSE_HOME/etc/keycloak-direct-access.json文件,如上面的 SSH 部分所述。 - 在 jconsole 中,您可以使用以下 URL:
service:jmx:rmi://localhost:44444/jndi/rmi://localhost:1099/karaf-root
and credentials: admin/password (基于您的环境具有 admin 权限的用户)。
2.1.7.10. 保护 Hawtio 管理控制台
要使用 Red Hat Single Sign-On 保护 Hawtio 管理控制台,请执行以下步骤:
流程
-
在您的域中,在 Red Hat Single Sign-On Admin Console 中创建客户端。例如,在 Red Hat Single Sign-On
demorealm 中,创建一个客户端hawtio-client,将public指定为 Access Type,并指定指向 Hawtio 的重定向 URI:配置对应的 Web Origin (本例中为 http://localhost:8181)。设置客户端范围映射,以在hawtio-client客户端详情中包含 帐户 客户端客户端的 view-profile 客户端角色。 使用以下示例中所示的内容,在
$FUSE_HOME/etc目录中创建keycloak-hawtio-client.json文件。根据您的 Red Hat Single Sign-On 环境,更改realm、资源和auth-server-url属性。resource属性必须指向上一步中创建的客户端。此文件供客户端(Hawtio JavaScript 应用)侧使用。{ "realm" : "demo", "clientId" : "hawtio-client", "url" : "http://localhost:8080/auth", "ssl-required" : "external", "public-client" : true }使用以下示例中所示的内容,在
$FUSE_HOME/etc目录中创建keycloak-direct-access.json文件。根据您的 Red Hat Single Sign-On 环境更改realm和url属性。此文件供 JavaScript 客户端使用。{ "realm" : "demo", "resource" : "ssh-jmx-admin-client", "auth-server-url" : "http://localhost:8080/auth", "ssl-required" : "external", "credentials": { "secret": "password" } }使用以下示例中所示的内容,在
$FUSE_HOME/etcdicrectory 中创建keycloak-hawtio.json文件。根据您的红帽单点登录环境,更改realm和auth-server-url属性。此文件供服务器(JAAS 登录模块)中的适配器使用。{ "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" }启动 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进入 http://localhost:8181/hawtio,并以 Red Hat Single Sign-On 域的用户身份登录。
请注意,用户需要适当的域角色才能成功向 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 适配器 JAR 添加到应用程序中。然后您必须通过普通的 Spring Boot 配置(application.properties)提供一些额外的配置。
Keycloak Spring Boot 适配器利用 Spring Boot 的自动配置优势,因此所有您需要这样做的目的是将这个适配器 Keycloak Spring Boot starter 添加到您的项目中。
流程
要使用 Maven 将初学者添加到项目中,请在依赖项中添加以下内容:
<dependency> <groupId>org.keycloak</groupId> <artifactId>keycloak-spring-boot-starter</artifactId> </dependency>添加 Adapter BOM 依赖项:
<dependencyManagement> <dependencies> <dependency> <groupId>org.keycloak.bom</groupId> <artifactId>keycloak-adapter-bom</artifactId> <version>15.0.8.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。
流程
您可以通过普通的 Spring Boot 配置来配置 Spring Boot 适配器的域,而不是
keycloak.json文件。例如: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 (例如在测试中)。-
要配置 Policy Enforcer,与 keycloak.json 不同,请使用
policy-enforcer-config而不是policy-enforcer。 指定通常位于
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 过滤器适配器
如果您在没有 Red Hat Single Sign-On 适配器的平台上部署 Java Servlet 应用程序,则您选择使用 servlet 过滤器适配器。这个适配器的工作方式与其他适配器不同。在 web.xml 中定义安全约束。而是使用 Red Hat Single Sign-On servlet 过滤器适配器定义一个过滤器映射来保护您要安全的 url 模式。
Backchannel logout 的工作方式与标准适配器不同。它不会无效的 HTTP 会话,而是将其标记为已注销的会话 ID。没有标准的方法来基于会话 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 的 path-pattern。默认情况下不配置 skipPattern。
模式与没有 上下文路径 的 requestURI 匹配。如果 context-path /myapp a request for /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 Console 中配置客户端,使用指向过滤器的 url-pattern 所涵盖的安全部分的 Admin URL。
Admin URL 将向 Admin URL 发出回调,以便执行类似后端注销的操作。因此,本例中的 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 过滤器具有与其他适配器相同的配置参数,但您必须将它们定义为过滤 initparams 而不是上下文参数。
要使用此过滤器,请将此 maven 工件包括在您的 WAR poms 中:
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-servlet-filter-adapter</artifactId>
<version>15.0.8.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 的客户端适配器有一些错误处理工具。在身份验证过程中遇到错误时,Red Hat Single Sign-On 将调用 HttpServletResponse.sendError ()。您可以在 web.xml 文件中设置错误页面,以处理错误,但您想要。Red Hat Single Sign-On 可以抛出 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?redirect_uri=encodedRedirectUri,如果您与浏览器有 SSO 会话,您会注销。
在使用 HttpServletRequest.logout () 选项时,适配器针对 Red Hat Single Sign-On 服务器通过刷新令牌执行 back-channel POST 调用。如果方法从未受保护的页面(一个没有检查有效令牌的页面)执行,则刷新令牌不可用,在这种情况下,适配器会跳过调用。因此,建议使用一个受保护的页面来执行 HttpServletRequest.logout (),以便当前令牌始终考虑帐户,并在需要时执行与红帽单点登录服务器的交互。
如果您想要避免作为注销过程的一部分注销外部身份提供程序,您可以提供 启动_idp 参数,并将值是问题中身份提供程序的身份(别名)。当作为由外部身份提供程序启动的单个注销的一部分调用 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 授权端点。
支持的参数有:
-
Scope - 使用空格分隔的范围列表。空格分隔的列表通常参考特定 客户端上定义的客户端范围。请注意,范围
openid将始终添加到适配器的范围列表中。例如,如果您输入范围选项地址电话,则 Red Hat Single Sign-On 的请求将包含范围参数scope=openid 地址电话。 提示 - Red Hat Single Sign-On 支持这些设置:
-
login- SSO 将被忽略,并且始终会显示 Red Hat Single Sign-On 登录页面,即使该用户已经通过身份验证 -
同意- 仅对具有必要条件的客户端适用。如果使用了,则始终会显示 Consent 页面,即使用户之前授予这个客户端。 -
none- 不会显示登录页面;相反,用户将重定向到应用程序,如果用户还没有通过身份验证,则会出现错误。此设置允许您在应用程序一侧创建一个过滤器/中断器,并向用户显示自定义错误页面。请参阅规格中的更多详情。
-
-
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 客户端需要发送 backchannel 请求(例如,为令牌交换代码,或刷新令牌)时,它需要针对 Red Hat Single Sign-On 服务器进行身份验证。默认情况下,可以通过三种方式验证客户端:客户端 ID 和客户端机密,客户端使用签名 JWT 进行身份验证,或使用客户端机密通过签名的 JWT 进行客户端身份验证。
2.1.14.1. 客户端 ID 和客户端 Secret
这是 OAuth2 规范中介绍的传统方法。客户端有一个 secret,需要同时识别适配器(应用程序)和 Red Hat Single Sign-On 服务器。您可以在 Red Hat Single Sign-On Admin 控制台中生成特定客户端的机密,然后将此 secret 粘贴到应用程序侧的 keycloak.json 文件中:
"credentials": {
"secret": "19666a4f-32dd-4049-b082-684c74115f28"
}2.1.14.2. 使用签名 JWT 进行客户端身份验证
这基于 RFC7523 规范。它以这种方式工作:
-
客户端必须具有私钥和证书。对于 Red Hat Single Sign-On,这可以通过传统的
密钥存储文件获得,该文件可在客户端应用的类路径上或文件系统中某个位置提供。 - 客户端应用程序启动后,它允许以 JWKS 格式下载其公钥,使用 http://myhost.com/myapp/k_jwks 等 URL 来下载其公钥,假设 http://myhost.com/myapp 是客户端应用程序的基本 URL。此 URL 可以被 Red Hat Single Sign-On 使用(请参阅以下)。
-
在身份验证过程中,客户端会生成一个 JWT 令牌,并使用其私钥为其签名,并将其发送到特定后端请求的红帽单点登录(如 code-to-token 请求)在
client_assertion参数中。 Red Hat Single Sign-On 必须具有客户端的公钥或证书,以便它可以验证 JWT 上的签名。在 Red Hat Single Sign-On 中,您需要为客户端配置客户端凭证。首先,您需要在管理控制台的选项卡
凭据中选择签署的JWT作为验证客户端的方法。然后您可以选择在密钥选项卡中之一:-
配置 JWKS URL,Red Hat Single Sign-On 可下载客户端的公钥。这可以是 URL,如 http://myhost.com/myapp/k_jwks(请参阅上述信息)。这个选项最为灵活,因为客户端可以随时轮转其密钥,而红帽单点登录则始终在需要时下载新密钥,而无需更改配置。更准确地说,当 Red Hat Single Sign-On 在看到由 unknown
kid签名的令牌(密钥 ID)时下载新密钥。 - 以 PEM 格式、JWK 格式或从密钥存储上传客户端的公钥或证书。使用此选项时,公钥被硬编码,在客户端生成新密钥对时必须更改。如果您尚未提供自己的红帽单点登录管理控制台,您也可以从红帽单点登录管理控制台生成自己的密钥存储。有关如何设置 Red Hat Single Sign-On Admin Console 的详情,请参考 服务器管理指南。
-
配置 JWKS URL,Red Hat Single Sign-On 可下载客户端的公钥。这可以是 URL,如 http://myhost.com/myapp/k_jwks(请参阅上述信息)。这个选项最为灵活,因为客户端可以随时轮转其密钥,而红帽单点登录则始终在需要时下载新密钥,而无需更改配置。更准确地说,当 Red Hat Single Sign-On 在看到由 unknown
对于在适配器中设置,您需要在 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",
"token-expiration": 10
}
}
使用此配置时,密钥存储文件 keystore-client.jks 必须在您的 WAR 的 classpath 上可用。如果不使用前缀 classpath: 您可以指向运行客户端应用程序的文件系统中的任何文件。
2.1.15. 多租户
在我们的上下文中,多 Tenancy 意味着单个目标应用程序(WAR)可以通过多个红帽单点登录域进行保护。域可以位于同一红帽单点登录实例或不同的实例上。
实际上,这意味着应用程序需要有多个 keycloak.json 适配器配置文件。
您可以使用部署到不同 context-paths 的不同适配器配置文件来有多个 WAR 实例。但是,这可能会不方便,您可能还希望根据 context-path 以外的其他内容选择该域。
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);
}
}
}
您还需要配置将 KeycloakConfigResolver 实现用于 web.xml 中的 keycloak.config.resolver context-param:
<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 相同的域中托管
处理集群的过程并不像常规应用程序一样简单。主要的原因是浏览器和服务器端应用程序都向 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 存储的一个限制是,在 Cookie 中为每个 HTTP 请求传递了整个安全上下文。这会影响性能。
另一种小限制是无限限制,对单点的支持有限。如果 init servlet 注销(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,URI 被解析为用于访问 Red Hat Single Sign-On 的 URL。
例如,如果您的应用程序的 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 配置
您可以在 Red Hat Single Sign-On Admin 控制台中配置特定客户端的管理员 URL。Red Hat Single Sign-On 服务器使用它来将后端请求发送到应用程序以进行各种任务,如注销用户或推送吊销策略。
例如,backchannel logout 的工作方式是:
- 用户从一个应用程序发送注销请求
- 应用程序向 Red Hat Single Sign-On 发送注销请求
- Red Hat Single Sign-On 服务器使用户会话无效
- 然后,Red Hat Single Sign-On 服务器使用与会话关联的 admin url 发送 backchannel 请求到应用程序
- 当应用程序收到注销请求时,它会使对应的 HTTP 会话无效
如果 admin URL 包含 ${application.session.host},它将被替换为与 HTTP 会话关联的节点的 URL。
2.1.16.4. 注册应用程序节点
上一节中介绍了 Red Hat Single Sign-On 如何向与特定 HTTP 会话关联的节点发送注销请求。但是,在某些情况下,管理员可能希望将管理任务传播到所有注册的集群节点,而不仅仅是它们中的一个。例如,要在策略之前不向应用程序推送新内容,或者从应用程序注销所有用户。
在这种情况下,Red Hat Single Sign-On 需要了解所有应用程序集群节点,以便它将事件发送到所有这些应用程序。为了实现此目的,我们支持自动发现机制:
- 当新应用程序节点加入集群时,它会向 Red Hat Single Sign-On 服务器发送注册请求
- 申请可能因配置的定期间隔重新授权于 Red Hat Single Sign-On
- 如果 Red Hat Single Sign-On 服务器没有在指定超时内收到重新注册请求,则它会自动取消注册特定节点
- 当 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 中,您可以指定最大节点重新注册超时(应该大于适配器配置中的 register-node-period )。您还可以通过 Admin 控制台手动添加和删除集群节点,这在不想依赖于自动注册功能时很有用,或者在不使用自动取消注册功能时删除过时的应用程序节点会很有用。
2.1.16.5. 每个请求中的刷新令牌
默认情况下,应用程序适配器仅在访问令牌过期时刷新访问令牌。但是,您还可以将适配器配置为在每次请求上刷新令牌。这可能会对性能产生影响,因为您的应用会将更多的请求发送到红帽单点登录服务器。
启用该功能编辑应用程序的 WEB-INF/keycloak.json 文件并添加:
"always-refresh-token": true
这可能会对性能有显著影响。只有在您不能依赖后端信息传播且不要在策略前传播时,才启用这个功能。要考虑的另一个因素是,默认访问令牌具有较短的过期时间,因此即使注销没有传播,令牌将在注销的几分钟内过期。
2.2. JavaScript 适配器
Red Hat Single Sign-On 附带一个客户端 JavaScript 库,可用于保护 HTML5/JavaScript 应用程序。JavaScript 适配器为 Cordova 应用内置支持。
该程序库可以直接从位于 /auth/js/keycloak.js 的红帽单点登录服务器检索,并作为 ZIP 归档发布。
最佳实践是从 Red Hat Single Sign-On 服务器直接加载 JavaScript 适配器,因为升级服务器时会自动更新它。如果您将适配器复制到 web 应用程序,请确保仅在升级服务器后升级适配器。
需要注意的一点是,客户端必须是一个公共客户端,因为无法将客户端凭证存储在客户端的应用程序中。这可确保您为客户端配置的重定向 URI 正确且尽可能具体。
要使用 JavaScript 适配器,您必须首先在 Red Hat Single Sign-On Admin 控制台中为您的应用程序创建客户端。确保为 Access Type 选择了 public。
您还需要配置 Valid Redirect URI 和 Web Origins。具体来说,因为无法这样做,可能会导致安全漏洞。
在创建了客户端后,点 Installation 选项卡为 Format 选项 选择 Keycloak OIDC JSON,然后点击 Download。下载的 keycloak.json 文件应当托管在 Web 服务器上与 HTML 页面相同的位置。
另外,您可以跳过配置文件并手动配置适配器。
以下示例演示了如何初始化 JavaScript 适配器:
<html>
<head>
<script src="keycloak.js"></script>
<script>
function initKeycloak() {
var keycloak = new Keycloak();
keycloak.init().then(function(authenticated) {
alert(authenticated ? 'authenticated' : 'not authenticated');
}).catch(function() {
alert('failed to initialize');
});
}
</script>
</head>
<body onload="initKeycloak()">
<!-- your page content goes here -->
</body>
</html>
如果 keycloak.json 文件位于不同的位置,您可以指定它:
var keycloak = new Keycloak('http://localhost:8080/myapp/keycloak.json');或者,您也可以在带有所需配置的 JavaScript 对象中传递:
var keycloak = new Keycloak({
url: 'http://keycloak-server/auth',
realm: 'myrealm',
clientId: 'myapp'
});
默认情况下,为了进行身份验证,您需要调用 登录功能。但是,有两个选项可用于使适配器自动进行身份验证。您可以将 login-required 或 check-sso 传递给 init 功能。如果用户登录到 Red Hat Single Sign-On,或者未显示登录页面,则 login-required 将验证客户端。只有用户已登录后,check-sso 才会验证客户端,如果用户未在登录,则将重新重定向到应用程序,并保持未经身份验证的身份验证。
您可以配置 silent check-sso 选项。启用此功能后,您的浏览器不会完全重定向到 Red Hat Single Sign-On 服务器并返回应用程序,但此操作将在隐藏的 iframe 中执行,因此仅在应用初始化后,浏览器才会被浏览器初始化并解析。这在 SPAs (页面应用程序)中特别有用。
要启用 silent check-sso,您必须在 init 方法中提供 silentCheckSsoRedirectUri 属性。此 URI 需要在应用程序中是有效的端点(当然,必须将其配置为 Red Hat Single Sign-On 管理控制台中客户端的有效重定向):
keycloak.init({
onLoad: 'check-sso',
silentCheckSsoRedirectUri: window.location.origin + '/silent-check-sso.html'
})成功检查验证状态并从 Red Hat Single Sign-On 服务器检索令牌后,在 iframe 中载入 silent check-sso redirect uri 的页面。它没有将收到的令牌发送到主应用程序以外的其他任务,应该只类似如下:
<html>
<body>
<script>
parent.postMessage(location.href, location.origin)
</script>
</body>
</html>请注意,在指定位置的此页面必须由应用程序本身提供,且不是 JavaScript 适配器的一部分!
银级 检查功能 在某些现代化浏览器中受到限制。请参阅《 带跟踪保护》章节的现代浏览器。
要启用 login-required 设置 onLoad to login-required 并传递给 init 方法:
keycloak.init({
onLoad: 'login-required'
})
在验证了用户后,通过在 授权 标头中包括 bearer 令牌,为应用进行红帽单点登录保护的 RESTful 服务请求。例如:
var loadData = function () {
document.getElementById('username').innerText = keycloak.subject;
var url = 'http://localhost:8080/restful-service';
var req = new XMLHttpRequest();
req.open('GET', url, true);
req.setRequestHeader('Accept', 'application/json');
req.setRequestHeader('Authorization', 'Bearer ' + keycloak.token);
req.onreadystatechange = function () {
if (req.readyState == 4) {
if (req.status == 200) {
alert('Success');
} else if (req.status == 403) {
alert('Forbidden');
}
}
}
req.send();
};
请记住,要记住的一点是,访问令牌默认具有较短的过期时间,因此您可能需要在发送请求前刷新访问令牌。您可以通过 updateToken 方法进行此操作。更新Token 方法返回一个承诺,仅当令牌成功刷新时才会轻松地调用该服务,并在用户没有时显示错误。例如:
keycloak.updateToken(30).then(function() {
loadData();
}).catch(function() {
alert('Failed to refresh token');
});2.2.1. 会话状态 iframe
默认情况下,JavaScript 适配器会创建一个隐藏的 iframe,用于检测是否有 Single-Sign Out。这不需要任何网络流量,而是通过查看特殊状态 Cookie 来检索状态。通过设置传递给 init 方法的选项中的 checkLoginIframe: false 可禁用这个功能。
您不应该依赖直接查找此 Cookie。其格式可能会改变,它也与红帽单点登录服务器的 URL 相关联,而不是您的应用程序。
会话状态 iframe 功能在某些现代化浏览器中受到限制。请参阅 包含跟踪保护章节的现代浏览器。
2.2.2. 隐式和混合流
默认情况下,JavaScript 适配器使用 Authorization Code 流。
在这个版本中,Red Hat Single Sign-On 服务器会将授权代码(而非身份验证令牌)返回给应用。JavaScript 适配器会交换访问令牌 的代码,并在浏览器重新重定向到应用程序后刷新令牌。
Red Hat Single Sign-On 还支持 Implicit 流,其中使用 Red Hat Single Sign-On 成功身份验证后会立即发送访问令牌。这的性能可能比标准流更高,因为没有额外的请求来交换令牌代码,但在访问令牌过期时可能会产生影响。
但是,在 URL 片段中发送访问令牌可能是一个安全漏洞。例如,令牌可以通过 Web 服务器日志和浏览器历史记录泄露。
要启用隐式流,您需要在 Red Hat Single Sign-On Admin 控制台中为客户端启用 Implicit Flow Enabled 标志。您还需要传递参数 流,并将值 隐式 传递给 init 方法:
keycloak.init({
flow: 'implicit'
})需要注意的是,只提供了访问令牌,也没有刷新令牌。这意味着,访问令牌已过期后,应用程序必须重新指向 Red Hat Single Sign-On 来获取新的访问令牌。
红帽单点登录还支持 混合 流。
这要求客户端在管理控制台中启用 Standard Flow Enabled 和 Implicit Flow Enabled 标志。然后,Red Hat Single Sign-On 服务器会将代码和令牌发送到您的应用。访问令牌可以立即使用,而代码可以被交换来执行访问和刷新令牌。与隐式流类似,混合流非常适合性能,因为访问令牌会立即可用。但是,该令牌仍然在 URL 中发送,前面提到的安全漏洞可能仍会应用。
混合流程中的一个优点是,刷新令牌可供应用程序使用。
对于混合流程,您需要将带有值 hybrid 的参数值传递给 init 方法:
keycloak.init({
flow: 'hybrid'
})2.2.3. 带有 Cordova 的混合应用程序
Keycloak 支持使用 Apache Cordova 开发的混合移动应用。JavaScript 适配器有两种模式: cordova 和 cord :
ova -native
默认为 cordova,如果尚未配置任何适配器类型且有 window.cordova,则适配器将自动选择。登录后,它将打开一个 InApp Browser,允许用户与 Red Hat Single Sign-On 交互,然后通过重定向到 http://localhost 来返回应用程序。因此,您必须在 Admin Console 的客户端配置部分中将此 URL 列为有效的 redirect-uri。
虽然这个模式易于设置,但它也会有一些缺点:
- InApp-Browser 是嵌入在应用程序中且不是手机的默认浏览器。因此,它将有不同的设置,存储的凭证将不可用。
- InApp-Browser 可能也很慢,特别是在渲染更复杂的它们时。
- 在使用这种模式前,需要考虑安全性问题,例如,应用程序可以获取用户凭证的访问权限,因为它可以完全控制浏览器渲染登录页面,因此不允许在不信任的应用程序中使用。
使用此示例应用程序帮助您开始使用 :https://github.com/keycloak/keycloak/tree/master/examples/cordova
替代模式 cordova-native 采用不同的方法。它使用系统浏览器打开登录页面。用户通过身份验证后,浏览器使用特殊 URL 重新重定向到应用。在那里,Red Hat Single Sign-On 适配器可以通过从 URL 读取代码或令牌来完成登录。
您可以通过将适配器类型 cordova-native 传递给 init 方法来激活原生模式:
keycloak.init({
adapter: 'cordova-native'
})这个适配器需要两个额外的插件:
- Cordova-plugin-browsertab: 允许应用程序在系统的浏览器中打开网页
- Cordova-plugin-deeplinks :允许浏览器通过特殊 URL 重新重定向到您的应用程序
链接到每个平台上的应用程序的技术详情需要特殊设置。有关更多说明,请参阅 deeplinks 插件文档中的 Android 和 iOS 部分。
打开应用程序的不同链接:自定义方案(例如 myapp://login 或 android-app://com.example.myapp/https/example.com/login)和 Universal Links (iOS)/ Deep Links (Android)。虽然前者易于设置,并且通常更可靠地工作,但以后会提供额外的安全性,因为它们是唯一的,并且只有域的所有者可以注册它们。在 iOS 上已弃用 custom-URL。我们建议您使用通用链接,将回退站点与 custom-url 链接结合使用,以获得最佳可靠性。
另外,我们推荐以下步骤提高与 Keycloak 适配器的兼容性:
-
iOS 上的通用基础镜像看似更可靠地使用
response-mode设置为查询 -
要防止 Android 在重定向上打开应用程序新实例,请将以下代码片段添加到
config.xml中:
<preference name="AndroidLaunchMode" value="singleTask" />
有一个 app 示例,它演示了如何使用 native-mode: https://github.com/keycloak/keycloak/tree/master/examples/cordova-native
2.2.4. 自定义适配器
有时,在默认情况下不支持的环境中,需要运行 JavaScript 客户端(如 Capacitor)。为了使可以在这些类型的未知环境中使用 JavasScript 客户端来传递自定义适配器。例如,第三方库可以提供这样的适配器,以便在没有问题的情况下运行 JavaScript 客户端:
import Keycloak from 'keycloak-js';
import KeycloakCapacitorAdapter from 'keycloak-capacitor-adapter';
const keycloak = new Keycloak();
keycloak.init({
adapter: KeycloakCapacitorAdapter,
});这个特定软件包不存在,但它会给出一个很好的例子,说明如何把适配器传递给客户端。
您还可以自行进行适配器,因此您必须实施 KeycloakAdapter 界面中描述的方法。例如,以下 TypeScript 代码可确保正确实现所有方法:
import Keycloak, { KeycloakAdapter } from 'keycloak-js';
// Implement the 'KeycloakAdapter' interface so that all required methods are guaranteed to be present.
const MyCustomAdapter: KeycloakAdapter = {
login(options) {
// Write your own implementation here.
}
// The other methods go here...
};
const keycloak = new Keycloak();
keycloak.init({
adapter: MyCustomAdapter,
});自然,您也可以通过省略类型信息而无 TypeScript 执行此操作,但要确保正确实施接口将完全与您保留。
2.2.5. 之前的浏览器
JavaScript 适配器依赖于 Base64 (window.btoa 和 window.atob)、HTML5 History API 和可选的 Promise API。如果您需要支持不提供这些浏览器(如 IE9)),则需要添加多填充器。
polyfill 库示例:
- Base64 - https://github.com/davidchambers/Base64.js
- HTML5 History - https://github.com/devote/HTML5-History-API
- Promise - https://github.com/stefanpenner/es6-promise
2.2.6. 带有跟踪保护的现代浏览器
在一些浏览器的最新版本中,应用了各种 Cookie 策略,以防止第三方跟踪用户,如 Chrome 中的 SameSite 或完全阻止第三方 Cookie。预计这些策略会变得更严格,并且会随着时间的推移其他浏览器使用,最终导致第三方环境中的 Cookie 被浏览器完全不受支持并阻止。受此问题影响的适配器功能可能会在以后被弃用。
JavaScript adapter 依赖于第三方 Cookie 用于 Session Status iframe、silent check-sso 和 part for常规(非静默) 检查-sso。这些功能具有有限的功能,或者可根据浏览器对 Cookie 的限制性而完全禁用。适配器会尝试检测此设置并相应地做出反应。
2.2.6.1. 带有"SameSite=Lax by Default"策略的浏览器
如果在 Red Hat Single Sign-On side 以及应用程序端配置 SSL / TLS 连接,则支持所有功能。请参阅配置 SSL/TLS。受影响对于从版本 84 开始的 Chrome 示例。
2.2.6.2. 使用阻塞第三方 Cookie 的浏览器
不支持会话状态 iframe,并在 JS 适配器检测到此类浏览器行为时自动禁用。这意味着适配器无法将会话 Cookie 用于 Single Sign-Out 检测,且必须完全依赖令牌。这意味着,当用户在另一个窗口中注销时,使用 JavaScript 适配器的应用程序不会注销,直到它尝试刷新 Access Token。因此,建议将 Access Token Lifespan 设置为相对较短的时间,以便检测到注销而不是更早时间。请查看 会话和令牌超时。
不支持 silent check-sso,默认情况下回退到常规(非静默) 检查-sso。通过在传递给 init 方法的选项中设置 silentCheckSsoFallback: false 来更改此行为。在这种情况下,如果检测到限制浏览器行为,则检查-sso 将会被完全禁用。
常规的 check-sso 也会受到影响。由于 Session Status iframe 不支持,在适配器初始化时,必须进行额外的重定向到 Red Hat Single Sign-On 来检查用户的登录状态。这与标准行为不同,即使用 iframe 告知用户是否登录,并且仅在注销时执行重定向。
受影响的浏览器是以 13.1 版本开始的示例 Safari。
2.2.7. JavaScript Adapter Reference
2.2.7.1. Constructor
new Keycloak();
new Keycloak('http://localhost/keycloak.json');
new Keycloak({ url: 'http://localhost/auth', realm: 'myrealm', clientId: 'myApp' });2.2.7.2. Properties
- 已验证
-
如果用户通过身份验证,则为
true,否则为false。 - token
-
在向服务请求的
Authorization标头中发送的 base64 编码令牌。 - tokenParsed
- 将令牌解析为 JavaScript 对象。
- subject
- 用户 ID。
- idToken
- base64 编码的 ID 令牌。
- idTokenParsed
- 将解析的 id 令牌解析为 JavaScript 对象。
- realmAccess
- 与令牌关联的 realm 角色。
- resourceAccess
- 与令牌关联的资源角色。
- refreshToken
- base64 编码的刷新令牌,可用于检索新令牌。
- refreshTokenParsed
- 将刷新令牌解析为 JavaScript 对象。
- timeSkew
- 浏览器时间和 Red Hat Single Sign-On 服务器的时间间隔(以秒为单位)。这个值只是估算值,但在确定令牌是否已过期时就足够准确。
- responseMode
- init 中传递的响应模式(默认值是碎片)。
- 流
- init 中传递的流.
- adapter
允许您覆盖重定向的方式,其他浏览器相关的功能将由库处理。可用的选项:
- "默认" - 库使用浏览器 api 进行重定向(这是默认设置)
- "Cordova" - 库将尝试使用 InAppBrowser cordova 插件加载 keycloak login/registration 页面(当库在 cordova 生态系统中正常工作时)
- "Cordova-native" - 库尝试使用 BrowserTabs cordova 插件,打开登录和注册页面。这需要额外的设置来重定向到应用程序(请参阅 第 2.2.3 节 “带有 Cordova 的混合应用程序”)。
- Custom - 允许您实施自定义适配器(仅适用于高级用例)
- responseType
- 发送到带有登录请求的 Red Hat Single Sign-On 的响应类型。这根据初始化期间使用的流值来决定,但可通过设置此值来覆盖。
2.2.7.3. Methods
2.2.7.3.1. init (选项)
调用 来初始化适配器。
选项是一个对象,其中:
-
useNonce - 添加加密非ce 以验证身份验证响应是否与请求匹配(默认为
true)。 -
在Load - 指定负载时要执行的操作。支持的值为
login-required或check-sso。 - silentCheckSsoRedirectUri - 为 silent 验证设置重定向 uri 检查(在Load 上)是否设置为"check-sso"。
-
当浏览器不支持 silent
check-sso时,silent CheckSsoFallback - Enables fall back to regularcheck-sso(浏览器不支持 silent check-sso)。 - Token - 为令牌设置初始值。
- refreshToken - 为刷新令牌设置初始值。
- idToken - 为 id 令牌设置初始值(与令牌或刷新令牌一起使用)。
- timeSkew - 以秒数为单位为本地时间和 Red Hat Single Sign-On 服务器设置一个 skew 值(只能与令牌或刷新令牌一起使用)。
-
checkLoginIframe - Set to enable/disable monitoring login state (默认为
true)。 - checkLoginIframeInterval - 设置检查登录状态的时间间隔(默认为 5 秒)。
-
responseMode - 在登录请求时设置发送到 Red Hat Single Sign-On 服务器的 OpenID Connect 响应模式。有效值为
query或片段。默认值为片段,这意味着成功身份验证后,Red Hat Single Sign-On 将重定向到带有 URL 片段中添加的 OpenID Connect 参数的 JavaScript 应用。这通常是更安全的,它比查询进行了安全建议。 -
流 - 设置 OpenID Connect 流。有效值为
标准、隐式或混合。 -
enableLogging - 启用从 Keycloak 到控制台的日志消息(默认为
false)。 pkceMethod - 要使用的概念验证交换方法(PKCE)。配置这个值可启用 PKCE 机制。可用的选项:
- "S256" - 基于 SHA256 的 PKCE 方法
- MessageReceiveTimeout - 以毫秒为单位设置等待 Keycloak 服务器的消息响应的超时。例如,这用于等待第三方 Cookie 检查期间的消息。默认值为 10000。
返回在初始化完成时解析的承诺。
2.2.7.3.2. login(options)
重定向至 上的登录表单(选项是一个带有 redirectUri 和/或提示字段的可选对象)。
选项是一个对象,其中:
- redirecturi - 指定在登录后要重定向到的 uri。
-
提示 - 此参数允许在 Red Hat Single Sign-On 服务器端略自定义登录流。例如,如果值为 登录,则 enforce 显示
登录屏幕。如需详细信息以及提示参数的所有可能值,请参阅 Parameters Forwarding 部分。 -
maxAge - 只在用户已经通过身份验证时才使用。指定发生用户验证以来的最长时间。如果用户已经通过身份验证的时间超过
maxAge,则忽略 SSO,并且需要再次重新验证。 - loginHint - 用于预先填充登录格式的用户名/电子邮件字段。
-
Scope - 用来将 scope 参数转发到 Red Hat Single Sign-On 登录端点。使用空格分隔的范围列表。这些通常引用特定 客户端上定义的客户端范围。请注意,范围
openid将始终添加到适配器的范围列表中。例如,如果您输入范围选项地址电话,则 Red Hat Single Sign-On 的请求将包含范围参数scope=openid 地址电话。 - idpHint - 用于告知 Red Hat Single Sign-On 跳过显示登录页面,并自动重定向到指定的身份提供程序。如需了解更多信息,请参阅 身份提供程序文档。
-
action - 如果值为
register,则用户会被重定向到注册页面,否则为登录页面。 - locale - 设置 'ui_locales' query param,它符合 OIDC 1.0 规范的 3.1.2.1 部分。
-
cordovaOptions - 指定传递给 Cordova in-app-browser (如果适用)的参数。选项
隐藏和位置不受这些参数的影响。所有可用选项均在 https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-inappbrowser/ 中定义。示例:{ zoom: "no", hardwareback: "yes" };
2.2.7.3.3. createLoginUrl(options)
返回要登录表单的 URL (选项是一个带有 redirectUri 和/or prompt 字段的可选对象)。
选项是一个对象,支持与功能 登录 相同的选项。
2.2.7.3.4. logout (选项)
重定向 以注销。
选项是一个对象,其中:
- redirecturi - 指定在注销后要重定向到的 uri。
2.2.7.3.5. createLogoutUrl(options)
返回 URL 以注销用户。
选项是一个对象,其中:
- redirecturi - 指定在注销后要重定向到的 uri。
2.2.7.3.6. register(options)
重定向 以注册表。使用选项操作登录的快捷方式 = 'register'
选项与登录方法相同,但 'action' 设置为 'register'
2.2.7.3.7. createRegisterUrl(options)
返回 url 以注册页面。使用选项 action 创建LoginUrl 快捷方式 = 'register'
选项与 createLoginUrl 方法相同,但 'action' 设置为 'register'
2.2.7.3.8. accountManagement()
重定向至帐户管理控制台.
2.2.7.3.9. createAccountUrl(options)
将 URL 返回到帐户管理控制台。
选项是一个对象,其中:
- redirecturi - 指定在重定向到应用程序时要重定向到的 uri。
2.2.7.3.10. hasRealmRole(role)
如果令牌具有给定域角色,则返回 true。
2.2.7.3.11. hasResourceRole(role, resource)
如果令牌具有资源的给定角色(如果没有使用指定的 clientId,则返回资源为可选)。
2.2.7.3.12. loadUserProfile()
加载用户配置文件。
返回使用配置集解析的保证。
例如:
keycloak.loadUserProfile()
.then(function(profile) {
alert(JSON.stringify(profile, null, " "))
}).catch(function() {
alert('Failed to load user profile');
});2.2.7.3.13. isTokenExpired(minValidity)
如果令牌在过期前的 minValidity 秒少于 minValidity 秒,则返回 true (如果没有使用指定 0,minValidity 是可选的)。
2.2.7.3.14. updateToken(minValidity)
如果令牌在 minValidity 秒内过期(如果没有使用指定 5),则令牌为可选(如果没有使用指定 5)。如果启用了会话状态 iframe,则还会检查会话状态。
返回用布尔值解析的保证会指示令牌是否被刷新。
例如:
keycloak.updateToken(5)
.then(function(refreshed) {
if (refreshed) {
alert('Token was successfully refreshed');
} else {
alert('Token is still valid');
}
}).catch(function() {
alert('Failed to refresh the token, or the session has expired');
});2.2.7.3.15. clearToken()
清除身份验证状态,包括令牌。当应用程序检测到会话已过期时,这很有用,例如更新令牌失败。
调用此结果会导致调用AuthLogout 回调监听程序。
2.2.7.4. 回调事件
适配器支持为特定事件设置回调监听程序。
例如:
keycloak.onAuthSuccess = function() { alert('authenticated'); }可用的事件有:
- onReady (authenticated)- 在初始化适配器时调用。
- onAuthSuccess - 在用户成功身份验证时调用。
- onAuthError - 调用在身份验证过程中出现错误。
- onAuthRefreshSuccess - 在令牌被刷新时调用。
- 在尝试刷新令牌时出现错误,则 onAuthRefreshError - 调用它。
- onAuthLogout - 当用户注销时(仅在启用会话状态 iframe 或 Cordova 模式时才调用)。
- onTokenExpired - 当访问令牌过期时调用。如果刷新令牌可用时,可以使用 updateToken 刷新令牌,或者在不是(即隐式流)的情况下刷新令牌,您可以重定向到登录屏幕来获取新的访问令牌。
2.3. Node.js 适配器
Red Hat Single Sign-On 提供在 Connect (保护服务器端 JavaScript 应用)基础上构建的 Node.js 适配器,其目标是足够灵活地与 Express.js 等框架集成。
要使用 Node.js 适配器,首先必须在 Red Hat Single Sign-On Admin 控制台中为您的应用程序创建一个客户端。适配器支持公共、机密和仅 bearer 访问类型。要选择哪个选项取决于用例的场景。
在创建了客户端后,点 Installation 选项卡,选择 Red Hat Single Sign-On OIDC JSON for Format Options,然后点 Download。下载的 keycloak.json 文件应该在项目的根目录下。
2.3.1. 安装
假设您已经安装了 Node.js,请为您的应用程序创建一个文件夹:
mkdir myapp && cd myapp
使用 npm init 命令为应用程序创建 package.json。现在,在 dependencies 列表中添加 Red Hat Single Sign-On connect 适配器:
"dependencies": {
"keycloak-connect": "file:keycloak-connect-15.0.2.redhat-00001.tgz"
}2.3.2. 使用
- 实例化 Keycloak 类
-
Keycloak类为配置和集成提供中央点。最简单的创建涉及参数。
var session = require('express-session');
var Keycloak = require('keycloak-connect');
var memoryStore = new session.MemoryStore();
var keycloak = new Keycloak({ store: memoryStore });
默认情况下,这将找到名为 keycloak.json 的文件,以及应用程序的主可执行文件,以初始化特定于 keycloak 的设置(公钥、域名和各种 URL)。keycloak.json 文件从 Red Hat Single Sign-On Admin Console 获取。
通过此方法实例化可导致正在使用的所有默认值。另外,也可以提供配置对象,而不是 keycloak.json 文件:
let kcConfig = {
clientId: 'myclient',
bearerOnly: true,
serverUrl: 'http://localhost:8080/auth',
realm: 'myrealm',
realmPublicKey: 'MIIBIjANB...'
};
let keycloak = new Keycloak({ store: memoryStore }, kcConfig);应用程序也可以使用以下方法将用户重定向到首选身份提供程序:
let keycloak = new Keycloak({ store: memoryStore, idpHint: myIdP }, kcConfig);- 配置 web 会话存储
-
如果要使用 Web 会话管理服务器端状态以进行身份验证,则需要使用至少一个
store参数初始化Keycloak (…),传递express-session的实际会话存储。
var session = require('express-session');
var memoryStore = new session.MemoryStore();
var keycloak = new Keycloak({ store: memoryStore });- 传递自定义范围值
-
默认情况下,scope 值
openid作为参数传递给 Red Hat Single Sign-On 的登录 URL,但您可以添加额外的自定义值:
var keycloak = new Keycloak({ scope: 'offline_access' });2.3.3. 安装中间件
在实例化后,将中间件安装到支持连接的应用程序中:
var app = express();
app.use( keycloak.middleware() );2.3.4. 配置代理
如果应用程序在代理后面运行,则必须根据 代理指南后面的 代理配置 SSL 连接 Express。使用不正确的代理配置可能会导致生成无效的重定向 URI。
配置示例:
var app = express();
app.set( 'trust proxy', true );
app.use( keycloak.middleware() );2.3.5. 检查身份验证
要在访问资源前检查用户是否已通过身份验证,只需使用 keycloak.checkSso ()。仅当用户已经登录后,它才会进行身份验证。如果用户没有登录,该浏览器将被重新重定向到初始请求的 URL,并保持未经身份验证的身份验证:
app.get( '/check-sso', keycloak.checkSso(), checkSsoHandler );
2.3.6. 保护资源
- 简单的身份验证
-
要强制用户在访问资源前进行身份验证,只需使用
keycloak.protect ()的 no-argument 版本:
app.get( '/complain', keycloak.protect(), complaintHandler );
- 基于角色的授权
- 使用当前应用程序的应用程序角色保护资源:
app.get( '/special', keycloak.protect('special'), specialHandler );使用不同应用程序的应用程序角色 保护资源 :
app.get( '/extra-special', keycloak.protect('other-app:special'), extraSpecialHandler );使用 realm 角色保护资源的安全:
app.get( '/admin', keycloak.protect( 'realm:admin' ), adminHandler );
- 基于资源的授权
-
基于资源的授权允许您根据 Keycloak 中定义的一组策略来保护资源及其具体方法/操作,从而从应用程序外部化授权。这可以通过公开可用于保护资源的
keycloak.enforcer方法来实现。*
app.get('/apis/me', keycloak.enforcer('user:profile'), userProfileHandler);
keycloak-enforcer 方法以两种模式运行,具体取决于 response_mode 配置选项的值。
app.get('/apis/me', keycloak.enforcer('user:profile', {response_mode: 'token'}), userProfileHandler);
如果将 response_mode 设置为 令牌,则代表向您的应用程序的 bearer 令牌代表代表您的服务器上获取权限。在这种情况下,Keycloak 使用服务器获得的权限发布新的访问令牌。如果服务器没有响应具有预期权限的令牌,则请求会被拒绝。当使用此模式时,您应该能够从请求获取令牌,如下所示:
app.get('/apis/me', keycloak.enforcer('user:profile', {response_mode: 'token'}), function (req, res) {
var token = req.kauth.grant.access_token.content;
var permissions = token.authorization ? token.authorization.permissions : undefined;
// show user profile
});当应用程序正在使用会话时,首选此模式,并想从服务器缓存以前的决策,并自动处理刷新令牌。对于充当客户端和服务器的应用程序,这个模式特别有用。
如果将 response_mode 设为 权限 (默认模式),服务器只返回授予的权限列表,而不发出新的访问令牌。除了不发布新令牌外,此方法还通过 请求 公开服务器授予的权限,如下所示:
app.get('/apis/me', keycloak.enforcer('user:profile', {response_mode: 'permissions'}), function (req, res) {
var permissions = req.permissions;
// show user profile
});
无论正在使用的 response_mode 是什么,keycloak.enforcer 方法将首先尝试检查发送到应用程序的 bearer 令牌的权限。如果 bearer 令牌已采用预期的权限,则不需要与服务器交互来获取决策。这在您的客户端能够在访问受保护资源前从服务器获取访问令牌时特别有用,因此它们可以使用 Keycloak Authorization Services (如增量授权)提供的一些功能,并避免 keycloak.enforcer 被强制访问资源时对服务器的额外请求。
默认情况下,策略强制程序将使用定义为应用程序(例如,通过 keycloak.json)定义的 client_id 来引用 Keycloak 授权服务中的客户端。在这种情况下,客户端不能是公共的,它实际上是一个资源服务器。
如果您的应用程序同时充当公共客户端(frontend)和资源服务器(backend),您可以使用以下配置来引用 Keycloak 中的不同客户端,并带有您要强制的策略:
keycloak.enforcer('user:profile', {resource_server_id: 'my-apiserver'})建议您在 Keycloak 中使用不同的客户端来代表您的前端和后端。
如果您使用 Keycloak 授权服务启用了保护的应用程序,且已在 keycloak.json 中定义客户端凭证,您可以将额外声明推送到服务器,并供您的策略使用。为此,您可以定义一个 声明配置选项,它需要一个功能来返回一个带有您要推送的声明的 JSON:
app.get('/protected/resource', keycloak.enforcer(['resource:view', 'resource:write'], {
claims: function(request) {
return {
"http.uri": ["/protected/resource"],
"user.agent": // get user agent from request
}
}
}), function (req, res) {
// access granted有关如何配置 Keycloak 以保护应用程序资源的详情,请查看授权服务 指南。
- 高级授权
- 要根据 URL 本身的一部分保护资源,假设每个部分都有一个角色:
function protectBySection(token, request) {
return token.hasRole( request.params.section );
}
app.get( '/:section/:page', keycloak.protect( protectBySection ), sectionHandler );高级登录配置:
默认情况下,所有未授权的请求都会被重新定向到 Red Hat Single Sign-On 登录页面,除非您的客户端仅是 bearer。但是,机密或公共客户端可以托管可浏览和 API 端点。要防止在未经身份验证的 API 请求上重定向并返回 HTTP 401,您可以覆盖 redirectToLogin 功能。
例如,此覆盖会检查 URL 是否包含 /api/ 并禁用登录重定向:
Keycloak.prototype.redirectToLogin = function(req) {
var apiReqMatcher = /\/api\//i;
return !apiReqMatcher.test(req.originalUrl || req.url);
};2.3.7. 其他 URL
- 显式用户触发的 logout
-
默认情况下,中间件会捕获对
/logout的调用,以便通过 Red Hat Single Sign-On-centric logout 工作流向用户发送。这可以通过在middleware ()调用中指定logout配置参数来更改:
app.use( keycloak.middleware( { logout: '/logoff' } ));
当调用 user-triggered logout 时,可以传递一个 query 参数 redirect_url :
https://example.com/logoff?redirect_url=https%3A%2F%2Fexample.com%3A3000%2Flogged%2Fout
然后,这个参数被用作 OIDC logout 端点的重定向 url,用户会被重定向到 https://example.com/logged/out。
- Red Hat Single Sign-On Admin Callbacks
-
另外,中间件还支持来自红帽单点登录控制台的回调以注销单个会话或所有会话。默认情况下,这些类型的管理回调发生于
/的根 URL,但可通过向 Middleware()调用提供admin参数来更改:
app.use( keycloak.middleware( { admin: '/callbacks' } );2.4. 其他 OpenID Connect 库
Red Hat Single Sign-On 可通过提供的适配器进行保护,这些适配器通常更易于使用,并更好地与红帽单点登录集成。但是,如果您的编程语言、框架或平台没有可用于您的编程语言、框架或平台,您可以选择使用通用 OpenID Connect Relying party (RP)库。本章论述了特定于 Red Hat Single Sign-On 的详细信息,不包含特定的协议详情。如需更多信息,请参阅 OpenID Connect 规格 和 OAuth2 规格。
2.4.1. Endpoints
最重要的端点是 已知的 配置端点。它列出了与 Red Hat Single Sign-On 中 OpenID Connect 实施相关的端点和其他配置选项。端点是:
/realms/{realm-name}/.well-known/openid-configuration
要获取完整的 URL,请添加 Red Hat Single Sign-On 的基本 URL,并将 {realm-name} 替换为您的域的名称。例如:
http://localhost:8080/auth/realms/master/.well-known/openid-configuration
某些 RP 库从此端点检索所有必需的端点,但您可能需要单独列出端点。
2.4.1.1. 授权端点
/realms/{realm-name}/protocol/openid-connect/auth授权端点执行最终用户的身份验证。这可以通过将用户代理重定向到此端点来完成。
如需了解更多详细信息,请参阅 OpenID Connect 规格中的 Authorization Endpoint 部分。
2.4.1.2. 令牌端点
/realms/{realm-name}/protocol/openid-connect/token令牌端点用于获取令牌。令牌可通过交换授权代码或直接提供凭证来获取,具体取决于所使用的流。令牌端点也用于在令牌过期时获取新的访问令牌。
如需了解更多详细信息,请参阅 OpenID Connect 规格中的 Token Endpoint 部分。
2.4.1.3. UserInfo 端点
/realms/{realm-name}/protocol/openid-connect/userinfouserinfo 端点返回有关经过身份验证的用户的标准声明,并由 bearer 令牌保护。
如需了解更多详细信息,请参阅 OpenID Connect 规格中的 Userinfo Endpoint 部分。
2.4.1.4. 注销端点
/realms/{realm-name}/protocol/openid-connect/logoutlogout 端点注销经过身份验证的用户。
用户可以代理重定向到端点,在这种情况下,活跃用户会话被注销。之后,用户代理会重新重定向到应用程序。
端点也可以由应用直接调用。要直接调用此端点,需要包含该端点,以及验证客户端所需的凭据。
2.4.1.5. 证书端点
/realms/{realm-name}/protocol/openid-connect/certs证书端点返回由域启用的公钥,编码为 JSON Web Key (JWK)。根据 realm 设置,可以启用一个或多个密钥来验证令牌。如需更多信息,请参阅 服务器管理指南和 JSON Web 密钥规格。
2.4.1.6. 内省端点
/realms/{realm-name}/protocol/openid-connect/token/introspect内省端点用于检索令牌的活动状态。换句话说,您可以使用它验证访问或刷新令牌。它只能被机密客户端调用。
有关如何在端点上调用的更多详细信息,请参阅 OAuth 2.0 Token Introspection 规格。
2.4.1.7. 动态客户端注册端点
/realms/{realm-name}/clients-registrations/openid-connect动态客户端注册端点用于动态注册客户端。
详情请查看客户端注册 章节 和 OpenID Connect Dynamic Client Registration 规格。
2.4.1.8. 令牌撤销端点
/realms/{realm-name}/protocol/openid-connect/revoke令牌撤销端点用于撤销令牌。此端点支持刷新令牌和访问令牌。
有关如何在这个端点上调用的更多详细信息,请参阅 OAuth 2.0 Token Revocation 规格。
2.4.1.9. 设备授权端点
/realms/{realm-name}/protocol/openid-connect/auth/device设备授权端点用于获取设备代码和用户代码。它可通过机密或公共客户端进行调用。
有关如何在这个端点上调用的更多详细信息,请参阅 OAuth 2.0 设备授权规格。
2.4.1.10. Backchannel Authentication 端点
/realms/{realm-name}/protocol/openid-connect/ext/ciba/auth后端通道身份验证端点用于获取 auth_req_id,用于标识客户端发出的身份验证请求。它只能被机密客户端调用。
有关如何在这个端点上调用的更多详细信息,请参阅 OpenID Connect Client Initiated Backchannel Authentication Flow 规格。
另请参阅 Red Hat Single Sign-On 文档的其他位置,如 本指南中的客户端初始身份验证身份验证评测部分以及《 服务器管理指南》 的客户端初始身份验证身份验证评测部分。
2.4.2. 验证访问令牌
如果您需要手动验证 Red Hat Single Sign-On 发布的访问令牌,您可以调用 Introspection Endpoint。这种方法的不足之处在于,您必须对红帽单点登录服务器进行网络调用。如果您同时出现太多验证请求,这可能会减慢服务器过载。红帽单点登录签发访问令牌是 JSON Web 令牌(JWT),采用 JSON Web 签名(JWS) 进行数字签名和编码。由于以这种方式编码,因此这允许您使用发出域的公钥在本地验证访问令牌。您可以在验证代码中硬编码域的公钥,或使用嵌入在 JWS 中的密钥 ID (KID)使用 证书端点 查找和缓存公钥。根据您编写的代码语言,第三方库的多个第三方库可帮助您进行 JWS 验证。
2.4.3. 流
2.4.3.1. 授权代码
授权代码流将用户代理重定向到 Red Hat Single Sign-On。用户通过 Red Hat Single Sign-On 成功进行身份验证后,创建授权代码并且用户代理重新重定向到应用程序。然后,应用程序使用授权代码及其凭证从 Red Hat Single Sign-On 获取 Access Token、Refresh Token 和 ID 令牌。
该流程针对 Web 应用程序为目标,但建议用于原生应用程序,包括移动应用,在其中可以嵌入用户代理。
如需了解更多详细信息,请参阅 OpenID Connect 规格中的 授权代码流。
2.4.3.2. 隐式
Implicit 流重定向与授权代码流类似,但会返回授权代码,而不是返回 Access Token 和 ID 令牌。这可减少额外调用以交换访问令牌授权代码的需求。但是,它不包括 Refresh Token。这会导致需要允许具有长过期时间的 Access Tokens,因为这很难使这些无效。或 需要新的重定向以在初始访问令牌过期后获取新的访问令牌。当应用程序只想验证用户并处理其本身时,Implicit 流很有用。
还有一个混合流程,同时返回 Access Token 和 Authorization Code。
需要注意的是,Implicit 流和混合流程都有潜在的安全风险,因为访问令牌可能会通过 Web 服务器日志和浏览器历史记录泄露。通过对访问令牌使用较短的过期时间可以缓解这个问题。
如需了解更多详细信息,请参阅 OpenID Connect 规格中的 Implicit Flow。
2.4.3.3. 资源所有者密码凭证
资源所有者密码凭证(称为 Red Hat Single Sign-On 中的 Direct Grant)允许交换令牌的用户凭证。除非您绝对需要,否则不建议使用此流。这很有用的示例是传统应用程序和命令行界面。
使用这个流程的限制有很多,包括:
- 用户凭证会公开给应用程序
- 应用程序需要登录页面
- 应用程序需要了解身份验证方案
- 更改身份验证流程需要更改应用程序
- 不支持身份代理或社交登录
- 不支持流(用户自我注册、所需操作等)
若要使客户端被允许使用 Resource Owner Password Credentials,客户端必须启用 Direct Access Grants Enabled 选项。
此流不包含在 OpenID Connect 中,而是属于 OAuth 2.0 规范的一部分。
如需更多详细信息,请参阅 OAuth 2.0 规格中的 Resource Owner Password Credentials Grant 章节。
2.4.3.3.1. 使用 CURL 的示例
以下示例演示了如何获取域 master 中用户的访问令牌,其密码为。这个示例使用机密客户端 myclient :
curl \ -d "client_id=myclient" \ -d "client_secret=40cc097b-2a57-4c17-b36a-8fdf3fc2d578" \ -d "username=user" \ -d "password=password" \ -d "grant_type=password" \ "http://localhost:8080/auth/realms/master/protocol/openid-connect/token"
2.4.3.4. 客户端凭证
客户端(应用程序和服务)希望代表自己而不是代表用户获得访问权限时,会使用客户端凭证。例如,这对于一般应用系统更改的后台服务很有用,而不是特定用户。
Red Hat Single Sign-On 支持客户端使用机密或公钥/私钥进行身份验证。
此流不包含在 OpenID Connect 中,而是属于 OAuth 2.0 规范的一部分。
如需更多详细信息,请参阅 OAuth 2.0 规范中的客户端凭据 级别章节。
2.4.3.5. 设备授权
在具有有限输入功能或缺少合适的浏览器的、在互联网连接的设备上运行的客户端使用设备授权。应用程序请求 Red Hat Single Sign-On a device code and user code。Red Hat Single Sign-On 创建了设备代码和用户代码。Red Hat Single Sign-On 将包括设备代码和用户代码返回响应。然后,应用为用户提供用户代码和验证 URI。用户使用其他浏览器访问验证 URI 进行验证。应用程序重复轮询 Red Hat Single Sign-On,直到 Red Hat Single Sign-On 完成用户授权。如果完成了用户身份验证,应用程序会获取设备代码。然后,应用程序使用设备代码及其凭证从 Red Hat Single Sign-On 获取 Access Token、Refresh Token 和 ID 令牌。
如需更多详细信息,请参阅 OAuth 2.0 设备授权规格。
2.4.3.6. 客户端发起的后向身份验证授权
客户端初始通道身份验证级别由希望与 OpenID 提供程序通信的客户端直接通信,而无需通过 OAuth 2.0 的授权代码授权等用户浏览器进行重定向。
客户端请求 Red Hat Single Sign-On a auth_req_id,用于标识客户端发出的身份验证请求。红帽单点登录创建 auth_req_id。
在收到这个 auth_req_id 后,这个客户端需要重复轮询 Red Hat Single Sign-On 以获取 Access Token、Refresh Token 和 ID Token,以返回 auth_req_id,直到用户通过身份验证为止。
如果客户端使用 ping 模式,则不需要重复轮询令牌端点,但可以等待红帽单点登录向指定的客户端通知端点发送的通知。客户端通知端点可以在 Red Hat Single Sign-On 管理控制台中配置。有关客户端通知端点的合同详情请参考 CIBA 规格。
如需了解更多详细信息,请参阅 OpenID Connect Client Initiated Backchannel Authentication Flow 规格。
另请参阅 Red Hat Single Sign-On 文档的其它位置,如 本指南的"后端身份验证"和" 服务器管理指南 "的"客户端 初始身份验证"一节。有关 FAPI CIBA 合规性的详情,请参考 本指南的 FAPI 部分。
2.4.4. 重定向 URI
使用基于重定向的流时,务必要为您的客户端使用有效的重定向 uri。重定向 uri 应该尽可能具体。这特别适用于客户端(公共客户端)应用程序。否则可能会导致:
- Open redirects - 这允许攻击者创建类似您的域的欺骗链接
- 未经授权的条目 - 当用户已经通过 Red Hat Single Sign-On 进行身份验证时,攻击者可以使用一个公共客户端,在无需用户的情况下重定向用户来获得访问权限
在生产环境中,Web 应用始终为所有重定向 URI 使用 https。不允许重定向到 http。
还有一个特殊的重定向 URI:
http://localhost- 此重定向 URI 可用于原生应用,并允许原生应用在随机端口上创建可用于获取授权代码的 Web 服务器。此重定向 uri 允许任何端口。
urn:ietf:wg:oauth:2.0:oob-
如果无法在客户端(或浏览器不可用)中启动 Web 服务器,可以使用特殊的
urn:ietf:wg:oauth:2.0:oob重定向 uri。当使用这个重定向 uri 时,Red Hat Single Sign-On 在标题和页面的框中显示一个带有代码的页面。应用程序可以检测到浏览器标题是否已更改,或者用户可以手动将代码复制到应用程序。在这个重定向 uri 中,用户可以使用不同的设备获取代码来粘贴到应用程序。
2.5. 财务级 API (FAPI)支持
Red Hat Single Sign-On 使管理员更容易确保其客户端符合这些规格:
此合规性意味着 Red Hat Single Sign-On 服务器将验证授权服务器的要求,具体如规范中所述。Red Hat Single Sign-On 适配器没有对 FAPI 的任何特定支持,因此需要在客户端(应用程序)侧需要手动验证,或者可能仍需要通过其他第三方解决方案进行。
2.5.1. FAPI 客户端配置集
为确保客户端符合 FAPI 兼容,您可以在您的域中配置 Client Policies,如 服务器管理指南 中所述,并将其链接到 FAPI 支持的全局客户端配置文件,它们可在每个域中自动可用。您可以根据需要客户端符合的 FAPI 配置文件,使用 fapi-1-baseline 或 fapi-1-advanced 配置集。
如果您要使用 Pushed Authorization Request (PAR),建议您的客户端同时使用 fapi-1-baseline 配置集和 fapi-1-advanced for PAR 请求。具体来说,F api-1-baseline 配置集包含 pkce-enforcer executor,这样可确保客户端使用带有安全 S256 算法的 PKCE。FAPI Advanced 客户端不需要这样做,除非它们使用 PAR 请求。
如果您要以 FAPI 兼容方式使用 CIBA,请确保您的客户端同时使用 fapi-1-advanced 和 fapi-ciba 客户端配置集。需要使用 fapi-1-advanced 配置集或其他包含请求的 executors 的客户端配置集,因为 fapi-ciba 配置集仅包含 CIBA-specific executors。当强制满足 FAPI CIBA 规格的要求时,需要更多要求,比如对机密客户端或证书绑定访问令牌的强制实施。
2.5.2. Open Banking Brasil Financial-grade API Security Profile
红帽单点登录与 Open Banking Brasil Financial-grade API Security Profile 1.0 实施者 Draft 2 兼容。与 FAPI 1 高级规格相比,这个要求要比 FAPI 1 高级 规格更加严格,因此可能需要以更严格的方式配置 Client Policies 来强制实施某些要求。特别是:
-
如果您的客户端没有使用 PAR,请确保它使用加密的 OIDC 请求对象。这可以通过使用启用了
Encryption的 client profile 及secure-request-objectexecutor 来实现。 -
确保对于 JWS,客户端使用
PS256算法。对于 JWE,客户端应使用RSA-OAEP和A256GCM。这可能需要在适用这些算法的所有 客户端设置 中设置。
2.5.3. TLS 注意事项
作为保密信息被交换,所有交互都应使用 TLS (HTTPS)加密。此外,FAPI 规格中有一些要求,适用于密码套件和 TLS 协议版本。要满足这些要求,您可以考虑配置允许的密码。此配置可以在 Elytron 子系统中的 KEYCLOAK_HOME/standalone/configuration/standalone-*.xml 文件中完成。例如,这个元素可以在 tls → server-ssl-contexts下添加
<server-ssl-context name="kcSSLContext" want-client-auth="true" protocols="TLSv1.2" \ key-manager="kcKeyManager" trust-manager="kcTrustManager" \ cipher-suite-filter="TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,TLS_DHE_RSA_WITH_AES_256_GCM_SHA384" protocols="TLSv1.2" />
对 kcKeyManager 和 kcTrustManager 的引用指的是对应的 Keystore 和 Truststore。详情请查看 Wildfly Elytron 子系统的文档,以及 Red Hat Single Sign-On 文档(如 网络设置 部分或 X.509 身份验证 部分)的其他部分。
第 3 章 使用 SAML 保护应用程序和服务
本节论述了如何使用 Red Hat Single Sign-On 客户端适配器或通用 SAML 供应商库通过 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>
其中一些配置切换可能特定于适配器,一些在所有适配器中都很常见。对于 Java 适配器,您可以使用 ${…} 213ure 作为系统属性替换。例如,${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>- entityID
- 这是此客户端的标识符。IdP 需要这个值来确定正在与之通信的客户端。此设置是 REQUIRED。
- sslPolicy
-
这是适配器将强制执行的 SSL 策略。有效值为:
ALL、EXTERNAL和NONE。对于all,所有请求都必须通过 HTTPS 访问。对于EXTERNAL,只有非私有 IP 地址必须通过 HTTPS 出现在线上。对于NONE,不需要通过 HTTPS 发出请求。此设置选项为 选项。默认值为EXTERNAL。 - nameIDPolicyFormat
-
SAML 客户端可以请求特定的 NameID 主题格式。如果您想要一个特定的格式,请填写这个值。它必须是标准的 SAML 格式标识符:urn
:oasis:names:tc:SAML:2.0:name-format:transient。此设置选项为 选项。默认情况下,没有请求特殊格式。 - forceAuthentication
-
SAML 客户端可以请求用户被重新验证,即使他们已在 IdP 中登录。把它设置为
true来启用。此设置选项为 选项。默认值为false。 - isPassive
-
SAML 客户端可以请求用户永远不会被要求验证,即使用户没有在 IdP 中登录。如果您想要这样做,则将其设置为
true。请勿与forceAuthentication一起使用,因为它们相反。此设置选项为 选项。默认值为false。 - turnOffChangeSessionIdOnLogin
-
在某些平台上成功登录时,会话 ID 被修改,以插入安全攻击向量。将此选项更改为
true以禁用此功能。建议您不要关闭它。默认值为false。 - autodetectBearerOnly
-
如果您的应用程序同时为 Web 应用程序和 Web 服务(如 SOAP 或 REST)提供,则此项应设为 true。它允许您将 Web 应用的未经身份验证的用户重定向到 Red Hat Single Sign-On 登录页面,但向未经身份验证的 SOAP 或 REST 客户端发送 HTTP
401状态代码,而不是将它们了解到登录页面。Red Hat Single Sign-On auto-detects SOAP 或 REST 客户端基于X-Requested-With、SOAPAction或Accept等典型标头。默认值为 false。 - logoutPage
-
这会将页面设置为在注销后显示。如果页面是完整的 URL,如
http://web.example.com/logout.html,则在使用 HTTP302状态代码注销后,用户会被重定向到该页面。如果指定了没有方案部分的链接,如/logout.jsp,则该页会在注销 后显示,无论它依赖于 web.xml 中的security-constraint声明,且页面针对部署上下文 root 解析。 - keepDOMAssertion
-
此属性应设置为 true,以便适配器将断言的 DOM 表示存储在与请求关联的
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>
Key 元素有两个可选属性 。当设置为 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>
以下是使用 KeyStore 元素定义的 XML 配置属性。
- file
- 密钥存储的文件路径。此选项是 选项。必须设置 file 或 resource 属性。
- resource
- KeyStore 的 WAR 资源路径。这是对 ServletContext.getResourceAsStream ()的方法调用时使用的路径。此选项是 选项。必须设置 file 或 resource 属性。
- password
- KeyStore 的密码。此选项是 REQUIRED。
如果您要定义 SP 将用来记录文档的密钥,还必须在 Java KeyStore 中指定对私钥和证书的引用。上例中的 PrivateKey 和证书元素定义了一个指向密钥存储内密钥或证书的别名。 密钥存储需要额外的密码才能访问私钥。在 PrivateKey 元素中,您必须在 password 属性中定义此密码。
3.1.1.2.2. 密钥 PEMS
在 Key 元素中,您直接使用 PrivateKeyPem、PublicKeyPem 和 CertificatePem 的子元素声明您的密钥和证书。这些元素中包含的值必须符合 PEM 密钥格式。如果您使用 openssl 或类似的命令行工具生成密钥,您通常会使用这个选项。
<Keys>
<Key signing="true">
<PrivateKeyPem>
2341251234AB31234==231BB998311222423522334
</PrivateKeyPem>
<CertificatePem>
211111341251234AB31234==231BB998311222423522334
</CertificatePem>
</Key>
</Keys>3.1.1.3. SP PrincipalNameMapping element
这个元素是可选的。在创建从 HttpServletRequest.getUserPrincipal () 等方法中获取的 Java Principal 对象时,您可以定义 Principal.getName () 方法返回的名称。
<SP ...> <PrincipalNameMapping policy="FROM_NAME_ID"/> </SP> <SP ...> <PrincipalNameMapping policy="FROM_ATTRIBUTE" attribute="email" /> </SP>
policy 属性定义用于填充此值的策略。这个属性的可能值有:
- FROM_NAME_ID
- 这个策略只使用任何 SAML 主题值。这是默认设置
- FROM_ATTRIBUTE
-
这将从从服务器接收的 SAML 断言中声明的其中一个属性中提取值。您需要指定在属性 XML 属性中使用的 SAML 断言属性的名称。
3.1.1.4. RoleIdentifiers 元素
RoleIdentifiers 元素定义从用户接收的断言内接收的 SAML 属性应该用作用户的 Jakarta EE 安全上下文中的角色标识符。
<RoleIdentifiers>
<Attribute name="Role"/>
<Attribute name="member"/>
<Attribute name="memberOf"/>
</RoleIdentifiers>
默认情况下 ,角色 属性值转换为 Jakarta EE 角色。有些 IdP 使用 member 或 memberOf 属性断言来发送角色。您可以定义一个或多个属性元素,以指定必须将哪些 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>
id 属性标识要使用哪个安装供应商。Property 子元素可以多次使用来为提供程序指定配置属性。
3.1.1.5.1. 基于属性的角色映射供应商
红帽单点登录包括 RoleMappingsProvider 实施,它利用属性文件执行 角色映射。此提供程序由 id properties-based-role-mapper 标识,它由 org.keycloak.adapters.saml.PropertiesBasedRoleMapper 类实施。
此提供程序依赖于两个配置属性,可用于指定要使用的 属性 文件的位置。首先,它利用配置的值来检查 properties.file.location 属性是否已指定,以 在文件系统中 定位属性文件。如果所配置的文件不在,则提供程序将引发 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>
如果尚未设置 配置,提供程序会检查 properties.file.locationproperties.resource.location 属性,使用配置的值从 WAR 资源加载属性文件。如果这个配置属性也不存在,则提供程序会尝试默认尝试从 /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>
属性 文件可以包含 roles 和 principals 作为键,以及用逗号分开的零个或多个角色列表,作为值。调用时,实施会迭代从断言中提取的角色集合,并在存在映射时对每个角色进行检查。如果角色映射到空角色,它将被丢弃。如果映射到一个或多个不同角色的集合,则会在结果集中设置这些角色。如果没有为角色找到映射,它将包含在结果集合中。
处理角色后,实施会检查从断言中提取的主体是否包含条目 属性文件。如果存在主体的映射,作为值列出的任何角色都会添加到结果集中。这允许将额外角色分配给主体。
例如,我们假设供应商已配置有以下属性文件:
roleA=roleX,roleY roleB= kc_user=roleZ
如果从具有 roleA、roleB 和 roleC 的断言器提取了主体的 kc_user,则分配给主体的最终角色集为 roleC、roleX、roleY 和 roleZ,因为 roleA 都被映射到 roleX 和 roleY, roleB 映射到空角色(因此被丢弃),roleC 会被原样使用,最后将一个额外的角色添加到 kc_user 主体(roleZ)。
注: 要在角色名称中使用空格进行映射,请使用 unicode 替换空间。例如,传入 'role A' 将显示为:
role\u0020A=roleX,roleY
3.1.1.5.2. 添加您自己的角色映射供应商
要添加自定义角色映射提供程序,只需实施 org.keycloak.adapters.saml.RoleMappingsProvider SPI。如需了解更多详细信息,请参阅 服务器开发人员指南中的 SAML 角色映射 SPI 部分。
3.1.1.6. IDP 元素
IDP 元素中的所有内容都描述了 SP (身份验证服务器)与 SP 通信的身份提供商(身份验证服务器)的设置。
<IDP entityID="idp"
signaturesRequired="true"
signatureAlgorithm="RSA_SHA1"
signatureCanonicalizationMethod="http://www.w3.org/2001/10/xml-exc-c14n#">
...
</IDP>
以下是您可以在 IDP 元素声明中指定的属性配置选项。
- entityID
- 这是 IDP 的签发者 ID。此设置是 REQUIRED。
- signaturesRequired
-
如果设置为
true,客户端适配器会将它发送的每个文档签名给 IDP。另外,客户端还希望 IDP 发送的所有文档都会被签名。此切换为所有请求和响应类型设置默认值,但您稍后您对此具有一些细致的控制。此设置包括 选项,默认为false。 - signatureAlgorithm
-
这是 IDP 要求使用签名文档的签名算法。允许的值有:
RSA_SHA1、RSA_SHA256、RSA_SHA512和DSA_SHA1。此设置是 OPTIONAL,默认为RSA_SHA256。 - signatureCanonicalizationMethod
-
这是 IDP 需要使用签名文档的签名规范方法。此设置选项为 选项。默认值为
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>
- 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"/>以下是您可以在这个元素上定义的配置属性:
- signRequest
-
客户端是否应该为 authn 请求签名?此设置选项为 选项。默认为 IDP
签名必需元素值的任何 IDP。 - validateResponseSignature
-
客户端是否应该为 IDP 签署从 auhtn 请求发回的断言响应文档?此设置 选项选项.默认为 IDP
签名必需元素值的任何 IDP。 - requestBinding
-
这是用于与 IDP 通信的 SAML 绑定类型。此设置选项为 选项。默认值为
POST,但您也可以将其设置为REDIRECT。 - responseBinding
-
SAML 允许客户端请求希望 authn 响应的绑定类型。这个值可以是
POST或REDIRECT。此设置选项为 选项。默认为客户端不会请求特定的绑定类型响应。 - assertionConsumerServiceUrl
-
IDP 登录服务(ACS)的断言使用者服务(ACS)的 URL 应向其中发送响应。此设置选项为 选项。默认情况下取消设置,它依赖于 IdP 中的配置。设置后,它必须以
/saml结尾,例如http://sp.domain.com/my/endpoint/for/saml。此属性的值在 SAMLAuthnRequest消息的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">- signRequest
-
客户端是否应该注销向 IDP 发出的请求?此设置选项为 选项。默认为 IDP
签名必需元素值的任何 IDP。 - signResponse
-
客户端是否应该注销它发送到 IDP 请求的响应?此设置选项为 选项。默认为 IDP
签名必需元素值的任何 IDP。 - validateRequestSignature
-
客户端是否应该从 IDP 中记录已签名的请求文档?此设置选项为 选项。默认为 IDP
签名必需元素值的任何 IDP。 - validateResponseSignature
-
客户端是否期望从 IDP 进行签名的注销响应文档?此设置选项为 选项。默认为 IDP
签名必需元素值的任何 IDP。 - requestBinding
-
这是用于向 IDP 发送 SAML 请求的 SAML 绑定类型。此设置选项为 选项。默认值为
POST,但您也可以将其设置为 REDIRECT。 - responseBinding
-
这是用于向 IDP 发送 SAML 响应的 SAML 绑定类型。这个值可以是
POST或REDIRECT。此设置选项为 选项。默认值为POST,但您也可以将其设置为REDIRECT。 - postBindingUrl
-
这是使用 POST 绑定时 IDP 注销服务的 URL。如果使用
POST绑定,则此设置是 REQUIRED。 - redirectBindingUrl
- 这是使用 REDIRECT 绑定时 IDP 注销服务的 URL。如果使用 REDIRECT 绑定,则此设置是 REQUIRED。
3.1.1.10. IDP 键子元素
IDP 的 Keys 子元素仅用于定义用来验证 IDP 签名的证书或公钥。它的定义方式与 SP 的 Keys 元素 相同。但是,您只需要定义一个证书或公钥引用。请注意,如果 Red Hat Single Sign-On server 和 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 子元素中声明将 签名 属性设置为 true 的多个 Key 元素来完成。当 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>3.1.1.11. IDP HttpClient 子元素
HttpClient 可选子元素定义了用于自动获取证书的 HTTP 客户端的属性,包含通过 IDP 的 SAML 描述符 在启用 时通过 IDP 进行签名验证的公钥。
<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" />- connectionPoolSize
-
此配置选项定义了与 Red Hat Single Sign-On 服务器的连接数量。这是 选项。默认值为
10。 - disableTrustManager
-
如果 Red Hat Single Sign-On 服务器需要 HTTPS,且这个配置选项被设置为
true,则不必指定信任存储。此设置仅应在开发期间使用,且不应 在生产环境中使用,因为它将禁用 SSL 证书的验证。这是 选项。默认值为false。 - allowAnyHostname
-
如果 Red Hat Single Sign-On 服务器需要 HTTPS,且这个配置选项被设置为
true,Red Hat Single Sign-On 服务器的证书通过 truststore 验证,但没有进行主机名验证。此设置仅应在开发期间使用,且不应在生产环境中使用,因为它部分禁用 SSL 证书的验证。在测试环境中,此集合可能有用。这是 选项。默认值为false。 - truststore
-
该值是 truststore 文件的文件路径。如果您为带有
classpath 的路径添加前缀:,则信任存储将从部署的类路径中获取。用于向 Red Hat Single Sign-On 服务器的外向 HTTPS 通信。进行 HTTPS 请求的客户端需要一种方式来验证所讨论的服务器主机。这是信任者的作用。密钥存储包含一个或多个可信主机证书或证书颁发机构。您可以通过提取红帽单点登录服务器 SSL 密钥存储的公共证书来创建此信任存储。这是 REQUIRED,除非禁用TrustManager为true。 - truststorePassword
-
truststore 的密码。如果设置了
truststore,则 REQUIRED 为 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 子系统。
然后,在 web.xml 中提供 keycloak 配置 /WEB-INF/keycloak-saml.xml 文件,并将 auth-method 更改为 KEYCLOAK-SAML。
您可以使用 ZIP 文件或 RPM 安装适配器。
3.1.3. 从 ZIP 文件安装适配器
每个适配器都是 Red Hat Single Sign-On 下载站点的独立下载。
流程
从 Downloads 站点安装适用于您的应用程序服务器的适配器。
在 JBoss EAP 7.x 上安装:
$ cd $EAP_HOME $ unzip rh-sso-saml-eap7-adapter.zip
在 JBoss EAP 6.x 上安装:
$ cd $EAP_HOME $ unzip rh-sso-saml-eap6-adapter.zip
这些 ZIP 文件在您的 JBoss EAP 分发中创建了特定于 JBoss EAP SAML 适配器的新 JBoss 模块。
使用 CLI 脚本在应用服务器配置中启用 Red Hat Single Sign-On SAML 子系统:
domain.xml或standalone.xml。启动服务器并运行应用到您的应用程序服务器的脚本。
对 JBoss EAP 7.1 或更高版本使用此命令
$ cd $JBOSS_HOME $ ./bin/jboss-cli.sh -c --file=bin/adapter-elytron-install-saml.cli
将此命令用于 JBoss EAP 7.0 和 EAP 6.4
$ cd $JBOSS_HOME $ ./bin/boss-cli.sh -c --file=bin/adapter-install-saml.cli
注意也可以在 JBoss EAP 7.1 或更高版本中使用旧的非Elytron 适配器,这意味着您可以在这些版本中使用
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>
当您需要在安全 Web 层中创建的安全上下文传播到您正在调用的 EJB (其他 EE 组件)时创建的安全上下文时,应结合使用 keycloak 安全域。否则,这个配置是可选的。
<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>安全上下文自动传播到 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。此设置表示,只有在请求来自同一域中时,才会将 Cookie 发送到应用程序。此行为可能会影响 SAML POST 绑定,这些绑定可能无法正常工作。要保留 SAML 适配器的完整功能,我们建议将容器创建的 JSESSIONID cookie 的 SameSite 值设置为 None。这样做可能会导致为容器的每个请求重置 Red Hat Single Sign-On 的会话。
为了避免将 SameSite 属性设置为 None,请考虑切换到 REDIRECT 绑定(如果可以接受),或者不需要进行这个临时解决方案的 OIDC 协议。
要将 Wildfly/EAP 中的 JSESSIONID cookie 的 SameSite 值设置为 None,请将包含以下内容的文件 undertow-handlers.conf 添加到您的应用程序的 WEB-INF 目录:
samesite-cookie(mode=None, cookie-pattern=JSESSIONID)
对此配置的支持在 19.1.0 版本 19.1.0 的 Wildfly 中提供。
3.1.4. 从 RPM 安装 JBoss EAP 7 适配器
在 Red Hat Enterprise Linux 7 中,术语频道被使用术语仓库替代。在这些说明中,仅使用术语存储库。
前提条件
您必须订阅 JBoss EAP 7 存储库,然后才能从 RPM 安装 EAP 7 适配器。
- 使用 Red Hat Subscription Manager 确保您的 Red Hat Enterprise Linux 系统已注册到您的帐户。如需更多信息,请参阅 红帽订阅管理文档。
如果您已订阅了另一个 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
流程
根据您的 Red Hat Enterprise Linux 版本,为 SAML 安装 EAP 7 适配器。
在 Red Hat Linux 7 上安装:
$ sudo yum install eap7-keycloak-saml-adapter-sso7_5
在 Red Hat Enterprise Linux 8 中安装:
$ sudo dnf install eap7-keycloak-adapter-sso7_5
注意RPM 安装的默认 EAP_HOME 路径为 /opt/rh/eap7/root/usr/share/wildfly。
为 SAML 模块运行安装脚本:
$ $EAP_HOME/bin/jboss-cli.sh -c --file=$EAP_HOME/bin/adapter-install-saml.cli
您的安装已完成。
3.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 系统已注册到您的帐户。如需更多信息,请参阅 红帽订阅管理文档。
- 如果您已订阅了另一个 JBoss EAP 存储库,必须先退订该存储库。
使用以下命令,使用红帽订阅管理器订阅 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
流程
使用以下命令为 SAML 安装 EAP 6 适配器:
$ sudo yum install keycloak-saml-adapter-sso7_5-eap6
注意RPM 安装的默认 EAP_HOME 路径为 /opt/rh/eap6/root/usr/share/wildfly。
为 SAML 模块运行安装脚本:
$ $EAP_HOME/bin/jboss-cli.sh -c --file=$EAP_HOME/bin/adapter-install-saml.cli
您的安装已完成。
3.1.5.1. 保护 WAR
这部分论述了如何通过在 WAR 软件包中添加配置和编辑文件直接保护 WAR 的安全。
您必须首先在 WAR 的 WEB-INF 目录中创建 keycloak-saml.xml 适配器配置文件。此配置文件的格式在 General Adapter Config 部分中描述。
接下来,您必须在 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>
除 auth-method 设置外的所有标准 servlet 设置。
3.1.5.2. 使用红帽单点登录 SAML 子系统保护 WAR
您不必打开 WAR 以通过 Red Hat Single Sign-On 对其进行保护。另外,您还可以通过 Red Hat Single Sign-On SAML Adapter 子系统从外部保护它。虽然您不必将 KEYCLOAK-SAML 指定为 auth-method,但在 web.xml 中定义 security-constraints。但是,您不必创建一个 WEB-INF/keycloak-saml.xml 文件。此元数据在服务器的 domain.xml 或 standalone.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>
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>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 过滤器的集群应用程序时,Backchannel logout 当前无法正常工作。
<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>Red Hat Single Sign-On 过滤器具有与其他适配器相同的配置参数,但您必须将其定义为过滤 initparams 而不是上下文参数。
如果您有不同的安全且不安全的 url 模式,可以定义多个过滤器映射。
您必须有一个包含 /saml 的过滤器映射。此映射覆盖所有服务器回调。
使用 IdP 注册 SP 时,您必须注册 http[s]://hostname/{context-root}/saml 作为 Assert Consumer Service URL 和 Single Logout Service URL。
要使用此过滤器,请将此 maven 工件包括在您的 WAR poms 中:
<dependency> <groupId>org.keycloak</groupId> <artifactId>keycloak-saml-servlet-filter-adapter</artifactId> <version>15.0.8.redhat-00001</version> </dependency>
要使用 Multi Tenancy the keycloak.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>3.1.7. 使用身份提供程序注册
对于基于 servlet 的适配器,您注册了断言使用者服务 URL 和单个注销服务的端点必须是附加到 servlet 应用的基本 URL,即 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,用于可分发的应用程序。作为前提条件,HTTP 会话需要在集群间发布(例如,应用程序在应用程序的 web.xml中被标记为 < distributable /> 标签)。
要启用这个功能,请在 /WEB_INF/web.xml 文件中添加以下部分:
对于 EAP 7,Wildic 10/11:
<context-param>
<param-name>keycloak.sessionIdMapperUpdater.classes</param-name>
<param-value>org.keycloak.adapters.saml.wildfly.infinispan.InfinispanSessionCacheIdMapperUpdater</param-value>
</context-param>对于 EAP 6:
<context-param>
<param-name>keycloak.sessionIdMapperUpdater.classes</param-name>
<param-value>org.keycloak.adapters.saml.jbossweb.infinispan.InfinispanSessionCacheIdMapperUpdater</param-value>
</context-param>
如果部署的会话缓存名为 deployment-cache,则用于 SAML 映射的缓存将命名为 deployment-cache.ssoCache。缓存的名称可以被上下文参数 keycloak.sessionIdMapperUpdater.infinispan.cacheName 覆盖。包含缓存的缓存容器与包含部署会话缓存的缓存容器相同,但可以通过上下文参数 keycloak.sessionIdMapperUpdater.infinispan.containerName 覆盖。
默认情况下,SAML 映射缓存的配置将从会话缓存衍生而来。可以在服务器的缓存配置部分中手动覆盖配置,与其它缓存相同。
目前,为了提供可靠的服务,建议为 SAML 会话缓存使用复制缓存。使用分布式缓存可能会导致 SAML 注销请求进入没有访问 SAML 会话索引到 HTTP 会话映射的节点,从而导致注销失败。
3.1.8.2. 在跨站点场景中注销
跨站点方案仅适用于 WildFly 10 及更高版本,EAP 7 及更高版本。
处理跨越多个数据中心的会话需要特殊处理。请考虑以下场景:
- 登录请求在数据中心 1 中的集群内处理。
- 管理问题注销特定 SAML 会话的请求,即数据中心 2 中的请求登录。
数据中心 2 必须注销数据中心 1 中存在的所有会话(以及共享 HTTP 会话的所有其他数据中心)。
要涵盖这种情况,需要将 上述 SAML 会话缓存不仅需要在一个单个集群内复制,而在所有数据中心中(例如,通过独立的 Infinispan/JDG 服务器 )进行复制:
- 缓存必须添加到独立的 Infinispan/JDG 服务器中。
- 前面几项中的缓存必须添加为对应的 SAML 会话缓存的远程存储。
在部署期间发现远程存储后,会在 SAML 会话缓存中显示,并相应地更新本地 SAML 会话缓存。
3.1.9. 获取断言属性
成功 SAML 登录后,应用程序代码可能需要获取使用 SAML 断言传递的属性值。HttpServletRequest.getUserPrincipal () 返回一个 Principal 对象,您可以将其输入到名为 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() {
...
}
}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>
客户端适配器还会设置您可以检索的 HttpServletRequest 属性。属性名称是 org.keycloak.adapters.spi.AuthenticationError。Typecast 这个对象为: 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;
}
}3.1.11. 故障排除
解决问题的方法是,在客户端适配器和 Red Hat Single Sign-On 服务器中为 SAML 启用调试。使用您的日志记录框架,将 org.keycloak.saml 软件包的日志级别设置为 DEBUG。完成此操作后,您可以查看正在发送到和从服务器发送的 SAML 请求和响应文档。
3.1.12. 多租户
SAML 为 多 密度提供与 OIDC 相同的功能,即单个目标应用程序(WAR)可以使用多个 Red Hat Single Sign-On 域进行保护。域可以位于同一红帽单点登录实例或不同的实例上。
为此,应用必须具有多个 keycloak-saml.xml 适配器配置文件。
虽然您可能有多个 WAR 实例,且不同的适配器配置文件部署到不同的上下文路径,但这可能会不方便,而且您可能还希望根据上下文路径以外的某些域进行选择。
Red Hat Single Sign-On 可以有自定义配置解析器,以便您可以为每个请求选择哪个适配器配置。在 SAML 中,配置只对登录处理非常感兴趣;一旦登录后,会话将进行身份验证,如果返回 keycloak-saml.xml 返回的 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);
}
}
}
您还必须配置用于 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>3.2. mod_auth_mellon Apache HTTPD 模块
mod_auth_mellon 模块是 SAML 的 Apache HTTPD 插件。如果您的语言/环境支持将 Apache HTTPD 用作代理,您可以使用 mod_auth_mellon 使用 SAML 保护您的 Web 应用程序。有关此模块的详情,请查看 mod_auth_mellon GitHub 仓库。
要配置 mod_auth_mellon,您需要:
- 一个身份提供程序(IdP)实体描述符 XML 文件,该文件描述了与 Red Hat Single Sign-On 或另一个 SAML IdP 的连接
- SP 实体描述符 XML 文件,用于描述您要保护的应用程序的 SAML 连接和配置。
- 私钥 PEM 文件,它是 PEM 格式的文本文件,用于定义应用程序用于签署文档的私钥。
- 证书 PEM 文件,这是为应用程序定义证书的文本文件。
- mod_auth_mellon-specific Apache HTTPD 模块配置。
3.2.1. Configuring mod_auth_mellon with Red Hat Single Sign-On
涉及两台主机:
- 运行 Red Hat Single Sign-On 的主机,称为 $idp_host,因为 Red Hat Single Sign-On 是 SAML 身份提供程序(IdP)。
- 运行 Web 应用的主机,称为 $sp_host。在 SAML 中,使用 IdP 的应用程序称为服务提供商(SP)。
以下所有步骤都需要在具有 root 权限的 $sp_host 上执行。
3.2.1.1. 安装软件包
要安装所需软件包,您需要:
- Apache Web 服务器(httpd)
- Mellon SAML SP 附加组件模块用于 Apache
- 创建 X509 证书的工具
要安装所需软件包,请运行以下命令:
yum install httpd mod_auth_mellon mod_ssl openssl
3.2.1.2. 为 Apache SAML 创建配置目录
建议您在一个位置保留与 Apache 使用 SAML 相关的配置文件。
在 Apache 配置根目录 /etc/httpd 下创建名为 saml2 的新目录:
mkdir /etc/httpd/saml2
3.2.1.3. 配置 Mellon 服务提供商
Apache 附加组件模块的配置文件位于 /etc/httpd/conf.d 目录中,且文件名扩展名 .conf。您需要创建 /etc/httpd/conf.d/mellon.conf 文件并将 Mellon 的配置指令放入其中。
Mellon 的配置指令可大致分为两类信息:
- 使用 SAML 身份验证保护的 URL
- 引用受保护的 URL 时,将使用 SAML 参数。
Apache 配置指令通常遵循 URL 空间中的层次结构,这些结构称为位置。您需要为 Mellon 指定一个或多个 URL 位置来保护。您具有如何添加适用于各个位置的配置参数的灵活性。您可以将所有必要参数添加到位置块中,也可以将 Mellon 参数添加到特定受保护位置的 URL 位置层次结构中的常用位置(或两者的某些组合)。由于 SP 以相同的方式运作,因此无论哪个位置触发 SAML 操作,因此此处使用的示例配置将通用 Mellon 配置指令放在层次结构的根目录中,然后可以使用最小指令定义特定位置。此策略可避免为每个受保护的位置复制相同的参数。
此示例只有一个受保护的位置:https://$sp_host/private。
要配置 Mellon 服务提供商,请执行以下步骤:
流程
- 使用以下内容创建文件 /etc/httpd/conf.d/mellon.conf:
<Location / >
MellonEnable info
MellonEndpointPath /mellon/
MellonSPMetadataFile /etc/httpd/saml2/mellon_metadata.xml
MellonSPPrivateKeyFile /etc/httpd/saml2/mellon.key
MellonSPCertFile /etc/httpd/saml2/mellon.crt
MellonIdPMetadataFile /etc/httpd/saml2/idp_metadata.xml
</Location>
<Location /private >
AuthType Mellon
MellonEnable auth
Require valid-user
</Location>以上代码中提到的一些文件会在后续步骤中创建。
3.2.2. 为 mod_auth_mellon 使用的 Cookie 设置 SameSite 值
浏览器计划将 Cookie 的 SameSite 属性的默认值设置为 Lax。此设置表示,只有在请求来自同一域中时,才会将 Cookie 发送到应用程序。此行为可能会影响 SAML POST 绑定,这些绑定可能无法正常工作。要保留 mod_auth_mellon 模块的完整功能,我们建议将 mod_auth_mellon 创建的 Cookie 的 SameSite 值设置为 None。这样做可能会导致使用 Red Hat Single Sign-On 登录。
要将 SameSite 值设置为 None,请在 mellon.conf 文件中的 < ;Location / > tag 中添加以下配置。
MellonSecureCookie On MellonCookieSameSite none
对此配置的支持包括在 0.16.0 版的 mod_auth_mellon 模块中。
3.2.2.1. 创建服务提供商元数据
在 SAML IdP 和 SP 中可交换 SAML 元数据,它是一个 XML 格式。元数据的 schema 是一种标准,因此,参与 SAML 实体可以相互消耗元数据。您需要:
- SP 使用的 IdP 元数据
- 描述 IdP 提供的 SP 元数据
SAML 元数据的一个组件是 X509 证书。这些证书用于两种目的:
- 为 SAML 消息签名,以便接收最终能够证明来自预期方的消息。
- 在传输期间加密消息(由于 SAML 消息通常发生在 TLS 保护的传输中)
如果您已有证书颁发机构(CA)或生成自签名证书,您可以使用自己的证书。在本例中简单起见,需要使用自签名证书。
因为 Mellon 的 SP 元数据必须反映已安装版本的 mod_auth_mellon 的功能,必须是有效的 SP 元数据 XML,并且必须包含 X509 证书(哪些创建可能是模糊的,除非您熟悉 X509 证书生成)。生成的元数据可以始终编辑,因为它是文本文件。该工具还会创建您的 X509 密钥和证书。
SAML IdP 和 SP 使用唯一名称(称为 EntityID)标识自己。要使用 Mellon 元数据创建工具,您需要:
- EntityID,通常是 SP 的 URL,并且通常检索 SP 元数据的 SP URL
- 将消耗 SP 的 SAML 消息的 URL,Mellon 调用 MellonPointPath。
要创建 SP 元数据,请执行以下步骤:
流程
创建几个 helper shell 变量:
fqdn=`hostname` mellon_endpoint_url="https://${fqdn}/mellon" mellon_entity_id="${mellon_endpoint_url}/metadata" file_prefix="$(echo "$mellon_entity_id" | sed 's/[^A-Za-z.]/_/g' | sed 's/__*/_/g')"运行以下命令调用 Mellon 元数据创建工具:
/usr/libexec/mod_auth_mellon/mellon_create_metadata.sh $mellon_entity_id $mellon_endpoint_url
将生成的文件移动到其目的地(在上面创建的 /etc/httpd/conf.d/mellon.conf 文件中引用):
mv ${file_prefix}.cert /etc/httpd/saml2/mellon.crt mv ${file_prefix}.key /etc/httpd/saml2/mellon.key mv ${file_prefix}.xml /etc/httpd/saml2/mellon_metadata.xml
3.2.2.2. 将 Mellon Service Provider 添加到红帽单点登录身份提供程序
假设:已在 $idp_host 上安装了 Red Hat Single Sign-On IdP。
Red Hat Single Sign-On 支持多个租赁,其中所有用户、客户端等都分组在名为 realm 中的内容。每个域都独立于其他域。您可以在 Red Hat Single Sign-On 中使用现有域,但本例中演示了如何创建一个名为 test_realm 的新域,并使用该域。
所有这些操作都使用 Red Hat Single Sign-On Admin 控制台来执行。您必须具有 $idp_host 的 admin 用户名和密码才能执行以下步骤。
流程
打开 Admin 控制台,再输入 admin 用户名和密码来登录。
登录管理控制台后,将有一个现有的域。当 Red Hat Single Sign-On 首次设置 root 域(master)时,会被默认创建。任何之前创建的域都列在管理控制台的下拉列表中。
- 从 realm 下拉列表中,选择 Add realm。
-
在 Name 字段中,键入
test_realm,再单击 Create。
3.2.2.2.1. 添加 Mellon Service Provider 作为域的客户端
在 Red Hat Single Sign-On SAML SP 中称为客户端。要添加 SP,我们必须位于 realm 的 Clients 部分。
- 单击左侧的 Clients 菜单项,然后单击右上角的 Create 来创建新客户端。
3.2.2.2.2. 添加 Mellon SP 客户端
要添加 Mellon SP 客户端,请执行以下步骤:
流程
- 将客户端协议设置为 SAML。
- 从 Client Protocol 下拉列表中选择 saml。
提供上面创建的 Mellon SP 元数据文件(/etc/httpd/saml2/mellon_metadata.xml)。
根据浏览器运行的位置,您可能必须将 SP 元数据从 $sp_host 复制到运行浏览器的计算机,以便浏览器能够查找该文件。
- 点 Save。
3.2.2.2.3. 编辑 Mellon SP 客户端
使用此流程设置重要的客户端配置参数。
流程
- 确保"Force POST Binding"为 On。
- 将 paosResponse 添加到 Valid Redirect URIs 列表中:
- 将 postResponse URL 复制到 "Valid Redirect URIs" 中,并将它粘贴到"+"下面的空添加文本字段。
- Change "postResponse" to "paosResponse".( SAML ECP 需要 paosResponse URL。)
- 点底部的 Save。
许多 SAML SP 根据组中的用户成员资格来确定授权。Red Hat Single Sign-On IdP 可以管理用户组信息,但它不提供用户的组,除非将 IdP 配置为将其作为 SAML 属性提供。
执行以下步骤将 IdP 配置为将用户组作为 SAML 属性提供。
流程
- 点客户端的 Mappers 选项卡。
- 在 Mappers 页面的右上角,点 Create。
- 从 Mapper Type 下拉列表中选择 Group 列表。
- 将 Name 设置为 "group list"。
- 将 SAML 属性名称设置为 "groups"。
- 点 Save。
剩余的步骤在 $sp_host 上执行。
3.2.2.2.4. 检索身份提供程序元数据
现在,您已在 IdP 上创建域,您需要检索与之关联的 IdP 元数据,以便 Mellon SP 识别它。在之前创建的 /etc/httpd/conf.d/mellon.conf 文件中,MllonIdPMetadataFile 被指定为 /etc/httpd/saml2/idp_metadata.xml,直到现在该文件在 $sp_host 上不存在。
使用这个步骤从 IdP 检索该文件。
流程
使用这个命令,将值替换为 $idp_host 的正确值:
curl -k -o /etc/httpd/saml2/idp_metadata.xml \ https://$idp_host/auth/realms/test_realm/protocol/saml/descriptor
现在,Mellon 被完全配置。
要运行语法检查 Apache 配置文件,请使用以下命令:
apachectl configtest
注意configtest 等同于 apachectl 的 -t 参数。如果配置测试显示任何错误,请在继续之前进行更正。
重启 Apache 服务器:
systemctl restart httpd.service
现在,您已将 Red Hat Single Sign-On 设置为 test_realm 和 mod_auth_mellon 中的 SAML IdP,作为 SAML SP 对 URL $sp_host/ protected (以及它下面的所有内容)通过对 $idp_host IdP 进行身份验证。
第 4 章 配置 Docker 注册表以使用 Red Hat Single Sign-On
Docker 身份验证默认为禁用。要启用查看 配置文件。
本节论述了如何将 Docker 注册表配置为使用 Red Hat Single Sign-On 作为其身份验证服务器。
有关如何设置和配置 Docker 注册表的更多信息,请参阅 Docker 注册表配置指南。
4.1. Docker registry 配置文件安装
对于具有更高级 Docker 注册表配置的用户,通常建议提供自己的注册表配置文件。Red Hat Single Sign-On Docker 供应商通过 Registry Config File Format 选项支持这种机制。选择这个选项将生成类似如下的输出:
auth:
token:
realm: http://localhost:8080/auth/realms/master/protocol/docker-v2/auth
service: docker-test
issuer: http://localhost:8080/auth/realms/master然后可以将此输出复制到任何现有 registry 配置文件。如需有关如何 设置文件或从 基本示例 启动的更多信息,请参阅 registry 配置文件规格。
不要忘记用 Red Hat Single Sign-On 域公共证书的位置配置 rootcertbundle 字段。如果不使用此参数,auth 配置将无法正常工作。
4.2. Docker registry 环境变量覆盖安装
通常,最好使用简单的环境变量覆盖来开发或 POC Docker 注册表。虽然这种方法通常不建议用于生产环境,但当一个需要快速和dirty 的方式来启用 registry 时,通常不建议使用此方法。只需使用客户端安装选项卡中的 Variable Override Format 选项,输出应类似以下示例:
REGISTRY_AUTH_TOKEN_REALM: http://localhost:8080/auth/realms/master/protocol/docker-v2/auth REGISTRY_AUTH_TOKEN_SERVICE: docker-test REGISTRY_AUTH_TOKEN_ISSUER: http://localhost:8080/auth/realms/master
请勿忘记使用 Red Hat Single Sign-On realm 的公共证书的位置配置 REGISTRY_AUTH_TOKEN_ROOTCERTBUNDLE 覆盖。如果不使用此参数,auth 配置将无法正常工作。
4.3. Docker Compose YAML 文件
这个安装方法是对 Red Hat Single Sign-On 服务器进行身份验证的一种简便方法。它仅用于开发目的,不应在生产环境中使用。
zip 文件安装机制为希望了解 Red Hat Single Sign-On 服务器可以与 Docker 注册表交互的开发人员提供了快速入门。要配置:
流程
- 从所需域创建客户端配置。此时,您没有 Docker 注册表 - 快速入门将负责这一部分。
- 从安装选项卡中选择"Docker Compose YAML"选项并下载 .zip 文件
- 将存档解压缩到所需位置,并打开 目录。
-
使用
docker-compose 启动Docker 注册表
建议您在 'master' 以外的域中配置 Docker 注册表客户端,因为 HTTP Basic auth 流不存在。
旦上述配置发生,且 keycloak 服务器和 Docker registry 正在运行,docker 身份验证应成功:
[user ~]# docker login localhost:5000 -u $username Password: ******* Login Succeeded
第 5 章 使用客户端注册服务
为了申请或服务利用 Red Hat Single Sign-On,它必须在红帽单点登录中注册客户端。管理员可以通过管理控制台(或管理员 REST 端点)执行此操作,但客户端也可以通过红帽单点登录客户端注册服务自行注册。
客户端注册服务提供对 Red Hat Single Sign-On Client Representations、OpenID Connect Client Meta Data 和 SAML Entity Descriptors 的内置支持。客户端注册服务端点为 /auth/realms/<realm>/clients-registrations/<provider>。
内置支持的供应商 有 :
- 默认 - Red Hat Single Sign-On Clientpresentation (JSON)
- 安装 - Red Hat Single Sign-On Adapter Configuration (JSON)
- openid-connect - OpenID Connect Client Metadata Description (JSON)
- saml2-entity-descriptor - SAML Entity Descriptor (XML)
以下小节介绍了如何使用不同的供应商。
5.1. 身份验证
要调用客户端注册服务,您通常需要令牌。令牌可以是 bearer 令牌、初始访问令牌或注册访问令牌。另外,您还可以在没有令牌的情况下注册新客户端,但随后您需要配置客户端注册策略(请参阅以下)。
5.1.1. bearer 令牌
bearer 令牌可由用户或服务帐户发布。调用端点需要以下权限(请参阅《 服务器管理指南》 以了解更多详细信息:
- create-client 或 manage-client - 要创建客户端
- 查看客户端或 manage-client - 要查看客户端
- manage-client - 要更新或删除客户端
如果您使用 bearer 令牌来创建客户端,建议您从仅具有 create-client 角色的服务账户中使用令牌(更多详情请参阅 服务器管理指南 )。
5.1.2. 初始访问令牌
注册新客户端的建议方法是使用初始访问令牌。初始访问令牌只能用于创建客户端,并具有可配置的过期时间,以及可以创建客户端数量的可配置限制。
初始访问令牌可以通过管理控制台创建。要创建新初始访问令牌,请先在 admin 控制台中选择域,然后单击左侧菜单中的 Realm Settings,然后在页面中显示的选项卡接 Client Registration。然后,最后单击 Initial Access Tokens 子选项卡。
现在,您可以看到任何现有的初始访问令牌。如果您有访问权限,您可以删除不再需要的令牌。您只能在创建令牌时检索令牌的值。要创建新令牌,请点击 Create。现在,您可以选择性地添加令牌应有效的时长,也可使用令牌创建多少个客户端。在点 Save 后,会显示令牌值。
现在复制/粘贴此令牌非常重要,因为您稍后无法检索该令牌。如果您忘记复制/粘贴,则删除令牌并创建另一个令牌。
令牌值在调用 Client Registration Services 时用作标准 bearer 令牌,方法是将其添加到请求中的 Authorization 标头中。例如:
Authorization: bearer eyJhbGciOiJSUz...
5.1.3. 注册访问令牌
通过客户端注册服务创建客户端时,响应将包括注册访问令牌。注册访问令牌提供检索客户端配置的访问,但也会在以后更新或删除客户端。注册访问令牌与 bearer 令牌或初始访问令牌相同。注册访问令牌仅在使用响应时有效,其响应将包括新的令牌。
如果客户端注册服务是在客户端注册服务之外创建的,则它没有与之关联的注册访问令牌。您可以通过管理控制台创建一个。如果您丢失了特定客户端的令牌,这可能也很有用。要创建新令牌,请在 admin 控制台中找到客户端,然后点击 Credentials。然后点击 Generate registration 访问令牌。
5.2. Red Hat Single Sign-On 代表
默认 客户端注册提供程序可用于创建、检索、更新和删除客户端。它使用 Red Hat Single Sign-On Client Representation 格式,它提供对客户端的支持,因为它可以通过管理控制台配置客户端,包括配置协议映射程序示例。
要创建客户端创建客户端代表(JSON),然后对 /auth/realms/<realm>/clients-registrations/default 执行 HTTP POST 请求。
它将返回一个包含注册访问令牌的客户端代表。如果要检索配置、更新或删除客户端,您应在某个位置保存注册访问令牌。
要检索客户端代表对 /auth/realms/<realm>/clients-registrations/default/<client id > 的 HTTP GET 请求。
它还会返回新的注册访问令牌。
要更新客户端代表,对更新的客户端代表执行 HTTP PUT 请求: /auth/realms/<realm>/clients-registrations/default/<client id>.
它还会返回新的注册访问令牌。
要删除客户端代表,请执行 HTTP DELETE 请求: /auth/realms/<realm>/clients-registrations/default/<client id>
5.3. Red Hat Single Sign-On 适配器配置
安装 客户端注册供应商可以用来检索客户端的适配器配置。除了令牌身份验证外,您还可以使用 HTTP 基本身份验证与客户端凭证进行身份验证。要做到这一点,请在请求中包含以下标头:
Authorization: basic BASE64(client-id + ':' + client-secret)
要检索适配器配置,然后对 /auth/realms/<realm>/clients-registrations/install/<client id > 执行 HTTP GET 请求。
公共客户端不需要身份验证。这意味着,对于 JavaScript 适配器,您可以使用上述 URL 直接从 Red Hat Single Sign-On 加载客户端配置。
5.4. OpenID Connect Dynamic Client Registration
Red Hat Single Sign-On 实施 OpenID Connect Dynamic Client Registration,它扩展了 OAuth 2.0 Dynamic Client Registration Protocol 和 OAuth 2.0 Dynamic Client Registration Management Protocol。
在 Red Hat Single Sign-On 中注册客户端的端点是 /auth/realms/<realm>/clients-registrations/openid-connect[/<client id>]。
此端点也可以在域的 OpenID Connect Discovery 端点中找到,即 /auth/realms/<realm>/.well-known/openid-configuration。
5.5. SAML 实体描述符
SAML 实体描述符端点只支持使用 SAML v2 实体描述符来创建客户端。它不支持检索、更新或删除客户端。对于这些操作,应使用 Red Hat Single Sign-On representation 端点。当创建 Red Hat Single Sign-On Clientpresentation 的客户端时,会返回一个关于创建的客户端的详细信息,包括注册访问令牌。
要创建客户端,请使用 SAML 实体 Descriptor 到 /auth/realms/<realm>/clients-registrations/saml2-entity-descriptor 执行 HTTP POST 请求。
5.6. 使用 CURL 的示例
以下示例是使用 CURL 的 clientId myclient 创建客户端。您需要将 eyJhbGciOiJSUz… 替换为正确的初始访问令牌或 bearer 令牌。
curl -X POST \
-d '{ "clientId": "myclient" }' \
-H "Content-Type:application/json" \
-H "Authorization: bearer eyJhbGciOiJSUz..." \
http://localhost:8080/auth/realms/master/clients-registrations/default5.7. 使用 Java 客户端注册 API 的示例
客户端注册 Java API 使使用 Java 的客户端注册服务变得简单。要使用(包括依赖项 org.keycloak:keycloak-client-registration-api:>VERSION<),请从 Maven 中包含依赖项的 org.keycloak:keycloak-client-registration-api:>VERSION <。
有关使用客户端注册的详情,请参考 JavaDocs。以下是创建客户端的示例。您需要将 eyJhbGciOiJSUz… 替换为正确的初始访问令牌或 bearer 令牌。
String token = "eyJhbGciOiJSUz...";
ClientRepresentation client = new ClientRepresentation();
client.setClientId(CLIENT_ID);
ClientRegistration reg = ClientRegistration.create()
.url("http://localhost:8080/auth", "myrealm")
.build();
reg.auth(Auth.token(token));
client = reg.create(client);
String registrationAccessToken = client.getRegistrationAccessToken();5.8. 客户端注册策略
当前计划适用于需要删除的客户端注册策略,以取代《 服务器管理指南》 中所述的客户端策略。客户端策略更为灵活,支持更多用例。
Red Hat Single Sign-On 目前支持两种方式通过客户端注册服务。
-
已验证的请求 - 注册新客户端的请求必须包含如上所述的
Initial Access Token或Bearer Token。 - 匿名请求 - 注册新客户端的请求不需要包含任何令牌
匿名客户端注册请求非常有趣且强大的功能,但您通常不希望任何人可以在没有任何限制的情况下注册新客户端。因此,我们有 客户端注册策略 SPI,它提供了一种限制谁可以注册新客户端及在哪个条件下注册的方法。
在 Red Hat Single Sign-On 管理控制台中,您可以单击 Client Registration 选项卡,然后选择 Client Registration Policies 子目录。在这里,您将看到默认为匿名请求配置哪些策略,以及针对经过身份验证的请求配置了哪些策略。
仅允许匿名请求(不含任何令牌的请求)只用于创建新客户端创建(注册)。因此,当您通过匿名请求注册新客户端时,响应将包含注册访问令牌,该令牌必须用于读取、更新或删除特定客户端的请求。但是,从匿名注册使用此注册访问令牌时,也会受到匿名注册政策的约束!这意味着,如果您有受信任的主机策略,更新客户端的请求也需要来自 受信任的主机。例如,在更新客户端以及存在 Consent 时,不允许禁用 Consent。
目前,我们有这些策略实现:
-
可信主机策略 - 您可以配置可信主机和可信域的列表。只能从这些主机或域发送给客户端注册服务的请求。从某些不可信 IP 发送的请求将被拒绝。新注册的客户端的 URL 还必须使用那些可信主机或域。例如,不允许将客户端的
Redirect URI设置为指向某些不可信主机的客户端。默认情况下,没有白名单的主机,因此匿名客户端注册会被禁用。 -
定同意策略 - 新注册的客户端将启用
Consent Allowedswitch。因此,在身份验证成功后,用户总是在需要批准权限时看到同意屏幕(客户端范围)。这意味着,除非用户批准,否则客户端无法访问任何个人信息或用户的权限。 - 协议映射策略 - 允许配置白名单协议映射程序实施列表。如果包含一些非whitelisted 协议映射程序,则无法注册或更新新的客户端。请注意,这个策略也用于经过身份验证的请求,因此即使对于经过身份验证的请求,也可以使用协议映射程序的一些限制。
-
客户端范围策略 - 允许将
客户端范围列入白名单,这些范围可用于新注册或更新的客户端。默认情况下,没有白名单范围,只有客户端范围定义为Realm Default Client Scopes会被默认列在白名单中。 -
完整范围策略 - 新注册的客户端将禁用
Full Scope Allowed开关。这意味着它们不会有任何有范围的域角色,或者其他客户端的角色。 - max Clients Policy - 如果 realm 中当前客户端数相同的或大于指定的限制,则拒绝注册。默认情况下,匿名注册需要 200。
- Client Disabled Policy - 新注册的客户端将被禁用。这意味着,管理员需要手动批准并启用所有新注册的客户端。默认情况下,即使匿名注册也不使用此策略。
第 6 章 使用 CLI 自动注册客户端
客户端注册 CLI 是一个命令行界面(CLI)工具,供应用开发人员用于在与红帽单点登录集成时以自助服务的方式配置新的客户端。它经过专门设计,可与 Red Hat Single Sign-On 客户端注册 REST 端点进行交互。
需要为任何应用程序创建或获取客户端配置才能使用 Red Hat Single Sign-On。您通常为托管在一个唯一主机名上的每个新应用配置新客户端。当应用程序与 Red Hat Single Sign-On 交互时,应用通过客户端 ID 标识自身,以便 Red Hat Single Sign-On 可以提供登录页面、单点登录(SSO)会话管理和其他服务。
您可以使用客户端注册 CLI 从命令行配置应用程序客户端,您可以在 shell 脚本中使用它。
要允许特定用户使用 Client Registration CLI,Red Hat Single Sign-On 管理员通常使用 Admin Console 配置具有适当角色的新用户,或者配置新客户端和服务器 secret 来授予客户端注册 REST API 的访问权限。
6.1. 配置用于客户端注册 CLI 的新常规用户
流程
-
以
admin用户身份登录管理控制台(例如 http://localhost:8080/auth/admin)。 - 选择要管理的 realm。
- 如果要使用现有用户,请选择该用户进行编辑;否则,创建一个新用户。
-
选择 Role Mappings > Client Roles > realm-management。如果您在 master 域中,选择 NAME-realm,其中
NAME是目标域的名称。您可以为 master 域中的用户授予对任何其他域的访问权限。 选择 Available Roles > manage-client 来授予一组完整的客户端管理权限。另一个选择是选择只读的 view-clients 或 create-client 以创建新客户端。
注意这些权限授予用户在不使用 Initial Access Token 或 Registration Access Token 的情况下执行操作的能力。
不能向用户分配任何 realm-management 角色。在这种情况下,用户仍然可以使用客户端注册 CLI 登录,但是在没有初始访问令牌的情况下无法使用它。试图执行任何没有令牌的操作会导致 403 Forbidden 错误。
管理员可以通过 Realm Settings > Client Registration > Initial Access Token 菜单从 Admin Console 签发 Initial Access Tokens。
6.2. 配置客户端以用于客户端注册 CLI
默认情况下,服务器将客户端注册 CLI 识别为 admin-cli 客户端,该客户端为每个新域自动配置。在使用用户名登录时,不需要额外的客户端配置。
流程
-
如果您想要为客户端注册 CLI 使用单独的客户端配置,请创建一个客户端(如
reg-cli)。 - 将 Standard Flow Enabled 设置切换到 Off。
通过将客户端
Access Type配置为Confidential并选择 Credentials > ClientId 和 Secret 来增强安全性。注意您可以在 Credentials
选项卡中配置客户端 Id 和 Secret或Signed JWT。如果要使用与客户端关联的服务帐户,请选择
Admin Console的 Clients 部分中要编辑的客户端,以启用服务帐户。- 在 Settings 下,将 Access Type 更改为 Confidential,将 Service Accounts Enabled 设置切换为 On,然后单击 Save。
- 单击 Service Account Roles,再选择所需的角色来配置服务帐户的访问权限。有关要选择的角色的详情,请参考 第 6.1 节 “配置用于客户端注册 CLI 的新常规用户”。
- 如果要使用常规用户帐户而不是服务帐户,将 Direct Access Grants Enabled 设置切换为 On。
-
如果客户端配置为
Confidential,请使用--secret选项在运行kcreg config 凭证时提供配置的 secret。 -
在运行
kcreg config credentials时,指定要使用的clientId(如--client reg-cli)。 -
启用服务帐户后,您可以在运行
kcreg 配置凭证时省略指定用户,仅提供客户端 secret 或密钥存储信息。
6.3. 安装客户端注册 CLI
客户端注册 CLI 打包在 Red Hat Single Sign-On Server 分发中。您可以在 bin 目录中找到执行脚本。Linux 脚本称为 kcreg.sh,Windows 脚本称为 kcreg.bat。
在设置客户端以便在文件系统中的任何位置使用时,将 Red Hat Single Sign-On 服务器目录添加到 PATH 中。
例如,在:
- Linux:
$ export PATH=$PATH:$KEYCLOAK_HOME/bin $ kcreg.sh
- Windows:
c:\> set PATH=%PATH%;%KEYCLOAK_HOME%\bin c:\> kcreg
KEYCLOAK_HOME 是指 Red Hat Single Sign-On Server 发行版被解包的目录。
6.4. 使用客户端注册 CLI
流程
- 使用您的凭证登录,启动一个经过身份验证的会话。
在客户端注册
REST 端点上运行命令。例如,在:
Linux:
$ kcreg.sh config credentials --server http://localhost:8080/auth --realm demo --user user --client reg-cli $ kcreg.sh create -s clientId=my_client -s 'redirectUris=["http://localhost:8980/myapp/*"]' $ kcreg.sh get my_client
Windows:
c:\> kcreg config credentials --server http://localhost:8080/auth --realm demo --user user --client reg-cli c:\> kcreg create -s clientId=my_client -s "redirectUris=[\"http://localhost:8980/myapp/*\"]" c:\> kcreg get my_client
注意在生产环境中,必须使用
https访问 Red Hat Single Sign-On,以避免将令牌公开给网络嗅探器。
如果服务器的证书没有由 Java 默认证书信任存储中包含的可信证书颁发机构(CA)发布,请准备一个
truststore.jks文件并指示客户端注册 CLI 使用它。例如,在:
Linux:
$ kcreg.sh config truststore --trustpass $PASSWORD ~/.keycloak/truststore.jks
Windows:
c:\> kcreg config truststore --trustpass %PASSWORD% %HOMEPATH%\.keycloak\truststore.jks
6.4.1. 登录
流程
- 使用客户端注册 CLI 登录时指定服务器端点 URL 和域。
-
指定用户名或客户端 id,这将导致使用特殊服务帐户。使用用户名时,必须为指定用户使用密码。在使用客户端 ID 时,您可以使用客户端 secret 或
签名 JWT而不是密码。
无论登录方法是什么,登录中的帐户都需要适当的权限才能执行客户端注册操作。请记住,非主域中的任何帐户只能有一个权限来管理同一域中的客户端。如果需要管理不同的域,您可以在不同域中配置多个用户,也可以在 主 域中创建单个用户,并添加用于管理不同域中客户端的角色。
您无法使用客户端注册 CLI 配置用户。使用 Admin Console Web 界面或 Admin Client CLI 配置用户。如需了解更多详细信息,请参阅" 服务器管理指南 "。
当 kcreg 成功登录时,它会接收授权令牌并将其保存在私有配置文件中,以便令牌可用于后续调用。有关配置文件的更多信息,请参阅 第 6.4.2 节 “使用其他配置”。
有关使用客户端注册 CLI 的更多信息,请参阅内置帮助。
例如,在:
- Linux:
$ kcreg.sh help
- Windows:
c:\> kcreg help
有关启动经过身份验证的会话的更多信息,请参阅 kcreg config credentials --help。
6.4.2. 使用其他配置
默认情况下,客户端注册 CLI 会在默认位置 ./.keycloak/kcreg.config 下自动维护配置文件。您可以使用 --config 选项指向另一个文件或位置,以并行维护多个通过身份验证的会话。从单个线程执行与单个配置文件相关联的操作是最安全的方法。
不要使配置文件对系统中的其他用户可见。配置文件包含应保持私有的访问令牌和 secret。
您可能希望通过将 --no-config 选项与所有命令搭配使用,以避免将 secret 存储在配置文件中,即使它比较方便,且需要更多令牌请求。使用每个 kcreg 调用指定所有身份验证信息。
6.4.3. 初始访问和注册访问令牌
那些在 Red Hat Single Sign-On 服务器上没有配置帐户的开发人员可使用客户端注册 CLI。只有当 realm 管理员向开发人员发出 Initial Access Token 时,才能执行此操作。它最多是 realm 管理员,决定如何和何时发布这些令牌。realm 管理员可以限制 Initial Access Token 的最长期限,以及可使用它创建的客户端总数。
当开发人员具有 Initial Access Token 后,开发人员就可以使用它来创建新客户端,而无需通过 kcreg config 凭证 进行身份验证。Initial Access Token 可以存储在配置文件中,也可以指定为 kcreg create 命令的一部分。
例如,在:
- Linux:
$ kcreg.sh config initial-token $TOKEN $ kcreg.sh create -s clientId=myclient
或者
$ kcreg.sh create -s clientId=myclient -t $TOKEN
- Windows:
c:\> kcreg config initial-token %TOKEN% c:\> kcreg create -s clientId=myclient
或者
c:\> kcreg create -s clientId=myclient -t %TOKEN%
在使用 Initial Access Token 时,服务器响应包括新发布的注册访问令牌。该客户端的任何后续操作都需要通过与该令牌进行身份验证,该令牌仅对该客户端有效。
客户端注册 CLI 自动使用其专用配置文件来保存并使用该令牌与其关联的客户端。只要使用相同的配置文件用于所有客户端操作,开发人员就不需要进行身份验证来读取、更新或删除以这种方式创建的客户端。
有关初始访问和 注册 访问令牌的更多信息,请参阅客户端注册。
请运行 kcreg config initial-token --help 和 kcreg config registration-token --help 命令以了解有关如何使用客户端注册 CLI 配置令牌的更多信息。
6.4.4. 创建客户端配置
使用凭证身份验证或配置 Initial Access Token 后面的第一项任务通常是创建新客户端。通常,您可能希望将准备的 JSON 文件用作模板,并设置或覆盖某些属性。
以下示例演示了如何读取 JSON 文件,覆盖它可能包含的任何客户端 ID,设置任何其他属性,并在成功创建后将配置打印到标准输出。
- Linux:
$ kcreg.sh create -f client-template.json -s clientId=myclient -s baseUrl=/myclient -s 'redirectUris=["/myclient/*"]' -o
- Windows:
C:\> kcreg create -f client-template.json -s clientId=myclient -s baseUrl=/myclient -s "redirectUris=[\"/myclient/*\"]" -o
运行 kcreg create --help 来获取有关 kcreg create 命令的更多信息。
您可以使用 kcreg attrs 来列出可用的属性。请记住,许多配置属性没有被检查是否有有效性或一致性。最多为您提供了正确的值。请记住,您的模板中不应该包含任何 id 字段,并且不应将它们指定为 kcreg create 命令的参数。
6.4.5. 检索客户端配置
您可以使用 kcreg get 命令来检索现有客户端。
例如,在:
- Linux:
$ kcreg.sh get myclient
- Windows:
C:\> kcreg get myclient
您还可以将客户端配置检索为适配器配置文件,您可以使用 web 应用程序打包该文件。
例如,在:
- Linux:
$ kcreg.sh get myclient -e install > keycloak.json
- Windows:
C:\> kcreg get myclient -e install > keycloak.json
运行 kcreg get --help 命令来获取有关 kcreg get 命令的更多信息。
6.4.6. 修改客户端配置
可以通过两种方法更新客户端配置。
种方法是,在获取当前配置后,向服务器提交完整的新状态,将其保存到文件中,对其进行编辑,并将其发布回服务器。
例如,在:
- Linux:
$ kcreg.sh get myclient > myclient.json $ vi myclient.json $ kcreg.sh update myclient -f myclient.json
- Windows:
C:\> kcreg get myclient > myclient.json C:\> notepad myclient.json C:\> kcreg update myclient -f myclient.json
第二种方法获取当前客户端,设置或删除它的字段,并在一个步骤中返回它。
例如,在:
- Linux:
$ kcreg.sh update myclient -s enabled=false -d redirectUris
- Windows:
C:\> kcreg update myclient -s enabled=false -d redirectUris
您还可以使用仅包含要应用更改的文件,因此您不必将太多值指定为参数。在这种情况下,指定 --merge 告知客户端注册 CLI,而不将 JSON 文件视为完整的新配置,它应该将其视为要对现有配置应用的一组属性。
例如,在:
- Linux:
$ kcreg.sh update myclient --merge -d redirectUris -f mychanges.json
- Windows:
C:\> kcreg update myclient --merge -d redirectUris -f mychanges.json
运行 kcreg update --help 命令来获取有关 kcreg update 命令的更多信息。
6.4.7. 删除客户端配置
使用以下示例删除客户端。
- Linux:
$ kcreg.sh delete myclient
- Windows:
C:\> kcreg delete myclient
运行 kcreg delete --help 命令来获取有关 kcreg delete 命令的更多信息。
6.4.8. 刷新无效的注册访问令牌
当使用 --no-config 模式执行创建、读取、更新和删除(CRUD)操作时,客户端注册 CLI 无法为您处理注册访问令牌。在这种情况下,可能丢失了客户端最近发布的注册访问令牌的跟踪,从而无法在该客户端上执行任何进一步的 CRUD 操作,而无需使用具有 manage-clients 权限的帐户进行身份验证。
如果您有权限,您可以为客户端发布新的注册访问令牌,并将其打印到标准输出或保存到您选择的配置文件中。否则,您必须要求域管理员为您的客户端发布一个新的注册访问令牌并将其发送给您。然后,您可以通过 --token 选项将其传递给任何 CRUD 命令。您还可以使用 kcreg config registration-token 命令将新令牌保存到配置文件中,并让 Client Registration CLI 从该时间点自动为您处理它。
运行 kcreg update-token --help 命令来获取有关 kcreg update-token 命令的更多信息。
6.5. 故障排除
问:在登录时,我得到一个错误:Parameter client_assertion_type 缺失 [invalid_client]。
答:这个错误表示您的客户端被配置为带有
签名 JWT令牌凭证,这意味着您必须在登录时使用--keystore参数。
第 7 章 使用令牌交换
令牌交换 是技术预览,不被完全支持。此功能默认为禁用。
要使用 -Dkeycloak.profile=preview 或 -Dkeycloak.profile.feature.token_exchange=enabled 来启用服务器。如需了解更多详细信息,请参阅 配置文件。
要使用令牌交换,您还应启用 token_exchange 功能。请查看 配置文件。
7.1. 令牌交换如何工作
在 Red Hat Single Sign-On 中,令牌交换是使用一组凭证或令牌来获取完全不同的令牌的过程。客户端可能想要在较低的可信应用上调用,因此可能希望降低其具有的当前令牌。客户端可能希望为链接的社交供应商帐户存储的令牌交换红帽单点登录令牌。您可能希望信任由其他 Red Hat Single Sign-On 域或外部 IDP 分离的外部令牌。客户端可能需要模拟用户。以下是关于令牌交换的 Red Hat Single Sign-On 当前功能的简要概述。
- 客户端可以交换为针对不同客户端的新令牌创建的现有 Red Hat Single Sign-On 令牌
- 客户端可以为外部令牌交换现有红帽单点登录令牌,即链接的 Facebook 帐户
- 客户端可以为 Red Hat Single Sign-On 令牌交换外部令牌。
- 客户端可以模拟用户
Red Hat Single Sign-On 中的令牌交换是 IETF 中 OAuth Token Exchange 规格的松散实施。我们扩展了它,忽略其中的一些部分,并松散解释规范中的其他部分。它是在域的 OpenID Connect 令牌端点上调用的简单授权类型调用。
/auth/realms/{realm}/protocol/openid-connect/token
它接受表格参数(应用程序/x-www-form-url 编码),输出取决于您请求的交换的令牌类型。令牌交换是客户端端点,因此请求必须为调用客户端提供身份验证信息。公共客户端将客户端标识符指定为表单参数。机密客户端也可以使用表单参数传递其客户端 ID 和机密,即 Basic Auth,或者您的管理员已在域中配置了客户端身份验证流。
7.1.1. 表单参数
- client_id
- 或许还要.客户端使用表单参数进行身份验证时需要此参数。如果您使用 Basic Auth、客户端 JWT 令牌或客户端证书身份验证,则不要指定此参数。
- client_secret
- 必需可能.客户端需要使用表格参数进行身份验证并将客户端 secret 用作凭证,客户端需要这个参数。如果域中的客户端通过不同的方法进行身份验证,则不要指定此参数。
- grant_type
-
必需。参数的值必须是
urn:ietf:params:oauth:grant-type:token-exchange。 - subject_token
- 可选。代表请求所发出的方身份的安全令牌。如果您交换了现有令牌,则需要一个新令牌。
- subject_issuer
-
可选。标识
subject_token的签发者。如果令牌来自当前域,或者能否从subject_token_type确定了签发者,它可以留空。否则,需要指定它。有效值是为您的域配置的身份提供程序的别名。或由特定身份提供程序配置的签发者声明标识符。 - subject_token_type
-
可选。此参数是通过
subject_token参数传递的令牌类型。如果subject_token来自 realm,则默认为urn:ietf:params:oauth:token-type:access_token,则默认为 urn:ietf:params:oauth:token-type:access_token。如果是外部令牌,则可能需要根据subject_issuer的要求指定此参数。 - requested_token_type
-
可选。此参数表示客户端要交换的令牌类型。目前只支持 oauth 和 OpenID Connect 令牌类型。这个值的默认值取决于它是
urn:ietf:params:oauth:token-type:refresh_token,在这种情况下,您要在响应中返回访问令牌和刷新令牌。其他适当的值有urn:ietf:params:oauth:token-type:access_token和urn:ietf:params:oauth:token-type:id_token - 受众
- 可选。此参数指定您希望新令牌为 mint 的目标客户端。
- requested_issuer
-
可选。此参数指定客户端希望由一个外部供应商重新连接令牌。它必须是域中
配置的身份提供程序的别名。 - requested_subject
- 可选。如果客户端想要模拟其他用户,则指定用户名或用户 id。
- scope
- 未实施。这个参数代表客户端请求的目标组 OAuth 和 OpenID Connect 范围。它不在此时间内实施,但一旦红帽单点登录支持一般将支持范围。
我们目前仅支持 OpenID Connect 和 OAuth 交换。根据用户需求,以后可能会添加基于 SAML 的客户端和身份提供程序的支持。
7.1.2. 来自令牌交换请求的响应
调用成功的响应将返回 HTTP 200 响应代码,其包含依赖于 requested-token-type 和 requested_issuer 要求的内容类型。请求的 OAuth 令牌类型将返回 JSON 文档,如 OAuth Token Exchange 规格中所述。
{
"access_token" : ".....",
"refresh_token" : ".....",
"expires_in" : "...."
}
请求刷新令牌的客户端将在响应中返回访问和刷新令牌。仅请求访问令牌类型的客户端只获得响应中的访问令牌。对于通过 request _issuer paramater 请求外部签发者的客户端,则过期信息可能或不包括。
错误响应通常低于 400 HTTP 响应代码类别,但根据错误的严重性,可能会返回其他错误状态代码。错误响应可能包括内容,具体取决于 requested_issuer。基于 OAuth 的交换可能会返回 JSON 文档,如下所示:
{
"error" : "...."
"error_description" : "...."
}
根据交换类型,可能会返回其他错误声明。例如,如果用户没有到身份提供程序的链接,OAuth 身份提供程序可能包含额外的 account-link-url 声明。此链接可用于客户端发起的链接请求。
令牌交换设置需要了解 admin 权限(有关更多信息,请参阅 服务器管理指南 )。您需要授予客户端交换权限。本章后续部分将对此进行更为详细的探讨。
本章的其余部分讨论了设置要求,并提供了有关不同交换场景的示例。为了简单起见,让我们向当前域调用一个令牌,作为 内部 令牌,以及由外部域或身份提供程序作为 外部 令牌的 mint 令牌。
7.2. 内部令牌交换
使用内部令牌来交换您特定客户端的现有令牌,并且您希望为不同的目标客户端使用一个新的令牌交换此令牌。您为何要执行此操作?这通常是,当客户端本身有令牌提示时,需要向需要访问令牌内不同声明和权限的其他应用程序发出额外请求。可能需要此类交换的其它原因是,您需要执行"权限降级",其中您的应用程序需要在较低的可信应用程序上调用,而您不需要传播当前的访问令牌。
7.2.1. 为交换授予权限
希望为不同客户端交换令牌的客户端需要在管理控制台中获得授权。您需要在目标客户端定义 令牌交换 的细致性权限。
目标客户端权限
流程
将 权限启用 切换到 ON。
目标客户端权限
该页面显示 token-exchange 链接。
点击该链接开始定义权限。
此设置页面会显示。
目标客户端交换权限设置
- 点 Authorization 链接为这个权限定义策略
- 点 Policies 标签页。
创建 客户端 策略。
创建客户端策略
- 在请求令牌交换的起始客户端中输入。
创建此策略后,返回到目标客户端的 token-exchange 权限,然后添加您刚才定义的客户端策略。
应用客户端策略
您的客户端现在有调用的权限。如果您没有正确执行此操作,如果您尝试进行交换,则会收到 403 Forbidden 响应。
7.2.2. 发出请求
当客户端交换为另一个客户端令牌的现有令牌时,您可以使用 使用者 参数。此参数必须是您在管理控制台中配置的目标客户端的客户端标识符。
curl -X POST \
-d "client_id=starting-client" \
-d "client_secret=the client secret" \
--data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
-d "subject_token=...." \
--data-urlencode "requested_token_type=urn:ietf:params:oauth:token-type:refresh_token" \
-d "audience=target-client" \
http://localhost:8080/auth/realms/myrealm/protocol/openid-connect/token
subject_token 参数必须是目标域的访问令牌。如果您的 requested_token_type 参数是刷新令牌类型,则响应将包含访问令牌、刷新令牌和过期。以下是您从此调用返回的示例 JSON 响应:
{
"access_token" : "....",
"refresh_token" : "....",
"expires_in" : 3600
}7.3. 外部令牌交换的内部令牌
您可以为外部身份提供程序交互的 externl 令牌交换域令牌。此外部身份提供程序必须在管理控制台的 Identity Provider 部分中配置。目前只支持基于 OAuth/OpenID Connect 的外部身份提供程序,这包括所有社交供应商。Red Hat Single Sign-On 不会向外部供应商执行后端交换。因此,如果帐户未链接,您将无法获取外部令牌。要获得这些条件的一个外部令牌,必须满足:
- 用户必须至少使用外部身份提供程序登录
- 用户必须通过用户帐户服务与外部身份提供程序相关联
- 用户帐户使用 客户端初始帐户链接 API 通过外部身份提供程序链接。
最后,外部身份提供程序必须被配置为存储令牌,或者,上述操作之一必须已使用与您要交换的内部令牌相同的用户会话执行。
如果帐户未链接,交换响应将包含可用于建立它的链接。在进行 Request 部分中, 将对此进行更为详细的探讨。
7.3.1. 为交换授予权限
内部外部令牌交换请求将被拒绝,并带有 403、Forbidden 响应,直到您为调用客户端授予权限,以便与外部身份提供程序交换令牌。要向客户端授予权限,您需要转至身份提供程序的配置页面到 权限选项卡。
身份供应商权限
流程
将 权限启用 切换到 ON。
身份供应商权限
页面中显示 token-exchange 链接。
点击链接以开始定义权限。
此时会出现此设置页面。
身份供应商交换权限设置
点 Authorization 链接,进入 Policies 选项卡以创建客户端策略。
创建客户端策略
- 输入作为请求令牌交换的经过身份验证的客户端的起始客户端。
返回到身份提供程序的 token-exchange 权限,再添加您刚才定义的客户端策略。
应用客户端策略
您的客户端现在有调用的权限。如果您没有正确执行此操作,如果您尝试进行交换,则会收到 403 Forbidden 响应。
7.3.2. 发出请求
当客户端将现有的内部令牌交换到外部令牌时,您可以提供 requested_issuer 参数。参数必须是配置的身份提供程序的别名。
curl -X POST \
-d "client_id=starting-client" \
-d "client_secret=the client secret" \
--data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
-d "subject_token=...." \
--data-urlencode "requested_token_type=urn:ietf:params:oauth:token-type:access_token" \
-d "requested_issuer=google" \
http://localhost:8080/auth/realms/myrealm/protocol/openid-connect/token
subject_token 参数必须是目标域的访问令牌。requested_token_type 参数必须是 urn:ietf:params:oauth:token-type:access_token 或 left blank。目前,不支持其他请求的令牌类型。以下是您从此调用返回成功 JSON 响应的示例:
{
"access_token" : "....",
"expires_in" : 3600
"account-link-url" : "https://...."
}如果外部身份提供程序没有因为任何原因而链接,您将获得带有此 JSON 文档的 HTTP 400 响应代码:
{
"error" : "....",
"error_description" : "..."
"account-link-url" : "https://...."
}
错误 声明将为 token_expired 或 not_linked。提供了 account-link-url 声明,以便客户端可以执行 客户端初始帐户链接。大多数(如果不是全部)供应商需要通过浏览器 OAuth 协议进行链接。使用 account-link-url 仅向它添加 redirect_uri 查询参数,您可以转发浏览器来执行链接。
7.4. 内部令牌交换的外部令牌
您可以针对内部令牌信任并交换外部身份供应商连接外部令牌。这可用于在域间桥接,或者只是从您的社交提供程序信任令牌。它与一个身份提供商浏览器登录类似,如果新用户在您的域中导入您的域中(如果它不存在)。
外部令牌交换的当前限制是,如果外部令牌映射到现有用户,则不会允许交换,除非现有用户已向外部身份提供程序有帐户链接。
当交换完成时,将在 realm 中创建用户会话,并且根据 requested_token_type 参数值,您会收到访问或刷新令牌。您应该注意,这个新用户会话将保持活动状态,直到超时或直到您通过此新访问令牌调用域的注销端点。
这些类型的更改需要在 Admin 控制台中配置的身份提供程序。
目前,不支持 SAML 身份提供程序。Twitter 令牌不能交换。
7.4.1. 为交换授予权限
在完成外部令牌交换之前,授予调用客户端的权限,以便进行交换。此权限以与内部 权限相同的方式授予。
如果您还提供一个 使用者 参数,其值指向调用一个不同的客户端,则必须授予调用客户端的权限,以交换到在 受众 参数中指定的目标客户端。本节稍后将对此进行 探讨。
7.4.2. 发出请求
subject_token_type 必须是 urn:ietf:params:oauth:token-type:access_token 或 urn:ietf:params:oauth:token-type:jwt。如果类型是 urn:ietf:params:oauth:token-type:access_token,您必须指定 subject_issuer 参数,且必须是配置的身份提供程序的别名。如果类型为 urn:ietf:params:oauth:token-type:jwt,该提供程序将通过 JWT 中的 签发者 声明(必须是提供程序的别名)或提供程序配置中的注册签发者进行匹配。
为进行验证,如果令牌是访问令牌,则将调用提供程序的用户 info 服务来验证令牌。成功调用意味着访问令牌有效。如果主题令牌是 JWT,如果提供程序启用了签名验证,则它将默认在用户信息服务上调用来验证令牌。
默认情况下,内部令牌 Minted 将使用调用客户端来确定令牌中的使用为调用客户端定义的协议映射程序。另外,您可以使用 audience 参数指定不同的目标客户端。
curl -X POST \
-d "client_id=starting-client" \
-d "client_secret=the client secret" \
--data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
-d "subject_token=...." \
-d "subject_issuer=myOidcProvider" \
--data-urlencode "subject_token_type=urn:ietf:params:oauth:token-type:access_token" \
-d "audience=target-client" \
http://localhost:8080/auth/realms/myrealm/protocol/openid-connect/token
如果您的 requested_token_type 参数是刷新令牌类型,则响应将包含访问令牌、刷新令牌和过期。以下是您从此调用返回的示例 JSON 响应:
{
"access_token" : "....",
"refresh_token" : "....",
"expires_in" : 3600
}7.5. 模拟(Impersonation)
对于内部和外部令牌交换,客户端可以代表用户模拟不同的用户。例如,您可能有一个需要模拟用户的管理员应用程序,以便支持工程师能够调试问题。
7.5.1. 为交换授予权限
主体令牌代表的用户必须具有模拟其他用户的权限。有关如何启用此权限,请参阅" 服务器管理指南 "。它可以通过角色或通过精细的管理权限完成。
7.5.2. 发出请求
按照其他章节中所述提出请求,除了指定 requested_subject 参数外。此参数的值必须是用户名或用户 id。
curl -X POST \
-d "client_id=starting-client" \
-d "client_secret=the client secret" \
--data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
-d "subject_token=...." \
--data-urlencode "requested_token_type=urn:ietf:params:oauth:token-type:access_token" \
-d "audience=target-client" \
-d "requested_subject=wburke" \
http://localhost:8080/auth/realms/myrealm/protocol/openid-connect/token7.6. 直接 Naked Impersonation
您可以在不提供 subject_token 的情况下进行内部令牌交换请求。这被称为直接模拟器,因为它将许多信任放在客户端,因为客户端可以在 realm 中模拟任何用户。对于无法获取主题令牌来交换的应用程序,您可能需要执行此操作。例如,您可以集成执行直接与 LDAP 登录的传统应用程序。在这种情况下,传统的应用程序能够验证用户本身,但无法获取令牌。
为客户端启用直接 naked impersonation 是非常风险的。如果客户端的凭据被盗,客户端就可以模拟系统中的任何用户。
7.6.1. 为交换授予权限
如果提供了 使用者 参数,则调用客户端必须具有对客户端进行交换的权限。本章前文中介绍了如何设置此设置。
另外,必须授予调用客户端的权限才能模拟用户。(在管理控制台中)。
流程
- 点菜单中的 Users。
单击权限选项卡。
用户权限
将 权限 Enabled 切换到 true。
身份供应商权限
该页面会显示 模拟 链接。
点击该链接开始定义权限。
此设置页面会显示。
用户识别权限设置
- 点击 Authorization 链接
前往 Policies 选项卡,再创建客户端策略。
创建客户端策略
- 输入作为请求令牌交换的经过身份验证的客户端的起始客户端。
返回到用户的 模拟 权限,再添加您刚才定义的客户端策略。
应用客户端策略
您的客户端现在有权模拟用户。如果您没有正确进行这个操作,如果您尝试进行这种交换,则会收到 403 Forbidden 响应。
公共客户端不允许直接模拟。
7.6.2. 发出请求
要发出请求,只需指定 requested_subject 参数。这必须是有效用户的用户名或用户 ID。如果需要,还可以指定 受众 参数。
curl -X POST \
-d "client_id=starting-client" \
-d "client_secret=the client secret" \
--data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
-d "requested_subject=wburke" \
http://localhost:8080/auth/realms/myrealm/protocol/openid-connect/token7.7. 使用服务帐户扩展权限模型
为交换授予客户端权限时,您不一定为每个客户端和每个客户端启用这些权限。如果客户端有与它关联的服务帐户,您可以使用角色将权限分组在一起,并通过为客户端的服务帐户分配角色来分配权限并分配交换权限。例如,您可以定义一个 naked-exchange 角色,并且具有该角色的任何服务帐户都可以进行 naked 交换。
7.8. 交换漏洞
当您开始允许令牌交换时,您必须了解和小心。
第一个是公共客户端。公共客户端不需要客户端凭据才能执行交换。具有有效令牌的任何人都可以 模拟公共客户端 并执行允许公共客户端执行的交换。如果有任何由域管理的不可信客户端,公共客户端可能会在您的权限模型中打开漏洞。这就是为什么直接的交换不允许公共客户端,并在调用客户端是公共客户端时中止并中止。
可以根据 Facebook、Google 等域令牌交换社交令牌。在交换令牌允许时要做的注意和标明,因为它难以在这些社交网站上创建虚设帐户。使用默认角色、组和身份提供程序映射程序来控制将哪些属性和角色分配给外部社交用户。
直接 naked 交换非常危险。您在调用客户端时有很多信任,它将永远不会泄漏其客户端凭证。如果这些凭证被泄漏,则 thief 可以模拟您系统中的任何人。这与具有现有令牌的机密客户端直接进行比较。您有两个身份验证因素:访问令牌和客户端凭证,您只能处理一个用户。因此,使用直接的交换功能。