2015-11-25 60 views
0

我试图使用socket.io实现身份验证和会话。express-session在与socket.io配合使用时未设置会话cookie

经过大量的研究,我设置了以下使用快速和快速会话。

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

此外,

我用快递4.13.3快递会话1.12.1和socket.io 1.3.7没有Cookie是从我的应用程序的浏览器设置(这可能是为什么这两个组件创建不同的会话?)。

下面是我已经设置了服务器端代码:

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

下面是在控制台输出:

enter image description here

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

enter image description here

我甚至看到困惑,在控制台登录时session对象没有任何id财产,但session.id打印不同的值。也许这是来自对象原型链或其他东西。

我可以想到的与我的代码和教程有唯一的区别是,他们都服务于同一个快递服务器的index.html页面。就我而言,我在本地拥有该文件。

我读过的地方,在这种情况下,我必须发送一个http请求来建立socket.io连接之前表示。

socket.io.js客户端库是从一个由快递和socket.io(<script src="http://127.0.0.1/socket.io/socket.io.js"></script>)共享同一台服务器提供服务,除了这个我也打在建立套接字连接之前测试的目的明确的路线/login

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


的代码主要是基于:


PS:我想要做的是,当套接字客户端重新连接,我需要把他放回他的地方与会议的细节。我不想用express来分享会话,但表达中间件是我用socket.io实现会话的唯一方法。

回答

5

该问题与express或socket.io无关。

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

所以这是一个跨域ajax请求,在这种情况下,一些浏览器拒绝处理Set-Cookie标头。

我们可以通过添加

xhrFields: { 
    withCredentials: true 
}, 
在阿贾克斯选项

如mentined在这个answer

或者如果你有角工作,派出{withCredentials: true}

$http({withCredentials: true, ...}).get(...)中提到解决这个问题这answer

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

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

如果添加了镀铬不会让你在Access-Control-Allow-Origin头使用通配符*了。

您还应该将其设置为特定允许的域。

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

你不应该

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

此外,我建议您使用passportmodulepassport-local战略为此目的,所以你不必打扰为什么你的会议不工作。一旦它节省了我很多的时间。