【问题标题】:Socket.io on Express + handlebars doesn't work on httpsExpress + 车把上的 Socket.io 在 https 上不起作用
【发布时间】:2017-12-01 18:15:08
【问题描述】:

我正在尝试使用 socket.io,但是当我在服务器上使用 https 运行它时,我的 socket.io 不起作用。

我的app.js

let express = require('express');
let path = require('path');
let favicon = require('serve-favicon');
let logger = require('morgan');
let cookieParser = require('cookie-parser');
let bodyParser = require('body-parser');

let index = require('./routes/index');
let users = require('./routes/users');
let dashboard = require('./routes/dashboard');



let app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');

// uncomment after placing your favicon in /public
app.use(favicon(path.join(__dirname, 'public/images', 'chatbotico.png')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(methodOverride('X-HTTP-Method-Override'));
app.use(session({secret: 'supernova', saveUninitialized: true, resave: true}));
app.use(passport.initialize());
app.use(passport.session());

// Session-persisted message middleware
app.use(function(req, res, next){
    let err = req.session.error,
        msg = req.session.notice,
        success = req.session.success;

    delete req.session.error;
    delete req.session.success;
    delete req.session.notice;

    if (err) res.locals.error = err;
    if (msg) res.locals.notice = msg;
    if (success) res.locals.success = success;

    next();
});


app.use('/', index);
app.use('/users', users);
app.use('/users/dashboard', dashboard);

// realtime chatbot
    let socket = require('./config/sock');
    // Socket connection
    socket.conn();
socket.fromClient();


// catch 404 and forward to error handler
app.use(function(req, res, next) {
  let err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

所以我没有在 app.js 上使用 socket.io,而是创建了一个从应用程序调用它并保存所有套接字配置的函数

./config/sock

let app = require('express')();
let https = require('https');
let fs = require('fs');

let options = {
    key: fs.readFileSync('./server.key'),
    cert: fs.readFileSync('./server.crt'),
    requestCert: false,
    rejectUnauthorized: false
};


let server = https.createServer(options, app);


let io = require('socket.io')(server);
io.set("transports", ["xhr-polling","websocket","polling", "htmlfile"]);

let conn = function() {
    server.listen(8080, function(){

    });

    app.get('/', function (req, res) {
        res.set('Content-Type', 'text/xml; charset=utf-8');
        res.sendfile(__dirname + '/index.html');
    });
};

let fromClient = function() {
    io.on('connection', function (socket) {
        socket.on('fromClient', function (data) {
            console.log(data);
            });
        });
    });
};
module.exports = {conn,fromClient};

所以从我的客户端,我在车把上导入了 socket.io js,在 ./routes/dashboard 上路由

./views/dashboard/dashboard.hbs

<html>
[...]
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script>
<script src="../javascripts/convo.js"></script>
[...]
<html>

通过此导入,我尝试连接 convo.js 上的服务器端

./public/convo.js

let socket = io.connect('https://localhost:8080', { secure: true, reconnect: true, requestCert: false, rejectUnauthorized: false });

socket.emit('fromClient', { 'client' : 'some value'});

我的问题是,我已经尽一切努力让我的浏览器允许这些带有自签名证书的 https 连接。而且我不知道如何让它通过。

  localhost:8080 uses an invalid security certificate. 
The certificate is not trusted because it is self-signed. 
The certificate is not valid for the name localhost. Error code: 
SEC_ERROR_UNKNOWN_ISSUER 

谁能给我一盏灯。这不是产品,是大学项目,我不想买证书

【问题讨论】:

    标签: node.js express socket.io handlebars.js


    【解决方案1】:

    我已经解决了这个问题。 (浏览器真的不会再合作了。谢谢,世界上所有愚蠢的网络犯罪分子毁了我们其他人。)

    首先,编辑您机器的主机文件以包含类似的条目

    lucas.example.com   127.0.0.1
    

    这样您就可以在自己的机器上点击http://lucas.example.com:8080 而不是http://localhost:8080。让它发挥作用。 (使用您最喜欢的搜索引擎来了解如何编辑您的主机文件。)

    其次,为自己制作一个通用名称为 lucas.example.com 的自签名证书。在本地计算机的 Web 服务器中安装该证书。点击https://lucas.example.com:8080。您将在浏览器中收到证书错误。覆盖它并说服自己可以通过 https 看到 localhost。

    然后弄清楚如何将您的自签名证书导入浏览器并告诉您的浏览器信任它。这可能会有所帮助。 Getting Chrome to accept self-signed localhost certificate

    那么您应该可以从浏览器进行 wss 访问。

    最后,您需要在您的机器上安装 node.js 以信任您的自签名证书。这可能会有所帮助。 How do I use a self signed certificate for a HTTPS Node.js server?

    如果最坏的情况发生,您可以以不到 10 美元的价格从 namecheap.com(Comodo 的经销商)购买为期一年的证书。不过,您必须证明您拥有该域。

    或者,也许会纠缠你大学的 IT 部门,或者让你的教授这样做。适当的 TLS 证书应该是任何适当配置的大学开发实验室的一部分。他们应该获得类似*.studentlab.cs.uni.edu 的通配符证书,并让您为此类工作创建自己的lucas.studentlab.cs.uni.edu

    【讨论】:

    • 感谢 O.Jones! ,我会检查每一个提示,我会尽快给你回复:)
    【解决方案2】:

    O. Jones 的回答对我帮助很大。但我改变了使用 socket.io 的方法

    我将套接字与 express 连接到同一台服务器。

    所以在 app.js 上,我改变了套接字连接:

    // Socket connection
    let server = require('http').Server(app);
    socket.fromClient(server);
    

    并导出到bin/www,也就是服务器变量

    module.exports = {app: app, server: server};
    

    在 bin/www 我已经导入了应用程序和服务器,并运行它:

    var port = normalizePort(process.env.PORT || '3000');
    app.set('port', port);
    
        var app = require('../app').app;
    
    var server = require('../app').server;
    /**
     * Listen on provided port, on all network interfaces.
     */
    
    server.listen(port);
    server.on('error', onError);
    

    所以这允许我在正在运行的快速服务器中使用我的 socket.io(在服务器端)。

    let api = require('./api');
    let ipfs = require('./handlefiles');
    let funct = require('./function');
    let io;
    
    
    let fromClient = function(server) {
    
        io = require('socket.io')(server);
    
        io.on('connection', function (socket) {
            socket.on('fromClient', function (data) {
                api.getRes(data.client).then(function(res){
                    socket.emit('fromServer', { server: res.message, treat: res.action });
                });
            });
        });
    };
    
    module.exports = {fromClient};
    

    在客户端,我只是调用 localhost(或所需的主机)

    let socket = io('//localhost:3000');
    

    这将客户端与服务器端连接起来,让我无需证书即可运行我的应用程序,无论是在服务器端的开发还是生产环境中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-06
      • 2018-05-15
      • 1970-01-01
      • 1970-01-01
      • 2017-03-03
      • 1970-01-01
      • 2014-12-08
      • 1970-01-01
      相关资源
      最近更新 更多