如何保护用户在 socket.io 和Node js上的"channel"?



我创建了一个社交网络,发展得很好。我想使用socket.io和node实现实时通知。

嗯。已经做到了,而且是这样。。。

用户A向用户B发送消息,然后节点服务器通过发送通知写入对用户B吼叫的通道。

每个用户在浏览网站时都会连接到自己的频道:

<script type="text/javascript">
var socket = io.connect( 'https://notificationserver.com/' );
socket.on( 'notifications_USERID', function( data ) {
    var data_type=data.data_type;
    //sample
    if(data_type=="message"){
      $.notify("You got a new message", "success");
    }
});
</script>

很简单。用户的通道是notifications_USERID。

这当然不安全。如果有人将html页面保存到它的计算机上并加载它,他们就会收到特定的用户通知。

那么,只有真正的登录用户才能安全访问它,最好的方法是什么呢?

更新

我使用curl将数据发送到节点服务器,如下所示:

 $curl = curl_init();                                        
 $data = json_encode(array("receiverid"=>$uid,"secret"=>"SOMESECRET"));                                                         
 curl_setopt($curl, CURLOPT_URL, "http://notificationserver:1334");
 curl_setopt($curl, CURLOPT_POST, 1);
 curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
 curl_setopt($curl, CURLOPT_TIMEOUT, 1);
 curl_setopt($curl,CURLOPT_CONNECTTIMEOUT,1);
 curl_exec($curl);

这是我的应用程序JS文件

var http = require('http'),
    fs = require('fs');
var key="SOMESECRET";
var app = http.createServer(function (request, response) {
    if (request.method == 'POST') {
        var body = '';
        var jsonString = '';
        request.on('data', function (data) {
            body += data;
            jsonString += data;
            if (body.length > 1e6) { 
                request.connection.destroy();
            }
        });
        request.on('end', function () {

             var json_data=JSON.parse(jsonString);
             var receiverid=json_data.receiverid;
             var secret=json_data.secret;

             if(secret==key){
                NewMessageNotify(receiverid); 
             }else{
                request.connection.destroy(); 
             }

        });
    }else{
        response.writeHead(200, {'Content-Type': 'text/html'});
        response.write("<h1>Hello World</h1>");
        response.end();
    }
}).listen(1334);
var io = require('socket.io').listen(app);
function NewMessageNotify(receiverid){
    io.sockets.emit("notifications_"+receiverid,{ data_type: "message" }); 
}

您有一个破碎的安全模型,并将所有用户的所有消息发送给每个人(实际上是在广播它们)。只要稍微调整一下客户端javascript,或者从任何计算机运行一段流氓javascript,以比socket.io稍低的级别连接,任何用户都可以监听所有消息。

在此代码中:

function NewMessageNotify(receiverid){
    io.sockets.emit("notifications_"+receiverid,{ data_type: "message" }); 
}

io.sockets.emit()部分将该消息发送到所有打开的套接字。那根本不是你想做的。您希望"Bob"的消息只发送到Bob的套接字。然后,除了向你证明自己是Bob的人之外,其他人都没有机会查看它们。

因此,要只将Bob的消息发送到Bob的套接字,您必须在Bob和他的套接字之间保持一些相关性。通常,这将作为身份验证过程的一部分来完成(您没有显示),因此,当有人连接到您的服务器并成功通过Bob身份验证时,您将记录Bob和特定套接字之间的链接。我不太了解socket.io,不知道它是否有一个内置的机制来维护这个链接,但我知道你可以用几种方法来做到这一点。

  1. 如果你不打算拥有数以亿计的用户,你可以使用聊天室功能。当Bob使用唯一的用户ID登录时,你可以用他的名字加入他的聊天室。然后,当你想给鲍勃发消息时,你只需在聊天室里播放他的名字。他将是该聊天室的唯一监听器,因为你的服务器永远不会让其他人进入。这有点扭曲了聊天室的设计目的,但由于你的userId必须是唯一的,它允许你使用用户名作为聊天室名称和套接字。io会自动为你保留名称和套接字之间的链接。

  2. 你可以创建自己的用户和socket.id的数据结构。当给定的用户连接到你的服务器并成功通过身份验证时,你只需将他们添加到你的数据结构中。当它们断开连接时,您可以将它们移除。

样本代码:

var users = {};
io.on('connection', function(socket){
    // new socket connection here
    // authenticate the user
    // after successful login and authentication, add them to our data structure
    var username = "...";
    users[username] = socket;

    socket.on('disconnect', function() {
        // remove them from our data structure
        delete users[username];
    });
});

然后,向特定用户发送数据:

function NewMessageNotify(receiverid){
    // get socket for that specific user
    var socket = users[receiverid];
    if (socket) {
        socket.emit("notifications",{ data_type: "message" }); 
    }
}

相关内容

  • 没有找到相关文章

最新更新