2014-09-29 31 views
1

我创建了一个社交网络,发展得非常好。我想使用socket.io和节点实现实时通知。如何在socket.io和node js上保护用户的“通道”?

好吧。已经做了,而且它以这种方式工作...

用户A发送消息给用户B,比节点服务器通过EMIT通知写入该bellongs到用户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页面保存到它的计算机并加载它,他们将获得特定的用户通知。

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

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

THIS IS MY APP.JS FILE

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

你是如何发送消息:

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

然后将数据发送给特定的用户?我们可以看到这些代码吗?我认为你会认证一个连接用户,然后跟踪哪个socket.id连接到哪个认证的人。然后,当你想发送一条消息给那个人时,你只会将它发送给被认证为他们的套接字。您在技术上为每个用户使用自定义消息名称的方案允许任何人收听所有消息。 – jfriend00 2014-09-29 21:20:49

+0

如果您想充分利用StackOverflow,请在发布您的问题20-30分钟之内回来查看人们是否需要一些帮助来理解您的问题。绝大多数可能会帮助你的人会在头30-60分钟看到你的问题。如果它不完全清楚,而且你没有回答被问到的问题,那么人们就会继续前进,你会错过帮助。这个地方不像24小时后发布和回来的典型论坛。如果你的问题不清楚,它会在那之前关闭。 – jfriend00 2014-09-29 22:31:26

+0

你好。我,m使用php写入节点服务器。我也发送某种密码,服务器只有在“密码”匹配的情况下才会通知用户。这样我可以避免不必要的发布。 – SocialDub 2014-09-29 22:45:54

回答

3

你有一个破碎的安全模型,并将所有用户的所有消息发送给每个人(你基本上是在广播它们)。稍微调整一下客户端JavaScript或从任何计算机上运行的JavaScript的流氓片段,以低于socket.io的级别,任何用户都可以收听所有消息。

在此代码:

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

io.sockets.emit()部分发送该消息到所有打开的套接字。这不是你想要做的。你想让“Bob”的消息只被发送到Bob的套接字。然后,没有人有机会查看他们,除非你向Bob证实了你的身份。

因此,要将Bob的消息仅发送给Bob的套接字,您必须保持Bob与其套接字之间的某种关联。通常,这将作为身份验证过程的一部分完成(您不会显示),所以当有人与您的服务器建立socket.io连接并成功通过身份验证时,您会记录Bob与特定套接字之间的链接。我不知道socket.io是否足够知道它是否具有维护该链接的内置机制,但我知道有几种方法可以实现。

  1. 如果你不会有无数的用户,你可以使用聊天室的功能。当Bob用一个唯一的用户ID登录时,你可以用他的名字将他加入聊天室。然后,当你想给Bob发送一条消息时,你只需要以他的名字向聊天室进行广播。他将是聊天室的唯一监听者,因为你的服务器永远不会让其他人加入。这只是对聊天室设计的颠倒,但由于您的用户ID必须是唯一的,因此您可以使用用户名作为聊天室名称,并且socket.io会自动为您保留名称和套接字之间的链接。

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

示例代码:从服务器

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