2014-09-29 47 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" }); 
    } 
} 
相關問題