技术点:setInterval定时器+Object.defineProperty
背景:
某天打开文心一言想看看接口返回结构是怎样的,熟练的打开浏览器开发者工具查看网络请求。
发现出现了以下debugger断点
这难不倒我,去掉断点调试,继续下一步不就行了?心中暗暗自喜,一顿操作猛如虎,一看居然是二百五。什么鬼?怎样跳转空白页面了?我怎么看数据结构?
它是怎样做到检测debugger模式,并且跳转空白页面的?
出于好奇,带着问题我进行了研究,原理很简单,几行代码就可以实现
作用:
通过检查是否打开开发者调试工具,做一些相应的逻辑判断。防止被人恶意调试页面代码,发现漏洞
原理:
1.通过setInterval定时器轮询执行debugger,并记录执行时的时间
2.当操作浏览器跳过debugger继续执行时,获取当前时间
3.当前时间减去执行时的时间大于某个值时,则跳转到空白页面
代码解析:
// 禁用浏览器debuggerfunction disableDebugger() {const obj = Object.create(null);// 记录当前时间let t = Date.now();//监听对象属性的获取Object.defineProperty(obj, 'is_debug', {get: () => {// 当对象属性的取值方法被触发时,判断时间间隔是否大于50ms,替换为空白页if (Date.now() - t > 50) {location.replace('about:blank')}},});// 定时打印is_debug触发属性的get方法进行判断setInterval(() => {// 记录开始debugger时间t = Date.now();//触发debugger//通过构造函数 Function 来创建一个新的函数,这个新函数的内容是调用debugger,(function debug() {})['constructor']('debugger')();// 触发obj.is_debug的get方法console.log(obj.is_debug);}, 100);}disableDebugger()
疑问:
1.为什么通过console.log(obj.is_debug)获取值,从而触发Object.defineProperty get方法,而不是直接判断时间触发跳转?
答:增加代码阅读难度,防新手。哈哈,顺便复习一下defineProperty的使用
2.为什么使用构造函数调用debugger,直接调用不行吗?
答:增加代码阅读难度,防新手;可以
总结:通过js防止别人debugger代码其实是伪代码,只能防君子,防不了小人;防新手防不了大神;先打开调试工具,去除断点设置,再打输入网页地址,该方法就会失效。