我尝试使用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
页面上提供服务。在我的情况下,我在本地提供了文件。
我已经在某处读过,在这种情况下,我必须在建立socket.io连接之前发送http
请求。
socket.io.js
客户端库是由express和socket.io(<script src="http://127.0.0.1/socket.io/socket.io.js"></script>
)共享的同一服务器提供的,除此之外,我还点击了快速路由{{ 1}}用于在建立套接字连接之前进行测试。
所以我想知道为什么客户端没有设置cookie,以及为什么express和socket请求创建了不同的会话..?我在这里想念的是什么..?
1 代码主要基于:
P.S:我想要做的是,当一个套接字客户端重新连接时,我需要让他回到他所处的会话细节。我并不是真的想与express分享会话,但是表达中间件是我实现socket.io会话的唯一途径。答案 0 :(得分:5)
问题与express或socket.io无关。
问题在于,我是从Express和socket.io服务器以外的本地服务器加载项目。
所以它是一个跨域的ajax请求,在这种情况下,某些浏览器拒绝处理Set-Cookie
标头。
我们可以通过添加
来解决这个问题xhrFields: {
withCredentials: true
},
在此answer
中的ajax选项中或者如果您正在使用角色,请发送{withCredentials: true}
$http({withCredentials: true, ...}).get(...)
,如answer中所述。
在服务器端,设置此标头:
res.header("Access-Control-Allow-Credentials", 'true');
如果您添加,Chrome将不再允许您在*
标题中使用通配符Access-Control-Allow-Origin
。
您还应将其设置为特定的允许域。
res.header("Access-Control-Allow-Origin", "allowed domains");
答案 1 :(得分:-1)
你不应该
function toss()
{
//If both coins come up HEADS or TAILS, the player wins. Otherwise the player loses.
//random number generator 0 to 1
//change image source using getElementById to div id coinA and coinB
//if random numbers same, set resultText innerHTML to "You Win"
//var x = Math.floor(Math.random() * (1 - 0 + 1)) + 0;
var x = Math.floor(Math.random()*2);
var coinImg = document.querySelectorAll("#coinA, #coinB");
if (x == 0){
coinImg.src = "images/coin0.png";
document.getElementById("resultText").innerHTML = "You Lost";
} else {
coinImg.src = "images/coin1.png";
document.getElementById("resultText").innerHTML = "You Win";
}
}
Here is the HTML:
<img src="images/coin1.png" id="coinA" width="100" height="100" alt="coin">
<img src="images/coin1.png" id="coinB" width="100" height="100" alt="coin">
<button type="button" onclick="toss()">Go</button>
<div id="resultText">Press GO to play!</div>
此外,我建议您将res.session.save(); // add this line
res.json({ status: 'success' }); // or just res.send({status:success});
module与passport
策略用于此目的,这样您就不必费心为什么会话不起作用了。一旦它为我节省了很多的时间。