TLDR:我在使用Material-UI(服务器端渲染)和Nginx(使用反向代理)为NextJS设置CSP时遇到了麻烦。
目前,我在加载材质-UI样式表和加载自己的样式时遇到问题
使用来自@material-ui/core/styles
的makeStyles
注意事项:
- 我访问https://material-ui.com/styles/advanced/#next-js以启用SSR
- https://github.com/mui-org/material-ui/tree/master/examples/nextjs
- 我查看了https://material-ui.com/styles/advanced/#how-does-one-implement-csp,但我不确定如何让nginx遵循
nonce
值,因为nonce是作为不可预测的字符串生成的。
默认.conf(nginx)
# https://www.acunetix.com/blog/web-security-zone/hardening-nginx/
upstream nextjs_upstream {
server localhost:3000;
# We could add additional servers here for load-balancing
}
server {
listen $PORT default_server;
# redirect http to https. use only in production
# if ($http_x_forwarded_proto != 'https') {
# rewrite ^(.*) https://$host$request_uri redirect;
# }
server_name _;
server_tokens off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
# hide how is app powered. In this case hide NextJS is running behind the scenes.
proxy_hide_header X-Powered-By;
# set client request body buffer size to 1k. Usually 8k
client_body_buffer_size 1k;
client_header_buffer_size 1k;
client_max_body_size 1k;
large_client_header_buffers 2 1k;
# ONLY respond to requests from HTTPS
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload";
# to prevent click-jacking
add_header X-Frame-Options "DENY";
# don't load scripts or CSS if their MIME type as indicated by the server is incorrect
add_header X-Content-Type-Options nosniff;
add_header 'Referrer-Policy' 'no-referrer';
# Content Security Policy (CSP) and X-XSS-Protection (XSS)
add_header Content-Security-Policy "default-src 'none'; script-src 'self'; object-src 'none'; style-src 'self' https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap ; form-action 'none'; frame-ancestors 'none'; base-uri 'none';" always;
add_header X-XSS-Protection "1; mode=block";
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
location / {
# limit request types to HTTP GET
# ignore everything else
limit_except GET { deny all; }
proxy_pass http://nextjs_upstream;
}
}
5条答案
按热度按时间vfwfrxfs1#
我找到的解决方案是在_document.tsx中向内联js和css添加nonce值
_文件.tsx
使用uuid v4生成nonce,并使用crypto nodejs模块将其转换为base64。然后创建内容安全策略并添加生成的nonce值。创建函数以完成创建nonce和生成CSP,并返回CSP字符串沿着nonce
在HTML Head中添加生成的CSP并添加 meta标记。
来源:https://github.com/vercel/next.js/blob/master/examples/with-strict-csp/pages/_document.js
nginx配置
请确保删除有关内容安全策略的添加标头。2它可能会覆盖CSP in _document.jsx文件。
替代解决方案
创建一个自定义服务器,并注入nonce和内容安全策略,这些可以在_document.tsx中访问
xkftehaa2#
建议在标题中设置内容安全策略,而不是在 meta标记中设置。在
NextJS
中,您可以通过修改next.config.js
在标题中设置CSP。下面是一个添加CSP标头的示例。
下一个文档:https://nextjs.org/docs/advanced-features/security-headers
2guxujil3#
是的,为了将CSP与Material-UI(和JSS)一起使用,您需要使用
nonce
。由于您有SSR,我看到两个选项:
1.您可以使用next-secure-headers包甚至Helmet在服务器端发布CSP头。我希望您找到一种方法,如何将
nonce
从Next传递到Material UI。1.你可以在
nginx
配置中发布CSP头(现在你是怎么做的),并通过nginx生成'nonce',即使它作为反向代理工作。你需要在nginx中有ngx_http_sub_module
或ngx_http_substitutions_filter_module
。TL;DR;详细说明它是如何工作的,请参见https://scotthelme.co.uk/csp-nonce-support-in-nginx/(这比使用
$request_id
nginx var要复杂一点)nszi6y054#
Nextjs配置支持CSP标头:
https://nextjs.org/docs/advanced-features/security-headers
nkoocmlb5#
客户端呈现应用程序的解决方案
使用中间件和getInitialProps可以实现此功能。您只需要SSR
<Head>{...}</Head>
就可以实现此功能。