← Backend / 工程实践

02_HTTP_API与安全

HTTP 资源契约、认证与逐资源授权、输入校验、Cookie、CORS 和幂等。

HTTP API 与安全

学习目标:设计稳定的资源接口,并区分认证、授权、输入校验与浏览器安全机制。

1. 先定义 API 契约

以笔记资源为例:

请求 目的 常见成功状态
GET /notes?cursor=... 列表 200
GET /notes/{id} 详情 200
POST /notes 创建 201,可返回 Location
PATCH /notes/{id} 部分更新 200 或 204
DELETE /notes/{id} 删除 204

客户端和服务端要约定字段、分页、排序、错误结构、时区与兼容策略。400 代表请求格式或参数问题,401 是未认证,403 是已认证但无权操作,404 可用于不存在或按安全策略隐藏无权资源,409 常用于状态冲突。

2. 四层边界

  1. <span style="color:#1E90FF;font-weight:700;">认证(authentication)</span>:请求是谁发的?
  2. <span style="color:#1E90FF;font-weight:700;">授权(authorization)</span>:此用户能操作这条资源吗?
  3. 输入校验:字段类型、长度、范围、格式与业务状态是否合理?
  4. 输出控制:只返回客户端需要的字段,避免泄露令牌、哈希或内部错误。

对每条笔记查询同时限制 id 和 owner_id,不能仅靠前端隐藏按钮。数据库参数化查询防 SQL 注入;HTML 输出按上下文转义,避免 XSS;不要把富文本直接当可信 HTML。

3. 会话、Cookie 与跨域

浏览器会话 Cookie 通常设置 HttpOnly、Secure 和合适的 SameSite;使用 Cookie 的写操作应评估 CSRF 防护。CORS 是浏览器的跨域读取控制,不是服务端认证或授权。跨域配置应列出允许来源,避免把敏感凭据与无限制来源组合。

密码只用成熟算法与库进行加盐哈希,不能自制加密方案。令牌要考虑过期、撤销、最小权限与泄露后的处置;不要把长期凭证放进 URL。

4. 幂等与重试

网络重试可能让创建请求执行两次。对支付、下单等不可重复操作,使用请求幂等键并在服务端持久记录处理结果;仅在客户端“禁用按钮”不够。对外部依赖设置超时和有界重试,避免无限重试把故障放大。

<div style="border-left:4px solid #DC143C;padding:0.55em 0.8em;margin:0.8em 0;color:#DC143C;"><strong>易错点:</strong>“已登录”不代表“有权访问任意 ID”。越权访问测试必须覆盖用户 A 操作用户 B 资源的情况。</div>

自测

  1. CORS 放开是否等于用户获得了权限?不是。
  2. 为什么 POST 失败后直接重试可能有风险?首次请求可能已经写入,只是响应丢失。

5. 明确请求与错误的样子

以创建笔记为例,规定输入为 { "title": "...", "body": "..." },成功返回 201、Location: /notes/{id} 和包含 id、title、body、version 的响应。字段长度、空白处理、时区格式和未知字段策略都应写入契约。错误结构可统一为 { "code": "validation_error", "message": "标题不能为空", "requestId": "..." };code 用于程序分支,message 给用户展示,requestId 用于排查。

失败场景 建议响应 服务端要做的事
<span style="color:#2E8B57;font-weight:600;">未登录</span> 401 不访问私有资源
<span style="color:#2E8B57;font-weight:600;">无权访问</span> 403 或按策略隐藏为 404 在查询或业务层检查归属
<span style="color:#2E8B57;font-weight:600;">版本冲突</span> 409 返回可供重试的稳定错误码
<span style="color:#2E8B57;font-weight:600;">服务故障</span> 500/503 记录内部原因,不泄漏堆栈

6. 会话与 CSRF 的关系

Cookie 会随满足条件的请求自动发送,这让跨站请求伪造成为需要考虑的风险。SameSite 可以降低部分风险,但是否需要 CSRF token 要结合浏览器兼容性、请求方式和部署方式决定。前端发起跨域请求时若使用 Cookie,还需明确凭证模式和后端允许来源;CORS 只影响浏览器脚本的跨域读取,不替代身份校验。

无论使用 Cookie 还是 Bearer token,都要设计过期、撤销与异常登录处理。不要把访问令牌放在 URL、日志或前端公开配置中。密码存储使用成熟密码哈希算法和库,并限制登录尝试频率。

7. 幂等键的最小流程

客户端为一次创建意图生成唯一键并随请求发送。服务端在持久化层把“用户 + 幂等键 + 请求摘要 + 结果”关联起来;同键同请求返回第一次的结果,同键不同请求拒绝。并发请求要由唯一约束或锁保证只执行一次。练习:模拟“写入成功但响应丢失”,验证重试不会创建两条笔记。