拦截WebSocket消息

Ale*_*lex 9 javascript websocket node.js electron

对于 ajax 请求,可以使用以下代码完成:

let oldXHROpen = window.XMLHttpRequest.prototype.open;
window.lastXhr = '';
window.XMLHttpRequest.prototype.open = function(method, url, async, user, password) {
  this.addEventListener('load', function() {
    window.lastXhr = this.responseText;
  });
  return oldXHROpen.apply(this, arguments);
};
Run Code Online (Sandbox Code Playgroud)

lastXhr变量将保存最后的响应。

但对于 websocket 如何才能实现这一点呢?

The*_*uad 25

你需要尽快制作这个包装纸

@brunoff你是对的,因为你总是可以通过傀儡窗口逻辑在服务器之前使用你的函数,或者data你可以从自身劫持MessageEvent

function listen(fn){
  fn = fn || console.log;

  let property = Object.getOwnPropertyDescriptor(MessageEvent.prototype, "data");
  
  const data = property.get;

  // wrapper that replaces getter
  function lookAtMessage() {

    let socket = this.currentTarget instanceof WebSocket;

    if (!socket) {
      return data.call(this);
    }

    let msg = data.call(this);

    Object.defineProperty(this, "data", { value: msg } ); //anti-loop
    fn({ data: msg, socket:this.currentTarget, event:this });
    return msg;
  }
  
  property.get = lookAtMessage;
  
  Object.defineProperty(MessageEvent.prototype, "data", property);
}

listen( ({data}) => console.log(data))
Run Code Online (Sandbox Code Playgroud)

您可以尝试输入代码并在此页面的控制台中运行它,然后运行他们的 WebSocket 示例。

  • 唯一有效的解决方案... (2认同)

Ion*_*zău 10

要拦截消息,您必须监视onmessage = fnaddEventListener("message", fn)呼叫。

\n

为了能够修改我们必须首先onmessage覆盖全局。WebSocket下面是拦截传入消息,但以类似的方式,您可以监视send拦截传出消息(客户端发送到服务器的消息)的方法。

\n

我使用 Firebase 在页面上对此进行了测试,它运行良好,但您必须在其他脚本之前对其进行初始化,以确保 websocket 库(可以是 socket.io、ws 等)正在使用重写的构造函数WebSocket

\n

监视传入消息修改data

\n

最终,您可以在调用真实消息侦听器 \xe2\x80\x93 之前覆盖data,如果您无法控制页面功能并希望在消息侦听器中注入您自己的数据,这将变得很方便。

\n
const OriginalWebsocket = window.WebSocket\nconst ProxiedWebSocket = function() {\n  console.log("Intercepting web socket creation")\n\n  const ws = new OriginalWebsocket(...arguments)\n\n  const originalAddEventListener = ws.addEventListener\n  const proxiedAddEventListener = function() {\n    if (arguments[0] === "message") {\n      const cb = arguments[1]\n      arguments[1] = function() {\n        // Here you can get the actual data from the incoming messages\n        // Here you can even change the data before calling the real message listener\n        Object.defineProperty(e, "data", { value: 'your injected data' })\n        console.log("intercepted", arguments[0].data)\n        return cb.apply(this, arguments)\n      }\n    }\n    return originalAddEventListener.apply(this, arguments)\n  }\n  ws.addEventListener = proxiedAddEventListener\n\n  Object.defineProperty(ws, "onmessage", {\n    set(func) {\n      return proxiedAddEventListener.apply(this, [\n        "message",\n        func,\n        false\n      ]);\n    }\n  });\n  return ws;\n};\n\nwindow.WebSocket = ProxiedWebSocket;\n
Run Code Online (Sandbox Code Playgroud)\n

如果不需要修改数据,可以按照答案的第二部分进行操作。

\n

监视传入消息而不修改数据

\n

如果您只想监听消息而不覆盖 data,事情会更简单:

\n
const OriginalWebsocket = window.WebSocket\nconst ProxiedWebSocket = function() {\n  const ws = new OriginalWebsocket(...arguments)\n  ws.addEventListener("message", function (e) {\n    // Only intercept\n    console.log(e.data)\n  })\n  return ws;\n};\nwindow.WebSocket = ProxiedWebSocket;\n
Run Code Online (Sandbox Code Playgroud)\n

监视传出消息

\n

以非常类似的方式,您可以代理send用于将数据发送到服务器的方法。

\n
const OriginalWebsocket = window.WebSocket\nconst ProxiedWebSocket = function() {\n  const ws = new OriginalWebsocket(...arguments)\n  const originalSend = ws.send\n  const proxiedSend = function() {\n    console.log("Intercepted outgoing ws message", arguments)\n    // Eventually change the sent data\n    // arguments[0] = ...\n    // arguments[1] = ...\n    return originalSend.apply(this, arguments)\n  }\n  ws.send = proxiedSend\n  return ws;\n};\nwindow.WebSocket = ProxiedWebSocket;\n
Run Code Online (Sandbox Code Playgroud)\n

如果有任何不清楚的地方,请随时提出任何问题。

\n