keycloak-extension-playground深度解析:用户存储(User Storage)扩展开发详解

keycloak-extension-playground深度解析:用户存储(User Storage)扩展开发详解

【免费下载链接】keycloak-extension-playgroundSimple project environment for creating custom Keycloak extensions项目地址: https://gitcode.com/gh_mirrors/ke/keycloak-extension-playground

keycloak-extension-playground是一个专注于Keycloak扩展开发的开源项目环境,为开发者提供了丰富的用户存储扩展示例。本文将深入探讨如何利用该项目进行用户存储扩展开发,帮助新手快速掌握Keycloak用户存储集成的核心技术。

为什么需要用户存储扩展?

在企业级应用中,用户数据往往存储在多样化的系统中,如LDAP服务器、关系型数据库或其他身份管理系统。Keycloak的用户存储扩展功能允许将这些外部用户数据源无缝集成到Keycloak中,实现统一身份认证和授权。

keycloak-extension-playground提供了多种用户存储扩展实现,包括:

  • LDAP用户存储扩展:custom-ldap-user-storage-provider/src/main/java/com/github/thomasdarimont/keycloak/ldap/CustomLdapUserStorageProvider.java
  • 远程Keycloak联邦存储:remote-keycloak-federation/src/main/java/com/github/thomasdarimont/keycloak/federation/RemoteKeycloakUserStorageProvider.java
  • 轻量级用户存储:flyweight-user-storage-provider-extension/src/main/java/com/github/thomasdarimont/keycloak/userstorage/flyweight/FlyweightAcmeUserStorageProvider.java

用户存储扩展核心接口

Keycloak用户存储扩展开发主要涉及以下核心接口:

UserStorageProvider

所有用户存储扩展的基础接口,定义了生命周期方法:

public interface UserStorageProvider extends Provider { void close(); }

UserLookupProvider

用户查找接口,实现用户的基本查询功能:

public interface UserLookupProvider { UserModel getUserById(String id, RealmModel realm); UserModel getUserByUsername(String username, RealmModel realm); UserModel getUserByEmail(String email, RealmModel realm); }

CredentialInputValidator

凭证验证接口,用于验证用户密码等凭证:

public interface CredentialInputValidator { boolean supportsCredentialType(String credentialType); boolean isConfiguredFor(RealmModel realm, UserModel user, String credentialType); boolean isValid(RealmModel realm, UserModel user, CredentialInput input); }

实战:自定义LDAP用户存储扩展

扩展LDAPStorageProvider

keycloak-extension-playground中的CustomLdapUserStorageProvider展示了如何扩展Keycloak的LDAP存储提供器:

public class CustomLdapUserStorageProvider extends LDAPStorageProvider { @Override public boolean removeUser(RealmModel realm, UserModel user) { // 自定义删除逻辑:禁用用户而非真正删除 user.setEnabled(false); return true; } // 工厂类实现 @AutoService(UserStorageProviderFactory.class) public static class Factory extends LDAPStorageProviderFactory { @Override public String getId() { return "custom-ldap"; } @Override public String getHelpText() { return "Custom LDAP User Store which disables users on remove."; } } }

远程Keycloak用户联邦

RemoteKeycloakUserStorageProvider实现了跨Keycloak实例的用户联邦,允许从远程Keycloak服务器查询和验证用户:

public class RemoteKeycloakUserStorageProvider implements UserStorageProvider, UserLookupProvider, CredentialInputValidator { @Override public UserModel getUserByUsername(String username, RealmModel realm) { // 先检查本地用户 UserModel localUser = session.userLocalStorage().getUserByUsername(realm, username); if (localUser != null) { return localUser; } // 从远程Keycloak查询用户 List<UserRepresentation> users = getRemoteKeycloak().getUserByUsername( componentModel.get("realm"), username, false); if (users == null || users.isEmpty()) { return null; } return toAdapter(realm, users.get(0)); } @Override public boolean isValid(RealmModel realm, UserModel user, CredentialInput credentialInput) { // 通过远程Keycloak验证用户凭证 AccessTokenResponse accessTokenResponse = getRemoteKeycloak().validatePassword( componentModel.get("realm"), componentModel.get("clientId"), componentModel.get("clientSecret"), user.getUsername(), credentialInput.getChallengeResponse(), OAuth2Constants.PASSWORD, "profile email"); return accessTokenResponse != null; } }

轻量级用户存储实现

FlyweightAcmeUserStorageProvider展示了一种轻量级用户存储实现,采用享元模式减少内存占用:

public class FlyweightAcmeUserStorageProvider implements UserStorageProvider, UserLookupProvider, UserQueryProvider, CredentialInputUpdater, CredentialInputValidator { private final AcmeUserRepository repository; @Override public UserModel getUserByUsername(String username, RealmModel realm) { return createAdapter(realm, repository.findUserByUsernameOrEmail(username)); } protected UserModel createAdapter(RealmModel realm, AcmeUser acmeUser) { if (acmeUser == null) { return null; } return new AcmeUserAdapter(session, realm, storageComponentModel, acmeUser); } @Override public boolean isValid(RealmModel realm, UserModel user, CredentialInput input) { if (!supportsCredentialType(input.getType()) || !(input instanceof UserCredentialModel)) { return false; } UserCredentialModel cred = (UserCredentialModel) input; return repository.validateCredentials(user.getUsername(), cred.getValue()); } }

用户存储扩展的配置与使用

配置认证流程

在Keycloak管理控制台中,您需要配置认证流程以使用自定义用户存储提供器。以下是一个典型的浏览器认证流程配置界面:

配置用户存储提供器

为您的用户存储扩展配置必要的参数,如角色名称、客户端ID等:

处理访问控制

用户存储扩展可以与Keycloak的授权机制结合,实现基于角色的访问控制。当用户没有所需角色时,将显示访问被拒绝的错误页面:

如何开始开发

  1. 克隆项目仓库:
git clone https://gitcode.com/gh_mirrors/ke/keycloak-extension-playground
  1. 选择一个用户存储扩展示例作为起点,如:

    • custom-ldap-user-storage-provider
    • remote-keycloak-federation
    • flyweight-user-storage-provider-extension
  2. 根据您的需求修改代码,实现自定义逻辑

  3. 使用Maven构建扩展:

mvn clean install
  1. 将生成的JAR文件部署到Keycloak的standalone/deployments目录

总结

keycloak-extension-playground提供了丰富的用户存储扩展示例,涵盖了从LDAP集成到远程Keycloak联邦的多种场景。通过本文的介绍,您应该对Keycloak用户存储扩展开发有了深入的了解。无论是企业级LDAP集成,还是跨系统用户联邦,Keycloak的用户存储扩展机制都能满足您的需求。

希望本文能帮助您快速掌握Keycloak用户存储扩展开发,如有任何问题,欢迎查阅项目中的示例代码或相关文档。

【免费下载链接】keycloak-extension-playgroundSimple project environment for creating custom Keycloak extensions项目地址: https://gitcode.com/gh_mirrors/ke/keycloak-extension-playground

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考