You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Chrome扩展中记录网站自动建立的WebSocket服务端请求?

如何在Chrome扩展中劫持并记录网站原有WebSocket的消息

为什么window.WebSocket会返回undefined?

Chrome扩展的内容脚本默认运行在隔离世界中,这个环境和页面自身的全局环境完全分开——你在内容脚本里访问的window并不是页面实际的window对象,所以拿不到页面的WebSocket构造函数,自然返回undefined。解决核心是把劫持代码注入到页面的主世界(页面自身的全局上下文)里。

实现WebSocket消息记录的具体方案

1. 编写劫持脚本

下面的代码会重写页面的WebSocket构造函数,在不破坏原有功能的前提下,记录所有新建立的WebSocket连接和收到的消息:

(function() {
  // 保存原始的WebSocket构造函数
  const OriginalWebSocket = window.WebSocket;

  // 重写WebSocket构造函数
  window.WebSocket = function(...args) {
    // 创建原始的WebSocket实例
    const wsInstance = new OriginalWebSocket(...args);
    
    // 记录连接建立的信息(比如连接地址)
    console.log('[WS Logger] 新连接建立:', args[0]);

    // 处理onmessage事件
    const originalOnMessage = wsInstance.onmessage;
    wsInstance.onmessage = function(event) {
      try {
        // 解析并记录消息内容
        const messageData = JSON.parse(event.data);
        console.log('[WS Logger] 收到消息:', messageData);
      } catch (e) {
        // 如果消息不是JSON格式,直接打印原始数据
        console.log('[WS Logger] 收到非JSON消息:', event.data);
      }
      // 调用原本的onmessage逻辑,保证页面功能正常
      if (originalOnMessage) originalOnMessage.call(this, event);
    };

    // 处理通过addEventListener绑定的message事件
    const originalAddEventListener = wsInstance.addEventListener;
    wsInstance.addEventListener = function(type, listener, options) {
      if (type === 'message') {
        const wrappedListener = function(event) {
          try {
            const messageData = JSON.parse(event.data);
            console.log('[WS Logger] 收到消息(listener):', messageData);
          } catch (e) {
            console.log('[WS Logger] 收到非JSON消息(listener):', event.data);
          }
          // 调用原本的监听函数
          listener.call(this, event);
        };
        return originalAddEventListener.call(this, type, wrappedListener, options);
      }
      return originalAddEventListener.call(this, type, listener, options);
    };

    return wsInstance;
  };

  // 复制原始WebSocket的静态属性(比如WebSocket.CLOSED等常量)
  Object.assign(window.WebSocket, OriginalWebSocket);
})();

2. 在扩展中注入脚本

有两种方式可以把上述代码注入到页面主世界:

  • 方式一:Manifest配置(Chrome 112+)
    在manifest.json中添加内容脚本配置,指定world: "MAIN"直接注入到主世界:
    {
      "manifest_version": 3,
      "name": "WebSocket Logger",
      "version": "1.0",
      "content_scripts": [
        {
          "matches": ["https://your-target-site.com/*"], // 替换成你的目标网站
          "js": ["ws-logger.js"], // 把上面的代码保存为ws-logger.js
          "world": "MAIN",
          "run_at": "document_start" // 确保在页面加载前注入
        }
      ]
    }
    
  • 方式二:动态注入(兼容旧版本Chrome)
    如果需要兼容Chrome 112以下版本,可以在内容脚本中动态创建<script>标签注入代码:
    // content-script.js
    const injectScript = document.createElement('script');
    injectScript.textContent = `
      // 把上面的劫持代码粘贴到这里
      (function() {
        const OriginalWebSocket = window.WebSocket;
        // ... 完整劫持逻辑
      })();
    `;
    // 注入到页面并立即移除标签
    document.documentElement.appendChild(injectScript);
    injectScript.remove();
    
    同时在manifest.json中配置这个内容脚本在document_start时运行:
    {
      "content_scripts": [
        {
          "matches": ["https://your-target-site.com/*"],
          "js": ["content-script.js"],
          "run_at": "document_start"
        }
      ]
    }
    

能否直接在控制台测试?

可以,但有个关键前提:必须在页面加载前注入代码,否则页面已经建立的WebSocket连接不会被劫持。具体操作:

  1. 打开目标网站的控制台(F12)
  2. 在控制台中粘贴上述劫持代码并执行
  3. 刷新页面——此时页面新建立的WebSocket连接就会被记录
    如果页面已经加载完成再粘贴代码,只能记录之后新建的连接,之前已经存在的连接无法被捕获。

内容的提问来源于stack exchange,提问作者Brage

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 22:13:17