我创建了一个非常好的社交网络。我想使用socket.io和node实现实时通知。
好。已经做到了,它以这种方式工作......
USER A向USER B发送消息,而不是通过emit通知节点服务器写入用户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);
这是我的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" });
}
答案 0 :(得分:3)
您的安全模型已损坏,并且正在向所有人发送所有用户的所有消息(您实际上是在广播它们)。通过略微调整客户端javascript或从任何计算机运行的流氓javascript片段,以比socket.io
略低的水平挂钩,任何用户都可以收听所有消息。
在此代码中:
function NewMessageNotify(receiverid){
io.sockets.emit("notifications_"+receiverid,{ data_type: "message" });
}
io.sockets.emit()
部分将该消息发送到所有打开的套接字。这根本不是你想要做的。你想要消息&#34; Bob&#34;只被发送到鲍勃的套接字。然后,没有其他人有机会查看它们,除非你以Bob身份认证自己。
因此,要将Bob的消息仅发送给Bob的套接字,您必须在Bob和他的套接字之间保持一些关联。通常,这将作为身份验证过程的一部分(您不会显示)完成,因此当有人与您的服务器建立socket.io连接并成功通过Bob身份验证时,您将记录Bob和a之间的链接特定插座。我不太了解socket.io,知道它是否有内置的机制来维护该链接,但我知道有几种方法可以做到。
如果您没有数以万计的用户,您可以使用聊天室功能。当Bob使用唯一的用户ID登录时,您可以将他与他的名字一起加入聊天室。然后,当你想给Bob发送一条消息时,你只需用他的名字向聊天室广播。他将成为该聊天室的唯一监听者,因为您的服务器永远不会让其他任何人进入它。这稍微违背了聊天室的设计,但由于你的userIds必须是唯一的,它允许你使用用户名作为聊天室名称,socket.io将自动为你保留名称和套接字之间的链接。
您可以创建自己的用户和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" });
}
}