From 675f7e501296caecc838d9f082451da0d8b19d37 Mon Sep 17 00:00:00 2001 From: ysn <2126564605@qq.com> Date: Tue, 19 May 2026 09:32:11 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A6=81=E7=94=A8=20F12=E3=80=81=E7=A6=81?= =?UTF-8?q?=E6=AD=A2=E5=8F=B3=E9=94=AE=E6=BA=90=E7=A0=81=E6=B3=84=E9=9C=B2?= =?UTF-8?q?=E3=80=81=E9=94=99=E8=AF=AF=E9=A1=B5=E4=B8=8D=E6=8A=9B=E5=A0=86?= =?UTF-8?q?=E6=A0=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.js | 5 ++ src/utils/security.js | 142 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 src/utils/security.js diff --git a/src/main.js b/src/main.js index da01750..50a1c5f 100644 --- a/src/main.js +++ b/src/main.js @@ -4,6 +4,8 @@ import Cookies from 'js-cookie' import Element from 'element-ui' import './assets/styles/element-variables.scss' +// 安全防护 +import { initSecurity, setupErrorHandler } from '@/utils/security' import '@/assets/styles/index.scss' // global css import '@/assets/styles/ruoyi.scss' // ruoyi css @@ -74,6 +76,9 @@ Vue.use(Element, { }) Vue.config.productionTip = false +// 初始化安全防护 +initSecurity() +setupErrorHandler(Vue) new Vue({ el: '#app', diff --git a/src/utils/security.js b/src/utils/security.js new file mode 100644 index 0000000..90f3791 --- /dev/null +++ b/src/utils/security.js @@ -0,0 +1,142 @@ +/** + * 安全防护模块 + * 禁用 F12、禁止右键、隐藏错误堆栈 + */ + +export function initSecurity() { + // 生产环境才启用安全防护 + if (process.env.NODE_ENV !== 'production') { + return; + } + + // ============================================== + // 1. 禁用 F12 打开开发者工具 + // ============================================== + document.addEventListener('keydown', function(e) { + // F12 + if (e.keyCode === 123) { + e.preventDefault(); + e.stopPropagation(); + return false; + } + // Ctrl + Shift + I + if (e.ctrlKey && e.shiftKey && e.keyCode === 73) { + e.preventDefault(); + e.stopPropagation(); + return false; + } + // Ctrl + Shift + J + if (e.ctrlKey && e.shiftKey && e.keyCode === 74) { + e.preventDefault(); + e.stopPropagation(); + return false; + } + // Ctrl + U (查看源代码) + if (e.ctrlKey && e.keyCode === 85) { + e.preventDefault(); + e.stopPropagation(); + return false; + } + // Ctrl + S (保存页面) + if (e.ctrlKey && e.keyCode === 83) { + e.preventDefault(); + e.stopPropagation(); + return false; + } + }); + + // ============================================== + // 2. 禁止右键菜单 + // ============================================== + document.addEventListener('contextmenu', function(e) { + e.preventDefault(); + e.stopPropagation(); + return false; + }); + + // ============================================== + // 3. 防止通过控制台注入 + // ============================================== + const originalConsole = console; + const blockedMethods = ['debug', 'log', 'info', 'warn', 'error']; + + // 只在生产环境屏蔽控制台 + blockedMethods.forEach(method => { + console[method] = function() {}; + }); + + // 保留一个隐藏的控制台方法供内部使用 + window.__safeConsole = originalConsole; + + // ============================================== + // 4. 检测开发者工具并警告 + // ============================================== + function detectDevTools() { + const threshold = 160; + const devtools = { + open: false, + orientation: null + }; + + const check = setInterval(() => { + const widthThreshold = window.outerWidth - window.innerWidth > threshold; + const heightThreshold = window.outerHeight - window.innerHeight > threshold; + const orientation = widthThreshold ? 'vertical' : 'horizontal'; + + if (!(heightThreshold && widthThreshold) && + ((window.Firebug && window.Firebug.chrome && window.Firebug.chrome.isInitialized) || + widthThreshold || heightThreshold)) { + if (!devtools.open) { + devtools.open = true; + devtools.orientation = orientation; + // 可以在这里添加检测到开发者工具时的处理逻辑 + console.log('检测到开发者工具'); + } + } else { + devtools.open = false; + devtools.orientation = null; + } + }, 500); + + return function() { + clearInterval(check); + }; + } + + // 启动检测 + detectDevTools(); +} + +/** + * Vue 错误处理器 - 隐藏错误堆栈 + */ +export function setupErrorHandler(Vue) { + Vue.config.errorHandler = function(err, vm, info) { + // 生产环境只记录错误,不抛出详细堆栈 + if (process.env.NODE_ENV === 'production') { + // 可以在这里发送错误日志到服务器 + console.error('应用错误:', err.message); + // 不抛出详细错误信息,避免泄露源码 + return; + } + // 开发环境正常抛出错误 + console.error('Vue Error:', err, info); + }; + + // 全局异常捕获 + window.addEventListener('error', function(e) { + if (process.env.NODE_ENV === 'production') { + e.preventDefault(); + // 只记录错误消息,不暴露堆栈 + console.error('全局错误:', e.message); + } + }); + + // Promise 未捕获异常 + window.addEventListener('unhandledrejection', function(e) { + if (process.env.NODE_ENV === 'production') { + e.preventDefault(); + console.error('Promise错误:', e.reason?.message || 'Unknown'); + } + }); +} \ No newline at end of file