升级 Keycloak

本指南介绍如何升级 Keycloak。请按以下顺序使用以下步骤

  1. 查看先前 Keycloak 版本的迁移变更。

  2. 升级 Keycloak 服务器。

  3. 升级 Keycloak adapters。

  4. 升级 Keycloak 客户端库(Admin client、Authorization client、Policy enforcer)。这些库独立于 Keycloak 服务器发布,并且通常可以独立于 Keycloak 服务器进行更新,因为最新发布的客户端库版本应与最新发布的 Keycloak 服务器版本兼容。有关更多信息,请参阅 升级 Keycloak 客户端库

迁移变更

迁移到 26.2.0

重大变更

重大变更被定义为需要现有用户对其配置进行更改。

X-Forwarded-Host 标头端口行为的更改

X-Forwarded-Host 标头可以选择也包含端口。在以前的版本中,当标头中省略端口时,Keycloak 会回退到实际的请求端口。例如,如果 Keycloak 监听端口 8080,并且请求包含 X-Forwarded-Host: example.com 标头,则解析的 URL 为 http://example.com:8080

现在已更改,省略端口会导致从解析的 URL 中删除端口。先前示例中解析的 URL 现在将为 http://example.com

为了缓解这种情况,请让您的反向代理在 X-Forwarded-Host 标头中包含端口,或者将其配置为设置包含所需端口的 X-Forwarded-Port 标头。

安装 Oracle JDBC 驱动程序的更改

需要显式添加到发行版的 Oracle JDBC 驱动程序所需的 JAR 已更改。请使用 ojdbc17 JAR 而不是提供 ojdbc11 JAR,如安装 Oracle 数据库驱动程序指南中所述。

JWT 客户端身份验证与最新的 OIDC 规范对齐

OpenID Connect 核心规范的最新草案版本更改了客户端身份验证方法 private_key_jwtclient_secret_jwt 的 JWT 客户端断言中受众验证的规则。

以前,JWT 客户端断言的 aud claim 被松散地定义为“受众应该是授权服务器令牌端点的 URL”,这并不排除使用其他 URL。

修订后的 OIDC Core 规范使用了更严格的受众检查:“受众值必须是以字符串形式传递的 OP 的 Issuer Identifier,而不是单元素数组。”。

我们调整了 private_key_jwtclient_secret_jwt 的 JWT 客户端身份验证器,默认情况下仅允许令牌中包含单个受众。目前,受众可以是 issuer、令牌端点、自省端点或客户端 JWT 身份验证使用的其他 OAuth/OIDC 端点。但是,由于现在仅允许单个受众,这意味着不可能使用其他不相关的受众值,这是为了确保 JWT 令牌确实仅对 Keycloak 的客户端身份验证有用。

通过 OIDC 登录协议 SPI 的新选项,可以将此严格的受众检查恢复为以前更宽松的检查。如果服务器使用以下选项启动,则仍然允许在 JWT 中使用多个受众

--spi-login-protocol-openid-connect-allow-multiple-audiences-for-jwt-client-authentication=true

请注意,此选项将来可能会被删除。可能在 Keycloak 27 中。因此,强烈建议您更新客户端以使用单个受众,而不是使用此选项。还建议您的客户端在发送 JWT 进行客户端身份验证时使用 issuer URL 作为受众,因为这将与未来版本的 OIDC 规范兼容。

值得注意的变更

值得注意的变更是指内部行为的更改,旨在防止常见的错误配置、修复错误或简化 Keycloak 的运行。

内置 X509 客户端证书查找提供程序强制执行 proxy-trusted-addresses

内置 X.509 客户端证书查找提供程序现在反映了 proxy-trusted-addresses 配置选项。只有在代理受信任或 proxy-trusted-addresses 未设置的情况下,才会处理通过 HTTP 标头提供的证书。

零配置安全集群通信

对于集群多个节点,Keycloak 使用分布式缓存。从此版本开始,对于所有基于 TCP 的传输堆栈,节点之间的通信都使用 TLS 加密,并使用自动生成的临时密钥和证书进行保护。

如果您未使用基于 TCP 的传输堆栈,建议迁移到 jdbc-ping 传输堆栈,以从简化的配置和增强的安全性中受益。

如果您在以前的版本中提供了自己的密钥库和信任存储来保护 TCP 传输堆栈通信,那么现在建议迁移到自动生成的临时密钥和证书,以从简化的设置中受益。

如果您正在使用自定义传输堆栈,则可以通过将选项 cache-embedded-mtls-enabled 设置为 false 来禁用此默认行为。

有关更多信息,请查看分布式缓存指南中的保护传输堆栈

Operator 创建 NetworkPolicy 以限制流量

Keycloak Operator 现在默认创建 NetworkPolicy,以限制流向 Keycloak 分布式缓存使用的内部端口的流量。

这加强了默认安全设置,并最大程度地减少了新设置的配置步骤。我们希望这向后兼容现有部署,因此在升级时无需执行其他步骤。您可以通过在 Keycloak CR 中禁用 NetworkPolicy 的创建来返回到先前的行为。

如果您的部署脚本为 Keycloak 添加了显式的 NetworkPolicy,您应该考虑删除这些策略,并在升级后迁移到 Keycloak CR 中提供的新功能。

Operator 高级配置中阅读有关此内容的更多信息。

支持的标准令牌交换

在此版本中,Keycloak 添加了对标准令牌交换(功能 token-exchange-standard:v2)的支持。在过去的 Keycloak 版本中,Keycloak 仅具有预览令牌交换功能,该功能现在称为旧版令牌交换(功能 token-exchange:v1)。旧版令牌交换仍处于预览状态,其工作方式与以前的版本相同。如果您使用了内部到内部令牌交换,请考虑迁移到新的标准令牌交换。

如果您希望继续使用旧版令牌交换,您会发现它的操作与以前的版本相同。无需禁用标准令牌交换功能。您的客户端仅在 Keycloak 客户端上启用标准令牌交换时才会使用它。但是,建议迁移到标准令牌交换。它是官方支持的方法,也是增强功能的优先事项。

在计划迁移到新的标准令牌交换时,请考虑以下注意事项

  • 功能 token-exchange-standard(表示新的标准令牌交换)默认启用。建议禁用 token-exchange 功能(表示旧版令牌交换),以确保请求将由新的标准令牌交换提供服务。

  • 您可以同时启用标准和旧版令牌交换功能,如果您需要涵盖标准用例(内部到内部)以及仅由旧版令牌交换实现的其他令牌交换用例,这将非常有用。例如,外部到内部令牌交换仅由旧版令牌交换实现。在这种情况下,Keycloak 最好通过标准令牌交换来服务标准的内部到内部请求,而其他请求由旧版令牌交换提供服务。标准或旧版令牌交换的选择取决于特定请求的参数。例如,包含非标准参数(如 requested_issuerrequested_subject)的请求被视为旧版。

    如果您仍然需要旧版令牌交换,则还需要启用细粒度管理权限版本 1 (FGAP:v1),因为版本 2 (FGAP:v2) 不支持令牌交换权限。这是有意的,因为令牌交换在概念上并不是真正的“管理”权限,因此令牌交换权限未添加到 FGAP:v2。

  • 标准令牌交换需要在客户端上启用开关,如令牌交换文档中所述。

请考虑以下两种类型的令牌交换行为的其他更改

  • 标准令牌交换不再需要或支持细粒度管理权限。

  • 关于 scope 和受众行为的最值得注意的更改是,应用的客户端 scope 基于触发令牌交换请求的客户端,而不是由 audience 参数指定的“目标”客户端。支持 audience 参数的多个值,如规范中所述。令牌交换文档中描述了详细信息。

  • 不再允许公共客户端发送令牌交换请求。旧版令牌交换允许公共客户端与自身交换令牌以缩小原始令牌的 scope。相反,此用例可以通过使用刷新令牌授权来覆盖,其中可以使用 scope 参数来缩小刷新的访问令牌的 scope,如OAuth2 规范中所述。

  • 此版本不支持将访问令牌交换为 SAML 断言。换句话说,不支持使用 requested_token_type=urn:ietf:params:oauth:token-type:saml2

  • 只有当客户端显式启用令牌交换功能时,才允许交换访问令牌以获取刷新令牌,如令牌交换文档中所述。目前,不支持请求离线令牌或在主题令牌从离线会话颁发时交换刷新令牌。建议尽可能交换访问令牌而不是刷新令牌。

支持细粒度管理员权限

从本版本开始,Keycloak 引入了 细粒度管理员权限 V2 ,为管理权限提供了改进且更灵活的授权模型。

  • FGAP:V2 功能默认启用。

  • FGAP:V1 功能仍处于预览状态,可以使用 --features=admin-fine-grained-authz:v1 启用。但是,V1 可能会在未来的版本中被弃用和移除。

从 V1 迁移到 V2

由于权限模型的根本性变化, 无法进行从 V1 到 V2 的自动迁移 。为了简化过渡

  • 引入了一个新的 admin-permissions 客户端。当您为 realm 启用此功能时,将创建此客户端。该客户端持有 FGAP:V2 的授权模型。

  • 现有的 FGAP:V1 授权模型在 realm-management 客户端中保持不变。

  • 管理员必须使用新模型 重新创建权限和策略 ,这可以在更新后的管理控制台的 权限 部分中配置。

FGAP:V1 和 FGAP:V2 之间的主要区别
  • Realm 级别启用

    • 可以使用 Realm 设置 中的新 管理员权限 开关为 realm 启用 FGAP:V2。

  • 集中式管理

    • 资源特定的 权限 选项卡(用于用户、组、客户端和角色)已被移除。

    • 新的 权限 部分为管理控制台中所有管理权限提供集中式管理。

  • 显式操作范围界定

    • 权限之间的传递依赖关系已被移除。

    • 管理员现在必须显式分配每个所需的权限。

    • 示例:要查看和管理资源,必须分别分配权限的 view manage 范围。

  • 权限模型更改

    • user-impersonated 用户权限已被 移除

    • configure 客户端权限已被 移除 。随着 V2 中显式操作范围界定的引入,manage 和 configure 之间的区别变得模糊不清。

    • user-impersonated 用户权限已被 移除 。相反,您可以使用 Groups 资源类型的 impersonate-members 范围来允许或拒绝模拟组成员。

    • manage-members 组权限不允许 realm 管理员从组中取消分配成员。原因是,在 V1 中,这允许组成员成为常规 realm 用户,以及创建 realm 中用户的变通权限。未来,我们将努力提供额外的范围来允许从组中删除成员。

  • 灵活的资源范围界定

    • 与 V1 不同,V1 中的权限要么授予 单个资源 (对于客户端、组和角色),要么授予 所有资源 (对于用户),V2 引入了更大的灵活性。

    • 管理员现在可以为以下对象定义权限

      • 特定资源

      • 一组选定的资源

      • 给定类型的所有 所有资源

      • 这适用于 所有资源类型 :客户端、用户、组和角色。

LDAP 提供程序现在可以将新用户、组和角色存储在基本 DN 的子 DN 中

添加新用户、组或角色时,LDAP 提供程序始终将它们存储在为搜索配置的同一基本 DN 中。但是,在某些部署中,管理员可能希望配置具有 subtree 范围的更广泛的 DN,以从多个子 DN 获取用户(或组/角色),但他们不希望新用户(或组/角色)存储在 LDAP 中的此基本 DN 中。相反,他们希望选择其中一个子 DN 来执行此操作。

现在可以使用 LDAP 提供程序以及 LDAP 组和角色映射器中的新 Relative User Creation DN 配置选项来控制将在何处创建新用户、组或角色。有关更多详细信息,请查看 LDAP 管理指南

移除 X-XSS-Protection 标头

由于 X-XSS-Protection 标头 不再受 Keycloak 支持的任何用户代理支持,因此已将其移除。此标头是 Internet Explorer、Chrome 和 Safari 的一项功能,当它们检测到反射型跨站脚本 (XSS) 攻击时,会阻止页面加载。

我们预计这不会影响任何部署,因为用户代理缺乏支持,并且此功能已被 内容安全策略 (CSP) 取代。

JWT 客户端身份验证为令牌定义了新的最大过期时间选项

当客户端配置为使用 Signed JWT Signed JWT with Client Secret 类型进行身份验证时,Keycloak 现在强制执行令牌的最大过期时间。这意味着,尽管令牌中的 exp (过期)声明可能晚得多,但 Keycloak 将不接受在此最大过期时间之前颁发的令牌。默认值为 60 秒。请注意,JWT 令牌应在发送以进行身份验证之前立即颁发。这样,客户端就有一分钟的窗口时间来发送令牌以进行登录。尽管如此,可以使用客户端 凭据 选项卡中的 最大过期时间 配置选项来调整此过期时间(有关更多信息,请参阅 服务器管理指南中的机密客户端凭据)。

迁移到 26.1.3

值得注意的更改

值得注意的变更是指内部行为的更改,旨在防止常见的错误配置、修复错误或简化 Keycloak 的运行。

发送重置电子邮件,强制联合用户在重置凭据后再次登录

以前,如果使用相同的身份验证会话(相同的浏览器),则重置凭据流程( 忘记密码 功能)会在重置凭据后保持用户登录状态。对于联合用户提供程序,此行为可能存在安全问题。想象一下,一个提供程序实现检测到用户为 已启用 ,成功执行了密码更改,但由于某种原因,用户密码的验证失败。在这种情况下,重置凭据流程允许用户在成功的密码更改后登录,而使用正常的浏览器流程本应不允许登录。这种情况并不常见,但默认情况下应避免。

因此,现在身份验证器 reset-credential-email 发送重置电子邮件 )有一个名为 force-login 重置后强制登录 )的新配置选项,其值为 true (始终强制登录)、 false (之前的行为,如果使用相同的身份验证会话,则保持用户登录状态)和 only-federated (默认值,强制联合用户再次进行身份验证,并保持存储在 Keycloak 内部数据库中的用户的先前行为)。

有关更改此选项的更多信息,请参阅 启用忘记密码

迁移到 26.1.0

重大更改

重大变更被定义为需要现有用户对其配置进行更改。

此版本中,公共 API 或已记录的行为没有重大更改。

值得注意的更改

值得注意的变更是指内部行为的更改,旨在防止常见的错误配置、修复错误或简化 Keycloak 的运行。

如果在初始交换中请求 offline_scope ,则离线访问会移除关联的在线会话

Keycloak 中的任何离线会话都是从在线会话创建的。当请求 offline_access 范围时,当前在线会话用于为客户端创建关联的离线会话。因此,到目前为止,任何 offline_access 请求完成都会创建两个会话:一个在线会话和一个离线会话。这种情况导致了不可靠的行为。例如,当仅请求使用 scope=offline_access 登录时,可能会创建一个未使用的在线会话,这在大多数情况下是无用的。这种情况导致了服务器资源的非必要消耗。

从本版本开始,如果 offline_scope 直接作为会话的首次交互请求,Keycloak 将移除初始在线会话。客户端在与离线会话关联的代码到令牌交换后检索离线令牌,但之前的在线会话将被移除。如果在线会话在 offline_scope 请求之前已被同一客户端或另一个客户端使用,则在线会话将像今天一样保持活动状态。这种情况也意味着,如果使用 scope=offline_access 的登录请求,并且用户之前尚未在 SSO 中进行身份验证,则不会在浏览器中创建 SSO 会话。尽管新行为是有道理的,因为客户端应用程序只是请求离线令牌,但这可能会影响某些依赖于在初始 offline_scope 令牌请求后在线会话仍然处于活动状态的场景。

新的客户端范围 service_account 用于 client_credentials 授权映射器

Keycloak 在 realm 级别引入了一个新的客户端范围,称为 service_account ,它负责通过协议映射器为 client_credentials 授权( client_idclientHostclientAddress )添加特定声明。当客户端配置中设置或取消设置 serviceAccountsEnabled 选项时,此范围将自动分配给客户端并从客户端取消分配。

以前,当客户端配置为启用服务帐户时,这三个映射器( Client IdClient HostClient IP Address )直接添加到专用范围,并且永远不会被移除。

对于大多数 Keycloak 部署来说,行为应该基本相同,因为令牌中的声明与以前基本相同。在您使用客户端凭据授权并且您正在通过一些手动移除或更新上述三个协议映射器的工具来准备 Keycloak 环境的情况下,您可能会受到影响。例如,如果您使用管理员 CLI 脚本为客户端启用服务帐户,然后移除内置的服务帐户协议映射器,您可以调整您的 CLI 以改为移除客户端的 service_account 客户端范围的分配,而不是移除协议映射器。

弃用通知

此处列出了在本版本中继续像以前一样工作的功能,但在未来的主要版本中将被移除。

生产环境的默认 db 选项已弃用。

在以前的版本中, db 选项在生产 ( start ) 模式和开发 ( start-dev ) 模式下都默认为 dev-file ,而 dev-file 从未在生产模式下受支持。在本版本中,我们已弃用此行为,在未来的某个版本中, db 选项在生产模式下将不再默认为 dev-file 。对于生产配置文件中的 build 或非优化 start 和非服务器命令 importexportbootstrap-admin ,应显式提供值。这是为了防止在生产环境中意外使用 dev-file (H2) 数据库,这通常表明配置错误。

JavaScript Authorization 客户端的已弃用 API

JavaScript Authorization 客户端的以下 API 已弃用,将在下一个主要版本中移除

  • KeycloakAuthorization 实例上的 ready 属性。

  • KeycloakAuthorization 实例上的 init() 方法。

这些 API 不再需要,因为初始化在调用 KeycloakAuthorization 实例上的方法时按需自动完成。您可以安全地移除任何依赖于这些 API 的代码。

用于从 OIDC 客户端启动注册的已弃用端点

用于通过 OIDC 客户端启动注册的 /realms/<realm>/protocol/openid-connect/registrations 端点现已弃用,因为存在从 OIDC 客户端启动注册的标准方法。Keycloak 现在支持这种方法。它使用参数 prompt=create

弃用 OrganizationsOrganizationMembers API 中的 getAll() 方法

OrganizationsOrganizationMembers API 中的 getAll() 方法现已弃用,将在下一个主要版本中移除。请改为使用 OrganizationsOrganizationMembers API 中对应的 list(first, max) 方法。

分布式缓存的已弃用传输堆栈

udpjdbc-ping-udptcpazureec2google 传输堆栈已弃用。用户应使用基于 TCP 的 jdbc-ping 堆栈作为直接替代品。

迁移到 26.0.6

密钥解析器的安全改进

使用 REALM_FILESEPARATOR_KEY 密钥解析器时,Keycloak 现在限制对 realm 之外的 FileVault 密钥的访问。在管理控制台中指定表达式占位符时,现在禁止使用可能导致路径遍历的字符。

此外, KEY_ONLY 密钥解析器现在转义 _ 字符,以防止在使用 REALM_UNDERSCORE_KEY 解析器时读取链接到另一个 realm 的密钥。转义只是将 _ 替换为 __ ,因此,例如, ${vault.my_secret} 现在查找名为 my__secret 的文件。我们认识到这是一个重大更改;因此,会记录警告以简化过渡。

迁移到 26.0.0

Infinispan 编组更改

编组是将 Java 对象转换为字节的过程,以便在 Keycloak 服务器之间通过网络发送它们。在 Keycloak 26 中,编组库已从 JBoss Marshalling 更改为 Infinispan Protostream。这些库彼此不兼容,并且需要一些步骤来确保会话数据不会丢失。

JBoss Marshalling 和 Infinispan Protostream 彼此不兼容,不正确的使用可能会导致数据丢失。因此,升级到此版本时,所有缓存都会被清除。

为了防止丢失用户会话,请先升级到 Keycloak 25,并按照 Keycloak 25 的迁移指南中概述的方式启用持久会话功能。

Operator 不再默认为 proxy=passthrough

Operator 将不再默认为 hostname v1 设置 proxy=passthrough。这允许使用 hostname v2 进行固定边缘主机名的部署按预期工作,而无需其他选项。

ClusterProvider API 中的新方法

以下方法已添加到 org.keycloak.cluster.ClusterProvider

  • void notify(String taskKey, Collection<? extends ClusterEvent> events, boolean ignoreSender, DCNotify dcNotify)

当多个事件发送到同一 taskKey 时,此方法会批量处理事件,并且仅执行单个网络调用。这是一种优化,旨在减少流量和网络相关资源。

在 Keycloak 26 中,新方法具有默认实现,以保持与自定义实现的向后兼容性。默认实现为每个事件执行单个网络调用,并且将在 Keycloak 的未来版本中移除。

为了提高组的可伸缩性,现在在移除 realm 时直接从数据库中移除组。因此,在移除 realm 时不再触发组相关事件,如 GroupRemovedEvent

如果您有扩展程序在移除 realm 时处理任何组相关事件,请确保改为使用 RealmRemovedEvent ,以便在移除 realm 及其组时执行任何清理或自定义处理。

GroupProvider 接口也已更新,添加了一个新的 preRemove(RealmModel) 方法,以强制实现正确处理在移除 realm 时移除组的情况。

从根路径自动重定向到相对路径

当指定 http-relative-path 属性时,用户会自动重定向到 Keycloak 托管的路径。这意味着当相对路径设置为 /auth ,并且用户访问 localhost:8080/ 时,页面将重定向到 localhost:8080/auth

当指定 http-management-relative-pathhttp-relative-path 属性时,管理界面也适用相同的情况。

这改善了用户体验,因为用户不再需要显式地将相对路径设置为 URL。

Operator 调度默认值

Keycloak Pod 现在将具有默认的亲和性,以防止来自同一 CR 的多个实例部署在同一节点上,并且来自同一 CR 的所有 Pod 将优先位于同一区域中,以防止拉伸缓存集群。

Operator 的默认 CPU 和内存限制/请求

为了遵循最佳实践,引入了 Operator 的默认 CPU 和内存限制/请求。这会影响非 OLM 安装和 OLM 安装。要覆盖 OLM 安装的默认值,请编辑 operator 的 subscription 中的 resources 部分。

keycloak-common 模块中的弃用

以下项目已被弃用,将在即将到来的 Keycloak 版本中移除,且没有替代项

  • org.keycloak.common.util.reflections.Reflections.newInstance(java.lang.Class<T>)

  • org.keycloak.common.util.reflections.Reflections.newInstance(java.lang.Class<?>, java.lang.String)

  • org.keycloak.common.util.reflections.SetAccessiblePrivilegedAction

  • org.keycloak.common.util.reflections.UnSetAccessiblePrivilegedAction

URL 编码一致使用 UTF-8 字符集

org.keycloak.common.util.Encode 现在始终使用 UTF-8 字符集进行 URL 编码,而不是隐式依赖于 file.encoding 系统属性。

配置 LDAP 连接池

在本版本中,LDAP 连接池配置完全依赖于系统属性。主要原因是 LDAP 连接池配置是 JVM 级别的配置,而不是特定于单个 realm 或 LDAP 提供程序实例的配置。

与以前的版本相比,任何与 LDAP 连接池相关的 realm 配置都将被忽略。如果您是从以前的版本迁移而来,并且以下任何设置已设置为您的 LDAP 提供程序,请考虑改用系统属性

  • connectionPoolingAuthentication

  • connectionPoolingInitSize

  • connectionPoolingMaxSize

  • connectionPoolingPrefSize

  • connectionPoolingTimeout

  • connectionPoolingProtocol

  • connectionPoolingDebug

有关更多详细信息,请参阅 配置连接池

此版本引入了轻松地为 base/loginkeycloak.v2/login 主题的登录页面添加自定义页脚的功能。为了使用自定义页脚,请在您的自定义登录主题中创建一个包含所需内容的 footer.ftl 文件。

有关更多详细信息,请参阅 向登录主题添加自定义页脚

跨重启持久化吊销的访问令牌

在本版本中,当使用嵌入式缓存时,吊销的访问令牌默认写入数据库并在集群重启时重新加载。

要禁用此行为,请使用 SPI 选项 spi-single-use-object-infinispan-persist-revoked-tokens ,如 所有提供程序配置 指南中所述。

SingleUseObjectProvider 的 SPI 行为已更改,对于吊销的令牌,仅必须使用方法 putcontains 。默认情况下强制执行此操作,并且可以使用 SPI 选项 spi-single-use-object-infinispan-persist-revoked-tokens 禁用。

高可用性多站点部署

Keycloak 26 对推荐的 HA 多站点架构进行了重大改进,最值得注意的是

  • Keycloak 部署现在能够同时在两个站点中处理用户请求。以前一次仅在一个站点中处理请求的负载均衡器配置将继续工作。

  • 现在需要主动监控站点之间的连接,以便在发生故障时在站点之间进行复制。蓝图描述了使用 Alertmanager 和 AWS Lambda 的设置。

  • 负载均衡器蓝图已更新为使用 AWS Global Accelerator,因为这避免了客户端 DNS 缓存导致的长时间故障转移时间。

  • 持久用户会话现在是架构的要求。因此,用户会话将在 Keycloak 或 Infinispan 升级时保留。

  • 外部 Infinispan 请求处理已得到改进,以减少内存使用量和请求延迟。

由于上述更改,您的现有 Keycloak 部署需要进行以下更改。

  1. 当启用 multi-site 功能时,缓存配置文件提供的 distributed-cache 定义将被忽略,因此您必须通过 cache-remote-* 命令行参数或 Keycloak CR 配置与外部 Infinispan 部署的连接,如蓝图中概述的那样。所有 remote-store 配置都必须从缓存配置文件中移除。

  2. 查看您当前在外部 Infinispan 中的缓存配置,并使用 Keycloak 文档最新版本中概述的配置更新它们。虽然以前版本的缓存配置仅在站点之间的备份复制失败时记录警告,但新配置确保两个站点的状态保持同步:当两个站点之间的传输失败时,调用者将看到错误。因此,您需要设置监控以在站点故障时断开两个站点的连接。《Keycloak 高可用性指南》包含有关如何设置此功能的蓝图。

  3. 虽然以前的负载均衡器配置将继续与 Keycloak 一起工作,但请考虑升级现有的 Route53 配置,以避免客户端 DNS 缓存导致的长时间故障转移时间。

  4. 如果您已使用 remote-store 配置更新了缓存配置文件 XML 文件,这些配置将不再起作用。请改为启用 multi-site 功能并使用 cache-remove-* 选项。

单站点设置中的外部 Infinispan

如果您在单站点设置中使用外部 Infinispan,则 Keycloak 的早期版本不支持此功能,Keycloak 26 也不支持此功能。为了防止用户通过 Keycloak 缓存 XML 中的手动配置或通过 CLI 选项意外使用它,现在使用功能标志 cache-embedded-remote-store 对其进行保护。它被标记为实验性功能,因此不受支持。除非启用此实验性功能,否则 Keycloak 26 将不会使用此类配置启动并显示错误。

如果您一直在使用外部 Infinispan 来在重启和升级之间保持用户登录状态,请改用默认启用的 persistent-user-sessions 功能。然后不再需要外部 Infinispan。

实验性功能 cache-embedded-remote-store 将在未来的次要版本中移除

管理员引导和恢复

当所有管理员用户都被锁定后,重新获得对 Keycloak 实例的访问权限曾经很困难。该过程需要多个高级步骤,包括直接数据库访问和手动更改。为了改善用户体验,Keycloak 现在提供了多种引导新管理员帐户的方法,可用于从此类情况中恢复。

因此,环境变量 KEYCLOAK_ADMINKEYCLOAK_ADMIN_PASSWORD 已弃用。您应该改用 KC_BOOTSTRAP_ADMIN_USERNAMEKC_BOOTSTRAP_ADMIN_PASSWORD 。这些也是通用选项,因此可以通过 cli 或其他配置源指定,例如 --bootstrap-admin-username=admin 。有关更多信息,请参阅新的 引导管理员和恢复 指南。

应用程序发起的必需操作重定向现在包含 kc_action 参数

当从应用程序发起的必需操作执行重定向返回时,必需操作提供程序名称现在通过 kc_action 参数返回。这简化了检测为客户端执行了哪个必需操作。执行结果可以通过 kc_action_status 参数确定。

注意:此功能需要更改 Keycloak JS 适配器,因此如果您想使用此功能,建议升级到最新版本的适配器。

keycloak-services 模块中的弃用

UserSessionCrossDCManager 已弃用,并计划在 Keycloak 的未来版本中移除。请阅读 UserSessionCrossDCManager Javadoc 以获取要使用的替代方法。

身份提供程序不再从 realm 表示中可用

作为改进 realm 和组织在拥有许多身份提供程序时的可伸缩性的一部分,realm 表示不再保存身份提供程序的列表。但是,当导出 realm 时,它们仍然可以从 realm 表示中获得。

要获取 realm 中的身份提供程序查询,请优先使用 /realms/{realm-name}/identity-provider/instances 端点。此端点支持过滤器和分页。

CLI 导入占位符替换

CLI 命令 kc.[sh|bat] import 现在已启用占位符替换。以前,占位符替换仅在启动时为 realm 导入启用。

如果您希望禁用 import 命令的占位符替换,请添加系统属性 -Dkeycloak.migration.replace-placeholders=false

新的 Java API,用于按名称搜索 realm

RealmProvider Java API 现在包含一个新方法 Stream<RealmModel> getRealmsStream(String search) ,该方法允许按名称搜索 realm。虽然有一个默认实现,在从提供程序加载流后对其进行过滤,但鼓励实现提供更有效的实现。

密钥库和信任库默认格式更改

Keycloak 现在根据文件扩展名确定密钥库和信任库的格式。如果文件扩展名为 .p12.pkcs12.pfx ,则格式为 PKCS12。如果文件扩展名为 .jks.keystore.truststore ,则格式为 JKS。如果文件扩展名为 .pem.crt.key ,则格式为 PEM。

您仍然可以通过显式指定 https-key-store-typehttps-trust-store-type 来覆盖自动检测。管理界面及其 https-management-key-store-type 也适用相同的情况。FIPS 严格模式的限制保持不变。

spi-truststore-file-* 选项和信任库相关选项 https-trust-store-* 已弃用,我们强烈建议使用系统信任库。有关更多详细信息,请参阅相关的 指南

提高选择身份提供程序的性能

IDENTITY_PROVIDER 表中添加了新索引,以提高查询性能,这些查询用于获取与组织关联的 IDP,以及获取可用于登录的 IDP(已 enabled 、非 link_only 、未标记为 hide_on_login 的 IDP)。

如果该表当前包含超过 300,000 个条目,则默认情况下,Keycloak 将在自动模式迁移期间跳过索引的创建,而是在迁移期间在控制台上记录 SQL 语句。在这种情况下,必须在 Keycloak 启动后在数据库中手动运行这些语句。

此外, kc.orghideOnLoginPage 配置属性已迁移到身份提供程序本身,以便在搜索提供程序时进行更高效的查询。因此,API 客户端应使用 IdentityProviderRepresentation 中的 getOrganizationId/setOrganizationIdisHideOnLogin/setHideOnLogin 方法,并避免使用现在已弃用的旧版配置属性来设置这些属性。

移除 GELF 日志记录处理程序

GELF 支持已弃用一段时间,并且在此版本中,它已最终从 Keycloak 中移除。其他日志处理程序可用且完全受支持,可以替代 GELF 使用,例如 Syslog。有关详细信息,请参阅日志记录指南

common 主题资源的路径已更改

keycloak 主题的 common 资源的一些路径已更改,特别是第三方库的资源。请务必相应地更新您的自定义主题

  • node_modules/patternfly/dist 现在是 vendor/patternfly-v3

  • node_modules/@patternfly/patternfly 现在是 vendor/patternfly-v4

  • node_modules/@patternfly-v5/patternfly 现在是 vendor/patternfly-v5

  • node_modules/rfc4648/lib 现在是 vendor/rfc4648

此外,以下资源已从 common 主题中移除

  • node_modules/alpinejs

  • node_modules/jquery

如果您之前在主题中使用了任何已移除的资源,请确保将它们添加到您自己的主题资源中。

附加数据源现在需要使用 XA

Keycloak 默认不使用 XA 数据源。但是,如果使用多个数据源,则认为这是不安全的。从本版本开始,如果您要向 Keycloak 添加额外的数据源,则需要使用 XA 数据源。如果默认数据源支持 XA,您可以通过设置 --transaction-xa-enabled=true 选项来实现。对于附加数据源,您需要在 quarkus.properties 文件中使用 quarkus.datasource.<your-datasource-name>.jdbc.transactions=xa 选项。最多只能有一个数据源是非 XA 的。当您的事务存储没有持久性存储时,不支持恢复。

主机名 v1 功能已移除

已弃用的主机名 v1 功能已移除。此功能在 Keycloak 25 中已弃用,并由主机名 v2 替代。如果您仍在使用此功能,则必须迁移到主机名 v2。有关更多详细信息,请参阅配置主机名 (v2)初始迁移指南

代理选项已移除

已弃用的 proxy 选项已移除。此选项在 Keycloak 24 中已弃用,并由 proxy-headers 选项与所需的主机名选项结合使用替代。有关更多详细信息,请参阅使用反向代理初始升级指南

默认情况下,所有用户会话都会持久化

由于数据库现在是用户会话的真实来源,因此可以限制会话缓存的大小以减少内存使用量。如果您使用默认的 conf/cache-ispn.xml 文件,则用于存储用户和客户端会话的缓存默认配置为仅存储 10000 个会话,并且每个条目有一个所有者。

使用类似于下面所示的配置更新您的自定义嵌入式 Infinispan 缓存配置文件,用于缓存 sessionsclientSessionsofflineSessionsofflineClientSessions

<distributed-cache name="sessions" owners="1">
    <!-- other configuration -->
    <memory max-count="10000"/>
</distributed-cache>

有关更多详细信息,请访问配置分布式缓存指南。

启用持久会话后,空闲会话的宽限期已移除

以前版本的 Keycloak 为用户和客户端会话的空闲时间添加了两分钟的宽限期。这是由于以前的架构中会话刷新时间在集群中异步复制而添加的。使用持久用户会话后,这不再是必需的,因此现在移除了宽限期。

要保留旧的行为,请更新您的 realm 配置,并将会话和客户端空闲时间延长两分钟。

已移除对旧版 redirect_uri 参数和 SPI 选项的支持

以前版本的 Keycloak 支持通过打开注销端点 URL(例如 http(s)://example-host/auth/realms/my-realm-name/protocol/openid-connect/logout?redirect_uri=encodedRedirectUri)自动注销用户并重定向到应用程序。此功能在 Keycloak 18 中已弃用,并已在本版本中移除,以支持遵循 OpenID Connect 规范。

作为此更改的一部分,以下相关的 SPI 配置选项已被移除

  • --spi-login-protocol-openid-connect-legacy-logout-redirect-uri

  • --spi-login-protocol-openid-connect-suppress-logout-confirmation-screen

如果您仍在使用这些选项或用于注销的 redirect_uri 参数,则应改为实施 OpenID Connect RP-Initiated Logout 规范

--optimized 启动选项的附加验证

--optimized 启动选项现在要求首先构建优化的服务器镜像。这可以通过首先运行 kc.sh|bat build 或通过任何其他不带 --optimized 标志的服务器命令(如 startexportimport)来实现。

适配器和 misc BOM 文件已移除

org.keycloak.bom:keycloak-adapter-bomorg.keycloak.bom:keycloak-misc-bom BOM 文件已移除。适配器 BOM 不再有用,因为大多数 Java 适配器已被移除。misc BOM 仅包含一个构件,keycloak-test-helper,并且该构件也已在此版本中移除。

keycloak-test-helper 已移除

maven 构件 org.keycloak:keycloak-test-helper 已在此版本中移除。该构件为处理 Java 管理客户端提供了一些辅助方法。如果您使用这些辅助方法,则可以在需要时将它们 fork 到您的应用程序中。

JEE admin-client 已移除

JEE admin-client 已在此版本中移除。我们仍然保持对 Jakarta admin-client 的支持。

凭据的新的通用事件类型

现在有用于更新 (UPDATE_CREDENTIAL) 和移除 (REMOVE_CREDENTIAL) 凭据的通用事件。凭据类型在事件的 credential_type 属性中描述。电子邮件事件侦听器支持新的事件类型。

以下事件类型现在已弃用,将在未来版本中移除:UPDATE_PASSWORDUPDATE_PASSWORD_ERRORUPDATE_TOTPUPDATE_TOTP_ERRORREMOVE_TOTPREMOVE_TOTP_ERROR

--import-realm 选项可以导入 master realm

当在 master realm 存在之前使用 --import-realm 选项运行 startstart-dev 命令时,如果 master realm 存在于导入材料中,则会导入它。之前的行为是首先创建 master realm,然后跳过其导入。

BouncyCastle FIPS 已更新

我们的 FIPS 140-2 集成现在已通过 BouncyCastle FIPS 库版本 2 的测试和支持。此版本已通过 Java 21 认证。如果您使用 FIPS 140-2 集成,建议将 BouncyCastle FIPS 库升级到最新文档中提到的版本。

BouncyCastle FIPS 版本 2 已通过 FIPS 140-3 认证。因此,只要在符合 FIPS 140-3 的系统上使用 Keycloak,Keycloak 就可以符合 FIPS 140-3 标准。这可能是基于 RHEL 9 的系统,该系统本身符合 FIPS 140-3 标准。但请注意,基于 RHEL 8 的系统仅通过 FIPS 140-2 认证。

setOrCreateChild() 方法已从 JavaScript Admin Client 中移除

groups.setOrCreateChild() 方法已从基于 JavaScript 的 Admin Client 中移除。如果您仍在使用此方法,请改用 createChildGroup()updateChildGroup() 方法。

Keycloak JS

此版本包括对 Keycloak JS 库的几项更改,应予以考虑。这些更改的主要动机是将库与 Keycloak 服务器解耦,以便可以独立重构库,从而简化代码并在未来更易于维护。更改如下

该库不再从服务器静态提供

Keycloak JS 库不再从 Keycloak 服务器静态提供。这意味着以下 URL 不再可用

  • /js/keycloak-authz.js

  • /js/keycloak-authz.min.js

  • /js/keycloak.js

  • /js/keycloak.min.js

  • /js/{version}/keycloak-authz.js

  • /js/{version}/keycloak-authz.min.js

  • /js/{version}/keycloak.js

  • /js/{version}/keycloak.min.js

此外,链接到这些 URL 上库的 keycloakJsUrl 属性已从管理控制台主题中移除。如果您的自定义主题使用此属性来包含库,您应该更新您的主题以使用不同的方法包含库。

如果您尚未这样做,则应使用诸如 NPM 之类的包管理器将库包含在您的项目中。该库在 NPM 注册表中以 keycloak-js 提供。您可以使用以下命令安装它

npm install keycloak-js

或者,服务器的发行版在 keycloak-js-26.0.0.tgz 存档中包含库的副本。您可以从那里将库复制到您的项目中。如果您在浏览器中直接使用库而没有构建,则需要自己托管该库。包管理器仍然是将库包含在项目中的推荐方法,因为它将使将来更新库更容易。

已移除对 UMD 发行版的支持

已移除 Keycloak JS 库的 UMD 发行版 Universal Module Definition。这意味着该库不再作为全局变量公开,而必须作为 模块 导入。此更改符合现代 JavaScript 开发实践,并允许浏览器和构建工具之间更一致的体验,并且通常会产生更可预测的代码,副作用更少。

如果您正在使用诸如 Vite 或 Webpack 之类的 bundler,则没有任何变化,您将获得与以前相同的体验。如果您在浏览器中直接使用该库,则需要更新您的代码以将该库作为模块导入

<!-- Before -->
<script src="/path/to/keycloak.js"></script>
<script>
    const keycloak = new Keycloak();
</script>

<!-- After -->
<script type="module">
    import Keycloak from '/path/to/keycloak.js';
    const keycloak = new Keycloak();
</script>

您也可以选择使用 import map 使库的导入不那么冗长

<script type="importmap">
    {
        "imports": {
            "keycloak-js": "/path/to/keycloak.js"
        }
    }
</script>
<script type="module">
    // The library can now be imported without specifying the full path, providing a similar experience as with a bundler.
    import Keycloak from 'keycloak-js';
    const keycloak = new Keycloak();
</script>

如果您正在使用 TypeScript,您可能需要更新您的 tsconfig.json 以便能够解析库

{
    "compilerOptions": {
        "moduleResolution": "Bundler"
    }
}
现在需要 Keycloak 实例的配置

以前,可以构造一个 Keycloak 实例而无需传递任何配置。然后,配置将根据包含的 keycloak.js 脚本的路径从服务器的 keycloak.json 文件自动加载。由于该库不再从服务器静态提供,因此此功能已被移除。您现在需要在构造 Keycloak 实例时显式传递配置

// Before
const keycloak = new Keycloak();

// After
const keycloak = new Keycloak({
    url: "http://keycloak-server",
    realm: "my-realm",
    clientId: "my-app"
});

// Alternatively, you can pass a URL to a `keycloak.json` file.
// Note this is not recommended as it creates additional network requests, and is prone to change in the future.
const keycloak = new Keycloak('http://keycloak-server/path/to/keycloak.json');
登录方法现在是 async

Keycloak JS 现在利用 Web Crypto API 进行各种加密功能。由于此 API 的异步性质,以下公共方法现在将始终返回 Promise

  • login()

  • createLoginUrl()

  • createRegisterUrl()

请务必更新您的代码以 await 这些方法

// Before
keycloak.login();
const loginUrl = keycloak.createLoginUrl();
const registerUrl = keycloak.createRegisterUrl();

// After
await keycloak.login();
const loginUrl = await keycloak.createLoginUrl();
const registerUrl = await keycloak.createRegisterUrl();

请务必更新您的代码以 await 这些方法。

现在需要安全上下文

Keycloak JS 现在需要 安全上下文 才能运行。原因是该库现在使用 Web Crypto API 进行各种加密功能。此 API 仅在安全上下文中可用,这些上下文是通过 HTTPS、localhost.localhost 域提供的上下文。如果您在非安全上下文中使用该库,则需要更新您的开发环境以使用安全上下文。

构建时选项的更严格的启动行为

当提供的构建时选项在启动时与上次优化的 Keycloak 构建期间服务器镜像中持久化的值不同时,Keycloak 现在将启动失败。以前,在这种情况下会显示警告消息。

功能已重命名

使用功能版本,功能 account3admin2login2 已重命名。禁用功能时,无需使用版本,例如,现在使用 --features-disabled=admin 禁用管理控制台。

要使用 login 的特定版本,请使用 --features=login:v1

迁移到 25.0.3

启用暴力破解时,默认情况下会阻止并发登录请求

如果攻击者并行发起大量登录尝试,则攻击者可能比暴力破解保护配置允许的密码猜测次数更多。这是由于暴力破解检查发生在暴力破解保护器锁定用户之前。为了防止这种竞争情况,暴力破解保护器现在拒绝所有在同一服务器中另一个登录正在进行时发生的登录尝试。

如果出于任何原因要禁用新功能,则有一个启动工厂选项

bin/kc.[sh|bat] start --spi-brute-force-protector-default-brute-force-detector-allow-concurrent-requests=true

迁移到 25.0.2

提高删除用户授权的性能

当客户端 scope 或完整的 realm 被删除时,关联的用户授权也应被移除。已在表 USER_CONSENT_CLIENT_SCOPE 上添加了一个新索引以提高性能。

请注意,如果表包含超过 300,000 个条目,则默认情况下,Keycloak 会在自动模式迁移期间跳过索引的创建,而是将 SQL 语句记录到控制台。这些语句必须在 Keycloak 启动后在数据库中手动运行。有关如何配置不同限制的详细信息,请查看升级指南

迁移到 25.0.0

新的主机名选项

默认情况下支持主机名 v2 选项,因为旧的主机名选项已弃用,并将在后续版本中移除。默认情况下会激活新选项,因此 Keycloak 将无法识别旧选项。

必要的迁移列表

旧选项 新选项

hostname <hostname>
hostname-url <url>
hostname-path <path>
hostname-port <port>

hostname <hostname/url>

hostname-admin <hostname>
hostname-admin-url <url>

hostname-admin <url>

hostname-strict-backchannel <true/false>

hostname-backchannel-dynamic <true/false>

如您所见,hostnamehostname-admin 选项的 *-url 后缀已移除。选项 hostname 接受主机名和 URL,但 hostname-admin 现在仅接受完整 URL。

此外,无法单独设置 pathport。您可以通过为 hostnamehostname-admin 选项提供完整 URL 来实现此目的。

如果端口不是 URL 的一部分,则会从传入的请求头动态解析端口。

除非 HTTPS 是 hostnamehostname-admin URL 的一部分,否则不再强制使用 HTTPS。如果未指定,则使用的协议 (http/https) 会从传入的请求动态解析。hostname-strict-https 选项已移除。

已移除的选项

hostname-url

hostname-admin-url

hostname-path

hostname-port

hostname-strict-backchannel

hostname-strict-https

为了使用旧的主机名选项以获得更多迁移时间,请启用功能 hostname:v1,例如 features=hostname:v1。请注意,hostname:v1hostname:v2 只能启用其中一个,不能同时启用两者。
示例
简化表示法
# Hostname v1
bin/kc.[sh|bat] start --hostname=mykeycloak.org --https-port=8543 --hostname-path=/auth --hostname-strict-https=true

# Hostname v2
bin/kc.[sh|bat] start --hostname=https://mykeycloak.org:8543/auth

如您在示例中看到的,现在可以通过单个 hostname 选项指定 URL 的所有部分,这简化了主机名设置过程。请注意,HTTPS 不是由 hostname-strict-https 选项强制执行的,而是通过在主机名 URL 中指定它来强制执行的。

Backchannel 设置
# Hostname v1
bin/kc.[sh|bat] start --hostname=mykeycloak.org --hostname-strict-backchannel=true

# Hostname v2
bin/kc.[sh|bat] start --hostname=mykeycloak.org --hostname-backchannel-dynamic=false

请注意,如果要对后端和前端端点使用相同的 URL,则行为会发生变化。以前,在主机名 v1 中,backchannel URL 是从请求头动态解析的。因此,为了实现所需的结果,您必须指定 hostname-strict-backchannel=true

对于主机名 v2,backchannel URL 已经与前端 URL 相同。为了从请求头动态解析它,您需要设置 hostname-backchannel-dynamic=true 并为 hostname 选项提供完整 URL。

有关更多详细信息和更全面的方案,请参阅配置主机名 (v2)

security-admin-console 客户端重定向 URI

${authAdminUrl} 的处理在主机名 v1 中已更改。以前,对于主机名 v1,如果未设置 hostname-adminhostname-admin-url 选项,则管理 URL 会从请求动态解析。对于主机名 v2,管理 URL 将默认设置为前端 URL。如果设置了 hostname 选项且 hostname-strict 为 true,则此更改将阻止具有备用主机名的重定向 URI 用于使用根 URL ${authAdminUrl} 的客户端。您应该考虑使用 hostname-admin 选项而不是重定向 URI,以允许单个备用主机名。应移除备用主机名重定向,因为 security-admin-console 客户端只需要根 URL 为 ${authAdminUrl} 的默认重定向 URI /admin/master/console/*

持久用户会话

以前版本的 Keycloak 仅在数据库中存储离线用户会话和离线客户端会话。新功能 persistent-user-sessions 不仅在内存中,而且还在数据库中存储在线用户会话和在线客户端会话。这将允许用户即使在所有 Keycloak 实例重启或升级后仍保持登录状态。

启用持久用户会话

此功能是预览功能,默认情况下禁用。要使用它,请将以下内容添加到您的构建命令中

bin/kc.sh build --features=persistent-user-sessions ...

有关更多详细信息,请参阅启用和禁用功能指南。容量调整指南包含一个新的段落,描述了启用此功能后更新的资源需求。

如果为现有部署启用了此功能,而该部署仅使用嵌入式 Infinispan 存储会话,则现有的在线用户会话和客户端会话将不会迁移到数据库。它只会影响新创建的在线用户会话和在线客户端会话。

启用持久会话后,在线用户会话、离线用户会话、在线客户端会话和离线客户端会话的内存缓存默认限制为每个节点 10000 个条目,这将减少大型安装的 Keycloak 的总体内存使用量。从内存中逐出的项目将在需要时按需从数据库加载。要为缓存设置不同的大小,请编辑 Keycloak 的缓存配置文件,为这些缓存设置 <memory max-count="..."/>。启用此功能后,预计每次登录、注销和刷新令牌请求的数据库利用率都会增加。

要在 Keycloak 多站点设置中的外部 Infinispan 中配置缓存大小,请查阅更新后的使用 Infinispan Operator 为 HA 部署 Infinispan 指南。

启用此功能后,选项 spi-user-sessions-infinispan-offline-session-cache-entry-lifespan-overridespi-user-sessions-infinispan-offline-client-session-cache-entry-lifespan-override 不再可用,因为它们以前用于覆盖离线会话在内存中保留的时间。

在升级期间迁移用户会话

从 Keycloak 24 或更早版本升级时,管理员可以选择将现有的在线用户会话和客户端会话迁移到持久会话。为此,这些现有会话需要存储在远程 Infinispan 或配置为 Keycloak 嵌入式缓存的 JDBC 持久性的数据库中。不支持迁移 Keycloak 24 的内存会话,因为由于嵌入式 Infinispan 的主要版本升级,所有 Keycloak 实例都需要在升级之前关闭。

用户会话的迁移仅在升级到 Keycloak 25 时启用持久用户会话时才有效。如果您选择在不启用持久用户会话的情况下升级到 25,则目前无法在稍后时间点触发现有会话的迁移。

稍后通过配置更改启用此功能可能会导致 Keycloak 与会话相关的未定义行为,如果持久会话和非持久会话共存。为防止这种情况,请在启用该功能的情况下启动第一个节点之前删除所有现有的在线用户会话和客户端会话。这意味着所有 Keycloak 节点都需要停止,并且如果使用,Infinispan 远程缓存存储和嵌入式 Infinispan JDBC 持久性需要清除。

要在 Keycloak 升级期间迁移用户会话,请执行以下步骤

  1. 停止所有正在运行的旧版 Keycloak 实例。

  2. 创建备份

    • 创建 Keycloak 数据库的备份。

    • 如果使用 JDBC 持久性,请创建该数据库的备份(如果您希望能够重试会话的迁移)。

    • 如果使用外部 Infinispan,请创建其数据的备份(如果您希望能够重试会话的迁移)。

  3. 启动启用了持久用户会话功能的新 Keycloak 实例。

    第一个启动节点将

    1. 将数据库迁移到模式版本 25。

    2. 将所有会话信息从远程 Infinispan 或为 Keycloak 嵌入式缓存配置的 JDBC 持久性复制到 Keycloak 的数据库。

      数据将存储在表 offline_user_sessionoffline_client_session 中,其中 offline_flag 设置为 false

    3. 清除缓存。

      这包括清除外部 Infinispan 的缓存(如果使用了外部 Infinispan),以及清除 JDBC 持久性(如果使用了 JDBC 持久性)。

  4. 更新 Keycloak 的缓存配置 XML,用于缓存 sessionsclientSessions

    • 如果使用 JDBC 持久性,请删除 JDBC 持久性的配置。

    • 如果远程 Infinispan 已在单站点设置中仅用于在 Keycloak 重启时保持用户会话,请删除这些缓存的远程 Infinispan 配置。

    如果在多站点设置中使用远程 Infinispan,您可以通过配置内存中的条目数来降低外部 Infinispan 的资源消耗。使用使用 Infinispan Operator 为 HA 部署 Infinispan 指南中概述的设置。
  5. 滚动重启 Keycloak 以激活新的缓存配置 XML。

注销现有用户

在以前的版本以及禁用该功能时,重启所有 Keycloak 节点会注销所有用户。要在使用 persistent-user-sessions 功能的情况下注销 realm 的所有在线用户会话,请像以前一样使用以下步骤

  1. 登录到管理控制台。

  2. 选择菜单项 会话

  3. 选择操作 注销所有活动会话

默认启用嵌入式缓存的指标

现在默认启用嵌入式缓存的指标。要启用延迟直方图,请将选项 cache-metrics-histograms-enabled 设置为 true

默认启用 HTTP 端点的指标

Keycloak 提供的指标现在包括以 http_server 开头的 HTTP 服务器指标。请参见下面的示例。

http_server_active_requests 1.0
http_server_requests_seconds_count{method="GET",outcome="SUCCESS",status="200",uri="/realms/{realm}/protocol/{protocol}/auth"} 1.0
http_server_requests_seconds_sum{method="GET",outcome="SUCCESS",status="200",uri="/realms/{realm}/protocol/{protocol}/auth"} 0.048717142

使用新选项 http-metrics-histograms-enabledhttp-metrics-slos 来启用默认直方图 bucket 或服务级别目标 (SLO) 的特定 bucket。有关直方图的更多信息,请阅读 Prometheus 文档中关于直方图 的内容,了解如何使用 http_server_requests_seconds_bucket 中提供的附加指标系列。

Argon2 密码哈希

在 Keycloak 24 版本中,我们的密码哈希算法发生了一项更改,导致 CPU 使用率增加。为了解决这个问题,我们为非 FIPS 环境选择了不同的默认哈希算法 Argon2,这使 CPU 使用率恢复到 Keycloak 24 版本之前的水平。

预计总体 CPU 使用率将提高,数据库活动将暂时增加

Keycloak 高可用性指南中的 CPU 和内存资源容量调整概念已更新,以反映新的哈希默认值。

升级后,在基于密码的登录期间,用户的密码将使用新的哈希算法和哈希迭代重新哈希作为一次性活动,并在数据库中更新。由于这会从 Keycloak 的内部缓存中清除用户,因此您还会看到数据库级别的读取活动增加。随着越来越多的用户密码被重新哈希,这种增加的数据库活动将随着时间的推移而减少。

更新的 JVM 垃圾回收设置

为了支持 Argon2 的内存密集型特性,我们已将默认 GC 从 ParallelGC 更新为 G1GC,以获得更好的堆利用率。请在此升级后密切监视 JVM 堆利用率。根据您的具体工作负载,可能需要进行额外的调整。

限制使用 HTTP 响应时的内存使用量

在某些场景下,例如 brokering,Keycloak 使用 HTTP 与外部服务器通信。为了避免在这些提供程序发送过多数据时发生拒绝服务,Keycloak 现在默认将响应限制为 10 MB。

用户可以通过设置提供程序配置选项 spi-connections-http-client-default-max-consumed-response-size 来配置此限制

将使用的响应限制为 1 MB
bin/kc.[sh|bat] --spi-connections-http-client-default-max-consumed-response-size=1000000

主机名验证策略

spi-truststore-file-hostname-verification-policy 和新的 tls-hostname-verifier 选项的默认值现在是 DEFAULT,而不是 WILDCARD。WILDCARD 和 STRICT 选项值已弃用 - 您应该只依赖 DEFAULT。

WILDCARD 支持的行为,DEFAULT 不支持的行为:* 允许子域名名称中的通配符(例如 *.foo.com)匹配任何内容,包括多个级别(例如 a.b.foo.com)。* 允许针对众所周知的公共后缀进行匹配 - 例如 foo.co.gl 可能匹配 *.co.gl

STRICT 支持的行为,DEFAULT 不支持的行为:* STRICT 使用一个小型的排除列表,用于以 2 个字母顶级域名结尾的 2 个或 3 个字母域名 (*.XXX.YY),以确定通配符是否匹配。相反,DEFAULT 使用来自 https://publicsuffix.org/list/ 的更完整的公共后缀规则和排除列表

不希望您依赖 WILDCARD 或 STRICT 选项的这些行为。

解决了已过期身份验证会话的“您已登录”问题

当身份验证会话过期且用户已登录时,Keycloak 现在不会向最终用户显示消息您已登录。而是将有关过期身份验证会话的错误重定向到客户端应用程序,以便客户端可以对其进行操作并按照服务器管理指南身份验证会话章节中的描述重新启动身份验证。您可以考虑更新您的应用程序以使其能够处理此错误。

移除了一个模型模块

模块 org.keycloak:keycloak-model-legacy 模块在以前的版本中已弃用,并在此版本中移除。请改用 org.keycloak:keycloak-model-storage 模块。

XA 事务更改

  • 选项 transaction-xa-enabled 将默认为 false,而不是 true。如果您需要 XA 事务支持,现在需要显式地将此选项设置为 true。

  • XA 事务恢复支持默认启用。事务日志将存储在 KEYCLOAK_HOME/data/transaction-logs 中。

移除离线会话预加载

在以前的版本中已弃用后,现在移除了启动时预加载离线会话的旧行为。

在运行时指定 cache 选项

选项 cachecache-stackcache-config-file 不再是构建选项,它们只能在运行时指定。这消除了由于它们而执行构建阶段和重建镜像的需求。请注意,它们在 build 阶段不会被识别,因此您需要将它们从 build 阶段移除并添加到 runtime 阶段。如果您不将当前的缓存选项添加到 runtime 阶段,Keycloak 将回退到默认缓存设置。

kcadm 和 kcreg 更改

kcadm 和 kcreg 解析和处理选项和参数的方式已更改。来自用法错误、错误选项或参数的错误消息可能与以前的版本略有不同。此外,用法错误将具有退出代码 2 而不是 1。

移除自定义用户属性索引

当按用户属性搜索用户时,Keycloak 不再搜索用户属性名称强制小写比较。这意味着在搜索时,将使用 Keycloak 用户属性表上的本机索引。如果您已创建自己的基于 `lower(name)` 的索引来加速搜索,则现在可以将其移除。

新的默认客户端 scope basic

名为 basic 的新客户端 scope 已添加为 realm “default” 客户端 scope,因此将添加到所有新创建的 OIDC 客户端。客户端 scope 也会在迁移期间自动添加到所有现有的 OIDC 客户端。

此 scope 包含以下声明的预配置协议映射器

  • sub(有关详细信息,请参见下面专门的部分)

  • auth_time

这提供了额外的帮助,以减少轻量级访问令牌中的声明数量,同时也提供了配置始终自动添加的声明的机会。

如果您在某些 realm 中已经有一个名为 basic 的客户端 scope,那么新的客户端 scope basic 将不会添加到您的 realm 中,也不会添加到任何客户端。在这种特定情况下,迁移将被忽略。在这种情况下,您要么需要确保在迁移到此 Keycloak 版本之前将您的客户端 scope 重命名为 basic 以外的名称,要么您需要手动处理令牌中缺少的 subauth_time 声明(如果您需要它们),并且您可能需要手动将相应的协议映射器添加到您的某些客户端 scope。

移除 session_state 声明

session_state 声明包含与 sid 声明相同的值,现在已从所有令牌中移除,因为它不是 OpenID Connect 前端通道注销和 OpenID Connect 后端通道注销规范所要求的。session_state 声明仍然按照 OpenID Connect 会话管理规范存在于访问令牌响应中。

请注意,setSessionState() 方法也已从 IDToken 类中移除,取而代之的是 setSessionId() 方法,而 getSessionState() 方法现在已被弃用。

新的 Session State (session_state) 映射器也已包含在内,可以分配给客户端 scope(例如 basic 客户端 scope)以恢复到旧的行为。

如果使用旧版本的 JS 适配器,则也应通过使用如上所述的客户端 scope 来使用 Session State (session_state) 映射器。

sub 声明通过协议映射器添加到访问令牌

sub 声明以前总是添加到访问令牌中,现在默认添加,但使用新的 Subject (sub) 协议映射器。

Subject (sub) 映射器默认在 basic 客户端 scope 中配置。因此,升级到此版本后无需额外配置。

如果您正在使用 Pairwise subject identifier 映射器来映射访问令牌的 sub 声明,您可以考虑禁用或移除 Subject (sub) 映射器,但这并非严格必要,因为 Subject (sub) 协议映射器在 Pairwise subject identifier 映射器之前执行,因此 pairwise 值将覆盖 Subject (sub) 映射器添加的值。这也可能适用于其他自定义协议映射器实现,它们会覆盖 sub 声明,因为 Subject (sub) 映射器目前作为第一个协议映射器执行。

您可以仅对访问令牌、轻量级访问令牌和内省响应使用 Subject (sub) 映射器来配置 sub 声明。IDToken 和 Userinfo 始终包含 sub 声明。

该映射器对服务帐户无效,因为不存在用户会话,并且 sub 声明始终添加到访问令牌中。

Nonce 声明仅添加到 ID 令牌

nonce 声明现在仅添加到 ID 令牌,严格遵循 OpenID Connect Core 1.0 规范。正如规范中指出的,当在授权请求中发送相同的参数时,该声明在 ID 令牌中是强制性的。规范还建议在 刷新请求后不要添加 nonce。以前,该声明在所有响应(包括刷新)中都设置为所有令牌(访问令牌、刷新令牌和 ID 令牌)。

软件中还包含一个新的 Nonce backwards compatible 映射器,可以分配给客户端 scope 以恢复到旧的行为。例如,JS 适配器在版本 24.0.0 中修复问题 #26651 之前,检查了所有令牌中返回的 nonce 声明。因此,如果使用旧版本的 JS 适配器,则应通过使用客户端 scope 将映射器添加到所需的客户端。

REFRESH_TOKEN 事件中的 userId 现在始终从用户会话中获取,而不是从刷新令牌中的 sub 声明中获取。REFRESH_TOKEN_ERROR 事件中的 userId 现在始终为 null。此更改的原因是,随着可选的 sub 声明的引入,刷新令牌中 sub 声明的值可能为 null,或者在使用成对主体标识符或其他覆盖 sub 声明的方式时,甚至可能与实际用户 ID 不同。

但是,现在添加了 refresh_token_sub 详细信息作为向后兼容性,以便在 REFRESH_TOKEN_ERROR 事件中缺少 userId 的情况下提供有关用户的信息。

使用旧版本的 javascript 适配器

如果您在应用程序中使用最新的 Keycloak 服务器和旧版本的 javascript 适配器,您可能会受到上述令牌更改的影响,因为以前版本的 javascript 适配器依赖于 Keycloak 添加的声明,但这些声明不受 OIDC 规范的支持。这包括

  • 在使用 Keycloak Javascript 适配器 24.0.3 或更旧版本的情况下,添加 Session State (session_state) 映射器

  • 在使用早于 Keycloak 24 的 Keycloak Javascript 适配器的情况下,添加 Nonce backwards compatible 映射器

您可以将协议映射器直接添加到相应的客户端,或者添加到某些客户端 scope,您的客户端应用程序可以使用这些客户端 scope 来依赖旧版本的 Keycloak Javascript 适配器。有关更多详细信息,请参阅前面专门介绍 session_statenonce 声明的部分。

默认 http-pool-max-threads 减少

如果未设置 http-pool-max-threads,则默认值将为 50 或 4 x(可用处理器)中的较大值。以前,默认值为 200 或 8 x(可用处理器)中的较大值。由于减少了活动线程之间的上下文切换,因此对于大多数使用场景,减少任务线程数将导致略高的性能。

指标和健康端点的管理端口

/health/metrics 端点可通过管理端口 9000 访问,默认情况下该端口已开启。这意味着这些端点不再暴露于标准的 Keycloak 端口 80808443

为了反映旧的行为,请使用属性 --legacy-observability-interface=true,这将不会在管理端口上暴露这些端点。但是,此属性已弃用,将在未来版本中移除,因此建议不要使用它。

管理接口使用与默认 Keycloak HTTP 服务器不同的 HTTP 服务器,并且可以单独配置它们。请注意,如果未为管理接口属性提供任何值,则它们将从默认 Keycloak HTTP 服务器继承。

有关更多详细信息,请参阅 配置管理接口

转义组路径中的斜杠

Keycloak 从未转义组路径中的斜杠。因此,名为 group/slash 的组是 top 的子组,使用完整路径 /top/group/slash,这显然具有误导性。从该版本开始,可以启动服务器以对名称中的这些斜杠执行转义。

bin/kc.[sh|bat] start --spi-group-jpa-escape-slashes-in-group-path=true

转义字符是波浪号 ~。之前的示例将生成路径 /top/group~/slash。转义标记最后一个斜杠是名称的一部分,而不是层次结构分隔符。

转义目前默认禁用,因为它代表行为上的更改。然而,建议启用转义,并且它可能成为未来版本中的默认设置。

更改为类 EnvironmentDependentProviderFactory

方法 EnvironmentDependentProviderFactory.isSupported() 在多个版本中已被弃用,现在已被移除。

请改为实现 isSupported(Config.Scope config)

移除已弃用的 LinkedIn 提供程序

在 22.0.2 版本中,LinkedIn 的 OAuh 2.0 社交提供程序已被新的 OpenId Connect 实现取代。旧的提供程序已被弃用但未移除,以防它在某些现有 realm 中仍然可用。Keycloak 25.0.0 肯定会移除旧的提供程序及其关联的 linkedin-oauth 功能。从现在开始,默认的 LinkedIn 社交提供程序是唯一可用的选项。

改进了 findGrantedResourcesfindGrantedOwnerResources 查询的性能

RESOURCE_SERVER_RESOURCERESOURCE_SERVER_PERM_TICKET 表格包含超过 10 万条条目,并且用户被授予访问超过 1 千个资源的权限时,这些查询的性能很差。查询已得到简化,并为 requesterowner 列引入了新的索引。

新的索引都应用于 RESOURCE_SERVER_PERM_TICKET 表格。如果表格当前包含超过 30 万条条目,Keycloak 将默认在自动架构迁移期间跳过索引的创建,而是在迁移期间在控制台上记录 SQL 语句。在这种情况下,必须在 Keycloak 启动后在数据库中手动运行这些语句。

有关如何配置不同限制的详细信息,请参阅 升级指南

AccessTokenIDTokenJsonWebToken 类中移除已弃用的方法

以下方法已从 AccessToken 类中移除

  • expiration。请改用 exp 方法。

  • notBefore。请改用 nbf 方法。

  • issuedAt。请改用 iat 方法。

以下方法已从 IDToken 类中移除

  • getAuthTimesetAuthTime。请分别使用 getAuth_timesetAuth_time 方法。

  • notBefore。请改用 nbf 方法。

  • issuedAt。请改用 iat 方法。

  • setSessionState。请改用 setSessionId 方法(有关详细信息,请参阅上面关于 session_state 声明的部分)

以下方法已从 JsonWebToken 类中移除

  • expiration。请改用 exp 方法。

  • notBefore。请改用 nbf 方法。

  • issuedAt。请改用 iat 方法。

您还应该预期令牌中未设置 expnbf 声明,因为它们是可选的。以前,这些声明被设置为值 0,这没有多大意义,因为它们的值应该是有效的 NumericDate

方法 getExp 添加到 SingleUseObjectKeyModel

由于从 AccessTokenIDTokenJsonWebToken 中移除了已弃用的方法,SingleUseObjectKeyModel 也进行了更改,以保持与过期值相关的方法名称的一致性。

之前的 getExpiration 方法现在已被弃用,您应该首选使用新引入的 getExp 方法,以避免 2038 年后的溢出。

PasswordHashProvider 上的方法 encode 已弃用

接口 org.keycloak.credential.hash.PasswordHashProvider 上的方法 String encode(String rawPassword, int iterations) 已弃用。该方法将在未来的 Keycloak 版本之一中移除。可能是 Keycloak 27 版本。

移除 CollectionUtil intersection 方法

方法 org.keycloak.common.util.CollectionUtil.intersection 已被移除。您应该在现有集合上使用 'java.util.Collection.retainAll' 代替。

Resteasy util 类已弃用

org.keycloak.common.util.Resteasy 已被弃用。您应该使用 org.keycloak.util.KeycloakSessionUtil 来获取 KeycloakSession 代替。

强烈建议避免使用创建自定义提供程序以外的其他方式获取 KeycloakSession

会话生存期和空闲计算的细微变化

在以前的版本中,当验证会话是否仍然有效时,会话最大生存期和空闲超时计算略有不同。现在,该验证使用与项目其余部分相同的代码。

如果会话正在使用记住我功能,则空闲超时和最大生存期是通用 SSO 和记住我配置值之间的最大值。

外部 Infinispan 要求

Keycloak 现在要求外部 Infinispan 部署的 Infinispan 服务器版本至少为 15.0.0。HA 指南中概述的多站点设置支持外部 Infinispan 部署。

Oracle 数据库驱动程序不包含在发行版中

Oracle 数据库 JDBC 驱动程序不再是 Keycloak 发行版的一部分。如果您希望使用 Oracle DB,您必须手动安装与您的特定环境兼容的 Oracle 驱动程序版本。有关此过程的说明,请参阅 配置数据库 指南。

已弃用的主题变量

以下变量在管理主题中已弃用,将在未来版本中移除

  • authServerUrl。请改用 serverBaseUrl

  • authUrl。请改用 adminBaseUrl

以下变量在帐户主题中已弃用,将在未来版本中移除

  • authServerUrl。请改用 serverBaseUrl,请注意 serverBaseUrl 不包含尾部斜杠。

  • authUrl。请改用 serverBaseUrl,请注意 serverBaseUrl 不包含尾部斜杠。

客户端会话中获取和设置当前刷新令牌的方法现在已弃用

接口 org.keycloak.models.AuthenticatedClientSessionModel 中的方法 String getCurrentRefreshToken()void setCurrentRefreshToken(String currentRefreshToken)int getCurrentRefreshTokenUseCount()void setCurrentRefreshTokenUseCount(int currentRefreshTokenUseCount) 已弃用。它们已被需要标识符作为参数的类似方法替换,例如 getRefreshToken(String reuseId),以便管理客户端会话中的多个刷新令牌。这些方法将在未来的 Keycloak 版本之一中移除。可能是 Keycloak 27 版本。

迁移到 24.0.4

通过 Admin User API 更新用户时,不再支持对用户属性进行部分更新

通过 Admin User API 更新用户属性时,更新用户属性(包括根属性,如 usernameemailfirstNamelastName)时,您无法执行部分更新。

如果您通过 Admin User API 更新用户属性,但未传递管理员具有写入权限的所有属性,则缺少的属性将被移除。另一方面,如果某个属性被标记为管理员只读,则不发送该属性不会将其移除。

有关用户配置文件设置的详细信息,请参阅 用户配置文件文档

迁移到 24.0.3

org.keycloak.userprofile.UserProfileDecorator 接口的更改

为了正确支持 realm 中的多个用户存储提供程序,org.keycloak.userprofile.UserProfileDecorator 接口已更改。

decorateUserProfile 方法不再在首次解析用户配置文件配置(并缓存它)时调用,而是在每次通过用户配置文件提供程序管理用户时调用。因此,该方法更改了其约定为

List<AttributeMetadata> decorateUserProfile(String providerId, UserProfileMetadata metadata)

与之前的约定和行为不同,此方法仅为从中加载用户的用户存储提供程序调用。

使用通配符时重定向 URI 验证的更改

出于安全考虑,如果传递的重定向 URI 包含 userinfo 部分或其 path 访问父目录 (/../),则重定向 URI 验证现在执行精确字符串匹配(不涉及通配符)。

完整的通配符 * 仍然可以在开发中用作具有这些特征的 http(s) URI 的有效重定向。在生产环境中,对于任何此类 URI,都需要配置没有通配符的精确有效重定向 URI。

请注意,不建议在生产中使用通配符有效重定向 URI,并且 OAuth 2.0 规范未涵盖它们。

已弃用的用于移除凭据的 Account REST 端点

用于移除用户凭据的 Account REST 端点已弃用。从该版本开始,Account Console 不再使用此端点。它已被 Delete Credential 应用程序发起的动作取代,当用户想要移除用户凭据时,Account Console 会触发该动作。

迁移到 24.0.2

密码哈希的更改

Keycloak 24.0.0 的发行说明已更新,其中包含对预期性能影响的更正描述,以及大小调整指南。

迁移到 24.0.0

欢迎主题的更改

“welcome”主题已更新为使用新的布局,现在使用 PatternFly 5 而不是 PatternFly 3。如果您正在扩展主题或提供自己的主题,则可能需要按如下方式更新它

从 PatternFly 3 迁移到 PatternFly 5

欢迎主题是 Keycloak 中较过时的主题之一。它最初基于 PatternFly 3,但现在已更新为使用 PatternFly 5,跳过了一个主要版本。如果您的自定义主题扩展了内置主题,您将需要更新它以使用 PatternFly 5 语法。有关详细信息,请查阅 PatternFly 5 文档

如果您仍然在自己的自定义主题中使用 PatternFly 3(而不是扩展内置主题),您可以继续使用它,但 PatternFly 3 支持将在未来版本中移除,因此您应考虑尽快迁移到 PatternFly 5。

自动重定向到管理控制台

如果启用了管理控制台,则欢迎页面将在管理用户已存在的情况下自动重定向到它。可以通过在 theme.properties 文件中设置 redirectToAdmin 来修改此行为。默认情况下,该属性设置为 false,除非您正在扩展内置主题,在这种情况下,该属性设置为 true

这些属性以前用于导航元素,这些元素现在已不再存在。如果您正在扩展内置主题,您将需要从 theme.properties 文件中移除这些属性,因为它们不再具有任何效果。

资源现在从“common”资源加载

背景、徽标和 favicon 等图像现在从“common”资源而不是主题资源加载。此更改意味着,如果您正在扩展内置主题并覆盖这些图像,您将需要将它们移动到主题的“common”资源,并更新您的 theme.properties 文件以包含新路径

# This defaults to 'common/keycloak' if not set.
import=common/your-theme-name

帐户控制台主题自定义的更改

如果您之前扩展了现已弃用的版本 2 的帐户控制台主题,您将需要更新您的主题以使用新版本 3 的帐户控制台主题。新版本的帐户控制台主题在如何自定义方面进行了一些更改。要从一个干净的状态开始,您可以按照新的 自定义快速入门 进行操作。

要移动您的自定义主题,请首先将 parent 更改为新主题

# Before
parent=keycloak.v2

# After
parent=keycloak.v3

如果您有任何自定义 React 组件,您将直接导入 React,而不是使用相对路径

// Before
import * as React from "../../../../common/keycloak/web_modules/react.js";

// After
import React from "react";

如果您使用 content.json 自定义主题,则文件结构有一些更改,具体来说

  • content 属性已重命名为 children

  • idiconcomponentName 属性已被移除,因为 modulePath 提供了相同的功能。

Keycloak JS 导入可能需要更新

如果您直接从 Keycloak 服务器加载 Keycloak JS,则可以安全地忽略此部分。如果您从 NPM 包加载 Keycloak JS 并使用 Webpack、Vite 等捆绑器,则可能需要对您的代码进行一些更改。Keycloak JS 包现在在 package.json 文件中使用 exports 字段。这意味着您可能必须更改您的导入

// Before
import Keycloak from 'keycloak-js/dist/keycloak.js';
import AuthZ from 'keycloak-js/dist/keycloak-authz.js';

// After
import Keycloak from 'keycloak-js';
import AuthZ from 'keycloak-js/authz';

功能变更

不再允许在 --features--features-disabled 列表中具有相同的功能。该功能应仅出现在一个列表中。

--features 列表中使用未版本化的功能名称(例如 docker)将允许为您启用最受支持/最新的功能版本。如果您需要在各个版本之间获得更可预测的行为,请引用您想要的特定版本,例如 docker:v1

用户配置文件更改

用户配置文件默认启用

用户配置文件功能现在默认启用。declarative-user-profile 功能不再可用,因为用户配置文件假定为已启用。因此,用户配置文件已启用开关已从Realm 设置中移除,并替换为非托管属性。从以前的版本迁移时,行为如下:

  • 对于用户配置文件已启用设置为的部署,升级后非托管属性将设置为。因此,仅允许用户配置文件显式支持的用户属性。

  • 对于用户配置文件已启用设置为的部署(这也是禁用 declarative-user-profile 功能的部署的默认设置,而这又是默认设置),升级后非托管属性将设置为。因此,行为应与以前禁用用户配置文件的版本基本相同。属性选项卡将保留在管理控制台的用户详细信息部分中。此外,只要特定的自定义主题支持,用户现在可以通过 UI 页面(例如注册页面和更新配置文件页面)设置任意属性。自定义主题也应像以前一样工作。但是,请考虑更新您的主题以使用用户配置文件,甚至在需要添加自定义属性时移除您的自定义主题。请参阅后续关于主题的部分。此外,请考虑将非托管属性切换为,或仅为管理员启用此开关,以便您可以主要依赖于使用托管属性。

有关非托管属性的详细信息,请参阅 用户配置文件文档

默认验证

默认用户配置文件配置带有一组基本预定义字段的默认验证。当默认禁用 declarative-user-profile 功能时,这些验证在以前的版本中不存在。如果由于向后兼容性而遇到问题,您可以根据需要更改默认验证器。默认验证器如下:

  • usernameemailfirstNamelastName 属性的最大长度为 255 个字符。由于数据库约束,这些验证也间接地存在于以前的版本中,表格 USER_ENTITY 中这些字段的最大长度为 255 个字符。但是,当使用用户存储提供程序时,以前可能可以使用更长的值。

  • username 属性的最小长度为三个字符。默认情况下,用户名还具有 username-prohibited-charactersup-username-not-idn-homograph 验证器,这些验证器在以前的版本中不存在。有关这些属性的详细信息,请参阅 用户配置文件文档的验证部分。请注意,除非您启用了 realm 开关 Edit username enabled,否则默认情况下用户名是不可编辑的。此更改意味着用户名不正确的现有用户仍然可以工作,并且不会强制他们更新用户名。但是,新用户将被强制在注册或通过管理 REST API 创建时使用正确的用户名。

  • firstNamelastName 属性现在具有 person-name-prohibited-characters 验证器,这在之前的版本中是没有的。 有关这些属性的详细信息,请参阅用户配置文件文档的验证部分。 请注意,默认情况下名字和姓氏都是可编辑的,因此,如果用户从以前的版本中已经有了不正确的名字/姓氏,则在更新其用户配置文件时,将被强制更新它们。

具有特殊字符的用户属性名称

在以前的版本中,您可以创建具有诸如 some:attributesome/attribute 等属性名称的用户。 用户配置文件有意不允许您在用户配置文件配置中创建具有如此特殊名称的属性。 因此,您可能需要为您的 realm 配置非托管属性,并为管理员(理想情况下)或最终用户(如果确实需要)启用非托管属性。 尽管强烈建议避免使用此类属性名称。

默认启用“验证配置文件”必需操作

新的 realm 默认启用 verify-profile 必需操作。 但是,当您从以前的版本迁移时,您现有的 realm 将具有与之前相同的 verify-profile 操作状态,这通常意味着禁用,因为它在以前的版本中默认是禁用的。 有关此必需操作的详细信息,请参阅用户配置文件文档

用户配置文件 SPI 的重大更改

如果您在扩展程序中使用用户配置文件 SPI,您可能会受到此版本中引入的 API 更改的影响。

org.keycloak.userprofile.Attributes 接口包含以下更改

  • 方法 getValues 已重命名为 get,使其与常规 Java Map 中的相同操作更加一致

  • 方法 isRootAttribute 已移动到实用程序类 org.keycloak.userprofile.UserProfileUtil.isRootAttribute

  • 方法 getFirstValue 已重命名为 getFirst,使其不那么冗长

  • 方法 getReadable(boolean) 已被删除,现在只要具有读取权限,就会返回所有属性(包括根属性)。

Freemarker 模板的更改,以基于用户配置文件和 realm 呈现页面

在此版本中,以下模板已更新,以便可以根据为 realm 设置的用户配置文件配置动态呈现属性

  • login-update-profile.ftl

  • register.ftl

  • update-email.ftl

这些模板分别负责呈现更新配置文件页面(当为用户启用更新配置文件必需操作时)、注册页面和更新电子邮件页面(当启用 UPDATE_EMAIL 功能时)。

如果您使用自定义主题来更改这些模板,它们将按预期运行,因为仅更新了内容。 但是,我们建议您查看如何配置{声明式用户配置文件},并尽可能避免通过使用此功能提供的所有功能来更改内置模板。

此外,declarative-user-profile 功能用于呈现相同流程页面的模板不再是必需的,并在此版本中已删除

  • update-user-profile.ftl

  • register-user-profile.ftl

如果您在以前的版本中使用 declarative-user-profile 功能并自定义了上述模板,请相应地更新 login-update-profile.ftlregister.ftl

通过代理首次登录时更新配置文件页面的新 Freemarker 模板

在此版本中,当用户首次通过代理进行身份验证时,服务器将使用 idp-review-user-profile.ftl 模板呈现更新配置文件页面。

在以前的版本中,在首次代理登录流程期间用于更新配置文件的模板是 login-update-profile.ftl,与用户向 realm 进行身份验证时更新配置文件所使用的模板相同。

通过为每个流程使用单独的模板,可以更清楚地区分模板实际用于哪个流程,而不是共享同一个模板,并可能引入意外的更改和行为,而这些更改和行为应该只影响特定流程的页面。

如果您对 login-update-profile.ftl 模板进行了自定义,以自定义用户在通过代理进行身份验证时如何更新其配置文件,请确保将您的更改移动到新模板。

信任库更改

spi-truststore-file-* 选项和信任库相关选项 https-trust-store-* 已被弃用。 因此,请使用信任库材料的新默认位置 conf/truststores,或使用 truststore-paths 选项指定您所需的路径。 有关详细信息,请参阅相关的指南

tls-hostname-verifier 属性应代替 spi-truststore-file-hostname-verification-policy 属性使用。

更改的附带影响是,现在信任库提供程序始终配置了一些证书(至少存在默认的 Java 受信任证书)。 此新行为可能会影响 Keycloak 的其他部分。

例如,如果 attestation conveyance 配置为 Direct 验证,则 webauthn 注册可能会失败。 以前,如果未配置信任库提供程序,则不会验证传入的证书。 但现在始终执行此验证。 注册失败,并显示 invalid cert path 错误,因为 dongle 发送的证书链不受 Keycloak 的信任。 身份验证器的证书颁发机构需要存在于信任库提供程序中,才能正确执行 attestation。

已弃用的 --proxy 选项

--proxy 选项已被弃用,并将在未来的版本中删除。 下表解释了已弃用的选项如何映射到受支持的选项。

已弃用的用法 新的用法

kc.sh(未设置 proxy 选项)

kc.sh

kc.sh --proxy none

kc.sh

kc.sh --proxy edge

kc.sh --proxy-headers forwarded|xforwarded --http-enabled true

kc.sh --proxy passthrough

kc.sh --hostname-port 80|443(取决于是否使用 HTTPS)

kc.sh --proxy reencrypt

kc.sh --proxy-headers forwarded|xforwarded

为了加强安全性,--proxy-headers 选项不允许同时选择 forwardedxforwarded 值(就像以前的 --proxy edge--proxy reencrypt 的情况一样)。
当使用 proxy headers 选项时,请确保您的反向代理正确设置并覆盖 ForwardedX-Forwarded-* 标头。 要设置这些标头,请查阅您的反向代理的文档。 配置错误将使 Keycloak 暴露于安全漏洞。

当使用 Operator 时,您也可以设置 proxy headers

apiVersion: k8s.keycloak.org/v2alpha1
kind: Keycloak
metadata:
  name: example-kc
spec:
  ...
  proxy:
    headers: forwarded|xforwarded
如果未指定 proxy.headers 字段,则 Operator 会回退到以前的行为,默认情况下隐式设置 proxy=passthrough。 这会导致服务器日志中出现弃用警告。 此回退将在未来的版本中删除。

Admin API 和 Account 上下文中用户表示形式的更改

org.keycloak.representations.idm.UserRepresentationorg.keycloak.representations.account.UserRepresentation 表示类都已更改,以便在分别向 Admin 和 Account API 获取或发送表示形式有效负载时,根用户属性(例如 usernameemailfirstNamelastNamelocale)具有一致的表示形式。

usernameemailfirstNamelastNamelocale 属性已移动到新的 org.keycloak.representations.idm.AbstractUserRepresentation 基类。

此外,getAttributes 方法的目标是仅表示自定义属性,因此您不应期望在此方法返回的 map 中找到任何根属性。 此方法主要针对客户端在更新或获取给定用户的任何自定义属性时使用。

为了解析包括根属性在内的所有属性,添加了一个新的 getRawAttributes 方法,以便生成的 map 也包括根属性。 但是,此方法不能从表示形式有效负载中使用,其目标是在服务器管理用户配置文件时使用。

https-client-auth 是构建时选项

选项 https-client-auth 之前被视为运行时选项,但是 Quarkus 不支持这一点。 该选项需要在构建时而不是运行时处理。

顺序加载离线会话和远程会话

从该版本开始,Keycloak 集群的第一个成员将顺序加载远程会话,而不是并行加载。 如果启用了离线会话预加载,这些会话也将顺序加载。

以前的代码导致集群在启动时资源消耗过高,并且在生产环境中难以分析,并且如果节点在加载期间重新启动,则可能导致复杂的故障情况。 因此,已更改为顺序会话加载。

对于离线会话,Keycloak 在此版本和以前版本中的默认设置是按需加载这些会话,与尝试并行预加载相比,这可以更好地扩展大量离线会话。 使用此默认设置的安装不受离线会话加载策略更改的影响。 启用了离线会话预加载的安装应迁移到禁用离线会话预加载的设置。

已弃用的离线会话预加载

Keycloak 的默认行为是按需加载离线会话。 以前在启动时预加载它们的旧行为现在已被弃用,因为在启动时预加载它们无法随着会话数量的增长而很好地扩展,并且会增加 Keycloak 的内存使用量。 旧行为将在未来的版本中删除。

要在弃用但尚未删除的情况下重新启用旧行为,请使用功能标志和 SPI 选项,如下所示

bin/kc.[sh|bat] start --features-enabled offline-session-preloading --spi-user-sessions-infinispan-preload-offline-sessions-from-database=true

UserSessionProvider 的 API 弃用了方法 getOfflineUserSessionByBrokerSessionId(RealmModel realm, String brokerSessionId)。 请改用方法 getOfflineUserSessionByBrokerUserIdStream(RealmModel, String brokerUserId) 先获取用户的会话,然后根据需要按代理会话 ID 进行过滤。

Infinispan 指标对缓存管理器和缓存名称使用标签

当为 Keycloak 的嵌入式缓存启用指标时,指标现在对缓存管理器和缓存名称使用标签。

不带标签的旧指标示例
vendor_cache_manager_keycloak_cache_sessions_statistics_approximate_entries_in_memory{cache="sessions",node="..."}
带标签的新指标示例
vendor_statistics_approximate_entries_in_memory{cache="sessions",cache_manager="keycloak",node="..."}

要还原安装的更改,请使用自定义 Infinispan XML 配置并按如下方式更改配置

<metrics names-as-tags="false" />

用户属性值长度扩展

从该版本开始,Keycloak 支持存储和搜索长度超过 255 个字符的用户属性值,这在以前是一个限制。

在允许用户更新属性的设置中,例如通过帐户控制台,请通过添加验证来防止拒绝服务攻击。 确保不允许使用非托管属性,并且所有可编辑属性都具有限制输入长度的验证。

对于非托管属性,最大长度为 2048 个字符。 对于托管属性,默认最大长度为 2048 个字符。 管理员可以通过添加类型为 length 的验证器来更改此设置。

Keycloak 将用户相关对象缓存在其内部缓存中。 使用较长的属性会增加缓存消耗的内存。 因此,建议限制长度属性的大小。 考虑将大型对象存储在 Keycloak 外部,并通过 ID 或 URL 引用它们。

此更改在表 USER_ATTRIBUTEFED_USER_ATTRIBUTE 上添加了新索引。 如果这些表包含超过 300000 个条目,则默认情况下 Keycloak 将在自动模式迁移期间跳过索引创建,而是在迁移期间将 SQL 语句记录到控制台上,以便在 Keycloak 启动后手动应用。 有关如何配置不同限制的详细信息,请参阅升级指南

新添加的索引 USER_ATTR_LONG_VALUES_LOWER_CASEFED_USER_ATTR_LONG_VALUES_LOWER_CASE 可能会超出 Oracle 设置的最大 30 个字符的限制,如果数据库在兼容模式下运行。 自 Oracle 版本 12.2 以来,支持更长的索引名称。
LDAP 的其他迁移步骤

这适用于符合以下所有条件的安装

  • LDAP 目录中的用户属性大于 2048 个字符或二进制属性大于 1500 字节。

  • 属性由管理员或用户通过管理控制台、API 或帐户控制台更改。

为了能够通过 UI 和 REST API 更改这些属性,请执行以下步骤

  1. 在 realm 的用户配置文件中将上述标识的属性声明为托管属性。

  2. 为上一步中添加的每个属性定义一个 length 验证器,指定属性值的期望最小和最大长度。 对于二进制值,在预期的二进制长度上增加 33%,以计入 Keycloak 内部 base64 编码二进制值的开销。

自定义用户存储提供程序的其他迁移步骤

这适用于符合以下所有条件的安装

  • 运行 MariaDB 或 MySQL 作为 Keycloak 的数据库。

  • FED_USER_ATTRIBUTE 中的条目的 VALUE 列中的内容大于 2048 个字符。 此表用于启用联合的自定义用户提供程序。

  • 长属性由管理员或用户通过管理控制台或帐户控制台更改。

为了能够通过 UI 和 REST API 更改这些属性,请执行以下步骤

  1. 在 realm 的用户配置文件中将上述标识的属性声明为托管属性。

  2. 为上一步中添加的每个属性定义一个 length 验证器,指定属性值的期望最小和最大长度。

Admin send-verify-email API 现在使用相同的电子邮件验证模板

PUT /admin/realms/{realm-name}/users/{id}/send-verify-email

在此版本中,API 将使用 email-verification.ftl 模板,而不是 executeActions.ftl

升级前
Perform the following action(s): Verify Email
升级后
Confirm validity of e-mail address email@example.org.

如果您已自定义 executeActions.ftl 模板以修改用户如何使用此 API 验证其电子邮件,请确保将您的修改转移到新模板。

将引入一个名为 lifespan 的新参数,以允许覆盖默认的生存期值(12 小时)。

如果您喜欢以前的行为,请按如下方式使用 execute-actions-email API。

PUT /admin/realms/{realm-name}/users/{id}/execute-actions-email

["VERIFY_EMAIL"]

删除 SAML 加密的已弃用模式

版本 21 中引入的 SAML 加密兼容模式现已删除。 系统属性 keycloak.saml.deprecated.encryption 不再由服务器管理。 仍使用旧签名密钥进行加密的客户端应从新的 IDP 配置元数据中更新它。

密码哈希的更改

在此版本中,我们调整了密码哈希默认值,以匹配 OWASP 密码存储建议

作为此更改的一部分,默认密码哈希提供程序已从 pbkdf2-sha256 更改为 pbkdf2-sha512。 此外,基于 pbkdf2 的密码哈希算法的默认哈希迭代次数也发生了如下更改

提供程序 ID 算法 旧迭代次数 新迭代次数

pbkdf2

PBKDF2WithHmacSHA1

20.000

1.300.000

pbkdf2-sha256

PBKDF2WithHmacSHA256

27.500

600.000

pbkdf2-sha512

PBKDF2WithHmacSHA512

30.000

210.000

如果 realm 没有使用 hashAlgorithmhashIterations 显式配置密码策略,则新配置将在下一次基于密码的登录时生效,或者在创建或更新用户密码时生效。

新密码哈希配置的性能

在配备 Intel i9-8950HK CPU (12) @ 4.800GHz 的机器上进行的测试,得出了哈希 1000 个密码的以下平均时间差异(3 次运行的平均值)。 请注意,由于运行时较长,因此使用较少的密码计算了 PBKDF2WithHmacSHA1 的平均持续时间。

提供程序 ID 算法 旧持续时间 新持续时间 差异

pbkdf2

PBKDF2WithHmacSHA1

122 毫秒

3.114 毫秒

+2.992 毫秒

pbkdf2-sha256

PBKDF2WithHmacSHA256

20 毫秒

451 毫秒

+431 毫秒

pbkdf2-sha512

PBKDF2WithHmacSHA512

33 毫秒

224 毫秒

+191 毫秒

pbkdf2 提供程序的用户可能需要显式减少哈希迭代次数以重新获得可接受的性能。 这可以通过在 realm 的密码策略中显式配置哈希迭代次数来完成。

预计总体 CPU 使用率增加和临时数据库活动增加

Keycloak 高可用性指南中 CPU 和内存资源调整大小的概念已更新,以反映新的哈希默认值。 在我们的测试中,每次基于密码的登录的 CPU 使用率增加了五倍,其中包括更改的密码哈希和未更改的 TLS 连接处理。 由于 Keycloak 的其他活动(如刷新访问令牌和客户端凭据授权)的平均效应,总体 CPU 增加应在两到三倍左右。 然而,这取决于安装的独特工作负载。

升级后,在基于密码的登录期间,用户的密码将使用新的哈希算法和哈希迭代作为一次性活动重新哈希,并在数据库中更新。 由于这会从 Keycloak 的内部缓存中清除用户,您还将看到数据库级别的读取活动增加。 随着越来越多的用户密码被重新哈希,这种增加的数据库活动将随着时间的推移而减少。

如何继续使用旧的 pbkdf2-sha256 密码哈希?

要为 realm 保留旧的密码哈希,请在 realm 密码策略中显式指定 hashAlgorithmhashIterations

  • 哈希算法:pbkdf2-sha256

  • 哈希迭代次数:27500

Operator 引用的资源轮询

通过 Keycloak CR 引用的 Secret 和 ConfigMap 现在将轮询更改,而不是通过 api 服务器监视。 检测到更改可能需要大约 1 分钟。

这样做是为了不需要对这些资源进行标签操作。 升级后,如果任何 Secret 仍然具有 operator.keycloak.org/component 标签,则可以删除或忽略它。

重命名 JPA 提供程序配置选项以进行迁移

删除 Map Store 后,以下配置选项已重命名

  • spi-connections-jpa-legacy-initialize-emptyspi-connections-jpa-quarkus-initialize-empty

  • spi-connections-jpa-legacy-migration-exportspi-connections-jpa-quarkus-migration-export

  • spi-connections-jpa-legacy-migration-strategyspi-connections-jpa-quarkus-migration-strategy

重命名模型模块

删除 Map Store 后,以下模块已重命名

  • org.keycloak:keycloak-model-legacy-privateorg.keycloak:keycloak-model-storage-private

  • org.keycloak:keycloak-model-legacy-servicesorg.keycloak:keycloak-model-storage-services

并且 org.keycloak:keycloak-model-legacy 模块已被弃用,并将在下一个版本中删除,以支持 org.keycloak:keycloak-model-storage 模块。

临时锁定日志已替换为事件

现在,当用户被暴力破解保护器临时锁定时,会有一个新的事件 USER_DISABLED_BY_TEMPORARY_LOCKOUT。 ID 为 KC-SERVICES0053 的日志已被删除,因为新事件以结构化形式提供了信息。

由于这是一个成功事件,因此默认情况下,新事件记录在 DEBUG 级别。 使用 服务器管理指南中的事件侦听器章节 中描述的设置 spi-events-listener-jboss-logging-success-level 来更改所有成功事件的日志级别。

要触发自定义操作或自定义日志条目,请按照 服务器开发人员指南 中的事件侦听器 SPI 中的描述编写自定义事件侦听器。

Operator 自定义属性键

Operator 用于高级配置的属性键已从 operator.keycloak 更改为 kc.operator.keycloak

Keycloak CR 资源选项

当在 Keycloak CR 和 KeycloakRealmImport CR 中未指定 resources 选项时,将使用默认值。 Keycloak 部署和 realm 导入 Job 的默认 requests 内存设置为 1700MiBlimits 内存设置为 2GiB

Cookie 的更新

作为重构 Keycloak 中 cookie 处理的一部分,cookie 的设置方式有一些更改

  • 如果请求是通过安全上下文进行的,则所有 cookie 现在都将设置 secure 属性

  • WELCOME_STATE_CHECKER cookie 现在设置 SameSite=Strict

对于自定义扩展,可能需要进行一些更改

  • LocaleSelectorProvider.KEYCLOAK_LOCALE 已被弃用,因为 cookie 现在通过 CookieProvider 进行管理

  • HttpResponse.setWriteCookiesOnTransactionComplete 已被删除

  • HttpCookie 已被弃用,请改用 NewCookie.Builder

  • ServerCookie 已被弃用,请改用 NewCookie.Builder

内部算法从 HS256 更改为 HS512

Keycloak 用于签名内部令牌(Keycloak 本身使用的 JWT,例如刷新令牌或操作令牌)的算法正在从 HS256 更改为更安全的 HS512。 现在为 realm 添加了一个名为 hmac-generated-hs512 的新密钥提供程序。 请注意,在迁移的 realm 中,旧的 hmac-generated 提供程序和旧的 HS256 密钥仍然保留,并且仍然验证升级之前颁发的令牌。 按照轮换密钥指南,当不再存在旧令牌时,可以手动删除 HS256 提供程序。

在容器中运行时,JVM 内存设置不同

当在容器中运行时,JVM 选项 -Xms-Xmx 已被 -XX:InitialRAMPercentage-XX:MaxRAMPercentage 取代。 Keycloak 没有指定静态最大堆大小设置,而是将最大值指定为容器总内存的 70%。

由于堆大小是根据容器总内存动态计算的,因此您应始终为容器设置内存限制

如果未设置内存限制,则内存消耗会迅速增加,因为最大堆大小会增长到容器总内存的 70%。

有关更多详细信息,请参阅在容器中运行 Keycloak 指南。

GELF 日志处理程序已被弃用

随着提供与 GELF 集成的底层库的淘汰,Keycloak 将不再开箱即用地支持 GELF 日志处理程序。 此功能将在未来的版本中删除。 如果您需要外部日志管理,请考虑使用文件日志解析。

迁移到 23.0.5

jboss-logging 事件消息的更改

由于问题 #25078jboss-logging 消息值现在被引用(默认情况下为字符 ")并经过清理以防止任何换行符。 提供程序中有两个新选项(spi-events-listener-jboss-logging-sanitizespi-events-listener-jboss-logging-quotes)允许您自定义新行为。 例如,要避免清理和引用,服务器可以按以下方式启动

./kc.sh start --spi-events-listener-jboss-logging-sanitize=false --spi-events-listener-jboss-logging-quotes=none ...

有关选项的更多信息,请参阅所有提供程序配置指南

迁移到 23.0.4

修复 Groups.getSubGroups briefRepresentation 参数的处理

版本 23.0.0 在 Groups 资源上引入了一个新的端点 getSubGroups(“children”),其中参数 briefRepresentation 的含义是指检索子组的完整表示形式。 现在含义已更改为返回简要表示形式。

迁移到 23.0.2

客户端的有效重定向 URI 始终使用精确字符串匹配进行比较

版本 1.8.0 在将重定向 URI 与客户端指定的有效重定向进行比较时,引入了主机名和 scheme 的小写。 不幸的是,它并非在所有协议中都完全有效,例如,主机对于 http 是小写的,但对于 https 不是。 由于 OAuth 2.0 安全最佳实践 建议使用精确字符串匹配来比较 URI,因此 Keycloak 将遵循该建议,并且从现在开始,即使对于主机名和 scheme,有效重定向也使用精确大小写进行比较。

对于依赖旧行为的 realm,其客户端的有效重定向 URI 现在应为每个应由服务器识别的 URI 保留单独的条目。

尽管在配置客户端时引入了更多步骤和冗长性,但新行为实现了更安全的部署,因为基于模式的检查通常是安全问题的原因。 这些问题是由于它们的实现方式以及它们的配置方式造成的。

Operator -secrets-store Secret

旧版本的 Operator 创建了一个 Secret 来跟踪监视的 Secret。 新版本的 Operator 不再使用 -secrets-store Secret,因此可以删除它。

如果您使用的是 23.0.0 或 23.0.1 版本,并在 operator 日志中看到 “org.keycloak.operator.controllers.KeycloakAdminSecretDependentResource → java.lang.IllegalStateException: More than 1 secondary resource related to primary” 错误,则删除 -secrets-store Secret,或者升级到 23.0.2 版本,此问题已在 23.0.2 版本中解决。

迁移到 23.0.0

在 OAuth 2.0/OpenID Connect 身份验证响应中添加了 iss 参数

RFC 9207 OAuth 2.0 授权服务器发行者识别规范在 OAuth 2.0/OpenID Connect 身份验证响应中添加了参数 iss,以实现安全的授权响应。

在之前的版本中,我们没有这个参数,但现在 Keycloak 默认添加了这个参数,这是规范要求的。

然而,一些 OpenID Connect / OAuth2 适配器,特别是较旧的 Keycloak 适配器,可能无法处理这个新参数。

例如,在客户端应用程序成功身份验证后,该参数将始终存在于浏览器 URL 中。在这些情况下,禁用向身份验证响应添加 iss 参数可能很有用。这可以在 Keycloak 管理控制台中为特定客户端完成,在客户端详细信息中的 OpenID Connect 兼容模式部分中进行配置,详情请参见与旧适配器的兼容性。存在专用的 从身份验证响应中排除发行者 开关,可以将其打开以阻止向身份验证响应添加 iss 参数。

通配符处理

JPA 允许在搜索时使用通配符 %_,而其他提供程序(如 LDAP)仅允许使用 *。由于 * 是 LDAP 中自然的通配符,因此它在所有位置都有效,而在 JPA 中,它仅在搜索字符串的开头和结尾有效。从本版本开始,唯一的通配符是 *,它在所有提供程序的所有搜索字符串位置中都保持一致。特定提供程序中的所有特殊字符(如 JPA 的 %_)都将被转义。对于精确搜索,使用添加引号(如 "w*ord"),其行为与之前的版本保持一致。

主题的语言文件默认使用 UTF-8 编码

此版本现在遵循 Java 及更高版本的标准机制,该机制假定资源包文件以 UTF-8 编码。

以前版本的 Keycloak 支持在第一行使用注释(如 # encoding: UTF-8)指定编码,但现在不再支持,并且会被忽略。

主题的消息属性文件现在以 UTF-8 编码读取,并自动回退到 ISO-8859-1 编码。如果您使用不同的编码,请将文件转换为 UTF-8。

由 realm 和客户端角色映射器映射的声明的值格式的更改

在本版本之前,当 Multivalued 设置禁用时,realm(User Realm Role)和客户端(User Client Role)协议映射器都会映射字符串化的 JSON 数组。

然而,Multivalued 设置指示声明应映射为列表,或者如果禁用,则仅映射来自同一值列表的单个值。

在此版本中,当角色和客户端映射器标记为单值(Multivalued 禁用)时,它们现在映射到用户的有效角色中的单个值。

登录 UI 中密码字段的更改

在此版本中,我们希望引入一个切换开关来隐藏/显示密码输入。

受影响的页面
  • login.ftl

  • login-password.ftl

  • login-update-password.ftl

  • register.ftl

  • register-user-profile.ftl

通常,所有 <input type="password" name="password" /> 现在都封装在一个 div 中。输入元素后面跟着一个按钮,该按钮可以切换密码输入的可见性。

旧代码示例

<input type="password" id="password" name="password" autocomplete="current-password" style="display:none;"/>

新代码示例

<div class="${properties.kcInputGroup!}">
    <input type="password" id="password" name="password" autocomplete="current-password" style="display:none;"/>
    <button class="pf-c-button pf-m-control" type="button" aria-label="${msg('showPassword')}"
            aria-controls="password" data-password-toggle
            data-label-show="${msg('showPassword')}" data-label-hide="${msg('hidePassword')}">
        <i class="fa fa-eye" aria-hidden="true"></i>
    </button>
</div>

默认 Keycloak CR 主机名

当在 OpenShift 上运行时,启用 ingress,并将 spec.ingress.classname 设置为 openshift-default 时,您可以将 Keycloak CR 中的 spec.hostname.hostname 留空。operator 将为 CR 的存储版本分配一个默认主机名,类似于 OpenShift Route 在没有显式主机的情况下创建的主机名,即 ingress-namespace.appsDomain。如果 appsDomain 更改,或者您因任何原因需要不同的主机名,请更新 Keycloak CR。

已移除已弃用的 auto-build CLI 选项

auto-build CLI 选项已被标记为弃用很长时间。在此版本中,它已被完全移除,不再受支持。

执行 start 命令时,服务器会根据配置自动构建。为了阻止此行为,请设置 --optimized 标志。

kc.sh 和 shell 元字符

kc.sh 不再对参数和环境变量 JAVA_OPTS_APPEND 和 JAVA_ADD_OPENS 使用额外的 shell eval,因此继续使用双重转义/引用将导致参数被误解。例如,不要使用

bin/kc.sh start --db postgres --db-username keycloak --db-url "\"jdbc:postgresql://#:5432/keycloak?ssl=false&connectTimeout=30\"" --db-password keycloak --hostname localhost

使用单次转义

bin/kc.sh start --db postgres --db-username keycloak --db-url "jdbc:postgresql://#:5432/keycloak?ssl=false&connectTimeout=30" --db-password keycloak --hostname localhost

此更改还意味着您不能使用单引号值调用 kc.sh 的所有参数。例如,您不能再使用

bin/kc.sh "start --help"

而是必须使用单独的参数

bin/kc.sh start --help

同样,不要使用

bin/kc.sh build "--db postgres"

而是必须使用单独的参数

bin/kc.sh build --db postgres

Dockerfile run 命令中也需要使用单独的参数。

移除了 RegistrationProfile 表单操作

表单操作 RegistrationProfile(在身份验证流程的 UI 中显示为 Profile Validation)已从代码库和所有身份验证流程中移除。默认情况下,它位于每个 realm 的内置注册流程中。用户属性的验证以及包括所有用户属性的用户创建都由 RegistrationUserCreation 表单操作处理,因此不再需要 RegistrationProfile。通常,与此更改无关,无需采取进一步操作,除非您在自己的提供程序中使用了 RegistrationProfile 类。

数据提供程序和模型中已弃用的方法

  • RealmModel#getTopLevelGroupsStream() 和重载方法现在已弃用

GroupProvider 更改

添加了一个新方法,允许搜索和分页顶级组。如果您实现了此接口,则需要实现以下方法

Stream<GroupModel> getTopLevelGroupsStream(RealmModel realm,
                                           String search,
                                           Boolean exact,
                                           Integer firstResult,
                                           Integer maxResults)

GroupRepresentation 更改

  • 添加了新字段 subGroupCount,用于通知客户端任何给定组上有多少个子组

  • subGroups 列表现在仅在请求层次结构数据的查询中填充

  • 此字段从“自下而上”填充,因此不能依靠它来获取组的所有子组。使用 GroupProvider 或从 GET {keycloak server}/realms/{realm-name}/groups/{group_id}/children 请求子组

组管理 API 的新端点

添加了端点 GET {keycloak server}/realms/{realm-name}/groups/{group_id}/children,作为获取支持分页的特定组的子组的一种方式

RESTEasy Reactive

依赖 RESTEasy Classic 不再是一种选择,因为它不再可用。对于依赖 RESTEasy Classic 和 org.jboss.resteasy.spi.* 相关包的 SPI 和代码,将需要进行迁移。

部分导出需要 manage-realm 权限

端点 POST {keycloak server}/realms/{realm-name}/partial-export 和管理控制台中的相应操作现在需要 manage-realm 权限才能执行,而不是 view-realm 权限。此端点将 realm 配置导出到 JSON 文件中,新的权限更合适。参数 exportGroupsAndRolesexportClients 分别将 realm 组/角色和客户端包含在导出中,继续管理相同的权限(query-groupsview-clients)。

移除用于修剪事件详细信息长度的选项

自此版本起,Keycloak 支持 EventEntity details 列的长值。因此,它不再支持修剪事件详细信息长度的选项 --spi-events-store-jpa-max-detail-length--spi-events-store-jpa-max-field-length

用户配置文件更新

此版本包括许多与用户配置文件相关的修复和更新,因为我们正在努力将此功能从预览版推广到正式支持版。SPI 存在细微更改,例如在 UserProfileProvider 接口上新添加的方法 boolean isEnabled(RealmModel realm)。此外,一些用户配置文件类和一些验证器相关类(但不是内置验证器实现)已从 keycloak-server-spi-private 模块移动到 keycloak-server-spi 模块。但是,java 类的包保持不变。在某些极端情况下,您可能会受到影响,例如当您使用自己的 UserProfileProvider 实现覆盖内置实现时。但是,请注意 UserProfileProvider 是不受支持的 SPI。

移除 Map Store

Map Store 在以前的版本中一直是一个实验性功能。从本版本开始,它已被移除,用户应继续使用当前的 JPA 存储。

自此版本起,不再可能使用 --storage 相关 CLI 选项。模块 keycloak-model-map* 已被移除。

从我们的翻译中移除了命名空间

所有翻译都已移动到一个文件中,用于管理控制台。如果您制作了自己的翻译或扩展了管理控制台,则需要将它们迁移到这种新格式。此外,如果您的数据库中有“覆盖”,则必须从键中删除命名空间。某些键仅在不同的命名空间中相同,这在帮助文档中最为明显。在这些情况下,我们在键后添加了后缀 Help

如果您愿意,可以使用此 node 脚本来帮助迁移。它将获取所有单个文件并将它们放入一个新文件中,并处理一些映射

import { readFileSync, writeFileSync, appendFileSync } from "node:fs";

const ns = [
  "common",
  "common-help",
  "dashboard",
  "clients",
  "clients-help",
  "client-scopes",
  "client-scopes-help",
  "groups",
  "realm",
  "roles",
  "users",
  "users-help",
  "sessions",
  "events",
  "realm-settings",
  "realm-settings-help",
  "authentication",
  "authentication-help",
  "user-federation",
  "user-federation-help",
  "identity-providers",
  "identity-providers-help",
  "dynamic",
];

const map = new Map();
const dup = [];

ns.forEach((n) => {
  const rawData = readFileSync(n + ".json");
  const translation = JSON.parse(rawData);
  Object.entries(translation).map((e) => {
    const name = e[0];
    const value = e[1];
    if (map.has(name) && map.get(name) !== value) {
      if (n.includes("help")) {
        map.set(name + "Help", value);
      } else {
        map.set(name, value);
        dup.push({
          name: name,
          value: map.get(name),
          dup: { ns: n, value: value },
        });
      }
    } else {
      map.set(name, value);
    }
  });
});

writeFileSync(
  "translation.json",
  JSON.stringify(Object.fromEntries(map.entries()), undefined, 2),
);

const mapping = [
  ["common:clientScope", "clientScopeType"],
  ["identity-providers:createSuccess", "createIdentityProviderSuccess"],
  ["identity-providers:createError", "createIdentityProviderError"],
  ["clients:createError", "createClientError"],
  ["clients:createSuccess", "createClientSuccess"],
  ["user-federation:createSuccess", "createUserProviderSuccess"],
  ["user-federation:createError", "createUserProviderError"],
  ["authentication-help:name", "flowNameHelp"],
  ["authentication-help:description", "flowDescriptionHelp"],
  ["clientScopes:noRoles", "noRoles-clientScope"],
  ["clientScopes:noRolesInstructions", "noRolesInstructions-clientScope"],
  ["users:noRoles", "noRoles-user"],
  ["users:noRolesInstructions", "noRolesInstructions-user"],
  ["clients:noRoles", "noRoles-client"],
  ["clients:noRolesInstructions", "noRolesInstructions-client"],
  ["groups:noRoles", "noRoles-group"],
  ["groups:noRolesInstructions", "noRolesInstructions-group"],
  ["roles:noRoles", "noRoles-roles"],
  ["roles:noRolesInstructions", "noRolesInstructions-roles"],
  ["realm:realmName:", "realmNameField"],
  ["client-scopes:searchFor", "searchForClientScope"],
  ["roles:searchFor", "searchForRoles"],
  ["authentication:title", "titleAuthentication"],
  ["events:title", "titleEvents"],
  ["roles:title", "titleRoles"],
  ["users:title", "titleUsers"],
  ["sessions:title", "titleSessions"],
  ["client-scopes:deleteConfirm", "deleteConfirmClientScopes"],
  ["users:deleteConfirm", "deleteConfirmUsers"],
  ["groups:deleteConfirm_one", "deleteConfirmGroup_one"],
  ["groups:deleteConfirm_other", "deleteConfirmGroup_other"],
  ["identity-providers:deleteConfirm", "deleteConfirmIdentityProvider"],
  ["realm-settings:deleteConfirm", "deleteConfirmRealmSetting"],
  ["roles:whoWillAppearLinkText", "whoWillAppearLinkTextRoles"],
  ["users:whoWillAppearLinkText", "whoWillAppearLinkTextUsers"],
  ["roles:whoWillAppearPopoverText", "whoWillAppearPopoverTextRoles"],
  ["users:whoWillAppearPopoverText", "whoWillAppearPopoverTextUsers"],
  ["client-scopes:deletedSuccess", "deletedSuccessClientScope"],
  ["identity-providers:deletedSuccess", "deletedSuccessIdentityProvider"],
  ["realm-settings:deleteSuccess", "deletedSuccessRealmSetting"],
  ["client-scopes:deleteError", "deletedErrorClientScope"],
  ["identity-providers:deleteError", "deletedErrorIdentityProvider"],
  ["realm-settings:deleteError", "deletedErrorRealmSetting"],
  ["realm-settings:saveSuccess", "realmSaveSuccess"],
  ["user-federation:saveSuccess", "userProviderSaveSuccess"],
  ["realm-settings:saveError", "realmSaveError"],
  ["user-federation:saveError", "userProviderSaveError"],
  ["realm-settings:validateName", "validateAttributeName"],
  ["identity-providers:disableConfirm", "disableConfirmIdentityProvider"],
  ["realm-settings:disableConfirm", "disableConfirmRealm"],
  ["client-scopes:updateSuccess", "updateSuccessClientScope"],
  ["client-scopes:updateError", "updateErrorClientScope"],
  ["identity-providers:updateSuccess", "updateSuccessIdentityProvider"],
  ["identity-providers:updateError", "updateErrorIdentityProvider"],
  ["user-federation:orderChangeSuccess", "orderChangeSuccessUserFed"],
  ["user-federation:orderChangeError", "orderChangeErrorUserFed"],
  ["authentication-help:alias", "authenticationAliasHelp"],
  ["authentication-help:flowType", "authenticationFlowTypeHelp"],
  ["authentication:createFlow", "authenticationCreateFlowHelp"],
  ["client-scopes-help:rolesScope", "clientScopesRolesScope"],
  ["client-scopes-help:name", "scopeNameHelp"],
  ["client-scopes-help:description", "scopeDescriptionHelp"],
  ["client-scopes-help:type", "scopeTypeHelp"],
  ["clients-help:description", "clientDescriptionHelp"],
  ["clients-help:clientType", "clientsClientTypeHelp"],
  ["clients-help:scopes", "clientsClientScopesHelp"],
  ["common:clientScope", "clientScopeTypes"],
  ["dashboard:realmName", "realmNameTitle"],
  ["common:description", "description"],
];

mapping.forEach((m) => {
  const key = m[0].split(":");
  try {
    const data = readFileSync(key[0] + ".json");
    const translation = JSON.parse(data);
    const value = translation[key[1]];
    if (value) {
      appendFileSync(
        "translation.json",
        '"' + m[1] + '": ' + JSON.stringify(value) + ',\n',
      );
    }
  } catch (error) {
    console.error("skipping namespace key: " + key);
  }
});

将其保存到 public/locale/<language> 文件夹中名为 transform.mjs 的文件中,并使用以下命令运行它

node ./transform.mjs
这可能无法完成完整的转换,但非常接近。

迁移到 22.0.4

用于指定电子邮件本地部分最大长度的新参数

添加了一个新参数 --spi-user-profile-declarative-user-profile-max-email-local-part-length,用于设置电子邮件本地部分的最大长度,同时考虑向后兼容性。默认值为 64。用法示例

kc.[sh|bat] start --spi-user-profile-declarative-user-profile-max-email-local-part-length=100 ...

迁移到 22.0.2

从客户端高级设置组合框中移除了“永不过期”选项

现在已从客户端选项卡“高级设置”的所有组合框中移除了 永不过期 选项。此选项具有误导性,因为不同的生存时间或空闲超时时间永远不是无限的,而是受常规用户会话或 realm 值的限制。因此,移除了此选项,转而使用其他两个剩余选项:从 realm 设置继承(客户端使用常规 realm 超时时间)和 在以下时间过期(为客户端覆盖该值)。在内部,永不过期-1 表示。现在,该值在管理控制台中显示警告,管理员无法直接设置。

新的 LinkedIn OpenID Connect 社交提供程序

为专注于商业和就业的平台引入了一个新的社交身份提供程序,名为 LinkedIn OpenID Connect。LinkedIn 最近发布了一个面向开发人员的新产品,名为 使用 OpenID Connect 登录 LinkedIn。该产品提供了一种使用 OpenID Connect 对成员进行身份验证的新方法,但默认的 OpenID Connect v1.0 身份提供程序目前无法与其配合使用。因此,Keycloak 添加了这个新的身份提供程序,作为新产品的特定社交提供程序。

基于 OAuth 的旧 LinkedIn 方式似乎已从 开发者门户 中完全移除。现有的 LinkedIn 社交提供程序如何与当前应用程序协同工作尚不清楚。Keycloak 保留了旧的提供程序,并将其重命名为 LinkedIn (已弃用),但在默认禁用的 linkedin-oauth 弃用功能中。它将在未来的版本中移除。如果需要,请在启动时再次启用它

kc.[sh|bat] start --features linkedin-oauth ...

迁移到 22.0.0

从 Java EE 过渡到 Jakarta EE

Keycloak 将其代码库从 Java EE(企业版)迁移到其后继者 Jakarta EE,这为 Keycloak 带来了各种变化。

我们已升级所有 Jakarta EE 规范以支持 Jakarta EE 10,例如

  • Jakarta Persistence 3.1

  • Jakarta RESTful Web Services 3.1

  • Jakarta Mail API 2.1

  • Jakarta Servlet 6.0

  • Jakarta Activation 2.1

Jakarta EE 10 提供了一种现代化、简化、轻量级的方法来构建云原生 Java 应用程序。此举措提供的主要更改是将命名空间从 javax.* 更改为 jakarta.*。这不适用于 JDK 中直接提供的 javax.* 包,例如 javax.securityjavax.netjavax.crypto 等。

您的自定义扩展、提供程序或 JPA 实体可能会受到这些更改的影响。

升级到 Quarkus 3

Keycloak 已升级到 Quarkus Java 框架的第 3 版。Quarkus 3 延续了通过快速发展和使用最新技术提供尖端用户体验来推动 Java 开发的传统。它继续提高整体性能和效率。

Quarkus 3 基于 Jakarta EE 10,与 Keycloak 相同,在它们之间创建了平滑的互操作性。此外,它还包含与 Jakarta EE 10 Core Profile 对齐的 Eclipse MicroProfile 6。Quarkus 3 升级的核心部分是内置支持 JPA 3.1 和 Hibernate ORM 6。

quarkus.hibernate-orm.* 属性不再起作用

对于 Quarkus 3,Hibernate ORM 配置必须在 persistence.xml 文件或 Quarkus 属性中指定,但不能同时在两个位置指定。Keycloak 使用 persistence.xml 文件,因此,不再可能通过 Quarkus 的配置属性(对于名称以 quarkus.hibernate-orm 开头的默认持久化单元)来覆盖 Keycloak 的 JPA 存储配置。

升级到 Hibernate ORM 6

Keycloak 现在受益于升级到 Hibernate ORM 6.2,其中包括改进的性能、更好的 SQL、现代 JDK 支持以及对现代 RDBMS 功能的支持。性能改进主要影响 JDBC、HQL 转换和 Criteria 转换。

如果您有自定义提供程序或 JPA 实体,这些更改可能会影响您。

我们建议查看 Quarkus 迁移指南Hibernate 发行说明 以获取更多信息。

从 Keycloak JS 适配器中移除了旧版 Promise API

旧版 Promise API 方法已从 Keycloak JS 适配器中移除。这意味着不再可能在适配器返回的 Promise 上调用 .success().error()。而应使用标准化的 Promise 方法,例如 .then().catch()

迁移前
const keycloak = new Keycloak();

keycloak.init()
  .success(function(authenticated) {
    alert(authenticated ? 'authenticated' : 'not authenticated');
  }).error(function() {
    alert('failed to initialize');
  });
迁移后
const keycloak = new Keycloak();

keycloak.init()
  .then(function(authenticated) {
    alert(authenticated ? 'authenticated' : 'not authenticated');
  }).catch(function() {
    alert('failed to initialize');
  });
或者,当使用 await 关键字来解包这些 Promise 时
const keycloak = new Keycloak();

try {
  const authenticated = await keycloak.init();
  alert(authenticated ? 'authenticated' : 'not authenticated');
} catch (error) {
  alert('failed to initialize');
}

导出和导入执行自动构建

在以前的版本中,exportimport 命令需要首先运行 build 命令。从本版本开始,如果构建时配置已更改,则 exportimport 命令将执行 Keycloak 的自动重建。

当迁移首先运行 build 命令的现有脚本时,通过向 exportimport 命令添加 --optimized 命令行选项进行迁移,以避免 Keycloak 自动重建映像。在此操作中不添加 --optimized 选项可能会导致 Keycloak 触发重建并恢复为默认值,然后连接到数据库进行导出和导入将不起作用。

以下示例假定运行时参数(如数据库密码)通过配置文件或环境变量提供。

迁移前:在运行导出命令之前运行构建命令
bin/kc.[sh|bat] build --db=postgres ...
bin/kc.[sh|bat] export --dir <dir>
迁移后:向导出命令添加 --optimized
bin/kc.[sh|bat] build --db=postgres ...
bin/kc.[sh|bat] export --optimized --dir <dir>
迁移后:利用自动构建功能
bin/kc.[sh|bat] export --dir <dir> --db=postgres ...
注意

当自动构建运行时,构建时选项将对所有后续使用 --optimized 标志启动的命令生效,包括 start 命令。

在以前的版本中,exportimport 命令仅允许在配置文件或环境变量中使用运行时参数,例如数据库 URL。从本版本开始,这些运行时参数现在也可以在命令行中使用。使用 --help 选项查找有关支持的参数的信息。

重命名了 Keycloak Admin 客户端工件

在升级到 Jakarta EE 后,Keycloak Admin 客户端的工件已重命名为更具描述性的名称,并考虑了长期可维护性。我们仍然提供两个单独的 Keycloak Admin 客户端,一个支持 Jakarta EE,另一个支持 Java EE。

我们停止发布 org.keycloak:keycloak-admin-client-jakarta 工件。用于 Keycloak Admin 客户端的默认工件(支持 Jakarta EE)是 org.keycloak:keycloak-admin-client(自 22.0.0 版本起)。

新的支持 Java EE 的工件是 org.keycloak:keycloak-admin-client-jee

Jakarta EE 支持
迁移前
<dependency>
    <groupId>org.keycloak</groupId>
    <artifactId>keycloak-admin-client-jakarta</artifactId>
    <version>21.0.0</version>
</dependency>
迁移后
<dependency>
    <groupId>org.keycloak</groupId>
    <artifactId>keycloak-admin-client</artifactId>
    <version>22.0.0</version>
</dependency>
Java EE 支持
迁移前
<dependency>
    <groupId>org.keycloak</groupId>
    <artifactId>keycloak-admin-client</artifactId>
    <version>21.0.0</version>
</dependency>
迁移后
<dependency>
    <groupId>org.keycloak</groupId>
    <artifactId>keycloak-admin-client-jee</artifactId>
    <version>22.0.0</version>
</dependency>

直通代理模式更改

Keycloak 的代理配置设置对于 直通 模式不再解析请求中的 HTTP 转发标头,因为当代理以直通模式转发 HTTPS 连接时,代理无法添加、删除或更新 HTTP 标头。

希望解析客户端请求中的 HTTP 标头的安装应使用 边缘重新加密 设置。

有关详细信息,请参见 使用反向代理

所有主题的统一回退消息解析

当您使用 realm 本地化消息时,此更改可能只会影响您。

在此版本之前,当使用 realm 本地化消息时,跨主题的回退消息解析是不一致的。更多信息可以在以下 issue 中找到。

现在,所有主题的实现都已统一。通常,最具体的匹配语言标签的消息具有最高优先级。如果同时存在 realm 本地化消息和主题 i18n 消息,则 realm 本地化消息具有更高的优先级。总结来说,消息的优先级如下(RL = realm 本地化,T = 主题 i18n 文件):RL <变体> > T <变体> > RL <区域> > T <区域> > RL <语言> > T <语言> > RL en > T en

可能可以通过一个示例更好地解释这一点:当请求变体 de-CH-1996 并且存在该变体的 realm 本地化消息时,将使用此消息。如果不存在此类 realm 本地化消息,则会在主题 i18n 文件中搜索该变体的相应消息。如果不存在此类消息,则会搜索区域(de-CH)的 realm 本地化消息。如果不存在此类 realm 本地化消息,则会在主题 i18n 文件中搜索该区域的消息。如果仍然找不到消息,则会搜索语言(de)的 realm 本地化消息。如果没有匹配的 realm 本地化消息,则会在主题 i18n 文件中搜索该语言的消息。作为最后的后备方案,将使用英语 (en) 翻译:首先,将搜索英语 realm 本地化 - 如果未找到,则会在主题 i18n 文件中搜索英语消息。

UserQueryProvider 更改

UserQueryProvider 接口已拆分为两个。一个是 UserQueryMethodsProvider,提供查询用户的功能。第二个是 UserCountMethodsProvider,提供计算特定存储中用户数量的功能。

Keycloak 现在能够区分可以高效执行计数查询的用户存储提供程序和不能高效执行计数查询的用户存储提供程序。UserQueryProvider 接口仍然存在,并扩展了这两个新接口。因此,UserQueryProvider 的现有实现无需进行任何修改,因为它保留了相同的方法。

LDAPStorageProvider 搜索更改

从本版本开始,Keycloak 在查询联合 LDAP 数据库时使用分页机制。搜索用户应与本地数据库中的搜索保持一致。

自此版本起,LDAPStorageProvider 仅实现 UserQueryMethodsProvider,而不实现 UserQueryProvider

弃用 Keycloak OpenID Connect 适配器

从本版本开始,我们将不再投入时间在以下 Keycloak OpenID Connect 适配器上

  • Keycloak Wildfly OpenID Connect 适配器

  • Keycloak JEE Servlet OpenID Connect 适配器

  • Keycloak Spring Boot 和 Spring Security OpenID Connect 适配器

此举措已反映在我们的文档和快速入门存储库中。请考虑查看以下参考资料以获取更多信息

我们建议开始考虑将您的应用程序迁移到上述参考资料中的替代方案。这些适配器在未来的版本中应不再可用。

弃用 Keycloak JEE SAML 适配器

Keycloak JEE SAML 适配器已停止开发,在本版本发布后,我们将不再投入时间进行开发。

官方适配器现在基于 Jakarta,当您将应用程序切换到此技术后,应立即使用该适配器。

此更改已在我们的文档和快速入门存储库中。有关更多信息,请考虑查看以下参考资料

如果您无法将应用程序迁移到 Jakarta,您仍然可以使用“旧版”SAML JEE 适配器,并且仍然能够与服务器的未来版本集成。但是,请考虑尽快升级您的应用程序,因为我们不再为 JEE 提供支持。

openshift-integration 功能的更改

预览功能 openshift-integration 已从 Keycloak 代码库中移除,并移动到单独的扩展中。这包括移动相关提供程序,例如自定义客户端存储提供程序和用于 Openshift 集成的令牌审查端点。

如果您使用了此功能,则在启动 Keycloak 服务器时,您不应再使用 openshift-integration 功能,而是需要从自定义扩展部署 JAR 文件。您可以查看 Openshift 扩展 及其 README 文件中的说明,了解如何将扩展部署到您的 Keycloak 服务器。

Openshift 扩展不是由 Keycloak 团队正式支持和维护的。您只能自行承担风险使用它。
移除了 Http Challenge 流程

内置身份验证流程 http challenge 以及身份验证器实现 no-cookie-redirectbasic-authbasic-auth-otp 已被移除。http challenge 身份验证流程也旨在用于 Openshift 集成,因此它已与其他相关功能一起移除,如上所述。身份验证器实现已移动到上一段中描述的 Openshift 扩展。

如果您将 http challenge 流程用作 realm 流程,或者用作任何身份提供程序的 First Broker LoginPost Broker Login 流程,则无法进行迁移。请务必更新您的 realm 配置以消除对 http challenge 流程的使用,然后再进行迁移。如果您将 http challenge 流程用作任何客户端的 Authentication Flow Binding Override,则迁移将完成,但您将无法再登录到该客户端。迁移后,您需要重新创建流程并更新客户端的配置以使用新的/不同的 Json 流程。

移除第三方依赖项

移除 openshift-integration 使我们能够从 Keycloak 发行版中移除一些第三方依赖项。这包括 openshift-rest-clientokio-jvmokhttpcommons-langcommons-compressjboss-dmrkotlin-stdlib。这意味着,如果您将这些库中的任何一个用作部署到 Keycloak 服务器的您自己的提供程序的依赖项,您可能还需要将这些 jar 文件显式复制到 Keycloak 发行版的 providers 目录中。

上下文和依赖注入不再对 JAX-RS 资源启用

为了提供更好的运行时性能并尽可能利用底层堆栈,所有使用 javax.ws.rs.core.Context 注解进行上下文数据注入的点都被移除。预期的性能提升包括在请求生命周期中不再多次创建代理实例,并大幅减少运行时的反射代码量。

如果您正在扩展以下 SPI 之一

  • PolicySpi

  • AdminRealmResourceSpi

  • IdentityProviderSpi

  • RealmResourceSPI

您应该检查您的自定义 JAX-RS(子)资源,以便按照以下方式获取任何上下文数据

KeycloakSession session = org.keycloak.common.util.Resteasy.getContextData(KeycloakSession.class);

如果您需要访问当前的请求和响应对象,您现在可以直接从 KeycloakSession 中获取它们的实例

@Context
org.jboss.resteasy.spi.HttpRequest request;
@Context
org.jboss.resteasy.spi.HttpResponse response;

已被替换为

KeycloakSession session = // obtain the session, which is usually available when creating a custom provider from a factory
KeycloakContext context = session.getContext();

HttpRequest request = context.getHttpRequest();
HttpResponse response = context.getHttpResponse();

如果您在调用 JAX-RS 资源方法时无法访问 KeycloakSession 实例,您可以从 JAX-RS 运行时获取上下文数据,如下所示

KeycloakSession session = org.keycloak.common.util.Resteasy.getContextData(KeycloakSession.class);

可以通过 KeycloakContext 实例从运行时获取其他上下文数据

KeycloakSession session = // obtain the session
KeycloakContext context = session.getContext();
MyContextualObject myContextualObject = context.getContextObject(MyContextualObject.class);

升级您的自定义 JAX-RS 资源

如果您正在通过以下 SPI 扩展服务器的 REST API

  • PolicySpi

  • AdminRealmResourceSpi

  • IdentityProviderSpi

  • RealmResourceSPI

您需要在打包自定义提供程序的 JAR 文件中添加一个空的 META-INF/beans.xml 文件。否则,它们在运行时不会被服务器识别。

如果您正在使用 RealmResourceSPIAdminRealmResourceSpi,您可以选择在 META-INF 下添加一个名为 beans.xml 的空文件,或者使用 jakarta.ws.rs.ext.Provider 注解来注解 JAX-RS 资源类。

您还应该确保您的 JAX-RS 方法通过使用 @Consumes@Produces 注解分别标记它们来声明预期的输入和输出媒体类型。

数据提供程序和模型中已弃用的方法

在早期版本的 Keycloak 中,提供程序和模型接口经历了一个清理过程,其中涉及弃用某些方法。在此版本中,这些方法已被移除,并且一些其他方法已被弃用。Keycloak 21 中这些方法的 Javadoc 包含了关于其对应替换的信息。

  • RealmModel#searchForGroupByNameStream(String, Integer, Integer) 已被移除。

  • UserProvider#getUsersStream(RealmModel, boolean) 已被移除。

  • UserSessionPersisterProvider#loadUserSessions(int, int, boolean, int, String) 已被移除。

  • 为流式处理工作添加的接口已被移除。例如 RoleMapperModel.Streams 和类似的接口。

  • 联合存储提供程序类中的 Streams 接口已被弃用。

  • KeycloakModelUtils#getClientScopeMappings 已被移除。

  • KeycloakSession 中已弃用的方法已被移除。

  • UserQueryProvider#getUsersStream 方法已被移除。

多个 Keycloak 实例

可以在同一命名空间中创建多个 Keycloak CR,并且它们将由 operator 独立管理。为了实现这一点,必须重新创建旧版本 operator 创建的 StatefulSets。当 operator 升级时,这将自动发生,并导致少量停机时间。

k8s.keycloak.org/v2alpha1 变更

条件状态字段从布尔值更改为字符串,以符合标准的 Kubernetes 条件。在 CRD 中,它将暂时表示为接受任何内容,但它将始终是一个字符串。请确保您对该字段的任何使用都已更新为期望值 "True"、"False" 或 "Unknown",而不是 true 或 false。

Keycloak 支持 IPv4/IPv6 双栈

Keycloak 支持 IPv4/IPv6 双栈,并且默认可以通过 IPv4 和 IPv6 地址访问。在旧版本的 Keycloak 中,默认方法是仅使用 IPv4 地址。

有关更多详细信息,请参阅 使用 IPv4 或 IPv6 配置 Keycloak 服务器

迁移到 21.1.0

默认情况下,Classpath 上提供了 Javascript 引擎

在之前的版本中,当 Keycloak 在 Java 17 上与 Javascript 提供程序(脚本身份验证器、Javascript 授权策略或用于 OIDC 和 SAML 客户端的脚本协议映射器)一起使用时,需要将 javascript 引擎复制到发行版中。现在不再需要这样做,因为 Nashorn javascript 引擎默认在 Keycloak 服务器中可用。当您部署脚本提供程序时,建议不要将 nashorn 脚本引擎及其依赖项复制到 Keycloak 发行版中。

服务帐户客户端的默认客户端 ID 映射器更改

服务帐户客户端的默认 客户端 ID 映射器已更改。Token Claim Name 字段值已从 clientId 更改为 client_idclient_id claim 符合 OAuth2 规范

clientId userSession 注释仍然存在。

Keycloak JS 适配器必须使用 new 运算符实例化

从历史上看,可以通过直接调用 Keycloak() 函数来创建 Keycloak JS 适配器的实例

const keycloak = Keycloak();

为了使其与 JavaScript 世界的现代约定保持一致,可以使用 new 运算符 来创建实例

const keycloak = new Keycloak();

函数式构造函数已被弃用一段时间,但从这个版本开始,当使用它时,我们将主动记录弃用消息。这种构造函数风格将在未来的版本中移除,因此请确保迁移您的代码以使用 new 运算符。

迁移到 21.0.2

条款和条件用户属性迁移

terms_and_conditions 用户属性在 21.0.0 版本中意外更改为大写。此版本将用户属性恢复为小写。该属性的值在接受条款和条件页面时设置。

如果您的任何自定义扩展依赖于此属性,您可能需要调整您的代码以同时检查 terms_and_conditionsTERMS_AND_CONDITIONS 属性。

迁移到 21.0.0

Keycloak 使用 Micrometer 进行指标监控

Keycloak 提供了一个可选的指标端点,该端点以 Prometheus 格式导出指标。在此版本中,提供此数据的实现从 SmallRye 切换到 Micrometer,Micrometer 是 Quarkus 推荐的指标库

由于此更改,指标已被重命名。下表显示了一些示例。

建议在升级之前和之后查看端点返回的所有指标,并更新仪表板和警报中的用法。

表 1. 更改的指标名称示例
旧指标名称 新指标名称

base_gc_total

jvm_gc_pause_seconds_count

base_gc_time_total_seconds

jvm_gc_pause_seconds_sum

base_thread_count

jvm_threads_live_threads

vendor_agroal_*

agroal_*

SAML 已弃用的 RSA_SHA1 和 DSA_SHA1 算法

算法 RSA_SHA1DSA_SHA1 在 SAML 适配器、客户端和身份提供程序上可以配置为 签名算法,已被弃用。我们建议使用基于 SHA256SHA512 的更安全的替代方案。此外,在 Java 17 或更高版本上,使用这些算法验证已签名的 SAML 文档或断言的签名不起作用。如果您使用此算法,并且使用您的 SAML 文档的另一方在 Java 17 或更高版本上运行,则签名验证将不起作用。

可能的解决方法是从文件 $JAVA_HOME/conf/security/java.security 中配置的属性 jdk.xml.dsig.secureValidationPolicy 的“不允许的算法”列表中删除诸如 http://www.w3.org/2000/09/xmldsig#rsa-sha1http://www.w3.org/2000/09/xmldsig#dsa-sha1 之类的算法。

SAML SP 元数据更改

在此版本中,Keycloak 将拒绝解密使用为签名目的生成的 realm 密钥加密的断言。此更改意味着从 IDP 到 SP(Keycloak 充当 SP)的所有加密通信将停止工作。

有两种方法可以使其工作

  • 或者使用较新版本的 Keycloak 生成的元数据更新 IDP 配置,

  • 或者在向后兼容模式下运行 Keycloak,这将使 Keycloak 可以使用旧版本 Keycloak 生成的元数据。可以使用 -Dkeycloak.saml.deprecated.encryption=true 标志启用此模式。请注意,此向后兼容模式计划在 Keycloak 24 中移除。

用户会话提供程序中已弃用的方法已被移除

在 Keycloak 13 中,引入了 UserLoginFailureProvider,并且 UserSessionProvider 中的某些方法已移至此处。UserSessionProvider 中的方法已被弃用,现在已被移除。这些方法的 Javadoc 包含了相应的替换(请参阅 Keycloak 20 版本的 Javadoc)。

使用旧管理控制台的自定义主题将无法工作

旧的管理控制台已在之前的版本中弃用,最终被移除。这也意味着您的自定义主题,如果使用它作为父主题或从中导入,将无法工作。强烈建议不要部署此类主题,因为扩展旧的管理控制台已不再适用,并且部署此类主题可能会在 Keycloak 中出现问题(至少在日志中会出现警告或错误)。

Curl 已从容器中移除

Keycloak 容器镜像 已被修改以增强安全性。因此,curl 和其他 CLI 工具已被移除,您可能已在自定义镜像中使用过它们。请参阅更新后的 容器指南,了解如何处理此更改的信息。

迁移到 20.0.0

RESTEasy 版本更新

将 Keycloak Admin REST 客户端的 RESTEasy 版本更新到下一个主要版本。

H2 版本更新

Keycloak 出于开发目的附带了 H2 数据库驱动程序。因为它仅用于开发目的,所以绝不应在生产环境中使用。

在此版本中,H2 驱动程序已从 1.x 版本升级到 2.x 版本。此更改可能需要更改 H2 JDBC URL 或迁移现有 Keycloak 设置中的 H2 数据库文件。

H2 JDBC URL 的更改

为了使 Keycloak 能够在 H2 2.x 版本上使用其 JPA 旧版存储运行,JDBC URL 需要属性 NON_KEYWORDS=VALUE

在 Keycloak 初始化 H2 而不使用额外参数的设置中,Keycloak 将自动附加该属性。这是开发设置的默认设置。

如果在命令行或配置文件中提供了 H2 JDBC URL,并且它已经在 JDBC URL 中包含 NON_KEYWORDS= 属性,则需要使用 VALUE 关键字修改此属性。

如果 H2 数据库的连接工厂在 Keycloak 外部初始化,则该初始化需要注意添加 NON_KEYWORDS 属性。

有关详细信息,请参阅 H2 文档 关于 NON_KEYWORDS 属性

H2 数据库文件的升级

使用 H2 1.x 版本创建的 H2 数据库基本文件不应与 2.x 版本一起使用。

清除现有的 H2 数据库文件以使用空数据库启动,使用 Keycloak 的导出和导入功能导出和导入 realm,或参考 H2 数据库项目网站上的迁移说明,了解有关如何迁移 H2 数据库内容的详细信息。

新版本 Keycloak Operator 中的重大更改

为了使用最新版本的 Keycloak Operator,需要手动重新安装和升级您的 CR。没有自动迁移。

此版本包含 Keycloak CR 中的以下重大更改

serverConfiguration 自由格式字段已重命名

从现在开始,它被称为 additionalOptions。此决策背后的想法是使其更符合 Keycloak Quarkus 发行版,并实现/保持命名一致性。serverConfiguration 仍然可以用于配置在 Keycloak 自定义资源 (CR) 中没有声明替代方案的选项。服务提供程序可以是这种用法的很好示例。

Ingress 选项已改进

过去,它曾经通过 disableDefaultIngress 属性定义。我们决定稍微澄清一下,因此从现在开始,您可以使用以下结构来控制您的 ingress 设置

spec:
    ...
    ingress:
      enabled: false
HTTP 选项已添加

与 ingress 类似,您可以通过更好的结构化方式定义多个 HTTP 选项

spec:
    ...
  http:
    httpEnabled: true
    httpPort: 80
    httpsPort: 443
    tlsSecret: my-tls-secret
Hostname 选项已添加

最后但并非最不重要的一点,hostname 选项也已更改

spec:
    ...
  hostname:
    hostname: [keycloak-server-hostname]
    admin: [admin-console-hostname]
    adminUrl: [admin-console-base-url]
    strict: [true|false]
    strictBackchannel: [true|false]
某些字段不再是必需的

hostnametlsSecret 字段现在是可选的,以与 Quarkus 发行版配置保持一致。这样,我们也取消了将 INSECURE-DISABLE 特殊值设置为这些字段的可能性。为了禁用 hostname 检查并启用 HTTP,请遵循与 Quarkus 发行版相同的方法,即设置 strict: falsestrictBackchannel: falsehttpEnabled: true 字段。

OLM 通道已更改为 fast

Keycloak Operator Lifecycle Manager 的默认通道已更改为 fast

数据提供程序和模型中已弃用的方法已被移除

在 Keycloak 15 之前,我们清理了提供程序和模型接口,其中我们弃用了一些方法。这些方法的 Javadoc 包含相应的替换方法(请参阅 Keycloak 19 版本的 Javadoc)。在此版本中,这些方法已被移除。以下是所有已更改类的列表。

弃用和移除方法的最常见模式如下。

  • 流式处理 - 接口现在仅包含基于 Stream 的方法。

    例如,在 GroupProvider 接口中

    @Deprecated
    List<GroupModel> getGroups(RealmModel realm);

    已被替换为

    Stream<GroupModel> getGroupsStream(RealmModel realm);

    有关流式处理工作的更多详细信息,请参见 KEYCLOAK-14011

  • 一致的参数顺序 - 方法现在具有严格的参数顺序,其中 RealmModel 始终是第一个参数。

    例如,在 UserLookupProvider 接口中

    @Deprecated
    UserModel getUserById(String id, RealmModel realm);

    已被替换为

    UserModel getUserById(RealmModel realm, String id)
已更改接口列表

o.k. 代表 org.keycloak. 包)

  • server-spi 模块

    • o.k.credential.CredentialInputUpdater

    • o.k.credential.UserCredentialStore

    • o.k.models.ClientProvider

    • o.k.models.ClientSessionContext

    • o.k.models.GroupModel

    • o.k.models.GroupProvider

    • o.k.models.KeyManager

    • o.k.models.KeycloakSessionFactory

    • o.k.models.ProtocolMapperContainerModel

    • o.k.models.RealmModel

    • o.k.models.RealmProvider

    • o.k.models.RoleContainerModel

    • o.k.models.RoleMapperModel

    • o.k.models.RoleModel

    • o.k.models.RoleProvider

    • o.k.models.ScopeContainerModel

    • o.k.models.UserCredentialManager

    • o.k.models.UserModel

    • o.k.models.UserProvider

    • o.k.models.UserSessionProvider

    • o.k.models.utils.RoleUtils

    • o.k.sessions.AuthenticationSessionProvider

    • o.k.storage.client.ClientLookupProvider

    • o.k.storage.group.GroupLookupProvider

    • o.k.storage.user.UserLookupProvider

    • o.k.storage.user.UserQueryProvider

  • server-spi-private 模块

    • o.k.events.EventQuery

    • o.k.events.admin.AdminEventQuery

    • o.k.keys.KeyProvider

所有更改都链接到以下 issue

迁移到 19.0.2

OpenID Connect 注销提示

在 Keycloak 18.0.0 中,注销现在与新的 OIDC 规范兼容,该规范更改了 url 参数的处理方式。但是,为了也与早期版本保持兼容,引入了一个兼容性标志。有关向后兼容性选项的更多信息,请参阅 升级指南,该选项允许您的应用程序仍然使用旧格式的 url 参数。

虽然现在可以将 url 参数配置为兼容,但与 Keycloak 17 及更早版本仍然存在一个不兼容之处。如果用户未提供有效的 idTokenHint,则会显示注销提示而不是成功的注销重定向。因此,引入了一个新的兼容性标志 suppress-logout-confirmation-screen 以抑制注销屏幕。

您可以在启动服务器时通过输入以下命令来启用此参数

bin/kc.[sh|bat] --spi-login-protocol-openid-connect-suppress-logout-confirmation-screen=true start

通过此配置,您仍然可以使用注销端点,而无需用户提示。

向后兼容性开关将在未来的某个版本(可能是 Keycloak 23)中移除。建议您尽快更新您的客户端,如上所述,而不是依赖此开关。

通过 SAML javascript 协议映射器部署脚本

到目前为止,在其 SAML 客户端或客户端作用域上使用 SAML javascript 协议映射器的管理员,可以通过 Keycloak 管理控制台以及 RESTful Admin API 将脚本上传到服务器。

从现在开始,此功能被禁用,用户应直接将脚本部署到服务器。此行为与其他基于脚本的提供程序保持一致。有关更多详细信息,请查看 JavaScript 提供程序

UserInfo 端点更改

错误响应更改

UserInfo 端点现在返回完全符合 RFC 6750(OAuth 2.0 授权框架:Bearer 令牌使用)的错误响应。错误代码和描述(如果可用)作为 WWW-Authenticate 挑战属性而不是 JSON 对象字段提供。响应将如下所示,具体取决于错误情况

  • 如果未提供访问令牌

    401 Unauthorized
    WWW-Authenticate: Bearer realm="myrealm"
  • 如果同时使用多种方法来提供访问令牌(例如,Authorization 标头 + POST access_token 参数),或者 POST 参数重复

    400 Bad Request
    WWW-Authenticate: Bearer realm="myrealm", error="invalid_request", error_description="..."
  • 如果访问令牌缺少 openid 作用域

    403 Forbidden
    WWW-Authenticate: Bearer realm="myrealm", error="insufficient_scope", error_description="Missing openid scope"
  • 如果无法解析 UserInfo 响应签名/加密的加密密钥

    500 Internal Server Error
  • 如果出现令牌验证错误,则返回 401 Unauthorized 以及 invalid_token 错误代码。此错误包括用户和客户端相关的检查,实际上捕获了所有剩余的错误情况

    401 Unauthorized
    WWW-Authenticate: Bearer realm="myrealm", error="invalid_token", error_description="..."
其他更改
  • 现在要求访问令牌具有 openid 作用域,这是 UserInfo 作为 OpenID Connect 而非 OAuth 2.0 特有的功能所规定的。如果令牌中缺少 openid 作用域,则请求将被拒绝,并返回 403 Forbidden(见上文)。

  • UserInfo 现在检查用户状态,如果用户被禁用,则返回 invalid_token 响应。

迁移到 19.0.0

新的管理控制台现在是默认控制台

新的管理控制台现在是 Keycloak 中的默认控制台。如果您无法开始使用新的管理控制台,可以继续使用旧的管理控制台,方法是禁用新的控制台,例如运行

bin/kc.sh start-dev --features-disabled=admin2

继续使用旧的管理控制台的另一种方法是将 master realm 或任何其他 realm 的主题设置为 keycloak

由于新的管理控制台与旧的管理控制台显着不同,现在基于 React 并使用较新版本的 PatternFly,因此任何自定义主题都极有可能必须从头开始重新实现。要为新的管理控制台创建自定义主题,该主题应扩展 keycloak.v2 而不是 keycloak

如果您已明确将 master realm 或任何其他 realm 的管理控制台主题设置为 keycloak,它将继续使用旧的管理控制台。要更新到新的管理控制台,您需要将主题更改为 keycloak.v2

旧的管理控制台将在 Keycloak 21 中移除。

服务器配置和启动的更改

在此版本之前,您会在运行 start 命令时使用 --auto-build 来告诉服务器,如果任何构建选项在启动服务器之前已更改,则有条件地运行 build

在此版本中,--auto-build 标志已弃用,您不再需要使用它来指示您要在启动服务器时设置构建选项。相反,如果任何构建选项已更改,服务器始终默认在启动服务器之前运行 build。新的行为改进了配置和启动服务器的整体体验,使其成为可选的(尽管强烈建议),以便为了获得最佳启动时间和内存占用而预先运行 build 命令。

现在,为了获得最佳启动时间和内存占用,请设置 --optimized 选项以禁用新的默认行为。--optimized 标志告诉服务器,不需要直接作为启动一部分检查和运行 build

kc.sh start --optimized

如果您已经使用自定义镜像来设置构建选项并运行优化的 Keycloak 容器,请确保在调用 start 命令时设置 --optimized 选项。

有关更多详细信息,请查看 配置指南容器指南

健康端点的潜在重大更改

在 Keycloak 19.0.0 之前,基于 quarkus 的 Keycloak 发行版总是意外地启用了以下非应用程序端点

  • /q/health

  • /q/health/live

  • /q/health/ready

  • /q/metrics

从 Keycloak 19.0.0 开始,这些端点被禁用,请求将导致 404 HTTP 状态代码。如果您正在使用 /q/…​ 端点,请确保在升级到 Keycloak 19.0.0 时更改您的探测和监控系统以使用预期的健康端点。

预期的健康端点是

  • /health

  • /health/live

  • /health/ready

  • /metrics

除了禁用 /q/ 端点外,以下是对健康端点进行的其它改进

  • 用于活性探测的 health/live 端点现在与数据库连接健康状况分离,以匹配当前的良好实践,并且不与 health/ready 端点具有相同的行为。因此,当调用 /health/live 时,数据库检查不再显示在 checks: 数组中,因此当数据库出现问题时,活性探测仍将返回 HTTP 状态代码 200 和 UP 状态,因此可能不会触发 pod 重启。

  • 用于就绪探测的 health/ready 端点仍然会检查数据库连接是否正常工作。请确保您的配置中不仅设置了 health-enabled=true,还设置了 metrics-enabled=true,以启用数据库检查,从而实现有效的就绪探测。当数据库连接处于不健康状态时,它将返回 HTTP 状态码 503 和 DOWN 状态。

预计未来会在这个领域有更多增强功能。有关更多信息,请参阅 健康指南

使用 GELF / 集中式日志管理的更改

正如发布说明中所述,Keycloak 现在开箱即用地支持 gelf 日志记录,用于集中式日志记录系统。

如果您在之前的版本中自己添加了 gelf 相关的 quarkus jar 包,请务必切换到 日志记录指南 中受支持的配置选项,并从 providers 文件夹中删除您的 jar 包。

影响开发人员的更改

Keycloak 正在进行大规模重构,这会影响现有代码。其中一些更改需要更新现有代码。这些更改将在下面更详细地描述。

更改的理由

Keycloak 有一些限制;例如,升级 Keycloak 集群需要停机。为了解决这些限制,已经启动了深入的重构。

此版本中的更改主要与存储重构和新存储(称为 map storage)的准备工作有关。此存储最终将取代当前的存储,在本版本中当前的存储将被称为旧式存储。旧式存储在 Keycloak 中仍然可用几个版本。

新存储对服务层和存储层之间的职责进行了严格分离。因此,服务层对对象来源的可见性将受到限制,因此它将无法区分缓存对象或非缓存对象,或者源自本地或联合存储的对象。

用户存储 SPI 将被弃用。它将在几个版本内继续受到支持,但最终将被 Map Storage SPI 取代,Map Storage SPI 将能够为任何已识别的领域(例如用户、角色、客户端或组)创建自定义存储。

依赖于旧式存储中服务可用的详细程度的扩展将需要进行调整,以便在旧式存储的完整弃用期内保留此能力。以下部分描述了如何完成此调整。

使用旧式存储和 map 存储是互斥的;一个存储不能在另一个存储处于活动状态时使用。

模块结构的更改

作为引入新存储功能的一部分,KeycloakSession 中围绕存储功能的几个公共 API 已被整合,一些已被弃用,将在接下来的版本之一中删除。引入了三个新模块,并且来自 server-spiserver-spi-privateservices 模块的面向数据的代码已移动到那里

org.keycloak:keycloak-model-legacy

包含来自旧式存储的所有面向公众的 API,例如用户存储 API。

org.keycloak:keycloak-model-legacy-private

包含与用户存储管理相关的私有实现,例如存储 *Manager 类。

org.keycloak:keycloak-model-legacy-services

包含所有直接在旧式存储上操作的 REST 端点,并且在新存储中没有意义。

只要旧式存储得到支持,这些模块就将可用。在此期间之后,它们将被删除。

此更改会影响 Wildfly 分发版中现有用户存储提供程序的部署。如果您的用户存储提供程序部署为 WAR 归档文件,则需要在该归档文件中添加 META-INF/jboss-deployment-structure.xml 文件,声明修改后的依赖项,如下所示

<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
    <deployment>
        <dependencies>
            <module name="org.keycloak.keycloak-model-legacy" meta-inf="import"/>
        </dependencies>
    </deployment>
</jboss-deployment-structure>
KeycloakSession 中的更改

KeycloakSession 已被简化。KeycloakSession 中的几个方法已被弃用,将在未来的版本中删除。

KeycloakSession 会话包含几个用于获取特定对象类型提供程序的方法,例如对于 UserProvider,有 users()userLocalStorage()userCache()userStorageManager()userFederatedStorage()。这种情况可能会让开发人员感到困惑,他们必须了解每个方法的确切含义,并且依赖于当前的存储布局。新存储不区分联合存储和本地存储。

出于这些原因,KeycloakSession 中仅保留 users() 方法,并且应替换上面列出的所有其他调用。其余方法已被弃用,最终将被删除。相同的弃用模式适用于其他对象区域的方法,例如 clients()groups()。所有以 *StorageManager()*LocalStorage() 结尾的方法在被调用时现在都会抛出异常,因为在新存储中没有直接的替代方法。下一节描述如何在旧存储中使用旧 API 时将这些调用迁移到新 API 或使用旧 API。

KeycloakSession 中已弃用的方法将在未来的版本中删除。keycloak-model-legacy-* 模块将可用更长时间,最终将被删除。

迁移不依赖于旧式存储的现有提供程序

如果现有提供程序不调用已弃用的方法,则无需迁移,对于大多数提供程序来说应该是这种情况。

如果提供程序使用已弃用的方法,但不依赖于本地存储与非本地存储,则将调用从现在已弃用的 userLocalStorage() 更改为方法 users() 是最佳选择。请注意,这里的语义发生了变化,因为如果本地设置中启用了缓存,则新方法会涉及缓存。

迁移前:访问现在抛出异常的已弃用 API
session.userLocalStorage();
迁移后:访问新的 API 调用者不依赖于旧式存储 API
session.users();
迁移依赖于旧式存储的现有提供程序

在极少数情况下,当自定义提供程序需要区分特定提供程序的模式时,可以使用 LegacyStoreManagers 数据存储提供程序来访问已弃用的对象。仅当旧式模块是部署的一部分时,此选项才可用。

迁移前:访问现在抛出异常的已弃用 API
session.userLocalStorage();
迁移后:通过 LegacyStoreManagers API 访问旧功能
((LegacyDatastoreProvider) session.getProvider(DatastoreProvider.class)).userLocalStorage();

一些与用户存储相关的 API 为了方便起见已包装在 org.keycloak.storage.UserStorageUtil 中。

创建自定义存储提供程序

用于创建自定义存储提供程序的 API 尚未完全稳定,尽管它作为技术预览版提供。有关详细信息,请参阅 MapStorageProvider SPI 及其 Javadoc。新 API 的可用性是下一个 Keycloak 版本的优先事项。

RealmModel 的更改

方法 `getUserStorageProviders`、`getUserStorageProvidersStream`、`getClientStorageProviders`、`getClientStorageProvidersStream`、`getRoleStorageProviders` 和 `getRoleStorageProvidersStream` 已被删除。依赖于这些方法并在启用旧式存储的情况下运行的代码应按如下方式转换实例

迁移前:代码将由于 API 更改而无法编译
realm.getClientStorageProvidersStream()...;
迁移后:将实例强制转换为旧式接口
((LegacyRealmModel) realm).getClientStorageProvidersStream()...;

同样,过去实现 RealmModel 接口并希望提供这些方法的代码应实现新的接口 LegacyRealmModel。此接口是 RealmModel 的子接口,包含旧方法

迁移前:代码实现旧接口
public class MyClass extends RealmModel {
    /* might not compile due to @Override annotations for methods no longer present
       in the interface RealmModel. /
    / ... */
}
迁移后:代码实现新接口
public class MyClass extends LegacyRealmModel {
    /* ... */
}
接口 UserCache 已移动到旧式模块

由于对象的缓存状态对于服务将是透明的,因此接口 UserCache 已移动到模块 keycloak-legacy。因此,对 session.userCache() 的调用将仅返回 UserProvider,这是一个重大更改。

依赖于旧式实现的的代码应直接访问 UserCache。虽然在使用旧式存储进行缓存时可能需要此类调用,但在使用新的 map 存储时则不需要,因为新的 map 存储透明地处理缓存。

迁移前:代码将由于返回类型更改而无法编译
// session.userCache() might return null, null-check omitted for brevity.
session.userCache().evict(realm, user);
迁移后:直接使用 API
// session.getProvider(UserCache.class) might return null, null-check omitted for brevity.
session.getProvider(UserCache.class).evict(realm, user);

要触发 realm 的失效,请考虑触发事件,而不是使用 UserCache API

迁移前:代码将由于返回类型更改而无法编译
UserCache cache = session.getProvider(UserCache.class);
if (cache != null) cache.clear();
迁移后:使用失效 API
session.invalidate(InvalidationHandler.ObjectType.REALM, realm.getId());
用户的凭据管理

用户的凭据以前使用 session.userCredentialManager().method(realm, user, ...) 进行管理。新的方法是利用 user.credentialManager().method(...)。这种形式使凭据功能更接近用户的 API,并且不依赖于事先了解用户凭据在 realm 和存储中的位置。

旧的 API 已被弃用,并且仅在部署中启用旧式存储时才有效。新的 API 将适用于旧存储和新存储。

迁移前:访问已弃用的 API
session.userCredentialManager().createCredential(realm, user, credentialModel)
迁移后:访问新的 API
user.credentialManager().createStoredCredential(credentialModel)

对于自定义 UserStorageProvider,当返回 UserModel 时,需要实现一个新的方法 credentialManager()。由于这些提供程序在启用了旧式存储的环境中运行,因此必须返回 LegacyUserCredentialManager 的实例

迁移前:代码将由于 UserModel 需要的新方法 credentialManager() 而无法编译
public class MyUserStorageProvider implements UserLookupProvider, ... {
    /* ... */
    protected UserModel createAdapter(RealmModel realm, String username) {
        return new AbstractUserAdapter(session, realm, model) {
            @Override
            public String getUsername() {
                return username;
            }
        };
    }
}
迁移后:为旧式存储实现 API UserModel.credentialManager()
public class MyUserStorageProvider implements UserLookupProvider, ... {
    /* ... */
    protected UserModel createAdapter(RealmModel realm, String username) {
        return new AbstractUserAdapter(session, realm, model) {
            @Override
            public String getUsername() {
                return username;
            }

            @Override
            public SubjectCredentialManager credentialManager() {
                return new LegacyUserCredentialManager(session, realm, this);
            }
        };
    }
}

旧式 Keycloak Operator 中已弃用的 podDisruptionBudget

在此版本中,我们已弃用 旧式 Keycloak Operator 的 Keycloak CR 中的 podDisruptionBudget 字段。当 Operator 部署在 Kubernetes 1.25 及更高版本上时,将忽略此可选字段。

作为一种解决方法,您可以在集群中手动创建 Pod Disruption Budget,例如

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  labels:
    app: keycloak
  name: keycloak
spec:
  maxUnavailable: 1
  selector:
    matchLabels:
      component: keycloak

另请参阅 Kubernetes 文档

新 Keycloak Operator 中的部署更改

新的 Keycloak Operator 现在对 Keycloak 部署使用 StatefulSet 而不是 Deployment。由于 Operator 在此版本中是技术预览版,因此没有自动迁移。如果您在 18.0.z 中使用新的 Operator,请务必在升级到 19.0.0 后备份、删除并重新创建您的 Keycloak CR。

迁移到 18.0.0

逐步验证

逐步验证是一项新功能。此功能提供 acr 客户端作用域,其中包含一个协议映射器,该映射器应将 acr 声明添加到令牌中。acr 声明现在不会像此版本之前那样自动添加,而是通过使用此客户端作用域和协议映射器来添加。

客户端作用域作为 realm “默认”客户端作用域添加,因此将添加到所有新创建的客户端。出于性能原因,客户端作用域不会在迁移期间自动添加到所有现有客户端。迁移后,客户端默认情况下不会具有 acr 声明。考虑以下可能的措施

  • 如果您不打算使用逐步验证功能,但您依赖令牌中的 acr 声明,则可以禁用 step_up_authentication 功能。在正常身份验证的情况下,声明将添加值为 1,在 SSO 身份验证的情况下,声明将添加值为 0

  • 通过管理 REST API 或管理控制台手动将 acr 客户端作用域添加到您的客户端。如果您想使用逐步验证,则尤其需要这样做。如果您的 realm 中有大量客户端并且想要对所有客户端使用 acr 声明,则可以针对您的数据库触发一些类似于以下的 SQL。但是,请记住,如果 Keycloak 已经启动,则清除缓存或重启服务器

insert into CLIENT_SCOPE_CLIENT (CLIENT_ID, SCOPE_ID, DEFAULT_SCOPE) select CLIENT.ID as CLIENT_ID, CLIENT_SCOPE.ID as SCOPE_ID, true as DEFAULT_SCOPE
from CLIENT_SCOPE, CLIENT where CLIENT_SCOPE.REALM_ID='test' and CLIENT_SCOPE.NAME='acr' and CLIENT.REALM_ID='test' and CLIENT.PROTOCOL='openid-connect';

OpenID Connect 注销

以前版本的 Keycloak 支持通过打开注销端点 URL(例如 http(s)://example-host/auth/realms/my-realm-name/protocol/openid-connect/logout?redirect_uri=encodedRedirectUri)自动注销用户并重定向到应用程序。虽然该实现易于使用,但它可能对性能和安全性产生负面影响。新版本更好地支持基于 OpenID Connect RP-Initiated Logout 规范的注销。不再支持参数 redirect_uri;此外,在新版本中,用户需要确认注销。当您包含参数 post_logout_redirect_uri 以及带有用于登录的 ID 令牌的参数 id_token_hint 时,可以省略确认并执行自动重定向到应用程序。

现有部署会受到以下影响

  • 如果您的应用程序直接使用带有 redirect_uri 参数的注销端点链接,则您可能需要按上述方式更改此链接。考虑完全删除 redirect_uri 参数,或将其替换为 id_token_hintpost_logout_redirect_uri 参数。

  • 如果您使用 java 适配器并且您的应用程序通过调用 httpServletRequest.logout() 执行注销,则您不会受到影响,因为此调用使用注销端点的后通道变体,并且该变体未更改。

  • 如果您使用最新的 javascript 适配器,您也不会受到影响。但是,如果您的应用程序使用旧版本的 JavaScript 适配器,则您会受到影响,因为此适配器使用带有已弃用的 redirect_uri 参数的注销端点变体。在这种情况下,您可能需要升级到最新版本的 JavaScript 适配器。

  • 对于 Node.js 适配器,与 JavaScript 适配器适用相同的准则。建议您更新到最新版本,因为旧版本的适配器使用已弃用的 redirect_uri 参数。使用最新的 Node.js 适配器,只要您按照文档或 Node.js 适配器示例中所述使用基于 /logout URL 的注销,您就不会受到影响。但是,如果您的应用程序直接使用方法 keycloak.logoutUrl,您可以考虑将 idTokenHint 作为此方法的第二个参数添加。在此版本中新添加了将 idTokenHint 作为第二个参数添加的可能性。idTokenHint 需要是在登录期间获得的有效 ID 令牌。添加 idTokenHint 是可选的,但如果您省略它,您的用户将需要确认注销屏幕,如前所述。此外,他们将在注销后不会重定向回应用程序。

有一个向后兼容性选项,允许您的应用程序仍然使用旧格式的 redirect_uri 参数。

您可以在启动服务器时通过输入以下命令来启用此参数

bin/kc.[sh|bat] --spi-login-protocol-openid-connect-legacy-logout-redirect-uri=true start

通过此配置,您仍然可以使用带有 redirect_uri 参数的格式。请注意,如果省略 id_token_hint,则需要确认屏幕。

向后兼容性开关将在未来的某个版本(可能是 Keycloak 23)中移除。建议您尽快更新您的客户端,如上所述,而不是依赖此开关。

删除 upload-scripts 功能

以前版本的 Keycloak 支持通过管理界面(如管理控制台和 REST API)管理 JavaScript 代码。从此版本开始,不再可能这样做,您现在应该将脚本部署到服务器,以便配置以下提供程序

  • OpenID Connect 脚本映射器

  • 脚本身份验证器(身份验证执行)

  • JavaScript 策略

有关如何将脚本部署到服务器的更多详细信息,请参阅文档。请注意,要使用脚本,您仍然需要启用 scripts 技术预览功能。

kc.[sh|bat] start --auto-build --features=preview

部署脚本时,服务器将自动创建其相应的提供程序,以便您可以在配置身份验证流程、映射器和授权策略时选择它们。

一般来说,更新 realm 的步骤如下

  • 升级前,删除您正在使用的任何脚本提供程序。

  • 升级后,按照 文档 中的说明部署您的脚本。

  • 更新您的身份验证流程、映射器和客户端授权设置,以使用从部署到服务器的脚本创建的提供程序。

帐户控制台 Patternfly 升级

Patternfly (PF) React 库已更新,@patternfly/react-core 从 v3.153.3 更新到 v4.147.0,@patternfly/react-icons 从 v3.15.16 更新到 v 4.11.8,以及 @patternfly/react-styles 从 v3.7.14 更新到 v4.11.8。对帐户控制台进行了一些小的 UI 更新,使其与 PF 设计标准保持一致。

由于 PF 中的重大更改,自定义开发的帐户 UI 可能与这些更新不兼容。大多数重大更改应通过更新 PF 组件上的 props 来解决。

资源

已知具有重大更改的组件

  • Alert (警报)

  • action prop 更改为 actionClose

  • Expandable (可展开)

  • 重命名为 ExpandableSection

  • Title (标题)

  • size 属性现在使用 TitleSizes

  • DataListContent (数据列表内容)

  • noPadding 更改为 hasNoPadding

  • Grid, Stack, Level, Gallery (网格、堆叠、层级、画廊)

  • gutter 属性更改为 hasGutter

  • Modal (模态框)

  • 尺寸控制从例如 isLarge 更改为使用 ModalVariant,例如 variant={ModalVariant.large}

  • Select (选择框)

  • ariaLabelTypeAhead 更改为 typeAheadAriaLabel

  • isExpanded 更改为 isOpen

  • ariaLabelledBy 更改为 aria-labelledby

  • DataListContent (数据列表内容)

  • noPadding 更改为 hasNoPadding

Quarkus 分发版:将 metrics-enabled 选项拆分为 health-enabled 和 metrics-enabled

metrics-enabled 选项现在仅启用 Keycloak 的指标。要启用就绪和活跃度健康端点,有一个新的布尔选项 health-enabled。这允许更细粒度地使用这些选项,例如,启用指标但不为本地用例启用就绪/活跃度探测。为了保持与之前设置 metrics-enabled=true 时的相同行为,您需要在构建 Keycloak 时额外设置 health-enabled=true

迁移到 17.0.0

默认分发版现在由 Quarkus 提供支持

Keycloak 的默认分发版现在由 Quarkus 提供支持,这为您配置 Keycloak 和部署自定义提供程序带来了一些重大更改。有关更多信息,请查看 Quarkus 迁移指南

Keycloak 的 WildFly 分发版现已弃用,支持将于 2022 年 6 月结束。我们建议尽快迁移到 Quarkus 分发版。但是,如果您需要在旧版 WildFly 分发版上保留一段时间,则需要考虑一些更改

  • 旧版分发版标签的容器镜像已更改。要使用旧版分发版,请使用标签 legacy17.0.0-legacy

  • 网站上旧版分发版的下载已更改为 keycloak-legacy-17.0.0.[zip|tar.gz]

如果您在迁移到 Quarkus 分发版时遇到问题,缺少配置某些内容的能力,或者有一般想法和反馈,请在 GitHub Discussions 中发起讨论。

从预览版 Quarkus 分发版迁移

自 Keycloak 15.1.0 中发布预览版 Quarkus 分发版以来,许多内容已更改。了解已更改内容的理想方法是查看新的 服务器指南。总而言之,更改包括

  • 容器现在发布到 quay.io/keycloak/keycloak:latestquay.io/keycloak/keycloak:17.0.0

  • 网站上的下载重命名为 keycloak-17.0.0.[zip|tar.gz]

  • conf/keycloak.properties 更改为 conf/keycloak.conf,这统一了配置文件和 CLI 参数之间的配置键。

  • build optionsruntime configuration 之间更清晰的分离。

  • 自定义 Quarkus 配置通过 conf/quarkus.properties 完成。

  • h2-memh2-file 数据库重命名为 dev-memdev-file

  • 功能现在使用 --features--features-disabled 启用/禁用,取代了以前为每个功能设置单独配置键的方法。

  • 运行时配置不再可以传递给 kc.[sh|bat] build,并且不再持久保存在构建中

  • 日志记录级别和格式现在使用 --log-level--log-format 配置,而在过去,这些必须使用不受支持的 Quarkus 属性进行配置。

客户端策略迁移:client-scopes

如果您使用了包含 client-scopes 条件的策略并直接编辑了 JSON 文档,则需要将 JSON 文档中的 “scope” 字段名称更改为 “scopes”。

Liquibase 升级到 4.6.2 版本

Liquibase 从 3.5.5 版本更新到 4.6.2 版本,其中包括许多错误修复以及使用 ServiceLoader 注册自定义扩展的新方法。

从以前的 Keycloak 版本到 Keycloak 17.0.0 的迁移已经过所有当前支持的数据库的广泛测试,但我们要强调密切关注 升级指南 的重要性,特别是在升级前备份现有数据库。虽然我们尽力测试了 Liquibase 升级的后果,但某些安装可能正在使用我们未知的特定设置。

迁移到 16.0.0

WildFly 25 升级

WildFly 25 弃用了旧式安全子系统,该子系统除其他外还用于配置 TLS。由于更改量很大,我们无法像过去那样提供迁移脚本。

我们建议您从 Keycloak 16 中提供的默认配置文件开始,并应用相关的更改,而不是复制以前版本的 Keycloak 的配置文件。

Keycloak 子系统的配置可以直接复制。

有关 Elytron 子系统的更多信息,请参阅 WildFly 文档

对于由此带来的不便,我们深感抱歉,并理解这将使所有人升级到 Keycloak 16 变得更加困难,但我们实在找不到替代方法。

值得指出的一件事是切换到 Quarkus 分发版,我们计划在 Keycloak 17 中使其完全受支持,这将使配置和升级 Keycloak 变得更加容易。

有关 WildFly 25 的更多信息,请参阅 WildFly 25 发行说明

代理环境变量

Keycloak 现在尊重标准 HTTP_PROXYHTTPS_PROXYNO_PROXY 环境变量,用于传出的 HTTP 请求。如果您定义了 HTTP_PROXY 变量,但在 SPI 配置中没有指定显式代理映射,则此更改可能会导致意外使用代理服务器。要防止 Keycloak 使用这些环境变量,您可以为所有请求显式创建无代理路由,如 .*;NO_PROXY

Keycloak Operator 中已弃用的功能

在此版本中,我们已弃用和/或标记为不受支持 Keycloak Operator 中的某些功能。这涉及 Backup CRD 和 operator 管理的 Postgres 数据库。

Keycloak Operator 示例,包括不受支持的 Metrics 扩展

以前,在 Keycloak Operator 创建 Keycloak CR 的示例中添加了一个不受支持的 metrics 扩展。这已被删除。

迁移到 14.0.0

客户端策略迁移

客户端策略功能自 Keycloak 12 以来一直是预览功能,并且没有适当的支持。如果您尝试过此功能并在 Keycloak 12 或 Keycloak 13 中配置了一些客户端策略或客户端配置文件,则需要在新版本中再次配置您的客户端策略和客户端配置文件。配置的格式已发生重大更改,因为它只是一个预览版,因此我们不提供 Keycloak 12 或 Keycloak 13 中创建的客户端策略和客户端配置文件的自动迁移。

迁移到 13.0.0

需要手动迁移步骤

当 standalone.xml 包含对任何 SmallRye 模块的引用时,需要手动更改。SmallRye 模块已从底层 WildFly 分发版中删除,并且如果配置引用它们,服务器将无法启动。因此,如果 standalone.xml 中的配置引用了这些模块,则通过 migrate-standalone.cli 的服务器配置迁移在对配置进行任何更改之前就会失败。在这种情况下,要执行服务器配置迁移,您必须手动删除所有引用 SmallRye 模块的行。在默认配置中,您需要专门删除以下行

<extension module="org.wildfly.extension.microprofile.config-smallrye"/>
<extension module="org.wildfly.extension.microprofile.health-smallrye"/>
<extension module="org.wildfly.extension.microprofile.metrics-smallrye"/>
<subsystem xmlns="urn:wildfly:microprofile-config-smallrye:1.0"/>
<subsystem xmlns="urn:wildfly:microprofile-health-smallrye:2.0" security-enabled="false" empty-liveness-checks-status="${env.MP_HEALTH_EMPTY_LIVENESS_CHECKS_STATUS:UP}" empty-readiness-checks-status="${env.MP_HEALTH_EMPTY_READINESS_CHECKS_STATUS:UP}"/>
<subsystem xmlns="urn:wildfly:microprofile-metrics-smallrye:2.0" security-enabled="false" exposed-subsystems="*" prefix="${wildfly.metrics.prefix:wildfly}"/>

升级到 Wildfly 23

Keycloak 服务器已升级为使用 Wildfly 23 作为底层容器。这不直接涉及任何特定的 Keycloak 服务器功能,但是,请注意与迁移相关的这些更改

依赖项更新

依赖项已更新为 Wildfly 23 服务器使用的版本。例如,Infinispan 现在是 11.0.9.Final

配置更改

standalone(-ha).xmldomain.xml 文件中存在一些配置更改。您应该按照 下载 Keycloak 服务器 部分自动处理配置文件的迁移。但是,以下是最重要的更改,如果您进行了自己的配置更改,您可能需要注意这些更改

  • Infinispan 缓存容器的 module 属性现在已弃用(未使用),并且已替换为 modules 属性,该属性表示与此缓存容器的配置关联的模块集。此外,由于使用了 Wildfly 23 作为底层容器,因此各种元素的属性也进行了一些其他更改。例如,managed-executor-servicemanaged-scheduled-executor-service 元素现在可以识别新的 hung-task-termination-period 属性。有关详细信息,请参阅 Wildfly 23 完整模型参考

升级到 Wildfly 22

Keycloak 服务器已升级为使用 Wildfly 22 作为底层容器。这不直接涉及任何特定的 Keycloak 服务器功能,但是,请注意与迁移相关的这些更改

依赖项更新

依赖项已更新为 Wildfly 22 服务器使用的版本。例如,Infinispan 现在是 11.0.8.Final

配置更改

standalone(-ha).xmldomain.xml 文件中存在一些配置更改。您应该按照 下载 Keycloak 服务器 部分自动处理配置文件的迁移。但是,以下是最重要的更改,如果您进行了自己的配置更改,您可能需要注意这些更改

迁移到 12.0.2

只读属性

添加了对只读用户属性的支持。这包括用户属性,这些属性不应由用户或管理员在通过 REST API 或 Keycloak 用户界面更新用户时进行编辑。如果您使用以下功能,这一点尤其重要

  • 自定义用户存储提供程序

  • 自定义身份验证器

  • 自定义 JavaScript 授权策略,这些策略基于某些用户属性建立授权

  • 带有用于将 X.509 证书映射到用户身份的自定义属性的 X.509 身份验证器

  • 任何其他自定义功能,其中某些用户属性用作存储身份验证/授权/身份上下文的元数据,而不是简单的用户个人资料信息。

有关详细信息,请参阅 威胁模型缓解章节

有效的请求 URI

如果您使用 OpenID Connect 参数 request_uri,则您的客户端需要配置 Valid Request URIs。这可以通过管理控制台在客户端详细信息页面上配置,也可以通过管理 REST API 或客户端注册 API 配置。Valid Request URIs 需要包含特定客户端允许的请求 URI 值列表。这是为了避免 SSRF 攻击。可以像 Valid Redirect URIs 选项一样使用通配符或相对路径,但出于安全目的,我们通常建议使用尽可能具体的值。

迁移到 13.0.0

升级到 Wildfly 22

Keycloak 服务器已升级为使用 Wildfly 22 作为底层容器。这不直接涉及任何特定的 Keycloak 服务器功能,但有一些与迁移相关的更改值得一提。

依赖项更新

依赖项已更新为 Wildfly 22 服务器使用的版本。例如,Infinispan 现在是 11.0.8.Final

配置更改

standalone(-ha).xmldomain.xml 文件中存在一些配置更改。您应该按照下载 Keycloak 服务器部分自动处理配置文件的迁移。如果需要更多详细信息,例如,因为您自己进行了一些配置更改,则最重要的更改列表如下

迁移到 12.0.0

升级到 Wildfly 21

Keycloak 服务器已升级为使用 Wildfly 21 作为底层容器。这不直接涉及任何特定的 Keycloak 服务器功能,但是,请注意与迁移相关的这些更改

依赖项更新

依赖项已更新为 Wildfly 21 服务器使用的版本。例如,Infinispan 现在是 11.0.4.Final。

配置更改

standalone(-ha).xmldomain.xml 文件中存在一些配置更改。您应该按照 下载 Keycloak 服务器 部分自动处理配置文件的迁移。但是,以下是最重要的更改,如果您进行了自己的配置更改,您可能需要注意这些更改

  • Infinispan 缓存的 object-memory 元素现在已弃用(未使用),并替换为 heap-memory 元素。

跳过为 Docker 协议身份验证创建用户会话

使用 Docker 协议成功进行身份验证后,不会创建用户会话。有关详细信息,请参阅服务器管理指南

升级到 PatternFly 4

Keycloak 登录主题组件已升级到 PatternFly 4。旧的 PatternFly 3 与新的 PatternFly 4 同时运行,因此可以保留 PF3 组件。但是,对登录主题的设计进行了一些更改。请根据这些更改升级您的自定义登录主题。在 keycloak/examples/themes/theme/sunrise 目录中可以找到包含必要更改的示例。无需其他设置。

默认情况下,客户端凭据授权不使用刷新令牌

从这个 Keycloak 版本开始,OAuth2 客户端凭据授权端点默认情况下不颁发刷新令牌。此行为与 OAuth2 规范一致。此更改的副作用是,在成功进行客户端凭据身份验证后,Keycloak 服务器端不会创建用户会话,从而提高了性能和内存消耗。建议使用客户端凭据授权的客户端停止使用刷新令牌,而是在每次请求时始终使用 grant_type=client_credentials 进行身份验证,而不是使用 refresh_token 作为授权类型。与此相关的是,Keycloak 在 OAuth2 撤销端点中支持撤销访问令牌,因此允许客户端在需要时撤销单个访问令牌。

为了向后兼容,仍然可以坚持旧版本的行为。当使用此功能时,在客户端凭据授权成功身份验证后,仍将颁发刷新令牌,并且还将创建用户会话。可以在 Keycloak 管理控制台中的特定客户端上启用此功能,在客户端详细信息中,在 OpenID Connect 兼容模式 部分,使用 对客户端凭据授权使用刷新令牌 开关。

迁移到 11.0.0

升级到 Wildfly 20

Keycloak 服务器已升级为使用 Wildfly 20 作为底层容器。这不直接涉及任何特定的 Keycloak 服务器功能,但是,请注意与迁移相关的这些更改

依赖项更新

依赖项已更新为 Wildfly 20 服务器使用的版本。例如,Infinispan 现在是 10.1.8.Final。

配置更改

standalone(-ha).xmldomain.xml 文件中存在一些配置更改。您应该按照下载 Keycloak 服务器部分自动处理配置文件的迁移。

跨数据中心复制更改
  • 您将需要将 Infinispan 服务器升级到 9.4.19 版本。旧版本可能仍然有效,但由于不再进行测试,因此无法保证。

  • 建议在配置 Infinispan 缓存时,使用添加到 remote-store 元素的 protocolVersion 属性。当连接到 Infinispan 服务器 9.4.18 时,由于 Keycloak 服务器和 Infinispan 服务器之间的 Infinispan 库版本不同,建议的热棒协议版本为 2.9。有关更多详细信息,请参阅跨数据中心文档。

  • 建议在 connectionsInfinispan 子系统下使用 remoteStoreSecurityEnabled 属性。有关更多详细信息,请参阅跨数据中心文档。

LDAP 无导入错误修复

在之前的 Keycloak 版本中,当 LDAP 提供程序配置为 导入用户 关闭时,即使某些非 LDAP 映射的属性被更改,也可以更新用户。这种情况导致了令人困惑的行为,即属性似乎已更新,但实际上并未更新。在当前版本中,如果任何非 LDAP 映射的属性被更改,则完全不允许执行更新。

这应该不会影响大多数部署,但某些情况下可能会在一些罕见的情况下受到影响。例如,如果您之前尝试使用管理 REST API 更新用户,并且该用户有一些不正确的属性更改,则可以进行更新。在当前版本中,更新是不可能的,您将立即被告知原因。

UserModel 更改

UserModel 中的字段 usernameemailfirstNamelastName 已迁移到自定义属性,为在即将到来的版本中向 Keycloak 添加更复杂的用户配置文件做准备。如果数据库包含具有完全相同名称的自定义属性的用户,则需要在升级之前迁移自定义属性。此迁移不会自动发生。否则,它们将不再从数据库中读取,并可能被删除。这种情况意味着现在也可以通过 UserModel.getFirstAttribute(UserModel.USERNAME) 访问和设置 username。其他字段也存在类似的含义。直接或间接子类化 UserModel 的 SPI 的实现者应确保 setUsernamesetSingleAttribute(UserModel.USERNAME, …​)(以及其他字段的类似方法)之间的行为是一致的。策略评估功能的用户如果在其评估中使用属性数量,则必须调整其策略,因为现在每个用户默认都将拥有四个新属性。

UserModel 的公共 API 没有更改。无需更改前端资源或访问用户数据的 SPI。此外,数据库尚未更改。

Instagram IdP 已迁移到新的 API

Instagram IdP 现在使用新的 API,因为旧的旧版 API 已弃用。这需要获取新的 API 凭据。有关详细信息,请参阅服务器管理指南

对于使用 Instagram IdP 的现有用户,特别是那些将其作为唯一身份验证选项的用户,需要特别注意。此类用户必须在 2020 年 9 月 30 日之前使用 Instagram IdP 登录 Keycloak。在那天之后,他们将必须使用不同的身份验证方法(如密码)登录以手动更新其 Instagram 社交链接,或在 Keycloak 中创建新帐户。这是因为 Instagram 用户 ID 在旧 API 和新 API 之间不兼容,但新 API 暂时返回新旧用户 ID 以允许迁移。Keycloak 会在用户登录后自动迁移 ID。

非标准令牌内省端点已删除

在以前的版本中,Keycloak 公布了两个内省端点:token_introspection_endpointintrospection_endpoint。后者是 RFC-8414 定义的端点。前者以前已弃用,现在已删除。

迁移到 9.0.1

JavaScript 适配器中的旧版 Promise

不再需要在 JavaScript 适配器中设置 promiseType,并且两者都同时可用。建议尽快更新应用程序以使用原生 Promise API (thencatch),因为旧版 API (successerror) 将在某个时候被删除。

重复的顶级组

9.0.1 版本修复了一个问题,该问题可能会在领域中创建重复的顶级组。然而,之前重复组的存在使升级过程失败。如果 Keycloak 服务器正在使用 H2、MariaDB、MySQL 或 PostgreSQL 数据库,则可能会受到此问题的影响。在启动升级之前,请检查服务器是否包含重复的顶级组。例如,可以在数据库级别执行以下 SQL 查询来列出它们

SELECT REALM_ID, NAME, COUNT(*) FROM KEYCLOAK_GROUP WHERE PARENT_GROUP is NULL GROUP BY REALM_ID, NAME HAVING COUNT(*) > 1;

在每个领域中,只能存在一个同名的顶级组。重复项应在升级前进行审核和删除。升级中的错误包含消息 Change Set META-INF/jpa-changelog-9.0.1.xml::9.0.1- KEYCLOAK-12579-add-not-null-constraint::keycloak failed.

迁移到 9.0.0

改进了用户区域设置的处理

对如何选择登录页面的区域设置以及何时更新用户的区域设置进行了一些改进。

有关更多详细信息,请参阅服务器管理指南

令牌表示 Java 类中已弃用的方法

在 2038 年,int 将无法再保存自 1970 年以来的秒数值,因此我们正在努力将这些值更新为 long 值。此外,令牌表示中还存在另一个与处理 int 值相关的问题。int 默认情况下将在 JSON 表示中生成 0,但它不应包含在内。

有关已弃用方法的详细信息和替换方法,请参阅 JavaDocs。

迁移到 8.0.2

更多身份验证流程更改

同一流程中不支持 REQUIRED 和 ALTERNATIVE 执行

在以前的版本中,可以在同一身份验证流程中的同一级别拥有 REQUIRED 和 ALTERNATIVE 执行。这种方法存在一些问题,我们在身份验证 SPI 中进行了重构,这意味着这不再被认为是有效的。如果在同一级别配置了 ALTERNATIVE 和 REQUIRED 执行,则 ALTERNATIVE 执行将被视为禁用。因此,在迁移到最新版本时,您现有的身份验证流程将自动迁移,并保留与以前版本相同的行为。如果它们在与某些 REQUIRED 执行相同的级别包含 ALTERNATIVE 执行,则 ALTERNATIVE 执行将被添加到单独的 REQUIRED 子流程中。这应确保特定身份验证流程的行为与以前版本相同/相似。我们始终建议仔细检查您的身份验证流程的配置,并对其进行测试,以仔细检查一切是否按预期工作。如果您有一些更自定义的身份验证流程和自定义身份验证器实现,则此建议尤其适用。

迁移到 8.0.0

新的默认主机名提供程序

旧的请求和固定主机名提供程序已替换为新的默认主机名提供程序。请求和固定主机名提供程序现在已弃用,建议尽快切换到默认主机名提供程序。

升级到 Wildfly 18

Keycloak 服务器已升级为使用 Wildfly 18 作为底层容器。这不直接涉及任何特定的 Keycloak 服务器功能,但是,请注意与迁移相关的这些更改

依赖项更新

依赖项已更新为 Wildfly 18 服务器使用的版本。例如,Infinispan 现在是 9.4.16.Final。

配置更改

standalone(-ha).xmldomain.xml 文件中存在一些配置更改。您应该按照下载 Keycloak 服务器部分自动处理配置文件的迁移。

跨数据中心复制更改
  • 您将需要将 Infinispan 服务器升级到 9.4.19 版本。旧版本可能仍然有效,但由于我们不再进行测试,因此无法保证。

将脚本部署到服务器

到目前为止,管理员可以通过 Keycloak 管理控制台以及 RESTful 管理 API 将脚本上传到服务器。

从现在开始,默认情况下此功能已禁用,用户应首选将脚本直接部署到服务器。有关更多详细信息,请查看JavaScript 提供程序

JavaScript 适配器中的客户端凭据

在以前的版本中,开发人员被允许向 JavaScript 适配器提供客户端凭据。从现在开始,此功能已删除,因为客户端应用不安全,无法保存机密信息。

身份验证流程更改

我们对身份验证流程进行了一些重构和改进,这需要在迁移期间引起一些注意。

已删除 OPTIONAL 执行要求

关于迁移,最重要的更改是从身份验证执行中删除对 OPTIONAL 要求的支持,并将其替换为 CONDITIONAL 要求,这允许更大的灵活性。以前版本中配置的现有 OPTIONAL 身份验证器将替换为 CONDITIONAL 子流程。这些子流程将 条件 - 用户已配置 条件配置为第一个执行,并将以前的 OPTIONAL 身份验证器(例如 OTP 表单)配置为第二个执行。从用户的角度来看,身份验证期间的行为与以前版本相同。

Java SPI 中的更改

Java 身份验证 SPI 和凭据提供程序 SPI 中存在一些更改。Authenticator 接口未更改,但如果您正在开发更高级的身份验证器,这些身份验证器引入了一些新的凭据类型(CredentialModel 的子类),则可能会受到影响。CredentialProvider 接口发生了一些更改,并引入了一些新接口,例如 CredentialValidator。此外,如果您的身份验证器支持 OPTIONAL 执行要求,则您可能会受到影响。建议仔细检查服务器开发指南中的最新身份验证示例,以获取更多详细信息。

Freemarker 模板更改

Freemarker 模板中存在一些更改。如果您有自己的主题,其中包含用于登录表单或某些帐户表单的自定义 Freemarker 模板,特别是与 OTP 相关的表单,则可能会受到影响。建议仔细检查最新 Keycloak 中的 Freemarker 模板中的更改,并根据其调整您的模板。

用户凭据更改

我们增加了围绕用户凭据存储的灵活性。除其他事项外,每个用户可以拥有相同类型的多个凭据,例如多个 OTP 凭据。因此,对数据库架构进行了一些更改。但是,以前版本中的凭据应自动更新为新格式,并且用户仍然应该能够使用在以前版本中设置的密码或 OTP 凭据登录。

迁移到 7.0.0

升级到 Wildfly 17

Keycloak 服务器已升级为使用 Wildfly 17 作为底层容器。这不直接涉及任何特定的 Keycloak 服务器功能,但是,请注意与迁移相关的这些更改

依赖项更新

依赖项已更新为 Wildfly 17 服务器使用的版本。例如,Infinispan 现在是 9.4.14.Final。

配置更改

standalone(-ha).xmldomain.xml 文件中存在一些配置更改。您应该按照下载 Keycloak 服务器部分自动处理配置文件的迁移。

跨数据中心复制更改
  • 您将需要将 Infinispan 服务器升级到 9.4.19 版本。旧版本可能仍然有效,但由于我们不再进行测试,因此无法保证。

迁移到 6.0.0

升级到 Wildfly 16

Keycloak 服务器已升级为使用 Wildfly 16 作为底层容器。这不直接涉及任何特定的 Keycloak 服务器功能,但是,请注意与迁移相关的这些更改

依赖项更新

依赖项已更新为 Wildfly 16 服务器使用的版本。例如,Infinispan 现在是 9.4.8.Final。

配置更改

standalone(-ha).xmldomain.xml 文件中存在一些配置更改。您应该按照下载 Keycloak 服务器部分自动处理配置文件的迁移。

跨数据中心复制更改
  • 您将需要将 Infinispan 服务器升级到 9.4.19 版本。旧版本可能仍然有效,但由于我们不再进行测试,因此无法保证。

新的可选客户端作用域

我们添加了一个新的 microprofile-jwt 可选客户端作用域来处理 MicroProfile/JWT Auth 规范中定义的声明。这个新的客户端作用域定义了协议映射器,用于将已验证用户的用户名设置为 upn 声明,并将领域角色设置为 groups 声明。

能够将 prompt=none 传播到默认 IDP

我们在 OIDC 身份提供程序配置中添加了一个名为 接受来自客户端的 prompt=none 转发 的新开关,以标识能够处理包含 prompt=none 查询参数的转发请求的 IDP。

到目前为止,当收到带有 prompt=none 的身份验证请求时,如果用户未在领域中进行身份验证,则领域将返回 login_required 错误,而无需检查用户是否已通过 IDP 进行身份验证。从现在开始,如果可以为身份验证请求确定默认 IDP(通过使用 kc_idp_hint 查询参数或为领域设置默认 IDP),并且如果为 IDP 启用了 接受来自客户端的 prompt=none 转发 开关,则身份验证请求将转发到 IDP 以检查用户是否已在那里进行身份验证。

重要的是要注意,仅当指定了默认 IDP 时,此开关才会被考虑在内,在这种情况下,我们知道将身份验证请求转发到哪里,而无需提示用户选择 IDP。如果无法确定默认 IDP,我们无法假定将使用哪个 IDP 来满足身份验证请求,因此不会执行请求转发。

迁移到 5.0.0

升级到 Wildfly 15

Keycloak 服务器已升级为使用 Wildfly 15 作为底层容器。这不直接涉及任何特定的 Keycloak 服务器功能,但是,请注意与迁移相关的这些更改

依赖项更新

依赖项已更新为 Wildfly 15 服务器使用的版本。例如,Infinispan 现在是 9.4.3.Final。

配置更改

standalone(-ha).xmldomain.xml 文件中存在一些配置更改。您应该按照下载 Keycloak 服务器部分自动处理配置文件的迁移。

跨数据中心复制更改
  • 您将需要将 Infinispan 服务器升级到 9.4.19 版本。旧版本可能仍然有效,但由于我们不再进行测试,因此无法保证。

迁移到 4.8.2

Google 身份提供程序已更新为使用 Google Sign-in 身份验证系统

Keycloak 4.8.1 及更早版本中的 Google 身份提供程序实现依赖于 Google+ API 端点进行授权和获取用户个人资料。从 2019 年 3 月起,Google 将取消对 Google+ API 的支持,转而使用新的 Google Sign-in 身份验证系统。Keycloak 身份提供程序已更新为使用新的端点,因此如果正在使用此集成,请确保升级到 Keycloak 4.8.2 或更高版本。

如果您遇到错误,提示在目录中找不到应用程序标识符,您将需要在 Google API 控制台 门户中重新注册客户端应用程序,以获取新的应用程序 ID 和密钥。

您可能需要调整自定义映射器,以适应 Google+ 用户信息端点提供的非标准声明,以及 Google Sign-in API 以不同名称提供的声明。请查阅 Google 文档,以获取有关可用声明的最新信息。

LinkedIn 社交代理已更新为 LinkedIn API 的版本 2

根据 LinkedIn 的说法,所有开发人员都需要迁移到其 API 和 OAuth 2.0 的版本 2.0。因此,我们更新了 LinkedIn 社交代理。

使用此代理的现有部署在尝试使用 LinkedIn API 的版本 2 获取用户个人资料时,可能会开始遇到错误。此错误可能与用于配置代理的客户端应用程序缺乏授权访问 Profile API 或在身份验证过程中请求特定 OAuth2 作用域的权限有关。

即使对于新创建的 LinkedIn 客户端应用程序,您也需要确保客户端能够请求 r_liteprofiler_emailaddress OAuth2 作用域(至少),以及客户端应用程序可以从 https://api.linkedin.com/v2/me 端点获取当前成员的个人资料。

由于 LinkedIn 在访问成员信息方面施加的这些隐私限制,以及当前成员的 Profile API 返回的声明集有限,LinkedIn 社交代理现在使用成员的电子邮件地址作为默认用户名。这意味着在身份验证期间发送授权请求时,始终会设置 r_emailaddress

迁移到 4.6.0

新的默认客户端作用域

我们添加了新的领域默认客户端作用域 rolesweb-origins。这些客户端作用域包含协议映射器,用于将用户的角色和允许的 Web 源添加到令牌。在迁移期间,这些客户端作用域应自动添加到所有 OpenID Connect 客户端作为默认客户端作用域。因此,数据库迁移完成后无需进行任何设置。

协议映射器 SPI 添加

与此相关的是,对(不受支持的)协议映射器 SPI 进行了少量添加。只有当您实现了自定义 ProtocolMapper 时,才可能会受到影响。ProtocolMapper 接口上引入了一个新的 getPriority() 方法。该方法已设置为返回 0 的默认实现。如果您的协议映射器实现依赖于访问令牌 realmAccessresourceAccess 属性中的角色,则可能需要提高映射器的优先级。

受众解析

现在,对于已验证用户在令牌中至少有一个客户端角色的所有客户端,其受众会自动添加到访问令牌中的 aud 声明中。另一方面,访问令牌可能不会自动包含为其颁发令牌的前端客户端的受众。有关更多详细信息,请阅读服务器管理指南

JavaScript 适配器 Promise

要将原生 JavaScript Promise 与 JavaScript 适配器一起使用,现在需要在 init 选项中将 promiseType 设置为 native

过去,如果原生 Promise 可用,则会返回一个包装器,该包装器同时提供旧版 Keycloak Promise 和原生 Promise。这导致了一些问题,因为错误处理程序并非总是在原生错误事件之前设置,从而导致 Uncaught (in promise) 错误。

Microsoft 身份提供程序已更新为使用 Microsoft Graph API

Keycloak 4.5.0 及更早版本中的 Microsoft 身份提供程序实现依赖于 Live SDK 端点进行授权和获取用户个人资料。从 2018 年 11 月起,Microsoft 将取消对 Live SDK API 的支持,转而使用新的 Microsoft Graph API。Keycloak 身份提供程序已更新为使用新的端点,因此如果正在使用此集成,请确保升级到 Keycloak 4.6.0 或更高版本。

由于应用程序的 ID 格式发生更改,在“Live SDK 应用程序”下注册的旧版客户端应用程序将无法与 Microsoft Graph 端点一起使用。如果您遇到错误,提示在目录中找不到应用程序标识符,您将需要在 Microsoft 应用程序注册 门户中重新注册客户端应用程序,以获取新的应用程序 ID。

升级到 Wildfly 14

Keycloak 服务器已升级为使用 Wildfly 14 作为底层容器。这不直接涉及任何特定的 Keycloak 服务器功能,但是,请注意与迁移相关的这些更改

依赖项更新

依赖项已更新为 Wildfly 14 服务器使用的版本。例如,Infinispan 现在是 9.3.1.Final。

配置更改

standalone(-ha).xmldomain.xml 文件中存在一些配置更改。您应该按照下载 Keycloak 服务器部分自动处理配置文件的迁移。

跨数据中心复制更改
  • 您将需要将 Infinispan 服务器升级到 9.4.19 版本。旧版本可能仍然有效,但由于我们不再进行测试,因此无法保证。

迁移到 4.4.0

升级到 Wildfly 13

Keycloak 服务器已升级为使用 Wildfly 13 作为底层容器。这不直接涉及任何特定的 Keycloak 服务器功能,但是,请注意与迁移相关的这些更改

依赖项更新

依赖项已更新为 Wildfly 13 服务器使用的版本。例如,Infinispan 现在是 9.2.4.Final,Undertow 是 2.0.9.Final

配置更改

standalone(-ha).xmldomain.xml 文件中存在一些配置更改。您应该按照 下载 Keycloak 服务器 部分自动处理配置文件的迁移。但是,以下是最重要的更改,如果您进行了自己的配置更改,您可能需要注意这些更改

  • infinispan 缓存上的 eviction 元素现在已弃用(未使用),并替换为 object-memory 元素

  • Infinispan 子系统中的 cache-container 元素不再识别 jndi-attribute

跨数据中心复制更改
  • 您将需要将 Infinispan 服务器升级到 9.4.19 版本。旧版本可能仍然有效,但由于我们不再进行测试,因此无法保证。

  • 您不再需要在 Infinispan 服务器配置文件中配置安全性。

  • 需要从 Infinispan 服务器配置文件中复制缓存的配置中删除 transaction 元素。这是由于 infinispan 错误 https://issues.redhat.com/browse/ISPN-9323 所需的。

迁移到 4.3.0

主机名配置

在以前的版本中,建议使用过滤器来指定允许的主机名。现在可以设置固定主机名,这使得更容易确保使用有效的主机名,并且还允许内部应用程序通过备用 URL(例如内部 IP 地址)调用 Keycloak。建议您在生产环境中切换到此方法。

迁移到 4.0.0

客户端模板已更改为客户端作用域

我们增加了对客户端作用域的支持,这在迁移期间需要一些注意。

客户端模板已更改为客户端 Scope

客户端模板已更改为客户端作用域。如果您有任何客户端模板,它们的协议映射器和角色作用域映射将被保留。

名称中替换了空格

名称中带有空格字符的客户端模板已通过将空格替换为下划线来重命名,因为客户端作用域的名称中不允许空格。例如,客户端模板 my template 将更改为客户端作用域 my_template

将客户端作用域链接到客户端

对于具有客户端模板的客户端,相应的客户端作用域现在作为 Default Client Scope 添加到客户端。因此,协议映射器和角色作用域映射将在客户端上保留。

领域默认客户端作用域未与现有客户端链接

在迁移期间,内置客户端作用域列表以及 Realm Default Client Scopes 列表被添加到每个领域。但是,现有客户端不会升级,新的客户端作用域不会自动添加到它们。此外,所有协议映射器和角色作用域映射都保留在现有客户端上。在新版本中,当您创建一个新客户端时,它会自动附加领域默认客户端作用域,并且没有任何协议映射器附加到它。我们在迁移期间没有更改现有客户端,因为无法正确检测自定义项,例如,您将为客户端的协议映射器进行自定义。如果您想更新现有客户端(从它们中删除协议映射器并将它们与客户端作用域链接),您需要手动执行此操作。

需要再次确认授权同意

客户端作用域的更改需要重构授权同意。授权同意现在指向客户端作用域,而不是角色或协议映射器。由于此更改,用户先前确认的持久授权同意不再有效,用户需要在迁移后再次确认授权同意页面。

删除了一些配置开关

从角色详情中删除了开关 Scope Param Required。从协议映射器详情中删除了开关 Consent RequiredConsent Text。这些开关已由客户端作用域功能取代。

授权服务的更改

我们增加了对 UMA 2.0 的支持。这个版本的 UMA 规范对如何从服务器获取权限引入了一些重要的更改。

以下是 UMA 2.0 支持引入的主要更改。有关详细信息,请参阅 授权服务指南

授权 API 已删除

在 UMA 2.0(UMA 1.0)之前,客户端应用程序使用授权 API 以 RPT 格式从服务器获取权限。新版本的 UMA 规范已删除了授权 API,Keycloak 也已将其删除。在 UMA 2.0 中,现在可以通过使用特定的授权类型从令牌端点获取 RPT。有关详细信息,请参阅 授权服务指南

Entitlement API 已删除

随着 UMA 2.0 的引入,我们决定利用令牌端点和 UMA 授权类型,以允许从 Keycloak 获取 RPT,并避免使用不同的 API。Entitlement API 提供的功能保持不变,并且仍然可以为一组或多个资源和作用域获取权限,或者在未提供资源或作用域的情况下从服务器获取所有权限。有关详细信息,请参阅 授权服务指南

UMA Discovery 端点的更改

UMA Discovery 文档已更改,请参阅 授权服务指南 了解详细信息。

Keycloak 授权 JavaScript 适配器的更改

Keycloak 授权 JavaScript 适配器 (keycloak-authz.js) 已更改,以符合 UMA 2.0 引入的更改,同时保持与以前相同的行为。主要的更改是如何调用 authorizationentitlement 方法,现在它们期望一个特定的对象类型来表示授权请求。这个新的对象类型通过支持 UMA 授权类型支持的不同参数,为如何从服务器获取权限提供了更大的灵活性。

One of the main changes introduced by this release is that you are no longer required to exchange access tokens with RPTs in
order to access resources protected by a resource server (when not using UMA). Depending on how the policy enforcer is configured on the resource server side, you can just send regular
access tokens as a bearer token and permissions will still be enforced.
Keycloak 授权客户端 Java API 的更改

当升级到新版本的 Keycloak 授权客户端 Java API 时,您会注意到一些表示类已移动到 org.keycloak:keycloak-core 中的不同包。

迁移到 3.4.2

在 OpenID Connect 身份验证响应中添加了 session_state 参数

OpenID Connect 会话管理规范要求参数 session_state 出现在 OpenID Connect 身份验证响应中。

在之前的版本中,我们没有这个参数,但现在 Keycloak 默认添加了这个参数,这是规范要求的。

然而,一些 OpenID Connect / OAuth2 适配器,特别是较旧的 Keycloak 适配器,可能无法处理这个新参数。

例如,在成功对客户端应用程序进行身份验证后,该参数将始终出现在浏览器 URL 中。在这些情况下,禁用将 session_state 参数添加到身份验证响应可能很有用。这可以在 Keycloak 管理控制台中为特定客户端完成,在客户端详细信息中,在 OpenID Connect Compatibility Modes 部分中,如 与旧适配器的兼容性 中所述。存在专用的 Exclude Session State From Authentication Response 开关,可以将其打开以防止将 session_state 参数添加到身份验证响应。

参数 session_state 在 3.4.2 中添加,但是开关 Exclude Session State From Authentication Response 在 4.0.0.Beta1 中添加。如果您的 Keycloak 服务器版本为 3.4.2 或 3.4.3,并且您遇到 session_state 参数的问题,您需要将服务器升级到 4.0.0.Beta1 或更高版本。

迁移到 3.2.0

新的密码哈希算法

我们添加了两种新的密码哈希算法(pbkdf2-sha256 和 pbkdf2-sha512)。新的领域将使用 pbkdf2-sha256 哈希算法,迭代次数为 27500 次。由于 pbkdf2-sha256 比 pbkdf2 稍快,因此迭代次数从 20000 次增加到 27500 次。

如果密码策略包含哈希算法(未指定)和迭代次数(20000)的默认值,则现有领域将被升级。如果您更改了哈希迭代次数,如果您想使用更安全的哈希算法,则需要手动更改为 pbkdf2-sha256。

ID 令牌需要 scope=openid

OpenID Connect 规范要求在初始授权请求中使用带有值 openid 的参数 scope。因此,在 Keycloak 2.1.0 中,我们更改了适配器以在重定向 URI 中使用 scope=openid 到 Keycloak。现在我们也更改了服务器部分,只有当真正使用 scope=openid 时,ID 令牌才会发送到应用程序。如果未使用,则将跳过 ID 令牌,并且只会将访问令牌和刷新令牌发送到应用程序。这也允许您有目的地省略 ID 令牌的生成 - 例如,为了空间或性能目的。

直接授权(OAuth2 资源所有者密码凭据授权)和服务帐户登录(OAuth2 客户端凭据授权)现在默认情况下也不使用 ID 令牌。您需要显式添加 scope=openid 参数才能包含 ID 令牌。

身份验证会话和操作令牌

我们正在努力支持多数据中心。作为初始步骤,我们引入了身份验证会话和操作令牌。身份验证会话取代了先前版本中使用的客户端会话。操作令牌目前特别用于身份验证器或 requiredActionProvider 需要向用户发送电子邮件并要求用户单击电子邮件中的链接的场景。

以下是与此相关的具体更改,可能会影响您的迁移。

与此相关的第一个更改是在 standalone.xmlstandalone-ha.xml 中引入新的 Infinispan 缓存 authenticationSessionsactionTokens。如果您使用我们的迁移 CLI,则无需过多担心,因为您的 standalone(-ha).xml 文件将自动迁移。

第二个更改是更改了身份验证 SPI 中某些方法的签名。如果您使用自定义 AuthenticatorRequiredActionProvider,这可能会影响您。类 AuthenticationFlowContextRequiredActionContext 现在允许检索身份验证会话而不是客户端会话。

我们还添加了一些对粘性会话的初始支持。如果您不想受其影响并希望获得更好的性能,您可能需要更改您的负载均衡器/代理服务器并对其进行配置。路由被添加到新的 AUTH_SESSION_ID cookie。更多信息请参阅集群文档。

另一个更改是,token.getClientSession() 已被删除。例如,如果您正在使用客户端发起的身份代理链接功能,这可能会影响您。

ScriptBasedAuthenticator 更改了绑定名称,从 clientSession 更改为 authenticationSession,因此如果您正在使用此身份验证器,则需要更新您的脚本。

最后,我们向管理控制台添加了一些新的超时设置。这允许您例如为管理员和用户自身触发的电子邮件操作指定不同的超时时间。

迁移到 2.5.1

旧离线令牌的迁移

如果您从 2.2.0 或更早版本迁移,并且您使用了离线令牌,则您的离线令牌在令牌头中没有 KID。我们在 2.3.0 中将 KID 添加到令牌头,并增加了拥有多个领域密钥的能力,因此 Keycloak 能够根据令牌 KID 找到正确的密钥。

对于没有 KID 的离线令牌,Keycloak 2.5.1 将始终使用活动领域密钥来查找用于令牌验证的正确密钥。换句话说,旧离线令牌的迁移将起作用。例如,您的用户在 1.9.8 中请求了离线令牌,然后您从 1.9.8 迁移到 2.5.1,然后您的用户仍然能够在 2.5.1 版本中刷新其旧离线令牌。

但是存在一个限制。一旦您更改了领域活动密钥,用户将无法再刷新旧的离线令牌。因此,您不应更改活动领域密钥,直到所有使用离线令牌的用户都刷新了他们的令牌。显然,新刷新的令牌将在标头中包含 KID,因此在所有用户交换了他们的旧离线令牌后,您可以自由更改活动领域密钥。

迁移到 2.5.0

Infinispan 缓存的更改

standalone.xmlstandalone-ha.xml 配置文件中,Infinispan 子系统中定义的 realms 缓存现在默认具有 10000 条记录的驱逐策略。这与 users 缓存的默认值相同。

此外,authorization 缓存现在默认情况下没有任何驱逐策略。

迁移到 2.4.0

服务器 SPI 分割为服务器 SPI 和服务器 SPI Private

keycloak-server-spi 模块已拆分为 keycloak-server-spi 和 keycloak-server-spi-private。keycloak-server-spi 中的 API 在次要版本之间不会更改,而我们保留在次要版本之间更改 keycloak-server-spi-private 中 API 的权利,并且很可能会更改。

SAML 断言中的密钥加密算法

SAML 断言和文档中的密钥现在使用 RSA-OAEP 加密方案进行加密。如果您想使用加密的断言,请确保服务提供商理解这种加密方案。在不太可能出现 SP 无法处理新方案的情况下,Keycloak 可以设置为在使用系统属性 keycloak.saml.key_trans.rsa_v1.5 设置为 true 启动时使用旧的 RSA-v1.5 加密方案。

Infinispan 缓存 realms 和 users 始终是本地缓存

即使您在集群中使用 Keycloak,在 standalone-ha.xml 的 Infinispan 子系统中定义的 realmsusers 缓存现在始终是本地缓存。存在一个单独的缓存 work,它处理集群节点之间发送无效消息,并告知整个集群底层 realmsusers 缓存中哪些记录应该被无效。

迁移到 2.3.0

分页端点的默认最大结果数

所有支持分页的管理 REST API 端点现在都将默认最大结果数设置为 100。如果您想返回超过 100 个条目,则需要使用 ?max=<RESULTS> 显式指定。

在 2.3.0 版本中,我们添加了对公钥轮换的支持。当管理员在 Keycloak 管理控制台中轮换领域密钥时,客户端适配器将能够识别它并自动从 Keycloak 下载新的公钥。但是,只有当您的适配器中没有带有硬编码公钥的 realm-public-key 选项时,才会进行新的密钥的自动下载。因此,我们不再建议在适配器配置中使用 realm-public-key 选项。

请注意,此选项仍然受支持,但只有当您真的想在适配器配置中拥有硬编码的公钥并且永远不从 Keycloak 下载公钥时,它才可能有用。理论上,这样做的一个原因可能是为了避免中间人攻击,如果您在适配器和 Keycloak 之间有不受信任的网络,但在这种情况下,更好的选择是使用 HTTPS,这将保护适配器和 Keycloak 之间的所有请求。

添加了 Infinispan 缓存 keys

在此版本中,我们向 Infinispan 子系统添加了新的缓存 keys,该缓存在 standalone.xmlstandalone-ha.xml 配置文件中定义。它还定义了一些驱逐和过期策略。此缓存在内部用于缓存服务器信任的实体的外部公钥(身份提供商或使用签名 JWT 进行身份验证的客户端)。

迁移到 2.2.0

databaseSchema 属性 已弃用

JPA 和 Mongo 的 databaseSchema 属性现在都 已弃用 并且 initializeEmptymigrationStrategy 替换initializeEmpty 可以设置为 truefalse,并控制是否应初始化空数据库。migrationStrategy 可以设置为 updatevalidatemanualmanual 仅支持关系数据库,并将创建一个 SQL 文件,其中包含对数据库架构的必要更改。请注意,对于 Oracle 数据库,创建的 SQL 文件包含 Oracle SQL 客户端理解的 SET DEFINE OFF 命令。如果该脚本要被任何其他客户端使用,请将这些行替换为您选择的工具的等效命令,该命令禁用变量扩展,或者如果此类功能不适用,则完全删除它。

客户端的有效重定向 URI 的更改

以下场景受到影响

  • 当在客户端中保存带有查询组件的有效重定向 URI(例如 https://#/auth?foo=bar)时,授权请求中的 redirect_uri 必须与此 URI(或此客户端中的其他注册 URI)完全匹配。

  • 当在客户端中保存不带查询组件的有效重定向 URI 时,redirect_uri 也必须完全匹配。

  • 当注册的有效重定向 URI 中存在查询组件时,不再支持通配符,因此 redirect_uri 也需要与此保存的 URI 完全匹配。

  • 不再允许在注册的有效重定向 URI 中使用片段(如 https://#/auth#fragment)。

从身份提供商中删除了默认身份验证

身份提供商不再具有将其设置为默认身份验证提供商的选项。请转到“身份验证”,选择“Browser 流”,然后配置“Identity Provider Redirector”。它具有设置默认身份提供商的选项。

迁移到 2.0.0

不再支持从 1.0.0.Final 升级

不再支持从 1.0.0.Final 升级。要升级到此版本,请先升级到 1.9.8.Final,然后再升级到 2.0.0。

迁移到 1.9.5

默认密码哈希间隔增加到 20K

新领域的默认密码哈希间隔已增加到 20K(之前为 1)。此更改将对用户进行身份验证时的性能产生影响。例如,使用旧的默认值 (1),哈希密码所需的时间不到 1 毫秒,但使用新的默认值 (20K),相同的操作可能需要 50-100 毫秒。

迁移到 1.9.3

添加用户脚本已重命名

将管理员用户添加到 Keycloak 的脚本已重命名为 add-user-keycloak

迁移到 1.9.2

删除了适配器选项 auth-server-url-for-backend-requests

由于某些场景中使用该选项时出现问题,我们已删除选项 auth-server-url-for-backend-requests。更详细地说,可以从 2 个不同的上下文(内部和外部)访问 Keycloak 服务器,这会导致令牌验证等方面出现问题。

如果您仍然想使用此选项提供的网络优化(避免应用程序通过负载均衡器发送后通道请求,而是将它们直接发送到本地 Keycloak 服务器),您可能需要在主机配置 (DNS) 级别处理它。

迁移到 1.9.0

主题和提供程序目录已移动

我们已将主题和提供程序目录从 standalone/configuration/themesstandalone/configuration/providers 移动到 themesproviders。如果您添加了自定义主题和提供程序,则需要将它们移动到新位置。您还需要更新 keycloak-server.json,因为它已因此而更改。

仅当 Keycloak 开启时,适配器子系统才引入依赖项

以前,如果您已将我们的 SAML 或 OIDC Keycloak 子系统适配器安装到 WildFly 或 JBoss EAP 中,我们将自动将 Keycloak 客户端 jar 包含到每个应用程序中,无论您是否正在使用 Keycloak。现在,只有当您为该适配器开启 Keycloak 身份验证(通过子系统或 web.xml 中的 auth-method)时,这些库才会被添加到您的部署中。

客户端注册服务端点已移动

客户端注册服务端点已从 {realm-name}/clients 移动到 {realm-name}/clients-registrations

身份验证响应中的会话状态参数已重命名

在 OpenID Connect 身份验证响应中,我们曾经将会话状态作为 session-state 返回,这根据规范是不正确的,并且已重命名为 session_state

已弃用的 OpenID Connect 端点

在 1.2 中,我们弃用了一些与 OpenID Connect 规范不一致的端点,这些端点现在已被删除。这也适用于验证令牌端点,该端点已在 1.8 中被新的内省端点取代。

主题模板的更新

template.ftl 中的反馈已移动,格式略有更改。

模块和源代码重组

我们的大部分模块和源代码已合并到两个 Maven 模块中:keycloak-server-spi 和 keycloak-services。SPI 接口位于 server-spi 中,实现位于 keycloak-services 中。所有 JPA 依赖模块都已合并到 keycloak-model-jpa 下。Mongo 和 Infinispan 也同样如此,分别位于模块 keycloak-model-mongo 和 keycloak-model-infinispan 下。

对于适配器,登录后会话 ID 已更改

为了堵塞安全攻击媒介,对于支持它的平台(Tomcat 8、Undertow/WildFly),Keycloak OIDC 和 SAML 适配器将在登录后更改会话 ID。您可以关闭此行为检查适配器配置开关。

SAML SP 客户端适配器更改

Keycloak SAML SP 客户端适配器现在需要一个特定的端点 /saml 在您的 IDP 中注册。

迁移到 1.8.0

管理员帐户

在以前的版本中,我们附带了一个默认管理员用户和一个默认密码,现在已将其删除。如果您正在全新安装 1.8,则必须首先创建一个管理员用户。

OAuth2 令牌内省

为了更符合 OAuth2 规范,我们添加了一个新的令牌内省端点。新端点可以通过 /realms/{realm-name}/protocols/openid-connect/token/introspect 访问,并且完全基于 RFC-7662

/realms/{realm-name}/protocols/openid-connect/validate 端点现在已弃用,我们强烈建议您尽快迁移到新的内省端点。此更改的原因是 RFC-7662 提供了更标准和安全的内省端点。

新的令牌内省 URL 现在可以从 OpenID Connect 提供商的配置中获取,地址为 /realms/{realm-name}/.well-known/openid-configuration。您将在响应中找到一个名为 token_introspection_endpoint 的声明。只有 confidential clients 允许调用新端点,这些客户端通常充当资源服务器,并查找令牌元数据以执行本地授权检查。

迁移到 1.7.0.CR1

默认情况下,客户端禁用直接访问授权

为了更符合 OpenID Connect 规范,我们在管理控制台中添加到客户端设置页面添加了标志,您可以在其中启用/禁用各种 OpenID Connect/OAuth2 流(标准流、隐式流、直接访问授权、服务帐户)。作为其中的一部分,对于新客户端,我们默认禁用 Direct Access Grants(对应于 OAuth2 Resource Owner Password Credentials Grant)。

从以前版本迁移的客户端,只有在其具有 Direct Grants Only 标志的情况下才启用 Direct Access GrantsDirect Grants Only 标志已删除,因为如果您启用直接访问授权并禁用标准+隐式流,您将获得相同的效果。

我们还为每个领域添加了内置客户端 admin-cli。此客户端启用了 Direct Access Grants。因此,如果您正在使用管理 REST API 或 Keycloak admin-client,您应该更新您的配置以使用 admin-cli 而不是 security-admin-console,因为后者默认情况下不再启用直接访问授权。

“首次登录时更新个人资料”选项已从身份提供商移动到审核个人资料身份验证器

在此版本中,我们添加了 First Broker Login,它允许您指定当新用户通过身份提供商(或社交提供商)登录,但尚不存在链接到社交帐户的 Keycloak 用户时,应执行的确切操作。作为此工作的一部分,我们向身份提供商添加了选项 First Login Flow,您可以在其中指定流程,然后在管理控制台的“Authentication”选项卡下配置此流程。

我们还从身份提供商设置中删除了选项 Update Profile On First Login,并将其移动到 Review Profile 身份验证器的配置中。因此,一旦您指定了应为您的身份提供商使用哪个流程(默认为 First Broker Login 流程),您就可以转到“Authentication”选项卡,选择流程,然后在 Review Profile 身份验证器下配置该选项。

不再支持 web.xml 中的元素 'form-error-page'

web.xml 中的 form-error-page 将不再适用于客户端适配器身份验证错误。您必须为各种 HTTP 错误代码定义 error-page。如果您想捕获和处理适配器错误情况,请参阅文档以获取更多详细信息。

IdentityProviderMapper 更改

接口本身和方法签名没有更改。但是,行为上存在一些更改。我们在此版本中添加了 First Broker Login 流,并且方法 IdentityProviderMapper.importNewUser 现在在 First Broker Login 流完成后调用。因此,如果您想在 Review Profile 页面中提供任何属性,您需要使用方法 preprocessFederatedIdentity 而不是 importNewUser。您可以通过调用 BrokeredIdentityContext.setUserAttribute 来设置任何属性,这将可在 Review profile 页面上使用。

迁移到 1.6.0.Final

刷新令牌不再可重用的选项

旧版本的 Keycloak 允许多次重用刷新令牌。Keycloak 仍然允许这样做,但也提供了一个选项 Revoke refresh token 来禁止它。该选项位于管理控制台的令牌设置下。当使用刷新令牌获取新的访问令牌时,也会包含一个新的刷新令牌。启用该选项后,下次刷新访问令牌时应使用此新刷新令牌。将不可能多次重用旧的刷新令牌。

一些软件包已重命名

我们进行了一些重组并重命名了一些软件包。这主要是关于重命名 util 类的内部软件包。您的应用程序中使用的最重要的类(例如 AccessToken 或 KeycloakSecurityContext)以及 SPI 仍然保持不变。但是,可能存在您会受到影响并且需要更新类导入的轻微可能性。例如,如果您正在使用多租户和 KeycloakConfigResolver,您将受到影响,例如 HttpFacade 类已移动到不同的软件包 - 现在是 org.keycloak.adapters.spi.HttpFacade

持久化用户会话

在此版本中,我们添加了对离线令牌的支持,这意味着我们现在正在将“离线”用户会话持久化到数据库中。如果您不使用离线令牌,则不会为您持久化任何内容,因此您无需担心更多 DB 写入会降低性能。但是,在所有情况下,您都需要更新 standalone/configuration/keycloak-server.json 并添加 userSessionPersister,如下所示

"userSessionPersister": {
    "provider": "jpa"
},

如果您希望将会话持久化到 Mongo 而不是经典的 RDBMS,请使用提供程序 mongo

迁移到 1.5.0.Final

领域和用户缓存提供程序

Infinispan 现在是默认且唯一的领域和用户缓存提供程序。在非集群模式下,使用本地 Infinispan 缓存。我们还删除了自定义的内存缓存和无缓存提供程序。如果您在 keycloak-server.json 中将 realmCache 或 userCache 设置为 mem 或 none,请删除这些设置。由于 Infinispan 是唯一的提供程序,因此不再需要 realmCache 和 userCache 对象,可以将其删除。

使用会话提供程序

Infinispan 现在是默认且唯一的用户会话提供程序。在非集群模式下,使用本地 Infinispan 缓存。我们还删除了 JPA 和 Mongo 用户会话提供程序。如果您在 keycloak-server.json 中将 userSession 设置为 mem、jpa 或 mongo,请删除它。由于 Infinispan 是唯一的提供程序,因此不再需要 userSession 对象,可以将其删除。

对于任何想要提高用户会话持久性的人来说,可以通过配置用户会话缓存,使其拥有多个所有者或使用复制的缓存来实现。也可以将 Infinispan 配置为持久化缓存,尽管这会对性能产生影响。

从注册和帐户管理中删除了联系方式

在默认主题中,我们现在已从注册页面和帐户管理中删除了联系方式。管理控制台现在列出所有用户属性,而不仅仅是特定于联系人的属性。管理控制台还具有向用户添加/删除属性的功能。如果您想添加联系方式,请参考示例中包含的地址主题。

迁移到 1.3.0.Final

Direct Grant API 始终启用

过去,Direct Grant API(或资源所有者密码凭据)默认情况下是禁用的,并且存在在 realm 上启用它的选项。现在 Direct Grant API 始终启用,并且移除了 realm 的启用/禁用选项。

数据库已更改

数据库再次发生了一些更改。请记住在升级之前备份您的数据库。

UserFederationProvider 已更改

UserFederationProvider 接口中存在一些小的更改。当升级到较新版本并升级一些签名已更改的方法时,您可能需要同步您的实现。更改非常小,但为了提高联合的性能是必要的。

WildFly 9.0.0.Final

继上次发布中所做的分发更改之后,Keycloak 的独立下载现在基于 WildFly 9.0.0.Final。这也影响了 overlay,它只能部署到 WildFly 9.0.0.Final 或 JBoss EAP 6.4.0.GA。服务器不再支持 WildFly 8.2.0.Final。

WildFly、JBoss EAP 和 JBoss AS7 适配器

现在有 3 个独立的适配器下载,分别用于 WildFly、JBoss EAP 和 JBoss AS7

  • eap6

  • wf9

  • wf8

  • as7

请确保您下载了正确的版本。

您还需要更新 standalone.xml,因为扩展模块和子系统定义已更改。有关详细信息,请参阅应用程序安全指南

从 1.2.0.Beta1 迁移到 1.2.0.RC1

分发更改

Keycloak 现在提供 3 种下载版本:standalone、overlay 和 demo bundle。standalone 适用于生产环境和非 JEE 开发人员。Overlay 旨在将 Keycloak 添加到现有的 WildFly 8.2 或 EAP 6.4 安装中,主要用于开发。最后,我们有一个 demo(或 dev)bundle,旨在帮助开发人员开始使用 Keycloak。此 bundle 包含一个 WildFly 服务器,其中包含 Keycloak 服务器和适配器。它还包含所有文档和示例。

数据库已更改

此版本再次包含许多数据库更改。其中最大的更改是 Application 和 OAuth 客户端的合并。请记住在升级之前备份您的数据库。

Application 和 OAuth 客户端合并

Application 和 OAuth 客户端现在合并到 Clients 中。管理控制台的 UI 和数据库也已更新。您数据库中的数据应自动更新。先前设置的 Applications 将转换为 Consent required 开关关闭的 Clients,OAuth Clients 将转换为此开关打开的 Clients。

从 1.1.0.Final 迁移到 1.2.0.Beta1

数据库已更改

此版本包含许多数据库更改。请记住在升级之前备份您的数据库。

访问令牌和 ID 令牌中的 iss

访问令牌和 ID 令牌中 iss 声明的值已从 realm name 更改为 realm url。这是 OpenID Connect 规范要求的。如果您正在使用我们的适配器,则无需更改,除非您一直在使用 bearer-only 并且未指定 auth-server-url,现在您必须添加它。如果您正在使用另一个库(或 RSATokenVerifier),则在验证 iss 时需要进行相应的更改。

OpenID Connect 端点

为了符合 OpenID Connect 规范,身份验证和令牌端点已更改为具有单个身份验证端点和单个令牌端点。按照规范,response_typegrant_type 参数用于选择所需的流程。旧端点(/realms/{realm-name}/protocols/openid-connect/login/realms/{realm-name}/protocols/openid-connect/grants/access/realms/{realm-name}/protocols/openid-connect/refresh/realms/{realm-name}/protocols/openid-connect/access/codes)现在已弃用,将在未来版本中删除。

主题更改

主题的布局已更改。目录层次结构过去是 type/name,现在已更改为 name/type。例如,名为 sunrise 的登录主题过去部署到 standalone/configuration/themes/login/sunrise,现在已移动到 standalone/configuration/themes/sunrise/login。此更改是为了更容易将同一主题的不同类型分组到一个文件夹中。

如果您过去以 JAR 形式部署主题,则必须创建自定义主题加载器,这需要 Java 代码。现在已简化为仅需要一个纯文本文件 (META-INF/keycloak-themes.json) 来描述 JAR 中包含的主题。

声明更改

以前,在管理控制台中,应用程序和 OAuth 客户端存在一个专用的 Claims 选项卡。它用于配置哪些属性应进入特定应用程序/客户端的访问令牌。此选项卡已被删除,并替换为更灵活的协议映射器。

您无需担心从先前版本迁移数据库。我们为 RDBMS 和 Mongo 都编写了迁移脚本,这应确保为特定应用程序/客户端配置的声明将转换为相应的协议映射器(尽管备份数据库后再迁移到较新版本仍然更安全)。这同样适用于从先前版本导出的 JSON 表示形式。

社交迁移到身份代理

我们重构了社交提供商 SPI,并将其替换为更灵活的 Identity Brokering SPI。管理控制台中的 Social 选项卡已重命名为 Identity Provider 选项卡。

同样,您无需担心从先前版本迁移数据库,就像声明/协议映射器一样。社交提供商的配置和用户的“社交链接”都将转换为相应的身份提供商。

您唯一需要做的操作是更改特定第三方社交提供商的管理控制台中允许的 Redirect URI。您可以先转到 Keycloak 管理控制台,然后从配置身份提供商的页面复制 Redirect URI。然后,您可以简单地将其粘贴为允许的 Redirect URI 到第三方提供商的管理控制台(例如,Facebook 管理控制台)。

从 1.1.0.Beta1 迁移到 1.1.0.Beta2

  • 适配器现在是单独下载的。它们不包含在 appliance 和 war 分发包中。我们现在有太多适配器了,发行版变得臃肿。

  • org.keycloak.adapters.tomcat7.KeycloakAuthenticatorValve +org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve

  • JavaScript 适配器现在具有 idToken 和 idTokenParsed 属性。如果您使用 idToken 来检索名字、电子邮件等,则需要将其更改为 idTokenParsed。

  • as7-eap-subsystem 和 keycloak-wildfly-subsystem 已合并为一个 keycloak-subsystem。如果您有现有的 standalone.xml 或 domain.xml,则需要编辑文件顶部附近,并将扩展模块名称更改为 org.keycloak.keycloak-subsystem。对于 AS7,扩展模块名称为 org.keycloak.keycloak-as7-subsystem。

  • AS7 不再支持服务器安装。您仍然可以将 AS7 用作应用程序客户端。

从 1.0.x.Final 迁移到 1.1.0.Beta1

  • RealmModel JPA 和 Mongo 存储模式已更改

  • UserSessionModel JPA 和 Mongo 存储模式已更改,因为这些接口已重构

  • 升级您的适配器,旧适配器与 Keycloak 1.1 不兼容。我们错误地解释了 JSON Web Token 和 OIDC ID Token 规范。'aud' 声明必须是客户端 ID,我们过去在那里存储 realm 名称并对其进行验证。

从 1.0 RC-1 迁移到 RC-2

  • 许多 info 级别的日志记录已更改为 debug。此外,realm 默认不再具有 jboss-logging 审计监听器。如果您希望在用户登录、注销、更改密码等时记录日志输出,请通过管理控制台启用 jboss-logging 审计监听器。

从 1.0 Beta 4 迁移到 RC-1

  • 注销 REST API 已重构。注销 URI 上的 GET 请求不再接受 session_state 参数。您必须先登录才能注销会话。您也可以 POST 到注销 REST URI。此操作需要有效的刷新令牌才能执行注销。签名与刷新令牌相同,减去 grant type 表单参数。有关详细信息,请参阅文档。

从 1.0 Beta 1 迁移到 Beta 4

  • LDAP/AD 配置已更改。它不再位于“Settings”页面下。现在它位于用户→联合下。“添加提供商”将显示“ldap”选项。

  • 身份验证 SPI 已被删除并重写。新的 SPI 是 UserFederationProvider,它更灵活。

  • ssl-not-required +ssl-required +all +external +none

  • DB Schema 再次更改。

  • 现在创建的应用程序默认具有完整的作用域。这意味着如果您不需要,则不必配置应用程序的作用域。

  • 用于导入 realm 数据的 JSON 文件格式已更改。现在,角色映射在特定用户的 JSON 记录下可用。

从 1.0 Alpha 4 迁移到 Beta 1

  • DB Schema 已更改。我们已将数据库导出添加到 Beta 1,但没有添加从旧版本导入数据库的功能。这将在未来的版本中支持。

  • 对于除 bearer-only 应用程序之外的所有客户端,您必须至少指定一个重定向 URI。除非您为该应用程序指定了有效的重定向 URI,否则 Keycloak 将不允许您登录。

  • Direct Grant API +ON

  • standalone/configuration/keycloak-server.json

  • JavaScript 适配器

  • 会话超时

从 1.0 Alpha 2 迁移到 Alpha 3

  • SkeletonKeyToken、SkeletonKeyScope、SkeletonKeyPrincipal 和 SkeletonKeySession 已重命名为:AccessToken、AccessScope、KeycloakPrincipal 和 KeycloakAuthenticatedSession。

  • ServletOAuthClient.getBearerToken() 方法签名已更改。现在它返回 AccessTokenResponse,以便您也可以获取刷新令牌。

  • 适配器现在在每次请求时检查访问令牌过期时间。如果令牌已过期,它们将尝试使用已保存的刷新令牌在身份验证服务器上调用刷新。

  • AccessToken 中的 Subject 已更改为用户 ID。

从 1.0 Alpha 1 迁移到 Alpha 2

  • DB Schema 已更改。在 Alpha 2 中,我们还没有任何数据迁移实用程序。

  • JBoss 和 WildFly 适配器现在通过 WildFly 子系统安装。请查看适配器安装文档。现在需要编辑 standalone.xml。

  • 引入了一种新的凭据类型“secret”。与其他凭据类型不同,它以明文形式存储在数据库中,并且可以在管理控制台中查看。

  • 不再需要应用程序和 OAuth 客户端凭据。这些客户端类型现在被硬编码为使用“secret”凭据类型。

  • 由于应用程序和 OAuth 客户端的“secret”凭据更改,您必须更新 keycloak.json 配置文件,并在管理控制台中的应用程序或 OAuth 客户端凭据选项卡中重新生成 secret。

升级 Keycloak 服务器

您需要在升级适配器之前升级服务器。

升级准备

在升级服务器之前,请执行以下步骤。

步骤
  1. 关闭 Keycloak。

  2. 备份旧安装,例如配置、主题等。

  3. 如果启用了 XA 事务,请处理任何打开的事务并删除 data/transaction-logs/ 事务目录。

  4. 使用关系数据库文档中的说明备份数据库。

    升级服务器后,数据库将不再与旧服务器兼容。如果您需要还原升级,请先还原旧安装,然后从备份副本还原数据库。

如果您的当前设置中禁用了 persistent-user-sessions 功能并升级了服务器,则除脱机用户会话外,所有用户会话都将丢失。拥有这些会话的用户将必须重新登录。请注意,在 26.0.0 之前的 Keycloak 服务器版本中,persistent-user-sessions 功能默认情况下处于禁用状态。

有关暴力破解检测和当前正在进行的身份验证流程的失败登录信息仅存储在内部缓存中,这些缓存在 Keycloak 关闭时会被清除。当前正在进行身份验证、更改密码或重置密码的用户需要在 Keycloak 启动并再次运行后重新启动身份验证流程。

下载 Keycloak 服务器

准备好升级后,您可以下载服务器。

步骤
  1. 从 Keycloak 网站下载并解压 keycloak-26.2.0.zip

    解压此文件后,您应该有一个名为 keycloak-26.2.0 的目录。

  2. 将此目录移动到所需位置。

  3. conf/providers/themes/ 从旧安装复制到新安装。

迁移数据库

Keycloak 可以自动迁移数据库模式,或者您可以选择手动执行。默认情况下,当您首次启动新安装时,数据库会自动迁移。

自动关系数据库迁移

要执行自动迁移,请启动连接到所需数据库的服务器。如果新服务器版本的数据库模式已更改,则迁移会自动开始,除非数据库记录过多。

例如,在具有数百万条记录的表上创建索引可能非常耗时,并可能导致严重的服务中断。因此,自动迁移存在 300000 条记录的阈值。如果记录数超过此阈值,则不会创建索引。相反,您会在服务器日志中找到警告,其中包含您可以手动应用的 SQL 命令。

要更改阈值,请为 connections-liquibase 提供程序设置 index-creation-threshold 属性值

kc.[sh|bat] start --spi-connections-liquibase-quarkus-index-creation-threshold=300000

手动关系数据库迁移

要启用数据库模式的手动升级,请为默认的 connections-jpa 提供程序将 migration-strategy 属性值设置为“manual”

kc.[sh|bat] start --spi-connections-jpa-quarkus-migration-strategy=manual

当您使用此配置启动服务器时,服务器会检查数据库是否需要迁移。所需的更改将写入 bin/keycloak-database-update.sql SQL 文件,您可以查看并手动针对数据库运行该文件。

要更改导出的 SQL 文件的路径和名称,请为默认的 connections-jpa 提供程序设置 migration-export 属性

kc.[sh|bat] start --spi-connections-jpa-quarkus-migration-export=<path>/<file.sql>

有关如何将此文件应用于数据库的更多详细信息,请参阅关系数据库的文档。将更改写入文件后,服务器将退出。

迁移主题

如果您创建了自定义主题,则必须将这些主题迁移到新服务器。此外,对内置主题的任何更改可能也需要在您的自定义主题中反映出来,具体取决于您自定义的方面。

步骤
  1. 将您的自定义主题从旧服务器的 themes 目录复制到新服务器的 themes 目录。

  2. 使用以下部分迁移模板、消息和样式。

    • 如果您自定义了迁移更改中列出的任何更新的模板,请比较基本主题中的模板,以检查您需要应用的任何更改。

    • 如果您自定义了消息,则可能需要更改键或值,或添加其他消息。

    • 如果您自定义了任何样式并且您正在扩展 Keycloak 主题,请查看对样式的更改。如果您正在扩展基本主题,则可以跳过此步骤。

迁移模板

如果您自定义了任何模板,请查看新版本以决定是否更新您的自定义模板。如果您进行了细微的更改,则可以将更新后的模板与您的自定义模板进行比较。但是,如果您进行了许多更改,请考虑将新模板与您的自定义模板进行比较。此比较将向您显示您需要进行的更改。

您可以使用 diff 工具来比较模板。以下屏幕截图比较了登录主题中的 info.ftl 模板和一个示例自定义主题

登录主题模板的更新版本与自定义登录主题模板的比较

Updated version of a Login theme template versus a custom Login theme template

此比较表明,第一个更改 (Hello world!!) 是自定义,而第二个更改 (if pageRedirectUri) 是对基本主题的更改。通过将第二个更改复制到您的自定义模板,您已成功更新了您的自定义模板。

在另一种方法中,以下屏幕截图比较了旧安装中的 info.ftl 模板与新安装中更新的 info.ftl 模板

旧安装中的登录主题模板与更新后的登录主题模板的比较

Login theme template from the old installation versus the updated Login theme template

此比较显示了基本模板中已更改的内容。然后,您可以手动将相同的更改应用到您的修改后的模板。由于此方法更复杂,因此仅在第一种方法不可行时才使用此方法。

迁移消息

如果您添加了对另一种语言的支持,则需要应用上面列出的所有更改。如果您没有添加对另一种语言的支持,则可能不需要进行任何更改。只有在您更改了主题中受影响的消息时,才需要进行更改。

步骤
  1. 对于添加的值,请查看基本主题中消息的值,以确定是否需要自定义该消息。

  2. 对于重命名的键,请在您的自定义主题中重命名该键。

  3. 对于更改的值,请检查基本主题中的值,以确定是否需要对您的自定义主题进行更改。

迁移样式

您可能需要更新您的自定义样式,以反映对内置主题样式所做的更改。考虑使用 diff 工具来比较旧服务器安装和新服务器安装之间样式表的更改。

例如

$ diff KEYCLOAK_HOME_OLD/themes/keycloak/login/resources/css/login.css \
KEYCLOAK_HOME_NEW/themes/keycloak/login/resources/css/login.css

查看更改并确定它们是否影响您的自定义样式。

升级 Keycloak 适配器

升级 Keycloak 服务器后,您可以升级适配器。早期版本的适配器可能与更高版本的 Keycloak 服务器一起使用,但早期版本的 Keycloak 服务器可能无法与更高版本的适配器一起使用。

与旧版本适配器的兼容性

较新版本的 Keycloak 服务器可能与旧版本的适配器一起使用。但是,Keycloak 服务器的一些修复程序可能会破坏与旧版本适配器的兼容性。例如,OpenID Connect 规范的新实现可能与旧客户端适配器版本不匹配。

对于这种情况,您可以使用兼容模式。对于 OpenID Connect 客户端,管理控制台在客户端详细信息页面上包含OpenID Connect 兼容模式。使用此选项,您可以禁用 Keycloak 服务器的一些新方面,以保持与旧客户端适配器的兼容性。有关更多详细信息,请参阅各个开关的工具提示。

升级 EAP 适配器

要升级 WildFly 适配器,请完成以下步骤

步骤
  1. 下载新的适配器归档文件。

  2. 通过删除 WILDFLY_HOME/modules/system/add-ons/keycloak/ 目录来删除之前的适配器模块。

  3. 将下载的归档文件解压缩到 WILDFLY_HOME

升级 JavaScript 适配器

要升级 JavaScript 适配器,请从 NPM 安装最新版本。

步骤
  1. npm install keycloak-js@latest

升级 Node.js 适配器

要升级 Node.js 适配器,请查看 Node.js 适配器文档