WordPress中CSP script-src拦截内联脚本的解决方案咨询
解决WordPress中wp_localize_script内联脚本的CSP Nonce兼容问题
核心问题
wp_localize_script生成的内联脚本默认没有钩子直接添加nonce属性,这是你之前尝试的过滤器无效的根本原因。以下是两种经过验证的可行方案:
方案一:手动输出带Nonce的内联变量(推荐)
放弃wp_localize_script,改用钩子手动输出带nonce的内联脚本,确保CSP信任:
- 先确保你的nonce生成逻辑全局可用(避免重复生成):
function custom_nonce_value() { static $nonce; if (empty($nonce)) { $nonce = wp_create_nonce('csp-nonce'); } return $nonce; }
- 保持CSP头部配置不变(确保nonce一致):
function add_csp_header() { $nonce = custom_nonce_value(); $csp = "script-src 'nonce-$nonce'"; // 可按需添加其他信任源,比如 'self' header("X-Content-Type-Options: nosniff"); header("Referrer-Policy: strict-origin-when-cross-origin"); header("Content-Security-Policy: $csp"); } add_action('send_headers', 'add_csp_header');
- 注册并入队主脚本,同时用钩子输出带nonce的全局变量:
// 注册并入队主脚本 wp_register_script( 'dibujos', get_stylesheet_directory_uri() . '/js/dibujos.js', array('jquery'), '1.0.0', true); wp_enqueue_script('dibujos'); // 输出带nonce的内联变量 function output_archvar_with_nonce() { $nonce = custom_nonce_value(); $arch_var = array( 'url' => get_bloginfo('url') ); ?> <script nonce="<?php echo esc_attr($nonce); ?>"> var archVar = <?php echo wp_json_encode($arch_var); ?>; </script> <?php } add_action('wp_print_scripts', 'output_archvar_with_nonce', 11); // 优先级11,确保在dibujos脚本后输出
方案二:用过滤器给wp_localize_script的内联脚本添加Nonce
WordPress 5.7+提供了wp_inline_script_attributes过滤器,专门用于修改内联脚本标签的属性,正好适配wp_localize_script生成的代码:
- 保留你原有的
custom_nonce_value和add_csp_header函数,添加以下过滤器:
function add_nonce_to_localized_script($attrs, $handle, $position) { // 仅给关联到dibujos的内联脚本添加nonce if ($handle === 'dibujos') { $nonce = custom_nonce_value(); $attrs['nonce'] = esc_attr($nonce); } return $attrs; } add_filter('wp_inline_script_attributes', 'add_nonce_to_localized_script', 10, 3);
- 继续使用你原有的
wp_localize_script代码即可,过滤器会自动给生成的内联脚本标签加上nonce属性。
为什么之前的方法失效?
wp_script_attributes仅作用于外部脚本标签,不处理内联脚本;- 早期的
script_loader_tag写法无法匹配wp_localize_script生成的内联脚本,因为这类内联脚本的handle关联到主脚本,需要用专门的wp_inline_script_attributes过滤器; wp_add_inline_script若调用时机错误(比如脚本未注册就调用),会导致无法正确关联,需确保在脚本注册后、输出前执行。
内容的提问来源于stack exchange,提问作者timholz
相关产品推荐
相关产品推荐

