Skip to content

CDN 部署注意事项

更新时间:2026/8/23 17:04:45

为加速访问, 不少部署会在站点前套一层 CDN(腾讯云 EdgeOne、CloudFlare、自建 nginx 缓存等)。 DaxPay 的后端 API 是动态 JSON 接口, 且部分接口返回一次性凭证(防重放 nonce、图形验证码), 一旦被 CDN 缓存, 会出现登录瘫痪、验证码失效、订单状态不更新等严重问题。

真实案例: 2026-08 演示站 admin.open.daxpay.cn 前置腾讯云 EdgeOne, 缓存了 GET /api/nonce/generate 的响应, 导致所有用户拿到同一份 nonce, 全站无法登录。缓存 5 分钟内报「请求验证已失效」, 超过 5 分钟后报「请求时间戳已过期」。

核心原则

  1. 所有 API 路径一律不缓存: 后端转发路径(常见的 /api/*)以及支付网关域名下的 /unipay/*/client/* 等接口路径, 必须在 CDN 显式配置「不缓存」
  2. 仅静态资源长缓存: 前端构建产物(assets/* 下的 js/css/图片/字体)、文档站等纯静态内容才适合 CDN 缓存
  3. 不要依赖「遵循源站」: 后端动态接口默认不返回 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 配置

规则引擎 中新建规则(优先级高于默认缓存行为):

  1. 匹配条件: URL Path + 正则匹配, 值:

    ^/(api|server|unipay|epay)(/|$)

    覆盖各域名下的 API 反代前缀:

    前缀所在域名用途
    /api/管理端 / 商户端 Web / 支付 H5后端 API 反代(各端统一)
    /unipay/网关 API 域名商户开放 API 与通道回调
    /epay/网关 API 域名易支付兼容 API

    正则末尾的 (/|$) 确保只匹配完整路径段; URL Path 匹配不含 query string, 无需考虑参数

  2. 执行动作: 节点缓存 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 的公钥接口为例(多次请求, 对比缓存状态):

bash
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/generatePOST登录防重放 nonce, 已从 GET 改为 POST(2026-08)
/captcha/imagePOST图形验证码, 已从 GET 改为 POST(2026-08)

新增接口时的约定: 免认证的 GET 接口若返回一次性凭证、随机值或用户敏感数据, 要么改用 POST, 要么显式设置 Cache-Control: no-store 响应头, 不要依赖部署侧永远记得配 CDN 规则。 保持 GET 的幂等查询接口(公钥、配置、订单状态轮询等)依赖 CDN 不缓存规则兜底。

基于 GNU LGPL v3.0 协议开源