如何在socket.io和node js上保护用户的“通道”?

我创build了一个社交networking,这个networking发展得非常好。 我想使用socket.io和节点实现实时通知。

好。 已经做到了,而且这样工作…

USER发送消息给用户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页面保存到电脑并加载,他们将获得特定的用户通知。

那么,什么才是最好的方法才能使其安全和可访问只有真正的login用户?

UPDATE

我使用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); 

这是我的APP.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或从任何一台计算机上运行的stream氓JavaScript代码,比socket.io稍微低一点,任何用户都可以听到所有的消息。

在这个代码中:

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

io.sockets.emit()部分将该消息发送给所有打开的套接字。 那不是你想要做的。 你想让“Bob”的消息只被发送到Bob的套接字。 然后,没有人有机会去查看他们,除非你是鲍勃authentication的人。

所以,要把鲍勃的信息只发送给鲍勃的套接字,你必须保持鲍勃和他的套接字之间的某种关联。 通常,这将作为身份validation过程的一部分完成(您不会显示),所以当有人与您的服务器build立socket.io连接并成功通过身份validation时,您将loggingBob与特定套接字之间的链接。 我不知道socket.io是否足够知道它是否具有维护该链接的内置机制,但我知道有几种方法可以做到这一点。

  1. 如果你不会有无数的用户,你可以使用聊天室function。 当Bob用一个唯一的用户IDlogin时,你可以把他join他的名字聊天室。 然后,当你想给鲍勃发一条消息的时候,你只需要用他的名字向聊天室进行广播。 他将是聊天室的唯一监听者,因为你的服务器永远不会让其他任何人进入。 这是对聊天室devise的一个颠倒,但是由于你的用户ID必须是唯一的,所以你可以使用用户名作为聊天室名称,而socket.io会自动为你保留名字和套接字之间的链接。

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

示例代码:

 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" }); } }