socket.io 및 세션?


96

Express 프레임 워크를 사용하고 있습니다. socket.io에서 세션 데이터에 도달하고 싶습니다. client.listener.server.dynamicViewHelpers 데이터로 express dynamicHelpers를 시도했지만 세션 데이터를 가져올 수 없습니다. 이를 수행하는 간단한 방법이 있습니까? 코드를 참조하십시오

app.listen(3000);

var io = require('socket.io');
var io = io.listen(app);

io.on('connection', function(client){
    // I want to use session data here
    client.on('message', function(message){
        // or here
    });
    client.on('disconnect', function(){
        // or here
    }); 
});

5
또는이 아주 좋은 게시물을 사용할 수 있습니다 : danielbaulig.de/socket-ioexpress
Fabiano Soriani

3
@FabianoPS-더 이상 작동하지 않음-connect는 더 이상 이것이 의존하는 parseCookie 메서드를 제공하지 않습니다.
UpTheCreek

1
@UpTheCreek-connect가 더 이상 parseCookie 메서드를 사용하지 않기 때문에 어떻게 이것이 가능할 수 있습니까?
Aust

@Aust-좋은 질문입니다. 지금 가장 좋은 방법이 무엇인지 모르겠습니다. 이것은 정말 엉망인 IMO입니다. 성가 시게도 대부분의 해결 방법 논의는 socket.io에 초점을 맞추고 있습니다 (모든 사람이 socket.io를 사용하는 것은 아닙니다!). 이제 parseSignedCookie 함수가 있지만 이것도 비공개이므로 변경 사항을 깨뜨릴 위험이 있습니다.
UpTheCreek

2
최신 버전의 Socket.IO (1.x) 및 Express (4.x)의 경우 다음 질문을 확인하십시오. stackoverflow.com/questions/25532692/…
pootzko 2014-09-23

답변:


68

이것은 flashsocket 전송을 통과하는 소켓에 대해서는 작동하지 않지만 (서버에 필요한 쿠키를 보내지 않음) 다른 모든 것에 대해서는 안정적으로 작동합니다. 내 코드에서 flashsocket 전송을 비활성화했습니다.

작동하기 위해 Express / connect 측에서 세션 저장소를 명시 적으로 정의하여 소켓 내부에서 사용할 수 있습니다.

MemoryStore = require('connect/middleware/session/memory'),
var session_store = new MemoryStore();
app.configure(function () {
  app.use(express.session({ store: session_store }));
});

그런 다음 소켓 코드 내에 connect 프레임 워크를 포함하여 쿠키 구문 분석을 사용하여 쿠키에서 connect.sid를 검색 할 수 있습니다. 그런 다음 connect.sid가있는 세션 저장소에서 다음과 같이 세션을 찾습니다.

var connect = require('connect');
io.on('connection', function(socket_client) {
  var cookie_string = socket_client.request.headers.cookie;
  var parsed_cookies = connect.utils.parseCookie(cookie_string);
  var connect_sid = parsed_cookies['connect.sid'];
  if (connect_sid) {
    session_store.get(connect_sid, function (error, session) {
      //HOORAY NOW YOU'VE GOT THE SESSION OBJECT!!!!
    });
  }
});

그런 다음 필요에 따라 세션을 사용할 수 있습니다.


3
socket_client.request가 socket.io-node의 최신 버전에서 제거 된 것 같습니다
Art

6
조심하세요 ... 지금이 작업을 수행하는 새로운 규칙이 있습니다 ... 대신 Socket.IO 인증을 사용하는 것이 좋습니다. @Jeffer에서 포스트 참조
BMiner

2
불행히도 이것은 더 이상 작동하지 않습니다-parseCookie는 더 이상 연결 유틸리티의 일부가 아닙니다. 분명히 그것은 공개 API의 일부가 아니 었습니다. 이 지저분한 대안이다 - parseSignedCookie는하지만,이 또한 개인 인 나는 .. 너무 사라질 위험에 자사의 추측 있도록
UpTheCreek

이제 생각해 보았습니다 .... 쿠키 용 저장소와 소켓 용 저장소를 동일한 저장소로 설정하는 것은 어떻습니까?
James

34

Socket.IO-sessions 모듈 솔루션은 클라이언트 (스크립팅) 수준에서 세션 ID를 노출하여 앱을 XSS 공격에 노출합니다.

대신 이 솔루션을 확인하십시오 (Socket.IO> = v0.7의 경우). 여기에서 문서를 참조 하십시오 .


1
@Jeffer-두 번째 솔루션은 현재 버전의 연결에서 더 이상 작동하지 않습니다.
UpTheCreek

2
-1 socket.io은 해당 모듈이 아닌 세션 ID를 노출하는 것입니다. 세션 ID는 어쨌든 쿠키에 클라이언트 측에 저장되기 때문에 이것은 큰 문제가 아닙니다. 또한 해당 튜토리얼은 최신 버전의 Express에서 작동하지 않습니다.
Aust

1
솔루션 링크는 단순히 socket.iogithub 페이지로 리디렉션됩니다 ..?
TJ

8

나는 바퀴를 완전히 재발 명하지 말 것을 제안합니다. 필요한 도구는 이미 npm 패키지입니다. 이것이 필요한 것이라고 생각합니다 : session.socket.io 요즘 사용하고 있으며 매우 도움이 될 것 같습니다 !! express-session을 socket.io 레이어에 연결하면 많은 이점이 있습니다!


6
다음은 socket.io> = 1.0에 대한 socket.io-express-sessions를 지원하는 업데이트 된 모듈입니다. github.com/xpepermint/socket.io-express-session
blnc

4

편집 : 작동하지 않는 일부 모듈을 시도한 후 실제로이 작업을 수행하기 위해 내 라이브러리를 작성했습니다. 뻔뻔한 플러그 : https://github.com/aviddiviner/Socket.IO-sessions 에서 확인 하세요 . 역사적인 목적으로 아래에 이전 게시물을 남겨 둘 것입니다.


위의 pr0zac 솔루션에 따라 flashsocket 전송 을 우회하지 않고도이 작업을 아주 깔끔하게 얻었습니다 . 나는 또한 Socket.IO와 함께 express를 사용하고 있습니다. 방법은 다음과 같습니다.

먼저 세션 ID를 뷰에 전달합니다.

app.get('/', function(req,res){
  res.render('index.ejs', {
    locals: { 
      connect_sid: req.sessionID
      // ...
    }
  });
});

그런 다음보기에서 Socket.IO 클라이언트 측에 연결합니다.

<script>
  var sid = '<%= connect_sid %>';
  var socket = new io.Socket();
  socket.connect();
</script>
<input type="button" value="Ping" onclick="socket.send({sid:sid, msg:'ping'});"/>

그런 다음 서버 측 Socket.IO 리스너에서이를 선택하고 세션 데이터를 읽고 / 씁니다.

var socket = io.listen(app);
socket.on('connection', function(client){
  client.on('message', function(message){
    session_store.get(message.sid, function(error, session){
      session.pings = session.pings + 1 || 1;
      client.send("You have made " + session.pings + " pings.");
      session_store.set(message.sid, session);  // Save the session
    });
  });
});

제 경우 session_store에는 redis-connect라이브러리를 사용하는 Redis 입니다.

var RedisStore = require('connect-redis');
var session_store = new RedisStore;
// ...
app.use(express.session({ store: session_store }));

이것이 Google을 검색하는 동안이 게시물을 찾는 사람에게 도움이되기를 바랍니다.


8
클라이언트 HTML에서 세션 ID를 넣는 것은 ... 보안 관점에서 좋은 아이디어되지 않습니다
UpTheCreek

4
세션 ID가 이미 로컬 쿠키에 저장되어 있는데 왜 HTML에 세션 ID를 넣는 것이 그렇게 나쁜 생각입니까?
Gavin

3
HttpOnly 쿠키로 설정하면 javascript에서 쿠키에 액세스 할 수 없기 때문입니다. session.sid를 HTML에 넣어 공격자에게 필요한 모든 것을 DOM에 제공합니다.
rochal

3

참조 : Socket.IO 인증

나는 통해 아무것도 가져 오는하지 제안 client.request...또는 client.listener...그 직접 부착되지 않는 client개체를 항상 로그인 한 사용자의 마지막을 가리!


2

Socket.IO-connect를 확인하십시오.

Socket.IO 노드 주위에 WebSocket 미들웨어 래퍼 연결 https://github.com/bnoguchi/Socket.IO-connect

이렇게하면 Socket.IO 이벤트 처리기로 처리하기 전에 Express / Connect 미들웨어 스택에서 Socket.IO 요청을 푸시하여 세션, 쿠키 등에 대한 액세스를 제공 할 수 있습니다. 비록 그것이 Socket.IO의 모든 전송과 함께 작동하는지 확신하지 못합니다.


불행하게도 모듈은 여전히 socket.io의 v0.6 사용하고 있음
fent

2

express-socket.io-session 을 사용할 수 있습니다 .

socket.io와 쿠키 기반의 익스프레스 세션 미들웨어를 공유하십시오. express> 4.0.0 및 socket.io> 1.0.0에서 작동하며 이전 버전과 호환되지 않습니다.

나를 위해 일했다!!


야. 프런트 엔드에서 세션 값을 어떻게 사용 하시겠습니까? npm 문서에서 볼 수 없습니다.
하리 램

1

https://github.com/bmeck/session-web-sockets 에서 볼 수 있습니다.

또는 다음을 사용할 수 있습니다.

io.on('connection', function(client) { 
  var session = client.listener.server.viewHelpers; 
  // use session here 
});

도움이 되었기를 바랍니다.


나는 session-web-sockets를 알고 있지만 이것을 위해 라이브러리를 사용하고 싶지 않으며 간단한 솔루션을 찾고 있습니다. client.listener.server.viewHelpers를 시도했습니다. 그러나 다음을 반환했습니다. {}
sfs

2
이것은 처음에는 작동하는 것처럼 보이지만 경쟁 조건으로 이어집니다. 나는 그것을 완전히 피하는 것이 좋습니다.
Shripad Krishna 2011

1

내가 제대로하고 있는지 잘 모르겠습니다. https://github.com/LearnBoost/socket.io/wiki/Authorizing

핸드 셰이크 데이터를 사용하여 쿠키에 액세스 할 수 있습니다. 그리고 쿠키에서 각 클라이언트의 세션 ID 인 connect.sid를 가져올 수 있습니다. 그런 다음 connect.sid를 사용하여 데이터베이스에서 세션 데이터를 가져옵니다 (RedisStore를 사용하고 있다고 가정합니다)


이것은 정확히 갈 길이지만 멋지지 않으므로 스택 오버플로 포인트를 얻을 수 없습니다. github.com/tcr/socket.io-sessiongithub.com/functioncallback/session.socket.io 나는 첫 번째가 좀 더 깔끔한 것을 좋아합니다. 두 번째는 좀 더 잘 문서화되어 있습니다.
James

@TJ 미안하지만 그 대답이 2 년 전이라는 것을 알고 있습니까? 그리고 아마 지금은 작동하지 않을 것입니다
Tan Nguyen

@TanNguyen 알아요, 그렇기 때문에 사람들에게 죽은 링크를 가리키는 것보다 답변을 업데이트 할 수 있도록 알려 드렸습니다
TJ

@TJ 감사합니다. 불행히도 2 년 전에 성능 문제로 socket.io에서 멀어졌습니다. 따라서, 나는 socket.io에서 세션을 처리하는 현재의 방법이 무엇인지 모른다
탄 응웬를
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.