使用http-proxy-middleware代理WebSocket前如何添加校验逻辑?
WebSocket代理校验问题解决方案
问题根源说明
你之前配置Apache用ws://协议代理时,请求直接走WebSocket升级链路,不会经过Express普通HTTP中间件处理流程,所以onProxyReq、onProxyRes这类普通HTTP代理事件不会触发。你之前尝试把Apache配置改成http://协议时,Apache不会自动转发WebSocket升级所需的头信息,所以到后端服务会返回Upgrade Required错误,这个配置是不可行的,需要改回ws://开头的配置。
另外你用responseInterceptor的思路本身不符合WebSocket场景:该钩子仅用于处理普通HTTP请求的响应,WebSocket在升级握手完成后就进入全双工通信模式,不会触发普通HTTP响应的相关钩子。
正确实现方案
你想到的在upgrade事件环节做校验是完全可行的,这也是该场景下最合理的校验时机,具体实现如下:
1. 恢复Apache正确配置
<Location /testws> ProxyPass ws://127.0.0.1:6006/testws ProxyPassReverse ws://127.0.0.1:6006/testws </Location>
2. 修改Node代理代码
移除不需要的普通HTTP响应处理配置,在upgrade事件中加入校验逻辑,校验失败时直接返回403状态码:
const express = require('express'); const { createProxyMiddleware } = require('http-proxy-middleware'); const app = express(); // 代理配置移除不需要的responseInterceptor、selfHandleResponse配置 const wsProxyOptions = { target: 'http://example.org', changeOrigin: true, ws: true, router: { '/testws': 'ws://127.0.0.1:6082', }, logLevel: 'debug' }; const wsProxy = createProxyMiddleware(wsProxyOptions); app.use(wsProxy); const server = app.listen(6006); // 自定义upgrade事件处理,加入校验逻辑 server.on('upgrade', (req, socket, head) => { // 这里写你的校验逻辑,比如校验请求头里的token、cookie、query参数等 const valid = checkAuth(req); // 自定义的校验函数 if (valid) { // 校验通过,走代理升级逻辑 wsProxy.upgrade(req, socket, head); } else { // 校验失败,返回403状态码 socket.write('HTTP/1.1 403 Forbidden\r\n\r\n'); socket.destroy(); return; } }); // 示例校验函数,可根据业务自定义,比如拿req.headers.authorization验签、拿cookie验session等 function checkAuth(req) { const token = req.headers['authorization'] || new URL(req.url, `http://${req.headers.host}`).searchParams.get('token'); return token === 'your_valid_token'; }
注意事项
- 校验逻辑可以直接读取
req对象的所有请求信息,包括请求头、URL参数、Cookie等,完全满足常规的身份校验需求 - 校验失败返回403时,必须手动关闭socket连接,避免连接悬空占用资源
- 该方案不需要手动处理WebSocket升级逻辑,http-proxy-middleware的
upgrade方法会自动完成和后端WebSocket服务的握手流程
内容的提问来源于stack exchange,提问作者user3345
相关产品推荐
相关产品推荐

