Spec-Zone.ru › Next.js

Политика безопасности контента

Политика безопасности контента (CSP) важна для защиты вашего приложения Next.js от различных угроз безопасности, таких как межсайтовый скриптинг (XSS), кликджекинг и другие атаки с внедрением кода.

Используя CSP, разработчики могут указать, какие источники допустимы для контента, скриптов, стилей, изображений, шрифтов, объектов, медиа (аудио, видео), фреймов и других элементов.

Примеры
  • Строгая CSP

Nonces

Nonce — это уникальная, случайная строка символов, созданная для одноразового использования. Она используется совместно с CSP для выборочного разрешения выполнения определённых встроенных скриптов или стилей, обойдя строгие директивы CSP.

Зачем использовать nonce?

Хотя CSP разработаны для блокировки вредоносных скриптов, существуют законные сценарии, где встроенные скрипты необходимы. В таких случаях nonces предоставляют способ разрешить выполнение этих скриптов, если у них есть правильный nonce.

Добавление nonce с помощью Middleware

Middleware позволяет добавлять заголовки и генерировать nonces до отрисовки страницы.

Каждый раз при просмотре страницы должен генерироваться новый nonce. Это означает, что необходимо использовать динамическую отрисовку для добавления nonces.

Например:

import { NextRequest, NextResponse } from 'next/server'
 
export function middleware(request: NextRequest) {
  const nonce = Buffer.from(crypto.randomUUID()).toString('base64')
  const cspHeader = `
    default-src 'self';
    script-src 'self' 'nonce-${nonce}' 'strict-dynamic';
    style-src 'self' 'nonce-${nonce}';
    img-src 'self' blob: data:;
    font-src 'self';
    object-src 'none';
    base-uri 'self';
    form-action 'self';
    frame-ancestors 'none';
    upgrade-insecure-requests;
`
  // Replace newline characters and spaces
  const contentSecurityPolicyHeaderValue = cspHeader
    .replace(/\s{2,}/g, ' ')
    .trim()
 
  const requestHeaders = new Headers(request.headers)
  requestHeaders.set('x-nonce', nonce)
 
  requestHeaders.set(
    'Content-Security-Policy',
    contentSecurityPolicyHeaderValue
  )
 
  const response = NextResponse.next({
    request: {
      headers: requestHeaders,
    },
  })
  response.headers.set(
    'Content-Security-Policy',
    contentSecurityPolicyHeaderValue
  )
 
  return response
}

По умолчанию Middleware выполняется для всех запросов. Можно фильтровать Middleware для выполнения на определённых путях, используя matcher.

Рекомендуется игнорировать совпадения с предварительными загрузками (из next/link) и статические ресурсы, которым не нужен заголовок CSP.

export const config = {
  matcher: [
    /*
     * Match all request paths except for the ones starting with:
     * - api (API routes)
     * - _next/static (static files)
     * - _next/image (image optimization files)
     * - favicon.ico (favicon file)
     */
    {
      source: '/((?!api|_next/static|_next/image|favicon.ico).*)',
      missing: [
        { type: 'header', key: 'next-router-prefetch' },
        { type: 'header', key: 'purpose', value: 'prefetch' },
      ],
    },
  ],
}

Чтение nonce

Теперь вы можете прочитать nonce из Server Component, используя headers:

import { headers } from 'next/headers'
import Script from 'next/script'
 
export default function Page() {
  const nonce = headers().get('x-nonce')
 
  return (
    <Script
      src="https://www.googletagmanager.com/gtag/js"
      strategy="afterInteractive"
      nonce={nonce}
    />
  )
}

Без Nonces

Для приложений, которым не нужны nonces, вы можете установить заголовок 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, ''),
          },
        ],
      },
    ]
  },
}

История версий

Рекомендуется использовать v13.4.20+ версии Next.js для правильной обработки и применения nonces.

© 2024 Vercel, Inc.
Licensed under the MIT License.
https://nextjs.org/docs/app/building-your-application/configuring/content-security-policy

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API