Keycloak
Keycloak 是一个服务器,而不是一个你嵌入脚本的页面,所以 Caputchin 以一个 Keycloak extension 的形式交付:一个你添加到 Keycloak 的 provider JAR。它在登录、密码重置和注册页面上渲染 Caputchin 组件,并在流程继续之前从 Keycloak 内部核验令牌。复选框组件和游戏都能用。
这个 extension 是开源的。完整参考(每一项配置属性、realm 导出的 JSON、theme 契约,以及一份兼容性矩阵)都在仓库里:github.com/Caputchin/caputchin-keycloak。从新建账户到第一个服务端已核验的会话,预计大约 15 分钟。
适用于 Keycloak 26.x(Quarkus 发行版)。你需要对 Keycloak 部署的访问权限,才能添加 provider JAR 并运行 kc.sh build,还需要你要保护的那个 realm 的管理员账户。
1. 创建一个站点密钥
在 caputchin.com/login 登录(首次登录会创建账户),打开你的 个人 团队,点击 创建站点密钥,用你的 Keycloak realm 名给它命名,然后点击 创建。把两个值都复制下来:
- 公钥(
cpt_pub_...), - 密钥(
cpt_sec_...)。它只显示一次。
创建你的账户和第一个站点密钥 会带你走一遍相同的界面,讲得更详细。
2. 安装这个 extension
从 最新发布版 下载 caputchin-keycloak.jar,把它复制到 Keycloak 的 providers/ 目录,然后重新构建:
cp caputchin-keycloak.jar "$KEYCLOAK_HOME/providers/"
"$KEYCLOAK_HOME/bin/kc.sh" build
"$KEYCLOAK_HOME/bin/kc.sh" start --optimized要让 Keycloak 发现这些 provider,kc.sh build 是必需的。在容器镜像里,复制 JAR 并在镜像中运行构建:
FROM quay.io/keycloak/keycloak:26.4
COPY caputchin-keycloak.jar /opt/keycloak/providers/
RUN /opt/keycloak/bin/kc.sh build如果想改为从源码构建 JAR,见 仓库的安装指南。
3. 把密钥交给 Keycloak
别把密钥放进 realm 配置:把它设为 Keycloak 服务器上的一个环境变量,例如 CAPUTCHIN_SECRET,然后重启 Keycloak。在第 5 步里你只填这个变量的名字。字面值的密钥或 ${vault.*} 引用也可以;见 仓库的配置指南。
4. 挑选组件如何渲染
有两种方式,而且你按 realm 来选。
开箱即用:自带的 theme
JAR 自带一个 caputchin 登录 theme。在 Admin Console 里打开你的 realm,进入 Realm settings → Themes,把 Login theme 设为 caputchin,然后点击 Save。组件就会在登录、重置和注册页面上渲染,无需编辑模板。如果你用的是原装的 Keycloak 登录,这是最快的路子。
无头:你自己的 theme 来渲染组件
如果你出一个自定义登录 theme(例如一个 Keycloakify 的 React theme),那就保留你的 theme,让这个 extension 以无头方式运行。它把组件配置暴露进页面上下文并校验令牌;你的 theme 渲染 <caputchin-widget>(或 <caputchin-game>)元素。令牌字段是 caputchin-token。完整的属性契约和一个 Keycloakify 示例在 仓库的 theme 指南 里。
5. 把它绑定到登录流程
Keycloak 不会就地更改某个步骤的 authenticator,所以你要把 Caputchin 步骤添加到流程的一个副本里,再删掉原来的步骤。
-
进入 Authentication。在 browser 流程上打开菜单(⋮),点击 Duplicate,给副本命名(例如
browser caputchin),然后点击 Duplicate。 -
在副本里找到 forms 子流程。点击它的 +(Add)按钮,选择 Add execution,选中 Caputchin Username Password Form,然后点击 Add。
-
把新步骤拖到 forms 子流程的最上面,放在 Conditional 2FA 子流程之上,让它在旧步骤原来的位置运行。它的要求是 Required。
-
从 forms 子流程中删除原来的 Username Password Form 步骤。
-
点击 Caputchin 步骤上的齿轮(Settings),填写:
- Alias:任意名字,例如
caputchin-login。 - Site key:你的公钥(
cpt_pub_...),这是唯一发送到浏览器的值。 - Secret key env var:第 3 步里的变量名,例如
CAPUTCHIN_SECRET。
然后点击 Save。其余字段都有可用的默认值:Widget mode 为
checkbox(或invisible、game),Locale 为kc(跟随 realm 的 locale),Fail closed 为开启,这样核验服务中断时会拦下登录,而不是放行。 - Alias:任意名字,例如
-
打开流程的 Action 菜单,点击 Bind flow,保留 Browser flow,然后点击 Save。
挑战渲染在与凭据相同的页面上,而不是作为一个单独的步骤。在默认设置下,检查会在用户点击 Sign In 时运行。
密码重置和注册
同样的做法也能保护另外两个表单:
| 流程 | 添加这个步骤 | 替换 |
|---|---|---|
| Reset credentials | Caputchin Reset Credential - Choose User | Choose User |
| Registration | Caputchin,放在注册表单子流程里,设为 Required | (与 Registration User Creation 并列添加) |
每个 Caputchin 步骤都有自己的设置(齿轮),所以要在每一个上都填写站点密钥和密钥变量。不要给 direct grant 流程添加挑战:那里没有浏览器,所以那会弄坏 API 令牌请求。仓库里的 绑定到流程 以 realm 导出 JSON 的形式展示了同样的设置。
更丰富的外观(哪个游戏、皮肤、品牌)只在 Caputchin 仪表盘 里就站点密钥本身设一次,所以你不必在 Keycloak 里重复。
6. 检查 Content Security Policy
Keycloak 默认的登录 Content Security Policy(在 Realm settings → Security defenses → Headers 下)是 frame-src 'self'; frame-ancestors 'self'; object-src 'none';。它限制的是框架,而不是脚本或连接,而游戏运行在一个 srcdoc 框架里,所以复选框、隐形组件和游戏都能在它不变的情况下正常工作。
如果你自己设了更严格的策略,就从 仓库的 CSP 指南 里的那份开始。script-src 指令同样作用于 Keycloak 自己的内联脚本,所以每次改动之后都要测试登录页面和 Account Console。
服务端核验(Keycloak 到验证主机)是一次服务器到服务器的调用,不受浏览器策略影响。
7. 确认第一个服务端已核验的会话
- 在隐私窗口里打开你应用的登录(或 realm 的登录页面)。
- 用一个测试用户登录。组件会在你点击 Sign In 时运行,然后 Keycloak 让你登录。
- 在 Caputchin 仪表盘 里,打开你的团队并点击你的站点密钥。刷新统计数据。
服务端已核验 现在至少显示 1:Keycloak 已向 Caputchin 确认了一个令牌。这就是你的第一个已核验会话。如果登录页面显示 "Verification failed. Please complete the check and try again." 而 服务端已核验 停在 0,说明令牌根本没有到达 Keycloak:在浏览器控制台里查找 Content Security Policy 错误(第 6 步)。如果 客户端已完成 增加了但登录仍然失败,检查第 3 步的密钥变量是否已在服务器上设置。统计与会话 解释了每一个数字。
在本地试一试
仓库包含一个一条命令的本地 Keycloak(e2e/),它接到一个本地 Caputchin 栈上,让你在部署前把三个设了关的流程都点一遍。见 仓库 README。