API Key 授权配置¶
从"本地开发无鉴权"升级到"生产可用的 scope + 限额 + 审计"。
概念速览¶
一把 key 一条记录,SHA-256 存在 keys.json(明文只在生成时打印,一次性)。
每把 key 有五类约束:
- scope —— 能调什么接口。
qot:read/acc:read/trade:simulate/trade:real - allowed_markets / allowed_symbols / allowed_trd_sides —— 市场 / 品种 / 方向白名单
- max_order_value / max_daily_value —— 单笔和日累计金额上限
- max_orders_per_minute —— 速率(滑动窗口)
- hours_window —— 时间窗口(本地时区,支持跨午夜
22:00-04:00) - allowed_machines —— 软机器绑定(防 keys.json 整体拷到别的机器)
REST / gRPC / 核心 WS / MCP 四条入口共享同一套 keys.json,你不用在四个地方各配一遍。
1. 安装 futucli¶
和 futu-opend 同一个 tarball / Cargo workspace 产出。
2. 生成一把只读 key¶
输出:
✅ Generated key "research"
plaintext: fc_8a3f2b9c1e5d7a4b8c2f9e1d3a5b7c9f ← 保存这串,别关终端
stored in: /Users/you/.config/futu/keys.json
明文只打一次
keys.json 里只存 SHA-256。明文丢了就丢了,只能 revoke 重生成。
3. 生成一把带额度的交易 key¶
./futucli gen-key \
--id sim-bot \
--scopes qot:read,acc:read,trade:simulate \
--allowed-markets HK,US \
--allowed-trd-sides SELL \
--max-order-value 100000 \
--max-daily-value 500000 \
--max-orders-per-minute 5 \
--hours-window 09:30-16:00 \
--expires 30d
这把 key 只能:
- 模拟环境下下单(trade:simulate,不是 trade:real)
- 只卖不买(--allowed-trd-sides SELL,allowed_trd_sides 白名单)
- 只做港美股
- 单笔 ≤ 10 万,日累计 ≤ 50 万
- 每分钟 ≤ 5 单
- 只在 09:30-16:00 之间能下
- 30 天后自动失效
4. 启动网关指向 keys.json¶
./futu-opend \
--login-account 12345678 --login-pwd 'your_pwd' \
--rest-port 22222 --rest-keys-file ~/.config/futu/keys.json \
--grpc-port 33333 --grpc-keys-file ~/.config/futu/keys.json \
--ws-keys-file ~/.config/futu/keys.json \
--audit-log /var/log/futu-audit.jsonl
启动日志会变:
INFO keys_loaded=2 REST keys file loaded (Bearer auth enabled)
INFO keys_loaded=2 gRPC keys file loaded (Bearer auth enabled)
INFO keys_loaded=2 WS keys file loaded (Bearer/?token auth enabled)
INFO audit JSONL logger enabled (target=futu_audit → file)
5. 用 key 访问各个接口¶
6. 列 / 改 / 吊销 key¶
# 看现在有哪些
./futucli list-keys
# 吊销一把
./futucli revoke-key sim-bot
# 改机器绑定(就地编辑,不换 plaintext)
./futucli bind-key sim-bot --this-machine
./futucli bind-key sim-bot --replace --machines fp_abc123,fp_def456
./futucli bind-key sim-bot --freeze # 临时禁用
./futucli bind-key sim-bot --clear # 解除绑定
热重载
改完 keys.json 不用重启 —— kill -HUP <pid> 就行。REST / gRPC / 核心 WS / MCP 四条入口都支持 SIGHUP 热重载,新 key 秒级生效,吊销的 key 立刻失效。
7. 查审计日志¶
# 最近被拒的请求
jq 'select(.outcome=="reject")' /var/log/futu-audit.jsonl | tail -20
# 某把 key 今天下了多少单
jq 'select(.key_id=="sim-bot" and .endpoint|test("order"))' /var/log/futu-audit.jsonl | wc -l
# 按 reason 统计(DuckDB 也行)
jq -r 'select(.outcome=="reject") | .reason' /var/log/futu-audit.jsonl \
| sort | uniq -c | sort -rn
8. Prometheus 抓 metrics¶
/metrics 端点在 bearer_auth middleware 之外,不需要 token:
curl http://localhost:22222/metrics
# futu_auth_events_total{iface="rest",outcome="allow",key_id="research"} 1234
# futu_auth_limit_rejects_total{iface="grpc",key_id="sim-bot",reason="rate"} 7
# futu_ws_filtered_pushes_total{required_scope="trade",key_id="research"} 42
生产用防火墙 / bind 127.0.0.1 限制外部访问 metrics。