Greasemonkey-issued 重定向仅在重定向行之后调用 alert() 时有效

Greasemonkey-issued redirect only works if alert() is called after the redirection line

我工作的一个网站在未登录时会重定向到错误的登录页面。

<html>
  <head>
    <meta name="robots" content="noindex,nofollow">
    <script type="application/javascript">
      window.location.href = '/access/login?return_to=' + encodeURIComponent(window.location.href);
    </script>
  </head>
</html>

实际页面加载了 200 OK 而没有 Location: header。

为了解决这个问题,我编写了一个 Greasemonkey 脚本到 运行 在页面加载之前:

// ==UserScript==
// @name        Fix buggy login redirect
// @namespace  apburk@example.com
// @description Fixes the buggy redirect that redirects to the wrong login page
// @include    https://internal.domain/*
// @version    1
// @grant      none
// @run-at document-start
// ==/UserScript==
window.addEventListener('beforescriptexecute', function(e) {
if (document.getElementsByTagName("script")[0].text.trim() === "window.location.href = '/access/login?return_to=' + encodeURIComponent(window.location.href);") {

window.location.replace('https://example.com');
alert(" ");
}

}, true);

我的脚本会检查重定向到错误页面的 JavaScript 是否存在,然后将我发送到正确的登录 URL。

这个脚本工作正常——如果 alert() 在那里。删除 alert() 并且页面重定向到损坏的登录页面。然而,当 alert() 时,我从来没有看到警告框,但是 do 被重定向到正确的页面。

我可以保留 alert(),因为它似乎从来没有 运行,但我想删除它并仍然让页面重定向到我想要的页面。

我对这个问题的疑问:

该代码有一些 "race conditions"。由于缺少 alert(),旧的 JS 仍会在 location.replace(); 完成之前触发。
警报需要时间才能触发。有了它,location.replace 就可以提前完成。

正确的做法是停止脚本,然后启动替换。使用 stopPropagationpreventDefault 执行此操作。像这样:

window.addEventListener ('beforescriptexecute', function (e) {
    if (document.getElementsByTagName ("script")[0].text.trim()
        === "window.location.href = '/access/login?return_to=' + encodeURIComponent(window.location.href);"
    ) {
        e.stopPropagation ();
        e.preventDefault ();
        window.location.replace ('https://example.com');
    }
}, true);