在有些情况下 我们需要检测用户是否打开了浏览器的开发者工具 右键检查出来的就是开发者工具 比如前端爬虫检测 或者是避免用户非法篡改信息 本篇文章主要讲述几种前端js检测开发者工具是否打开的方法
1.重写toString()
对于一些浏览器,比如Chrome、FireFox,如果控制台输出的是对象,则保留对象的引用,每次打开开发者工具的时候都会重新调用一下对象的toString()方法将返回结果打印到控制台(console tab)上。
所以只需要创建一个对象,重写它的toString()方法,然后在页面初始化的时候就将其打印在控制台上(这里假设控制台还没有打开),当用户打开控制台时会再去调用一下这个对象的toString()方法,用户打开控制台的行为就会被捕获到。
下面是一个小小的例子,当Chrome用户的开发者工具状态从关闭向打开转移时,这个动作会被捕获到并交由回调函数处理:
<html>
<head>
<title>console detect test</title>
</head>
<body>
<script>
/**
* 控制台打开的时候回调方法
*/
function consoleOpenCallback(){
alert("CONSOLE OPEN");
return "";
}
/**
* 立即运行函数,用来检测控制台是否打开
*/
!function () {
// 创建一个对象
let foo = /./;
// 将其打印到控制台上,实际上是一个指针
console.log(foo);
// 要在第一次打印完之后再重写toString方法
foo.toString = consoleOpenCallback;
}()
</script>
</body>
</html>
测试环境火狐
二、debugger
类似于代码里的断点,浏览器在打开开发者工具时(对应于代码调试时的debug模式)检测到debugger标签(相当于是程序中的断点)的时候会暂停程序的执行:
此时需要点一下那个蓝色的“Resume script execution”程序才会继续执行,这中间会有一定的时间差,通过判断这个时间差大于一定的值就认为是打开了开发者工具。这个方法并不会误伤,当没有打开开发者工具时遇到debugger标签不会暂停,所以这种方法还是蛮好的,而且通用性比较广。
下面是一个使用debugger标签检测开发者工具是否打开的例子:
<html>
<head></head>
<body>
<script>
function consoleOpenCallback() {
alert("CONSOLE OPEN");
}
!function () {
const handler = setInterval(() => {
const before = new Date();
debugger;
const after = new Date();
const cost = after.getTime() - before.getTime();
if (cost > 100) {
consoleOpenCallback();
clearInterval(handler)
}
}, 1000)
}();
</script>
</body>
</html>
三、检测窗口大小
检测窗口大小比较简单,首先要明确两个概念,窗口的outer大小和inner大小:
window.innerWidth / window.innerHeight :可视区域的宽高,window.innerWidth包含了纵向滚动条的宽度,window.innerHeight包含了水平(横向)滚动条的宽度。
window.outerWidth / window.outerHeight:会在innerWidth和innerHeight的基础上加上工具条的宽度。
关于检测窗口大小,不再自己写例子,有人专门针对此写了个库:https://github/sindresorhus/devtools-detect,毕竟几百个star,比我这个渣渣写的好多了,代码比较简单,使用部分其github都有说明,这里只对其核心代码做个分析,此处贴出鄙人对此库核心代码的分析:
/* eslint-disable spaced-comment */
/*!
devtools-detect
Detect if DevTools is open
https://github/sindresorhus/devtools-detect
by Sindre Sorhus
MIT License
comment by CC11001100
*/
(function () {
'use strict';
var devtools = {
open: false,
orientation: null
};
// inner大小和outer大小超过threshold被认为是打开了开发者工具
var threshold = 160;
// 当检测到开发者工具后发出一个事件,外部监听此事件即可,设计得真好,很好的实现了解耦
var emitEvent = function (state, orientation) {
window.dispatchEvent(new CustomEvent('devtoolschange', {
detail: {
open: state,
orientation: orientation
}
}));
};
// 每500毫秒检测一次开发者工具的状态,当状态改变时触发事件
setInterval(function () {
var widthThreshold = window.outerWidth - window.innerWidth > threshold;
var heightThreshold = window.outerHeight - window.innerHeight > threshold;
var orientation = widthThreshold ? 'vertical' : 'horizontal';
// 第一个条件判断没看明白,heightThreshold和widthThreshold不太可能同时为true,不论是其中任意一个false还是两个都false取反之后都会为true,此表达式恒为true
if (!(heightThreshold && widthThreshold) &&
// 针对Firebug插件做检查
((window.Firebug && window.Firebug.chrome && window.Firebug.chrome.isInitialized) || widthThreshold || heightThreshold)) {
// 开发者工具打开,如果之前开发者工具没有打开,或者已经打开但是靠边的方向变了才会发送事件
if (!devtools.open || devtools.orientation !== orientation) {
emitEvent(true, orientation);
}
devtools.open = true;
devtools.orientation = orientation;
} else {
// 开发者工具没有打开,如果之前处于打开状态则触发事件报告状态
if (devtools.open) {
emitEvent(false, null);
}
// 将标志位恢复到未打开
devtools.open = false;
devtools.orientation = null;
}
}, 500);
if (typeof module !== 'undefined' && module.exports) {
module.exports = devtools;
} else {
window.devtools = devtools;
}
})();
缺点:
-
使用window属性检查大小可能会有浏览器兼容性问题,因为不是专业前端只测试了Chrome和ff是没有问题的。
-
此方案还是有漏洞的,就拿Chrome浏览器来说,开发者工具窗口有四个选项:单独窗口、靠左、靠下、靠右。
-
靠左、靠右、靠下都会占用当前窗口的一些空间,这种情况会被检测到,但是独立窗口并不会占用打开网页窗口的空间,所以这种情况是检测不到的,可去此页面进行验证:https://sindresorhus/devtools-detect/。
详细内容参考: https://wwwblogs/cc11001100/p/9265945.html
在有些情况下 我们需要检测用户是否打开了浏览器的开发者工具 右键检查出来的就是开发者工具 比如前端爬虫检测 或者是避免用户非法篡改信息 本篇文章主要讲述几种前端js检测开发者工具是否打开的方法
1.重写toString()
对于一些浏览器,比如Chrome、FireFox,如果控制台输出的是对象,则保留对象的引用,每次打开开发者工具的时候都会重新调用一下对象的toString()方法将返回结果打印到控制台(console tab)上。
所以只需要创建一个对象,重写它的toString()方法,然后在页面初始化的时候就将其打印在控制台上(这里假设控制台还没有打开),当用户打开控制台时会再去调用一下这个对象的toString()方法,用户打开控制台的行为就会被捕获到。
下面是一个小小的例子,当Chrome用户的开发者工具状态从关闭向打开转移时,这个动作会被捕获到并交由回调函数处理:
<html>
<head>
<title>console detect test</title>
</head>
<body>
<script>
/**
* 控制台打开的时候回调方法
*/
function consoleOpenCallback(){
alert("CONSOLE OPEN");
return "";
}
/**
* 立即运行函数,用来检测控制台是否打开
*/
!function () {
// 创建一个对象
let foo = /./;
// 将其打印到控制台上,实际上是一个指针
console.log(foo);
// 要在第一次打印完之后再重写toString方法
foo.toString = consoleOpenCallback;
}()
</script>
</body>
</html>
测试环境火狐
二、debugger
类似于代码里的断点,浏览器在打开开发者工具时(对应于代码调试时的debug模式)检测到debugger标签(相当于是程序中的断点)的时候会暂停程序的执行:
此时需要点一下那个蓝色的“Resume script execution”程序才会继续执行,这中间会有一定的时间差,通过判断这个时间差大于一定的值就认为是打开了开发者工具。这个方法并不会误伤,当没有打开开发者工具时遇到debugger标签不会暂停,所以这种方法还是蛮好的,而且通用性比较广。
下面是一个使用debugger标签检测开发者工具是否打开的例子:
<html>
<head></head>
<body>
<script>
function consoleOpenCallback() {
alert("CONSOLE OPEN");
}
!function () {
const handler = setInterval(() => {
const before = new Date();
debugger;
const after = new Date();
const cost = after.getTime() - before.getTime();
if (cost > 100) {
consoleOpenCallback();
clearInterval(handler)
}
}, 1000)
}();
</script>
</body>
</html>
三、检测窗口大小
检测窗口大小比较简单,首先要明确两个概念,窗口的outer大小和inner大小:
window.innerWidth / window.innerHeight :可视区域的宽高,window.innerWidth包含了纵向滚动条的宽度,window.innerHeight包含了水平(横向)滚动条的宽度。
window.outerWidth / window.outerHeight:会在innerWidth和innerHeight的基础上加上工具条的宽度。
关于检测窗口大小,不再自己写例子,有人专门针对此写了个库:https://github/sindresorhus/devtools-detect,毕竟几百个star,比我这个渣渣写的好多了,代码比较简单,使用部分其github都有说明,这里只对其核心代码做个分析,此处贴出鄙人对此库核心代码的分析:
/* eslint-disable spaced-comment */
/*!
devtools-detect
Detect if DevTools is open
https://github/sindresorhus/devtools-detect
by Sindre Sorhus
MIT License
comment by CC11001100
*/
(function () {
'use strict';
var devtools = {
open: false,
orientation: null
};
// inner大小和outer大小超过threshold被认为是打开了开发者工具
var threshold = 160;
// 当检测到开发者工具后发出一个事件,外部监听此事件即可,设计得真好,很好的实现了解耦
var emitEvent = function (state, orientation) {
window.dispatchEvent(new CustomEvent('devtoolschange', {
detail: {
open: state,
orientation: orientation
}
}));
};
// 每500毫秒检测一次开发者工具的状态,当状态改变时触发事件
setInterval(function () {
var widthThreshold = window.outerWidth - window.innerWidth > threshold;
var heightThreshold = window.outerHeight - window.innerHeight > threshold;
var orientation = widthThreshold ? 'vertical' : 'horizontal';
// 第一个条件判断没看明白,heightThreshold和widthThreshold不太可能同时为true,不论是其中任意一个false还是两个都false取反之后都会为true,此表达式恒为true
if (!(heightThreshold && widthThreshold) &&
// 针对Firebug插件做检查
((window.Firebug && window.Firebug.chrome && window.Firebug.chrome.isInitialized) || widthThreshold || heightThreshold)) {
// 开发者工具打开,如果之前开发者工具没有打开,或者已经打开但是靠边的方向变了才会发送事件
if (!devtools.open || devtools.orientation !== orientation) {
emitEvent(true, orientation);
}
devtools.open = true;
devtools.orientation = orientation;
} else {
// 开发者工具没有打开,如果之前处于打开状态则触发事件报告状态
if (devtools.open) {
emitEvent(false, null);
}
// 将标志位恢复到未打开
devtools.open = false;
devtools.orientation = null;
}
}, 500);
if (typeof module !== 'undefined' && module.exports) {
module.exports = devtools;
} else {
window.devtools = devtools;
}
})();
缺点:
-
使用window属性检查大小可能会有浏览器兼容性问题,因为不是专业前端只测试了Chrome和ff是没有问题的。
-
此方案还是有漏洞的,就拿Chrome浏览器来说,开发者工具窗口有四个选项:单独窗口、靠左、靠下、靠右。
-
靠左、靠右、靠下都会占用当前窗口的一些空间,这种情况会被检测到,但是独立窗口并不会占用打开网页窗口的空间,所以这种情况是检测不到的,可去此页面进行验证:https://sindresorhus/devtools-detect/。
详细内容参考: https://wwwblogs/cc11001100/p/9265945.html