CDN 部署注意事项
为加速访问, 不少部署会在站点前套一层 CDN(腾讯云 EdgeOne、CloudFlare、自建 nginx 缓存等)。 DaxPay 的后端 API 是动态 JSON 接口, 且部分接口返回一次性凭证(防重放 nonce、图形验证码), 一旦被 CDN 缓存, 会出现登录瘫痪、验证码失效、订单状态不更新等严重问题。
真实案例: 2026-08 演示站
admin.open.daxpay.cn前置腾讯云 EdgeOne, 缓存了GET /api/nonce/generate的响应, 导致所有用户拿到同一份 nonce, 全站无法登录。缓存 5 分钟内报「请求验证已失效」, 超过 5 分钟后报「请求时间戳已过期」。
核心原则
- 所有 API 路径一律不缓存: 后端转发路径(常见的
/api/*)以及支付网关域名下的/unipay/*、/client/*等接口路径, 必须在 CDN 显式配置「不缓存」 - 仅静态资源长缓存: 前端构建产物(
assets/*下的 js/css/图片/字体)、文档站等纯静态内容才适合 CDN 缓存 - 不要依赖「遵循源站」: 后端动态接口默认不返回
Cache-Control响应头, CDN 在「无源站头」时的默认行为各家不一(有的按自身默认 TTL 缓存 200 响应), 必须显式配置不缓存规则, 不能指望默认行为
为什么动态 API 不能被缓存
| 风险类型 | 机制 | 后果 |
|---|---|---|
| 一次性凭证被共享 | nonce、图形验证码存 Redis 一次性消费, 响应被缓存后所有用户拿到同一份 | 登录全站失败; 验证码防刷机制失效, 可被识别一次后反复使用 |
| 轮询拿到旧状态 | 订单状态查询类接口(如码牌 /client/device/qrcode/order-status)同一 URL 高频重复请求, 必然命中缓存 | 用户支付成功后页面永远显示未支付 |
| 数据串号 | CDN 缓存键通常只有 URL 不含请求头, 不同用户(不同 token)同 URL 的 200 响应可能互相命中 | 用户 A 看到用户 B 的数据 |
| 配置/密钥过时 | 公钥(/token/public-key)、收银台配置等被缓存, 源站更新后 CDN 继续分发旧值 | 密钥轮换后登录解密失败, 且难排查 |
腾讯云 EdgeOne 配置
在 规则引擎 中新建规则(优先级高于默认缓存行为):
匹配条件:
URL Path+ 正则匹配, 值:^/(api|server|unipay|epay)(/|$)覆盖各域名下的 API 反代前缀:
前缀 所在域名 用途 /api/管理端 / 商户端 Web / 支付 H5 后端 API 反代(各端统一) /unipay/网关 API 域名 商户开放 API 与通道回调 /epay/网关 API 域名 易支付兼容 API 正则末尾的
(/|$)确保只匹配完整路径段; URL Path 匹配不含 query string, 无需考虑参数执行动作: 节点缓存 TTL = 不缓存(同时建议浏览器缓存也设为不缓存)
host 条件不用加 —— 不加 host 时规则对站点下所有开启代理加速的域名统一生效, 管理端、商户端、H5、网关 API 域名一条规则全覆盖; 除非某个 host 是纯静态站点才值得单独限定。
前端静态资源(assets/ 下的 js/css/图片)不匹配这条正则, 继续走 CDN 缓存, 加速收益保留。
CloudFlare 配置
在 Cache Rules 中新建规则:
- 匹配: URI Path starts with
/api/ - 缓存资格: Bypass cache
自建 nginx 反代缓存的话, 对 API 路径不要配置 proxy_cache, 或用 proxy_cache_bypass/proxy_no_cache 排除。
如何验证配置生效
用 curl 观察缓存指示头, 以仍是 GET 的公钥接口为例(多次请求, 对比缓存状态):
curl -sD - -o /dev/null https://你的域名/api/token/public-key | grep -i "eo-cache-status"EO-Cache-Status: MISS— 回源正常EO-Cache-Status: HIT— 被缓存了, API 有问题
不同 CDN 的指示头不同: CloudFlare 是 CF-Cache-Status, nginx 自建常见 X-Cache。 更直接的判断: 同一 GET 接口连续请求两次, 响应内容完全相同即为被缓存 (一次性凭证接口改 POST 后不适用此法, 可用公钥/配置类 GET 接口验证)。
后端一次性凭证接口(开发约定)
| 接口 | 方法 | 说明 |
|---|---|---|
/nonce/generate | POST | 登录防重放 nonce, 已从 GET 改为 POST(2026-08) |
/captcha/image | POST | 图形验证码, 已从 GET 改为 POST(2026-08) |
新增接口时的约定: 免认证的 GET 接口若返回一次性凭证、随机值或用户敏感数据, 要么改用 POST, 要么显式设置 Cache-Control: no-store 响应头, 不要依赖部署侧永远记得配 CDN 规则。 保持 GET 的幂等查询接口(公钥、配置、订单状态轮询等)依赖 CDN 不缓存规则兜底。