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. 四层边界
- <span style="color:#1E90FF;font-weight:700;">认证(authentication)</span>:请求是谁发的?
- <span style="color:#1E90FF;font-weight:700;">授权(authorization)</span>:此用户能操作这条资源吗?
- 输入校验:字段类型、长度、范围、格式与业务状态是否合理?
- 输出控制:只返回客户端需要的字段,避免泄露令牌、哈希或内部错误。
对每条笔记查询同时限制 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>
自测
- CORS 放开是否等于用户获得了权限?不是。
- 为什么
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. 幂等键的最小流程
客户端为一次创建意图生成唯一键并随请求发送。服务端在持久化层把“用户 + 幂等键 + 请求摘要 + 结果”关联起来;同键同请求返回第一次的结果,同键不同请求拒绝。并发请求要由唯一约束或锁保证只执行一次。练习:模拟“写入成功但响应丢失”,验证重试不会创建两条笔记。