You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Next.js(Pages Router)中配置CSP仅允许指定脚本并拦截其余脚本?

Next.js Pages Router 内容安全策略(CSP)配置指南:仅允许可信脚本

一、解决你遇到的Nonce拦截内部脚本问题

你用nonce后内部脚本被拦,核心原因是没把nonce正确注入到Next.js自动生成的脚本标签里。Pages Router需要通过自定义_document.js实现nonce的动态生成与绑定,步骤如下:

  1. 生成请求级唯一nonce(绝不能硬编码,否则有安全风险)
  2. 给Next.js自动注入的脚本添加nonce属性
  3. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 18:22:17