最新消息: USBMI致力于为网友们分享Windows、安卓、IOS等主流手机系统相关的资讯以及评测、同时提供相关教程、应用、软件下载等服务。

JS检测浏览器开发者工具是否打开

业界 admin 3浏览 0评论

在有些情况下 我们需要检测用户是否打开了浏览器的开发者工具 右键检查出来的就是开发者工具 比如前端爬虫检测 或者是避免用户非法篡改信息 本篇文章主要讲述几种前端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;
    }
 
})();

缺点:

  1. 使用window属性检查大小可能会有浏览器兼容性问题,因为不是专业前端只测试了Chrome和ff是没有问题的。

  2. 此方案还是有漏洞的,就拿Chrome浏览器来说,开发者工具窗口有四个选项:单独窗口、靠左、靠下、靠右。

  3. 靠左、靠右、靠下都会占用当前窗口的一些空间,这种情况会被检测到,但是独立窗口并不会占用打开网页窗口的空间,所以这种情况是检测不到的,可去此页面进行验证: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;
    }
 
})();

缺点:

  1. 使用window属性检查大小可能会有浏览器兼容性问题,因为不是专业前端只测试了Chrome和ff是没有问题的。

  2. 此方案还是有漏洞的,就拿Chrome浏览器来说,开发者工具窗口有四个选项:单独窗口、靠左、靠下、靠右。

  3. 靠左、靠右、靠下都会占用当前窗口的一些空间,这种情况会被检测到,但是独立窗口并不会占用打开网页窗口的空间,所以这种情况是检测不到的,可去此页面进行验证:https://sindresorhus/devtools-detect/。
    详细内容参考: https://wwwblogs/cc11001100/p/9265945.html

发布评论

评论列表 (0)

  1. 暂无评论