这是 Beta 探索课程,内容结构、实验步骤和示例可能会继续调整。
用户认证
设计目标
我决定实现用户认证系统,让每个用户有独立的调用配额。
核心需求:
- 用户可以注册账号
- 系统分配唯一的 API Key
- 每次调用必须验证 API Key
- 限制每个用户的调用配额
这是一个完整的认证体系,我需要从零开始设计。
方案设计
API Key(访问密钥)的设计
API Key 是什么?
- 一个唯一的字符串
- 也可以理解为用户调用 API 时携带的访问密钥
- 用来标识用户身份和调用权限
- 需要在每次调用时携带
API Key 的格式:
ak_live_xxxxxxxxxxxxxxx (正式环境)
ak_test_xxxxxxxxxxxxxxx (测试环境)格式说明:
ak_:前缀,表示 API Keylive/test:环境标识- 后面:随机字符串
我特意加了环境标识,这样开发和生产环境可以分开管理。
数据模型设计
API Key 生成
生成安全的 API Key
设计流程
生成安全的 API Key
- 步骤 1:校验调用方身份,并绑定用户、应用和权限范围
- 步骤 2:校验身份、密钥或权限
- 步骤 3:读取 API Key、调用方信息和请求上下文
- 步骤 4:根据认证结果、权限和配额决定放行或拒绝
关注点:身份可信度、权限边界、配额消耗和审计追踪。
为什么使用 secrets 模块?
- 加密安全的随机数生成
- 不可预测
- 防止碰撞
我当时想,API Key 是用户的身份标识,必须在源头上保证安全。
用户注册流程
注册接口
设计流程
注册接口
- 步骤 1:生成认证结果并绑定用户、应用和权限范围
- 步骤 2:写入队列并异步消费
- 步骤 3:校验身份、密钥或权限
关注点:身份可信度、权限边界、配额消耗和审计追踪。
登录接口
设计流程
登录接口
- 步骤 1:生成认证结果并绑定用户、应用和权限范围
- 步骤 2:写入队列并异步消费
- 步骤 3:校验身份、密钥或权限
关注点:身份可信度、权限边界、配额消耗和审计追踪。
我特意让 API Key 只在注册时返回一次,之后就再也看不到了。这样设计是为了安全,但也带来了一些麻烦——用户如果弄丢了 API Key,就只能重置。
API 调用认证
修改天气 API 接口
设计流程
修改天气 API 接口
- 步骤 1:校验调用方身份,并绑定用户、应用和权限范围
- 步骤 2:生成认证结果并绑定用户、应用和权限范围
- 步骤 3:校验调用方身份,并绑定用户、应用和权限范围
- 步骤 4:计算用量、账单或套餐状态
关注点:身份可信度、权限边界、配额消耗和审计追踪。
通过统一认证入口,我可以把认证逻辑从业务流程中分离出来。这是我从之前做系统设计的经验中学到的——关注点分离。
客户端使用方式
正确的调用方式
设计流程
正确的调用方式
- 步骤 1:校验身份、密钥或权限
- 步骤 2:读取 API Key、调用方信息和请求上下文
- 步骤 3:根据认证结果、权限和配额决定放行或拒绝
- 步骤 4:返回认证结果,并写入审计、配额和异常访问记录
关注点:身份可信度、权限边界、配额消耗和审计追踪。
错误的调用方式
设计流程
错误的调用方式
- 步骤 1:校验身份、密钥或权限
- 步骤 2:读取 API Key、调用方信息和请求上下文
- 步骤 3:根据认证结果、权限和配额决定放行或拒绝
- 步骤 4:返回认证结果,并写入审计、配额和异常访问记录
关注点:身份可信度、权限边界、配额消耗和审计追踪。
安全考虑
API Key 的安全问题
问题 1:API Key 泄露
- 如果 API Key 泄露,他人可以冒用
- 配额被消耗
- 产生费用
解决方案:
- 提醒用户妥善保管 API Key
- 提供重置 API Key 的功能
- 设置 IP 白名单(可选)
- 监控异常调用
密码存储
问题 2:密码不能明文存储
设计流程
密码存储
- 步骤 1:读取 API Key、调用方信息和请求上下文
- 步骤 2:根据认证结果、权限和配额决定放行或拒绝
- 步骤 3:返回认证结果,并写入审计、配额和异常访问记录
关注点:身份可信度、权限边界、配额消耗和审计追踪。
更好的方案是使用 bcrypt:
设计流程
密码存储
- 步骤 1:读取 API Key、调用方信息和请求上下文
- 步骤 2:根据认证结果、权限和配额决定放行或拒绝
- 步骤 3:返回认证结果,并写入审计、配额和异常访问记录
关注点:身份可信度、权限边界、配额消耗和审计追踪。
我当时想,安全这件事,再怎么重视也不为过。
真实上线还要注意
- 不要只验证“这个 Key 对不对”。 还要记录它是谁、什么时候、从哪里调用了什么接口。
- Key 泄露要能止损。 用户应该能重置密钥,系统也应该能临时停用异常密钥。
- 认证、限流、计费要串起来。 否则用户明明被限流了,账单和日志却说不清原因。
效果验证
上线后,我观察了一周的数据:
滥用情况
| 指标 | 之前 | 现在 |
|---|---|---|
| 异常 IP 调用 | 每天 10+ 个 | 0 个 ✅ |
| 外部 API 滥用 | 频繁 | 0 次 ✅ |
| 正常用户体验 | 差 | 优秀 ✅ |
用户增长
| 指标 | 数值 |
|---|---|
| 注册用户 | 200 个 |
| 日活用户 | 80 个 |
| 平均每用户调用 | 100 次/天 |
看到这些数据,我知道这条路走对了。
新的问题
虽然解决了滥用问题,但带来了一些新挑战:
问题 1:数据存储
用户数据和调用日志越来越多:
- 用户表:200 条
- 日志表:每天 5 万条
- 增长速度:每月 150 万条
应该用什么数据库?
问题 2:查询性能
日志表查询越来越慢:
设计流程
问题 2:查询性能
- 步骤 1:读取 API Key、调用方信息和请求上下文
- 步骤 2:根据认证结果、权限和配额决定放行或拒绝
- 步骤 3:返回认证结果,并写入审计、配额和异常访问记录
关注点:身份可信度、权限边界、配额消耗和审计追踪。
随着数据量增长,这个查询会越来越慢。
如何优化?
问题 3:数据备份
如果数据库挂了,所有用户数据都会丢失。
如何备份数据?
一个问题解决了,新的问题又来了。这就是做系统的常态吧。