admin 管理员组

文章数量: 887021

实现

一、阻止打开

首先得知道用户能通过什么方式打开控制台,一个是通过键盘事件,一个是鼠标右键。
那就通过禁止键盘的f12事件:

漏洞:浏览器设置其他快捷键打开控制台,没了。

禁止右键事件:

识别打开

这时候问题来啦,有个聪明的小伙说那我先打开控制台,再进网站呢。
好问题,那就得让程序判断你有没有打开控制台:

通过浏览器宽高和可视宽高对比

这种是通过获取浏览器的可视区域宽高(整个浏览器)window.innerWidth / window.innerHeight和浏览器中项目显示的宽高(包括书签栏)window.outerWidth / window.outerHeight之间的差值来判断的,由于书签栏可能没显示,所以这个差值是有容错范围的,所以这个判断并不太准确,一般为200差值内就算没打开。

漏洞:这里的漏洞就特别大了,如果打开toggle device toolbar,或者设置控制台从新窗口打开,这个方法就无效了。实际上很多小小付费网站都是通过这种方法来阻止用户打开f12的。

通过控制台特性
1、 改写对象toString

这个方法好像只有给予chrome内核有效(我只在firfoxchromeie测试过):如果控制台输出的是对象,则保留对象的引用,每次打开控制台的时候,如果对象类型是function、date等(以前还有regexp,现在已失效),都会重新调用一下对象的toString()方法,将返回结果打印到控制台上。

经过测试:

步骤一步骤二步骤三结果
声明对象重写toString打印对象toString会在开始时多运行一次,所以可以使用一个计数器来判断哪次有效
声明对象打印对象重写toString如果初始化时控制台是开启状态,会检测不到这一次的状态
声明对象重写toString打印对象(这里的对象不做为第一个参数)可以成功监测每一次控制台状态

漏洞:只有对chrome内核的浏览器生效;或者重写console来处理,在地址栏输入以下代码再打开目标页面:

不过这个方法也可能失效,比如项目重写了console方法,使用_console来实现打印,也有可能就不是用console.log来打印的,可能用console.infoconsole.error

2、监听dom属性

浏览器在打印dom元素的时候,如果控制台处于关闭状态,不会获取元素属性,但是如果控制台处于开启状态,就会自动获取dom属性,从而触发监听事件

漏洞:不支持firfox

3、通过时间差

可以通过在代码里面加上debugger断点,这样要是用户打开控制台代码会在断点停止执行,会有一个时间差,有点烦的是由于项目eslint规定不能写debugger,还要加上no-debugger的注释

漏洞:如果设置浏览器断点不停止;或者有些项目在webpack配置drop_debugger: true,那debugger也会无效;

通过debugger这种方式还有一种方法是通过调用栈溢出这种思路来实现,如果打开控制套并设置断点不停止,这时候会因为一直调用某个方法导致调用栈溢出。所以,们可以设置一个间隔2000ms的定时器来不断执行某个方法,这样当控制台开启时,不论是否取消debugger调式,都会使页面卡住:

总结

我个人针对阻止用户打开控制台是结合2和3一起使用的。
虽然前端谈安全本身就是个伪命题,但是为什么还要做呢?
个人觉得,第一是能有效的提升前端被破解的门槛,二是能从安全的角度对项目进行思考优化。
反正,我做安全首先都会去实践尝试其他网站的防范方法,并尝试破解,成功的话还是挺有成就感的。

本文标签: 控制台 用户