React应用通过WSS连接MQTT Broker的问题求助
生产环境React应用通过WSS连接MQTT Broker失败排查与解决
问题概述
我在React应用中使用MQTT.js连接MQTT Broker时遇到WSS协议相关错误:
- 本地设备可正常连接
mqtts://my.domain.io:3941 - Python、MQTT Box、MQTT Explorer均可连接
wss://my.domain.io:3942并完成发布/订阅操作 - 生产环境React应用无法连接
wss://my.domain.io:3942;尝试连接39393端口时被浏览器阻止,且两种连接请求均未出现在Mosquitto日志中
配置与代码信息
Mosquitto配置文件(mosquitto.conf)
# mosquitto.conf pid_file /run/mosquitto/mosquitto.pid persistence true persistence_location /var/lib/mosquitto/ log_dest file /var/log/mosquitto/mosquitto.log include_dir /etc/mosquitto/conf.d allow_anonymous false password_file /etc/mosquitto/passwd listener 3940 protocol mqtt listener 39393 protocol websockets listener 3941 protocol mqtt cafile /etc/mosquitto/certs/ca.crt certfile /etc/mosquitto/certs/broker.crt keyfile /etc/mosquitto/certs/broker.key listener 3942 protocol websockets cafile /etc/mosquitto/certs/ca.crt certfile /etc/mosquitto/certs/broker.crt keyfile /etc/mosquitto/certs/broker.key
React应用连接代码(some.jsx)
// some.jsx useEffect(() => { let reconnectAttempts = 0; try { if (user && !client) { const host = "ws://my.domain.io:39393" // const host = "wss://my.domain.io:3942" const options = { keepalive: 60, clientId: `${user.username}_${user.id}_${user.tenant}_${Date.now()}`, username: "username", password: "password", clean: true, rejectUnauthorized: false }; const mqttClient = mqtt.connect(host, options); setClient(mqttClient); console.log("client: ", mqttClient); mqttClient.on("connect", () => { console.log("Connected to MQTT broker"); setIsConnected(true); setIsReconnecting(false); setIsDisconnected(false); reconnectAttempts = 0; }); mqttClient.on("disconnect", () => { console.log("Disconnected to MQTT broker"); setIsConnected(false); setIsDisconnected(true); }); mqttClient.on("close", (err) => { console.log("Closed connection to MQTT broker", err); }); mqttClient.on("reconnect", () => { reconnectAttempts++; setIsReconnecting(true); if (reconnectAttempts > 5) { mqttClient.end(); console.log("Reconnect attempts exceeded. Closing connection to MQTT broker"); setIsConnected(false); setIsDisconnected(true); return; } console.log("Reconnecting to MQTT broker", reconnectAttempts); }); mqttClient.on("error", (err) => { console.log("Error from MQTT broker", err); }); } } catch (error) { console.error("Error connecting to MQTT broker", error); } return () => { if (client) { console.log("MQTT Hook cleanup") client.end(); setClient(null); } } }, [user, client]);
Python测试连接代码(更新内容)
# some.py def connect(self): self.client.on_message = self.on_message self.client.on_connect = self.on_connect self.client.on_disconnect = self.on_disconnect self.client.tls_set(cert_reqs=ssl.CERT_NONE) self.client.username_pw_set(self.username, self.password) self.client.connect(self.broker, self.port, keepalive=10) self.client.loop_start()
报错信息
- 连接39393端口时:浏览器控制台报错
Mixed Content: The page at 'https://xxx' was loaded over HTTPS, but attempted to connect to the insecure WebSocket endpoint 'ws://my.domain.io:39393'. This request has been blocked; this endpoint must be available over WSS. - 连接3942端口时:浏览器控制台报错
WebSocket connection to 'wss://my.domain.io:3942/' failed
排查与解决方案
1. 解决混合内容问题(39393端口)
生产环境页面通过HTTPS加载,浏览器会强制阻止非安全的WS连接,必须使用WSS协议。因此39393端口仅适合本地测试,生产环境需切换到3942端口的WSS连接。
2. 修复WSS连接失败(3942端口)
端口与防火墙验证
- 确认服务器3942端口已对外开放,防火墙/安全组规则允许外部访问
- 在服务器本地执行
wscat -c wss://localhost:3942,验证Broker的WSS服务是否正常
证书配置检查
- 确保
broker.crt包含完整证书链(若使用第三方CA签发,需附加中间证书) - 验证证书域名与
my.domain.io完全匹配,无IP或泛域名不匹配问题 - 通过
openssl x509 -in /etc/mosquitto/certs/broker.crt -text -noout检查证书是否过期
MQTT.js参数调整
- 修正WSS URL拼写:确保使用完整格式
wss://my.domain.io:3942(原代码注释中的URL缺少闭合引号) - 若使用自签名/私有CA证书,需在连接参数中指定CA证书:
import caCert from './ca.crt'; // 导入CA证书文件 const options = { // ...其他参数 ca: caCert, rejectUnauthorized: false // 仅临时测试使用,生产环境建议设为true并确保证书可信 };
生产环境反向代理配置(推荐)
通过Nginx反向代理转发WSS请求,避免直接暴露MQTT端口:
server { listen 443 ssl; server_name my.domain.io; ssl_certificate /path/to/your/cert.crt; ssl_certificate_key /path/to/your/key.key; location /mqtt { proxy_pass http://localhost:3942; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; } }
此时React应用连接URL改为wss://my.domain.io/mqtt,无需指定端口。
3. 日志调试
- 开启Mosquitto debug日志:在
mosquitto.conf中添加log_type debug,重启服务后查看/var/log/mosquitto/mosquitto.log,确认是否有连接请求记录 - 增强React错误日志输出:
mqttClient.on("error", (err) => { console.error("MQTT Error Details:", err.message, err.stack); });
内容的提问来源于stack exchange,提问作者nidea1
相关产品推荐
相关产品推荐

