экспресс-сеанс не устанавливает cookie сеанса при использовании с socket.io

Я пытаюсь реализовать аутентификацию и сеансы с socket.io.

После долгого исследования 1 я установил следующее, в котором используются экспресс-сеанс и экспресс-сеанс.

Проблема в том, что соединения express и socket.io, похоже, имеют разные сеансы, поскольку id, который я получаю, отличается.

Кроме того, в моем приложении в браузере не установлен файл cookie (возможно, поэтому оба компонента создают разные сеансы?)

Я использую экспресс 4.13.3 экспресс-сеанс 1.12.1 и socket.io 1.3.7.

Ниже приведен код на стороне сервера, который я установил:

var app = require('express')();
var server = app.listen(80);
var parser = require('body-parser');
var Session = require('express-session');
var io = require('socket.io')(server);
var game = require('./game.js');
var session = Session({
  secret: 'some secret',
  resave: false,
  saveUninitialized: false,
  cookie: {
    'name': 'test',
    httpOnly: false,
    secure: false,
    maxAge: ((60 * 1000) * 60)
  }
});
app.use(parser.urlencoded({
  extended: false
}));
app.use(session);
app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});
app.post('/login', function(req, res) {
  console.log('login %s', req.session.id);
  console.dir(req.session, {
    color: true
  });
  res.json({
    status: 'success'
  });
});
io.use(function(socket, next) {
  session(socket.handshake, {}, next);
});
console.log('socket server started @ %s !', 80);
io.on('connection', function(socket) {
  console.log('user connected %s', socket.handshake.session.id);
  console.dir(socket.handshake.session, {
    color: true
  });
  socket.on('disconnect', function() {
    console.log('user disconnected');
    console.dir(socket.handshake.session, {
      color: true
    });
  });
});

и код на клиенте для тестирования:

$.ajax({
   url: 'http://127.0.0.1:80/login',
   type:'post',
   success: function(response) {
      var socket = io('http://127.0.0.1:80');
   }
});

Ниже вывод в консоли:

введите описание изображения здесь

и это раздел ресурсов в браузере:

введите описание изображения здесь

Я даже сбит с толку, увидев, что объект session не имеет никакого свойства id при входе в консоль, но session.id выводит разные значения. Возможно, это исходит из цепочки прототипов объектов или чего-то в этом роде.

Единственная разница, которую я могу придумать для своего кода и учебных пособий, заключается в том, что все они обслуживают страницу index.html с одного и того же экспресс-сервера. В моем случае файл у меня локально.

Я где-то читал, что в таких случаях я должен отправить http запрос для выражения перед установкой соединения socket.io.

Библиотека на стороне клиента socket.io.js обслуживается с того же сервера, который используется совместно с express и socket.io (<script src="http://127.0.0.1/socket.io/socket.io.js"></script>), кроме этого, я также использую экспресс-маршрут /login для тестирования до того, как будет установлено соединение с сокетом.

Поэтому мне интересно, почему на стороне клиента не устанавливаются файлы cookie и почему экспресс-запросы и запросы сокетов создали разные сеансы ...? Что мне здесь не хватает ..?


1 Код в основном основан на:


P.S: Я пытаюсь сделать следующее: когда клиент сокета повторно подключается, мне нужно вернуть его туда, где он был, с деталями сеанса. Я действительно не хочу делиться сеансами с экспрессом, но промежуточное ПО Express - единственный способ, с которым я столкнулся, для реализации сеансов с socket.io.


person T J    schedule 25.11.2015    source источник


Ответы (2)


Проблема не связана ни с экспрессом, ни с socket.io. Проблема в том, что я загружал проект с локального сервера, а не с сервера express и socket.io.

Таким образом, это междоменный запрос ajax, и в этом случае некоторые браузеры отказываются обрабатывать заголовок Set-Cookie. Мы можем исправить это, добавив следующие параметры в параметры ajax, как указано в этом ответе:

xhrFields: {
   withCredentials: true
},

Или, если вы работаете с angular, отправьте {withCredentials: true} как

$http({withCredentials: true, ...}).get(...), как указано в этом ответе.

На стороне сервера установите этот заголовок:

res.header("Access-Control-Allow-Credentials", 'true');

Если вы добавите это, Chrome больше не позволит вам использовать подстановочный знак * в заголовке Access-Control-Allow-Origin. Вы также должны установить его для определенных разрешенных доменов.

res.header("Access-Control-Allow-Origin", "allowed domains");
person T J    schedule 26.11.2015

Разве ты не должен

res.session.save(); // add this line
res.json({ status: 'success' }); // or just res.send({status:success});

?

Кроме того, я рекомендую вам использовать passport модуль со стратегией passport-local для этих целей, чтобы вам не приходилось беспокоиться о том, почему ваши сеансы не работают. Однажды это сэкономило мне много времени.

person kaytrance    schedule 25.11.2015