如何将标识符替换为其关联值以进行异地评估?

How to replace identifiers with their associated values for off-site evaluation?

我想要一个标签:

<script src="https://mysource.com/script?foo=bar"></script>

https://mysource.com/script 是一个云函数端点,returns 一个脚本应该 运行 在浏览器中使用 bar 作为 foo 的值。该脚本无法评估函数并简单地发回结果,因为它的预期行为会导致副作用,例如向 window 对象添加东西。

我可以通过以下方式做到这一点:

  //prevents code injection like eval("evilcode")
  function sanitize(){}

  const foo = sanitize(req.query.foo);
  const myFunc = ()=>{... <uses foo somewhere> ... <causes side effects> ...};
  let strFunction = myFunc.toString();
  strFunction = strFunction.replace("foo", foo);
  const script = "("+strFunction+")();";
  res.status(200).send(script);

但我不禁想知道是否有更好的方法来做到这一点。 Google 做了我想在他们的 gtag 脚本中做的事情。如果您转到 https://www.googletagmanager.com/gtag/js?id=AW-950577603 和 ctrl+f AW-950577603,您会看到查询的 ID (AW-950577603) 出现在 javascript 代码中。但我不知道他们所做的是否正是我正在做的,或者他们是否以更好的方式完成了。建议?

您的代码:

const myFunc = ()=>{... <uses foo somewhere> ... <causes side effects> ...};
let strFunction = myFunc.toString();
strFunction = strFunction.replace("foo", foo);
const script = "("+strFunction+")();";

您可以将 foo 设为参数,而不是文本替换 foo

const myFunc = (foo)=>{... <uses foo somewhere> ... <causes side effects> ...};
let strFunction = myFunc.toString();
const script = "("+strFunction+")("+foo+");";

您的代码:

//prevents code injection like eval("evilcode")
function sanitize(){}

const foo = sanitize(req.query.foo);

如果您希望 req.query.foo 显示为 JavaScript 字符串文字,那么 JSON.stringify 通常有效:

const foo = JSON.stringify(req.query.foo);

通常,我会将我的客户端 JavaScript 代码存储在一个单独的文件中。将客户端和服务器端分开 JavaScript 有助于我维护我的代码。在您的情况下,该文件可以公开一个名为 initializeMyApp 的函数,并且您可以使用另一个答案中解释的 动态创建对 initializeMyApp 的调用。例如:

let strFunction = fs.readFileSync("initializeMyApp.js", "utf-8");
const script = "("+strFunction+")("+foo+");";

甚至更好:将您的客户端 JavaScript 代码存储在一个单独的文件中,并将其作为静态内容提供(可能使用 CDN)。然后让客户端代码在单独的 <script>:

中调用 initializeMyApp
<script src="https://mysource.com/script"></script>
<script>initializeMyApp("bar");</script>