如何在.htaccess中配置Content-Security-Policy(CSP)以规避unsafe-inline/-eval,同时解决网站加载异常问题
如何在.htaccess中配置Content-Security-Policy(CSP)以规避unsafe-inline/-eval,同时解决网站加载异常问题
看起来你已经折腾好几个小时了,别着急,我们一步步排查和解决这个CSP配置的问题:
第一步:先定位核心问题——查看浏览器控制台报错
网站白屏但源码能加载,大概率是CSP拦截了部分资源(脚本、样式或其他)。你可以打开浏览器的F12开发者工具,切换到Security面板,里面会清晰显示哪条CSP规则拦截了哪个资源,这是最精准的排查依据。
第二步:修正你的Nonce配置问题
你尝试用nonce来规避inline限制,但这里有几个细节没处理对:
确保Apache的mod_unique_id模块已启用
你用到了%{UNIQUE_ID}变量,需要先确认Apache加载了mod_unique_id模块:- 打开Apache的配置文件(比如httpd.conf),检查是否有
LoadModule unique_id_module modules/mod_unique_id.so这一行,没有的话添加后重启Apache。 - 如果暂时无法启用这个模块,可以在PHP里自己生成随机nonce:
bin2hex(random_bytes(16)),替代$_SERVER['UNIQUE_ID']。
- 打开Apache的配置文件(比如httpd.conf),检查是否有
修正.htaccess里的CSP规则
原配置里的'nonce-%{UNIQUE_ID}e'多了个多余的e,正确写法应该是:<IfModule mod_headers.c> Header set X-XSS-Protection "1; mode=block" Header set X-Frame-Options "SAMEORIGIN" Header set X-Content-Type-Options "nosniff" Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains" # 修正后的CSP配置,nonce变量无需额外后缀 Header set Content-Security-Policy "default-src 'self' data:; style-src 'self'; script-src 'self' 'nonce-%{UNIQUE_ID}'; frame-src https:;" Header set Referrer-Policy "same-origin" Header set Feature-Policy "geolocation 'self'; vibrate 'none'" </IfModule>确保页面内所有脚本都带上正确的nonce
不仅是外部脚本,如果你页面里有内联脚本(比如<script>...</script>)或者内联样式(<style>...</style>),也需要给它们加上nonce属性,否则会被CSP拦截:<!-- 外部脚本 --> <script src="scripts/jquery.js" nonce="<random-nonce>"></script> <script src="scripts/main.js" nonce="<random-nonce>"></script> <!-- 如果有内联脚本,也要加nonce --> <script nonce="<random-nonce>"> // 内联代码内容 </script>
第三步:排查是否存在隐藏的内联代码
很多时候CSP报错不是因为外部资源,而是页面里的内联事件处理器(比如<button onclick="xxx()">)、内联样式或者动态生成的脚本/样式,这些都会触发unsafe-inline的拦截。
- 优先把内联事件处理器改成事件监听(比如在main.js里用
addEventListener) - 把内联样式移到style.css文件中
- 如果必须保留内联内容,除了用nonce,也可以计算内联代码的哈希值,加到CSP规则里(比如
script-src 'self' 'sha256-xxxxxx')
第四步:简化CSP规则逐步测试
如果还是有问题,可以先写一个最基础的CSP规则测试,再逐步添加限制:
Header set Content-Security-Policy "default-src 'self'; script-src 'self' 'nonce-%{UNIQUE_ID}'; style-src 'self'; img-src 'self' data:;"
确认基础规则生效后,再把frame-src、referrer-policy等其他规则加回来。
备注:内容来源于stack exchange,提问作者Wima




