无法使 socket.io 在 HTTPS 上工作

Posted

技术标签:

【中文标题】无法使 socket.io 在 HTTPS 上工作【英文标题】:Can't make socket.io work on HTTPS 【发布时间】:2018-03-27 03:59:50 【问题描述】:

我正在使用简单的 socket.io 2.0.3 服务器,没有 express 或任何类似的东西来在我的 Laravel 应用程序中运行简单的聊天功能。

在我决定将网站切换到 HTTPS 之前,一切都运行良好。现在 socket.io 拒绝连接 (ERR_CONNECTION_CLOSED)。

这是我最简单的设置:

server.js:

var io = require('socket.io')(8080, 
    origins : //some stuff
);

html 文件

<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script>

var socket = io(':8080');
//more stuff

我在服务器文件夹、intermediate.crt、domain.com.crt 和 domain.com.key 中有所有需要的证书文件

有人可以帮助提供最简单的示例如何在 https 上进行这项工作吗?提前致谢!

编辑:在不使用 Express 的情况下需要可能的解决方案。

【问题讨论】:

node.js, socket.io with SSL 的可能重复项在我看来,该线程应该拥有您需要的一切。 不使用 Express 有没有办法做到这一点? 仅仅在浏览器中包含客户端代码是不够的。需要有一个服务器端的 co 组件 somplace。 你不需要 express,但是一旦你有套接字运行,上面的链接会告诉你如何连接客户端。 【参考方案1】:

我无法用简单的 socket.io 代码编写这个,所以我最终还是使用了 express。

如果将来有人需要,这是最简单的工作代码:

server.js

var express = require('express');
var app = module.exports = express();
var https = require('https');
var fs = require('fs');
var server = https.createServer(
    key: fs.readFileSync(/*full path to your key*/),
    cert: fs.readFileSync(/*full path to your cert*/),
    ca: fs.readFileSync(/*full path to your intermediate cert*/),
    requestCert: true,
    rejectUnauthorized: false
,app);
server.listen(8080); //listen on port 8080

var io = require('socket.io').listen(server);

io.set('origins', /*your desired origins*/);

io.set('transports', ['websocket',
    'flashsocket',
    'htmlfile',
    'xhr-polling',
    'jsonp-polling',
    'polling']);

var sockets = ;
//your socket logic

在 HTML 中:

var socket = io(':8080',secure: true);

【讨论】:

在origin中我们需要设置socket的后端URL还是应用URL?【参考方案2】:

重要事实:

你必须使用 https 而不是 http , 需要加载 crt 文件并创建选项对象,如示例 客户端只需要正确的地址,例如:https://YOUR_domain.com:PORT

服务器端:

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//High definition
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
// Globals 
//var MEMORY_CLEANER_INTERVAL = 5000;
//var crypto = require('crypto');
var tls = require('tls');
//dl  = require('delivery');
var fs = require("fs");
var mysql      = require('mysql');
var express    = require("express");
var app = express();
var http = require('http');
var https = require('https');
//var mkdirp = require('mkdirp');
var path = require('path');
//var nodemailer = require('nodemailer');
//includer
function read(f) return fs.readFileSync(f).toString();
function include(f) eval.apply(global, [read(f)]);

//var BASE = require('./lib/level1_module');
//BASE.NAME = "YEap";

var pkey = fs.readFileSync('/etc/httpd/ssl/YOUR_FILE.key');
var pcert = fs.readFileSync('/etc/httpd/ssl/YOUR_FILE_com.crt')

var SERVER_PORT = 9000;
 var options = 
    hostname: 'YOUR_PAGE.com',
    port: 9000,  
    key: pkey, 
    cert: pcert,
    requestCert: true,
    rejectUnauthorized: false,
;

var server = https.createServer(options, app).listen(SERVER_PORT, function()
  console.log("Express server listening on port " + SERVER_PORT);
);  

var io = require('socket.io').listen(server);
server.listen(SERVER_PORT);
console.log('Socket server listening on port : ' , SERVER_PORT);

【讨论】:

你为什么在https服务器上调用.listen两次?【参考方案3】:

您可以使用所有相关设置创建一个 HTTPS 服务器实例

var https = require('https');
https.createServer(options, app).listen(443);

然后简单地将其传递给构造函数:

new SocketIo(https)

【讨论】:

以上是关于无法使 socket.io 在 HTTPS 上工作的主要内容,如果未能解决你的问题,请参考以下文章

Socket.io 在 localhost 上工作,但在部署 heroku 后无法工作?

Socket.io 无法使用 nodejs 在 aws 上工作

Socket IO Node Js 和 PHP,如何使其工作?

Socket.io 无法正常工作

如何使 socket.io 在 pm2 集群模式下正常工作?

Socket.IO 无法通过 https 连接