2.7. 弃用和删除的功能


2.7.1. truststore 弃用

spi-truststore-file jpeg 选项和信任存储相关的选项 https-trust-store114 已被弃用。因此,对信任存储资料使用新的默认位置 conf/truststores,或使用 truststore-paths 选项指定您需要的路径。详情请参阅 为传出请求配置可信证书。

应该使用 tls-hostname-verifier 属性,而不是 spi-truststore-file-hostname-verification-policy 属性。

更改的资料效果是,信任存储供应商总是使用一些证书(至少存在默认的 Java 可信证书)。这个新行为可能会影响红帽构建的 Keycloak 的其他部分。

例如,如果 测试 机构被配置为 Direct 验证,webauthn 注册可能会失败。在以前的版本中,如果 truststore 供应商没有配置传入的证书,则不会验证传入的证书。但是现在,这个验证总是被执行。注册失败,并显示 无效的证书路径 错误,因为 dongle 发送的证书链不被红帽构建的 Keycloak 信任。验证器的证书颁发机构需要存在于信任存储提供程序中,才能正确执行 attestation。

2.7.2. 弃用的 --proxy 选项

--proxy 选项已弃用,并将在以后的发行版本中删除。下表说明了已弃用的选项如何映射到支持的选项。

弃用的用法新用法

kc.sh (没有 代理 选项集)

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 选项不允许同时选择 正向和 x forwarded 值(因为它是 --proxy edge 和 --proxy reencrypt之前的情况)。

警告

使用 proxy 标头选项时,请确保您的反向代理正确设置并分别覆盖 Forwarded 或 X-ForwardedGalaxy 标头。要设置这些标头,请参阅您的反向代理文档。错误配置会将红帽构建的 Keycloak 暴露给安全漏洞。

您还可以使用 Operator 时设置代理标头:

apiVersion: k8s.keycloak.org/v2alpha1
kind: Keycloak
metadata:
  name: example-kc
spec:
  ...
  proxy:
    headers: forwarded|xforwarded
注意

如果没有指定 proxy.headers 字段,Operator 会默认隐式设置 proxy=passthrough 来回退到之前的行为。这会在服务器日志中产生弃用警告。此回退将在以后的发行版本中被删除。

2.7.3. 弃用的离线会话预加载

红帽构建的 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。

2.7.4. 弃用了数据供应商和模型的方法

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

2.7.5. Cookie 的弃用和删除

作为红帽构建的 Keycloak 中重构 Cookie 处理的一部分,有一些对 Cookie 的设置方式的更改:

  • 现在,如果请求通过安全上下文,则所有 Cookie 都会设置 secure 属性
  • WELCOME_STATE_CHECKER cookies 现在设置 SameSite=Strict

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

  • LocaleSelectorProvider.KEYCLOAK_LOCALE 已被弃用,因为 Cookie 现在通过 CookieProvider 管理
  • HttpResponse.setWriteCookiesOnTransactionComplete has been removed
  • HttpCookie 已被弃用,请使用 NewCookie.Builder
  • ServerCookie 已被弃用,请使用 NewCookie.Builder

2.7.6. 为 SAML 加密删除已弃用的模式

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

2.7.7. 重命名模型模块

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

  • org.keycloak:keycloak-model-legacy-private to org.keycloak:keycloak-model-storage-private
  • org.keycloak:keycloak-model-legacy-services to org.keycloak:keycloak-model-storage-services

和 org.keycloak:keycloak-model-legacy 模块已被弃用,并将在 org.keycloak:keycloak-model-storage 模块的下一发行版本中删除。

2.7.8. 删除了 RegistrationProfile 表单操作

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

通过 Admin User API 更新用户属性时,在更新用户属性时,您无法执行部分更新,包括 用户名、电子邮件、firstName 和 lastName 等 root 属性。

2.7.10. 弃用的 auto-build CLI 选项已被删除

auto-build CLI 选项在很长时间内被标记为弃用。在这个发行版本中,它已被完全删除,它不再被支持。

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

2.7.11. 删除选项以修剪事件的详情长度

从这个版本开始,Keycloak 支持 EventEntity details 列的长值。因此,它不再支持修剪事件详情长度 --spi-events-store-jpa-max-detail-length 和 --spi-events-store-jpa-max-field-length 的选项。

2.7.12. 从转换中删除命名空间

如果您编写了自己的翻译或扩展管理员 ui,则需要将它们迁移到此新格式时,我们将所有翻译移到 admin-ui 中的一个文件中。另外,如果您的数据库中有"overrides",则必须从密钥中删除命名空间。有些键只在不同的命名空间中相同,这最明显有助于。在这些情况下,我们使用 帮助 来记录密钥。

如果要使用这个节点脚本来帮助迁移。它将获取所有单个文件并将其放入一个新文件,并负责一些映射:

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
注意

这可能不会进行完整的转换,但非常接近。

Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

關於紅帽

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

让开源更具包容性

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

关于红帽文档

Legal Notice

Theme

© 2026 Red Hat
返回顶部