Postman发送WebSocket消息没反应,主因是协议模式选错(如Socket.IO/SignalR误用Raw)、消息格式不合规(如缺\u001e、引号错误)、鉴权未放行或JWT拦截器阻断握手。

Postman 发送 WebSocket 消息不是“发完就完”,必须先完成协议握手、匹配服务端期望的消息结构,否则连接看似成功,实际收不到响应或立刻断开。
WebSocket 连接后为什么 send 了没反应?
常见现象是点击 Connect 显示 Connected,但输入任意 JSON 或文本点 Send 后,服务端无日志、时间线里没回包、几秒后自动断开。
根本原因通常是:服务端不是裸 WebSocket,而是基于 Socket.IO 或 SignalR 等封装协议。它们要求首条消息必须是特定格式的握手帧,而不是业务数据。
- Socket.IO 必须先发
40(连接请求)或42["event", ...],不能直接发{"msg":"hello"} - SignalR 必须先发
{"protocol":"json","version":1},且每条消息末尾要加\u001e(ASCII 30,unit separator),Postman 编辑器默认不显示这个字符 - Spring Boot 原生
@ServerEndpoint一般接受裸文本/JSON,但若配了 JWT 拦截器或 Spring Security,/ws/{id}路径未放行,也会在握手阶段返回 403 或静默断连
如何确认该用 raw 还是 Socket.IO 模式?
看 URL 和服务端文档。Postman 的下拉菜单里选错模式,连接会失败或行为异常。
Postman 12.27.7 Windows x64 官方安装包,适用于 API 设计、调试、测试与协作。该系列包含 Enterprise 云端性能测试静态 IP 出口能力,以及接口规范标签管理改进,适合受限网络测试与规范资源组织场景。
- URL 是
ws://localhost:8080/ws或wss://api.example.com/chat→ 选Raw(裸 WebSocket) - URL 含
/socket.io/且带参数如?EIO=4&transport=websocket→ 必须选Socket.IO,否则无法解析 ping/pong 和事件包 - URL 是
wss://app.com/chathub且后端是 .NET SignalR → 仍选Raw,但后续所有消息都需按 SignalR 协议编码,不能当普通 JSON 用
如果不确定,抓浏览器开发者工具 Network → WS 标签页,看真实请求的 Frames 内容:出现 40、42 开头就是 Socket.IO;出现 {"type":6}(heartbeat)或 {"type":1,"target":"xxx"} 就是 SignalR。
发送消息时容易漏掉的关键细节
即使协议选对、URL 正确,消息体格式错一个字符,服务端就拒收。
- SignalR 消息必须以
\u001e结尾:{"arguments":["user","hi"],"target":"send","type":1}\u001e,Postman 编辑器里看不到这个字符,建议复制粘贴完整字符串,别手敲 - Socket.IO 的
42表示“事件消息”,40表示“连接”,2表示“ping”,不能写成42["msg"]少引号,也不能写成"42["msg"]"多引号 - 二进制消息(如图片 base64)必须切到
Binary模式,并选Base64,否则会被当文本转义 - 带鉴权的
wss连接,Postman 不支持在 WebSocket 请求里设Authorizationheader —— 必须把 token 放 URL 里,例如wss://api.com/ws?token=abc123
连接成功但收不到服务端推送?检查线程与拦截器
尤其在 Spring Boot + Spring Security + JWT 场景下,这是高频陷阱。
- Spring Security 默认拦截所有路径,必须显式放行 WebSocket 端点:
.requestMatchers("/ws/**").permitAll() - JWT Filter 里也要提前判断:
if (request.getRequestURI().startsWith("/ws")) return true;,否则@OnOpen方法执行时,SecurityContext 已被清空 - 原生 WebSocket 的
@OnOpen回调由 Tomcat 线程池触发,和 HTTP 请求的线程不是同一个,SecurityContextHolder.getContext().getAuthentication()在这里永远为null
真正能拿到用户身份的地方,是在握手阶段(HTTP upgrade 请求)里解析 Header 或 URL 参数,然后通过 session.getUserProperties().put("userId", userId) 存进去,@OnMessage 里再取。

















