Socket.io通过HTTPS无法连接报混合内容错误,该如何解决?
错误原因
这是典型的混合内容拦截错误:浏览器安全策略要求HTTPS协议加载的页面,所有发起的请求必须也走HTTPS协议,不能调用HTTP资源。你虽然客户端写了HTTPS开头的Socket连接地址,但你的Socket.io服务端本身跑的是HTTP协议,握手阶段会自动回落为HTTP请求,就触发了拦截。
解决方案
提供两种常用方案,可根据你的部署情况选择:
方案1:直接给Socket.io服务端配置HTTPS
- 提前准备好你网站域名对应的SSL证书文件(通常是
.crt公钥和.key私钥,部分服务商提供的是.pem格式),放到Node服务的同级目录 - 替换原Socket.io服务端代码,改为HTTPS模式,同时配置跨域避免额外报错:
const fs = require('fs'); const https = require('https'); // 加载你的SSL证书 const options = { key: fs.readFileSync('./你的证书私钥文件.key'), cert: fs.readFileSync('./你的证书公钥文件.crt') }; const server = https.createServer(options); const io = require('socket.io')(server, { // 配置跨域,允许你的HTTPS域名访问 cors: { origin: "https://你的域名.com", methods: ["GET", "POST"] } }); // 下面的原有业务逻辑不用修改 io.on('connection', function(socket) { console.log('Sockete birileri bağlandı'); socket.on('send-message', function(data) { console.log(data); io.emit('messages', data); }) socket.on('disconnect', function() { console.log('birileri geldi ve gitti') }) }); server.listen(5000);
- 修改PHP控制器中的请求地址,把
http://*****:5000改为https://*****:5000即可,如果PHP是在服务器本地调用Socket服务,可以加跳过证书校验的配置,避免自签名证书报错。
方案2:用Nginx反向代理(更推荐,无需修改Node服务)
如果你的HTTPS网站本身就是用Nginx托管的,直接加反向代理规则即可,共用网站的SSL证书,不需要单独开放5000端口到公网,安全性更高:
- 在你网站已经配置了HTTPS的Nginx server块中,添加如下规则:
location /socket.io/ { proxy_pass http://127.0.0.1:5000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_cache_bypass $http_upgrade; }
- 重载Nginx配置生效
- 修改客户端连接代码,不需要加端口,直接同域名请求即可:
var socket = io(); // 也可以显式写 var socket = io('https://你的域名.com'); 不需要带5000端口
- PHP端不需要修改,还是用本地HTTP地址
http://127.0.0.1:5000调用即可,本地内网请求不会触发混合内容拦截。
内容的提问来源于stack exchange,提问作者Walid
相关产品推荐
相关产品推荐

