您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Silently blocks most client-side redirects (links, forms, JS location, window.open, meta refresh). Works in page context & all frames; good for aggressive sites.
当前为
// ==UserScript== // @name Block All Client-Side Redirects (Quiet, All Frames) // @namespace https://github.com/osuobiem // @version 1.2 // @description Silently blocks most client-side redirects (links, forms, JS location, window.open, meta refresh). Works in page context & all frames; good for aggressive sites. // @author Gabriel Osuobiem // @match *://*/* // @run-at document-start // @all-frames true // @inject-into page // @grant none // ==/UserScript== (function () { 'use strict'; // If the manager ignores @inject-into page, fall back to a self-injected <script> so we still run in the page context. if (typeof window.__noRedirectInjected === 'undefined') { try { const s = document.createElement('script'); s.textContent = '(' + core.toString() + ')();'; (document.documentElement || document.head || document.body).appendChild(s); s.remove(); window.__noRedirectInjected = true; } catch (_) { // As a last resort run in this context (may be sandboxed; still helps for anchors/forms/meta). core(); } } function core() { const log = (...a) => { try { console.debug('[NoRedirect]', ...a); } catch (_) {} }; const noop = () => undefined; // Return a harmless Window-like stub so scripts that expect a Window don’t crash. const fakeWin = new Proxy(function () {}, { apply() { return null; }, get(_t, prop) { if (prop === 'closed') return true; if (prop === 'close') return noop; if (prop === 'focus') return noop; if (prop === 'blur') return noop; return noop; } }); function hardenLocation(win) { try { const L = win.location; const blockSet = (url) => { log('location set blocked', url); }; // Block window.location assign try { Object.defineProperty(win, 'location', { configurable: false, enumerable: true, get: () => L, set: blockSet }); } catch (_) {} // Block document.location alias try { Object.defineProperty(win.document, 'location', { configurable: false, enumerable: true, get: () => L, set: blockSet }); } catch (_) {} // Block methods assign/replace/reload ['assign', 'replace', 'reload'].forEach(m => { try { const orig = L[m].bind(L); L[m] = new Proxy(orig, { apply(_t, _th, args) { log(`location.${m} blocked`, args && args[0]); return; // no-op } }); } catch (_) {} }); } catch (_) {} } function hardenWindow(win) { // Block window.open try { const origOpen = win.open.bind(win); win.open = new Proxy(origOpen, { apply(_t, _th, args) { log('window.open blocked', args && args[0]); return fakeWin; } }); } catch (_) {} // Block History API navigations (SPAs/pushState) try { const H = win.history; ['pushState', 'replaceState', 'go', 'back', 'forward'].forEach(m => { try { const orig = H[m].bind(H); H[m] = new Proxy(orig, { apply() { log(`history.${m} blocked`); return; // no-op } }); } catch (_) {} }); } catch (_) {} // Block JS timer string eval redirects const navStr = /\b(?:top|parent|self|window)\s*\.\s*location\b|\blocation\s*=|\blocation\.(?:assign|replace)\s*\(|\bopen\s*\(/i; ['setTimeout', 'setInterval'].forEach(name => { try { const orig = win[name].bind(win); win[name] = new Proxy(orig, { apply(target, thisArg, args) { if (typeof args[0] === 'string' && navStr.test(args[0])) { log(`${name} redirect string blocked`, args[0]); return 0; } return Reflect.apply(target, thisArg, args); } }); } catch (_) {} }); // Neutralize onbeforeunload tricks try { Object.defineProperty(win, 'onbeforeunload', { configurable: true, get: () => null, set: () => { log('onbeforeunload blocked'); } }); } catch (_) {} // Prevent anchor-link navigations (but keep other clicks functional) try { win.addEventListener('click', e => { const a = e.target && e.target.closest ? e.target.closest('a[href]') : null; if (!a) return; e.preventDefault(); e.stopImmediatePropagation(); log('anchor click blocked', a.href); }, true); } catch (_) {} // Block form submits try { win.addEventListener('submit', e => { e.preventDefault(); e.stopImmediatePropagation(); log('form submit blocked', e.target && e.target.action); }, true); } catch (_) {} // Kill meta refresh (initial + dynamic) function stripMeta() { try { win.document.querySelectorAll('meta[http-equiv="refresh"], meta[http-equiv="Refresh"]').forEach(m => { log('meta refresh removed', m.content); m.remove(); }); } catch (_) {} } stripMeta(); try { new win.MutationObserver(stripMeta).observe(win.document.documentElement, { childList: true, subtree: true }); } catch (_) {} // Add defensive CSP (may be ignored by some browsers/sites) try { const meta = win.document.createElement('meta'); meta.httpEquiv = 'Content-Security-Policy'; meta.content = "navigate-to 'none'; form-action 'none'"; win.document.documentElement.prepend(meta); } catch (_) {} } function hardenRecursively(win) { hardenLocation(win); hardenWindow(win); // Same-origin child frames try { for (let i = 0; i < win.frames.length; i++) { const f = win.frames[i]; try { if (f.location && f.location.origin === win.location.origin) { hardenRecursively(f); } } catch (_) {} } } catch (_) {} // Also patch parent/top if same-origin ['parent', 'top'].forEach(ref => { try { const w = win[ref]; if (w && w !== win && w.location && w.location.origin === win.location.origin) { hardenLocation(w); hardenWindow(w); } } catch (_) {} }); } // Patch *now* at document-start hardenRecursively(window); // In case frames get added later (ads), attempt a delayed pass try { const again = () => { try { hardenRecursively(window); } catch (_) {} }; document.addEventListener('DOMContentLoaded', again, { once: true }); setTimeout(again, 1500); setTimeout(again, 4000); } catch (_) {} log('quiet redirect blocking active (page context, all frames).'); } })();