You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在.htaccess中配置Content-Security-Policy (CSP)随机数(nonce)时遭遇错误,寻求问题排查帮助

在.htaccess中配置Content-Security-Policy (CSP)随机数(nonce)时遭遇错误,寻求问题排查帮助

嘿,我来帮你梳理一下你遇到的问题,核心问题主要出在nonce的传递顺序和Apache配置的语法错误上,咱们一步步拆解:

首先,找出你代码里的几个关键问题:

  1. .htaccess里的SetEnv完全无效
    你在.htaccess里写了:

    SetEnv MY_CSP_NONCE "<?php echo $_SERVER['MY_CSP_NONCE']; ?>"
    

    Apache是不会解析PHP代码的!所以这个环境变量被设置成了字符串"<?php echo $_SERVER['MY_CSP_NONCE']; ?>",而不是你PHP生成的真实nonce值,这直接导致CSP头里的'nonce-%{ENV:MY_CSP_NONCE}'变成了无效的nonce,自然匹配不上你页面里的nonce。

  2. Apache Header指令的执行顺序早于PHP
    就算你用PHP的putenv()设置了环境变量,Apache在处理.htaccess的Header指令时,PHP脚本还没运行呢,所以Apache根本拿不到PHP生成的nonce值,顺序完全反了。

  3. CSP配置的语法错误
    你在style-src里嵌套了style-src-attr指令:

    style-src 'self' style-src-attr 'self' 'nonce-%{ENV:MY_CSP_NONCE}'
    

    这是错误的语法,style-src-attr是单独的CSP指令,不能放在style-src里面。这直接导致style-src指令无效,浏览器 fallback到了default-src,而你的default-src是'none',自然拒绝了内联样式。


接下来是具体的修复方案:

最靠谱的方式是把CSP头的设置从.htaccess移到PHP里,这样PHP生成nonce后可以直接同步设置CSP头,完美匹配页面里的nonce。

步骤1:修改.htaccess

移除这两行内容:

SetEnv MY_CSP_NONCE "<?php echo $_SERVER['MY_CSP_NONCE']; ?>"
Header always set Content-Security-Policy "expr=default-src 'none'; ..."  # 整行都删掉

步骤2:修改cookiesetter.php

让它生成nonce后直接输出CSP头:

<?php
// 生成安全的nonce
$nonce = rtrim(strtr(base64_encode(random_bytes(64)), '+/', '-_'), '=');

// 构建正确的CSP策略,注意修复style-src和style-src-attr的语法
$csp_policy = <<<CSP
default-src 'none'; 
script-src 'self' require-trusted-types-for 'script' https://www.googletagmanager.com https://www.facebook.com https://www.twitter.com https://www.instagram.com 'nonce-$nonce' 'strict-dynamic' 'wasm-eval' 'unsafe-eval'; 
script-src-elem 'self'; 
connect-src 'self'; 
img-src 'self' https://storage.googleapis.com data:; 
video-src 'self' https://storage.googleapis.com data:; 
style-src 'self' 'nonce-$nonce'; 
style-src-attr 'self' 'nonce-$nonce'; 
base-uri 'none'; 
object-src 'none'; 
frame-ancestors 'self'; 
frame-src 'self'; 
sandbox allow-same-origin allow-scripts allow-popups; 
media-src 'self'; 
worker-src 'self https://*.cloudflare.com'; 
manifest-src 'self'; 
child-src 'self'; 
prefetch-src 'self' https://storage.googleapis.com https://www.googletagmanager.com; 
form-action 'self' https://www.paystack.com; 
font-src 'self' data:; 
upgrade-insecure-requests
CSP;

// 输出CSP头
header("Content-Security-Policy: $csp_policy");
?>

步骤3:保留index.php里的nonce使用方式

你在index.php里的style和script标签加nonce的写法是对的,继续保留:

<?php include "cookiesetter.php" ?>
<html>
<head>
<title>Example</title>
<style nonce="<?php echo $nonce ?>">
bla bla bla
</style>
</head>
<body>
<script nonce="<?php echo $nonce ?>">
bla bla bla
</script>
</body>
</html>

关于mod_unique_id的问题

你之前用mod_unique_id报错,大概率是因为没在Apache里启用这个模块,或者在.htaccess里的配置方式不对。不过既然用PHP生成nonce的方式更灵活可控,咱们就用上面的方案就好啦。

备注:内容来源于stack exchange,提问作者Shasha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.21 07:39:53