从 curl 到工程封装:2FA 动态验证码 API 接入全指南
适用场景
双因素认证(2FA)已成为提升系统安全性的标配手段。TOTP(基于时间的一次性密码)是其中最流行的实现,兼容 Google Authenticator、Microsoft Authenticator 等主流验证器。2FA 动态验证码 API 提供了一套完整的 TOTP 生成与校验能力,适用于以下场景:
- 用户登录二次验证:在密码验证通过后,要求用户输入身份验证器上的 6 位码。
- 敏感操作确认:如修改密码、转账、删除资源等高风险操作,增加动态码校验。
- 服务间鉴权:为内部 API 调用生成临时的 TOTP 令牌,替代静态密钥。
- 批量返回前后周期码:某些情况需要同时使用上一、当前、下一个周期码(如网络延迟补偿),API 的 batch 模式可直接返回三组数据。
接口能力边界
该 API 基于 RFC6238 标准实现,提供生成、验证、批量三种操作模式。以下是关键约束:
- 请求方法:POST
- 接口地址:
https://v1.apizero.cn/api/2fa - QPS:20 次/秒(匿名调用与携带 API Key 调用共享此限流,具体额度以文档为准)
- 密钥要求:Base32 编码字符串,自动忽略空格、连字符,不区分大小写。
- 验证码位数:4~8 位,默认 6 位。
- 有效期:10~120 秒,默认 30 秒。
- 安全性:密钥仅参与计算,不存储、不回显;验证采用恒定时间比较,防止时序攻击。
请求参数与鉴权
Header 参数
| 参数名 | 必填 | 类型 | 说明 |
|---|---|---|---|
Authorization | 否 | string | Bearer <你的API Key>;可选,携带后获更高调用额度 |
Content-Type | 是 | string | 固定为application/json |
请求体字段
| 字段名 | 必填 | 类型 | 描述 |
|---|---|---|---|
secret | 是 | string | Base32 编码的 TOTP 密钥 |
action | 否 | string | 操作类型:generate(生成)、verify(校验)、batch(批量);默认generate |
code | 否 | string | 当action=verify时必填,待校验的验证码 |
period | 否 | number | 验证码有效期(秒),范围 10~120,默认 30 |
digits | 否 | number | 验证码位数,范围 4~8,默认 6 |
请求体为一个 JSON 对象,示例:
{ "secret": "JBSWY3DPEHPK3PXP", "action": "generate", "period": 30, "digits": 6 }从 curl 快速接入
以下示例演示如何使用 curl 直接调用接口。$APIZERO_API_KEY可替换为你的 API Key,若不携带也可匿名调用(但额度较低)。
1. 生成一个 TOTP 验证码
curl -sS \ -X POST \ -H "Content-Type: application/json" \ -d '{"secret":"JBSWY3DPEHPK3PXP","action":"generate","period":30,"digits":6}' \ "https://v1.apizero.cn/api/2fa"成功响应示例:
{ "code": 0, "msg": "成功", "data": { "digits": 6, "next_refresh": "2026-06-30 12:00:30", "period": 30, "remaining_seconds": 17, "timestamp": 1782000000, "totp_code": "123456" }, "request_id": "abc123" }2. 校验一个验证码
curl -sS \ -X POST \ -H "Content-Type: application/json" \ -d '{"secret":"JBSWY3DPEHPK3PXP","code":"678901","action":"verify","period":30,"digits":6}' \ "https://v1.apizero.cn/api/2fa"校验模式下,若code匹配当前周期验证码,响应data中应包含valid: true(具体字段请以文档为准)。
3. 批量获取验证码
curl -sS \ -X POST \ -H "Content-Type: application/json" \ -d '{"secret":"JBSWY3DPEHPK3PXP","action":"batch","period":30,"digits":6}' \ "https://v1.apizero.cn/api/2fa"batch模式会返回previous、current、next三个周期的验证码及相关时间信息,适用于网络延迟较大的场景。
返回值解读
通用响应结构:
{ "code": 0, // 业务状态码,0 表示成功 "msg": "成功", // 状态描述 "data": { /* 具体数据 */ }, "request_id": "abc123" }generate 模式 data 字段
| 字段 | 类型 | 说明 |
|---|---|---|
totp_code | string | 当前周期的 TOTP 验证码 |
digits | number | 验证码实际位数 |
period | number | 验证码有效期(秒) |
remaining_seconds | number | 当前码剩余有效秒数 |
next_refresh | string | 下一次刷新时间(格式:YYYY-MM-DD HH:mm:ss) |
timestamp | number | 服务器当前 Unix 时间戳(秒) |
verify 模式 data 字段
该模式返回valid布尔值,表示校验结果。具体字段名以文档为准。
batch 模式 data 字段
返回三个周期的验证码对象,分别键名为previous、current、next,每个对象结构与 generate 的 data 相同。
常见错误处理
| HTTP 状态码 | 业务 code | 常见原因 | 处理建议 |
|---|---|---|---|
| 400 | 40001 | secret缺失或非合法 Base32 字符串 | 检查密钥格式,确保不含非法字符 |
| 400 | 40002 | code位数不符或包含非数字字符 | 确认 code 长度等于digits |
| 400 | 40003 | period或digits超出允许范围 | 限制 period 10~120,digits 4~8 |
| 401 | 401 | 携带了无效的 Authorization Header | 检查 API Key 是否过期或格式错误 |
| 429 | 429 | 请求频率超过 20 QPS | 引入本地限流,如令牌桶或队列 |
| 5xx | - | 服务端临时故障 | 建议指数退避重试,间隔 1s/2s/4s 等 |
工程封装建议
1. 封装一个客户端类或函数
示例(Python 风格伪代码):
import requests import time class TOTPClient: def __init__(self, base_url: str, api_key: str = None): self.base_url = base_url self.headers = {"Content-Type": "application/json"} if api_key: self.headers["Authorization"] = f"Bearer {api_key}" def generate(self, secret: str, period: int = 30, digits: int = 6) -> dict: payload = {"secret": secret, "action": "generate", "period": period, "digits": digits} resp = requests.post(self.base_url, json=payload, headers=self.headers) resp.raise_for_status() return resp.json() def verify(self, secret: str, code: str, period: int = 30, digits: int = 6) -> bool: payload = {"secret": secret, "code": code, "action": "verify", "period": period, "digits": digits} resp = requests.post(self.base_url, json=payload, headers=self.headers) data = resp.json() if data["code"] != 0: raise Exception(f"Verify failed: {data['msg']}") return data["data"]["valid"]2. 错误重试机制
对于 5xx 错误或网络超时,使用指数退避重试。注意区分业务错误(如 code 错误)与可重试错误:
import time from requests.exceptions import RequestException def retry_request(func, max_retries=3, base_delay=1): for attempt in range(max_retries): try: return func() except RequestException as e: if attempt == max_retries - 1: raise time.sleep(base_delay * (2 ** attempt))3. 密钥存储
Base32 密钥是敏感信息,不要硬编码在代码中。建议通过环境变量、密钥管理服务或配置中心注入。同时注意日志输出时避免打印密钥。
4. 并发与限流
单账户 QPS 上限为 20。若服务需要高频调用,建议本地维护一个令牌桶,每秒补充 20 个 token,请求前获取 token。也可将请求排队串行化。
5. 日志与监控
记录每次请求的request_id、action、响应码和耗时。对code!=0或valid=false的请求单独告警,方便排查问题。
6. 时区与时间同步
TOTP 基于时间窗口,服务端与客户端时间偏差会导致验证失败。生产环境中建议使用 NTP 同步时间,并在 verify 时允许一定的时钟漂移窗口(API 服务端已内部处理,客户端无需额外配置)。
参考文档
- 2FA 动态验证码 API 文档
- 原始文档(Markdown)
