整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          Javascript:禁止按鈕,3種方法實(shí)現(xiàn)短信驗(yàn)證

          Javascript:禁止按鈕,3種方法實(shí)現(xiàn)短信驗(yàn)證倒計(jì)時(shí)

          avascript:禁止按鈕,3種方法實(shí)現(xiàn)短信驗(yàn)證倒計(jì)時(shí)

          表單中經(jīng)常會(huì)用到手機(jī)短信驗(yàn)證或者郵箱驗(yàn)證,點(diǎn)擊按鈕發(fā)送驗(yàn)證碼后會(huì)倒計(jì)時(shí),然后按鈕會(huì)成灰色不可點(diǎn)擊狀態(tài),或者點(diǎn)擊無(wú)效。這可以預(yù)防不法分子或者機(jī)器刷驗(yàn)證碼,下面講一下使用禁止按鈕實(shí)現(xiàn)短信驗(yàn)證倒計(jì)時(shí),你知道有幾種方法呢?

          禁止按鈕短信驗(yàn)證

          首先來(lái)了解一下禁止按鈕的實(shí)現(xiàn)和原理:

          <!DOCTYPE html>

          <html>

          <head>

          <title></title>

          <meta charset="utf-8">

          <script type="text/javascript">

          window.onload=function ()

          {

          var oBtn=document.getElementById('btn');

          //禁止按鈕

          oBtn.disabled=false;

          oBtn.onclick=function ()

          {

          oBtn.disabled=true;

          alert(oBtn.value);

          }

          }

          </script>

          </head>

          <body>

          <input type="button" id="btn" value="點(diǎn)我試試">

          </body>

          </html>

          短信驗(yàn)證

          禁止按鈕應(yīng)用:短信驗(yàn)證倒計(jì)時(shí)按鈕3種方法

          1、第一種方法

          <!DOCTYPE html>

          <html>

          <head>

          <title></title>

          <meta charset="utf-8">

          <script type="text/javascript">

          window.onload=function ()

          {

          var oBtn=document.getElementById('btn');

          var timer=null;

          var n=5;

          oBtn.onclick=function ()

          {

          oBtn.disabled=true;

          timer=setInterval(function(){

          n--;

          oBtn.value=n + '秒之后重新發(fā)送';

          if (n==0) {

          clearInterval(timer);

          oBtn.value='5秒之后重新發(fā)送';

          oBtn.disabled=false;

          n=5;

          }

          }, 1000);

          }

          }

          </script>

          </head>

          <body>

          <input type="button" value="5秒之后重新發(fā)送" id="btn">

          </body>

          </html>

          短線驗(yàn)證按鈕倒計(jì)時(shí)方法

          2、第二中方法

          <!DOCTYPE html>

          <html>

          <head>

          <title></title>

          <meta charset="utf-8">

          <script type="text/javascript">

          window.onload=function ()

          {

          var oBtn=document.getElementById('btn');

          var timer=null;

          var n=5;

          oBtn.onclick=function ()

          {

          this.disabled=true;

          var _this=this;

          // alert(_this);

          timer=setInterval(function(){

          // alert(_this);

          n--;

          _this.value=n + '秒之后重新發(fā)送';

          if (n==0) {

          clearInterval(timer);

          _this.value='5秒之后重新發(fā)送';

          _this.disabled=false;

          n=5;

          }

          }, 1000);

          }

          }

          </script>

          </head>

          <body>

          <input type="button" value="5秒之后重新發(fā)送" id="btn">

          </body>

          </html>

          短信驗(yàn)證倒計(jì)時(shí)

          3、第三種方法

          <!DOCTYPE html>

          <html>

          <head>

          <title></title>

          <meta charset="utf-8">

          <script type="text/javascript">

          window.onload=function ()

          {

          var oBtn=document.getElementById('btn');

          var timer=null;

          var n=5;

          var flag=false;

          oBtn.onclick=function ()

          {

          if (flag) {

          return;

          }

          flag=true;

          var _this=this;

          // alert(_this);

          timer=setInterval(function(){

          // alert(_this);

          n--;

          _this.value=n + '秒之后重新發(fā)送';

          if (n==0) {

          clearInterval(timer);

          _this.value='5秒之后重新發(fā)送';

          flag=false;

          n=5;

          }

          }, 1000);

          }

          }

          </script>

          </head>

          <body>

          <input type="button" value="5秒之后重新發(fā)送" id="btn">

          </body>

          </html>

          請(qǐng)關(guān)注鍵盤碼農(nóng),把你想知道的問(wèn)題在下面留言評(píng)論,更新你想要的答案,專為你解答!

          我們開(kāi)發(fā)系統(tǒng)的時(shí)候,可能會(huì)接到這樣的需求:不要讓用戶復(fù)制頁(yè)面上的文字或者圖片,不要讓用戶調(diào)試我們的頁(yè)面,更甚至也不要讓用戶進(jìn)行打印操作等等。

          聽(tīng)起來(lái)是不是讓人很頭大,這咋實(shí)現(xiàn)啊?這有必要嗎?這能禁住么?

          如果你沒(méi)做過(guò)這些,或者沒(méi)接到過(guò)這樣的需求,那你也應(yīng)該看到過(guò)某個(gè)網(wǎng)站做了一些這樣的措施。

          既然要做,我們就得想方案,先來(lái)看看禁止復(fù)制都有哪些方法。

          禁止復(fù)制

          假設(shè)我們有這樣一段代碼:

          <div style="padding-left: 56px;">
            <textarea rows="5" cols="33"></textarea>
          </div>
          <pre>
            海客談瀛洲,煙濤微茫信難求,
          
            越人語(yǔ)天姥,云霞明滅或可睹。
          
            天姥連天向天橫,勢(shì)拔五岳掩赤城。
          
            天臺(tái)四萬(wàn)八千丈,對(duì)此欲倒東南傾。
          
            我欲因之夢(mèng)吳越,一夜飛度鏡湖月。
          
            湖月照我影,送我至剡溪。
            </pre>

          接下來(lái)就通過(guò)這個(gè)例子來(lái)論述我們的方案:

          x效果

          1. 通過(guò)user-select:none

          這是一個(gè)css屬性,標(biāo)識(shí)了元素及其子元素的文本不可被選中,因此設(shè)定之后,文本將不能夠被選中,因此也就不能復(fù)制:

          <pre style="user-select: none;">
            海客談瀛洲,煙濤微茫信難求,
          
            越人語(yǔ)天姥,云霞明滅或可睹。
          
            天姥連天向天橫,勢(shì)拔五岳掩赤城。
          
            天臺(tái)四萬(wàn)八千丈,對(duì)此欲倒東南傾。
          
            我欲因之夢(mèng)吳越,一夜飛度鏡湖月。
          
            湖月照我影,送我至剡溪。
            </pre>

          我們?cè)谶@段文本上,加上這個(gè)樣式。

          效果

          可以看到,文字壓根就不能選擇,從鼠標(biāo)形狀也能看出來(lái)。

          1. 通過(guò)攔截copy操作

          由于用在進(jìn)行復(fù)制操作的時(shí)候,會(huì)觸發(fā)copy事件,我們可以通過(guò)監(jiān)聽(tīng)它來(lái)做一些處理,使得復(fù)制的行為發(fā)生改變:

          <div>
            <div style="padding-left: 56px;">
              <textarea rows="5" cols="33"></textarea>
            </div>
            <pre id="content">
              海客談瀛洲,煙濤微茫信難求,
          
              越人語(yǔ)天姥,云霞明滅或可睹。
          
              天姥連天向天橫,勢(shì)拔五岳掩赤城。
          
              天臺(tái)四萬(wàn)八千丈,對(duì)此欲倒東南傾。
          
              我欲因之夢(mèng)吳越,一夜飛度鏡湖月。
          
              湖月照我影,送我至剡溪。
            </pre>
          </div>
          <script>
            let c=document.getElementById('content')
            c.removeEventListener("copy", copyFilter)
            c.addEventListener("copy", copyFilter)
            function copyFilter(e) {
              let cp=e.clipboardData || window.clipboardData
              if(!cp) {
                return
              }
              let text=window.getSelection().toString()
              if(text) {
                e.preventDefault()
                cp.setData("text/plain", "你復(fù)制了一段魔法")
              }
            }
          </script>

          先獲取到我們要禁止復(fù)制的元素,然后給它添加一個(gè)copy的事件監(jiān)聽(tīng),在添加監(jiān)聽(tīng)之前,要先移除一下,這樣是為了避免局部刷新的時(shí)候重復(fù)添加,然后我們通過(guò)copyFilter函數(shù)來(lái)對(duì)這次操作進(jìn)行處理。

          先獲取剪貼板對(duì)象,如果當(dāng)前事件對(duì)象里不存在,那就從window里面取,然后我們通過(guò)getSelection再拿到選取的內(nèi)容,因?yàn)槲覀儗?duì)剪貼板對(duì)象進(jìn)行修改,所以要阻止默認(rèn)行為,然后把剪貼板的內(nèi)容重新賦值,可以是示例中那樣的一段文字,也可以設(shè)置為空,甚至是任意其他內(nèi)容,然后我們就可以看到產(chǎn)生的效果了:

          效果

          雖然能復(fù)制文本,但是由于我們攔截了復(fù)制操作,更改了它的行為,因此再粘貼的時(shí)候就變成了我們更改的樣子,也做到了禁止復(fù)制的功能。

          這種方式對(duì)于使用快捷鍵或者右鍵的方式都是有效的。

          1. 通過(guò)攔截cut操作

          這種情況主要是在可編輯區(qū)域,比如文本框、文本域、設(shè)置為contenteditable的元素等,用戶可以對(duì)文字進(jìn)行剪切操作,雖然上面禁止了復(fù)制,但是剪切是另一個(gè)操作,不攔截的話還是相當(dāng)于能復(fù)制出來(lái)。

          copy和cut只是觸發(fā)的事件不同而已,但是它們都是執(zhí)行相同的邏輯處理:

          <div>
            <div style="padding-left: 56px;">
              <textarea rows="5" cols="33"></textarea>
            </div>
            <pre id="content" contenteditable>
              海客談瀛洲,煙濤微茫信難求,
          
              越人語(yǔ)天姥,云霞明滅或可睹。
          
              天姥連天向天橫,勢(shì)拔五岳掩赤城。
          
              天臺(tái)四萬(wàn)八千丈,對(duì)此欲倒東南傾。
          
              我欲因之夢(mèng)吳越,一夜飛度鏡湖月。
          
              湖月照我影,送我至剡溪。
            </pre>
          </div>
          <script>
            let c=document.getElementById('content')
            c.removeEventListener("cut", copyFilter)
            c.addEventListener("cut", copyFilter)
            function copyFilter(e) {
              let cp=e.clipboardData || window.clipboardData
              if(!cp) {
                return
              }
              let text=window.getSelection().toString()
              if(text) {
                e.preventDefault()
                cp.setData("text/plain", "你復(fù)制了一段魔法")
              }
            }
          </script>

          這里我為了方便,給元素添加了contenteditable屬性,讓它變成可編輯的,copyFilter函數(shù)沒(méi)有變化,我們只是添加了一個(gè)剪切事件的監(jiān)聽(tīng),然后它們的處理函數(shù)都是copyFilter。看下效果:

          效果

          可以看到,首先我們對(duì)文字進(jìn)行剪切,沒(méi)有出現(xiàn)預(yù)期的效果,這時(shí)因?yàn)槲覀冊(cè)诖a里面對(duì)剪切進(jìn)行了攔截,并阻止了它的默認(rèn)行為,然后我們?cè)谡迟N的時(shí)候,文字也改變成我們?cè)O(shè)置的了。

          1. 通過(guò)媒體查詢控制打印

          雖然我們可以通過(guò)上面的幾種方法禁止在頁(yè)面上復(fù)制,但是用戶也可能開(kāi)啟打印預(yù)覽模式,在這種情況下,也是可以進(jìn)行復(fù)制的,我們要想對(duì)打印頁(yè)面進(jìn)行一些控制,那么就要用到媒體查詢,先看下打印的樣子:

          效果

          雖然我們做了限制,但是在打印頁(yè)面沒(méi)有生效,現(xiàn)在我們針對(duì)這個(gè)場(chǎng)景更改一下代碼:

          @media print {
            html {
              display: none;
            }
          }

          通過(guò)添加上面這個(gè)樣式規(guī)則,我們能夠使頁(yè)面在打印的時(shí)候,內(nèi)容隱藏起來(lái),這樣就無(wú)法進(jìn)行復(fù)制了:

          效果

          能夠看到,點(diǎn)擊打印的時(shí)候,預(yù)覽頁(yè)面一片空白,,這樣就禁止了在打印頁(yè)面進(jìn)行復(fù)制的操作。當(dāng)然了,你其實(shí)也可以設(shè)置其他的樣式屬性來(lái)做些控制,但要記住寫在打印的媒體查詢里面,只有這樣才會(huì)在打印頁(yè)面生效。

          1. 通過(guò)偽元素覆蓋內(nèi)容

          還有一種方式就是,通過(guò)設(shè)定一個(gè)偽元素,讓它全面覆蓋文本內(nèi)容,這樣鼠標(biāo)就不能選到實(shí)際的文本,改造一下代碼:

          .content {
            position: relative;
          }
          .content::before {
            content: '';
            position: absolute;
            left: 0px;
            top: 0px;
            width: 100%;
            height: 100%;
          }
          <pre id="content" class="content">
            海客談瀛洲,煙濤微茫信難求,
          
            越人語(yǔ)天姥,云霞明滅或可睹。
          
            天姥連天向天橫,勢(shì)拔五岳掩赤城。
          
            天臺(tái)四萬(wàn)八千丈,對(duì)此欲倒東南傾。
          
            我欲因之夢(mèng)吳越,一夜飛度鏡湖月。
          
            湖月照我影,送我至剡溪。
          </pre>

          現(xiàn)在就不能在元素上面選中文字了,不過(guò)用戶也可能還有一些操作,比如在內(nèi)容區(qū)域外面ctrl+a全選,或者在外面拖動(dòng)鼠標(biāo)來(lái)全選,如果是這種情形,那么我們可以通過(guò)監(jiān)聽(tīng)鍵盤和鼠標(biāo)事件來(lái)禁止全選等操作。

          1. 通過(guò)監(jiān)聽(tīng)鼠標(biāo)和鍵盤事件

          由于用戶有很多種操作的方式,鍵盤全選、鼠標(biāo)全選、鍵盤右鍵、鼠標(biāo)右鍵等等,我們?nèi)绻F舉的話,情況太多了,因此我們只監(jiān)聽(tīng)鼠標(biāo)按下和抬起事件,以及鍵盤的按下事件:

          document.removeEventListener("mousedown", haveSelect)
          document.addEventListener("mousedown", haveSelect)
          document.removeEventListener("mouseup", haveSelect)
          document.addEventListener("mouseup", haveSelect)
          document.removeEventListener("keydown", haveSelect)
          document.addEventListener("keydown", haveSelect)
          function haveSelect() {
            window.getSelection().removeAllRanges()
          }

          主要就是在removeAllRanges方法上面,能夠在觸發(fā)上面事件的時(shí)候,將所選區(qū)域清空,也就是不管你選沒(méi)選,咋選的,反正就是你只要進(jìn)行了操作,那我就那可能選擇的區(qū)域給你清空,這樣你就啥也干不了了。

          效果

          好,這樣就可以啦,無(wú)論怎么選,即使出現(xiàn)了選區(qū),但是只要你再按了鼠標(biāo)或者鍵盤,那么選區(qū)就會(huì)直接消失,就能達(dá)到不能復(fù)制的效果,因?yàn)槟惆l(fā)現(xiàn)啥都做不了。

          這里額外說(shuō)明一下,對(duì)于事件的監(jiān)聽(tīng),一定要用addEventListener來(lái)實(shí)現(xiàn),因?yàn)樗鼤?huì)將多個(gè)綁定的事件都添加上去,當(dāng)觸發(fā)的時(shí)候就會(huì)按照綁定的順序進(jìn)行執(zhí)行,如果是用賦值的方式,那么后面的會(huì)覆蓋前面的,而且賦值的方式很容易被篡改,可以很輕松的讓你的綁定函數(shù)不能執(zhí)行從而失效,而使用addEventListener就不會(huì)被人為覆蓋,只能通過(guò)綁定的函數(shù)句柄來(lái)手動(dòng)移除,也就是說(shuō)要移除的時(shí)候,必須使用跟綁定時(shí)使用同一個(gè)函數(shù)才行。

          通過(guò)CSS的方式禁止復(fù)制,可以很容易的被用戶解除,只能是設(shè)置的稍微復(fù)雜一點(diǎn),增加難度。而通過(guò)JS的方式禁止復(fù)制,也可以通過(guò)禁用頁(yè)面JavaScript代碼來(lái)解除,因此我們可以將內(nèi)容通過(guò)js來(lái)渲染,這樣如果頁(yè)面禁用了js,那么內(nèi)容也不會(huì)渲染。

          禁止調(diào)試

          對(duì)于禁止調(diào)試,主要是指用戶打開(kāi)控制臺(tái),控制臺(tái)也就是開(kāi)發(fā)者工具,我為了方便稱之為控制臺(tái),想要對(duì)頁(yè)面進(jìn)行調(diào)試時(shí),我們做一些處理,阻止這種行為,最大可能的攔截通過(guò)控制臺(tái)對(duì)系統(tǒng)的調(diào)試。
          主要的方法有幾種,由于打開(kāi)控制臺(tái)是瀏覽器提供的調(diào)試功能,因此我們沒(méi)法攔截打開(kāi)操作,即使通過(guò)事件監(jiān)聽(tīng)不允許快捷鍵這樣做,但是也可以通過(guò)其他方式進(jìn)行打開(kāi),因此我們的主要關(guān)注點(diǎn)就在于打開(kāi)控制臺(tái)之后,我們能做哪些事情來(lái)限制用戶行為。

          1. 禁用快捷鍵

          打開(kāi)控制臺(tái)的快捷鍵主要有F12和ctrl+shift+i,我們先把這倆給禁用了:

          document.removeEventListener("keydown", disableDevShortcut)
          document.addEventListener("keydown", disableDevShortcut)
          function disableDevShortcut(e) {
            console.log(e)
            if(e.keyCode===123) {
              e.preventDefault()
            }else if(e.keyCode===73 && e.ctrlKey && e.shiftKey) {
              e.preventDefault()
            }
          }

          這樣在使用這兩個(gè)快捷鍵的時(shí)候,頁(yè)面沒(méi)有任何反應(yīng),控制臺(tái)也不會(huì)喚起,因?yàn)槲覀冏柚沽怂鼈兊哪J(rèn)行為。

          1. 禁用右鍵的檢查功能

          除了通過(guò)快捷鍵,還可以使用右鍵的方式,并點(diǎn)擊檢查也會(huì)調(diào)出控制臺(tái)。

          效果

          這種情景,我們可以通過(guò)禁止在頁(yè)面上使用右鍵的方式,來(lái)阻止打開(kāi)控制臺(tái):

          document.removeEventListener("contextmenu", cancelContextmenu)
          document.addEventListener("contextmenu", cancelContextmenu)
          function cancelContextmenu(e) {
            e.preventDefault()
          }

          現(xiàn)在就不能通過(guò)右鍵打開(kāi)控制臺(tái)了,但是相應(yīng)的整個(gè)右鍵功能也都不能使用了。

          1. 設(shè)置無(wú)限斷點(diǎn)

          如果用戶最終打開(kāi)了控制臺(tái),比如通過(guò)在瀏覽器的更多功能中來(lái)打開(kāi)的話,那么我就需要采取其他的措施,其中之一就是給代碼設(shè)置無(wú)限斷點(diǎn),因?yàn)閿帱c(diǎn)只在控制臺(tái)打開(kāi)的時(shí)候才會(huì)發(fā)生作用,從而不必?fù)?dān)心非調(diào)試模式下的程序正常運(yùn)行。

          無(wú)限斷點(diǎn)的主要思路就是利用定時(shí)器等手段,頻繁的觸發(fā)斷點(diǎn)效果,使得不能輕松的調(diào)試程序,先看下代碼:

          ;(()=> {
            function breakDebugger() {
              if(new checkDebugger().check) {
                breakDebugger()
              }
            }
            function checkDebugger() {
              const now=new Date();
              eval('(function () {debugger;false;})()')
              const dur=Date.now() - now
              if(dur < 5) {
                return {check: false}
              }else {
                return {check: true}
              }
            }
            setInterval(()=> {
              eval('(function () {debugger;true;})()')
              breakDebugger()
            }, 500)
          })()

          我們利用一個(gè)立即執(zhí)行的自執(zhí)行函數(shù),來(lái)使我們的代碼被封裝在一個(gè)固定塊內(nèi),不與其他部分有任何影響。

          這里主要做了兩步:

          第一步設(shè)置一個(gè)重復(fù)執(zhí)行的定時(shí)器,其中包括了一個(gè)斷點(diǎn)和一個(gè)函數(shù)調(diào)用。

          第二步通過(guò)函數(shù)來(lái)遞歸調(diào)用斷點(diǎn),主要使用了實(shí)例化對(duì)象的方式和時(shí)間差的判斷。

          這樣做的主要作用就是在設(shè)置無(wú)限斷點(diǎn)的同時(shí),也能夠讓每次的斷點(diǎn)都是被重新生成的,看下效果,一目了然:

          效果

          發(fā)現(xiàn)沒(méi)有,我們通過(guò)這種方式,只要打開(kāi)了控制臺(tái),那么就會(huì)進(jìn)入到無(wú)限斷點(diǎn)的循環(huán)中,使得不能做任何其他事情,而且每個(gè)斷點(diǎn)的生成都會(huì)開(kāi)辟一個(gè)新的虛擬運(yùn)行環(huán)境,這種情況下,只有關(guān)閉控制臺(tái),才能結(jié)束斷點(diǎn)。

          即使使用右鍵選擇Never parse here,也毫無(wú)作用,雖然可以通過(guò)Deactive breakpoints按鈕來(lái)徹底禁用斷點(diǎn),就是下面這個(gè)按鈕:

          按鈕

          但是,如果這樣做的話,那么用戶也就同時(shí)失去了調(diào)試其他代碼的能力。

          況且,我們接下來(lái)還會(huì)介紹其他的控制手段,可以配合著使用。

          1. 監(jiān)測(cè)控制臺(tái)開(kāi)啟

          我們?nèi)绻苡幸环N手段,可以知道用戶開(kāi)啟了控制臺(tái),換句話說(shuō)只要控制臺(tái)被打開(kāi),就通知我們或者被我們監(jiān)測(cè)到,那么我們就可以執(zhí)行一些控制手段,這種效果肯定是很理想的,遺憾的是還沒(méi)有這種api暴露給我們?nèi)プ屛覀兡軌蜻@樣做。

          不過(guò)我們可以通過(guò)其他的方式,利用既有的一些能力來(lái)實(shí)現(xiàn)這一點(diǎn),這里我還是使用循環(huán)定時(shí)器,來(lái)不斷的去嗅探用戶是否開(kāi)啟了控制臺(tái),直接看代碼:

          ;(()=> {
            setInterval(function() {
              let foo=document.createElement('a')
              let a1=+new Date()
              console.table(foo)
              let a2=+new Date()
              if(a2 - a1 > 1) {
                location.href='about:blank'
              }
              console.clear()
            }, 500)
          })()

          同樣,通過(guò)一個(gè)自執(zhí)行函數(shù),我們開(kāi)啟了一個(gè)循環(huán)定時(shí)器,然后在回調(diào)方法里面,我們就去實(shí)現(xiàn)上面的目標(biāo),也是分為了兩步:

          第一步創(chuàng)建一個(gè)a元素,然后通過(guò)表格的形式將它打印出來(lái),并記錄下消耗的時(shí)間。

          第二步判斷耗時(shí)的長(zhǎng)短來(lái)控制是否跳轉(zhuǎn)到空白頁(yè),然后清空控制臺(tái)。

          這種方式主要是利用了console.table的特性,它會(huì)將元素以表格的形式輸出到控制臺(tái),大概就像下面的樣子:

          效果

          由于太多了,我就沒(méi)有全部截下來(lái),如果沒(méi)有打開(kāi)控制臺(tái)的話,使用console.table輸出我們創(chuàng)建的a標(biāo)簽是很快的,有多快呢,就是js執(zhí)行一條語(yǔ)句的速度,所以打印a1和a2的時(shí)間間隔非常短,幾乎為0,因?yàn)樗麄兛斓讲畈欢嗍峭瑫r(shí)執(zhí)行的,給大家打印看一下:

          效果

          我們先不打開(kāi)控制臺(tái),等輸出完畢再打開(kāi),很清楚的發(fā)現(xiàn),我們沒(méi)打開(kāi)控制臺(tái)的時(shí)候,輸出的a就是它標(biāo)簽,而且時(shí)間間隔是0毫秒。

          現(xiàn)在我們打開(kāi)控制臺(tái)的時(shí)候刷新一下頁(yè)面,看看控制臺(tái)的輸出:

          效果

          這次就變成了以table的形式輸出a元素,而且它的耗時(shí)明顯增多,不再是0毫秒,而是耗費(fèi)了10毫秒,雖然打開(kāi)控制臺(tái)的時(shí)候多次刷新頁(yè)面,每次輸出的毫秒數(shù)是不同的,但是跟關(guān)閉控制臺(tái)的時(shí)候輸出的耗時(shí)差距非常明顯,因此我們就可以在這個(gè)上面做文章。

          我在上面的代碼中假定了,只要是大于1毫秒的耗時(shí),那就表示用戶打開(kāi)了控制臺(tái),然后我們就把頁(yè)面給跳轉(zhuǎn)到空白頁(yè),當(dāng)然了你也可以做一些任何你想做的操作,比如彈出一個(gè)提示,或者把body內(nèi)容置空等等等等。

          回到我們上面的代碼,看一下它實(shí)際發(fā)生的作用和帶給我們的效果:

          效果

          哈哈,古德古德,平時(shí)瀏覽一切正常,只要?jiǎng)傄淮蜷_(kāi)控制臺(tái),瞬間頁(yè)面就被跳轉(zhuǎn)走了,什么都干不了。這樣我們就通過(guò)這種方式,達(dá)到了限制打開(kāi)控制臺(tái)的目的,也就是在當(dāng)前頁(yè)沒(méi)法調(diào)試,一打開(kāi)就跳轉(zhuǎn)。

          這種辦法由于是繞路實(shí)現(xiàn)的,那么你可能會(huì)有疑問(wèn),它穩(wěn)定嗎?會(huì)不會(huì)誤判,我可以對(duì)它絕對(duì)放心嗎?

          理論上來(lái)說(shuō),通過(guò)輸出的執(zhí)行時(shí)間是不太能精確掌握的,但是我們可以再做一些其他的措施來(lái)逼近真相:

          ;(()=> {
            setInterval(function() {
              let foo=document.createElement('a')
              let a1=+new Date()
              console.table(foo)
              let a2=+new Date()
              if(a2 - a1 > 1) {
                let time=0
                for(let i=0; i < 10; i++) {
                  let a1=+new Date()
                  console.table(foo)
                  let a2=+new Date()
                  time +=a2 - a1
                }
                if(time > 20) {
                  location.href='about:blank'
                }
              }
              console.clear()
            }, 500)
          })()

          我又改造了一下判斷的邏輯,當(dāng)發(fā)現(xiàn)輸出耗時(shí)為2毫秒甚至更多的時(shí)候,我立馬再進(jìn)行一次真?zhèn)闻袛啵簿褪钦f(shuō),萬(wàn)一由于其他的影響,導(dǎo)致我第7行的代碼誤判了,那么我再同步執(zhí)行一個(gè)循環(huán),連續(xù)輸出10次,把他們的耗時(shí)總和計(jì)算出來(lái),然后判斷是否大于20毫秒,如果還是耗時(shí)過(guò)高的話,那么就可以非常肯定的知道用戶是打開(kāi)了控制臺(tái),這個(gè)時(shí)候就可以放心的做一些處理了。

          最后

          其實(shí)限制用戶行為的方法有很多很多,上面列出了一些主要的,多種方法還是要結(jié)合著使用。你也可以自由發(fā)揮,多使用一些其他的手段,也會(huì)增加用戶復(fù)制或者調(diào)試的難度,比如防止用戶重寫console的方法,或者清除所有定時(shí)器等。

          甚至也可以將你的內(nèi)容繪制到canvas上面來(lái)防止復(fù)制,多加一些js的處理工作,防止禁用js的時(shí)候,我們的代碼不生效,只有在js可用的時(shí)候再去渲染內(nèi)容等。也可以在綜合考慮的情況下加上代碼混淆、代碼加密等措施。

          話說(shuō)回來(lái),大家都是同路人,何必相互為難,哈哈哈,不過(guò)提這個(gè)需求的人也著實(shí)會(huì)為難我們,既然提了那就盡力去做,能做到什么程度,只能說(shuō)是盡量做到極致。

          希望上面的內(nèi)容能夠幫助到你,也希望能夠?qū)δ阌兴鶈l(fā)。

          謝謝

          、CSS方法

          .disabled { pointer-events: none; }

          二、jQuery方法

          方法一

          $(this).click(function (event) {
              event.preventDefault();
          }

          方法二

          $('a').live('click', function(event) {
              alert("抱歉,已停用!");
              event.preventDefault();
          });

          注:此方法中的live亦可以為on, bind等方法

          方法三

          $('.disableCss').removeAttr('onclick'); //去掉標(biāo)簽中的onclick事件

          通過(guò)removeAttr方法來(lái)控制html標(biāo)簽的屬性已達(dá)到啟用或禁用事件。另, 使用這種方式也可以控制其他事件或其他效果。

          方法四

          $('#button').attr('disabled',"true");//添加disabled屬性
          $('#button').removeAttr("disabled"); //移除disabled屬性

          注:和方法三是一樣的, 不過(guò)disabled屬性一般用在類型為button或submit的input上


          主站蜘蛛池模板: 日韩人妻精品无码一区二区三区 | 国精产品一区一区三区有限公司| 亚洲一区动漫卡通在线播放| 日韩视频一区二区在线观看 | 免费无码一区二区| 亚洲爆乳精品无码一区二区三区| 春暖花开亚洲性无区一区二区 | 亚洲综合无码AV一区二区| 国产传媒一区二区三区呀| 无码精品一区二区三区| 日韩在线一区二区| 亚洲av乱码一区二区三区| 视频在线一区二区| 国产精品久久久久久一区二区三区| 91福利一区二区| 精品无码人妻一区二区免费蜜桃 | 波多野结衣一区二区三区aV高清| 日韩精品一区二区三区影院| 国产产一区二区三区久久毛片国语| 麻豆果冻传媒2021精品传媒一区下载| 色偷偷一区二区无码视频| 国产精品视频第一区二区三区 | 奇米精品视频一区二区三区| 国产成人精品无码一区二区 | 日韩精品一区二区三区不卡| 精品一区二区三区免费观看 | 精品无码一区在线观看| 精品亚洲AV无码一区二区 | 亚洲av无码一区二区乱子伦as | 亚洲av成人一区二区三区在线观看 | 国产精品免费视频一区| 日本精品视频一区二区三区| 国产一区在线观看免费| 国产福利一区二区在线视频| 国产精品男男视频一区二区三区| 精品国产一区二区三区久久| 亚洲一区二区三区在线观看蜜桃| 亚洲精品精华液一区二区| 精品国产一区二区三区久久影院| 波多野结衣一区二区免费视频| 国产成人高清精品一区二区三区|