【问题标题】:Hook window.location.* assignments and window.location.assign挂钩 window.location.* assignments 和 window.location.assign
【发布时间】:2018-09-04 16:27:33
【问题描述】:

我正在尝试拦截 window.location.* 分配和 window.location.assign 调用以更改离开前分配的 url,这可能吗? 当我尝试重新定义属性设置器时,我收到一个错误,我无法重新定义它。 我唯一的选择是代理页面并用字符串替换静态替换对 window.location 的所有分配吗? 虽然我宁愿避免它,因为 javascript 很时髦,而且这样的东西也可能是有效的,所以我必须跟踪所有分配:

var l = window.location;
var c = l;
var t = c.assign;
t('...');

【问题讨论】:

  • 这听起来像是X/Y problem。你认为你为什么要这样做?
  • @T.J.Crowder 我有一个代理,可以为我希望的任何网站提供服务。它挂钩所有 ajax 调用和所有资源获取,并通过代理传递它们。当脚本试图通过 window.location 分配更改当前位置时会出现问题,我需要拦截它们以更改要通过代理传递的 url。例如window.location = 'http://www.google.com' -> window.location = 'http://proxy-server/?url=http://www.google.com'
  • @Jorayen - 有趣!
  • @Jorayen,这个问题好像已经过去几年了,你有没有得到满意的解决方案?

标签: javascript hook


【解决方案1】:

一种解决方案是创建您自己的位置更改提供程序,您可以在其中拦截 URL 并进行相应的更改。然后,您的代码可以始终调用您的更改提供程序,而不是标准的 window.location 属性。

如果您处于设置位置属性的代码不受您控制的情况下,这将不起作用。

如果位置设置代码超出您的控制范围,请查看使用了beforeunload 事件的Javascript: How to intercept window.location change

【讨论】:

  • 我已经尝试了beforeunload 事件并在其中写入window.location,但它似乎没有效果。我对代码有一定程度的控制权,我有一个代理,它通过参数为任何页面提供服务,并且我为想要的网页提供服务。现在我可以使用某种正则表达式对任何分配进行静态替换,但这不是一个好的解决方案,正如我在我的操作中所说的那样。还有其他想法吗?
  • 有一个疯狂的想法...bennadel.com/blog/…。该示例至少允许您记录位置更改,但不知道您是否能够实际更改它。
  • 由于拉取的异步性质,它错过了大部分时间来检查 url 更改。只要我不能停止当前的重定位,并为我的代理创建一个新的,这种方法就不会有太大帮助:(
【解决方案2】:

不幸的是,我认为你不能做到这一点。如您所见,window 上的 location 属性是不可配置的(至少在 Chrome 和 Firefox 中)。如您所知,它非常特别:如果您尝试写入它(例如,用您自己的自定义对象替换它),而不是以正常方式替换属性,它会将您给它的内容转换为字符串并尝试在那里导航。因此,您无法用自己的东西替换 window.locationObject.defineProperty 不会让您(因为它是不可配置的),并且分配将不起作用。

这让您的任务是识别页面上 JavaScript 代码中对window.location 的所有写入,这在一般情况下是不可能的。虽然您可以找到所有 window.locationlocation 引用,并且静态分析会告诉您(不存在 evalnew Function)这些 windowlocation 变量是否是全局变量,您需要评估逐步编写代码以找到您在问题中提到的那种东西,甚至是简单的东西,例如:

(function(w) {
    w.location = "https://stackoverflow.com";
})(this);

完全改变解决方案的架构,您可以在服务器端运行无头浏览器并将其 DOM 的更改回显给客户端,拦截所有点击并将它们转发到服务器端代码以传递给无头浏览器。这可能有其自身的重大挑战。

【讨论】:

  • 我担心你会说无头浏览器,我已经在我的解决方案中开始使用它,但是因为我想要更轻量级和优雅的东西而放弃了它。好吧,我想这是唯一的方法,除非我检测到所有可能的分配,因为人们可以加密函数调用名称,例如:s
  • @Jorayen - 是的,您无法仅通过静态分析检测到这一点。 :-(
  • 好吧,我不喜欢无头浏览器的想法,因为我不知道何时将更改从服务器返回到客户端,因为在某些情况下我必须拉取更改,例如 @987654333 @调用,你可以说我可以挂钩它并且知道在发送回显更新之前我应该​​或多或少地等待所有计时器,但我认为它只会更深入兔子洞并使事情变得更加复杂。但我想到了一个可行的解决方案,希望你能告诉我你的想法。正如我们已经说过的那样,静态分析对window.location.* 的所有分配将很难。
  • 但是静态分析任何正在运行的脚本中的 all 分配,这意味着我必须找到诸如 object.property = ...object[property] = ... 之类的分配,而不关心 object 的内容是或property 是什么,例如我不在乎是否看到类似vfje_4[fjsh('dx')] 的内容。在找到 all 分配后,我会将它们包装在我自己的 setter 函数中,检查对象和属性指向的位置的 reference 以及例如引用是否相同作为window.location,然后我们“拦截”了对理想属性的写入(window.location
  • setter 类似于:setter(o, p) { if (window.location === o[p]) // bingo ...} 我们会在静态分析发现的每个分配中调用 setter。你有什么想法?
猜你喜欢
  • 1970-01-01
  • 2020-05-21
  • 1970-01-01
  • 2011-07-21
  • 2019-05-12
  • 1970-01-01
  • 2020-11-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多