تنظیم CSP بدون nonce در Next.js – استفاده از Subresource Integrity و پیکربندی امن در محیط‌های تولید

اگر اپلیکیشن شما به nonce نیاز ندارد، می‌توانید هدر Content Security Policy را مستقیماً در فایل next.config.js تنظیم کنید. همچنین Next.js از Subresource Integrity (SRI) به‌صورت آزمایشی پشتیبانی می‌کند که امکان استفاده از CSP سخت‌گیرانه را بدون نیاز به رندرینگ پویا فراهم می‌سازد. این مقاله نحوهٔ پیکربندی CSP، فعال‌سازی SRI، تفاوت‌های محیط توسعه و تولید، و نکات امنیتی مربوط به اسکریپت‌های ثالث را بررسی می‌کند.

CSP without nonceSubresource IntegritySecurity configurationStatic Next.js

~5 دقیقه مطالعه • بروزرسانی ۴ آبان ۱۴۰۴

تنظیم CSP بدون استفاده از nonce


اگر اپلیکیشن شما به اجرای اسکریپت‌های inline نیازی ندارد، می‌توانید هدر CSP را مستقیماً در فایل next.config.js تنظیم کنید:

const cspHeader = `
  default-src 'self';
  script-src 'self' 'unsafe-eval' 'unsafe-inline';
  style-src 'self' 'unsafe-inline';
  img-src 'self' blob: data:;
  font-src 'self';
  object-src 'none';
  base-uri 'self';
  form-action 'self';
  frame-ancestors 'none';
  upgrade-insecure-requests;
`

module.exports = {
  async headers() {
    return [
      {
        source: '/(.*)',
        headers: [
          {
            key: 'Content-Security-Policy',
            value: cspHeader.replace(/\n/g, ''),
          },
        ],
      },
    ]
  },
}

استفاده از Subresource Integrity (SRI)


Next.js به‌صورت آزمایشی از SRI برای CSP مبتنی بر هش پشتیبانی می‌کند. این روش امکان استفاده از رندرینگ استاتیک و کش CDN را فراهم می‌سازد.


فعال‌سازی SRI


در فایل next.config.js تنظیم زیر را اضافه کنید:

const nextConfig = {
  experimental: {
    sri: {
      algorithm: 'sha256',
    },
  },
}

module.exports = nextConfig

پیکربندی CSP همراه با SRI


می‌توانید همچنان از سیاست‌های CSP خود استفاده کنید. SRI به‌صورت مستقل هش‌های امنیتی را به اسکریپت‌ها اضافه می‌کند:

const cspHeader = `
  default-src 'self';
  script-src 'self';
  style-src 'self';
  img-src 'self' blob: data:;
  font-src 'self';
  object-src 'none';
  base-uri 'self';
  form-action 'self';
  frame-ancestors 'none';
  upgrade-insecure-requests;
`

module.exports = {
  experimental: {
    sri: {
      algorithm: 'sha256',
    },
  },
  async headers() {
    return [
      {
        source: '/(.*)',
        headers: [
          {
            key: 'Content-Security-Policy',
            value: cspHeader.replace(/\n/g, ''),
          },
        ],
      },
    ]
  },
}

مزایای SRI نسبت به nonce


  • پشتیبانی از رندرینگ استاتیک
  • سازگاری با کش CDN
  • عملکرد بهتر بدون نیاز به SSR در هر درخواست
  • امنیت در زمان build با تولید هش‌های رمزنگاری‌شده

محدودیت‌های SRI


  • آزمایشی بودن ویژگی
  • فقط در Webpack فعال است (نه Turbopack)
  • فقط در App Router پشتیبانی می‌شود
  • فقط در زمان build قابل استفاده است

تفاوت محیط توسعه و تولید


محیط توسعه


در حالت توسعه، برای پشتیبانی از ابزارهای دیباگ باید 'unsafe-eval' فعال باشد:

const isDev = process.env.NODE_ENV === 'development'

const cspHeader = `
  default-src 'self';
  script-src 'self' 'nonce-${nonce}' 'strict-dynamic' ${isDev ? "'unsafe-eval'" : ''};
  style-src 'self' ${isDev ? "'unsafe-inline'" : `'nonce-${nonce}'`};
  ...
`

محیط تولید


  • اطمینان حاصل کنید که Proxy روی همهٔ مسیرهای لازم اجرا می‌شود
  • مطمئن شوید که CSP اجازهٔ بارگذاری فایل‌های استاتیک Next.js را می‌دهد
  • دامنه‌های اسکریپت‌های ثالث را به CSP اضافه کنید

اسکریپت‌های ثالث و CSP


برای استفاده از سرویس‌هایی مانند Google Tag Manager:

import { GoogleTagManager } from '@next/third-parties/google'
import { headers } from 'next/headers'

export default async function RootLayout({ children }) {
  const nonce = (await headers()).get('x-nonce')

  return (
    <html lang="en">
      <body>
        {children}
        <GoogleTagManager gtmId="GTM-XYZ" nonce={nonce} />
      </body>
    </html>
  )
}

نمونهٔ CSP برای اسکریپت‌های گوگل


const cspHeader = `
  default-src 'self';
  script-src 'self' 'nonce-${nonce}' 'strict-dynamic' https://www.googletagmanager.com;
  connect-src 'self' https://www.google-analytics.com;
  img-src 'self' data: https://www.google-analytics.com;
`

خطاهای رایج در CSP


  • استایل‌های inline: از کتابخانه‌هایی استفاده کنید که از nonce پشتیبانی می‌کنند یا استایل‌ها را به فایل خارجی منتقل کنید
  • importهای پویا: مطمئن شوید که در script-src مجاز هستند
  • WebAssembly: در صورت نیاز 'wasm-unsafe-eval' را اضافه کنید
  • Service Worker: سیاست‌های مناسب برای اسکریپت‌های آن را تنظیم کنید

تاریخچه نسخه‌ها


نسخهتغییرات
v14.0.0افزوده شدن پشتیبانی آزمایشی از SRI برای CSP مبتنی بر هش
v13.4.20پیشنهاد شده برای مدیریت صحیح nonce و هدرهای CSP

جمع‌بندی


اگر اپلیکیشن شما به nonce نیاز ندارد، می‌توانید با استفاده از SRI و تنظیم مستقیم هدر CSP امنیت را حفظ کرده و از مزایای رندرینگ استاتیک و کش CDN بهره‌مند شوید. این روش برای اپلیکیشن‌هایی که به عملکرد بالا و امنیت در زمان build نیاز دارند، بسیار مناسب است.


نوشته و پژوهش شده توسط دکتر شاهین صیامی