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

如何基于Keycloak实现高并发场景下的访客登录?

问题描述

我正在API中用Keycloak实现访客登录功能,操作步骤如下:

  • 创建了一个仅拥有最小权限的访客角色及对应访客用户;
  • 用户选择访客登录时,需提供真实邮箱(比如user1@example.com);
  • API使用访客凭据向Keycloak发起认证请求,同时传递该真实邮箱。

发起认证的请求代码如下:

var authRequestParameters = new KeyValuePair<string, string>[]
{
    new("client_id", "my-client"),
    new("client_secret", "my-secret"),
    new("scope", "openid"),
    new("grant_type", "password"),
    new("username", "guest_user"),
    new("password", "guest_password_XXXXX"),
    new("guest_email", "user1@example.com") // 自定义字段
};

我期望返回的JWT令牌中包含guest_email声明,但实际并未出现:

{
  ---移除多余信息---
  "name": "Guest Guest",
  "guest_email": "user1@example.com" -- 缺失
}

我试过用User Session Note Mappers,但没达到预期;也了解过自定义protocol mappers,但不确定最优实现方式。

注意:同一访客账号会被多用户同时使用,解决方案必须支持高并发,确保会话数据不会互相覆盖,相关信息需存储在令牌层面,而非Keycloak数据库中。

具体问题

  1. 访客登录时,如何在JWT中传递并获取真实邮箱?
  2. 多用户环境下,如何实现无会话数据冲突的方案?
  3. 有没有更好的Keycloak访客登录实现方案?各有哪些优缺点?

解决方案

1. 在JWT中传递并获取真实邮箱

要把自定义的guest_email字段加入JWT,需使用自定义Script Protocol Mapper,确保数据仅存于当前令牌、不写入Keycloak数据库,步骤如下:

  • 登录Keycloak控制台,进入目标Realm → 客户端 → 你的客户端(my-client)→ Mappers标签页;
  • 点击「Create」,选择Script Mapper类型;
  • 配置参数:
    • Name: 例如guest_email_mapper
    • Script Type: Token Mapper
    • Token Type: Access Token(若需ID Token也包含,可新增同配置的Mapper选择ID Token)
    • Script内容:
      // 从当前认证请求中提取自定义参数guest_email
      var guestEmail = session.getContext().getRequest().getFormParam("guest_email");
      if (guestEmail) {
          // 将字段写入Access Token
          accessToken.setClaim("guest_email", guestEmail);
          // 如需写入ID Token,添加此行:
          // idToken.setClaim("guest_email", guestEmail);
      }
      
  • 保存后重新发起认证请求,JWT中即可包含guest_email声明。

User Session Note Mappers不可用的原因:它会把数据存入用户会话,同一访客账号被多人同时登录时,会话数据会被覆盖,不符合高并发要求。而Script Mapper直接从当前请求取参数写入令牌,每个令牌独立存储,无冲突风险。

2. 多用户环境下无会话冲突的实现

核心原则是不共享会话数据,所有访客自定义信息仅存于各自的JWT令牌中,不写入Keycloak的用户会话或用户实体:

  • 采用上述Script Mapper方案,直接从请求参数提取guest_email写入令牌,每个请求生成的令牌独立,不会互相覆盖;
  • 禁止使用修改用户会话或用户属性的操作(如User Session Notes、User Attribute Mappers),这类操作会导致并发访问时的数据冲突;
  • 合理设置Keycloak客户端的会话超时时间,避免旧会话残留,但因我们不依赖会话存储数据,即使会话复用,令牌内的guest_email仍保持独立。

3. 其他Keycloak访客登录方案及优缺点

方案一:一次性临时用户

  • 实现:用户选择访客登录时,API调用Keycloak Admin API动态创建带邮箱、最小权限的临时用户,登录后自动定时删除;
  • 优点:每个访客拥有独立账号,数据隔离性好,完全契合Keycloak原生用户模型;
  • 缺点:需具备Admin API权限,高并发下创建/删除用户存在性能开销,Keycloak用户存储压力大,需额外做过期用户清理。

方案二:Client Credentials Flow + 自定义声明

  • 实现:API使用Client Credentials Flow获取令牌,请求时传递访客邮箱,通过Script Mapper将邮箱写入令牌;
  • 优点:无需创建访客用户,流程简单,高并发友好,令牌数据完全独立;
  • 缺点:无法区分不同访客的会话(需额外添加标识),权限控制仅能基于客户端,无法实现细粒度访客权限区分。

方案三:Authorization Code Flow + 匿名身份

  • 实现:开启Keycloak匿名身份功能,访客无需登录直接获取匿名令牌,再通过API补充邮箱信息到令牌;
  • 优点:无需共享账号,原生支持匿名访问,流程更规范;
  • 缺点:需配置匿名身份提供者,额外的令牌补充步骤增加复杂度,匿名权限配置较繁琐。

当前方案(共享访客账号+Script Mapper)的优缺点:

  • 优点:无需额外用户管理,性能开销小,高并发友好;
  • 缺点:无法区分不同访客的用户级操作(如记录访客行为只能依赖令牌内的邮箱),Keycloak用户登录日志会混杂所有访客记录。

内容的提问来源于stack exchange,提问作者Masood Ahmad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 05:36:18