基于JavaScript+CSS实现禁用浏览器复制功能的几种方法
作者:伍哥的传说
网页中禁用用户的复制功能,包括 CSS 方法、JavaScript 方法、综合解决方案以及实际应用场景,适用于需要保护内容版权、防止恶意爬取或提升用户体验的场景,本文给大家介绍了基于JavaScript+CSS实现禁用浏览器复制功能的几种方法,需要的朋友可以参考下
快速开始
如果您想快速实现基本的复制保护,可以直接使用以下代码:
<!DOCTYPE html> <html> <head> <style> /* 基础保护样式 */ .protected { -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; -webkit-touch-callout: none; } </style> </head> <body class="protected"> <script> // 基础保护脚本 document.addEventListener("contextmenu", (e) => e.preventDefault()); document.addEventListener("keydown", (e) => { if (e.ctrlKey && (e.keyCode === 67 || e.keyCode === 65)) { e.preventDefault(); } }); </script> <h1>受保护的内容</h1> <p>这里的内容无法被轻易复制</p> </body> </html>
CSS 方法
CSS 方法是最基础且高效的保护方式,通过样式属性来禁用用户的选择和交互行为。
1. 禁用文本选择
基础语法
/* 禁用所有文本选择 - 基础版本 */ .no-select { -webkit-user-select: none; /* Safari */ -moz-user-select: none; /* Firefox */ -ms-user-select: none; /* Internet Explorer/Edge */ user-select: none; /* 标准语法 */ } /* 应用到整个页面 */ body { -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; }
高级配置
/* 完整的文本选择保护 */ .protected-content { -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; /* 移动端优化 */ -webkit-touch-callout: none; /* 禁用iOS Safari的长按菜单 */ -webkit-tap-highlight-color: transparent; /* 禁用点击高亮 */ -webkit-appearance: none; /* 移除默认样式 */ /* 禁用文本选择手柄 */ -webkit-text-size-adjust: none; } /* 选择性允许文本选择 */ .selectable { -webkit-user-select: text; -moz-user-select: text; -ms-user-select: text; user-select: text; } /* 只允许选择文本内容,不允许选择元素 */ .text-only { -webkit-user-select: text; -moz-user-select: text; -ms-user-select: text; user-select: text; } /* 允许全部选择 */ .select-all { -webkit-user-select: all; -moz-user-select: all; -ms-user-select: all; user-select: all; }
实际使用示例
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8" /> <style> /* 保护主要内容 */ .article-content { -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; padding: 20px; border: 1px solid #ddd; background: #f9f9f9; } /* 允许输入框正常使用 */ .user-input { -webkit-user-select: text; -moz-user-select: text; -ms-user-select: text; user-select: text; padding: 10px; border: 1px solid #ccc; width: 100%; margin: 10px 0; } /* 代码块可以选择 */ .code-block { -webkit-user-select: all; -moz-user-select: all; -ms-user-select: all; user-select: all; background: #f4f4f4; padding: 10px; font-family: monospace; } </style> </head> <body> <div class="article-content"> <h2>受保护的文章标题</h2> <p>这段内容无法被选择和复制</p> <img src="protected-image.jpg" alt="受保护的图片" /> </div> <input type="text" class="user-input" placeholder="这里可以正常输入和选择文本" /> <div class="code-block">console.log('这段代码可以被选择复制');</div> </body> </html>
2. 禁用拖拽功能
/* 禁用图片和媒体元素的拖拽 */ img, video, audio, canvas, svg { -webkit-user-drag: none; -khtml-user-drag: none; -moz-user-drag: none; -o-user-drag: none; user-drag: none; pointer-events: none; /* 完全禁用鼠标事件 */ } /* 禁用所有元素的拖拽 */ * { -webkit-user-drag: none; -khtml-user-drag: none; -moz-user-drag: none; -o-user-drag: none; user-drag: none; } /* 恢复必要的交互元素 */ .interactive, button, input, textarea, select, a { pointer-events: auto; -webkit-user-drag: auto; -khtml-user-drag: auto; -moz-user-drag: auto; -o-user-drag: auto; user-drag: auto; } /* 特殊处理:可拖拽的元素 */ .draggable { -webkit-user-drag: element; -khtml-user-drag: element; -moz-user-drag: element; -o-user-drag: element; user-drag: element; }
3. 移动端特殊优化
/* 移动端复制保护 */ .mobile-protected { -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; /* iOS Safari 特殊处理 */ -webkit-touch-callout: none; /* 禁用长按菜单 */ -webkit-tap-highlight-color: transparent; /* 禁用点击高亮 */ /* Android 特殊处理 */ -webkit-text-size-adjust: none; /* 禁用文本大小调整 */ /* 禁用双击缩放 */ touch-action: manipulation; /* 禁用选择手柄 */ -webkit-appearance: none; } /* 禁用文本选择高亮 */ .mobile-protected::selection { background: transparent; } .mobile-protected::-moz-selection { background: transparent; } /* 禁用iOS Safari的选择工具栏 */ .mobile-protected::-webkit-selection { background: transparent; }
JavaScript 方法
JavaScript 方法提供了更灵活和强大的保护功能,可以动态控制用户行为并提供反馈。
1. 禁用右键菜单
基础实现
// 方法1: 全局禁用右键菜单 document.addEventListener("contextmenu", function (e) { e.preventDefault(); return false; }); // 方法2: 针对特定元素 document .getElementById("protected-content") .addEventListener("contextmenu", function (e) { e.preventDefault(); alert("右键功能已被禁用"); return false; }); // 方法3: 使用事件委托 document.addEventListener("contextmenu", function (e) { if (e.target.classList.contains("protected")) { e.preventDefault(); console.log("尝试右键点击受保护内容"); return false; } });
高级实现
// 智能右键菜单禁用 class ContextMenuProtection { constructor(options = {}) { this.options = { showWarning: true, warningMessage: "此内容受到保护,无法使用右键菜单", allowedElements: ["input", "textarea"], ...options, }; this.init(); } init() { document.addEventListener("contextmenu", (e) => this.handleContextMenu(e)); } handleContextMenu(e) { const tagName = e.target.tagName.toLowerCase(); // 允许特定元素使用右键菜单 if (this.options.allowedElements.includes(tagName)) { return true; } // 检查是否有特殊标记 if (e.target.dataset.allowContextMenu === "true") { return true; } e.preventDefault(); if (this.options.showWarning) { this.showWarning(this.options.warningMessage); } return false; } showWarning(message) { // 创建自定义提示 const warning = document.createElement("div"); warning.textContent = message; warning.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: #ff4444; color: white; padding: 10px 20px; border-radius: 5px; z-index: 10000; font-size: 14px; `; document.body.appendChild(warning); setTimeout(() => { document.body.removeChild(warning); }, 2000); } } // 使用示例 const contextProtection = new ContextMenuProtection({ showWarning: true, warningMessage: "内容受保护,禁止右键操作", allowedElements: ["input", "textarea", "select"], });
2. 禁用键盘快捷键
基础实现
// 禁用常见的复制快捷键 document.addEventListener("keydown", function (e) { // 禁用 Ctrl+C (复制) if (e.ctrlKey && e.keyCode === 67) { e.preventDefault(); return false; } // 禁用 Ctrl+A (全选) if (e.ctrlKey && e.keyCode === 65) { e.preventDefault(); return false; } // 禁用 Ctrl+V (粘贴) if (e.ctrlKey && e.keyCode === 86) { e.preventDefault(); return false; } // 禁用 Ctrl+X (剪切) if (e.ctrlKey && e.keyCode === 88) { e.preventDefault(); return false; } // 禁用 Ctrl+S (保存) if (e.ctrlKey && e.keyCode === 83) { e.preventDefault(); return false; } // 禁用 F12 (开发者工具) if (e.keyCode === 123) { e.preventDefault(); return false; } // 禁用 Ctrl+Shift+I (开发者工具) if (e.ctrlKey && e.shiftKey && e.keyCode === 73) { e.preventDefault(); return false; } // 禁用 Ctrl+U (查看源代码) if (e.ctrlKey && e.keyCode === 85) { e.preventDefault(); return false; } });
高级键盘保护
class KeyboardProtection { constructor(options = {}) { this.options = { disableCopy: true, disablePaste: true, disableSelectAll: true, disableSave: true, disableDevTools: true, disablePrint: true, allowedInputs: ["input", "textarea"], showWarnings: true, ...options, }; this.forbiddenKeys = this.buildForbiddenKeys(); this.init(); } buildForbiddenKeys() { const keys = []; if (this.options.disableCopy) { keys.push({ ctrl: true, key: 67, name: "Ctrl+C (复制)" }); } if (this.options.disablePaste) { keys.push({ ctrl: true, key: 86, name: "Ctrl+V (粘贴)" }); } if (this.options.disableSelectAll) { keys.push({ ctrl: true, key: 65, name: "Ctrl+A (全选)" }); } if (this.options.disableSave) { keys.push({ ctrl: true, key: 83, name: "Ctrl+S (保存)" }); } if (this.options.disableDevTools) { keys.push( { key: 123, name: "F12 (开发者工具)" }, { ctrl: true, shift: true, key: 73, name: "Ctrl+Shift+I (开发者工具)" }, { ctrl: true, shift: true, key: 74, name: "Ctrl+Shift+J (控制台)" }, { ctrl: true, key: 85, name: "Ctrl+U (查看源代码)" } ); } if (this.options.disablePrint) { keys.push({ ctrl: true, key: 80, name: "Ctrl+P (打印)" }); } return keys; } init() { document.addEventListener("keydown", (e) => this.handleKeyDown(e)); } handleKeyDown(e) { const target = e.target; const tagName = target.tagName.toLowerCase(); // 允许在输入框中使用某些快捷键 if (this.options.allowedInputs.includes(tagName)) { // 在输入框中只禁用开发者工具相关快捷键 if (this.options.disableDevTools) { const devToolsKeys = this.forbiddenKeys.filter( (key) => key.name.includes("开发者工具") || key.name.includes("控制台") || key.name.includes("查看源代码") ); for (let forbidden of devToolsKeys) { if (this.matchesKeyCombo(e, forbidden)) { e.preventDefault(); this.showWarning(`${forbidden.name} 已被禁用`); return false; } } } return true; } // 检查所有禁用的快捷键 for (let forbidden of this.forbiddenKeys) { if (this.matchesKeyCombo(e, forbidden)) { e.preventDefault(); if (this.options.showWarnings) { this.showWarning(`${forbidden.name} 已被禁用`); } return false; } } } matchesKeyCombo(event, combo) { return ( (!combo.ctrl || event.ctrlKey) && (!combo.shift || event.shiftKey) && (!combo.alt || event.altKey) && event.keyCode === combo.key ); } showWarning(message) { if (this.options.showWarnings) { console.warn(message); // 可以在这里添加自定义的警告显示逻辑 } } } // 使用示例 const keyboardProtection = new KeyboardProtection({ disableCopy: true, disablePaste: true, disableSelectAll: true, disableSave: true, disableDevTools: true, disablePrint: true, allowedInputs: ["input", "textarea"], showWarnings: true, });
3. 禁用文本选择
// 方法1: 禁用选择事件 document.addEventListener("selectstart", function (e) { e.preventDefault(); return false; }); // 方法2: 清除已选择的文本 document.addEventListener("mouseup", function () { if (window.getSelection) { window.getSelection().removeAllRanges(); } else if (document.selection) { document.selection.empty(); } }); // 方法3: 禁用拖拽选择 document.addEventListener("dragstart", function (e) { e.preventDefault(); return false; }); // 方法4: 高级文本选择保护 class TextSelectionProtection { constructor(options = {}) { this.options = { clearSelectionInterval: 100, // 清除选择的间隔时间(ms) allowedElements: ["input", "textarea"], ...options, }; this.init(); } init() { // 禁用选择开始事件 document.addEventListener("selectstart", (e) => this.handleSelectStart(e)); // 禁用拖拽事件 document.addEventListener("dragstart", (e) => this.handleDragStart(e)); // 定期清除选择 if (this.options.clearSelectionInterval > 0) { setInterval( () => this.clearSelection(), this.options.clearSelectionInterval ); } // 监听鼠标事件 document.addEventListener("mouseup", () => this.clearSelection()); document.addEventListener("keyup", () => this.clearSelection()); } handleSelectStart(e) { const tagName = e.target.tagName.toLowerCase(); if (this.options.allowedElements.includes(tagName)) { return true; } e.preventDefault(); return false; } handleDragStart(e) { const tagName = e.target.tagName.toLowerCase(); if (this.options.allowedElements.includes(tagName)) { return true; } e.preventDefault(); return false; } clearSelection() { try { if (window.getSelection) { const selection = window.getSelection(); if (selection.rangeCount > 0) { // 检查选择是否在允许的元素中 const range = selection.getRangeAt(0); const container = range.commonAncestorContainer; const element = container.nodeType === Node.TEXT_NODE ? container.parentElement : container; const tagName = element.tagName ? element.tagName.toLowerCase() : ""; if (!this.options.allowedElements.includes(tagName)) { selection.removeAllRanges(); } } } else if (document.selection) { document.selection.empty(); } } catch (e) { // 忽略错误 } } } // 使用示例 const textProtection = new TextSelectionProtection({ clearSelectionInterval: 50, allowedElements: ["input", "textarea", "select"], });
4. 监控开发者工具
// 基础开发者工具检测 let devtools = { open: false, orientation: null, }; const threshold = 160; function detectDevTools() { if ( window.outerHeight - window.innerHeight > threshold || window.outerWidth - window.innerWidth > threshold ) { if (!devtools.open) { devtools.open = true; console.log("开发者工具已打开"); // 可以在这里添加警告或重定向 // window.location.href = 'about:blank'; } } else { devtools.open = false; } } setInterval(detectDevTools, 500); // 高级开发者工具检测 class DevToolsDetection { constructor(options = {}) { this.options = { checkInterval: 1000, onDetected: () => console.warn("检测到开发者工具"), onClosed: () => console.log("开发者工具已关闭"), threshold: 160, redirectUrl: null, showWarning: true, ...options, }; this.isOpen = false; this.init(); } init() { setInterval(() => this.check(), this.options.checkInterval); // 检测控制台输出 this.detectConsoleOutput(); // 检测调试器 this.detectDebugger(); } check() { const widthThreshold = window.outerWidth - window.innerWidth > this.options.threshold; const heightThreshold = window.outerHeight - window.innerHeight > this.options.threshold; if (widthThreshold || heightThreshold) { if (!this.isOpen) { this.isOpen = true; this.handleDetected(); } } else { if (this.isOpen) { this.isOpen = false; this.handleClosed(); } } } detectConsoleOutput() { // 重写console方法来检测控制台使用 const originalLog = console.log; console.log = (...args) => { this.handleDetected(); return originalLog.apply(console, args); }; } detectDebugger() { // 定期检查调试器 setInterval(() => { const start = performance.now(); debugger; const end = performance.now(); if (end - start > 100) { this.handleDetected(); } }, 3000); } handleDetected() { this.options.onDetected(); if (this.options.showWarning) { alert("检测到开发者工具,页面功能可能受限"); } if (this.options.redirectUrl) { window.location.href = this.options.redirectUrl; } } handleClosed() { this.options.onClosed(); } } // 使用示例 const devToolsDetection = new DevToolsDetection({ checkInterval: 1000, onDetected: () => { console.warn("开发者工具被检测到"); document.body.style.display = "none"; }, onClosed: () => { document.body.style.display = "block"; }, threshold: 160, showWarning: true, });
综合解决方案
将 CSS 和 JavaScript 方法结合起来,创建一个完整的复制保护系统。
完整的保护类
class CopyProtection { constructor(options = {}) { this.options = { // 基础保护选项 disableRightClick: true, disableSelection: true, disableKeyboardShortcuts: true, disableDeveloperTools: true, disableDragDrop: true, disablePrint: true, // 用户体验选项 showWarnings: true, allowedElements: ["input", "textarea", "select"], warningDuration: 2000, // 高级选项 clearSelectionInterval: 100, devToolsCheckInterval: 1000, redirectOnDevTools: false, redirectUrl: "about:blank", // 自定义消息 messages: { rightClick: "右键功能已被禁用", keyboard: "该快捷键已被禁用", devTools: "检测到开发者工具", selection: "文本选择已被禁用", }, ...options, }; this.isDevToolsOpen = false; this.init(); } init() { // 添加CSS样式 this.addProtectionStyles(); // 初始化各种保护功能 if (this.options.disableRightClick) { this.initRightClickProtection(); } if (this.options.disableSelection) { this.initSelectionProtection(); } if (this.options.disableKeyboardShortcuts) { this.initKeyboardProtection(); } if (this.options.disableDeveloperTools) { this.initDevToolsDetection(); } if (this.options.disableDragDrop) { this.initDragDropProtection(); } if (this.options.disablePrint) { this.initPrintProtection(); } console.log("🛡️ 复制保护系统已启动"); } addProtectionStyles() { const style = document.createElement("style"); style.id = "copy-protection-styles"; style.textContent = ` /* 基础保护样式 */ .copy-protected { -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -khtml-user-drag: none; -moz-user-drag: none; -o-user-drag: none; user-drag: none; } /* 媒体元素保护 */ .copy-protected img, .copy-protected video, .copy-protected audio, .copy-protected canvas { pointer-events: none; -webkit-user-drag: none; -khtml-user-drag: none; -moz-user-drag: none; -o-user-drag: none; user-drag: none; } /* 选择高亮禁用 */ .copy-protected::selection { background: transparent; } .copy-protected::-moz-selection { background: transparent; } /* 警告提示样式 */ .copy-protection-warning { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: linear-gradient(135deg, #ff6b6b, #ee5a24); color: white; padding: 15px 25px; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.3); z-index: 999999; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; font-size: 14px; font-weight: 500; text-align: center; animation: copyProtectionFadeIn 0.3s ease-out; } @keyframes copyProtectionFadeIn { from { opacity: 0; transform: translate(-50%, -50%) scale(0.8); } to { opacity: 1; transform: translate(-50%, -50%) scale(1); } } /* 允许的元素恢复正常功能 */ .copy-protected input, .copy-protected textarea, .copy-protected select { -webkit-user-select: text; -moz-user-select: text; -ms-user-select: text; user-select: text; pointer-events: auto; } `; document.head.appendChild(style); // 应用保护样式到body document.body.classList.add("copy-protected"); } initRightClickProtection() { document.addEventListener("contextmenu", (e) => { const tagName = e.target.tagName.toLowerCase(); if (this.options.allowedElements.includes(tagName)) { return true; } if (e.target.dataset.allowContextMenu === "true") { return true; } e.preventDefault(); if (this.options.showWarnings) { this.showWarning(this.options.messages.rightClick); } return false; }); } initSelectionProtection() { // 禁用选择开始 document.addEventListener("selectstart", (e) => { const tagName = e.target.tagName.toLowerCase(); if (this.options.allowedElements.includes(tagName)) { return true; } e.preventDefault(); return false; }); // 定期清除选择 if (this.options.clearSelectionInterval > 0) { setInterval(() => { this.clearSelection(); }, this.options.clearSelectionInterval); } // 监听鼠标和键盘事件 document.addEventListener("mouseup", () => this.clearSelection()); document.addEventListener("keyup", () => this.clearSelection()); } clearSelection() { try { if (window.getSelection) { const selection = window.getSelection(); if (selection.rangeCount > 0) { const range = selection.getRangeAt(0); const container = range.commonAncestorContainer; const element = container.nodeType === Node.TEXT_NODE ? container.parentElement : container; const tagName = element.tagName ? element.tagName.toLowerCase() : ""; if (!this.options.allowedElements.includes(tagName)) { selection.removeAllRanges(); } } } else if (document.selection) { document.selection.empty(); } } catch (e) { // 忽略错误 } } initKeyboardProtection() { const forbiddenKeys = [ { ctrl: true, key: 67, name: "Ctrl+C (复制)" }, { ctrl: true, key: 86, name: "Ctrl+V (粘贴)" }, { ctrl: true, key: 65, name: "Ctrl+A (全选)" }, { ctrl: true, key: 88, name: "Ctrl+X (剪切)" }, { ctrl: true, key: 83, name: "Ctrl+S (保存)" }, { ctrl: true, key: 80, name: "Ctrl+P (打印)" }, { key: 123, name: "F12 (开发者工具)" }, { ctrl: true, shift: true, key: 73, name: "Ctrl+Shift+I (开发者工具)" }, { ctrl: true, shift: true, key: 74, name: "Ctrl+Shift+J (控制台)" }, { ctrl: true, key: 85, name: "Ctrl+U (查看源代码)" }, ]; document.addEventListener("keydown", (e) => { const target = e.target; const tagName = target.tagName.toLowerCase(); // 允许在输入框中使用某些快捷键 if (this.options.allowedElements.includes(tagName)) { // 在输入框中只禁用开发者工具相关快捷键 const devToolsKeys = forbiddenKeys.filter( (key) => key.name.includes("开发者工具") || key.name.includes("控制台") || key.name.includes("查看源代码") ); for (let forbidden of devToolsKeys) { if (this.matchesKeyCombo(e, forbidden)) { e.preventDefault(); if (this.options.showWarnings) { this.showWarning(this.options.messages.keyboard); } return false; } } return true; } // 检查所有禁用的快捷键 for (let forbidden of forbiddenKeys) { if (this.matchesKeyCombo(e, forbidden)) { e.preventDefault(); if (this.options.showWarnings) { this.showWarning(this.options.messages.keyboard); } return false; } } }); } matchesKeyCombo(event, combo) { return ( (!combo.ctrl || event.ctrlKey) && (!combo.shift || event.shiftKey) && (!combo.alt || event.altKey) && event.keyCode === combo.key ); } initDragDropProtection() { document.addEventListener("dragstart", (e) => { const tagName = e.target.tagName.toLowerCase(); if (this.options.allowedElements.includes(tagName)) { return true; } e.preventDefault(); return false; }); } initPrintProtection() { // 禁用打印快捷键已在键盘保护中处理 // 这里可以添加额外的打印保护逻辑 window.addEventListener("beforeprint", (e) => { if (this.options.showWarnings) { this.showWarning("打印功能已被禁用"); } e.preventDefault(); return false; }); } initDevToolsDetection() { setInterval(() => { const widthThreshold = window.outerWidth - window.innerWidth > 160; const heightThreshold = window.outerHeight - window.innerHeight > 160; if (widthThreshold || heightThreshold) { if (!this.isDevToolsOpen) { this.isDevToolsOpen = true; this.handleDevToolsDetected(); } } else { this.isDevToolsOpen = false; } }, this.options.devToolsCheckInterval); } handleDevToolsDetected() { if (this.options.showWarnings) { this.showWarning(this.options.messages.devTools); } if (this.options.redirectOnDevTools) { setTimeout(() => { window.location.href = this.options.redirectUrl; }, 1000); } } showWarning(message) { // 移除已存在的警告 const existingWarning = document.querySelector(".copy-protection-warning"); if (existingWarning) { existingWarning.remove(); } // 创建新的警告 const warning = document.createElement("div"); warning.className = "copy-protection-warning"; warning.textContent = message; document.body.appendChild(warning); // 自动移除警告 setTimeout(() => { if (warning.parentNode) { warning.parentNode.removeChild(warning); } }, this.options.warningDuration); } // 公共方法:启用保护 enable() { document.body.classList.add("copy-protected"); console.log("🛡️ 复制保护已启用"); } // 公共方法:禁用保护 disable() { document.body.classList.remove("copy-protected"); console.log("🔓 复制保护已禁用"); } // 公共方法:销毁保护 destroy() { // 移除样式 const style = document.getElementById("copy-protection-styles"); if (style) { style.remove(); } // 移除类名 document.body.classList.remove("copy-protected"); // 移除警告 const warnings = document.querySelectorAll(".copy-protection-warning"); warnings.forEach((warning) => warning.remove()); console.log("🗑️ 复制保护已销毁"); } } // 使用示例 const protection = new CopyProtection({ // 基础保护选项 disableRightClick: true, disableSelection: true, disableKeyboardShortcuts: true, disableDeveloperTools: true, disableDragDrop: true, disablePrint: false, // 用户体验选项 showWarnings: true, allowedElements: ["input", "textarea", "select"], warningDuration: 3000, // 高级选项 clearSelectionInterval: 50, devToolsCheckInterval: 1000, redirectOnDevTools: false, // 自定义消息 messages: { rightClick: "🚫 右键功能已被禁用", keyboard: "⌨️ 该快捷键已被禁用", devTools: "🔧 检测到开发者工具", selection: "📝 文本选择已被禁用", }, });
高级技巧
1. 动态内容保护
// 动态添加保护到新内容 function protectNewContent() { const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { mutation.addedNodes.forEach((node) => { if (node.nodeType === Node.ELEMENT_NODE) { node.classList.add("copy-protected"); } }); }); }); observer.observe(document.body, { childList: true, subtree: true, }); }
2. 图片水印保护
// 为图片添加水印 function addWatermarkToImages() { document.querySelectorAll("img").forEach((img) => { img.addEventListener("load", function () { const canvas = document.createElement("canvas"); const ctx = canvas.getContext("2d"); canvas.width = this.naturalWidth; canvas.height = this.naturalHeight; // 绘制原图 ctx.drawImage(this, 0, 0); // 添加水印 ctx.font = "20px Arial"; ctx.fillStyle = "rgba(255, 255, 255, 0.5)"; ctx.fillText("© 版权所有", 10, 30); // 替换原图 this.src = canvas.toDataURL(); }); }); }
3. 内容加密显示
// 简单的内容混淆 function obfuscateContent() { const textNodes = document.createTreeWalker( document.body, NodeFilter.SHOW_TEXT, null, false ); const nodes = []; let node; while ((node = textNodes.nextNode())) { if (node.textContent.trim()) { nodes.push(node); } } nodes.forEach((node) => { const original = node.textContent; const obfuscated = btoa(original); // Base64编码 node.textContent = obfuscated; // 鼠标悬停时显示原文 node.parentElement.addEventListener("mouseenter", () => { node.textContent = original; }); node.parentElement.addEventListener("mouseleave", () => { node.textContent = obfuscated; }); }); }
浏览器兼容性
功能 | Chrome | Firefox | Safari | Edge | IE11 |
---|---|---|---|---|---|
user-select | ✅ | ✅ | ✅ | ✅ | ✅ |
contextmenu 事件 | ✅ | ✅ | ✅ | ✅ | ✅ |
selectstart 事件 | ✅ | ✅ | ✅ | ✅ | ✅ |
dragstart 事件 | ✅ | ✅ | ✅ | ✅ | ✅ |
keydown 事件 | ✅ | ✅ | ✅ | ✅ | ✅ |
touch-callout | ❌ | ❌ | ✅ | ❌ | ❌ |
tap-highlight-color | ✅ | ❌ | ✅ | ✅ | ❌ |
常见问题解答
Q1: 这些方法能 100%防止复制吗?
A: 不能。这些方法只能防止普通用户的意外复制,技术熟练的用户仍然可以通过多种方式绕过这些限制。
Q2: 会影响 SEO 吗?
A: 适当使用不会影响 SEO。搜索引擎爬虫通常不会执行 JavaScript,所以 CSS 的user-select: none
不会影响内容索引。
Q3: 如何在保护内容的同时保持可访问性?
A:
- 确保输入框和表单元素可以正常使用
- 为屏幕阅读器用户提供替代的内容访问方式
- 不要完全禁用键盘导航
Q4: 移动端效果如何?
A: 移动端的保护效果相对较好,特别是 iOS Safari 的-webkit-touch-callout: none
可以有效禁用长按菜单。
以上就是基于JavaScript+CSS实现禁用浏览器复制功能的几种方法的详细内容,更多关于JavaScript CSS禁用浏览器复制的资料请关注脚本之家其它相关文章!