首次MISS响应里的script nonce与CSP头一致,HIT之后却不一致或干脆缺失。nonce必须每个响应随机,不能随整页HTML被FPC固定缓存。
复现与判断
我保留了一个失败样本,并用同样输入在无缓存或单节点条件下再跑一遍。这样可以把前端假象、缓存和真正的数据问题分开。
数据库和日志对照
- 连续请求同一URL,对比CSP响应头和script标签nonce。
- 用X-Magento-Cache-Debug确认一次MISS、一次HIT。
curl -sI https://shop.example.com/page | grep -i "content-security|x-magento-cache" curl -s https://shop.example.com/page | grep -o "nonce=.[^ >]*" | head grep -R "nonce" app/code/Vendor app/design -n
为了避免把环境差异当成根因,我会先在预发布或数据库副本复现;涉及订单、库存和支付的操作,正式环境只做只读核对,修复脚本必须带明确的订单号或SKU范围。
这次的修法
不要在可缓存block里手工生成nonce。Magento支持的版本使用SecureHtmlRenderer渲染内联脚本,让框架按响应处理;更稳妥的是把脚本移到外部静态文件并用CSP白名单允许其来源。清理FPC后验证HIT响应。若反代覆盖CSP头,移除重复头。
修改范围
- 先在单个SKU、单个订单或单个Store验证。
- 保留可回退的旧配置,不覆盖原始证据。
- 需要批量处理时分批提交并输出成功/失败清单。
验证结果
- MISS和HIT都不报CSP错误
- 页面只有一份CSP策略
- 内联脚本使用框架生成方式
- Report-Only与Enforce环境一致
验收不只看后台提示“成功”。我还会从前台/API再走一次真实链路,并在下一轮cron、索引或缓存命中后重复检查,确认不是短暂正常。
顺手记下
把unsafe-inline加回去能消错但等于放弃这部分CSP防护。

