問題發生背景:
某些網站利用js代碼,阻止用戶使用F12打開debug調試,通過查看網頁源代碼,發現以下代碼:
//debug調試時跳轉頁面 var element = new Image(); Object.defineProperty(element,'id',{get:function(){window.location.href="http://www.baidu.com"}}); console.log(element);
以上代碼創建了一個<img>標簽,利用Object.defineProperty方法,在這個img上定義了id的getter,每當打印element時,就會調用這個getter,跳轉到百度。
在知乎上也看到過這個阻止debug調試的方法,但沒有給出破解方法,最近連續在兩個網站中發現這個代碼,於是嘗試破解
瀏覽器:chrome
破解過程:
1. 毀掉console.log,從而阻止跳轉
在查閱相關解決方法時,找到https://segmentfault.com/q/1010000013487697,其中有一個方法,在書簽中添加 javascript:console.log=function(){};,點一下這個書簽來運行這段js代碼,從而毀掉console.log方法(此前都不知道書簽還能用來運行js,長知識了)。然而實際上,瀏覽器會先執行console.log(element)再執行console.log=function(){},仍然會跳轉到百度,此方法失敗。
2. 監聽beforeunload事件
再次利用書簽的方法來運行js:javascript:window.addEventListener('beforeunload', function (e) { e.preventDefault();e.returnValue = '' });
通過監聽beforeunload事件並指定returnValue,瀏覽器會在網頁跳轉前詢問是否離開此網頁,點擊取消即可留在當前頁面。這樣當我們打開debug調試時,就可以取消頁面跳轉了。
一些迷惑:
1. console.log的執行時機:
在Chrome中,console.log在控制台打開后才起作用,它的確是調用了,但是還沒打印,也就是還沒有觸發<img>標簽id的getter;因此用書簽來毀掉console.log是在調用之后的,無法阻止打開debug時打印<img>標簽從而觸發getter方法。如果我們用書簽再次定義element的id的getter呢,結果也是失敗,因為對getter的重新定義也是在console.log調用之后發生的。這個console.log就像薛定諤的貓,當你打開debug它才會打印,但它已經發生了,你改變不了它發生的事實,除非在網頁加載前就去掉這段代碼或毀掉console.log。
2. 刷新頁面讀取network的數據:
用debug調試讀取network發過來的數據,必須要刷新頁面,一旦刷新,我們對beforeunload的監聽就會失效,必定觸發重定向,導致無法獲取network中資源的請求和響應數據。這時候單純使用瀏覽器的debug調試就很難拿到這些數據了,可以考慮使用postman直接抓包處理。
總結:
js代碼無法阻止用戶使用debug調試,但是能夠增加用戶調試的難度,要看你的頁面代碼始終有辦法。
那么有沒有僅用瀏覽器獲取network數據的方法呢,能否在頁面運行上述代碼前毀掉console.log?各位大佬求解!
(這里是前端小白Jiny,甚至還沒找到工作)