第 5 章 服务供应商接口(SPI)
Red Hat build of Keycloak 旨在覆盖大多数用例,而无需自定义代码,但我们也希望它可以被自定义。为了实现此红帽构建的 Keycloak,有许多服务提供商接口(SPI),您可以自行实施供应商。
5.1. 实施 SPI
要实施 SPI,您需要实施其 ProviderFactory 和 Provider 接口。您还需要创建服务配置文件。
例如,要实现 Theme Selector SPI,您需要实现 ThemeSelectorProviderFactory 和 ThemeSelectorProvider,并提供文件 META-INF/services/org.keycloak.theme.ThemeSelectorProviderFactory
。
ThemeSelectorProviderFactory 示例:
package org.acme.provider; import ... public class MyThemeSelectorProviderFactory implements ThemeSelectorProviderFactory { @Override public ThemeSelectorProvider create(KeycloakSession session) { return new MyThemeSelectorProvider(session); } @Override public void init(Config.Scope config) { } @Override public void postInit(KeycloakSessionFactory factory) { } @Override public void close() { } @Override public String getId() { return "myThemeSelector"; } }
建议您的供应商工厂实现通过方法 getId ()
返回唯一 id。但是,在 Overriding providers 部分所述,这个规则可能存在一些例外。
红帽构建的 Keycloak 创建一个供应商工厂实例,以便可以存储多个请求的状态。通过调用每个请求的工厂上的 create 来创建供应商实例,因此这些实例应该是轻量级的对象。
ThemeSelectorProvider 示例:
package org.acme.provider; import ... public class MyThemeSelectorProvider implements ThemeSelectorProvider { public MyThemeSelectorProvider(KeycloakSession session) { } @Override public String getThemeName(Theme.Type type) { return "my-theme"; } @Override public void close() { } }
服务配置文件示例(META-INF/services/org.keycloak.theme.ThemeSelectorProviderFactory
):
org.acme.provider.MyThemeSelectorProviderFactory
要配置您的供应商,请参阅配置供应商 章节。
例如,要配置供应商,您可以设置选项,如下所示:
bin/kc.[sh|bat] --spi-theme-selector-my-theme-selector-enabled=true --spi-theme-selector-my-theme-selector-theme=my-theme
然后,您可以在 ProviderFactory
init 方法中检索配置:
public void init(Config.Scope config) { String themeName = config.get("theme"); }
如果需要,您的供应商也可以查找其他供应商。例如:
public class MyThemeSelectorProvider implements ThemeSelectorProvider { private KeycloakSession session; public MyThemeSelectorProvider(KeycloakSession session) { this.session = session; } @Override public String getThemeName(Theme.Type type) { return session.getContext().getRealm().getLoginTheme(); } }
5.1.1. 覆盖内置供应商
如前文所述,建议您使用 ProviderFactory
实现的唯一 ID。但是,同时,覆盖红帽构建的 Keycloak 内置供应商会很有用。推荐方法是带有唯一 ID 的 ProviderFactory 实现,然后为实例设置默认供应商,如 配置提供程序 章节中所述。另一方面,这可能无法始终实现。
例如,当您需要对默认 OpenID Connect 协议进行一些自定义,并希望覆盖默认的 OIDCLoginProtocolFactory
实现的 Keycloak 实现时,您需要保留相同的 providerId。例如,OIDC 协议众所周知的端点,各种因素依赖于开放连接协议工厂的 ID。
在这种情况下,强烈建议您实施自定义实施的方法 order ()
,并确保其顺序高于内置实施。
public class CustomOIDCLoginProtocolFactory extends OIDCLoginProtocolFactory { // Some customizations here @Override public int order() { return 1; } }
如果有多个具有相同供应商 ID 的实现,则红帽构建 Keycloak 运行时只会使用具有最高顺序的那一个。
5.1.2. 在控制台中显示您的 SPI 实施的信息
有时,向红帽构建的 Keycloak 管理员显示有关供应商的额外信息会很有用。您可以显示供应商构建时间信息(例如,当前安装的自定义供应商版本)、提供商的当前配置(例如您的供应商与之通信的远程系统的 url)或一些操作信息(来自您的供应商的远程系统平均响应时间)。红帽构建的 Keycloak 管理控制台提供了 Server Info 页面来显示此类信息。
若要显示您的供应商的信息,最好在 ProviderFactory 中实施 org.keycloak.provider.ServerInfoAware
接口。
ProviderFactory
来自上例的 MyThemeSelectorProviderFactory
的实现示例:
package org.acme.provider; import ... public class MyThemeSelectorProviderFactory implements ThemeSelectorProviderFactory, ServerInfoAwareProviderFactory { ... @Override public Map<String, String> getOperationalInfo() { Map<String, String> ret = new LinkedHashMap<>(); ret.put("theme-name", "my-theme"); return ret; } }