Service Worker缓存错误CSP问题:WordPress双CSP配置失效求助
解决WordPress主站与/wp-admin/区域CSP被ServiceWorker缓存冲突的问题
这个问题我之前帮不少开发者排查过——本质是ServiceWorker的作用域和缓存机制,和你分路径配置的CSP规则撞在了一起。我来拆解下原因,再给你落地的解决方案:
为什么会出现CSP规则串用的情况?
- ServiceWorker作用域覆盖问题:如果你的ServiceWorker是注册在根路径
/下,它会默认接管整个域名的所有请求,包括/wp-admin/。当你先访问主站时,ServiceWorker会缓存主站的CSP响应头;后续访问/wp-admin/时,它可能直接返回缓存的主站CSP,而不是去服务器拉取专属的宽松规则。 - HTTP缓存的叠加影响:如果你的CSP响应头没有配置严格的
Cache-Control,浏览器本身也会缓存旧的CSP规则,导致切换页面时规则“串台”,偶尔还会出现主站加载/admin规则的反向问题。
具体解决步骤
1. 让ServiceWorker避开/wp-admin/请求
既然你不需要ServiceWorker优化后台,直接在ServiceWorker的fetch事件里跳过所有/wp-admin/相关的请求,让这些请求直接走服务器:
self.addEventListener('fetch', (event) => { // 检测请求路径是否包含/wp-admin/ if (event.request.url.includes('/wp-admin/')) { // 直接转发请求到服务器,不走ServiceWorker缓存 event.respondWith(fetch(event.request)); return; } // 这里放你的主站缓存逻辑(比如静态资源缓存、离线策略) });
如果你的ServiceWorker本来就只需要处理主站内容,注册时也可以更精准地设置作用域(不过上面的fetch拦截更稳妥):
navigator.serviceWorker.register('/sw.js', { // 限制ServiceWorker只作用于主站内容路径 scope: '/' })
2. 给CSP头添加禁止缓存的规则
不管是主站还是/wp-admin/的CSP,都要加上Cache-Control头,确保浏览器和ServiceWorker不会缓存这些规则:
# 主站CSP配置(保留你的严格规则) <Location /> <IfModule mod_headers.c> Header set Content-Security-Policy "default-src 'self'; script-src 'self'; ..." Header set Cache-Control "no-cache, no-store, must-revalidate" </IfModule> </Location> # /wp-admin/的CSP配置(你的原有规则加上Cache-Control) <Location /wp-admin/> <IfModule mod_headers.c> Header always unset Content-Security-Policy Header unset Content-Security-Policy Header set Content-Security-Policy "default-src 'self' ps.w.org;" Header set Cache-Control "no-cache, no-store, must-revalidate" </IfModule> </Location>
no-cache强制浏览器每次验证资源新鲜度,no-store彻底禁止缓存,双管齐下避免CSP规则被缓存。
3. 清理现有缓存并更新ServiceWorker
已经存在的旧缓存可能还在搞事情,需要强制清理:
在ServiceWorker的activate事件里删除所有旧缓存:
self.addEventListener('activate', (event) => { event.waitUntil( caches.keys().then((cacheNames) => { return Promise.all( cacheNames.map((cacheName) => { // 删除所有旧缓存,只保留新的缓存版本 return caches.delete(cacheName); }) ); }) ); });
同时在主页面的注册代码里添加更新提示,确保用户能加载最新的ServiceWorker:
navigator.serviceWorker.register('/sw.js').then((registration) => { registration.addEventListener('updatefound', () => { const newWorker = registration.installing; newWorker.addEventListener('statechange', () => { if (newWorker.state === 'installed' && navigator.serviceWorker.controller) { console.log('新的ServiceWorker已就绪,请刷新页面生效'); } }); }); });
4. 验证生效情况
用浏览器开发者工具的Network面板,查看/wp-admin/页面的响应头:
- 确认
Content-Security-Policy是你配置的宽松版本 - 确认
Cache-Control是no-cache, no-store, must-revalidate
再到Application面板的Cache Storage里,检查是否没有/wp-admin/相关的缓存条目。
这样调整后,主站和/wp-admin/的CSP规则就会各自独立,不会再被ServiceWorker的缓存搞混了。
内容的提问来源于stack exchange,提问作者Zelda
相关产品推荐
相关产品推荐

