GitHub: https://github.com/teamhanko/hanko · 官方文档: https://docs.hanko.io
Hanko 是一个开源的认证与用户管理平台,框架无关、易于集成,遵循隐私优先原则(数据最小化、防钓鱼),支持自托管,也提供全托管的 Hanko Cloud。仓库整体以 AGPL-3.0 开源,其中 elements/ 目录另有授权条款(见仓库 LICENSE)。
Hanko 用一句话概括:一个后端 API + 一组前端组件,即可为自己的应用接入现代登录体验。它把密码、Passkey、邮箱验证码等认证方式的繁琐细节全部封装好,开发者不必自己实现 WebAuthn 与令牌体系。
仓库主要由三大块组成(backend/、frontend/):
| 组件 | 位置 | 作用 |
|---|---|---|
| Hanko backend | backend/ | Go 编写的认证 API:密码、Passkey、邮箱 Passcode、用户与会话管理、JWT 签发 |
| hanko-elements | frontend/elements/ | Web Components,提供开箱即用的登录/注册/个人资料 UI,可用 CSS 定制 |
| hanko-frontend-sdk | frontend/frontend-sdk/ | 浏览器端 JS 客户端,封装与 backend API 的通信 |
其余部分:quickstart/(参考实现示例应用)、deploy/(docker-compose 编排)、e2e/(端到端测试)。文档已迁移到独立仓库 teamhanko/docs。
能力全景(来自官方 README):
最省事的方式是用仓库自带的 quickstart.yaml(含 backend、Postgres、前端组件、示例应用、Mailslurper):
git clone https://github.com/teamhanko/hanko.git cd hanko docker compose -f deploy/docker-compose/quickstart.yaml -p "hanko-quickstart" up --build
启动后访问:
| 地址 | 内容 |
|---|---|
| http://localhost:8888 | 登录/注册演示页(quickstart 应用) |
| http://localhost:8080 | Mailslurper Web UI(捕获发出的 passcode 邮件) |
| http://localhost:8000 | backend Public API(默认端口) |
| http://localhost:8001 | backend Admin API |
| http://localhost:8002 | backend Management API |
也可以直接体验线上样例 https://example.hanko.io 与 https://www.passkeys.io。
不想用 compose 时,可按官方文档顺序手动搭建:数据库 → 配置 → 迁移 → SMTP → 启动。
docker run --name=postgres \ -e POSTGRES_USER=hanko -e POSTGRES_PASSWORD=hanko -e POSTGRES_DB=hanko \ -p 5432:5432 -d postgres
cd backend go generate ./... go build -a -o hanko main.go
database: user: hanko password: hanko host: localhost port: 5432 database: hanko dialect: postgres # 或 mysql secrets: keys: - CHANGE-ME-TO-A-RANDOM-SECRET-AT-LEAST-16-CHARS # 必填,至少 1 个,用于加密签发 JWT 的 JWK service: name: My Authentication Service email_delivery: enabled: true email: from_address: no-reply@example.com from_name: Example App smtp: host: localhost # 本地调试可用 Mailslurper (端口 2500) port: 2500 webauthn: relying_party: id: "example.com" display_name: "Example Project" origins: - "https://example.com" server: public: cors: allow_origins: - "https://example.com"
secrets.keys至少需要 1 个条目,且每条必须是至少 16 字符的随机串;JWK 由该密钥加解密后持久化,并通过/.well-known/jwks.json发布公钥供客户端验签。
./hanko migrate up --config ./config.yaml # 应用数据库迁移 ./hanko serve all --config ./config.yaml # 同时启动 public + admin
编译出的 ./hanko 二进制提供以下子命令;Docker 形态等价于 docker run --mount type=bind,source=<配置绝对路径>,target=/config/config.yaml -p 8000:8000 ghcr.io/teamhanko/hanko:latest <子命令>。
| 命令 | 说明 |
|---|---|
./hanko serve public | 启动 Public API(默认 :8000,配置项 server.public.address) |
./hanko serve admin | 启动 Admin API(默认 :8001,需自备访问管控!) |
./hanko serve management | 启动 Management API(默认 :8002) |
./hanko serve all | 同时启动 public + admin |
./hanko migrate up / ./hanko migrate down | 应用 / 回滚数据库迁移 |
./hanko user import -i users.json | 按 JSON 文件批量导入用户(也支持 -u/--inputUrl) |
./hanko user export | 把用户导出为 JSON 文件 |
./hanko jwt create [user_id] | 签发调试用 JWT |
./hanko jwk create | 生成签名用 JWK |
./hanko config show | 打印当前生效配置 |
./hanko isready | 健康检查 |
./hanko version | 版本号 |
所有命令通常配合
--config <路径>指定配置文件(相对/绝对路径均可)。Admin API 与 Management API 必须部署在受访问管控保护的网络内。
| 配置块 | 关键字段 | 说明 |
|---|---|---|
database | user/password/host/port/database/dialect | 数据库连接;dialect 支持 postgres / mysql |
secrets | keys[] | JWK 加解密密钥,≥16 字符随机串,至少 1 个 |
service | name | 服务名,用于邮件 subject 等 |
email_delivery | enabled、email.from_address、smtp.host/port/user/password | SMTP 发信(passcode、验证、找回密码邮件) |
webauthn | relying_party.id/display_name/origins[] | WebAuthn 依赖方;id 填域名,origins 含协议与端口 |
server.public | cors.allow_origins[]、address | 前端域名白名单与监听地址;* 通配需同时设 unsafe_wildcard_origin_allowed: true |
server.ip | extractor、trusted_proxies[] | 客户端 IP 解析:direct(默认)/ x_forwarded_for / x_real_ip(后两者须配可信代理网段) |
password | enabled、min_password_length | 密码登录开关,默认关闭 |
session | enable_auth_token_header、cookie.secure、lifespan | 跨域场景用 X-Auth-Token 头传 JWT(默认 cookie) |
session.jwt_template | claims | 自定义 JWT 声明,支持 Go text/template + GJSON 读取用户元数据 |
mfa | totp.enabled、security_keys.enabled、optional | 二步验证:TOTP / 安全密钥,可设备信任 |
third_party | providers.*、custom_providers.*、redirect_url | OAuth 社交登录;内置提供方默认禁用,需显式 enabled + client_id/secret |
webhooks | enabled、hooks[].callback/events[] | 事件回调通知 |
audit_log | console_output.enabled、storage.enabled | 审计日志:默认打 STDOUT,可持久化到数据库 |
Web Components 版的接入只需要两步:安装 → register() → 页面放组件。
npm install @teamhanko/hanko-elements # 或 yarn add / pnpm install @teamhanko/hanko-elements
最小可用页面(官方示例):
<hanko-auth></hanko-auth> <script type="module"> import { register } from "https://cdn.jsdelivr.net/npm/@teamhanko/hanko-elements/dist/elements.js"; const { hanko } = await register("https://hanko.yourdomain.com"); hanko.onSessionCreated(() => { window.location.href = "/secured"; // 登录成功后的跳转 }); </script>
register(apiUrl, options) 支持的关键选项:shadow(默认 true,挂 shadow DOM)、injectStyles、enablePasskeys、translations、cookieDomain、cookieSameSite、sessionCheckInterval(毫秒,须 > 3000)。
可用组件:
| 组件 | 用途 |
|---|---|
<hanko-auth> | 登录 + 注册二合一 UI(可 mode="login\|registration" 指定初始流程) |
<hanko-login> / <hanko-registration> | 仅登录 / 仅注册 |
<hanko-profile> | 个人资料管理:邮箱、密码、Passkey、MFA |
<hanko-events> | 不渲染 UI,仅用于绑定会话事件 |
组件公共属性:lang(语言)、nonce(CSP 内联样式)、prefilled-email、prefilled-username 等。UI 定制可通过 CSS Variables / CSS Shadow Parts 完成,无需改组件源码。
自建 UI 时用 JS SDK 直接调用 backend API:
import { Hanko } from "@teamhanko/hanko-frontend-sdk"; const hanko = new Hanko("http://localhost:8000", { timeout: 13000, // 请求超时(ms) cookieName: "hanko", // 会话 cookie 名 localStorageKey: "hanko", // localStorage 前缀 sessionCheckInterval: 30000, // 会话有效性轮询间隔(ms),必须 > 3000 });
会话事件绑定(返回移除监听器的函数):
// 会话创建(登录成功 / 新 JWT 签发),可获得 JWT claims const off = hanko.onSessionCreated((sessionDetail) => { console.info("Session created", sessionDetail.claims); }); // 会话过期或被远端吊销 hanko.onSessionExpired(() => { /* 跳转登录页 */ }); // 登出 hanko.onUserLoggedOut(() => { /* ... */ });
开启并配置回调端点(回调需返回 HTTP 200,否则视为投递失败):
webhooks: enabled: true hooks: - callback: https://example.com/hook events: - user # 订阅父事件,接收全部子事件
每个事件会 POST 一个 JSON:{ "event": "事件名", "token": "<JWT>" },JWT 内含两个自定义声明:evt(事件名)与 data(变更对象全文,可用 secrets.keys 对应的 JWK 解码验签)。
支持的事件(可细分订阅子事件):
| 事件 | 触发时机 |
|---|---|
user | 用户/邮箱的创建、删除、更新(含主邮箱变更) |
user.create / user.delete | 用户创建 / 删除 |
user.login | 用户登录 |
user.update.email.create/delete/primary | 邮箱创建 / 删除 / 设为主邮箱 |
user.update.username.create/delete/update | 用户名的增删改 |
email.send | 邮件发送(或准备发送) |
通过 session.jwt_template.claims 在签发 JWT 时注入自定义声明,模板可访问用户上下文 .User(含 .User.UserID、.User.Email.Address、.User.Username、.User.Metadata.Public/Unsafe 等),元数据用 GJSON 路径语法读取:
session: jwt_template: claims: role: "user" # 静态值 user_email: "{{ .User.Email.Address }}" # 模板字符串 is_verified: "{{ .User.Email.IsVerified }}" # 布尔值 display_name: '{{ .User.Metadata.Public "display_name" }}' # 读公开元数据 scopes: - "read" - "write" - "{{if .User.Email.IsVerified}}admin{{else}}basic{{end}}" # 条件模板
sub、iat、exp、iss、session_id等保留键会被忽略;模板需符合 Go text/template 语法,非法模板会被记录并排除。