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支持中间件。 我们将用它来:
- validation连接用户标识,使用JSON Web Token (请参阅
jwt-simple
)他发送我们作为查询参数。 (请注意,这只是一个例子,还有很多其他方法可以做到这一点。) - 将其用户标识 (从令牌读取)保存在
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私人空间 。 然后,我们可以发送消息到特定的房间 (所以只有用户可以接收它们,而不是每个连接的客户端)。
在之前的步骤中,我们确保:
- 只有通过身份validation的用户才能连接到我们的Socket.IO接口。
- 对于每个连接的客户端,我们将用户标识保存为
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