js检测浏览器开发者工具打开状态

更新日期: 2021-10-09阅读: 1.5k标签: 浏览器

本篇文章基于github上disable-devtool项目做的分析。我这里只对项目中的部分代码进行分析,能力有限,望见谅。项目结构方面我就不进行赘述了,仅对项目src文件夹中的文件进行分析。

src中的main.js文件中,首先引入的是disableKeyAndMenu方法,是用来阻止鼠标右键和键盘打开开发者工具的。

function disableKeyAndMenu () {
    window.addEventListener('keydown', (e) => {
        e = e || window.event;
        const keyCode = e.keyCode || e.which;// 
        alert(e.keyCode);
        if (keyCode === 123 || (e.shiftKey && e.ctrlKey && e.keyCode === 73)) {
            e.returnValue = false;
            e.preventDefault();
            return false;}
        }, false);
        if (config.disableMenu) {
            window.addEventListener('contextmenu', (e) => {
            e = e || window.event;
            e.returnValue = false;
            e.preventDefault();
            return false;
        }, false);
    }
}

这个就很明显了,监听按键事件,如果按到可以打开开发者工具的按键就阻止默认事件。同时对页面进行监听,阻止鼠标右键事件。contextmenu就是用来监听触发内容菜单的,鼠标右键或者笔记本键盘的两指点击都可以监听到。

然后引入的是initInterval方法,该方法是用来初始化事件循环,防止用户在使用中使用其他方法打开开发者工具时页面无法得知。

export function initInterval () {
    let _pause = false;
    const pause = () => {_pause = true;};
    const goon = () => {_pause = false;};
    hackAlert(pause, goon); // 防止 alert等方法触发了debug延迟计算
    onPageShowHide(goon, pause); // 防止切后台触发了debug延迟计算
    interval = window.setInterval(() => {
        if (_pause) return;
        calls.forEach(fn => {fn(time++);
    });
        console.clear();
    }, config.interval);
    // 两秒之后判断 如果不是pc去掉定时器interval,为了优化移动端的性能
    // 如果控制面板被打开了该定时器timer会被清除
    timer = setTimeout(() => {
        if (!isPC()) {
            clearDDInterval();
        }
    }, config.stopIntervalTime);
}

其中isPc, hackAlter, onPageShowHIde是项目中封装的代码,都比较简单,我就不细说了。
简而言之这部分代码的功能就是如果是pc端打开网页,就执行事件循环检测开发者工具的运行状态。

然后就是核心部分的代码,initDetectors.

这个方法里面调用了三种方法去判断开发者工具的打开状态。

1:toString

function detector () {
    const isQQ = isQQBrowser();
    const isFF = isFirefox();
    //因为这个方法在chrome中执行有点问题,所以如果是chrome浏览器则直接返回,不再执行。
    if (!isQQ && !isFF) return;
    let lastTime = 0;
    const reg = /./;
    console.log(reg);
    reg.toString = function () {
        if (isQQ) { 
            // ! qq浏览器在控制台没有打开的时候也会触发 打开的时候会连续触发两次 使用这个来判断
            const time = new Date().getTime();
            if (lastTime && time - lastTime < 100) {
                triggerOnDevOpen(DETECTOR_TYPE.TO_STRING);
            } else {
                lastTime = time;
            }
        }else if (isFF) {    
            triggerOnDevOpen(DETECTOR_TYPE.TO_STRING);
        }
        return '';
    };
    registInterval(() => {
        console.log(reg);
    });
}

这个方法是基于console.log的工作原理去执行的。因为console.log的方法是根据不同浏览器去制定的,所以导致了不同的浏览器有不同的执行逻辑。我就以chrome举例来说吧。

chrome的控制台中console.log()是在打印对象的时候采用了懒加载的思路,在用户点击展开对象属性的时候,才会去获取该属性。但是chrome在执行console.log的时候就会执行一次reg的toString方法,这也是为什么无论这个开发者工具打开与否,如果toString方法里面和火狐浏览器一样去判断的话都会执行后面的代码。凭借着chrome的console.log的懒加载和直接执行的toString,可以进行判断,执行两次就是打开了开发者工具,执行一次就是没打开开发者工具。

当然,不同的浏览器有不同的情况,具体情况还需要在调试中不断修改。

2:defind-id

function detector () {
    const div = document.createElement('div');
    div.defineGetter('id', function () {
        triggerOnDevOpen(DETECTOR_TYPE.DEFINE_ID);
    });
    Object.defineProperty(div, 'id', {
        get: function () {
            triggerOnDevOpen(DETECTOR_TYPE.DEFINE_ID);
        },
    });
    registInterval(() => {
        console.log(div);
    });
}

通过创建一个div,并对div的id进行get监听,在控制台打印这个div的时候就可以得知开发者工具的打开状态。而且由于打印的懒加载,也可以确定如果开发者工具没有打开,div的id的get方法不会执行。

3:size

function checkWindowSizeUneven () {
    const threshold = 160;
    const widthUneven = window.outerWidth - window.innerWidth > threshold;
    const heightUneven = window.outerHeight - window.innerHeight > threshold;
    if (widthUneven || heightUneven) {
        triggerOnDevOpen(DETECTOR_TYPE.SIZE);
        return false;
    }
    return true;
}
export default function detector () {
    checkWindowSizeUneven();
    window.addEventListener('resize', () => {
        setTimeout(checkWindowSizeUneven, 100);
    }, true);
}

第三种方法是最简单的,就是当页面打开了开发者工具,开发者工具就会占据页面的一部分,同时监听resize时间,当页面尺寸有变化的时候会做出反映。160的参数可以保证下载和一些其他情况下不会误判断。

但是如果开发者工具是单独的页面这部分就很难去有一个精准的判断。而且chrome浏览器把开发者工具放到页面下方,最小的时候可以达到153像素(版本 94.0.4606.71(正式版本) (x86_64)),有可能会影响结果。

这三种是用户无感知的三种方法,还有一种用户可以感知到的方法。

!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);
}();

方法比较简单,就是比较两个date的时间差,如果debugger执行了,就是打开了开发者工具。但是这个方法也会受到影响,如果用户在sources中关闭了调试模式就无法做出正确的判断了

作者:算了_
链接:https://juejin.cn/post/7017016150269624356
来源:稀土掘金


链接: https://fly63.com/article/detial/10717

浏览器禁用了javascript,各种浏览器如何开启javascript的方法总汇

您的浏览器禁用了JS脚本运行,请启用该功能。怎么解除浏览器禁用js?这篇文章将总结整理各个浏览器如何开启、禁用javascript的方法总汇。

浏览器的回流与重绘 (Reflow & Repaint)

浏览器使用流式布局模型 (Flow Based Layout)。浏览器会把HTML解析成DOM,把CSS解析成CSSOM,DOM和CSSOM合并就产生了Render Tree。有了RenderTree,我们就知道了所有节点的样式,然后计算他们在页面上的大小和位置,最后把节点绘制到页面上。

IE6浏览器有哪些常见的bug,以及解决IE6常用bug的方法

IE6不支持min-height,解决办法使用css hack,ol内li的序号全为1,不递增。解决方法:为li设置样式display: list-item;定位父元素overflow: auto;,包含position: relative;子元素,子元素高于父元素时会溢出。解决办法:

css重设样式_清除浏览器的默认样式

由于不同的浏览器默认的样式也不同,所以在网页开发前设置一个公用样式,来清除各个浏览器的默认样式,已达到做的网页在各个浏览器中达到统一。

浏览器访问一个网站所经历的步骤

浏览器访问网站的步骤:Chrome搜索自身的DNS缓存、读取本地HOST文件、浏览器发起一个DNS的一个系统调用、浏览器获得域名对应的IP地址后,发起HTTP三次握手、TCP/IP连接建立起来、服务器端接受到了这个请求、浏览器根据拿到的资源对页面进行渲染

一个新式的基于文本的浏览器 Browsh

Browsh是一个纯文本浏览器,可以运行在大多数的TTY终端环境和任何浏览器。目前,终端客户端比浏览器客户端更先进。终端客户端即时更新和交付,以便于体验新的功能,例如,你可以观看视频。

浏览器内核有哪些?主流浏览器的所使用的内核介绍

一般说的浏览器内核是指浏览器最重要的核心部分,RenderingEngine,翻译成中文大概意思就是“解释引擎”,我们一般称为浏览器内核。由于不同的内核各自有一套自己的渲染网页和解释页面代码的机制,所以就会有一些问题存在。

程序员眼中的浏览器是什么样的?IE:有本事你卸了我啊

主流浏览器之争从上个世纪开就开始,已经持续了很长的时间。人们都在笑话IE,纷纷转向其它浏览器。今天,我向大家分享一下针对IE的搞笑图片,只是逗乐而已,喝杯咖啡,坐下来慢慢享受吧。

精打细算浏览器空闲时间

有时候我们希望在浏览器中执行一些低优先级的任务,比如记录统计数据、做一些耗时的数据处理等,暂且将其称为后台任务。这些任务跟动画计算、合成帧、响应用户输入等高优先级的任务共享主线程

深入浏览器事件循环的本质

浏览器的事件循环,前端再熟悉不过了,每天都会接触的东西。但我以前一直都是死记硬背:事件任务队列分为macrotask和microtask,浏览器先从macrotask取出一个任务执行,再执行microtask内的所有任务,接着又去macrotask取出一个任务执行

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!