⚠️重要提醒:无论怎么加固,前端防护永远不能100%杜绝源码查看,只能提高破解门槛,增加逆向成本。核心业务、密钥、算法必须放后端。
目标:对抗前面提到的破解手段:控制台修改、油猴脚本、打印预览、地址栏javascript伪协议、定时器绕过等。
1. 思路总览
基础版漏洞点:
- 仅仅赋值
oncontextmenu,如果网页/油猴使用addEventListener注册右键事件可以覆盖绕过。 - 防护变量、函数暴露在全局作用域,控制台可以直接修改变量关闭检测。
Ctrl+P打印预览页面内容完全暴露。debugger可以被开发者工具“禁用所有断点”直接废掉。- 防护逻辑只执行一次,外部脚本可以直接重写
oncontextmenu、checkDevTools函数。 - 浏览器地址栏
javascript:伪协议可以直接执行破解代码。
升级手段:
- 使用捕获阶段注册contextmenu事件,高优先级拦截;
- 使用IIFE闭包,把检测变量、函数私有化,不暴露到window全局;
- 增加
@media print媒体查询,打印模式清空页面内容; - 时间差反调试,对抗直接禁用debugger断点;
- 循环定时校验防护逻辑,一旦被篡改立刻恢复;
- 监听页面事件,阻断伪协议书签篡改;
- 禁止选中文本,增加复制难度。
2. 升级版完整HTML页面代码
<!DOCTYPEhtml><htmllang="zh-CN"><head><metacharset="UTF-8"><title>加固版前端防调试演示</title><style>/* 打印预览模式下清空页面内容,对抗Ctrl+P破解 */@mediaprint{body *{display:none!important;}}/* 禁止页面选中文本 */body{user-select:none;-webkit-user-select:none;}</style></head><body><div><h2>加固版:增强前端简易防调试</h2><p>增强对抗:控制台篡改、油猴脚本、打印预览、伪协议书签</p></div><scripttype="text/javascript">// IIFE闭包:所有变量、函数私有,不暴露到window全局,控制台无法直接修改变量(function(){constthreshold=160;letdevToolsOpen=false;// --------------------------// 1.多重拦截右键,捕获阶段优先执行,对抗addEventListener注册的右键事件// --------------------------functionbindContextMenu(){document.oncontextmenu=function(){returnfalse;};// capture=true 捕获阶段优先执行,优先级高于普通事件监听document.addEventListener('contextmenu',function(e){e.preventDefault();e.stopImmediatePropagation();returnfalse;},true);}// --------------------------// 2.键盘快捷键拦截 F12 Ctrl+U Ctrl+Shift+I/J// --------------------------functionbindKeyDown(){document.onkeydown=function(event){vare=event||window.event;if(e.keyCode===123){e.preventDefault();returnfalse;}if(e.ctrlKey&&e.keyCode===85){e.preventDefault();returnfalse;}if(e.ctrlKey&&e.shiftKey&&e.keyCode===73){e.preventDefault();returnfalse;}if(e.ctrlKey&&e.shiftKey&&e.keyCode===74){e.preventDefault();returnfalse;}};}// --------------------------// 3.窗口尺寸检测开发者工具// --------------------------functioncheckDevTools(){constwidthThreshold=window.outerWidth-window.innerWidth>threshold;constheightThreshold=window.outerHeight-window.innerHeight>threshold;if(widthThreshold||heightThreshold){if(!devToolsOpen){devToolsOpen=true;document.body.innerHTML="<div style='color:red;font-size:24px;text-align:center;margin-top:100px'>请勿打开开发者工具!</div>";}}else{devToolsOpen=false;}}// --------------------------// 4.时间差反调试,对抗直接禁用debugger断点// --------------------------functionantiDebugger(){conststart=performance.now();debugger;constend=performance.now();// 如果debugger被触发,时间会明显变长;时间差过大代表开发者工具打开if(end-start>100){document.body.innerHTML="<div style='color:red;font-size:24px;text-align:center;margin-top:100px'>请勿打开开发者工具!</div>";}}// --------------------------// 5.定时巡检:防止外部脚本、油猴脚本篡改防护逻辑,被篡改就立刻恢复// --------------------------functionwatchProtectLogic(){bindContextMenu();bindKeyDown();}// 初始化执行bindContextMenu();bindKeyDown();// 定时器循环setInterval(checkDevTools,500);setInterval(antiDebugger,1000);setInterval(watchProtectLogic,800);})();</script></body></html>3. 各个加固点原理与代码解析
3.1 多重阻止右键(捕获阶段)
原版仅仅设置document.oncontextmenu;油猴/插件可以通过addEventListener后注册事件绕过。
document.addEventListener('contextmenu',function(e){e.preventDefault();e.stopImmediatePropagation();returnfalse;},true);true代表捕获阶段执行,比普通冒泡阶段事件优先级更高;stopImmediatePropagation()阻止页面上其他所有contextmenu事件回调执行;- 配合定时
watchProtectLogic定时重新绑定,就算外部脚本清除事件,800ms后自动恢复。
3.2 闭包私有化变量函数
全部逻辑包裹在(function(){ ... })()闭包内部。
devToolsOpen、threshold、checkDevTools不会挂载到window;- 控制台无法直接访问、修改这些变量,不能直接通过控制台修改
devToolsOpen=false关闭检测。
漏洞:依然可以通过重写
setInterval、或者禁用JS绕过。
3.3 对抗打印预览Ctrl+P
css媒体查询打印样式:
@mediaprint{body *{display:none!important;}}当用户按下Ctrl+P唤起打印预览,页面所有元素直接隐藏,看不到任何内容。
漏洞:浏览器修改打印设置,关闭“使用页面样式”可以绕过。
3.4 时间差反调试对抗禁用debugger断点
conststart=performance.now();debugger;constend=performance.now();if(end-start>100){// 判定打开调试工具}原理:
- 如果开发者工具关闭,
debugger语句直接跳过,执行时间极短; - 如果开发者工具打开,哪怕勾选了禁用所有断点,处理debugger语句依然会消耗额外时间;
- 通过
performance.now()高精度时间判断时间差,识别调试状态。
3.5 定时巡检恢复防护逻辑
setInterval(watchProtectLogic,800);每隔800ms重新绑定右键、键盘拦截事件。
- 油猴脚本、控制台执行代码清除右键事件之后,最多800ms页面会自动重新恢复禁止右键;
- 增加破解难度,破解者需要持续不断覆盖事件。
3.6 user-select禁止选中文本
user-select:none;-webkit-user-select:none;禁止鼠标框选页面文字,普通用户无法直接复制文本。
注意:快捷键
Ctrl+A依然有概率选中文本,不能完全杜绝复制。
4. 仍然存在的漏洞
- 浏览器禁用JavaScript:全部防护直接失效,这是浏览器底层权限,JS无法阻止。
view-source:协议直接在地址栏查看原始HTML源码,JS完全拦截不到。- 抓包工具 Fiddler / Charles,直接拿到HTTP响应原始HTML。
- 开发者工具设置调试工具为独立窗口,窗口尺寸检测逻辑失效。
- 浏览器打印设置关闭页面CSS样式,打印预览依旧可以看到内容。
- 可以使用代理、无头浏览器(Puppeteer)后台获取页面DOM内容。
- 截图 + OCR识别文字,绕开一切JS交互限制。
结论:前端JS只能做防普通人复制,不能做安全保护。
5. 防护等级对比
| 破解手段 | 基础版简易防护 | 升级版进阶防护 |
|---|---|---|
控制台设置document.oncontextmenu=null | ✅直接破解 | 短时间生效,800ms自动恢复 |
| 油猴脚本清除右键事件 | ✅直接破解 | 定时自动恢复,破解需要持续劫持 |
| Ctrl+P打印预览泄露内容 | ✅直接破解 | 打印模式隐藏页面内容 |
| 开发者工具禁用debugger断点 | ✅直接绕过debugger | 增加时间差检测,提升绕过成本 |
| 控制台修改全局变量关闭检测 | ✅直接修改 | 闭包私有化,控制台拿不到内部变量 |
| Shift+右键绕过右键拦截 | ✅可以绕过 | 捕获阶段事件,大部分场景拦截 |
| 禁用JavaScript | 全部失效 | 全部失效 |
| view‑source协议看源码 | 全部失效 | 全部失效 |
6. 生产环境实战建议
- 不要把密钥、核心算法、业务校验写在前端JS,前端一切都可以被篡改。
- 该类防护适合:资讯展示页面,防止普通访客随手复制、截图式复制;不能用于保护敏感业务。
- 如果需要真正保护内容:
- 图片资源加水印;
- 重要文本接口后端鉴权返回;
- 关键校验逻辑全部放在后端;
- 不要过度堆砌反调试代码:大量debugger、循环检测会造成页面CPU占用升高,影响普通用户性能体验。