サーバー10.0.4.18のnode.js 4.0でポート8020で実行されているwebsocketを持っています。私はsocket.io v1.3、express、およびexpress-sessionを使用してwebsocketを実装しました。node.jsサーバー上のPHP WebサーバーとSocket.ioとの間にハンドシェイクを作成する方法は?
プロジェクト定義
私は、PHPアプリケーションから、それに接続するすべてのユーザーのためにsocket.ioでセッションを作成できるようにする必要があります。ユーザーが最初のHTTPリクエストを送信した後、HTTPリクエストとともにPHPからsocket.ioに渡されるトークンを使用してそれらを認証します。
ユーザーが認証された後、後で再利用するために、いくつかの個人データをsocket.ioセッション内に保存する必要があります。ユーザーがPHPアプリケーションをリフレッシュするたびに、socket.ioはすでに作成されているセッションデータを知る必要があります。
問題
たびにユーザーリロード/セッションデータが失われた、「彼/彼女はからの接続」PHPページをリフレッシュします。サーバーは、その接続が以前に作成されたセッションXYZに属していることを認識できません。
PHPとnode.jsの間でハンドシェークを作成する方法がわかりません。ここで、2つのサーバーがsocket.ioセッションを結び付ける固有のデータを交換できます。
問題で非常によく見
私は私のブラウザでこのリンクhttps://10.0.4.18:8020/set/MikeAを開きました。 「これでルートコードごとにnode.jsから直接セッションが作成されました」
その後、PHPを使用してwebsocketに接続しました。セッションが問題なくスティックされていることがわかりました。私はブラウザで複数のタブを開くことができ、同じセッションが期待通りにそこにあります。
URLがhttps://10.0.4.18:8020/set/MikeAであるため、私のブラウザとセッションの間にセッションが確立されているため、そこからexpress-socket.io-セッションパッケージhttps://www.npmjs.com/package/express-socket.io-session。
しかし、私が手動でURLを使用してセッションを作成しないと、セッションは1ページの読み込みにのみ有効です。そして、ページが再ロードされるたびに、セッションは決して存在しないように破壊されます!
質問
socket.ioからhttps://10.0.4.18:8020/set/MikeA経由でのWebSocketへの接続接続するときとき私は同じ動作を開発する必要があります。
PHPページとページを再読み込みするたびに2人のサーバーがセッションデータを正しいユーザーに結びつけることができるPHPサーバーとsocket.ioの間でハンドシェイクを確立するにはどうすればよいですか?ここで
は、ここに私の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サーバ
<!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>
私はしないでください:あなたはあなたがここでより多くの情報を見つけることができます
JWT
で、あなたは、トークンにデータを格納することができ、テーブルを使用しない場合もページがリロードされたり、ブラウザが別の場所に移動したときに、JavaScriptインスタンスがページごとに一意であり、新しいソケット接続が確立される必要があるため、JavaScriptインスタンスがすべて終了することが考えられます。接続は、セッションで作業するのが最善の方法です。ユーザーが初めてログインするか、初めて接続するときは、一意のセッションIDはcですサーバーからユーザーに送信され、ローカルに保存されるため、クライアントが新しい接続を開始するたびに、サーバーとのセッションIDでセッションが識別され、サーバーが再認識する必要があります。 –
@DanielMendelセッションをどのように戻しますかクライアント? node.jsサーバーから、最初のリクエストの後に特定のsessionIDをロードするにはどうすればよいですか? –