API 安全攻防:认证、授权与 OWASP API Top 10

FreeGuideOnline 最新 2026-06-12

为什么 API 安全如此重要

现代应用几乎都建立在 API 之上。无论是移动应用、单页应用还是微服务架构,API 都是数据交换与业务逻辑的核心通道。正因其广泛暴露和直接访问后端数据的特性,API 已成为攻击者的首选目标。传统 Web 安全关注表单、会话,而 API 安全需要全新的视角:无状态认证、细粒度授权、数据暴露控制以及速率限制等。OWASP API 安全项目提供了系统化的威胁模型与防御指南,是每一位开发者与安全工程师必须掌握的知识。

OWASP API 安全 Top 10 概览

OWASP API Security Top 10 专为 API 场景设计,聚焦最关键的十大风险。最新版本(2023)仍保持动态更新,核心风险类别与 2019 版一脉相承,但更强调授权缺陷与数据暴露。下表将 10 大风险按类型分组,以帮助快速建立认知地图。

风险编号 名称 核心问题
API1 失效的对象级授权 (BOLA) 针对同一对象的请求未做用户权限校验
API2 失效的用户认证 认证机制本身存在漏洞,可被绕过
API3 过度的数据暴露 API 响应返回过多字段,依赖客户端过滤
API4 缺乏资源与速率限制 可被暴力攻击、爬取或拒绝服务
API5 失效的功能级授权 (BFLA) 不同功能端点未实施适当角色校验
API6 批量分配 用户传入参数被绑定到内部对象属性,导致越权修改
API7 安全配置错误 错误信息泄露、不安全的 HTTP 头、默认配置
API8 注入 SQL、NoSQL、命令注入等
API9 资产管理不当 已废弃、调试或旧版 API 未关闭
API10 日志记录与监控不足 无法及时发现攻击或数据泄露

以上风险中,对象级授权与功能级授权是 API 安全的两大基石,几乎所有破坏性攻击都源于此。接下来我们将深入实战,剖析这些风险并给出可落地的防御方案。

认证 —— 谁在敲门?

不要自己造轮子

永远不要自行设计认证协议。使用经过广泛审计的标准方案:OAuth 2.0 + OpenID Connect 用于用户委托授权与身份验证;对于服务间通信,优先选择 Mutual TLS 或预共享密钥的 Bearer 令牌。避免 Basic Auth 在没有 TLS 的情况下使用,因为凭据几乎以明文传输。

令牌管理实践

  • JWT 的使用:签名很重要,务必使用非对称算法(RS256/ES256)或强对称密钥(HS256),并在服务端验证签名。敏感载荷必须加密(JWE)。
  • 短期令牌与刷新令牌:访问令牌(access token)过期时间应短,例如 15 分钟。客户端使用刷新令牌(refresh token)换取新访问令牌,刷新令牌应绑定客户端并支持轮转。
  • 撤销机制:维护令牌黑名单或使用短过期时间 + 无状态签名。注意不要在 JWT 中存储过多敏感数据,因为它们默认只是 Base64 编码,不是加密。

API 密钥与微服务

对于机器对机器调用,API 密钥容易泄露且难以轮换。推荐使用 OAuth 2.0 客户端凭证流,并为每个客户端生成独立凭据,同时施加最小权限。密钥必须通过环境变量或密钥管理服务注入,严禁硬编码。

授权 —— 你能做什么?

对象级授权 (BOLA)

这是 API 安全中最普遍且危害最大的漏洞。当 /api/users/{id} 接口只校验用户是否登录,而未校验登录用户的 ID 是否与 {id} 匹配时,攻击者通过遍历 ID 即可访问所有用户数据。

防御策略

  • 所有权校验:始终从认证会话中提取当前用户 ID,并将其与请求的资源所有者 ID 比较。避免仅依赖客户端传入的 ID。
  • 使用不可预测的标识符:对于公开资源,使用随机 UUID 而不是自增数字,但决不能仅靠混淆来保证安全。
  • 集中授权层:不要在业务逻辑中散落授权判断,而是用中间件或 AOP 统一校验,确保每个端点都经过授权检查。

功能级授权 (BFLA)

BOLA 检查“你能访问这个对象吗”,而 BFLA 检查“你能调用这个操作吗”。例如普通用户能否访问 /admin/export 端点。

防御策略

  • 基于角色的访问控制:在路由层定义所需角色,如 @RolesAllowed("ADMIN")
  • 默认拒绝:除非显式允许,否则拒绝所有请求。
  • 测试覆盖:编写自动化测试,用不同角色账户尝试访问每个端点,确保权限边界无遗漏。

批量分配与属性越权

批量分配通常发生在对象映射框架中,当接收 JSON 请求体时,直接绑定到内部数据模型。攻击者可能发送 {"role":"admin"} 把自己的账号提权。

防御

  • 定义允许字段白名单,永远不要直接将用户输入绑定到持久化对象。使用 DTO 并显式列出可设置的属性。
  • 区分用户可更新属性和内部属性。例如“注册时间”、“余额”等必须只能由服务端修改。

如何应对数据泄露与信息过载

最小化数据返回

API 响应应该只包含客户端真正需要的字段,而不是返回整个数据库行。常见错误是 GET /user 返回密码哈希、安全答案、内部标签等。

实践

  • 序列化与视图模型:针对不同角色、不同场景(列表 vs 详情)定义不同响应结构。
  • GraphQL 同样需要控制:即使客户端可以决定字段,也要在解析器中校验字段级权限。
  • 分页与过滤:避免一次返回大量记录,强制分页参数并提供合理的默认上限。

安全头与错误信息

  • 屏蔽技术栈:移除 X-Powered-By 等头,错误响应仅返回通用消息。
  • 避免泄漏堆栈跟踪:生产环境关闭调试模式,返回 {"error":"invalid_request"} 而非详细的代码行号。
  • CORS 配置:不要使用 Access-Control-Allow-Origin: *,尤其是在 API 使用凭证(cookies)时。应精确指定允许的源。

速率限制与资源保护

缺少速率限制,攻击者可通过暴力破解令牌字典、爬取数据或耗尽计算资源来影响服务。API 应当:

  • 为敏感端点(登录、注册、密码重置)设置严格的速率限制,如 5 次/分钟。
  • 使用滑动窗口或令牌桶算法,避免可预测的固定窗口复位。
  • 基于 IP、用户 ID 或 API 密钥多维度限流。
  • 对超出限制的请求返回 429 Too Many Requests,并在响应头中告知限制状态。

注入攻击:不仅是 SQL

API 同样需要防范注入,包括 SQL、NoSQL、命令注入以及表达式语言注入。当查询参数或请求体直接拼接到查询语句中时就会产生风险。

防御

  • 参数化查询:永远不要拼接字符串构建查询, ORM 也应使用安全的查询构建方式。
  • 输入验证与净化:根据数据类型进行严格白名单校验(例如整数、邮箱格式)。
  • 小心 NoSQL 操作符注入:比如 MongoDB 的 $gt$ne 可能被用在 JSON 输入中,确保输入是纯净的值而非操作符。

资产管理:你忘了那个旧接口

过时或影子 API 是攻击者的乐园。开发者经常忘记下线旧版本、测试端点或内部调试功能。

最佳实践

  • API 清单:定期自动发现所有公开接口,使用 swagger/OpenAPI 文件治理。
  • 版本控制:清晰设定 API 生命周期,废弃接口在响应头中加入 DeprecationSunset 头。
  • 仅暴露必要端点:生产环境移除 /swagger-ui/api-docs 等文档,或使用强认证保护。

日志与监控:最后一道防线

没有足够的日志,你永远无法知道什么时候发生了入侵。日志需要记录谁、在什么时间、做了什么操作、结果如何

  • 记录所有认证尝试(成功与失败)。
  • 记录敏感操作,如权限变更、大量数据导出。
  • 避免记录敏感数据:令牌、密码、个人身份信息不应写入明文日志。
  • 集成 SIEM 或警报系统,对异常模式(如突然的大量 403 错误)及时响应。

总结:纵深防御体系

OWASP API 安全最佳实践并非单个技术点,而是一套纵深防御体系。认证确保身份可信,授权保证最小权限,数据的谨慎输出减少泄露面,限流和日志提供韧性。将 OWASP API Top 10 内化为团队的威胁模型,并融入软件开发生命周期,从设计、编码到测试、监控,每一个环节都应嵌入这些校验点。

建议从今天起,在你的 API 代码库中检查以下三个最容易被忽视的地方:

  1. 每个端点是否都对当前用户进行了对象所有权检查?
  2. 响应 JSON 是否可能泄露了不必要的字段?
  3. 是否有未进行速率限制的认证相关端点?

修复这些问题,就已经堵住了绝大多数 API 攻击的入口。