配置主机名 (v2)

了解如何配置 Keycloak 公开的 前端 和 后端 终结点。

设置主机名选项的重要性

默认情况下,Keycloak 要求配置 hostname 选项,并且不会动态解析 URL。这是一项安全措施。

Keycloak 会公开自己的 URL,例如通过 OIDC 发现终结点,或者作为电子邮件中密码重置链接的一部分。如果主机名是从主机头动态解释的,它可能会为潜在攻击者提供操纵电子邮件中 URL 的机会,将用户重定向到攻击者的虚假域,并窃取敏感数据,例如操作令牌、密码等。

通过显式设置 hostname 选项,我们可以避免令牌可能由欺诈性颁发者颁发的这种情况。可以使用以下命令启动具有显式主机名的服务器。

bin/kc.[sh|bat] start --hostname my.keycloak.org
这些示例以生产模式启动 Keycloak 实例,这需要公钥证书和私钥才能确保通信安全。有关更多信息,请参阅配置 Keycloak 以进行生产

定义主机名选项的特定部分

如前例所示,方案和端口不需要显式指定。在这种情况下,Keycloak 会自动处理这些方面。例如,在给定的示例中,服务器将可以通过 https://my.keycloak.org:8443 访问。但是,反向代理通常会在默认端口(例如 443)上公开 Keycloak。在这种情况下,最好在 hostname 选项中指定完整 URL,而不是使 URL 的部分保持动态。然后,可以使用以下命令启动服务器。

bin/kc.[sh|bat] start --hostname https://my.keycloak.org

类似地,您的反向代理可能会在不同的上下文路径中公开 Keycloak。可以通过 hostnamehostname-admin 选项配置 Keycloak 以反映这一点。请参见以下示例

bin/kc.[sh|bat] start --hostname https://my.keycloak.org:123/auth

使用内部 URL 进行客户端之间的通信

Keycloak 能够为后端请求提供单独的 URL,从而实现内部通信,同时仍然使用公共 URL 进行前端请求。此外,后端是根据传入的标头动态解析的。请考虑以下示例

bin/kc.[sh|bat] start --hostname https://my.keycloak.org --hostname-backchannel-dynamic true

通过这种方式,您的应用程序(称为客户端)可以通过本地网络连接 Keycloak,而服务器仍然可以在 https://my.keycloak.org 上公开访问。

使用边缘 TLS 终止

正如您所看到的,HTTPS 协议是默认选择,符合 Keycloak 对安全最佳实践的承诺。但是,Keycloak 还为用户提供了在必要时选择 HTTP 的灵活性。这可以通过简单地指定 HTTP 侦听器来实现,请参阅配置 TLS以了解详细信息。使用边缘 TLS 终止代理,您可以按如下方式启动服务器。

bin/kc.[sh|bat] start --hostname https://my.keycloak.org --http-enabled true

此配置的结果是,您可以继续通过 HTTPS 在 https://my.keycloak.org 上访问 Keycloak,而代理使用 HTTP 和端口 8080 与实例进行交互。

使用反向代理

当代理转发 http 或重新加密 TLS 请求时,应设置 proxy-headers 选项。根据主机名设置,URL 的部分或全部可能被动态确定。

如果选择了 forwardedxforwarded,请确保您的反向代理分别正确设置并覆盖 ForwardedX-Forwarded-* 标头。要设置这些标头,请参阅反向代理的文档。错误配置会导致 Keycloak 暴露于安全漏洞。

完全动态 URL。

例如,如果您的反向代理正确设置了 Forwarded 标头,并且您不想硬编码主机名,Keycloak 可以适应这一点。您只需按如下方式启动服务器即可

bin/kc.[sh|bat] start --hostname-strict false --proxy-headers forwarded

通过这种配置,服务器尊重 Forwarded 标头设置的值。这也意味着所有端点都将被动态解析。

部分动态 URL

hostname 选项未指定为完整 URL 时,proxy-headers 选项也可以用来部分动态解析 URL。例如

bin/kc.[sh|bat] start --hostname my.keycloak.org --proxy-headers xforwarded

在这种情况下,方案、端口和上下文路径将从 X-Forwarded-* 标头动态解析,而主机名将静态定义为 my.keycloak.org

固定 URL

即使 hostname 设置为完整 URL,proxy-headers 仍然相关,因为标头用于确定请求的来源。例如

bin/kc.[sh|bat] start --hostname https://my.keycloak.org --proxy-headers xforwarded

在这种情况下,虽然没有从 X-Forwarded-* 标头动态解析任何内容,但 X-Forwarded-* 标头用于确定请求的正确来源。

在单独的主机名上公开管理控制台

如果您想在不同的主机上公开管理控制台,可以使用以下命令执行此操作

bin/kc.[sh|bat] start --hostname https://my.keycloak.org --hostname-admin https://admin.my.keycloak.org:8443

这允许您在 https://my.keycloak.org 上访问 Keycloak,并在 https://admin.my.keycloak.org:8443 上访问管理控制台,而后端将继续使用 https://my.keycloak.org

请记住,主机名和代理选项不会更改服务器侦听的端口。相反,它只会更改代理前面使用的静态资源(如 JavaScript 和 CSS 链接、OIDC 已知端点、重定向 URI 等)的端口。您需要使用 HTTP 配置选项更改服务器侦听的实际端口。有关详细信息,请参阅所有配置
使用 hostname-admin 选项不会阻止通过 hostname 选项指定的 frontend URL 访问管理 REST API 端点。如果您想限制对管理 REST API 的访问,则需要在反向代理级别执行此操作。管理控制台隐式使用 hostname-admin 选项指定的 URL 访问 API。

背景 - 服务器端点

Keycloak 公开了多个端点,每个端点都有不同的用途。它们通常用于应用程序之间的通信或管理服务器。我们认识到 3 个主要端点组

  • 前端

  • 后端

  • 管理

如果您想使用这些端点中的任何一个,则需要设置基本 URL。基本 URL 由几个部分组成

  • 一个方案(例如 https 协议)

  • 一个主机名(例如 example.keycloak.org)

  • 一个端口(例如 8443)

  • 一个路径(例如 /auth)

每个组的基本 URL 对令牌的颁发和验证方式、为需要用户重定向到 Keycloak 的操作创建链接的方式(例如,通过电子邮件链接重置密码时)以及最重要的,应用程序在从 realms/{realm-name}/.well-known/openid-configuration 获取 OpenID Connect 发现文档时如何发现这些端点具有重要影响。

前端

用户和应用程序使用前端 URL 通过前端通道访问 Keycloak。前端通道是可公开访问的通信通道。例如,基于浏览器的流程(访问登录页面、单击链接以重置密码或绑定令牌)可以被视为前端请求。

为了使 Keycloak 可通过前端 URL 访问,您需要设置 hostname 选项

bin/kc.[sh|bat] start --hostname my.keycloak.org

后端

后端端点是那些可以通过公共域或专用网络访问的端点。它们与 Keycloak 和客户端(由 Keycloak 保护的应用程序)之间的直接后端通信有关。这种通信可能通过本地网络进行,避免了反向代理。属于此组的端点的示例包括授权端点、令牌和令牌自省端点、用户信息端点、JWKS URI 端点等。

hostname-backchannel-dynamic 选项的默认值为 false,这意味着后端 URL 与前端 URL 相同。可以通过设置以下选项来启用从传入请求标头动态解析后端 URL。

bin/kc.[sh|bat] start --hostname https://my.keycloak.org --hostname-backchannel-dynamic true

请注意,hostname 选项必须设置为 URL。有关更多信息,请参阅下面的验证部分。

管理

类似于基本前端 URL,您还可以设置管理控制台的资源和端点的基本 URL。服务器使用特定 URL 公开管理控制台和静态资源。此 URL 用于重定向 URL、加载资源(CSS、JS)、管理 REST API 等。可以通过设置 hostname-admin 选项来实现此操作

bin/kc.[sh|bat] start --hostname https://my.keycloak.org --hostname-admin https://admin.my.keycloak.org:8443

同样,hostname 选项必须设置为 URL。有关更多信息,请参阅下面的验证部分。

解析 URL 的来源

如前几节所示,URL 可以通过多种方式解析:可以动态生成、硬编码,或者两者兼而有之。

  • 来自传入请求的动态

    • 主机头、方案、服务器端口、上下文路径

    • 代理设置的标头:ForwardedX-Forwarded-*

  • 硬编码

    • 服务器范围的配置(例如 hostnamehostname-admin 等)

    • 前端 URL 的 Realm 配置

验证

  • hostname URL 和 hostname-admin URL 将被验证为使用了完整 URL,包括方案和主机名。仅在存在的情况下才验证端口,否则将假设给定协议的默认端口(80 或 443)。

  • 在生产配置文件中(kc.sh|bat start),必须显式配置 --hostname--hostname-strict false

    • 这并不适用于开发配置文件(kc.sh|bat start-dev),其中 --hostname-strict false 是默认值。

  • 如果未配置 --hostname

    • hostname-backchannel-dynamic 必须设置为 false。

    • hostname-strict 必须设置为 false。

  • 如果配置了 hostname-admin,则 hostname 必须设置为 URL(而不仅仅是主机名)。否则,Keycloak 无法知道在访问管理控制台时什么是正确的前端 URL(包括端口等)。

  • 如果 hostname-backchannel-dynamic 设置为 true,则 hostname 必须设置为 URL(而不仅仅是主机名)。否则,Keycloak 在通过动态解析的后端访问时无法知道什么是正确的前端 URL(包括端口等)。

此外,如果配置了主机名,则 hostname-strict 将被忽略。

故障排除

要排除主机名配置故障,可以使用专用的调试工具,该工具可以按如下方式启用。

Keycloak 配置
bin/kc.[sh|bat] start --hostname=mykeycloak --hostname-debug=true

Keycloak 正确启动后,打开浏览器并访问:http://mykeycloak:8080/realms/<your-realm>/hostname-debug

相关选项

表 1. 默认情况下,此端点被禁用 (--hostname-debug=false)

hostname

服务器公开的地址。

可以是完整的 URL,也可以是主机名。仅当提供主机名时,方案、端口和上下文路径将从请求中解析。

CLI:--hostname
环境:KC_HOSTNAME

仅在启用 hostname:v2 功能时可用

hostname-admin

访问管理控制台的地址。

如果您使用反向代理在与 hostname 选项中指定的地址不同的地址上公开管理控制台,请使用此选项。

CLI:--hostname-admin
环境:KC_HOSTNAME_ADMIN

仅在启用 hostname:v2 功能时可用

hostname-backchannel-dynamic

启用对后端 URL 的动态解析,包括主机名、方案、端口和上下文路径。

如果您的应用程序通过私有网络访问 Keycloak,请将其设置为 true。如果设置为 true,则需要将hostname选项指定为完整 URL。

CLI: --hostname-backchannel-dynamic
环境变量: KC_HOSTNAME_BACKCHANNEL_DYNAMIC

仅在启用 hostname:v2 功能时可用

true, false (默认)

hostname-debug

切换主机名调试页面,该页面可在 /realms/master/hostname-debug 访问。

CLI: --hostname-debug
环境变量: KC_HOSTNAME_DEBUG

仅在启用 hostname:v2 功能时可用

true, false (默认)

hostname-strict

禁用从请求头动态解析主机名。

在生产环境中,应始终将其设置为 true,除非您的反向代理覆盖了 Host 头。如果启用,则需要指定hostname选项。

CLI: --hostname-strict
环境变量: KC_HOSTNAME_STRICT

仅在启用 hostname:v2 功能时可用

true (默认), false

在本页