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

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

本篇文章基于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的方法总汇。

监听浏览器刷新及关闭

为保证‘高度安全性’,用户每次退出页面或浏览器都要清除登陆信息,每次进入系统都要重新登陆(每次登陆还要手机验证码等乱七八糟的验证信息,,,求用户的心里阴影面积),但是刷新页面不可以清除登陆信息。

Js实现阻止浏览器返回的功能

无论pc端还是移动端,浏览器都会带有后退按钮或后退键.主要方便我们能返回以前访问过的页面,但有时候我们不得不关闭这个功能.尤其是对于一些推广落地页,用户进入后不希望它返回

window.open被拦截的解决方法总汇

介绍window.open方法被浏览器拦截的处理方式。在 Chrome 的安全机制里,非用户直接触发的 window.open 方法,是会被拦截的,这是由于浏览器为了维护用户安全和体验,下面采用几种变通方法解决:表单提交的方式、onclick事件、延迟打开等

Chrome浏览器crx格式插件安装教程

谷歌浏览器在旧版本(大概是v67版本)之前安装crx插件都非常简单,直接将crx拖放到浏览器内就可以安装了。但是之后的新版本(目前已经升级到v80版本)就只允许用户通过谷歌应用商店安装插件

如何将网站设置为浏览器首页

提示:按 Ctrl + D 即可添加网址到浏览器收藏夹中,方便下次访问fly63导航。下面是如何设置首页的方法。Google Chrome浏览器设为首页的方法;Firefox火狐浏览器设为首页的方法

完美解决安卓端百度浏览器屏蔽fixed悬浮元素的问题

h5活动页面底部有个悬浮图片按钮,使用fixed悬浮定位在底部,但是在安卓端的百度浏览器下打开,却发现该图片一闪而过,在百度浏览器中消失不见。

Fiddler无法正常抓取谷歌等浏览器的请求_解决方案

fiddler会自动给浏览器设置一个代理127.0.0.1端口8888,并且记忆浏览器的代理设置,所有的请求先走fiddler代理,再走浏览器代理。解决方案:关闭SwitchyOmega代理,或者使用其代理中的系统代理选项。即可解决问题。

js判断浏览器内核是否是safari浏览器

PC端只有Chrome有Safari字段吗?为什么不需要判断其他浏览器?其实360,QQ等浏览器的userAgent字段也会带有Safari字段,但是由于他们基于Chrome二次开发的,所有也会携带有Chrome字段。

Vue单页面应用阻止浏览器记住密码

现象1:路由切换时再次提示是否记住密码,解决办法:这其实是个代码bug,在登录页面,用form把输入框都包起来就行了。现象2:autocomplete=off无效

点击更多...

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