Keycloak:如何实现邮箱映射、隐藏或别名功能?
实现Keycloak OAuth授权码流程下的真实邮箱隐藏/虚拟邮箱映射
完全可以实现类似苹果的虚拟邮箱功能,在SSO场景下隐藏用户真实邮箱,以下是几种可行的落地方案:
方案1:自定义用户属性+协议映射(快速实现)
这是无需编码的最简方案:
- 在Keycloak管理后台的用户详情页,给每个用户添加自定义属性(比如
virtual_email),填入预先生成的虚拟邮箱(如j24hj21h4@yourdomain.com) - 进入对应客户端的「客户端范围」→「配置」→「添加内置映射器」,选择「用户属性」,配置将
email声明映射到virtual_email属性 - 后续客户端通过OAuth流程获取的ID Token/Access Token中,
email字段将返回虚拟邮箱,而非用户真实邮箱
若需批量生成虚拟邮箱,可通过Keycloak Admin API批量给用户添加virtual_email属性,生成规则可采用用户ID哈希值+自定义域名,保证唯一性。
方案2:自定义Protocol Mapper SPI(动态生成)
如果需要在用户首次登录时自动生成并存储虚拟邮箱,可开发自定义Keycloak协议映射器:
- 编写Java类实现
org.keycloak.protocol.oidc.mappers.OIDCAccessTokenMapper接口,核心逻辑是替换Token中的真实邮箱:public class VirtualEmailMapper implements OIDCAccessTokenMapper { @Override public void transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession, KeycloakSession session, ClientSessionContext clientSessionCtx) { UserModel user = userSession.getUser(); // 读取已生成的虚拟邮箱,不存在则自动生成并存储 String virtualEmail = user.getFirstAttribute("virtual_email"); if (virtualEmail == null) { // 用用户ID哈希生成唯一虚拟邮箱 String hash = Hashing.sha256().hashString(user.getId(), StandardCharsets.UTF_8).toString().substring(0, 8); virtualEmail = hash + "@yourdomain.com"; user.setSingleAttribute("virtual_email", virtualEmail); } // 替换Token中的email字段 token.getOtherClaims().put("email", virtualEmail); } } - 将代码打包成JAR,放到Keycloak的
providers目录下,执行kc.sh build(Windows环境用kc.bat build)重新构建 - 在客户端的「客户端范围」中添加自定义映射器,启用后即可自动处理邮箱替换
方案3:自定义用户存储SPI(完全隔离真实邮箱)
如果真实邮箱存储在外部系统,不希望Keycloak直接存储,可开发自定义用户存储Provider:
- 实现
org.keycloak.storage.UserStorageProvider接口,在getUserByEmail、getUserById等方法中,返回带有虚拟邮箱的用户对象,真实邮箱仅在与外部系统交互时调用 - 这种方式适合企业内部系统托管真实邮箱的场景,完全隔离真实邮箱与SSO流程
关键注意事项
- 权限控制:需在客户端配置中限制用户信息接口(如
/userinfo)的返回字段,确保客户端无法获取真实邮箱 - 邮件转发:若需支持虚拟邮箱接收邮件,需搭建邮件转发服务,将虚拟邮箱的邮件转发至用户真实邮箱
- 唯一性:虚拟邮箱生成规则必须保证全局唯一,避免不同用户生成重复的虚拟邮箱
内容的提问来源于stack exchange,提问作者meikel
相关产品推荐
相关产品推荐

