跨域缓存问题本质是浏览器对options预检或实际响应头缓存不一致所致;php需统一设置cors头、禁用预检缓存(access-control-max-age=0)、分层控制cache-control,并规避session与反向代理干扰。

跨域请求的缓存问题,本质是浏览器对 OPTIONS 预检请求或实际请求的响应头缓存策略不一致导致的——比如后端没明确控制缓存,浏览器就按默认规则(如对 200 响应缓存几秒)处理,结果后续请求拿的是旧的 Access-Control-Allow-Origin 或其他 CORS 头,造成跨域失败。
PHP 中必须禁用预检请求缓存(OPTIONS)
浏览器对 OPTIONS 预检响应会缓存(由 Access-Control-Max-Age 控制),但很多 PHP 框架或裸脚本没显式设置它,导致旧的 CORS 策略长期生效。
-
Access-Control-Max-Age值设为0表示不缓存预检结果(最安全);设为正整数(如86400)表示缓存秒数,但修改策略后需等缓存过期才生效 - 必须在所有响应(包括
OPTIONS和实际业务响应)中统一设置Access-Control-Allow-Origin,不能只在OPTIONS里设 - 如果用了动态域名(如
$_SERVER['HTTP_ORIGIN']),要校验白名单,否则直接回*会和带凭证(credentials)冲突
PHP 设置缓存控制头要区分响应类型
对 CORS 请求,不能只靠 Cache-Control: no-store 一刀切。实际要分两层控制:
- 预检响应(
OPTIONS):必须加Cache-Control: no-cache, no-store, must-revalidate+Pragma: no-cache+Expires: 0,否则部分浏览器(如旧版 Safari)仍可能缓存 - 业务响应(如
GET /api/data):若数据实时性要求高,用Cache-Control: no-cache(允许验证但不跳过);若绝对不能缓存,用no-store;避免用max-age=0,它和no-cache语义不同且兼容性差 - 注意:PHP 的
header()必须在输出任何内容前调用,否则会报Cannot modify header information
常见错误:CORS 头与缓存头互相干扰
以下组合会导致跨域失败或缓存异常:
立即学习“PHP免费学习笔记(深入)”;
- 设置了
Access-Control-Allow-Credentials: true,但Access-Control-Allow-Origin是*→ 浏览器直接拒绝,和缓存无关但常被误认为缓存问题 -
Cache-Control: public, max-age=3600用在含动态 CORS 头的响应上 → 缓存命中时返回旧的Origin对应头,跨域失败 - 用
session_start()后再输出 CORS 头 → PHP 默认开启session.cache_limiter(值为nocache),会自动注入冲突的缓存头,需提前调用session_cache_limiter('')清空
真正麻烦的不是加几行 header(),而是得同时盯住预检响应、业务响应、会话机制、反向代理(如 Nginx 可能覆盖 PHP 的缓存头)三层缓存行为。漏掉任意一层,都可能让前端在某个浏览器里突然跨域失败,且难以复现。











