監聽用戶打開控制檯修改dom屬性內容

今天程序猿節,祝大家永無bug

昨天接了個功能,已知有一個input類型爲password,在修改內容的時候也是密文展示,但是用戶還是覺得不安全,因爲可以在f12下找到dom並直接修改inputtype從而直接使其明文展示

wtf? 真有這麼不當人的用戶咩??

後來想了個辦法,頁面上展示的是基於此變量的計算屬性比如computedStr,然後頁面上的展示本質上就是這個計算屬性的值:

          <el-input
            v-model="passwordComputed"
            type="password"
            id="pswId"
            style="border:1px solid red"
            :clearable="dialogBtn !== 'preview'"
            :readonly="dialogBtn == 'preview'"
          />

隨後在計算屬性裏寫上它的邏輯,由於它是v-model因而要使用comp的get&set

    // computed
    passwordComputed: {
      get() {
        const basePasswordLen = baseMsg; //這個是該計算屬性依賴的源數據 已脫敏
        console.log("basePasswordLen :>> ", basePasswordLen);
        let encryptedStr = ``;
        for (let index = 0; index < basePasswordLen.length; index++) {
          encryptedStr += `•`;
        }
        return encryptedStr; // 當僅展示時,返回一堆`*`號,這樣用戶修改type也不怕啦,因爲它本質上就是`*`
      },
      set(newVal) {
        // 雙向綁定的是計算屬性,
        // const basePasswordLen = baseMsg; //這個是該計算屬性依賴的源數據 已脫敏
        // const prePsdLen = basePasswordLen.length; // 上一次的數據
        // const psdEle = document.getElementById("pswId");
        // console.log("psdEle :>> ", psdEle);
        // if (!newVal) {  //如果是新值是空字符,則將原值賦空
        //   baseMsg = ``;
        //   return;
        // }
        // // 如果小於原值,說明是刪除動作
        // if (newVal.length < prePsdLen) {
               // 刪減動作
        // } else {
        //   const { resultVal, startIndex, filterText } = this.filterNewValue(
        //     newVal,
        //     basePasswordLen
        //   );
        //   baseMsg = resultVal;  //將計算後的數據反賦給真正的變量
        //   這時候光標會異常,因爲上一行是整體賦值操作而不是新增操作,因而必須要重新設置下光標
        //   this.$nextTick(() => {
        //     psdEle.focus(); // 重新獲取焦點
        //     console.log(" psdEle.selectionStart :>> ", psdEle.selectionStart);
                // selectionStart與selectionEnd是同一值時,顯示光標所在所有,不同值時,中間的差值就是選中態 
        //     psdEle.selectionStart = psdEle.selectionEnd =
        //       startIndex + filterText.length + 1; // 重新設置光標 這一點非常重要,因爲此input不允許明文查看,因而光標的位置就很關鍵。  模仿光標正常input下輸入態  這裏其實還要加`1`,舉個例子,假設輸入了四個字符,那麼光標其實應該在第四位索引上
        //   });
        // }
      }
    }

在新增動作裏,添加對數據的計算

// methods
   // 數據清洗-》獲取輸入的數據和數據的第一個的下標
    filterNewValue(nv, ov) {
      let filterText = "";
      let startIndex = null;
      for (let index = 0; index < nv.length; index++) {
        if (nv[index] !== `•`) {
          filterText += nv[index];
          if (startIndex === null) {
            startIndex = index;
          }
        }
      }
      const resultVal = this.insertStringAt(ov, filterText, startIndex);
      return {
        resultVal,
        startIndex,
        filterText
      };
    },
    // 此處計算用戶本次輸入後的明文數據(包含所有)
    insertStringAt(originalString, stringToInsert, insertionIndex) {
      if (insertionIndex < 0) {
        insertionIndex = 0;
      }
      if (insertionIndex > originalString.length) {
        insertionIndex = originalString.length;
      }
      const part1 = originalString.slice(0, insertionIndex);
      const part2 = originalString.slice(insertionIndex);
      return part1 + stringToInsert + part2;
    },

終於寫完了,擦擦腦門汗,發現有一個大問題,我可以監聽用戶修改條目時的新增,無論他在開頭結尾或中間,但是我卻無法監聽它的刪減,準確的說,無法監聽它刪減時對應的數據和下標。
因爲:passwordComputed的值是一個基於base數據的***,所以在刪減這個數據的時候拿到的新值也只是**

眼前真的一黑...

狠狠抽了一口空氣,突然想明白了一件事:當前需求是希望用戶不要在f12時修改dom,那麼我們就可以以此爲切入點:
網上的案例是當用戶打開f12時直接debugger:

mounted(){
            // 監聽用戶f12時,直接debugger;可以但不該
            ((function () {
          var callbacks = [],
              timeLimit = 50,
              open = false;
          var str = /x/
          str.toString = function () {
              window.clearInterval = function () {
                  return '不能使用清除定時器了'
              }
          }
          setInterval(loop, 1);
          return {
              addListener: function (fn) {
                  callbacks.push(fn);
              },
              cancleListenr: function (fn) {
                  callbacks = callbacks.filter(function (v) {
                      return v !== fn;
                  });
              },
          };
          function loop() {
              var startTime = new Date();
              debugger;
              if (new Date() - startTime > timeLimit) {
                  if (!open) {
                      callbacks.forEach(function (fn) {
                          fn.call(null);
                      });
                  }
                  open = true;
                  window.stop();
                  console.log(str)
                  window.location.reload();
              } else {
                  open = false;
              }
          }
      })()).addListener(function () {
          window.location.reload();
      });

}

這段代碼寫下來,當用戶一打開開發者工具時就直接進入調試態,這太粗暴,太不優雅,本着對用戶負責的態度,於是放棄了這個做法(畢竟我們不能不當人不是)
然後又在想,可不可以直接監聽用戶在按f12對dom修改的動作,於是就找到了mutationObserve這個api,廢話不說,上代碼

貼貼:

<script>
let observer  // 沒用必要將其變成響應式,浪費性能
mounted(){
  this.$nextTick(() => {
     // 選擇需要觀察變動的節點
      const targetNode = document.getElementById("pswId");
      // 觀察器的配置(需要觀察什麼變動)
      // attributes: 觀察受監視元素的屬性值變更
      // childList: 監視目標節點(如果 subtree 爲 true,則包含子孫節點)添加或刪除新的子節點
      // subtree: 其他值也會作用於此子樹下的所有節點,而不僅僅只作用於目標節點
      const config = { attributes: true, childList: false, subtree: false }; // childList && subtree須設置爲false以節省性能 
      // 當觀察到變動時執行的回調函數
      const callback = function(mutationsList, observer) {
        for (let mutation of mutationsList) {
          if (mutation.type === "attributes") {
            targetNode.type = "password";
            // 停止監聽,一定要有這一步,否則頁面將直接卡死!
            observer.disconnect(); //關鍵點1
            // 隨即重新監聽
            observer.observe(targetNode, config);  // 關鍵點2
          }
        }
      };
      // 創建一個觀察器實例並傳入回調函數
      observer = new MutationObserver(callback);
      // 以上述配置開始觀察目標節點
      observer.observe(targetNode, config);
  }
},
  beforeDestroy() {
    // 停止觀察
    observer.disconnect();
  },
<script>

tips1: 關鍵點1必須要加,否則將會死循環至瀏覽器崩潰
tips1: 關鍵點2必須要加,否則將不再監聽

其實可以封裝成一個指令以便在整個項目裏使用,不過沒時間(其實就是懶)

以上。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章