MEANJS:SocketIO中的安全性

情况

我在我的MEAN.JS应用程序中使用库的SocketIO 。

在NodeJS服务器控制器中

var socketio = req.app.get('socketio'); socketio.sockets.emit('article.created.'+req.user._id, data); 

在AngularJS客户端控制器中

  //Creating listener Socket.on('article.created.'+Authentication.user._id, callback); //Destroy Listener $scope.$on('$destroy',function(){ Socket.removeListener('article.created.'+Authentication.user._id, callback); }); 

奥基。 效果很好…

问题

如果一个人(黑客或其他人)获得了用户id ,他可以在另一个应用程序中在同一个频道中创build一个监听器,他可以监视发送给用户的所有数据。 例如所有的通知…

  • 我怎么能做同样的事情,但更安全?

谢谢!

前段时间我偶然发现了同样的问题。 这是我的解决scheme(稍作修改 – 用于生产)。

我们将使用Socket.IO namespaces为每个用户创build私人空间 。 然后我们可以发送消息(服务器端)到特定的房间 。 在我们的例子中 – 只有特定的用户可以接收它们。

但是要为每个连接的用户创build私人空间 ,我们必须首先validation他们的身份。 我们将使用一个简单的身份validation中间件 , 自1.0版本以来 , 由Socket.IO支持 。

1.authentication中间件

自1.0版本以来, Socket.IO支持中间件。 我们将用它来:

  1. validation连接用户标识,使用JSON Web Token (请参阅jwt-simple )他发送我们作为查询参数。 (请注意,这只是一个例子,还有很多其他方法可以做到这一点。)
  2. 将其用户标识 (从令牌读取)保存在socket.io连接实例中,供以后使用(在步骤2中)。

服务器端代码示例:

 var io = socketio.listen(server); // initialize the listener io.use(function(socket, next) { var handshake = socket.request; var decoded; try { decoded = jwt.decode(handshake.query().accessToken, tokenSecret); } catch (err) { console.error(err); next(new Error('Invalid token!')); } if (decoded) { // everything went fine - save userId as property of given connection instance socket.userId = decoded.userId; // save user id we just got from the token, to be used later next(); } else { // invalid token - terminate the connection next(new Error('Invalid token!')); } }); 

下面是如何在初始化连接时提供令牌的示例,客户端:

 socket = io("http://stackoverflow.com/", { query: 'accessToken=' + accessToken }); 

2.命名空间

Socket.io命名空间使我们能够为每个连接的用户创build私人空间 。 然后,我们可以发送消息到特定的房间 (所以只有用户可以接收它们,而不是每个连接的客户端)。

在之前的步骤中,我们确保:

  1. 只有通过身份validation的用户才能连接到我们的Socket.IO接口。
  2. 对于每个连接的客户端,我们将用户标识保存为socket.io连接实例( socket.userId )的属性。

剩下要做的就是在每个连接上join适当的空间 ,名字等于新连接的客户端的用户ID。

 io.on('connection', function(socket){ socket.join(socket.userId); // "userId" saved during authentication // ... }); 

现在,我们可以发出只有这个用户才会收到的有针对性的消息:

 io.in(req.user._id).emit('article.created', data); // we can safely drop req.user._id from event name itself