You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Tampermonkey脚本早于页面脚本执行?解决IE强制登录限制

解决强制IE检测脚本关闭Chrome窗口的问题

我需要登录一个强制要求使用IE的网页,页面会执行以下脚本弹窗提示并关闭窗口:

<Script Language="javascript">
alert("Please use IE to login!");
window.opener = null;
window.close();
</Script>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<body>
...
</body>
</html>

我想用Chrome登录,必须阻止这段脚本关闭窗口。试过Tampermonkey脚本,哪怕设置// @run-at document-start,脚本还是晚于页面脚本执行,尝试的代码如下:

// ==UserScript==
// @name         New Userscript
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        http://localhost:8080/666/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=undefined.localhost
// @grant        none
// @run-at       document-start
// ==/UserScript==

// reference: https://github.com/jspenguin2017/Snippets/blob/master/onbeforescriptexecute.html
(function() {
    'use strict';
    
    const Event = class {
        constructor(script, target) {
            this.script = script;
            this.target = target;

            this._cancel = false;
            this._replace = null;
            this._stop = false;
        }

        preventDefault() {
            this._cancel = true;
        }
        stopPropagation() {
            this._stop = true;
        }
        replacePayload(payload) {
            this._replace = payload;
        }
    };

    let callbacks = [];
    window.addBeforeScriptExecuteListener = (f) => {
        if (typeof f !== "function") {
            throw new Error("Event handler must be a function.");
        }
        callbacks.push(f);
    };
    window.removeBeforeScriptExecuteListener = (f) => {
        let i = callbacks.length;
        while (i--) {
            if (callbacks[i] === f) {
                callbacks.splice(i, 1);
            }
        }
    };

    const dispatch = (script, target) => {
        if (script.tagName !== "SCRIPT") {
            return;
        }

        const e = new Event(script, target);

        if (typeof window.onbeforescriptexecute === "function") {
            try {
                window.onbeforescriptexecute(e);
            } catch (err) {
                console.error(err);
            }
        }else{
            console.log("window.onbeforescriptexecute no defined");
        }

        for (const func of callbacks) {
            if (e._stop) {
                break;
            }
            try {
                func(e);
            } catch (err) {
                console.error(err);
            }
        }

        if (e._cancel) {
            script.textContent = "";
            script.remove();
        } else if (typeof e._replace === "string") {
            script.textContent = e._replace;
        }
    };
    const observer = new MutationObserver((mutations) => {
        window.close = ()=>{return;};
        for (const m of mutations) {
            for (const n of m.addedNodes) {
                dispatch(n, m.target);
            }
        }
    });
    observer.observe(document, {
        childList: true,
        subtree: true,
    });
    
    //example
    (() => {
            "use strict";
            window.onbeforescriptexecute = (e) => {
                // You should check if textContent exists as this property is
                // buggy sometimes
                if (!e.script.textContent) {
                    return;
                }

                // Prevent execution of a script
                if (e.script.textContent.includes("window.close()")) {
                    e.preventDefault();
                    //e.stopPropagation();
                }

                // Change the code that runs
                if (e.script.textContent.includes("console.log")) {
                    // Original payload is e.script.textContent, you can
                    // manipulate it however you want, just pass the final
                    // payload to e.replacePayload when you are done
                    e.replacePayload("console.log(2);");
                    // Later event handlers can override your payload, you
                    // can call e.stopPropagation to make sure the current
                    // payload is applied
                }
            };
    })();
})();

可行的解决脚本

核心是在页面脚本运行前直接重写window.close,并拦截移除目标检测脚本,以下是优化后的Tampermonkey脚本:

// ==UserScript==
// @name         禁用IE检测窗口关闭
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  阻止强制IE的页面关闭Chrome窗口
// @author       You
// @match        http://localhost:8080/666/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=localhost
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    // 重写window.close,让它无法关闭窗口
    window.close = function() {
        console.log("窗口关闭操作已被拦截");
        return false;
    };

    // 监听页面新增节点,直接移除IE检测脚本
    const observer = new MutationObserver((mutations) => {
        for (const mutation of mutations) {
            for (const node of mutation.addedNodes) {
                if (node.tagName === 'SCRIPT' && node.textContent.includes('Please use IE to login')) {
                    node.textContent = '';
                    node.remove();
                    console.log("IE检测脚本已被移除");
                }
            }
        }
    });

    observer.observe(document.documentElement, {
        childList: true,
        subtree: true
    });
})();

原脚本无效的原因

你之前的脚本实现了自定义的onbeforescriptexecute机制,但Chrome原生并不支持这个事件,导致拦截时机还是晚于页面脚本执行。直接重写window.close+移除目标脚本的方式更直接,且能在页面脚本运行前生效。

内容的提问来源于stack exchange,提问作者cat friend

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 14:10:31