You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Keycloak 18.0.0+版本自定义用户身份提供商的非legacy实现方案咨询

Keycloak 18.0.0+版本自定义用户身份提供商的非legacy实现方案咨询

嗨,针对你升级Keycloak到21.0.0后不想依赖legacy包实现自定义用户身份集成的需求,我给你梳理下官方推荐的两种非legacy方案,你可以根据实际场景选择:

一、针对用户联邦场景(从外部数据源拉取/同步用户):使用拆分后的用户存储SPI

Keycloak 18+把原来单一的UserStorageProvider拆分成了更细粒度的SPI接口,这些接口都在org.keycloak.storage.user包下,完全不属于legacy范畴。你可以按需实现对应的核心接口:

  • 仅需根据用户名/邮箱/ID查找用户:实现UserLookupProvider
  • 需要支持用户列表查询(分页、过滤):实现UserQueryProvider
  • 需要支持用户创建/更新/删除:实现UserRegistrationProvider
  • 处理用户凭证(密码、OTP等):实现UserCredentialManagerProvider

简单实现示例

  1. 实现UserLookupProvider核心逻辑:
public class CustomUserLookupProvider implements UserLookupProvider {
    private final KeycloakSession session;
    private final ComponentModel model;

    // 构造方法注入会话和配置模型
    public CustomUserLookupProvider(KeycloakSession session, ComponentModel model) {
        this.session = session;
        this.model = model;
    }

    @Override
    public UserModel getUserByUsername(String username, RealmModel realm) {
        // 替换为你的自定义数据源查询逻辑,比如从数据库/API拉取用户
        UserModel user = session.userLocalStorage().addUser(realm, username);
        user.setEmail(username + "@yourdomain.com");
        user.setFirstName("Custom");
        user.setLastName("User");
        return user;
    }

    @Override
    public UserModel getUserByEmail(String email, RealmModel realm) {
        // 实现邮箱查找逻辑
        return null;
    }

    @Override
    public UserModel getUserById(String id, RealmModel realm) {
        // 实现ID查找逻辑
        return null;
    }
}
  1. 实现对应的工厂类(用于注册和创建Provider实例):
public class CustomUserLookupProviderFactory implements UserStorageProviderFactory<CustomUserLookupProvider> {
    @Override
    public CustomUserLookupProvider create(KeycloakSession session, ComponentModel model) {
        return new CustomUserLookupProvider(session, model);
    }

    // 定义Provider的唯一ID,后台配置时会显示
    @Override
    public String getId() {
        return "custom-user-lookup-provider";
    }

    // 后台配置时显示的帮助文本
    @Override
    public String getHelpText() {
        return "自定义用户查找Provider,从外部数据源拉取用户信息";
    }

    // 可选:添加配置项,比如数据源地址、认证信息等
    @Override
    public List<ProviderConfigProperty> getConfigProperties() {
        List<ProviderConfigProperty> properties = new ArrayList<>();
        properties.add(new ProviderConfigProperty(
            "data-source-url", "数据源地址", "外部用户数据源的API地址或JDBC URL",
            ProviderConfigProperty.STRING_TYPE, null
        ));
        return properties;
    }
}
  1. 注册Provider:在项目的META-INF/services目录下创建org.keycloak.storage.UserStorageProviderFactory文件,写入你的工厂类全限定名,比如:
com.yourcompany.keycloak.provider.CustomUserLookupProviderFactory

完成后,你就能在Keycloak后台的User Federation菜单里找到这个自定义Provider,配置后即可使用。

二、针对身份认证集成场景(对接外部SSO/身份系统):使用Identity Provider SPI

如果你的需求是让用户通过外部自定义身份系统登录Keycloak(比如企业内部的SSO),更推荐使用Keycloak的Identity Provider SPI,这是完全独立于legacy的方案,核心接口在org.keycloak.broker.provider包下。

核心步骤:

  • 实现IdentityProvider接口,或者继承抽象类AbstractIdentityProvider(简化开发)
  • 实现IdentityProviderFactory来创建Provider实例,并注册到META-INF/services/org.keycloak.broker.provider.IdentityProviderFactory

这种方案的优势是完全贴合Keycloak的身份认证流程,支持OAuth2、SAML之外的自定义认证协议,不需要处理用户存储的细节,只需要负责身份断言的转换。

总结

  • 若要从外部数据源拉取/管理用户:选择拆分后的用户存储SPI,避免使用legacy包的UserStorageProvider
  • 若要对接外部身份认证系统:选择Identity Provider SPI,这是官方推荐的身份集成方案

备注:内容来源于stack exchange,提问作者Djordje

火山引擎 最新活动