k8s系列 - 谷歌油猴插件开发http请求拦截

1,257 阅读1分钟

需求

1、前端请求为了安全考虑都是经过加密处理,不论接口地址还是请求参数,或者返回数据

2、安全性是解决了,但是开发测试找问题时就很麻烦,看不到数据

3、开发油猴插件,拦截请求,解密数据就能达到目的

方法

1、重写 XMLHttpRequest.prototype.open 代理 get 请求

2、重写 XMLHttpRequest.prototype.send 代理 post 请求

脚本

// ==UserScript==
// @name         解密助手
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        *
// @icon         https://www.google.com/s2/favicons?sz=64&domain=baidu.com
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_setClipboard
// @grant        GM_getClipboard
// @grant        GM_notification
// @grant        GM_xmlhttpRequest
// @grant        GM_download
// ==/UserScript==

(function () {
  "use strict";

  // 工具方法
  const Utils = {
    getQueryVariable(url, variable) {
      var query = url.split("?")[1];
      if (!query) return "";
      var vars = query.split("&");
      for (var i = 0; i < vars.length; i++) {
        var pair = vars[i].split("=");
        if (pair[0] == variable) {
          return pair[1];
        }
      }
      return "";
    },
    log(name, value) {
      console.info(`%c ${name}`, "color: #23f10a", value);
    },
    notification(text, timeout = 3000) {
      GM_notification({
        text,
        title: "通知",
        timeout,
      });
    },
    set(name, value) {
      GM_setValue(
        name,
        typeof value == "string" ? value : JSON.stringify(value)
      );
    },
    get(name, value) {
      return GM_getValue(name, value);
    },
    async wait(time = 1000) {
      await new Promise((resolve) => setTimeout(resolve, time));
    },
    debounce(fn, timestamp = 1000) {
      let go = true;
      return () => {
        if (!go) return;
        go = false;
        fn();
        go = true;
      };
    },
  };

  // 解密

  const ConsoleEncrypt = {
    decryptResponseData(encryptString) {
      // 自定解密过程 密文 -> 明文
      return encryptString;
    },
  };

  // http代理
  // 重写open https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/open
  // 重写send https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/send
  XMLHttpRequest.prototype.myOpen2 = XMLHttpRequest.prototype.open;
  XMLHttpRequest.prototype.mySend2 = XMLHttpRequest.prototype.send;
  const HttpProxy = {
    beforeXMLHttpRequestOpen() {
      XMLHttpRequest.prototype.open = function (
        method,
        url,
        async,
        user,
        password
      ) {
        try {
          if (method.toUpperCase() == "GET") {
            const encryptString = Utils.getQueryVariable(url, "encryptString");
            if (encryptString) {
              const decryptObject = ConsoleEncrypt.decryptResponseData(
                decodeURIComponent(encryptString)
              );
              // 打印解密数据
              console.log("解密请求GET", url, decryptObject);
            }
          }
        } catch (e) {}
        // 触发原请求
        this.myOpen2(method, url, async, user, password);
      };
    },
    beforeXMLHttpRequestSend() {
      XMLHttpRequest.prototype.send = function (body) {
        try {
          if (body) {
            const bodyObject = JSON.parse(body);
            const decryptObject = ConsoleEncrypt.decryptResponseData(
              decodeURIComponent(bodyObject.encryptString)
            );
            // 打印解密数据
            console.log(
              "解密请求POST",
              this.responseURL?.replace(/^http(s):\/\/[a-zA-Z0-9\.-]+/, ""),
              decryptObject
            );
          }
        } catch (e) {}
        this.mySend2(body);
      };
    },
  };

  // 程序启动
  HttpProxy.beforeXMLHttpRequestOpen();
  HttpProxy.beforeXMLHttpRequestSend();
})();