js控制台使用詳解,javascript控制台怎麼打開

手把手教你如何用JS代碼實現禁止打開控制台

主要為了通過禁止打開控制台,防止別人進行代碼調試。

轉載鏈接:
https://segmentfault.com/a/1190000021459140


1、禁止右鍵查看源碼和F12

//禁止F12鍵盤事件
document.addEventListener('keydown', function(event){
   return 123 != event.keyCode || (event.returnValue = false)
});
//禁止右鍵、選擇、複製
document.addEventListener(『'contextmenu'』, function(event){
   return event.returnValue = false
})

破解:還可以使用瀏覽器菜單中的開發者工具打開控制台

2、通過頁面寬度變化監測控制台

瀏覽寬高變化監測主要是監測瀏覽器可視區域的寬高:window.innerWidth / window.innerHeight(滾動條和內容區)和瀏覽器寬高:window.outerWidth / window.outerHeight(inner的基礎上加上工具條的寬高)之間的差值。

因為我們不知道瀏覽器是否開啟了工具條及工具條的寬高,所以我們設置一個閾值如200,如果outer – inner 大於200,我們就認為開啟了控制台。

function resize(){
    var threshold = 200;
    var widthThreshold = window.outerWidth - window.innerWidth > threshold;
    var heightThreshold = window.outerHeight - window.innerHeight > threshold;
    if(widthThreshold || heightThreshold){
        console.log('控制台打開了')
    }
}
window.addEventListener('resize', resize);
resize()

關於檢測窗口大小,有人專門針對此寫了個庫:
https://github.com/sindresorh…,感興趣的可以去看一下。

破解:監測瀏覽器寬高變化的缺點是非常明顯的,因為這種監測只能針對控制台內嵌的情形,但是很多瀏覽器都支持獨立窗口式的控制台。

3、利用控制台特性改寫對象toString

對於一些瀏覽器,如果控制台輸出的是對象,則保留對象的引用,每次打開控制台的時候,如果對象類型是function、date等(以前還有regexp,現在已失效),都會重新調用一下對象的toString()方法,將返回結果打印到控制台上。

經過測試:1)、先聲明對象,再重寫toString,最後打印對象,那麼toString會在開始時多運行一次,所以可以使用一個計數器來判斷哪次有效2)、先聲明對象,再打印對象,最後重寫toString,那麼如果初始化時控制台是開啟狀態,會檢測不到這一次的狀態3)、先聲明對象,再重寫toString,最後打印對象,但是對象不作為第一個參數,此時就可以成功監測每一次控制台狀態了4)、console.log、console.info、console.error等均有效5)、只在chrome內核瀏覽器有效,firefox、ie失效

var devtools = new Date(); //function(){};
devtools.toString = function() {
    console.log('控制台打開了');
    //或執行一段死循環
    window.open("about:blank", "_self"); 
}
console.log('', devtools);

破解:可通過標籤注入js代碼清空控制台(添加一個網頁標籤,標籤網址為javascript:console.clear();,進入網頁後,點擊該標籤頁,就會運行裏面的代碼),如果是定時器執行上述代碼,還需要重寫清空console(javascript:console.clear();for(var k in console){if(typeof console[k] == ‘function’){console[k] = function(){}}};)。

4、利用控制台特性進行監聽dom屬性

大部分瀏覽器在打印dom元素的時候,如果控制台處於關閉狀態,不會獲取元素屬性,但是如果控制台處於開啟狀態,就會自動獲取dom屬性,從而觸發監聽事件

function observerConsole(){
    //這裡使用dom元素,在打開控制台時才會計算id
    var dom = document.createElement("div")
    Object.defineProperty(dom, "id", {
        get: function(){
            console.log('控制台打開了')
        }
    })
    
    //ie不支持console.table
    //console.info(dom);
    console.log(dom);
}

除了使用console.log,我們還可以使用console.info,console.dir和console.error等等,需要注意的是ie不支持console.table

破解:通過標籤注入js代碼清空控制台,如果是定時器執行打印dom的操作,還需要重寫清空console。

上述方法需要注意瀏覽器對於defineProperty的支持,另外在firefox瀏覽器失效,因為firefox瀏覽器對於對象中監聽的屬性不會取值,需要手動點開才會觸發。所以對於firefox需要另闢蹊蹺才行,這裡我選擇使用debugger語句來實現,debugger 語句調用任何可用的調試功能,可以阻斷代碼執行,如果沒有調試功能可用,則此語句不起作用。所以我們可以在debugger前記錄時間,如果debugger沒有觸發,運行幾條語句的時間幾乎為0,但是如果被觸發,那間隔時間就不是幾十、幾百毫秒了。

function observerConsole(){
    var obj = Object.create(null), t = Date.now();
    Object.defineProperty(obj, "a", {
        get: function() {
            if(Date.now() - t > 100){
                console.log('控制台打開了')
            }
        }
    })
    setInterval(function(){
        t = Date.now();
        (function(){})["constructor"]("debugger")();//debugger;
        console.log(obj.a);
    }, 200)
}

缺點:如果瀏覽器取消了debugger調式,那麼就毫無意義了。chrome:

手把手教你如何用JS代碼實現禁止打開控制台

Firefox:

手把手教你如何用JS代碼實現禁止打開控制台

匯總3、4,可以做如下封裝:

var observerConsole = {
    openCallback: function(){
        console.log('控制台打開了');
        try {
            window.open("about:blank", "_self")
        } catch(e) {
            var btn = document.createElement("button");
            btn.onclick = function() {
                window.open("about:blank", "_self")
            }
            btn.click()
        }
    },
    observer: function(){
        //這裡使用dom元素,在打開控制台時才會計算id
        var dom = document.createElement("div"), that = this;
        Object.defineProperty(dom, "id", {
            get: function(){
                that.openCallback()
            }
        })
        //ie不支持console.table
        //console.info(dom);
        console.log(dom);
    },
    observerF: function(){
        var obj = Object.create(null), t = Date.now(), that = this;
        Object.defineProperty(obj, "a", {
            get: function() {
                if(Date.now() - t > 100){
                    that.openCallback()
                }
            }
        })
        setInterval(function(){
            t = Date.now();
            (function(){})["constructor"]("debugger")();//debugger;
            console.log(obj.a);
        }, 200)
    },
    init: function(){
        var t = window.navigator.userAgent.toLowerCase();
        t.indexOf("firefox") >= 0 ? this.observerF() : this.observer();
    }
}
ConsoleManager.init()

破解:通過標籤注入js代碼清空控制台、取消console.log等反破解:對console.log等進行重寫再包裝,如

let _console = {
      log : console.log,
      info : console.info,
      warn : console.warn,
      error : console.error
};

然後使用_console.log等替換上面的console.log。這裡可以使用閉包,防止別人對_console的再重寫。

代碼測試僅測試了firefox、ie、chrome瀏覽器及部分chrome內核瀏覽器(如360、qq瀏覽器、UC瀏覽器、搜狗瀏覽器)

5、利用debugger的特性,無限遞歸

這個方法不能監測控制台被打開,但是能達到不讓別人瀏覽你代碼的目的。

上面也說了:debugger 語句調用任何可用的調試功能,可以阻斷代碼執行,如果沒有調試功能可用,則此語句不起作用。

另外:每個瀏覽器都有其最大調用棧,如果超出就會拋出Maximum call stack size exceeded的錯誤並終止程序。

利用上面講的特性組合成下面的代碼:

function check() {
    function doCheck(a) {
        (function() {}["constructor"]("debugger")()); //debugger
        doCheck(++a);
    }
    try {
        doCheck(0)
    } catch(err) {
        console.log(err)
    }
};

上面代碼check運行時,如果控制台未開啟,debugger 不會起作用,但是doCheck會不斷循環,直至爆棧,拋出錯誤,中止本次check運行;如果控制台開啟,則會不斷的進行斷點調試和循環doCheck的調用,直至爆棧;如果控制台開啟,但是取消了debugger調式,雖然此時debugger 不會起作用,但遞歸是依然存在的,而且此時網頁性能與未開啟控制台相比會大幅度下降,嚴重的話,可能會卡死瀏覽器。

未開啟控制台時代碼運行時間:
Chrome:30-50ms
Firefox:200-400ms
Ie:10-30ms

開啟控制台但取消debugger時代碼運行時間:
Chrome:1000-2000ms
Firefox:頁面直接卡死

從上面的測試結果來看,我們可以設置一個間隔2000ms的定時器來不斷執行check,這樣當控制台開啟時,不論是否取消debugger調式,都會使頁面卡住。另外我們還可以對代碼進行混淆,增加閱讀困難度,我們還可以利用閉包完成上面操作,防止別人在控制台重置check:check=function(){}。

!function(){
    var _0x1cbb = ["tor", "struc", "call", "ger", "con", "bug", "de", "apply"];
    setInterval(check, 2e3);
    function check() {
        function doCheck(_0x1834ff) {
            if (('' + _0x1834ff / _0x1834ff)['length'] !== 0x1 || _0x1834ff % 0x14 === 0x0) {
                (function() {return !![]}[
                    _0x1cbb[0x4] + _0x1cbb[0x1] + _0x1cbb[0x0]
                ](
                    _0x1cbb[0x6] + _0x1cbb[0x5] + _0x1cbb[0x3]
                )[_0x1cbb[0x2]]());
            } else {
                (function() {return ![]}[
                    _0x1cbb[0x4] + _0x1cbb[0x1] + _0x1cbb[0x0]
                ](
                    _0x1cbb[0x6] + _0x1cbb[0x5] + _0x1cbb[0x3]
                )[_0x1cbb[0x7]]());
            }
            doCheck(++_0x1834ff);
        }
        try {
            doCheck(0)
        } catch(err) { }
    };
}();

優點:兼容性比較好,不易破解

缺點:會影響瀏覽器性能,造成頁面卡頓

破解:想辦法重置check函數

6、總結

如果文章和筆記能帶您一絲幫助或者啟發,請不要吝嗇你的贊和收藏,你的肯定是我前進的最大動力

原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/234330.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
投稿專員的頭像投稿專員
上一篇 2024-12-11 20:12
下一篇 2024-12-11 20:12

相關推薦

發表回復

登錄後才能評論