JavaScript MQTT WebSocket本地正常,HTTPS环境下连接失败
HTTPS环境下MQTT WebSocket连接被拦截的解决方案
问题根因
本地调试正常、部署到HTTPS站点后连接失败,触发的是浏览器强制混合内容安全规则:
- 当页面通过HTTPS协议加载时,所有页面发起的网络请求(包括WebSocket连接)必须使用对应的加密协议
- 非加密的
ws://端点会被浏览器直接拦截,必须替换为加密的wss://端点才能在HTTPS页面中正常通信 - 本地环境无拦截是因为本地调试通常使用HTTP协议或者localhost上下文,不受该安全规则约束
落地解决步骤
1. MQTT Broker侧配置WSS服务
WSS是基于TLS加密的WebSocket协议,和HTTPS共用同一套证书信任体系,需要先完成Broker侧的基础配置:
- 准备和站点域名匹配、受浏览器信任的正规CA签发的SSL证书,不支持自签名证书
- 在MQTT Broker(如Mosquitto、EMQX等)上新增WSS监听端口,通常独立WSS端口配置为8084,配置时绑定已准备好的SSL证书、证书私钥路径,保持WebSocket连接路径为默认的
/mqtt即可 - 如果使用Nginx等反向代理,也可以不单独开启Broker的WSS端口:将域名443端口下的
/mqtt路径反向代理到Broker的普通WS服务端口,由反向代理层完成TLS加密,同样可以对外提供WSS服务
2. 调整前端Paho MQTT客户端的连接配置
现有代码中Paho客户端的初始化写法,默认使用非加密WS协议连接8083端口,和HTTPS上下文不匹配,需要按WSS的连接参数调整:
- 原初始化代码:
var client = new Paho.Client('myserver.com',8083,'asdfg'); - 调整后的初始化代码(直接传入完整WSS连接地址):
var client = new Paho.Client('wss://myserver.com:8084/mqtt','asdfg');如果是通过443端口反向代理提供WSS服务,连接地址直接写为
wss://myserver.com/mqtt即可,不需要额外指定端口号
常见注意事项
- 不要尝试通过修改浏览器安全设置关闭混合内容拦截来临时解决问题,该策略是所有现代浏览器的默认强制规则,普通访问用户不会修改浏览器配置,问题会对所有线上用户复现
- 连接时需要校验证书状态:如果证书存在过期、域名不匹配、不受信任的问题,WSS连接会直接抛出证书错误被拦截
- 本地调试时尽量模拟线上HTTPS+WSS的完整链路,不要只在HTTP+WS的本地环境验证代码逻辑
内容的提问来源于stack exchange,提问作者Satheesh Chandran
相关产品推荐
相关产品推荐

