7.6. 配置技术
我们的 PropertyFileUserStorageProvider 示例是一个位拥塞。它被硬编码到提供程序的 jar 中嵌入的属性文件,这并不有用。我们可能希望使此文件的位置可由提供程序的每个实例配置。换句话说,我们可能希望在多个不同的域中多次重复使用此提供程序,并指向完全不同的用户属性文件。我们还将在管理控制台 UI 中执行此配置。
UserStorageProviderFactory 有额外的方法,您可以实现处理提供程序配置的方法。您可以描述您要为每个提供程序配置的变量,Admin Console 会自动呈现一个通用输入页面来收集此配置。实施后,回调方法也会在保存前、首次创建供应商以及更新时验证配置。UserStorageProviderFactory 从 org.keycloak.component.ComponentFactory 接口继承这些方法。
List<ProviderConfigProperty> getConfigProperties();
default
void validateConfiguration(KeycloakSession session, RealmModel realm, ComponentModel model)
throws ComponentValidationException
{
}
default
void onCreate(KeycloakSession session, RealmModel realm, ComponentModel model) {
}
default
void onUpdate(KeycloakSession session, RealmModel realm, ComponentModel model) {
}
ComponentFactory.getConfigProperties () 方法返回 org.keycloak.provider.ProviderConfigProperty 实例列表。这些实例声明呈现和存储提供程序的每个配置变量所需的元数据。
7.6.1. 配置示例 复制链接链接已复制到粘贴板!
我们来扩展 PropertyFileUserStorageProviderFactory 示例,允许您将供应商实例指向磁盘上的特定文件。
PropertyFileUserStorageProviderFactory
public class PropertyFileUserStorageProviderFactory
implements UserStorageProviderFactory<PropertyFileUserStorageProvider> {
protected static final List<ProviderConfigProperty> configMetadata;
static {
configMetadata = ProviderConfigurationBuilder.create()
.property().name("path")
.type(ProviderConfigProperty.STRING_TYPE)
.label("Path")
.defaultValue("${jboss.server.config.dir}/example-users.properties")
.helpText("File path to properties file")
.add().build();
}
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configMetadata;
}
ProviderConfigurationBuilder 类是一个很好的帮助程序类,用于创建配置属性列表。在这里,我们指定一个名为 path 的变量,它是 String 类型。在此提供程序的 Admin Console 配置页面上,此配置变量标记为 Path,默认值为 ${jboss.server.config.dir}/example-users.properties。当您将鼠标悬停在此配置选项的工具提示上时,它会显示帮助文本,文件到属性文件。
接下来,我们需要做的是验证磁盘上是否存在此文件。我们不想在域中启用此提供程序的实例,除非它指向有效的用户属性文件。为此,我们实施 validateConfiguration () 方法。
@Override
public void validateConfiguration(KeycloakSession session, RealmModel realm, ComponentModel config)
throws ComponentValidationException {
String fp = config.getConfig().getFirst("path");
if (fp == null) throw new ComponentValidationException("user property file does not exist");
fp = EnvUtil.replace(fp);
File file = new File(fp);
if (!file.exists()) {
throw new ComponentValidationException("user property file does not exist");
}
}
validateConfiguration () 方法提供 ComponentModel 中的配置变量,以验证磁盘上是否存在该文件。请注意,使用 org.keycloak.common.util.EnvUtil.replace () 方法。通过此方法,包含 ${} 的任何字符串会将该值替换为系统属性值。${jboss.server.config.dir} 字符串对应于服务器的 conf/ 目录,对于本例中非常有用。
接下来,我们需要做的是删除旧的 init () 方法。我们这样做,因为用户属性文件将为每个提供程序实例是唯一的。我们将此逻辑移到 create () 方法。
@Override
public PropertyFileUserStorageProvider create(KeycloakSession session, ComponentModel model) {
String path = model.getConfig().getFirst("path");
Properties props = new Properties();
try {
InputStream is = new FileInputStream(path);
props.load(is);
is.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
return new PropertyFileUserStorageProvider(session, model, props);
}
当然,这种逻辑是效率低下,因为每个事务从磁盘读取整个用户属性文件,但希望以简单的方式演示,如何对配置变量中的 hook 进行 hook。
7.6.2. 在管理门户中配置提供程序 复制链接链接已复制到粘贴板!
现在,在启用了配置时,您可以在 Admin 控制台中配置供应商时设置 path 变量。