如何在Next.js(Pages Router)中配置CSP仅允许指定脚本并拦截其余脚本?
Next.js Pages Router 内容安全策略(CSP)配置指南:仅允许可信脚本
一、解决你遇到的Nonce拦截内部脚本问题
你用nonce后内部脚本被拦,核心原因是没把nonce正确注入到Next.js自动生成的脚本标签里。Pages Router需要通过自定义_document.js实现nonce的动态生成与绑定,步骤如下:
- 生成请求级唯一nonce(绝不能硬编码,否则有安全风险)
- 给Next.js自动注入的脚本添加nonce属性
- 在CSP头中匹配该nonce
创建pages/_document.js,代码如下:
import Document, { Html, Head, Main, NextScript } from 'next/document'; import crypto from 'crypto'; class MyDocument extends Document { static async getInitialProps(ctx) { const initialProps = await Document.getInitialProps(ctx); // 生成16位随机nonce,每个请求唯一 const nonce = crypto.randomBytes(16).toString('hex'); // 设置CSP头,包含nonce和可信第三方域名 ctx.res.setHeader( 'Content-Security-Policy', `default-src 'self'; script-src 'nonce-${nonce}' 'strict-dynamic' https://trusted-ad.com https://trusted-thirdparty.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://trusted-ad.com; object-src 'none';` ); return { ...initialProps, nonce }; } render() { return ( <Html> <Head /> <body> <Main /> {/* 给Next.js自动脚本绑定nonce */} <NextScript nonce={this.props.nonce} /> </body> </Html> ); } } export default MyDocument;
这里的'strict-dynamic'很关键:它允许受信任(带nonce)的脚本动态加载其他子脚本,不用逐个添加域名,适合广告这类嵌套加载的场景。
二、固定可信来源的CSP配置(无需nonce)
如果你的第三方脚本来源是固定的(比如分析工具、广告平台的固定域名),直接在next.config.js里配置静态CSP即可:
/** @type {import('next').NextConfig} */ const nextConfig = { async headers() { return [ { source: '/:path*', headers: [ { key: 'Content-Security-Policy', value: `default-src 'self'; script-src 'self' https://trusted-ad.com https://trusted-analytics.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://trusted-ad.com; connect-src 'self' https://api.your-domain.com https://trusted-analytics.com; object-src 'none'; frame-src 'self' https://trusted-embed.com;`, }, ], }, ]; }, }; module.exports = nextConfig;
注:'unsafe-inline'多数情况下不能省——Next.js的内联样式会被拦截,除非你完全移除了所有内联样式。
三、调试技巧
- 打开浏览器控制台(F12),查看CSP报错:会明确告诉你哪个资源被拦截、需要添加到哪个指令里
- 测试阶段用
Content-Security-Policy-Report-Only头:只上报拦截日志,不实际阻断请求,方便调整策略 - 若动态脚本来源不固定,优先用
nonce + strict-dynamic组合,比逐个加域名更灵活安全
内容的提问来源于stack exchange,提问作者Raja Jahanzaib
相关产品推荐
相关产品推荐

