如何在Node.js中使用Express/Socket.io使用HTTPS

32

我正在尝试使用https运行我的节点服务器。我正在使用express和socket.io。

这是我的https代码:

var httpsPort = 443;
var privateKey = fs.readFileSync(mykeypath');
var certificate = fs.readFileSync(mycertificatepath');
var credentials = {key: privateKey, cert: certificate};
var https = require('https').Server(credentials,app);
var io = require('socket.io')(https);

https.listen(httpsPort, function(){
logger.info('listening on *:' + httpsPort);
});


app.get('/initGame', function (req,res){

var slots = require('./slots.json', 'utf8');
var userObject = {
    address : req.connection.remoteAddress,
    userAgent : req.headers['user-agent']
};
db.getPlayedGames(userObject,function(playedGames){
    logger.debug(playedGames);
    if(typeof playedGames == 'undefined' ){
        playedGames=0;
    }else{
        playedGames = playedGames.games_played;
    }
    var spinsLeft = 10-playedGames;
    res.json({
        spinsLeft: spinsLeft,
        slots: slots
    });
  });
});

在我的客户端上,它是以下内容:

var myServer = "//" + document.domain + ":443";

$.get( myServer + "/initGame", function(data) {
    totalSpinsLeft = data.spinsLeft;
    $('#trysLeft').text(totalSpinsLeft);
    Seven.init(data.slots);
}).fail(function(){
    setTimeout(function(){
        $('#spinner2').text('Fehler bitte neu laden!');
    },3000);

});

目前我的服务器出现以下异常:

uncaughtException: 缺少 PFX 或证书 + 私钥。

编辑:目前我正在收到

错误请求

您的浏览器发送了一个无法理解的请求给启用 SSL 的服务器端口。请改用 HTTPS 方案访问此 URL。

2个回答

87

没有您的密钥和证书文件,很难测试您的示例。在此我将提供一个示例,其中我使用Express、socket.io和https。

首先,我将创建密钥和证书文件,因此在目录中从终端运行以下命令:

下面的命令将生成一个包含RSA密钥的文件。

$ openssl genrsa 1024 > file.pem

在这里,您将被要求输入数据,但是您可以按下回车键将其留空,直到生成 crs.pem。

$ openssl req -new -key file.pem -out csr.pem

然后会创建一个file.crt文件,其中包含SSL证书。

$ openssl x509 -req -days 365 -in csr.pem -signkey file.pem -out file.crt

因此,在我的app.js文件中,我设置并启动服务器时,请注意我正在使用上一步生成的file.pemfile.crt文件:
var fs = require('fs');
var https = require('https');

var express = require('express');
var app = express();

var options = {
  key: fs.readFileSync('./file.pem'),
  cert: fs.readFileSync('./file.crt')
};
var serverPort = 443;

var server = https.createServer(options, app);
var io = require('socket.io')(server);

app.get('/', function(req, res) {
  res.sendFile(__dirname + '/public/index.html');
});

io.on('connection', function(socket) {
  console.log('new connection');
  socket.emit('message', 'This is a message from the dark side.');
});

server.listen(serverPort, function() {
  console.log('server up and running at %s port', serverPort);
});

然后我的public/index.html,在这里我正在使用服务器:

<!doctype html>
<html>

  <head>

  </head>
  <body>
    <h1>I am alive!!</h1>

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

    <script>
      var URL_SERVER = 'https://localhost:443';
      var socket = io.connect(URL_SERVER);

      socket.on('message', function(data) {
        alert(data);
      });
    </script>
  </body>

</html>

最后,如果您从浏览器访问https://localhost,您将看到一个警告框,其中包含来自WebSocket服务器的消息。


1
也对我有用,非常感谢。我注意到你将 (dot)Server 改为了 (dot)createServer - 有什么原因吗?我也改了,然后它就起作用了。 - edwardsmarkf
看起来没有什么区别,看看这个回答解决你的疑问。https://dev59.com/5V8d5IYBdhLWcg3wXBFe - Wilson
如何在没有恐怖的密钥警告的情况下实现这一点?此外,这是否适用于任何端口?或者我必须使用443端口?如果我们有多个使用socket.io的服务并且需要不同的端口,会出现跨域问题吗? - mylord
@DanL 如果你指的是 app.js 文件,它是在服务器端运行的。 - Wilson
因此,“require”在其中自动可用。 - Wilson
显示剩余7条评论

2
这是我使用express设置它的方法:
var fs = require( 'fs' );
var app = require('express')();
var https        = require('https');
var server = https.createServer({
    key: fs.readFileSync('./test_key.key'),
    cert: fs.readFileSync('./test_cert.crt'),
    ca: fs.readFileSync('./test_ca.crt'),
    requestCert: false,
    rejectUnauthorized: false
},app);
server.listen(8080);

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

io.sockets.on('connection',function (socket) {
    ...
});

app.get("/", function(request, response){
    ...
})

我希望这篇文章能够节省读者的时间。

嗨emonik,你是如何获取test_key.key、test_cert.crt和test_cs.crt文件的? - Claes Gustavsson
我使用 Let's Encrypt 作为 SSL。 - Claes Gustavsson
@ClaesGustavsson:使用以下代码来使用 Let's Encrypt:var server = https.createServer({ key: fs.readFileSync('privkey.pem'), cert: fs.readFileSync('fullchain.pem') },app); - emonik
Emonik,谢谢,但我仍然遇到这个错误?https://46.22.120.82:3000/socket.io/socket.io.js net :: ERR_INSECURE_RESPONSE。我像这样链接:<script src="https://46.22.120.82:3000/socket.io/socket.io.js"></script>并尝试连接:var socket = io.connect('https://46.22.120.82:3000', {secure: true}); - Claes Gustavsson
如果您有时间帮助我,我在这里有一个问题 :-) http://stackoverflow.com/questions/41347766/how-to-use-https-with-letsencrypt-socket-io-and-node-js - Claes Gustavsson
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接