如何在node.js服务器上创建PHP Web服务器和Socket.io之间的握手? [英] How to create a handshake between PHP web server and Socket.io on node.js server?

查看:191
本文介绍了如何在node.js服务器上创建PHP Web服务器和Socket.io之间的握手?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个websocket在server.js 4.0上运行在服务器10.0.4.18端口8020.我实现了我的websocket使用socket.io v1.3,express和express-session。

I have a websocket running on node.js 4.0 on server 10.0.4.18 at port 8020. I implemented my websocket using socket.io v1.3, express, and express-session.

项目定义

我需要能够为连接到它的每个用户在socket.io中创建一个会话从PHP应用程序。在用户发送第一个HTTP请求后,我将使用将从PHP传递到socket.io以及HTTP请求的令牌进行身份验证。

I need to be able to create a session in socket.io for every user that connects to it from a PHP application. After the user send the first HTTP request, I will authenticate them using a token that will be passed from PHP to socket.io along with the HTTP request.

用户验证后,我需要在socket.io会话中保存一些个人数据,以便稍后重用。每次用户刷新PHP应用程序时,socket.io将需要知道已经创建的会话数据。

After the user is authenticated, I need to save some personal data inside socket.io session to reuse later. Every time the user refresh the PHP application, socket.io will need to know the session data that is already created.

问题

每当用户重新加载/刷新PHP页面他/她从哪里连接时,会话数据丢失。服务器无法知道连接属于先前创建的会话XYZ。

Every time the user reloads/refreshed the PHP page "where he/she connected from", the session data are lost. The server fails to know that connection belong to session XYZ which is previously created created.

我不知道如何在PHP和node.js之间创建握手,其中两个服务器可以交换一个唯一的数据来将socket.io会话绑定到。

I am not sure how to create a handshake between PHP and node.js where the two server can exchange a unique data to tie the socket.io session to.

非常仔细地查看问题

我打开了这个链接 https://10.0.4.18:8020/set/MikeA 在我的浏览器这直接从node.js为路由代码创建了一个会话

I opened this link https://10.0.4.18:8020/set/MikeA in my browser. "This created a session for me directly from node.js per the route code"

然后我使用PHP连接到websocket,现在我可以看到会话坚持没问题!我可以在浏览器中打开多个选项卡,同样的会话就像预期的那样。

Then I connected to the websocket using PHP, now I can see that the session sticks with no problem! I was able to open multiple tabs in the browser and the same session is there as expected.

这次工作的原因是因为url https://10.0.4.18:8020/set/MikeA 建立了一个会话,并把它绑在我的浏览器和会话之间,从在那里,我可以使用express-socket.io-session包读取/写入我的会话。 https://www.npmjs.com/package/express-socket.io-session

The reason it worked this time is because the url https://10.0.4.18:8020/set/MikeA established a session and tied it between my browser and the session and from there I was able to read/write my session from socket.io using express-socket.io-session package https://www.npmjs.com/package/express-socket.io-session.

但是如果我不创建会话使用url手动会话只对一个页面加载只有好处。每次重新加载页面时,会话都将被销毁,因为它从未存在!

But if I do not create the session using the url manually the session will only be good for one page load only. And every time the page is reloaded the session is destroyed like it never existed!

问题

当通过 https://10.0.4.18:连接到websocket时,我需要开发相同的行为8020 / set / MikeA 当从socket.io连接时。

I need to develop the same behavior when connection to the websocket via https://10.0.4.18:8020/set/MikeA when connecting from the socket.io.

如何在两个服务器之间建立PHP服务器和socket.io之间的握手

How can I establish a handshake between PHP server and socket.io where the two servers can tie the session data to the correct user every time the PHP page is reloaded or a new browser's tab is opened?

这是我的websocket代码

Here is my websocket code

var app = require('express')(),
    https = require('https'),
    fs = require('fs'),
    session = require('express-session'),
    sharedsession = require("express-socket.io-session"),
    fileStore = require('session-file-store')(session),
    base64url = require('base64url'),
    cookieParser = require("cookie-parser"),
    env = require('./modules/config');


var server = https.createServer(
    {
        key: fs.readFileSync('certs/key.pem'),
        cert: fs.readFileSync('certs/cert.pem')
    }, app).listen(env.socket.port, env.socket.host, function () {
    console.log('\033[2J');
    console.log('Websocket is running at https://%s:%s', server.address().address, server.address().port);
});

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

var icwsReq = require('./modules/icws/request.js'),
    icwsConn = require('./modules/icws/connection.js'),
    icwsInter = require('./modules/icws/interactions.js'),
    sessionValidator = require('./modules/validator.js');

var icwsRequest = new icwsReq();
var sessionChecker = new sessionValidator();

var sessionStoreFile = new fileStore({path: './tmp/sessions'});

var clients = {};

var sessionOptions = {
        store: sessionStoreFile,
        secret: env.session.secret,
        name: env.session.name,
        rolling: true,
        saveUninitialized: false,
        resave: true,
        unset: 'keep',
        cookie: {
            maxAge: 60 * 60 * 1000
        }
    };

var sessionMiddleware = session(sessionOptions);

app.use(sessionMiddleware); // session support for the app


//Set access control headers on every express route.
app.use(function (req, res, next){
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type');
    next();
});


// Use shared session middleware for socket.io
io.use(sharedsession(sessionMiddleware, {
    autoSave: true
})); 

//Middleware for authorizing a user before establishing a connection
io.use(function(socket, next) {

    var myIP = socket.request.socket.remoteAddress || '';
    var token = socket.handshake.query.tokenId || '';
    var session = socket.handshake.session || {};

    if(!session && !token){
        console.log('Log: No session and no token!');
        return next(new Error('No tken/session found'));
    }

    if(!token){
        console.log('Log: token was not found');
        return next(new Error('Token not found'));
    }

    //SessionID should be defined on a page reload
    console.log('IP Address: ' + myIP + '      SessionID: ' + socket.handshake.sessionID);

    //allow any user that is authorized
    if(session && session.autherized && token == session.token){
        console.log('Log: you are good to go');
        return next(new Error('You are good to go'));
    }

    //if the client changed their token "client logged out"
    //terminate the open session before opening a new one
    if (session.autherized && token != session.token){

    var decodedToken = base64url.decode(token);

    sessionChecker.validateData(decodedToken, myIP, env.session.duration, function(isValid, icws){

        if(!isValid){
            console.log('Log: token could not be validated!');
            return next(new Error('Token could not be validated!'));
        }

        session.authorized = true;
        session.icwsServer = icws.host;
        session.icwsPort = icws.port;
        session.token = token;
        session.icwsSessionId = null;
        session.icwsToken = null;

        icwsRequest.setConnection(icws.host, icws.port);
        var icwsConnection = new icwsConn(icwsRequest);

        session.save(function(){
            console.log('Log: new connection to websocket!');
            return next();
        });
    });

});


io.on('connection', function (socket) { 

    console.log('Connection is validated and ready for action!');

    var socketId = socket.id;

    if(!socket.handshake.sessionID){
        console.log('sessionId was not found');
        return false;
    }

    var sessionID = socket.handshake.sessionID;
    var userCons = clients[sessionID] || [];

    //Add this socket to the user's connection
    if(userCons.indexOf(socketId) == -1){
        userCons.push(socketId);
    }

    clients[sessionID] = userCons;

    socket.on('chat', function(msg){

        for (var key in clients[sessionID]) {
          if (clients[sessionID].hasOwnProperty(key)) {
            var id = clients[sessionID][key];
            console.log('Client Said: ' + msg);
            io.to(id).emit('chat', {message: 'Server Said: ' + msg});
          }
        }
    });


    socket.on('disconnect', function(msg){
        console.log('Closing sessionID: ' + sessionID);
        var userCons = clients[sessionID] || [];

        var index = userCons.indexOf(socketId);

        if(index > -1){
            userCons.splice(index, 1);
            console.log('Removed Disconnect Message: ' + msg);
        } else {
            console.log('Disconnect Message: ' + msg);
        }

    }); 

    socket.on('error', function(msg){
        console.log('Error Message: ' + msg);
    }); 

});


app.get('/', function (req, res) {
    res.send('welcome: ' + req.sessionID);
});

app.get('/read', function (req, res) {
    res.send('welcome: ' + req.session.name);
});

app.get('/set/:name', function (req, res) {
    req.session.name = req.params.name;
    res.send('welcome: ' + req.session.name);
});

这是我如何从PHP服务器连接到websocket

Here is how I connect to the websocket from PHP server

<!doctype html>
<html lang="en-US">
  <head>
    <title>Socket.IO chat</title>
    <meta charset="utf-8">
    <style>
      * { margin: 0; padding: 0; box-sizing: border-box; }
      body { font: 13px Helvetica, Arial; }
      form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }
      form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; }
      form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }
      #messages { list-style-type: none; margin: 0; padding: 0; }
      #messages li { padding: 5px 10px; }
      #messages li:nth-child(odd) { background: #eee; }
    </style>

    <script src="https://10.0.4.18:8020/socket.io/socket.io.js"></script>
    <script type="text/javascript" src="/js/jquery-2.1.0.min.js"></script>
    <script>

        $(function(){
            var socket = io.connect('https://10.0.4.18:8020', {secure: true, port: 8020,  query : 'PHP generated token that will be used to authenticate the user from node.js'});

           //When the "send" button is clicked
            $('#f').click(function(e){
                e.preventDefault();
                var message = $('#m').val().trim();
                if( message  == ''){
                    return false;
                }

                socket.emit('chat', message);
                $('#m').val('');
            });

            socket.on('chat', function(msg){
                $('#messages').append($('<li>').text(msg.message));
            });

        });

    </script>

  </head>
  <body>
    <ul id="messages"></ul>
    <form action="" id="f">
      <input id="m" autocomplete="off" /><button>Send</button>
    </form>
  </body>
</html>


推荐答案

将令牌存储在浏览器中并发送来自php的每个请求,具有如下的授权承载:

Store the token in the browser and send it along with every request from the php, with an authorization bearer which looks like :

Authorization: Bearer token

所以每当node.js服务器得到一个请求,你可以比较用户对应的令牌并获取数据。

So everytime the node.js server get's an request you can compare the token to which user corresponds and get the data.

您可以将用户标识和令牌之间的关系存储在表中的到期日期,并在每次登录时刷新令牌。

You can store the relationship between the userid and the token with an expiry date in a table and refresh the token on every login.

如果您不想使用表格,可以使用JWT

Also if you don't want to use a table, you can store the data in the token, with JWT

在令牌中存储数据您可以在这里找到更多信息:

You can find more info here:

http://jwt.io/

这篇关于如何在node.js服务器上创建PHP Web服务器和Socket.io之间的握手?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆