如何在node.js服务器上的PHP Web服务器和Socket.io之间创build握手?

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

项目定义

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

用户通过身份validation后,我需要在socket.io会话中保存一些个人数据,以便以后重用。 每次用户刷新PHP应用程序时,socket.io都需要知道已经创build的会话数据。

问题

每当用户重新载入/刷新“他/她所连接的地方”的PHP页面时,会话数据都将丢失。 服务器无法知道连接属于之前创build的会话XYZ。

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

非常仔细的看问题

我在浏览器中打开了这个链接https://10.0.4.18:8020/set/MikeA 。 “这根据路由代码直接从node.js创build了一个会话”

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

这次工作的原因是因为urlhttps://10.0.4.18:8020/set/MikeAbuild立了一个会话,并将其绑定在我的浏览器和会话之间,从那里我能够从套接字读/写我的会话。 io使用express-socket.io-session包https://www.npmjs.com/package/express-socket.io-session 。

但是,如果我不使用手动创build会话会话将只适合一个页面加载。 每次页面重新加载时,会话都会被破坏,就像它从来没有存在过!

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

如何在PHP服务器和socket.io之间build立一个握手,在每次重新加载PHP页面或打开一个新的浏览器选项卡时,两台服务器可以将会话数据绑定到正确的用户?

这是我的websocket代码

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

 <!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的请求一起发送,授权持票人如下所示:

 Authorization: Bearer token 

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

您可以将用户标识和具有到期date的标记之间的关系存储在表中,并在每次login时刷新标记。

另外,如果您不想使用表格,则可以使用JWT将数据存储在令牌中

你可以在这里find更多的信息:

http://jwt.io/