与 socket.io 一起使用时,express-session 未设置会话 cookie [英] express-session isn't setting session cookie while using with socket.io

查看:54
本文介绍了与 socket.io 一起使用时,express-session 未设置会话 cookie的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to implement authentication and sessions with socket.io.

经过大量研究1,我设置了以下使用express和express-session的方法.

After a lot of research 1, I've set up the following which makes use of express and express-session.

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

The issue is that, express and socket.io connections seems to be having different sessions since the id I'm getting is different.

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

Also, no cookie is set in the browser from my application (which is possibly why both components are creating different sessions?)

我正在使用 express 4.13.3 express-session 1.12.1 和 socket.io 1.3.7.

I'm using express 4.13.3 express-session 1.12.1 and socket.io 1.3.7.

以下是我设置的服务器端代码:

Below is the server side code that I've set up:

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
    });
  });
});

以及用于测试目的的客户端代码:

and the code at client for testing purpose:

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

控制台输出如下:

这是浏览器中的资源部分:

and this is the resources section in browser:

我什至很困惑看到 session 对象在登录控制台时没有任何 id 属性,但是 session.id 打印不同的价值观.也许这是来自对象原型链之类的.

I'm even confused seeing that the session object is not having any id property when logged in console, but session.id prints different values. Maybe this is coming from the objects prototype chain or something.

我能想到的与我的代码和教程的唯一区别是,它们都从同一个快速服务器提供 index.html 页面.就我而言,我在本地拥有该文件.

The only difference I can think of with my code and the tutorials out there is that, they are all serving the index.html page from the same express server. In my case I've the file locally.

我在某处读到过,在这种情况下,我必须在建立 socket.io 连接之前发送一个 http 请求来表达.

I've read somewhere that in such cases I must send an http request to express before establishing the socket.io connection.

socket.io.js 客户端库由 express 和 socket.io 共享的同一服务器提供服务(<script src="http://127.0.0.0.1/socket.io/socket.io.js"></script>),除此之外,我还在使用快速路由 /login 进行测试套接字连接建立.

The socket.io.js client side library is served from the same server which is shared by express and socket.io (<script src="http://127.0.0.1/socket.io/socket.io.js"></script>), apart from this I'm also hitting the express route /login for testing purpose before the socket connection is established.

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

So I'm wondering why no cookie is being set in client side, and Why the express and socket requests have created different sessions..? What am I missing here..?

1 代码主要基于:

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

P.S: What I'm trying to do is, when a socket client re-connects, I need to put him back to where he was with the session details. I don't really want to share sessions with express, but express middleware is the only way I've came across to implement sessions with socket.io.

推荐答案

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

The problem had nothing to do with express or socket.io. The issue is that, I was loading the project from a local server other than the express and socket.io server.

所以这是一个跨域ajax请求,在这种情况下,一些浏览器拒绝处理Set-Cookie标头.我们可以通过在 answer 中提到的 ajax 选项中添加以下内容来解决此问题:

So it's a cross domain ajax request, in which case some browsers refuse to handle the Set-Cookie header. We can fix this by adding the following in ajax options as mentioned in this answer:

xhrFields: {
   withCredentials: true
},


或者,如果您正在使用 angular,发送 {withCredentials: true} 就像

$http({withCredentials: true, ...}).get(...) 如本 答案.

在服务器端,设置这个头:

At server side, set this header:

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

如果添加,chrome 将不再允许您在 Access-Control-Allow-Origin 标头中使用通配符 *.您还应该将其设置为特定的允许域.

If you add that, chrome will not allow you to use wildcard * in the Access-Control-Allow-Origin header anymore. You should also set it to specific allowed domains.

res.header("Access-Control-Allow-Origin", "allowed domains");

这篇关于与 socket.io 一起使用时,express-session 未设置会话 cookie的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆