如何使用Socket.IO强制一个用户的最大连接数?

时间:2015-04-19 06:09:01

标签: node.js express socket.io spam-prevention rate-limiting

我有一个非常简单的Socket.IO群聊系统(this one)。我想阻止人们使用JavaScript技巧从浏览器发送垃圾邮件。这是一次我公布网站的问题。

我应该采取什么措施来防止这种情况发生?我想计算一个浏览器的连接数,它超过了一个阈值,我想删除所有连接。我应该使用IP地址吗? socket.id对用户来说是唯一的吗?我该怎么办?

如果您想查看Socket.IO代码,请参阅highlighted code here

1 个答案:

答案 0 :(得分:0)

我在多人游戏中遇到同样的问题,以防止用户通过多个标签播放。

客户端可以通过多种方式拒绝识别,并使用多个ID登录。但是,由于您只想在同一浏览器中阻止用户,因此相对容易。

首先,使用passport进行身份验证,并使用passport.socketio从Express中间件“桥接”req.usersocket.request.user

接下来,由于io.on('connection')将始终触发来自客户端的最新套接字请求,因此您可以将其用作“过期”仍然从同一客户端连接的任何旧套接字的机会。这就是socket.request.user可以派上用场来识别它是否是同一个用户客户端的地方。像这样:

io.on('connection', function(socket) {
    var user = socket.request.user;

    // Suppose this user has connected from another tab,
    // then the socket.id from current tab will be
    // different from [see *1]

    var current_socket_id = socket.id;
    var last_socket_id = user.latest_socket_id;

    if (last_socket_id) {
        // If the user has an existing socket connection
        // from the previously opened tab,

        // Send disconnection request to the previous socket
        io.to(last_socket_id).emit('disconnect');
        // client-side will look like
        // socket.on('disconnect', function(){
        //     alert('You connected from a new tab, this tab will close now.')
        //     window.close();
        // });
    }

    // [*1] current socket.id is stored in the user
    user.latest_socket_id = socket.id;
    user.save();
});