加载 jQuery 等外部脚本时出现问题

回答 3 浏览 2119 2023-11-28

从今天早上开始,我在使用 Apps Script 部署网络应用程序时遇到了一个问题,这个程序以前运行得很好。当然,没有进行任何更改来证明这个问题是合理的。

外部脚本不会从 HTML 端加载,并且控制台中会出现新错误。

为了有一个可重现的例子:

Code.gs

function doGet() {

  var template = HtmlService.createTemplateFromFile('index');

  return template.evaluate()
                .setTitle('TEST')
                .addMetaTag('viewport', 'width=device-width, initial-scale=1')
                .setSandboxMode(HtmlService.SandboxMode.IFRAME)
}

index.html:

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  </head>
  <body>
        <div id="title">Hello</div>
  </body>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>

  <script>
    window.onload = function() {

      console.log('loaded');
      console.log($('#title').html());

    }
  </script>
</html>

控制台中的结果:

[ERROR] This document requires 'TrustedHTML' assignment. (jquery.min.js:2)

[ERROR] Uncaught TypeError: Failed to set the 'innerHTML' property on 'Element': This document requires 'TrustedHTML' assignment. (jquery.min.js:2)

[LOG] loaded

[ERROR] Uncaught ReferenceError: $ is not defined

源问题似乎是 <script src='' 加载 jQuery。但我没有注意到 Google 提供任何故障排除,这是对 Apps 脚本的新限制吗?

截图: “项目/控制台”/

Error Sources

Network + CSP

Waxim Corp 提问于2023-11-28
web.dev/articles/trusted-typesmplungjan 2023-11-28
我遇到了类似的问题,但我发现我的浏览器没有正确更新,完成更新后它现在可以完美运行。因此,我会尝试更新浏览器并确保其完成,然后再将时间浪费在困难的解决方案上。不过,它确实迫使我看一下 trustHTML。Cooper 2023-11-29
3 个回答
#1楼
得票数 11

我发现这个问题似乎与 Google 最近对内容安全策略 (CSP) 的更改有关,特别是影响了 AppScript 中 jQuery 的使用。此问题一直影响着众多开发者,您可以在此处的 Google 问题跟踪器上找到更多详细信息和正在进行的讨论:Google问题跟踪器 - CSP 和 jQuery 问题

根据我的发现,这个问题似乎是基于 Chromium 的浏览器特有的。在 Chrome 和 Edge 等环境中,包括它们的隐身模式,jQuery 无法正常运行。不过,我发现 Firefox 并没有遇到这个问题,并且可以按预期工作。

这种特定于浏览器的行为建议了一种解决方法:如果您在基于 Chromium 的浏览器上的 AppScript 项目中遇到 jQuery 问题,请尝试切换到 Firefox 作为临时解决方案,直到 Google 实现更永久的修复。

编辑:找到以下解决方法。将其放在 HTML <head> 的最顶部。

<script>
  if (window.trustedTypes && window.trustedTypes.createPolicy) {
    window.trustedTypes.createPolicy('default', {
      createHTML: string => string,
      createScriptURL: string => string,
      createScript: string => string,
    });
  }
</script>
Daniel Zambrano 提问于2023-11-28
Pang 修改于2023-11-29
看来您包含了来自其他地方的代码。如果您使用他人的作品而不注明出处,则构成抄袭,这在 Stack Exchange 上是不受欢迎的。要修复此问题,请编辑以确保执行全部以下操作: 1.包含 来源链接,2. 提及作者姓名,以及 3. 引用 复制的内容。有关更多详细信息,请参阅参考帮助此常见问题解答TheMaster 2023-12-04
#2楼 已采纳
得票数 7

根据 Google 问题跟踪器,这里有一个解决方法,可以将HTML<head>

<script>
  if (window.trustedTypes && window.trustedTypes.createPolicy) {
    window.trustedTypes.createPolicy('default', {
      createHTML: string => string,
      createScriptURL: string => string,
      createScript: string => string,
    });
  }
</script>
Hershy 提问于2023-11-28
Hershy 修改于2023-11-30
根据 Google 问题跟踪器” - 请编辑您的答案以链接您所遇到的问题指的是。Bergi 2023-11-29
问题跟踪器报告该问题已得到解决,并且不再需要此解决方法(但是,您可能需要清除浏览器缓存)。Aaron Dunigan AtLee 2023-11-30
看来您包含了来自其他地方的代码。如果您使用他人的作品而不注明出处,则构成抄袭,这在 Stack Exchange 上是不受欢迎的。要修复此问题,请编辑以确保执行全部以下操作: 1.包含 来源链接,2. 提及作者姓名,以及 3. 引用 复制的内容。有关更多详细信息,请参阅参考帮助此常见问题解答TheMaster 2023-12-04
#3楼
得票数 4

您的错误表明该网址不符合您的 CSP 。您没有更改您的代码 - 是的,但是您的服务器有一个 CSP 规则集,并且根据该规则,jQuery 被拒绝。您需要查看主请求的响应标头以及 HTML 中的元标记,以了解您的 CSP 实际是什么。然后找到它的定义位置(在服务器设置或元标记或一些自定义代码中)并进行调整,以便允许使用 jQuery。

或者,您可以在本地下载 jquery 脚本并在本地链接它。

编辑

我进一步了解了这一点,特别是在 https://developer.mozilla.org/en-US/docs/Web/API/TrustedHTML

这特别有趣,受到上面链接的启发:

const escapeHTMLPolicy = trustedTypes.createPolicy("myEscapePolicy", {
  createHTML: (string) => string.replace(/</g, "&lt;"),
});

let el = document.getElementById("myDiv");
const escaped = escapeHTMLPolicy.createHTML("<img src=x onerror=alert(1)>");
console.log(escaped instanceof TrustedHTML); // true
el.innerHTML = escaped;

当然,具有以下 HTML

<div id="myDiv"></div>

我测试了上面的内容,结果在 FireFox 中不起作用,在 Chrome 中起作用。

因此,您需要查看是否完全支持trustedTypes

if (typeof trustedTypes === "undefined") {
    alert("Trusted types are not supported");
} else {
    alert("Trusted types are supported");
}

现在,我建议您可以创建一个函数,在内部检查 trustedTypes 是否受支持,如果支持,则创建一个策略。否则,只需创建一个具有方法名称的函数。然后,您可以在任何浏览器中调用该函数,而不必担心哪里支持它,哪里不支持它:

function getEscapeHTMLPolicy() {
    if (typeof trustedTypes === "undefined") {
        return {
            createHTML: (string) => string.replace(/</g, "&lt;"),
        }
    } else {
        return escapeHTMLPolicy = trustedTypes.createPolicy("myEscapePolicy", {
            createHTML: (string) => string.replace(/</g, "&lt;"),
        })
    }
}
let escPol = getEscapeHTMLPolicy();

window.addEventListener("load", function() {
    document.getElementById("mydiv").innerHTML = escPol.createHTML(`<p>foo</p>`);
});
<div id="mydiv"></div>

Lajos Arpad 提问于2023-11-28
Lajos Arpad 修改于2023-11-28
我尝试在本地下载 jQuery 并直接提供服务,但出现完全相同的错误。关于我的 CSP,我认为它是由 Google 在 Apps Script 框架内统治的,或者也许我错了,您有如何进行的详细信息吗?Waxim Corp 2023-11-28
@WaximCorp 请提供完整的错误,可能是您问题中的屏幕截图,当您将信息添加到您的问题时,请在评论部分给我留言。Lajos Arpad 2023-11-28
完成,在最初的问题中添加了屏幕截图Waxim Corp 2023-11-28
编辑:选择网络中正确文件的屏幕截图Waxim Corp 2023-11-28
@WaximCorp 谢谢,正在调查!Lajos Arpad 2023-11-28