узел.js, socket.io с помощью SSL


Я пытаюсь получить socket.io запуск с моим сертификатом SSL, однако, он не будет подключаться.

Я основал свой код на примере чата:

var https = require('https');
var fs = require('fs');
/**
 * Bootstrap app.
 */
var sys = require('sys')
require.paths.unshift(__dirname + '/../../lib/');

/**
* Module dependencies.
*/

var express = require('express')
  , stylus = require('stylus')
  , nib = require('nib')
  , sio = require('socket.io');

/**
 * App.
 */
var privateKey = fs.readFileSync('../key').toString();
var certificate = fs.readFileSync('../crt').toString();
var ca = fs.readFileSync('../intermediate.crt').toString();

var app = express.createServer({key:privateKey,cert:certificate,ca:ca });


/**
 * App configuration.
 */

...

/**
 * App routes.
 */

app.get('/', function (req, res) {
  res.render('index', { layout: false });
});

/**
 * App listen.
 */

app.listen(443, function () {
  var addr = app.address();
  console.log('   app listening on http://' + addr.address + ':' + addr.port);
});

/**
 * Socket.IO server (single process only)
 */

var io = sio.listen(app,{key:privateKey,cert:certificate,ca:ca});
...

Если я удалю код SSL он работает нормально, однако с ним я получаю запрос на http://domain.com/socket.io/1/?t=1309967919512

обратите внимание, что он не пытается https, что приводит к его сбою.

Я тестирую на chrome, так как это целевой браузер для этого приложение.

Я извиняюсь, если это простой вопрос, я новичок node/socket.io.

спасибо!

6 136

6 ответов:

используйте безопасный URL для вашего начального соединения, т. е. вместо "http://" используйте "https://". Если выбран транспорт WebSocket, то Socket.IO следует автоматически использовать "wss: / /" (SSL) для подключения WebSocket тоже.

обновление:

вы также можете попробовать создать соединение с помощью опции "secure":

var socket = io.connect('https://localhost', {secure: true});

вот как мне удалось настроить его с помощью 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){
    ...
})


Я надеюсь, что это сэкономит чье-то время.

обновление : для тех, кто использует шифрование позволяет использовать этот

var server = https.createServer({ 
                key: fs.readFileSync('privkey.pem'),
                cert: fs.readFileSync('fullchain.pem') 
             },app);

на той же ноте, если ваш сервер поддерживает как http и https вы можете подключиться с помощью:

var socket = io.connect('//localhost');

до автоматическое определение схемы браузер и подключиться с помощью http/https соответственно. когда в HTTPS, транспорт будет защищен по умолчанию, как подключение с помощью

var socket = io.connect('https://localhost');

будет использовать безопасные веб-сокеты -wss:// (the {secure: true} является избыточным).

для получения дополнительной информации о том, как легко обслуживать http и https с помощью одного и того же узла сервер проверить ответ.

Если ваш сервер сертифицированный файл не является надежным, (например, вы можете создать хранилище ключей самостоятельно с keytool команда в java), вы должны добавить дополнительную опцию rejectUnauthorized

var socket = io.connect('https://localhost', {rejectUnauthorized: false});

проверить это.конфигурация..

app = module.exports = express();
var httpsOptions = { key: fs.readFileSync('certificates/server.key'), cert: fs.readFileSync('certificates/final.crt') };        
var secureServer = require('https').createServer(httpsOptions, app);
io = module.exports = require('socket.io').listen(secureServer,{pingTimeout: 7000, pingInterval: 10000});
io.set("transports", ["xhr-polling","websocket","polling", "htmlfile"]);
secureServer.listen(3000);

на стороне сервера:

import http from 'http';
import https from 'https';
import SocketIO, { Socket } from 'socket.io';
import fs from 'fs';
import path from 'path';

import { logger } from '../../utils';

const port: number = 3001;

const server: https.Server = https.createServer(
  {
    cert: fs.readFileSync(path.resolve(__dirname, '../../../ssl/cert.pem')),
    key: fs.readFileSync(path.resolve(__dirname, '../../../ssl/key.pem'))
  },
  (req: http.IncomingMessage, res: http.ServerResponse) => {
    logger.info(`request.url: ${req.url}`);

    let filePath = '.' + req.url;
    if (filePath === './') {
      filePath = path.resolve(__dirname, './index.html');
    }

    const extname = String(path.extname(filePath)).toLowerCase();
    const mimeTypes = {
      '.html': 'text/html',
      '.js': 'text/javascript',
      '.json': 'application/json'
    };

    const contentType = mimeTypes[extname] || 'application/octet-stream';

    fs.readFile(filePath, (error: NodeJS.ErrnoException, content: Buffer) => {
      if (error) {
        res.writeHead(500);
        return res.end(error.message);
      }
      res.writeHead(200, { 'Content-Type': contentType });
      res.end(content, 'utf-8');
    });
  }
);

const io: SocketIO.Server = SocketIO(server);

io.on('connection', (socket: Socket) => {
  socket.emit('news', { hello: 'world' });
  socket.on('updateTemplate', data => {
    logger.info(data);
    socket.emit('updateTemplate', { random: data });
  });
});

server.listen(port, () => {
  logger.info(`Https server is listening on https://localhost:${port}`);
});

на стороне клиента:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Websocket Secure Connection</title>
</head>

<body>
  <div>
    <button id='btn'>Send Message</button>
    <ul id='messages'></ul>
  </div>
  <script src='../../../node_modules/socket.io-client/dist/socket.io.js'></script>
  <script>
    window.onload = function onload() {
      const socket = io('https://localhost:3001');
      socket.on('news', function (data) {
        console.log(data);
      });

      socket.on('updateTemplate', function onUpdateTemplate(data) {
        console.log(data)
        createMessage(JSON.stringify(data));
      });
      const $btn = document.getElementById('btn');
      const $messages = document.getElementById('messages');

      function sendMessage() {
        socket.emit('updateTemplate', Math.random());
      }

      function createMessage(msg) {
        const $li = document.createElement('li');
        $li.textContent = msg;
        $messages.appendChild($li);
      }

      $btn.addEventListener('click', sendMessage);
    }
  </script>
</body>

</html>