Redis,Node.js和Socket.io:跨服务器authentication和node.js理解

我得到了一个运行在Rails和Backbone.js上的单页面应用程序。 我通过Redis使用Node.js将数据推送和同步到客户端。 我想了解,保护和优化套接字通信。

用console.log写时,我看到一些日志行( console.log('Redis connection on ..') )正在重复(见下文)。

有谁能解释我为什么? 有没有一些特定的Node.js行为,我不明白,通过我的代码实现?

这是我的Node.js代码:

 var io = require('socket.io').listen(3003); var redis = require('redis'); var cookie = require("cookie"); var redis_subs = redis.createClient(6379, "localhost"); var redis_auth = redis.createClient(6379, "localhost"); var authenticated = false; var authentication_status = function (status) { if (status === true) { console.log('Authentication status is true.'); } else { console.log('Authentication status is false.'); } authenticated = status; }; redis_subs.subscribe('application_channel'); io.configure(function () { io.set('authorization', function (data, callback) { console.log('Cross authentication...'); if (data.headers.cookie) { data.cookie = cookie.parse(data.headers.cookie); data.sessionID = data.cookie['_validation_token_key']; redis_auth.hget(["sessionStore", data.sessionID], function (err, session) { if (err || !session) { console.log('Socket.io authorization say false'); return callback(authentication_status(false), false); } else { data.session = JSON.parse(session); console.log('Socket.io authorization say true'); return callback(authentication_status(true), true); } }); } else { console.log('Socket.io authorization say false'); return callback(authentication_status(false), false); } }); }); io.on('connection', function(socket){ if (socket.handshake.session) { var user_socket_channel = socket.handshake.session['user_socket_channel'] redis_subs.on('message', function(redis_channel, rawdata) { console.log('Redis connection on '+redis_channel); console.log('Handshaked Session, authenticated user. All channels allowed.'); var data = JSON.parse(rawdata); if (data.channel) { var socket_channel = data.channel; } else { var socket_channel = user_socket_channel; } var rails_data = data.data; console.log('Socket.io emiting on ['+socket_channel+']') socket.emit(socket_channel, rails_data); }); } else { redis_subs.on('message', function(redis_channel, rawdata) { console.log('Redis connection on '+redis_channel); console.log('No handshaked Session, unauthenticated user. Public channels allowed.'); var data = JSON.parse(rawdata); var rails_data = data.data; console.log('Socket.io emiting on [public]') socket.emit('public', rails_data); }); } }); 

这是我testing它的方式,以及日志重复的具体用例:

使用网页浏览器1(例如Firefox)login时加载页面; 输出:

  info - socket.io started Cross authentication... Socket.io authorization say true Authentication status is true. debug - authorized info - handshake authorized bJxm_IcWl2mKZT4Ed-kV debug - setting request GET /socket.io/1/websocket/bJxm_IcWl2mKZT4Ed-kV debug - set heartbeat interval for client bJxm_IcWl2mKZT4Ed-kV debug - client authorized for debug - websocket writing 1:: 

加载浏览器2注销的相同页面(例如:Chrome)

 Cross authentication... Socket.io authorization say false Authentication status is false. debug - authorized info - handshake unauthorized 

通过页面/浏览器1(Firefox)发送一些数据 – > Rails – > Redis,输出:

 Redis connection on application_channel Handshaked Session, authenticated user. All channels allowed. Socket.io emiting on [hLTYXuvP+13aQlIT9CZiYc1i9eg=] debug - websocket writing 5:::{"name":"hLTYXuvP+13aQlIT9CZiYc1i9eg=","args":[null]} 

重新加载browser2上的页面(Chrome,注销),仍然输出

 Cross authentication... Socket.io authorization say false Authentication status is false. debug - authorized info - handshake unauthorized 

在browser1 / Firefox上重新加载页面,并通过页面和Rails向Redis推送更多的数据,输出:

 Redis connection on application_channel Handshaked Session, authenticated user. All channels allowed. Socket.io emiting on [hLTYXuvP+13aQlIT9CZiYc1i9eg=] Redis connection on application_channel Handshaked Session, authenticated user. All channels allowed. Socket.io emiting on [hLTYXuvP+13aQlIT9CZiYc1i9eg=] debug - websocket writing 5:::{"name":"hLTYXuvP+13aQlIT9CZiYc1i9eg=","args":[null]} 

正如您所看到的,事件被复制,Redis侦听器现在捕获两个连接; 每次我将重新加载page1 / Firefox,它会复制一次(3,4,5 …)。

我不明白这个行为。 我错过了什么? 顺便说一下,正如你所看到的,我不太了解Socket.io configure的目标, set authorizationcallback ,返回true或false,当Node到达io.on('connection')和Redis监听器无论如何。

好的,我已经得到了答案。 我很难搞清楚,一直在找几个小时。

以下是允许我使其工作的相关主题(答案和评论):

如何删除“消息”侦听器上的Redis

这是我的代码:

 io.on('connection', function(client){ console.log('Client id #'+client.id); if (client.handshake.session) { var user_socket_channel = client.handshake.session['user_socket_channel']; } var redis_listener = function(redis_channel, rawdata) { console.log('Redis connection on '+redis_channel); var data = JSON.parse(rawdata); if (data.channel) { var socket_channel = data.channel; } else { if (user_socket_channel) { var socket_channel = user_socket_channel; } else { var socket_channel = 'public' } } var rails_data = data.data; console.log('Socket.io emiting on ['+socket_channel+']'); client.emit(socket_channel, rails_data); }; redis_subs.on('message', redis_listener); client.on('disconnect', function(){ console.log('Client disconnect, removing redis listener..'); redis_subs.removeListener('message', redis_listener); }); }); 

根据上下文,您需要在io.client.disconnect事件上调用redis.removeListener。

这是一个可能的select:

https://github.com/LearnBoost/Socket.IO/wiki/Configuring-Socket.IO

顺便说一下,这个相关的问题似乎与一个准确的答案类似,但实际上并没有(没有工作)。 此外,请看高亮显示的评论:

如何在socket.io中重用redis连接?