CSP 的 font-src 限制导致自定义字体加载失败怎么办?
我在 React 项目里用了 Google Fonts,但部署后控制台报错说被 CSP 的 font-src 策略拦截了,明明已经在 meta 标签里加了 ‘self’ 和 fonts.gstatic.com,还是不行。
试过把策略改成 font-src ‘self’ https://fonts.gstatic.com; 但还是加载不了,本地开发没问题,上线就挂。这是我的组件代码:
import { useEffect } from 'react';
function App() {
useEffect(() => {
const link = document.createElement('link');
link.href = 'https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap';
link.rel = 'stylesheet';
document.head.appendChild(link);
}, []);
return <div style={{ fontFamily: 'Inter, sans-serif' }}>Hello</div>;
}
font-src配置没覆盖到字体文件的实际请求路径。你虽然加了fonts.gstatic.com,但要注意 Google Fonts 的字体文件(.woff2、.woff等)并不是直接从fonts.googleapis.com加载的,而是由它返回的 CSS 再去请求fonts.gstatic.com的资源。但更关键的是:你动态插入的
标签里用的是fonts.googleapis.com,而 CSP 的style-src和font-src都是独立生效的。如果你的 CSP 里没把fonts.googleapis.com加进style-src,这个本身就会被拦截,根本不会触发后续的字体请求。所以先确认 CSP 里有没有同时满足:
-
style-src 'self' https://fonts.googleapis.com—— 允许加载 Google Fonts 的 CSS-
font-src 'self' https://fonts.gstatic.com—— 允许加载字体文件另外,你本地开发没问题,上线就挂,大概率是生产环境的 CSP 是通过 HTTP 响应头(
Content-Security-Policy)设置的,而不是标签。标签对 CSP 的支持很有限,比如font-src、frame-src这些指令在里基本被浏览器忽略(Chrome 就不认)。检查下服务器有没有通过响应头注入 CSP?比如 Nginx 里有没有类似:
如果有的话,确认没拼错、没漏分号、没用引号包住整个字符串(但指令值要用引号)。如果 CSP 是通过 Node.js / Express 设置的,也要检查是不是用了
helmet之类的中间件,可能默认配置太严格。最后顺手验证下:打开 Network 面板,看那个
Inter的 CSS 请求是不是 200,字体文件是不是 200 或 304,有没有被标记成(blocked:csp)。如果 CSS 请求被 block 了,就是style-src的问题;如果 CSS 加载了但字体 403 或 blocked,才是font-src没配对。顺带一提,
&是 HTML 转义符,JS 里应该用&,不过这个不影响 CSP,只是代码不规范而已。