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

如何解码Blazor的SignalR请求响应,实现Python机器人服务请求

用Python对接Blazor的SignalR二进制请求方案

核心原理

Blazor Server依赖SignalR实现双向通信,你抓包看到的二进制请求是MessagePack序列化格式(SignalR默认的高效二进制序列化方式),只要解码这种格式并遵循SignalR的通信流程,就能用Python模拟请求。


步骤1:完成SignalR协商流程

SignalR通信的第一步是协商,用来获取连接凭证和支持的传输方式,对应你抓包的第一个JSON响应:

{"negotiateVersion":1,"connectionId":"mPtGjJ-copmHDi80CWjLew","connectionToken":"2tEI4GP4tq3gVE_dBzjGoQ","availableTransports":[{"transport":"ServerSentEvents","transferFormats":["Text"]},{"transport":"LongPolling","transferFormats":["Text","Binary"]}]}

用Python发起协商请求:

import requests

# 替换为实际的Blazor服务器协商端点(通常是/_blazor/negotiate)
negotiate_url = "https://your-blazor-server/_blazor/negotiate"
resp = requests.post(negotiate_url)
negotiate_info = resp.json()

# 提取关键参数
connection_id = negotiate_info["connectionId"]
connection_token = negotiate_info["connectionToken"]

步骤2:解码SignalR二进制请求

你抓包的第二个二进制内容是MessagePack格式的Invoke调用,包含要执行的方法(DispatchEventAsync)和点击事件参数。用Python的msgpack库解码:

import msgpack

# 将抓包的二进制数据转为bytes类型(示例用你提供的内容转码)
binary_req = b'\xc2\x19\xc0\xb2DispatchEventAsync\xda[{"eventHandlerId":654,"eventName":"click","eventFieldInfo":null},    {"detail":1,"screenX":713,"screenY":484,"clientX":675,"clientY":308,"offsetX":68,"offsetY":35,"pageX"    :675,"pageY":508,"button":0,"buttons":0,"ctrlKey":false,"shiftKey":false,"altKey":false,"metaKey":false,"type":"click"}]'

# 解码MessagePack数据
decoded_data = msgpack.unpackb(binary_req, raw=False)
method_name = decoded_data[0]  # 得到 "DispatchEventAsync"
event_params = decoded_data[1] # 得到点击事件的参数数组

print(f"调用方法:{method_name}")
print(f"事件参数:{event_params}")

步骤3:用Python模拟发送SignalR请求

选择抓包中支持Binary传输的LongPolling方式,构造MessagePack格式的请求发送:

# 发送消息的端点(替换为实际路径)
send_url = f"https://your-blazor-server/_blazor/send?connectionId={connection_id}&connectionToken={connection_token}"

# 构造要发送的MessagePack数据(格式为[方法名, 参数数组])
send_payload = msgpack.packb([
    "DispatchEventAsync",
    [
        {"eventHandlerId": 654, "eventName": "click", "eventFieldInfo": None},
        {"detail": 1, "screenX": 713, "screenY": 484, "clientX": 675, "clientY": 308, "offsetX": 68, "offsetY": 35, "pageX": 675, "pageY": 508, "button": 0, "buttons": 0, "ctrlKey": False, "shiftKey": False, "altKey": False, "metaKey": False, "type": "click"}
    ]
])

# 发送请求,设置正确的Content-Type
headers = {"Content-Type": "application/x-msgpack"}
resp = requests.post(send_url, data=send_payload, headers=headers)
print(f"请求状态码:{resp.status_code}")

关键注意事项

  • 端点路径:Blazor Server的SignalR端点通常是/_blazor/negotiate、/_blazor/connect、/_blazor/send,要以实际抓包的路径为准。
  • 请求头模拟:服务器可能验证User-Agent、Referer等头信息,直接复制浏览器抓包的请求头加到Python请求中,避免被拦截。
  • eventHandlerId:这个ID是服务器为页面元素生成的临时标识,每次连接可能变化,需要在协商后通过抓包页面初始化的SignalR消息获取,或者模拟页面加载流程拿到。
  • 连接生命周期:SignalR连接需要维护心跳,长时间不交互可能被断开,必要时要处理重连逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 21:35:32