01学完你能做到
- 区分认证、授权、权限范围和数据授权。
- 设计 API Key 的哈希存储、轮换、吊销和审计日志。
- 识别对象级授权失效和多租户串数据风险。
- 用最小权限、最小必要和授权范围思路设计数据服务。
02这课解决什么问题
数据服务面对多个客户时,如何确认调用者是谁、允许调用哪些接口、可以访问哪些数据,并保证一个租户不能读到另一个租户的对象?
03认证、授权与对象隔离
认证(authentication)回答“你是谁”。请求没有有效凭证或凭证已失效,通常返回 401。
授权(authorization)回答“你能做什么”。调用者已经通过认证,但没有对应权限,通常返回 403。
对象级授权继续回答“你要访问的这个对象属于你吗”。即使 API Key 和权限范围都正确,也必须检查对象的租户归属。为了不暴露其他租户对象是否存在,某些系统会对越权对象返回 404;具体错误合同应保持一致并写入文档。
多租户系统还需要在数据访问层统一带上 tenant_id 过滤,或使用数据库的行级安全策略。不能只依赖开发者“记得在每个接口加一个 WHERE 条件”,还要用自动化测试验证 A 租户无法读取 B 租户的数据。
04API Key 是持有者凭证
API Key 可以理解为持有者凭证:谁拿到它,谁就可能以对应身份调用服务。因此应把它当作秘密处理,而不是普通的用户编号。
一套基本的生命周期包括:
- 生成足够随机的 Key,并使用可识别但不泄露秘密的前缀,方便扫描和审计。
- 明文只在创建时展示一次;服务端保存不可逆的哈希或带服务端密钥的哈希。
- 支持轮换:先创建新 Key,切换调用方后再吊销旧 Key,避免为了换密钥而停服。
- 支持按用途、环境或 Agent 分开创建 Key,减少单个 Key 泄露时的影响范围。
- 审计日志只记录 Key 前缀、租户、工具、对象、时间和结果,不记录完整 Key。
高熵随机 API Key 可以使用适合秘密凭证的哈希方案;用户密码则应使用专门的慢哈希方案。密钥管理服务、环境变量和访问控制比把 Key 写进代码、截图或聊天记录更合适。
05Scope 与数据授权
scope 描述一把 Key 能执行哪类操作,例如 market:read、finance:read。最小权限原则要求只授予当前任务所需的 scope。
数据授权(entitlement) 描述调用者能访问哪些数据集、时间范围、频率或使用场景,例如日终行情与实时行情分开授权。scope 管“能做哪类操作”,entitlement 管“能看哪份数据”,两者都要检查。
数据授权还可能来自上游许可、合同和展示范围。一个 API 能返回某份数据,不代表调用者可以将它再发布给自己的用户。对外展示、转发、再分发和用于产品化的权限,需要回到上游许可和合同确认。
06数据合规的通用原则
数据服务至少要区分两类授权问题:
- 数据来源授权:上游数据提供方是否允许采集、存储、调用、展示、转发或再分发,以及允许的终端范围和用途。
- 用户数据保护:账号、调用日志、自选股、组织信息等是否包含个人信息或其他受保护数据,收集和保存是否有明确目的和必要性。
《中华人民共和国数据安全法》确立了数据分类分级保护和全流程安全管理等要求。工程上可以落实为:识别数据类别,控制访问范围,记录处理活动,进行风险监测,发现漏洞及时补救,发生事件按适用要求处置和报告。
《中华人民共和国个人信息保护法》要求个人信息处理具有合法、正当、必要目的,收集范围应限于实现处理目的所需的最小范围,保存期限应为实现目的所必要的最短时间。课程中的审计日志、租户信息和自选股数据,也应评估是否涉及个人信息,并据此设计访问、脱敏、留存和删除策略。
这些是通用工程原则,不替代针对具体业务、数据类型和跨境场景的法律意见。涉及交易所或其他上游数据的商业许可时,还要单独核对许可文本和合同,不要仅凭“公开可查”判断可以再分发。
07在金融数据链路中的位置
客户 / Agent
│ API Key
▼
网关或 MCP 服务
├─ 认证:Key 是否有效、是否吊销
├─ scope:是否允许这类操作
├─ entitlement:是否包含这份数据
├─ 对象归属:是否属于当前租户
├─ 限流与计量
▼
数据访问层:强制 tenant_id 过滤
▼
返回结果 + 脱敏审计日志鉴权应发生在业务逻辑之前,但不能只在网关做一次。数据访问层仍要强制做租户过滤,尤其是内部服务之间调用时。审计日志要能回答“谁、何时、调用了什么、访问了哪个数据集、结果如何”,同时避免生成新的密钥泄露源。
08一个最小模型
PEPPER = secrets.token_bytes(32) # 生产环境由密钥管理服务托管
def hash_key(raw):
return hmac.new(PEPPER, raw.encode(), hashlib.sha256).hexdigest()
def handle(raw_key, tool, object_id=None):
meta = KEY_STORE.get(hash_key(raw_key)) if raw_key else None
if meta is None or meta["revoked"]:
return 401
if REQUIRED_SCOPE[tool] not in meta["scopes"]:
return 403
if REQUIRED_DATASET[tool] not in meta["datasets"]:
return 403
if object_id and OBJECTS[object_id]["tenant_id"] != meta["tenant_id"]:
return 404
return 200这只是教学模型。生产系统还需要处理并发、密钥轮换、密钥管理服务故障、缓存失效、权限变更传播和审计数据留存等问题。
09常见误区
- 把认证当成授权:有有效 Key 只说明调用者被识别,不说明它能访问所有接口和数据。
- 数据库明文存 Key:数据库泄露后会直接暴露全部凭证,应保存安全的哈希并支持轮换。
- 只做接口级权限,不做对象级权限:修改一个对象 ID 就能读到别人的数据,是常见的 API 安全风险。
- 所有用途共用一把 Key:按生产、测试、Agent 或数据集拆分 Key,便于最小授权和单独吊销。
- 把数据授权当成技术权限:技术上能调用,不代表合同允许展示、转发或再分发。
- 只在应用代码里过滤租户:应在统一数据访问层或数据库安全策略中强制隔离,并测试跨租户访问。
- 无限保存调用日志:日志可能含有个人信息或敏感业务信息,应设定必要字段、访问权限和保存期限。
10延伸阅读
11一分钟讲给别人
试着用自己的话讲一遍API 安全不是只有登录。先用 Key 认证“你是谁”,再用 scope 判断“你能做什么”,再检查数据授权和对象归属,防止租户之间串数据。Key 只展示一次、服务端存哈希、能轮换和吊销。金融数据还有合同边界:技术上能返回,不代表就能对外转发。
6 道自测
先在心里答一遍,再展开对照。能说清理由,比答对数字更重要。
01401 和 403 通常分别表示什么?
02为什么 API Key 不应以明文保存?
03scope 与数据授权有什么区别?
04什么是对象级授权失效?
05数据服务为什么要同时考虑来源授权和用户数据保护?
06多租户隔离为什么不能只靠每个接口手写过滤条件?
已看 0/6 题
练动手练习
任务:为一个“Agent 专用 Key”设计权限:只允许读取日终行情,不允许读取实时行情、财务数据或其他租户的自选股。列出 Key 存储、权限检查、对象过滤、日志字段和吊销流程,并写出至少两条跨租户访问测试。
完成这一课
读完讲义、看完自测答案,这一课就算学完了。
- 读完讲义
- 看完全部自测
本课为投资者教育内容,案例数字均为示意,不构成任何投资建议,也不承诺收益。规则和费率会变,实际操作前请以交易所、监管机构和产品的最新公告为准。