我正在使用socket.io通信开发一个项目。基本结构是我已经设置了一个需要身份验证的自定义命名空间。我通过JWT(Json Web Tokens)提供身份验证。
我的问题如下。身份验证作为命名空间中间件提供,如果失败,则使用next
调用套接字中间件函数的Error
回调。如果我在自定义命名空间内实现身份验证,一切正常。例如:
var io = require('socket.io')();
io
.of('/somePath')
.use(function authenticate(socket,next){
if (authenticate.(socket)){
var err = new Error('UnauthorizedError');
next(err);
}
else{
next();
}
})
.on('connection',function(){
console.log('Socket successfully connected to custom namespace /somePath');
});
io.listen(3000);
//Client Code
var clientIO = require('socket.io-client');
var client = clientIO('http://localhost:3000/somePath');
client.on('connect',function(){
console.log('Connected to host');
});
client.on('error',function(err){
console.error(err);
});
客户端通常从命名空间中间件收到错误。
然而如果我想拥有更多共享相同身份验证逻辑的自定义命名空间,我必须分别为每个人实现逻辑。例如:
var io = require('socket.io')();
io
.of('/somePath')
.use(function authenticate(socket,next){
if (authenticate.(socket)){
var err = new Error('UnauthorizedError');
next(err);
}
else{
next();
}
})
.on('connection',function(){
console.log('Socket successfully connected to custom namespce /somePath');
});
io
.of('/someOtherPath')
.use(function authenticate(socket,next){
if (authenticate.(socket)){
var err = new Error('UnauthorizedError');
next(err);
}
else{
next();
}
})
.on('connection',function(){
console.log('Socket successfully connected to custom namespce /someOtherPath');
});
io.listen(3000);
//Client Code
var clientIO = require('socket.io-client');
var client = clientIO('http://localhost:3000/somePath');
client.on('connect',function(){
console.log('Connected to host');
});
client.on('error',function(err){
console.error(err);
});
这又一次有效。这里的身份验证问题是这样,我们只为自定义命名空间设置了身份验证。默认命名空间/
仍然不受保护,客户端可以在没有任何凭据的情况下连接到它。
所以,我想,我应该使用身份验证机制作为主命名空间的中间件,以便它必须通过它才能继续进行自定义命名空间连接。例如:
//Server Code
var io = require('socket.io')();
io.use(function(socket,next){
var err = new Error('I want an error');
next(err);
})
io.on('connection', function(socket){
console.log('Connected on main namespace');
});
io.listen(3000);
//Namespace
io
//First Path
.of('somePath')
.on('connection',function(){
console.log('Socket successfully connected to custom namespce /somePath');
});
//Second path
.of('someOtherPath')
.on('connection',function(){
console.log('Socket successfully connected to custom namespce /someOtherPath');
})
//Client Code
var clientIO = require('socket.io-client');
var client = clientIO('http://localhost:3000/somePath');
client.on('connect',function(){
console.log('Connected to host');
});
client.on('error',function(err){
console.error(err);
});
请注意,中间件未在主命名空间中设置,而不在其他两个自定义命名空间上设置
此方法无需身份验证即可解决与主命名空间问题的连接,但会产生其他问题!。从socket.io连接的工作方式到自定义命名空间,它们首先连接到主命名空间/
,然后连接到自定义提供的命名空间(在本例中为/somePath
,/someOtherPath
。这样,套接字客户端(自定义命名空间)在首次尝试连接到主命名空间时遇到错误,并且不会继续尝试连接到我们希望它连接到的自定义命名空间。但是,在客户端上我们在自定义命名空间上设置了错误处理程序,因此错误在主命名空间通道上传输,而不是由正在侦听自定义命名空间的客户端错误处理程序捕获,而自定义命名空间又从未连接过主命名空间连接失败。
总之,通过在主命名空间设置中间件以防止未经授权的使用,尝试连接到自定义命名空间的客户端不会收到身份验证错误。
关于如何规避这一点的任何想法?
由于