Socket IO только сеанс не сохраняется
Я использую Socket.io
в приложении чата, которое я создаю. Я пытаюсь настроить сеанс так, чтобы я мог сохранять логин пользователей между сеансами.
Вот соответствующий код:
index.js (сервер)
var cookieParser = require('cookie-parser')();
var session = require('cookie-session')({ secret: 'secret' });
app.use(cookieParser);
app.use(session);
io.use(function(socket, next) {
var req = socket.handshake;
var res = {};
cookieParser(req, res, function(err) {
if (err) return next(err);
session(req, res, next);
});
});
io.on('connection', function(socket){
socket.on('test 1', function(){
socket.handshake.test = 'banana';
});
socket.on('test 2', function(){
console.log(socket.handshake.test);
});
});
chat.js (клиент)
var socket = io();
socket.emit('test 1');
socket.emit('test 2');
В приведенном выше коде, он будет печатать banana
на консоли, как ожидалось. Однако, если я прокомментирую "тест 1" так:
var socket = io();
// socket.emit('test 1');
socket.emit('test 2');
Он напечатает undefined
на консоли.
Должна ли она печатать banana
, так как она использует сеанс и сохраняется между запросами? Я также сталкиваюсь с той же проблемой, если я инвертирую порядок, в котором я называю "тест 1" и "тест 2".
Что я делаю неправильно? Что мне не хватает для того, чтобы сессия сохранялась, как ожидалось?
Ответы
Ответ 1
Проблема заключается в том, что вы используете cookie-session
, а socket.io не позволяет устанавливать cookie из-за спецификации XMLHttpRequest
, также у вас нет request/response
в середине веб-сокета транзакции, поэтому вы не можете установить файл cookie ответа.
С вашим промежуточным программным обеспечением вы можете видеть файлы cookie, но вы не можете установить его в socket.io.
Это может быть обеспечено в этом примере:
io.use(function(socket, next) {
var req = socket.request;
var res = req.res;
cookieParser(req, res, function(err) {
if (err) return next(err);
session(req, res, next);
});
});
io.on('connection', function(socket){
var req = socket.request;
console.log(req.session.test)
socket.on('test 1', function(){
req.session.test = 'banana';
});
socket.on('test 2', function(){
console.log(req.session.test);
});
});
app.get('/', function(req, res) {
console.log(req.session.test)
if (!req.session.test) {
req.session.test = 'banana request'
}
})
Вы можете использовать что-то вроде redis
для продолжения сеансов или некоторых "взломать", чтобы установить его в рукопожатие.
Другой вариант - не использовать сеансы вообще и просто установить свойство в объекте socket
или в другом объекте javascript, но в этом случае вы не можете разделить объект между серверами/службами.
Ответ 2
- По-прежнему доступны заголовки.
- Вы можете сохранять данные на стороне сервера для каждого сокета: socket.my_value = "любой тип данных";
- Вы можете сохранить данные в объекте io.sockets, io.my_value = "любой тип данных"
Итак, пример:
io.on('connection', function(socket){
var id = socket.handshake.query.id; //you can set this in client connection string http://localhost?id=user_id
//Validate user, registered etc. and if ok/
if(validateUser(id)) {
//if this is reconnect
if(io.sessions[id]) {
socket.session_id = io.sessions[id].session_id;
} else {
var session_id = random_value;
socket.session_id = some_random_value;
io.sessions[id] = {
user_id: id,
session_id: socket.session_id
};
}
registerEvent(socket);
} else {
socket.emit('auth_error', 'wrong user');
}
});
function registerEvent(socket) {
socket.on('some_event', function(data, callback) {
if(!socket.session_id) {
callback('unathorized');//or emit
socket.emit('auth_error', 'unauthorized');
}
//do what you want, user is clear
});
}