受到如何与Socket.IO 1.x和Express 4.x共享会话的启发,我以某种“干净”的方式实现了套接字认证,无需使用cookie解析器并从头文件中读取cookie,但很少有项目对我来说仍不清楚。示例使用上一个稳定的socket.io版本1.3.6。
var express = require('express'),
session = require('express-session'),
RedisStore = require('connect-redis')(session),
sessionStore = new RedisStore(),
io = require('socket.io').listen(server);
var sessionMiddleware = session({
store : sessionStore,
secret : "blabla",
cookie : { ... }
});
function socketAuthentication(socket, next) {
var sessionID = socket.request.sessionID;
sessionStore.get(sessionID, function(err, session) {
if(err) { return next(err); }
if(typeof session === "undefined") {
return next( new Error('Session cannot be found') );
}
console.log('Socket authenticated successfully');
next();
});
}
io.of('/abc').use(socketAuthentication).on('connection', function(socket) {
// setup events and stuff
});
io.use(function(socket, next) {
sessionMiddleware(socket.request, socket.request.res, next);
});
app.use(sessionMiddleware);
app.get('/', function(req, res) { res.render('index'); });
server.listen(8080);
index.html
<body>
...
<script src="socket.io/socket.io.js"></script>
<script>
var socket = io('http://localhost:8080/abc');
</script>
</body>
所以io('http://localhost:8080/abc');
从客户端发送初始HTTP握手请求到服务器,从服务器可以收集cookie和许多其他请求信息。所以服务器可以通过socket.request访问该初始请求。
我的第一个问题是为什么握手请求不在快速会话中间件的范围之内?(更普遍地在app.use
中间件范围内?)在某种程度上,我预计这个app.use(sessionMiddleware); 在该初始请求之前触发,然后轻松访问socket.request.session
其次,中间件定义的场景io.use()
会发生什么?仅用于初始HTTP握手请求?它似乎io.use()
是用于套接字相关的东西(问题是:什么东西),而app.use
标准的请求。
我不太清楚为什么在上面的例子中io.use()
被解雇了io.of('/abc').use()
。我故意写下这个命令,io.of('/abc').use()
首先看它是否会起作用,并且工作正常。应该反过来写。
最后,socket.request.res也像一些人在链接问题中指出的,有时会undefined
导致应用程序崩溃,问题可以通过提供空对象而不是socket.request.res来解决
发布于 2018-04-26 16:52:00
为什么握手请求不在快速会话中间件的范围内?
因为socket.io将附加到一个http.Server,它是快速下的图层。它在socket.io 的源代码中的评论中提到。
这是因为第一个请求是一个常规的http请求,用于将请求的无状态http连接升级为完全状态的websocket连接。因此,它必须通过适用于常规http请求的所有逻辑,这没什么意义。
使用io.use()定义的中间件会触发哪些场景?
每当创建一个新的套接字连接时。
所以每次客户端连接时都会调用使用io.use()注册的中间件。然而,一旦客户端连接上了,当从客户端接收到数据包时它就不会被调用。如果连接是在自定义命名空间或主命名空间上启动的,则无关紧要,它将始终被调用。
为什么io.use()在io.of('/ abc')。use()之前触发?
命名空间是socket.io实现的一个细节,事实上,websockets将始终首先命中主命名空间。
为了说明这种情况,请看这段代码和它产生的输出:
var customeNamespace = io.of('/abc');
customeNamespace.use(function(socket, next){
console.log('Use -> /abc');
return next();
});
io.of('/abc').on('connection', function (socket) {
console.log('Connected to namespace!')
});
io.use(function(socket, next){
console.log('Use -> /');
return next();
});
io.on('connection', function (socket) {
console.log('Connected to namespace!')
});
输出:
Use -> /
Main namespace
Use -> /abc
Connected to namespace!
查看socket.io团队添加到他们的文档中的警告:
重要说明:命名空间是Socket.IO协议的实现细节,并且与底层传输的实际URL无关,默认为/socket.io/...。
为什么socket.request.res未定义?
据我所知,它永远不应该是未定义的。这可能与您的具体实施有关。
https://stackoverflow.com/questions/-100008269
复制相似问题