禁止调试,阻止浏览器F12开发者工具
分析
这两天突然想看看文心一言的http通信请求接口,于是想着用F12看看。谁知道刚打开开发者工具,居然被动debugger了。直接被JS写死的debugger关键字下了断点。行吧,不让调试就不让调试吧,关闭开发者工具之后,直接跳到了空白页。
大家都知道浏览器的开发者工具能干啥,正经的用法:开发时调试代码逻辑,修改布局样式;不正经的用法:改改元素骗骗人,找找网站接口写爬虫,逆向js破解加密等等,所以说前端不安全,永远不要相信用户的输入。
而这次碰到的这个情况确实可以在用户端做一些防御操作,但是也可以绕过。
PS:开发者工具Ctrl+F8可以禁用断点调试
先做一波分析。
首先,防止你用F12调试,先用debugger关键字阻止你进行任何操作。随后,在你关闭之后,又直接跳转到空白页,不让你接着操作。
这就需要一个开发者工具检测的机制了,发现你打开了开发者工具,就给你跳走到空白页。
所以,关键就是要实现开发者工具的检测。
实现
经过查阅一番,发现原来这个debugger可能并不仅仅是阻止你进行调试的功能,同时还兼具判断开发者工具是否打开的作用。怎么实现?
debugger本身只是调试,阻止你继续对前端进行调试,但是代码中并不知道用户是否打开了开发者工具,所以就无法进行更进一步的操作,例如文心一言的跳转到空白页。
但是,有一点,你打开开发者工具之后,debugger下了断点,程序就停到那里了,如果你不打开开发者工具,程序是不会停止到断点的。没错,这就是我们可以判断的方式,时间间隔。正常情况下debugger前后的时间间隔可以忽略不计。但是,当你打开开发者工具之后,这个时间间隔就产生了,判断这个时间间隔,就可以知道是否打开了开发者工具。
<!DOCTYPE html>
<html>
<header>
<title>test</title>
</header>
<body>
<h1>test</h1>
</body>
<script>
setInterval(function() {
var startTime = performance.now();
// 设置断点
debugger;
var endTime = performance.now();
// 设置一个阈值,例如100毫秒
if (endTime - startTime > 100) {
window.location.href = 'about:blank';
}
}, 100);
</script>
</html>
通过设置一个定时循环任务来进行检测。
在不打开发者工具的情况下,debugger是不会执行将页面卡住,而恰恰是利用debugger的这一点,如果你打开开发者工具一定会被debugger卡住,那么上下文时间间隔就会增加,在对时间间隔进行判断,就能巧妙的知道绝对开了开发者工具,随后直接跳转到空白页即可。
performance.now()
返回的时间戳以双精度浮点数 double 的形式表示时间,精度最高可达微秒级。而Date.now():返回的时间戳没有被限制在一毫秒的精确度内,小于 1ms 的测试不出来结果。
1s =1000ms(毫秒) = 1000000(微秒),即1毫秒 = 1000微秒
比如一个例子:
let start = performance.now();
// 调用一个耗时间的循环
for (let i = 0; i < 100000; i++) {
let doSomething = i * i;
}
let end = performance.now()
// 返回的时间戳,是自创建上下文以来经过的时间,跟打开网页的时间有关,但是这不是绝对的。
// 如果返回的值是178764.00000002384185791 这类的,这种的会被处理为 178764
console.log('开始时间:', start); // 178764
console.log('结束时间:', end); // 178764.10000002384
// 以毫秒计的运行时长
console.log('运行时长:',end - start) // 0.10000002384185791 毫秒
performance.now()是一个用于测量代码执行时间的方法,它返回一个高精度的时间戳,表示自页面加载以来的毫秒数。
performance.now()`方法返回的时间戳基于浏览器的性能计时器,通常具有更高的精度和准确性,比使用 Date对象的方式更为精确。这个方法在性能分析和代码优化中经常被使用,可以帮助开发者确定代码执行的耗时,从而找到性能瓶颈并进行优化。
const startTime = performance.now();
// 执行一些耗时的操作
for (let i = 0; i < 1000000; i++) {
// 模拟一些计算任务
Math.sqrt(i);
}
const endTime = performance.now();
const executionTime = endTime - startTime;
console.log(`代码执行时间:${executionTime} 毫秒`);
在上述示例代码中,我们使用 `performance.now()` 方法获取代码执行前的时间戳,并将其保存在 `startTime` 变量中。然后,我们执行一些耗时的操作(在这个例子中是一个简单的循环计算平方根)。最后,我们再次调用 `performance.now()` 方法获取代码执行后的时间戳,并将其保存在 `endTime` 变量中。通过计算 `endTime - startTime`,我们得到了代码执行的时间差,即代码执行时间。
请注意,`performance.now()` 返回的时间戳是一个浮点数,通常以毫秒为单位。然而,浏览器可能会根据不同的环境和实现返回更高精度的值,例如微秒(百万分之一秒)或纳秒(十亿分之一秒)。因此,不同浏览器和设备上的精度可能会有所不同。
使用 `performance.now()` 方法可以帮助开发者进行性能测试和优化,以确保代码在执行时达到预期的性能要求。