Adobe Commerce:在内容安全策略(CSP)限制模式下,签出页面出现内联JavaScript问题

在启用 CSP限制模式 的情况下,本文为签出期间在Adobe Commerce 2.4.7中通过Adobe Commerce管理和Google标签管理器添加自定义JavaScript时遇到的一些问题提供了详细的解释和解决方案。 具体来说,它处理​ 拒绝执行内联脚本,因为它违反了浏览器控制台日志中显示的以下内容安全策略directiv e错误消息。 此错误表示内联脚本因严格的CSP设置而被阻止,这些设置旨在通过阻止执行未经授权的脚本来增强安全性。

从Adobe Commerce 2.4.7开始,对于店面和管理区域中的付款页面,CSP配置为默认在 限制模式 下运行。 对于所有其他页面,它以 仅报告 模式运行。 此增强功能要求将所有JavaScript列入白名单,包括与第三方服务或扩展的自定义集成。 未能将自定义JavaScript列入白名单会导致浏览器在管理员区域和店面区域的结账和支付页面上阻止执行这些脚本。

本文中提供的解决方案不限于解决通过Google管理员的设计配置添加的Commerce Tag Manager (GTM)内联JavaScript或JavaScript存在的问题。 它们也可以应用于已将内联JavaScript添加到Commerce代码的其他方案。 这包括直接嵌入到Adobe Commerce生态系统模板、模块或任何其他部分的自定义脚本。 通过执行上述步骤,您可以确保所有内联脚本都已正确列入白名单并允许执行,从而在遵守CSP限制的同时维护自定义代码的功能。

注意:强烈建议通过内容安全策略 Adobe Commerce文档中所述的方法引入新的JavaScript。 这些方法可确保您的脚本符合CSP准则,从而增强Commerce网站的安全性。 通过遵循脚本包含的最佳实践(例如使用具有适当的nonce或哈希属性的外部脚本),您可以将安全漏洞的风险降至最低,并确保提供更顺畅、更安全的用户体验。

描述 description

查看有关环境和要再现的步骤的详细信息。

环境

云基础架构上的Adobe Commerce和Adobe Commerce内部部署:

  • 2.4.7及更高版本
  • 2.4.6像素
  • 2.4.5-pX
  • 2.4.4像素

问题/症状

以下是因CSP限制导致脚本无法在结账和付款页面上执行时的常见问题及其解决方案列表:

  • 使用内联JavaScript的GTMHTML标记
  • 主题配置中的内联JS

具有内联JavaScript的 GTMHTML标记

在Google Tag Manager中配置的自定义HTML标记中的JavaScript在店面结账或付款页面上无法正常执行。

重现问题的步骤

  1. 使用包含内联JavaScript的自定义HTML标记配置Google标记管理器。
  2. 将Google Tag Manager与Adobe Commerce集成。 有关步骤,请参阅《Adobe Commerce促销指南》中的配置Google Analytics帐户
  3. 将产品添加到购物车并继续结帐。
  4. 在任何支持的浏览器中打开Developer Console。

预期的结果

控制台中不会显示与自定义JavaScript相关的错误,并且脚本执行成功。

实际结果

错误​ 拒绝执行脚本,因为内容安全策略 ​的script-src指令中未出现该脚本的哈希、nonce或“unsafe-inline”。 控制台中存在,并且脚本不会执行。

注意:确切的错误消息可能因浏览器而异,但它通常表示CSP阻止了脚本。 这些消息突出显示,由于当前的CSP设置,不允许运行脚本。

原因

Google Tag Manager自定义HTML标签中的JavaScript由Google Tag Manager本身注入店面。 因此,此脚本未在CSP设置中预先列入白名单,因此浏览器会阻止其执行。 出现这种情况是因为CSP限制执行任何未明确允许的内联脚本,从而确保增强的安全性,但需要为自定义脚本进行额外的配置。

解决方案

  • 将JavaScript哈希列入白名单。 有关详细信息,请参阅本文中的解决方法部分。
  • 使用Nonce签名Google Tag Manager自定义HTMLJavaScript 。 有关详细信息,请参阅本文中的解决方法部分。

主题配置中的内联JS

此问题非常类似于包含内联JavaScript的自定义HTML标记问题。 不同之处在于,该脚本不是在Google标签管理器管理中添加JavaScript,而是添加到某个可用范围的设计配置页面的Adobe Commerce管理中。 使用此方法,可以将内联HTML片段、JavaScript或样式表添加到主题的页眉或页脚。 与任何其他内联JavaScript一样,它要求在结账页面上执行白名单。

重现问题的步骤

  1. 设计配置中的HTML页眉页脚配置为包含内联JavaScript。
  2. 将产品添加到购物车并继续结帐。
  3. 在任何支持的浏览器中打开Developer Console。

预期的结果

控制台中不会显示与自定义JavaScript相关的错误,并且脚本执行成功。

实际结果

错误​ 拒绝执行脚本,因为内容安全策略 ​的script-src指令中未出现该脚本的哈希、nonce或“unsafe-inline”。 控制台中存在,并且脚本不会执行。

注意:确切的错误消息可能因浏览器而异,但它通常表示CSP阻止了脚本。 这些消息突出显示,由于当前的CSP设置,不允许运行脚本。

原因

设计配置的HTML头中的脚本和样式表以及页脚部分中的其他HTML是混合输入字段。 这些字段可以包含HTML、样式表或JavaScript。 由于此动态内容,无法自动对这些字段的内容进行哈希处理并将其列入白名单。 因此,如果将JavaScript添加到这两个字段的任何一个,则必须手动将其列入白名单才能在签出页面上执行。 这是必需的,因为CSP会限制执行任何明确不允许的内联脚本。 虽然这可以确保增强的安全性,但还需要额外的配置以允许自定义脚本。

解决方案

将JavaScript哈希列入白名单。 有关详细信息,请参阅本文中的解决方法部分。

解决方法 resolution

每个提供的解决方案都独立运行。 仔细评估和选择最能满足您特定需求的解决方案。 考虑实施的上下文、所涉及脚本的性质以及Adobe Commerce站点的安全要求,以确定适当的解决方案。

将JavaScript哈希列入白名单

要解决此问题,自定义内联JavaScripts必须在CSP设置中列入白名单。 这样可以确保脚本被明确允许执行,而绕过默认的安全限制。

将GTM自定义HTML脚本列入白名单具有挑战性,因为GTM可能会先修改JavaScript,然后再将其注入文档对象模型(DOM),包括删除换行符和注释。 此外,Google的算法可能会随着时间的推移而发生更改,恕不另行通知,这可能会使哈希失效。 您需要使用Google Chrome生成的哈希(如步骤C中所述),并准备定期更新白名单中的哈希。 或者,考虑使用Nonce签署Google Tag Manager自定义HTMLJavaScript,以获得更强大的解决方案。

  1. 为JavaScript主体生成哈希。

    注意:若要成功生成哈希,需要将脚本送入哈希生成器。 请务必仔细复制脚本。 在复制所有换行符和任何可能的不可见字符时,排除JavaScript的开始和结束脚本标记。 这包括开头script或其他标记之后的换行符(如果有)。 如果哈希与脚本不完全匹配,则会拒绝执行。

    1. 在Mac上,您可以将整个脚本主体(包括开始script标记之后的任何换行符)复制到剪贴板,然后在终端中执行以下命令。

      php -r "echo base64_encode(hash('sha256', shell_exec('pbpaste'), true)) 。 PHP_EOL;”

      此PHP命令获取剪贴板内容,计算其SHA-256哈希,将哈希转换为二进制文件,然后以base64格式对其进行编码,最后打印结果。

    2. 您可以使用各种联机哈希生成器为脚本创建所需的哈希。

      警告: 请务必了解,如果您决定使用第三方在线服务来为CSP生成哈希,则必须考虑隐私影响。 某些服务可能会将您的脚本上传到其服务器以进行哈希处理,这可能会危害脚本中包含的敏感数据。 为了降低此风险,建议使用受信任的工具或脚本在本地生成哈希,以确保您的数据安全且私密。

    3. 您可以使用Google Chrome浏览器获取已为JavaScript生成的哈希,该哈希在签出页面上被拒绝从Developer Console执行。

      1. 使用添加了阻止的JavaScript的Google Chrome浏览器转到签出页面。

      2. Cmd+Option+J (在macOS上)或Ctrl+Shift+J (在Windows/Linux上)打开Developer Console。

      3. 在控制台中找到CSP错误消息。

      4. 在错误消息的最后一句中,您会找到为被阻止的脚本生成的哈希代码。

      5. 复制sha256-之后的代码,省略引号。

        注意: 如果您有多个被阻止的JavaScript文件,则控制台中会显示多条错误消息。 确保您确定要列入白名单的确切JavaScript。 建议您逐个添加和测试每个JavaScript文件,以避免将错误的脚本错误地列入白名单。

        有关如何为内联JavaScript生成哈希的更多详细信息,请参阅Adobe Commerce开发人员内容安全策略指南中的高级CSP配置

  2. 将脚本哈希列入白名单。 首先将哈希添加到模块的csp_whitelist.xml文件:

    <>

    < value id="my-script" type="hash" algorithm="sha256"> YOUR-HASH-1< /value>

    < /values>

    其中,YOUR-HASH-1应替换为您在上一步中获得的哈希值。
    要将多个脚本列入白名单,请为每个脚本添加<> < /value>标记,例如:

    <>

    < value id="my-script" type="hash" algorithm="sha256"> YOUR-HASH-1< /value>

    < value id="my-new-script" type="hash" algorithm="sha256"> YOUR-HASH-2< /value>

    <>

    如果文件不存在,请创建该文件并包含以下内容。

    < ?xml version="1.0" encoding="UTF-8"?>

    < csp_whitelist xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:noNamespaceSchemaLocation="urn:magento:模块:Magento_Csp:etc/csp_whitelist.xsd">

    <策略>

    <策略id="script-src">

    <>

    < value id="my-script" type="hash" algorithm="sha256"> YOUR-HASH-1< /value>

    < value id="my-new-script" type="hash" algorithm="sha256"> YOUR-HASH-2< /value>

    < /values>

    < /policy>

    < /policies>

    < /csp_whitelist>

  3. 刷新缓存:将哈希添加到csp_whitelist.xml文件后,必须刷新缓存以确保更改生效。 刷新缓存可清除存储的数据,以便立即应用更新的CSP设置。 您可以通过导航到 系统 来刷新缓存 > 工具 在Commerce管理面板中> 缓存管理,然后选择 刷新Magento缓存 按钮。  或者,使用命令行:

    bin/magento cache:flush

    此命令清除所有缓存类型,确保系统能够识别新的CSP设置。

使用Nonce 签署Google Tag Manager自定义HTMLJavaScript

允许在GTM中执行JavaScript的另一种方法是,向脚本的开头标记添加nonce。 nonce属性提供了一种将特定的内联脚本动态列入白名单的方法,确保允许执行这些脚本。 有关更多详细信息,请参阅使用CSP Nonce提供程序以允许使用内联脚本文档。

警告: 请记住,如果GTM帐户被破坏,攻击者可以将恶意JavaScript注入店面,并使用nonce签名,从而允许执行。 这可能会导致在结账过程中窃取敏感数据。

Adobe Commerce开发部分

注意:在Adobe Commerce 2.4.8及更高版本中,CSP Nonce变量注入将开箱即用。 如果您在早期版本的Adobe Commerce中实施此自定义注入,请在升级到Adobe Commerce 2.4.8或更高版本之前回滚这些自定义项。 如果您正在运行Adobe Commerce 2.4.8或更高版本,请转至GTM配置部分。

  1. 在自定义模块中,利用CSP Nonce提供程序,并将nonce传递给JavaScript。 有关更多详细信息,请参阅Adobe Commerce开发人员文档中的Basic Template Concepts

  2. 使用JavaScript将全局变量注入nonce:

    <脚本>

    window.cspNonce = config.cspNonce;

    < /script>

  3. 此脚本使用当前nonce的值设置全局变量cspNonce,之后可以在Google标签管理器变量中捕获该变量,并将其用于签署自定义HTML脚本,以确保允许在CSP下执行这些脚本。 应将其插入所有页面。

GTM配置部分

  1. 从GTM捕获此变量的值:

    1. 创建类型为 Google变量 的JavaScript标签管理器变量。 为变量提供一个清晰的名称,因为稍后将引用该变量。 在此示例中,它是gtmNonce

    2. 全局变量名称 设置为在上一步中插入的JavaScript全局变量的名称。 在此示例中,它是cspNonce

  2. 修改包含需要在签出时执行的JavaScript的自定义HTML块,使其包含nonce属性,并引用您之前创建的GTM变量。

<脚本nonce="{{gtmNonce}}">
                     console.log(“这是一个测试”);
              < /script>

注意:请确保选中 Support document.write 复选框,因为这对于脚本正常运行至关重要。

通过添加nonce属性,使用提供的nonce对脚本进行签名,使其能够在内容安全策略(CSP)下安全执行。

recommendation-more-help
3d58f420-19b5-47a0-a122-5c9dab55ec7f