복붙노트

[REDIS] 레디 스, Node.js를, 그리고 Socket.io : 크로스 서버 인증과 이해 Node.js를

REDIS

레디 스, Node.js를, 그리고 Socket.io : 크로스 서버 인증과 이해 Node.js를

나는 레일과 Backbone.js에서 실행되는 단일 페이지 응용 프로그램을 얻었다. 나는 클라이언트에 동기화 데이터를 밀어하는 레디 스를 통해 Node.js를 사용하고 있습니다. 나는 안전하고 최적화 소켓 통신을 이해하려고 노력하고 있습니다.

CONSOLE.LOG에 쓸 때 나는 일부 로그 라인 (을 console.log ( '에서 레디 스 연결 ..')) (우는 소리 참조) 중복을 받고 참조하십시오.

사람이 왜 나를 설명 할 수 있습니까? 내 코드의 구현을 통해 내가 이해하지 못하는거야 행동, 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);
      });
    }
});

여기에 내가 그것을 테스트하고있는 방법과 로그 중복을 받고 특정 사용 사례는 다음과 같습니다

존재가 로그인 한 상태에서 페이지를로드, 웹 browser1으로 (예를 들어, 파이어 폭스); 산출:

   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::

같은 페이지를로드하는 로그 아웃되는 browser2으로 (예를 들어, 크롬)

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

일부 페이지에서 데이터를 전송 / browser1 (파이어 폭스) -> 레일 -> 레디 스, 출력 :

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에 페이지를 다시로드, 여전히 출력

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

browser1 / 파이어 폭스에 페이지를 다시로드하고 페이지 및 레일 출력을 통해 레디 스에 좀 더 많은 데이터를 밀어 :

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

당신이 볼 수 있듯이, 이벤트는 중복있어, 그리고 레디 스 리스너 이제 두 개의 연결을 잡을; 내가 PAGE1 다시로드거야 때마다 / 파이어 폭스, 그것은 (... 3,4,5)이 한 번 더 복제됩니다.

나는이 행동을 이해하지 않습니다. 나는 무엇을 놓치고? 당신이 볼 수있는 노드가 io.on ( '연결')와 레디 스 청취자에게 도달 될 때 그런데, 정말, Socket.io의 구성, 설정 권한 부여 및 콜백, true 또는 false를 반환의 목표 중 하나를 이해하지 못하는 어쨌든.

해결법

  1. ==============================

    1.좋아, 나는 나의 대답을 가지고있다. 나는 힘든 시간을 알아내는, 시간을 찾고 있었다 ...

    좋아, 나는 나의 대답을 가지고있다. 나는 힘든 시간을 알아내는, 시간을 찾고 있었다 ...

    여기에 내가 그것을 일 (답변 및 댓글) 할 수 관련 주제는 다음과 같습니다

    '메시지'청취자에 레디 스를 제거하는 방법

    그리고 여기 내 코드는 :

    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

    그런데이 관련 질문은 정확한 답과 비슷한 일을 보이지만 (작동하지 않았다) 사실이 아니다. 또한 더 강조 코멘트를 보면 :

    어떻게 socket.io에서 레디 스 연결을 재사용?

  2. from https://stackoverflow.com/questions/21767658/redis-node-js-and-socket-io-cross-server-authentication-and-node-js-understa by cc-by-sa and MIT license