3

我正在尝试使用 socket.io 实现身份验证和会话。

经过大量研究1,我设置了以下使用 express 和 express-session 的工具。

问题是,express 和 socket.io 连接似乎有不同的会话,因为id我得到的是不同的。

此外,我的应用程序的浏览器中没有设置 cookie(这可能是两个组件创建不同会话的原因?)

我正在使用 express 4.13.3express-session1.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对象没有任何属性,但打印出不同的值。也许这来自对象原型链或其他东西。idsession.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建立套接字连接之前访问 express 路由以进行测试。

所以我想知道为什么客户端没有设置 cookie,为什么 express 和 socket 请求创建了不同的会话..?我在这里想念什么..?


1代码主要基于:


PS:我想做的是,当套接字客户端重新连接时,我需要将他放回他所在的位置,并提供会话详细信息。我真的不想与 express 共享会话,但 express 中间件是我遇到的使用 socket.io 实现会话的唯一方法。

4

2 回答 2

7

该问题与 express 或 socket.io 无关。问题是,我从 express 和 socket.io 服务器以外的本地服务器加载项目。

所以这是一个跨域的ajax请求,在这种情况下一些浏览器拒绝处理Set-Cookieheader。我们可以通过在此答案中提到的 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");
于 2015-11-26T05:19:20.477 回答
-1

你不应该

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

?

而且,我有点建议您为此目的使用带有策略的passport 模块passport-local,这样您就不必担心为什么您的会话不起作用。一旦它为我节省了很多时间。

于 2015-11-25T13:10:38.477 回答