You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Keycloak用户添加基于邮箱MD5哈希的程序化自定义字段

实现Keycloak用户创建后自动添加邮箱MD5哈希自定义字段的内置方案

完全可以通过Keycloak的内置扩展能力实现,无需开发包装器,下面提供两种可行的内置方案:

方案一:使用脚本监听器(轻量化,无需编译代码)

这是最快的实现方式,通过Keycloak的脚本扩展能力编写事件监听逻辑:

  1. 提前配置自定义用户属性
    进入目标Realm的「User Profile」设置,添加一个名为email_md5的自定义属性(如果Keycloak版本默认允许自由添加用户属性,这一步可以跳过)。

  2. 创建用户注册事件脚本监听器

    • 进入Realm的「Events」→「Listeners」页面,点击「Add Listener」,选择类型为script
    • 在脚本编辑框中输入以下Groovy代码,监听用户注册事件并生成MD5哈希:
      import org.keycloak.events.EventType
      import org.keycloak.models.UserModel
      import java.security.MessageDigest
      import java.math.BigInteger
      
      class EmailMD5Listener implements EventListenerProvider {
          private final KeycloakSession session
      
          EmailMD5Listener(KeycloakSession session) {
              this.session = session
          }
      
          @Override
          void onEvent(Event event) {
              if (EventType.REGISTER == event.getType()) {
                  UserModel user = session.users().getUserById(event.userId, session.context.realm)
                  if (user != null && user.email != null) {
                      // 统一邮箱格式(小写+去空格)避免哈希不一致
                      String normalizedEmail = user.email.toLowerCase().trim()
                      // 计算MD5哈希
                      MessageDigest md = MessageDigest.getInstance("MD5")
                      byte[] hashBytes = md.digest(normalizedEmail.getBytes())
                      String md5Hash = new BigInteger(1, hashBytes).toString(16).padLeft(32, '0')
                      // 设置自定义属性
                      user.setSingleAttribute("email_md5", md5Hash)
                  }
              }
          }
      
          @Override
          void onEvent(AdminEvent event, boolean includeRepresentation) {}
      
          @Override
          void close() {}
      }
      
    • 保存并启用该监听器。
  3. 验证效果
    创建新用户,查看该用户的「Attributes」标签页,会自动生成email_md5字段,值为邮箱的MD5哈希。

注意:如果Keycloak默认禁用了脚本支持,需要在配置文件中启用:

  • 对于standalone模式,在standalone.xml中添加/修改:<spi name="scripting"><default-provider>javascript</default-provider><provider name="javascript" enabled="true"/></spi>
  • 对于容器化部署,设置环境变量KEYCLOAK_SPI_SCRIPTING_ENABLED=true

方案二:Java SPI扩展(适合复杂逻辑/高性能场景)

如果需要更复杂的业务逻辑或者对性能要求较高,可以开发自定义的Keycloak事件监听器SPI:

  1. 创建Java项目
    基于Keycloak的SPI接口,实现EventListenerProvider和EventListenerProviderFactory:

    import org.keycloak.events.Event;
    import org.keycloak.events.EventListenerProvider;
    import org.keycloak.events.EventListenerProviderFactory;
    import org.keycloak.events.EventType;
    import org.keycloak.models.KeycloakSession;
    import org.keycloak.models.UserModel;
    
    import java.security.MessageDigest;
    import java.math.BigInteger;
    
    public class EmailMD5EventListener implements EventListenerProvider {
        private final KeycloakSession session;
    
        public EmailMD5EventListener(KeycloakSession session) {
            this.session = session;
        }
    
        @Override
        public void onEvent(Event event) {
            if (EventType.REGISTER.equals(event.getType())) {
                UserModel user = session.users().getUserById(event.getUserId(), session.getContext().getRealm());
                if (user != null && user.getEmail() != null) {
                    String normalizedEmail = user.getEmail().toLowerCase().trim();
                    try {
                        MessageDigest md = MessageDigest.getInstance("MD5");
                        byte[] hashBytes = md.digest(normalizedEmail.getBytes());
                        String md5Hash = new BigInteger(1, hashBytes).toString(16).padLeft(32, '0');
                        user.setSingleAttribute("email_md5", md5Hash);
                    } catch (Exception e) {
                        // 处理哈希计算异常
                        e.printStackTrace();
                    }
                }
            }
        }
    
        @Override
        public void onEvent(AdminEvent event, boolean includeRepresentation) {}
    
        @Override
        public void close() {}
    }
    
    // 工厂类
    public class EmailMD5EventListenerFactory implements EventListenerProviderFactory {
        @Override
        public EventListenerProvider create(KeycloakSession session) {
            return new EmailMD5EventListener(session);
        }
    
        @Override
        public void init(org.keycloak.Config.Scope config) {}
    
        @Override
        public void postInit(KeycloakSessionFactory factory) {}
    
        @Override
        public void close() {}
    
        @Override
        public String getId() {
            return "email-md5-listener"; // 监听器唯一标识
        }
    }
    
  2. 打包部署
    将项目打包成JAR文件,放到Keycloak的providers目录下,执行kc.sh build(或对应平台的构建命令)后重启Keycloak。

  3. 启用监听器
    在Realm的「Events」→「Listeners」页面,添加并启用email-md5-listener即可。

额外注意事项

  • MD5哈希是不可逆的,确保业务场景不需要还原邮箱内容
  • 若用户邮箱后续修改,上述方案不会自动更新email_md5字段,如需支持可以添加对UPDATE_EMAIL事件的监听逻辑
  • 自定义属性名称可根据业务需求调整,只需保持代码中的属性名一致即可

内容的提问来源于stack exchange,提问作者Tan Nguyen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 17:11:16