我有一个在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);
});
}
});
这是我测试的方式,以及日志变得重复的特定用例:
使用Web浏览器1(例如Firefox)在登录时加载页面;输出:
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
通过page / browser1(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]}
在浏览器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=]
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 authorization
并且callback
,返回真或假,如节点是伸手io.on('connection')
和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。
这是一个可能的选择:
https://github.com/LearnBoost/Socket.IO/wiki/Configuring-
Socket.IO
问题内容: 我可以不用密码就可以将Node应用程序连接到Redis,但是添加密码后,我无所事事。 这是我的代码,摘自一个示例: 在运行应用程序时,我得到以下堆栈跟踪: 生成该行的行是最后一个-如果我注释掉尝试设置RedisStore的尝试,则不会出现任何错误。 我确定密码正确(我可以在redis- cli中进行验证,如果我将密码更改为错误,则可以验证auth回调不会触发)。如果我删除密码并注释掉两
问题内容: 我一直在学习redis和node.js。我有两个问题,找不到令人满意的答案。 我的第一个问题是关于在node.js中重用Redis客户端。我找到了这个问题和答案:如何在socket.io中重用Redis连接,但还不足以让我满意。 现在,如果我在连接事件中创建redis客户端,它将为每个连接生成。因此,如果我有2万个并发用户,那么将有2万个Redis客户端。 如果我将其放在连接事件之外,
我想知道socket.io身份验证的最佳实践是什么。 Alice发出事件'message',参数包括Bobs、唯一标识符等。Bob在监听Socket.on('message')事件时接收消息。
问题内容: 我正在尝试在Node.js中使用Socket.IO,并试图允许服务器为每个Socket.IO客户端赋予一个身份。由于套接字代码不在http服务器代码的范围内,因此无法轻松访问已发送的请求信息,因此我假设在连接期间需要将其发送出去。什么是最好的方法 1)将有关谁通过Socket.IO连接到服务器的信息 2)验证他们说的是谁(如果正在使事情变得更容易,我目前正在使用Express) 问题答
问题内容: 是否存在node.js的现有用户身份验证库?特别是,我正在寻找可以对用户进行密码身份验证的东西(使用自定义后端身份验证数据库),并将该用户与会话相关联。 在编写身份验证库之前,我认为我会看看人们是否知道现有的库。通过Google搜索找不到任何明显的内容。 -Shreyas 问题答案: 看起来连接中间件的connect-auth插件正是我所需要的:http : //wiki.github
问题内容: 我使用password.js在我的nodejs + express.js应用程序上处理身份验证。我设置了一个LocalStrategy以从mongodb吸引用户 我的问题是, 当我重新启动节点服务器时 , 用户必须重新进行身份验证 。这是一个问题,因为我正在积极开发它,并且不想在每次重新启动时都登录…(+我使用节点管理器) 这是我的应用设置: 和会话序列化设置: 我尝试使用connec