如何让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
相关产品推荐
相关产品推荐

