您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
保护用户剪贴板内容,允许或禁止网站污染剪贴板。
// ==UserScript== // @name 请不要污染我的剪贴板 // @namespace Violentmonkey Scripts // @version 1.0 // @description 保护用户剪贴板内容,允许或禁止网站污染剪贴板。 // @match *://*/* // @grant GM_notification // @grant GM_registerMenuCommand // @grant GM_setValue // @grant GM_getValue // @run-at document-start // @license MIT /* jshint esversion: 8 */ // ==/UserScript== (function() { 'use strict'; const PERMISSION_KEY = 'CLIPBOARD_PERMISSIONS'; let permissions = GM_getValue(PERMISSION_KEY, {}); // 创建权限管理菜单 GM_registerMenuCommand("剪贴板权限管理", showPermissionManager); /**************** 核心拦截逻辑 ****************/ // 修复1:正确处理传统execCommand const originalExecCommand = document.execCommand.bind(document); document.execCommand = function(command, showUI, value) { if (/^(copy|cut|paste)$/i.test(command)) { const allowed = checkPermissionSync( 'execCommand:' + command, `网站试图通过document.execCommand执行【${command.toUpperCase()}】操作` ); return allowed ? originalExecCommand(command, showUI, value) : false; } return originalExecCommand(command, showUI, value); }; // 修复2:正确处理现代Clipboard API if (navigator.clipboard) { // 写入拦截 const originalWrite = navigator.clipboard.writeText.bind(navigator.clipboard); navigator.clipboard.writeText = async function(data) { const allowed = await checkPermissionAsync( 'clipboard:write', `网站试图写入剪贴板内容:${truncateText(data)}` ); return allowed ? originalWrite(data) : Promise.reject(new DOMException('Not allowed', 'NotAllowedError')); }; // 读取拦截 const originalRead = navigator.clipboard.readText.bind(navigator.clipboard); navigator.clipboard.readText = async function() { const allowed = await checkPermissionAsync( 'clipboard:read', '网站试图读取剪贴板内容' ); return allowed ? originalRead() : Promise.reject(new DOMException('Not allowed', 'NotAllowedError')); }; } // 修复3:优化事件监听劫持 const originalAddEventListener = EventTarget.prototype.addEventListener; EventTarget.prototype.addEventListener = function(type, listener, options) { if (['copy', 'cut', 'paste'].includes(type)) { const wrappedListener = (e) => { const operation = type === 'paste' ? '读取' : '写入'; const allowed = checkPermissionSync( 'event:' + type, `网站通过【${type}】事件进行剪贴板${operation}` ); if (allowed) return listener(e); e.preventDefault(); e.stopImmediatePropagation(); }; return originalAddEventListener.call(this, type, wrappedListener, options); } return originalAddEventListener.call(this, type, listener, options); }; /**************** 工具函数 ****************/ // 同步权限检查(用于同步API) function checkPermissionSync(permissionId, message) { const domain = window.location.hostname; const fullKey = `${domain}:${permissionId}`; // 检查已保存的权限 if (permissions[fullKey] !== undefined) { return permissions[fullKey]; } // 交互式询问 const choice = confirm(`${message}\n\n是否允许本次操作?\n(确定=允许,取消=拒绝)`); const remember = confirm('是否永久记住此选择?'); if (remember) { permissions[fullKey] = choice; GM_setValue(PERMISSION_KEY, permissions); } return choice; } // 异步权限检查(用于异步API) async function checkPermissionAsync(permissionId, message) { return new Promise(resolve => { resolve(checkPermissionSync(permissionId, message)); }); } function showPermissionManager() { let msg = '已保存的剪贴板权限:\n'; Object.keys(permissions).forEach(k => { msg += `\n${k.replace(':', ' → ')}: ${permissions[k] ? '✓' : '×'}`; }); alert(msg + '\n\n提示:在弹窗中选择"记住"可永久保存设置'); } function truncateText(text, max = 50) { return text.length > max ? text.substring(0, max) + '...' : text; } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址