Tôi có một websocket chạy trên node.js 4.0 trên máy chủ 10.0.4.18 tại cổng 8020. Tôi đã triển khai websocket của mình bằng cách sử dụng socket.io v1.3, express và express-session.Làm thế nào để tạo một cái bắt tay giữa máy chủ web PHP và Socket.io trên máy chủ node.js?
Dự án Definition
tôi cần để có thể tạo ra một phiên trong socket.io cho mọi người dùng kết nối với nó từ một ứng dụng PHP. Sau khi người dùng gửi yêu cầu HTTP đầu tiên, tôi sẽ xác thực chúng bằng cách sử dụng một mã thông báo sẽ được chuyển từ PHP sang socket.io cùng với yêu cầu HTTP.
Sau khi người dùng được xác thực, tôi cần lưu một số dữ liệu cá nhân trong phiên socket.io để sử dụng lại sau này. Mỗi khi người dùng làm mới ứng dụng PHP, socket.io sẽ cần phải biết dữ liệu phiên đã được tạo.
Vấn đề
Mỗi lần load lại dùng/làm mới trang PHP "nơi anh/cô ấy được kết nối từ", dữ liệu phiên bị mất. Máy chủ không biết rằng kết nối thuộc về phiên XYZ được tạo trước đó.
Tôi không chắc chắn cách tạo một cái bắt tay giữa PHP và node.js trong đó hai máy chủ có thể trao đổi một dữ liệu duy nhất để kết nối phiên socket.io với.
trông rất chặt chẽ tại các vấn đề
Tôi mở liên kết này https://10.0.4.18:8020/set/MikeA trong trình duyệt của mình. "Điều này đã tạo một phiên cho tôi trực tiếp từ node.js trên mã tuyến"
Sau đó, tôi kết nối với websocket bằng cách sử dụng PHP, bây giờ tôi có thể thấy rằng phiên không có vấn đề gì! Tôi đã có thể mở nhiều tab trong trình duyệt và cùng một phiên ở đó như mong đợi.
Lý do nó hoạt động lần này là vì url https://10.0.4.18:8020/set/MikeA đã thiết lập phiên và gắn nó giữa trình duyệt của tôi và phiên và từ đó tôi có thể đọc/ghi phiên của mình từ socket.io sử dụng express-socket.io- gói phiên https://www.npmjs.com/package/express-socket.io-session.
Nhưng nếu tôi không tạo phiên sử dụng url theo cách thủ công, phiên sẽ chỉ tốt cho một lần tải trang. Và mỗi lần trang được tải lại phiên sẽ bị hủy như không bao giờ tồn tại!
Câu hỏi
tôi cần phải phát triển các hành vi tương tự khi kết nối đến WebSocket qua https://10.0.4.18:8020/set/MikeA khi kết nối từ socket.io.
Làm cách nào để thiết lập bắt tay giữa máy chủ PHP và socket.io nơi hai máy chủ có thể kết hợp dữ liệu phiên cho đúng người dùng mỗi khi trang PHP được tải lại hoặc tab của trình duyệt mới được mở?
Đây là mã WebSocket tôi
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);
});
Dưới đây là làm thế nào tôi kết nối với WebSocket từ máy chủ 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>
tôi không nghĩ rằng điều này là có thể vì khi trang được tải lại hoặc trình duyệt di chuyển đến một trang khác tất cả các trường hợp JavaScript chết vì chúng là duy nhất trên mỗi trang và cần thiết lập kết nối ổ cắm mới, nếu bạn muốn xác định người dùng từ kết nối cách tốt nhất là làm việc với các phiên, khi người dùng đăng nhập hoặc kết nối lần đầu tiên, một id phiên duy nhất là c reated và được gửi từ máy chủ đến người dùng và được lưu trữ cục bộ, vì vậy mỗi khi khách hàng bắt đầu một kết nối mới, nó sẽ tự xác định nó với id phiên tới máy chủ và máy chủ nên recoginze –
@DanielMendel Làm cách nào để chuyển lại phiên khách hàng? Từ máy chủ node.js, làm cách nào để tải một sessionID cụ thể sau yêu cầu đầu tiên? –