如何在Next.js中将nonce添加到内联样式和脚本中?

3b6akqbq  于 2023-06-29  发布在  其他
关注(0)|答案(1)|浏览(176)

假设Content-Security-Policy策略如下:

default-src 'self'; script-src https://ray.run

Next.js由于以下错误而无法运行:
拒绝应用内联样式,因为它违反了以下内容安全策略指令:“default-src 'self'"。启用内联执行需要'unsafe-inline'关键字、哈希('sha 256-zu 3 j 41 gcw 4FOWZYIiUz/VyL 9 HYakAfKLQFMCEcWNkAc =')或nonce('nonce-...')。请注意,哈希不适用于事件处理程序,样式属性和JavaScript:除非存在“unsafe-hashes”关键字。还请注意,没有显式设置“style-src”,因此使用“default-src”作为回退。
拒绝执行内联脚本,因为它违反了以下内容安全策略指令:“script-src https://ray.run“。启用内联执行需要'unsafe-inline'关键字、哈希('sha 256-qJ 8 ozvdSL 8lvQo 3 N 0 L0 SYjL 5lY 0 bLZcaD/xXL 4 BlEpQ =')或nonce('nonce-...')。
根据错误提示,我有两个选择:允许“unsafe-inline”或添加nonce。然而,阅读Next.js文档,我找不到任何关于如何将nonce导入内联样式和脚本的内容。
对于上下文,我使用next.js13与React Server Component(RSC)。

63lcw9qa

63lcw9qa1#

要将nonce属性添加到<script><styles>标记中,需要在middleware.ts文件中定义content-security-policy头(适用于next@13.4.0及更高版本)。
Next.js(在renderToHTMLOrFlight函数中)解析头部以提取nonce值,然后将其添加到生成的HTML标记中。
下面是一个middleware函数的例子:

import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
  const nonce = crypto.randomUUID();
  const csp = `script-src 'nonce-${nonce}';`;

  // Clone the request headers
  const requestHeaders = new Headers(request.headers);

  // Set the CSP header so that Next.js can read it and generate tags with the nonce
  requestHeaders.set('content-security-policy', csp);

  // Create new response
  const response = NextResponse.next({
    request: {
      // New request headers
      headers: requestHeaders
    }
  });

  // Also set the CSP header in the response so that it is outputted to the browser
  response.headers.set('content-security-policy', csp);

  return response;
}

如有必要,您还可以添加自定义请求头来读取页面中的nonce值:

requestHeaders.set('x-nonce', nonce);

更进一步,根据mdn documentation
每次页面加载时,随机数的生成方式都应该不同(随机数只生成一次!).
这意味着您不能在next.config.js文件中设置它,因为它只会在构建时生成一次。在middleware函数中,将为每个请求重新生成nonce值。
最后但并非最不重要的一点是,这只适用于dynamic routes,而不适用于静态渲染,因为nonce的值对于每个页面加载都必须不同。
代码最初由@danieltott在GitHub上发布:https://github.com/vercel/next.js/issues/43743#issuecomment-1542684019
相关讨论:

相关问题