nginx 托管 react 应用需适配严格 csp:统一静态资源路径、消除内联脚本/样式、配置 nonce/hash 机制;dangerouslysetinnerhtml 和手动 标签会破坏 csp,应改用安全渲染方式。

用 Nginx 托管 React 应用本身很简单,但加上严格的 CSP(Content Security Policy)防护后,容易因策略过严导致白屏、资源加载失败或 React 路由跳转异常。关键在于:静态资源路径要统一、内联脚本/样式必须消除、CSP 需适配 React 的运行时行为(如 eval、nonce 或 hash 机制),同时保留开发体验的灵活性。
构建 React 应用时规避内联风险
React 默认构建(npm run build)不会生成内联脚本或样式,但以下情况会破坏 CSP 安全性:
- 在 JSX 中写
dangerouslySetInnerHTML渲染未转义 HTML,可能引入内联<script></script>;应改用 DOM API 或安全渲染库 - 使用
style={{ color: 'red' }}是安全的(CSS 属性由 React 注入 style 标签外的 DOM 属性),但若手动插入<style>...</style>就触发style-src 'unsafe-inline'限制 - 避免在
index.html中添加内联<script></script>或<style></style>—— 所有逻辑应走打包产物(main.xxx.js、static/css/*.css)
Nginx 配置基础托管与 history 模式支持
React Router 使用 BrowserRouter 时依赖 HTML5 History API,需让 Nginx 将所有非静态资源请求回退到 index.html:
location / {
try_files $uri $uri/ /index.html;
}
同时确保静态文件正确服务:
location /static/ {
alias /var/www/my-react-app/build/static/;
expires 1y;
add_header Cache-Control "public, immutable";
}
注意:React 构建输出目录(如 build/)需完整部署到 Nginx 的 root,且 index.html 中的 <base href="/>%20%E4%B8%8E%E5%AE%9E%E9%99%85%E9%83%A8%E7%BD%B2%E8%B7%AF%E5%BE%84%E4%B8%80%E8%87%B4%EF%BC%88%E5%A6%82%E9%83%A8%E7%BD%B2%E5%9C%A8%E5%AD%90%E8%B7%AF%E5%BE%84%20/app/%EF%BC%8C%E5%88%99%E9%9C%80%E9%85%8D%E7%BD%AE%20homepage%20%E5%B9%B6%E8%B0%83%E6%95%B4%20Nginx%20location%20/app/%EF%BC%89%E3%80%82
%E9%85%8D%E7%BD%AE%E4%B8%A5%E6%A0%BC%E4%BD%86%E5%8F%AF%E7%94%A8%E7%9A%84%20CSP%20%E5%93%8D%E5%BA%94%E5%A4%B4
%0A%E7%9B%B4%E6%8E%A5%E5%9C%A8%20Nginx%20%E4%B8%AD%E7%94%A8%20add_header%20%E8%AE%BE%E7%BD%AE%20CSP%EF%BC%8C%E6%8E%A8%E8%8D%90%E4%BD%BF%E7%94%A8%20Content-Security-Policy%EF%BC%88%E8%80%8C%E9%9D%9E%E6%97%A7%E7%89%88%20X-Content-Security-Policy%EF%BC%89%EF%BC%9A
add_header%20Content-Security-Policy%20" default-src script-src style-src img-src data: https: font-src connect-src frame-ancestors base-uri form-action always>要点说明:
-
script-src不允许'unsafe-inline'或'unsafe-eval';React 生产包不含eval,但若用了Function构造器或某些第三方库(如部分图表库)可能触发,需查构建产物或替换库 - 用
sha256-xxx指定index.html中可能存在的内联脚本哈希(实际 React 构建不生成内联脚本,此值可省略;若有自定义<script></script>,需用openssl dgst -sha256 -binary 计算) -
connect-src必须包含 API 接口域名(如connect-src 'self' https://api.example.com),否则fetch或axios请求被拦截 -
frame-ancestors 'none'防止被嵌入 iframe;base-uri 'self'禁止修改<base>;form-action 'self'限制表单提交目标
调试 CSP 违规并持续优化
CSP 违规不会中断页面,但会在浏览器控制台报错,并可配置上报:
- 在 CSP 中加入
report-uri /csp-report或report-to csp-endpoint(需配合 Reporting API)收集违规详情 - 本地调试时,先用
Content-Security-Policy-Report-Only头,观察控制台警告再收紧策略,避免直接上线白屏 - 检查 Network 面板中哪些资源被阻止(Status 显示
blocked:csp),对照 CSP 规则补全对应src类型(如字体加载失败需加font-src) - 若使用 Google Analytics、Clarity 等第三方脚本,需显式加入
script-src和img-src(如https://www.google-analytics.com),并确认其是否支持 nonce/hash
不复杂但容易忽略:CSP 是声明式策略,不是开关;它依赖你对应用所有资源来源的清晰认知。从最小权限起步,逐项放开,比一开始就写宽泛策略更可靠。










