Kratos是独立运行的身份服务而非Go SDK,需通过HTTP调用其public API(如/self-service/login/browser)完成认证流程;启用MFA须配置Courier和Identity Schema,并在注册后显式传login_to_session以触发会话创建。

Kratos不是SDK,别试图import它进你的Go项目
Kratos 是一个独立运行的身份服务(HTTP API 服务),不是 Go 库。你不能 go get github.com/ory/kratos 然后在自己代码里调用 NewClient() 来“集成”它——这不是设计意图,强行这么做会绕过它的安全模型、会丢失 session 管理、会破坏 selfservice 流程的原子性。正确做法是让 Kratos 作为后端认证中心,你的应用通过 HTTP 调用它的 public API(如 /self-service/login/browser)完成登录,由 Kratos 全权处理密码校验、MFA 触发、TOTP 验证、session 发放等整条链路。
启用MFA前必须配置Courier和Identity Schema
默认安装的 Kratos 不开箱即用 MFA。两个硬性前置条件缺一不可:
- 在
config.yaml中启用courier:确保courier.smtp或courier.sendgrid配置完整且测试通过(用ory kratos courier test验证),否则绑定 MFA 时无法发送验证邮件或备用码 - 修改
identity.schema.json:在properties下新增"totp_secret"字段(string, nullable),并设"x-ory-kratos-identity-schema": true;否则用户注册后无法存密钥,kratos identity update会因 schema 校验失败而拒绝写入
改完 schema 必须重启 Kratos,且所有已有 identity 需手动补字段(用 kratos identity update --schema-id),否则老用户无法启用 MFA。
前端调用/self-service/flows/registration时必须传login_to_session
这是 Kratos MFA 流程里最隐蔽的坑:如果你的注册流程没显式触发 session 创建,后续登录时 Kratos 就不会检查该用户是否启用了 MFA。关键点在于注册成功后,必须立即用返回的 session 对象(含 identity.id 和 session.id)发起一次 POST /self-service/flows/login/requests/{request_id} 并带上 {"login_to_session": true}。否则即使你在管理后台把用户 totp_enabled 设为 true,Kratos 登录时也当普通用户处理,跳过 TOTP 校验环节。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
立即学习“go语言免费学习笔记(深入)”;
常见错误现象:用户已绑定 Google Authenticator,但登录时只输密码就进了系统,完全没弹 MFA 输入框。
校验TOTP失败?先看Kratos日志里的time.Now().UTC()输出
Kratos 内部用 time.Now().UTC() 计算 TOTP 时间步长,但它不暴露这个值。当用户扫码后输入 6 位码却提示 “invalid code”,90% 是服务端时间未同步——不是 NTP 问题,而是容器或 VM 的 UTC 时区被意外覆盖。实操检查步骤:
- 进 Kratos 容器执行
date -u,确认输出是 UTC 时间(如Tue Jul 1 03:02:15 UTC 2026),不是 CST 或其他本地时区 - 查 Kratos 日志中类似
time="2026-07-01T03:02:15Z" level=info msg="validating totp code"的时间戳,对比用户手机时间(注意:手机必须关“自动设置时区”,手动设为 UTC 或对应时区) - 若偏差超 30 秒,立刻在宿主机运行
timedatectl set-ntp true,容器内挂载/etc/timezone:/etc/timezone:ro并重启 Kratos
别碰 valid_window 参数。Kratos 固定用 ±1 窗口(3 个周期),改配置文件无效;强行 patch 源码会导致 session 状态错乱。

















