2012-08-29 3 views
17

Node.js를 기반으로 채팅 응용 프로그램을 만들려고합니다. 나는 ExpressJS 세션 시스템을 사용하여 websocket 서버 (ws 라이브러리)를 강제하고 싶습니다. 불행히도, 나는 붙어있어. 세션의 데이터를 가져 오는 데 사용되는 MemoryStore 해시가 쿠키의 세션 ID와 다릅니다. 누군가 내가 뭘 잘못하고 있는지 설명해 줄 수 있니?ExpressJS 및 웹 소켓 및 세션 공유

웹 소켓 서버 코드 부분 :

module.exports = function(server, clients, express, store) { 
    server.on('connection', function(websocket) { 
    var username; 

    function broadcast(msg, from) {...} 

    function handleMessage(msg) {...} 

    express.cookieParser()(websocket.upgradeReq, null, function(err) { 
     var sessionID = websocket.upgradeReq.cookies['sid']; 

      //I see same value in Firebug 
     console.log(sessionID); 

      //Shows all hashes in store 
      //They're shorter than sessionID! Why? 
     for(var i in store.sessions) 
      console.log(i); 

     store.get(sessionID, function(err, session) { 
       websocket.on('message', handleMessage); 

       //other code - won't be executed until sessionID in store 

       websocket.on('close', function() {...}); 
     }); 
    }); 
}); 
} 

저장소 개체 정의 :

var store = new express.session.MemoryStore({ 
    reapInterval: 60000 * 10 
}); 

응용 프로그램 구성 : 주요 코드의

app.configure(function() { 
    app.use(express.static(app.get("staticPath"))); 
    app.use(express.bodyParser()); 
    app.use(express.cookieParser()); 

    app.use(express.session({ 
     store: store, 
     secret: "dO_ob", 
     key: "sid" 
    })); 
}); 

부 :

var app = express(); 
var httpServer = http.createServer(app); 
var websocketServer = new websocket.Server({server: httpServer}); 
httpServer.listen(80); 

샘플 디버깅 출력 :

- websocket.upgradeReq.headers.cookie "sid=s%3A64a%2F6DZ4Mab8H5Q9MTKujmcw.U8PJJIR%2BOgONY57mZ1KtSPx6XSfcn%2FQPZ%2FfkGwELkmM" 
- websocket.upgradeReq.cookies["sid"] "s:64a/6DZ4Mab8H5Q9MTKujmcw.U8PJJIR+OgONY57mZ1KtSPx6XSfcn/QPZ/fkGwELkmM" 
- i "64a/6DZ4Mab8H5Q9MTKujmcw" 
+1

간단하고 추한 해결하는 데 도움이 : sessionID와 = sessionID.match (/ : [A-ZA-Z0-9/+] + \ ./) [0]. 슬라이스 (1, -1),하지만이 문제를 해결하고 싶습니다. – skorczan

+0

해결 방법을 제공해 주셔서 감사합니다. :) 이것에 대한 적절한 해결책을 찾았습니까? – Tim

답변

16

나는이 작업을 얻을 수 있었다. 세션 저장소 대신 cookieParser에서 암호를 지정해야한다고 생각합니다. 내 응용 프로그램에서

예 :

var app = express(); 
var RedisStore = require('connect-redis')(express); 
var sessionStore = new RedisStore(); 
var cookieParser = express.cookieParser('some secret'); 

app.use(cookieParser); 
app.use(express.session({store: sessionStore})); 


wss.on('connection', function(rawSocket) { 

    cookieParser(rawSocket.upgradeReq, null, function(err) { 
    var sessionID = rawSocket.upgradeReq.signedCookies['connect.sid']; 
    sessionStore.get(sessionID, function(err, sess) { 
     console.log(sess); 
    }); 
    }); 

}); 
14

나는이 나를 위해 작동 발견했다. 비록 이것이 최선의 방법이라고 생각하지 않습니다. 먼저 명시 적 응용 프로그램을 초기화하십시오.

// whatever your express app is using here... 
var session = require("express-session"); 
var sessionParser = session({ 
    store: session_store, 
    cookie: {secure: true, maxAge: null, httpOnly: true} 
}); 
app.use(sessionParser); 

이제 WS 연결에서 세션 미들웨어를 명시 적으로 호출하십시오. express-session 모듈을 사용하는 경우 미들웨어가 쿠키를 단독으로 구문 분석합니다. 그렇지 않으면 먼저 쿠키 파싱 미들웨어를 통해 쿠키를 보내야 할 수 있습니다. 당신이 ws 모듈을 사용하는 경우

ws.on("request", function(req){ 
    sessionParser(req.httpRequest, {}, function(){ 
     console.log(req.httpRequest.session); 
     // do stuff with the session here 
    }); 
}); 

:

당신이 websocket 모듈을 사용하는 경우 express를 사용하여,

여러분의 편의를 위해
ws.on("connection", function(req){ 
    sessionParser(req.upgradeReq, {}, function(){ 
     console.log(req.upgradeReq.session); 
     // do stuff with the session here 
    }); 
}); 

, 여기에 완벽하게 동작하는 예제입니다, express-sessionws :

var app = require('express')(); 
var server = require("http").createServer(app); 
var sessionParser = require('express-session')({ 
    secret:"secret", 
    resave: true, 
    saveUninitialized: true 
}); 
app.use(sessionParser); 

app.get("*", function(req, res, next) { 
    req.session.working = "yes!"; 
    res.send("<script>var ws = new WebSocket('ws://localhost:3000');</script>"); 
}); 

var ws = new require("ws").Server({server: server}); 
ws.on("connection", function connection(req) { 
    sessionParser(req.upgradeReq, {}, function(){ 
     console.log("New websocket connection:"); 
     var sess = req.upgradeReq.session; 
     console.log("working = " + sess.working); 
    }); 
}); 

server.listen(3000); 
+4

downvote에 대해 설명해주십시오. – Azmisov

+0

파티가 조금 늦었지만 코드가 컴파일되지 않습니다. 마지막 줄 앞에'''가 없다. –

+0

@matejkramny 고마워, 지금 고치다 – Azmisov

0

현재 아래의 코드가 잘 작동하고 있습니다. 나는 그것이 그것이 단점과 안전이라는 것을 모른다. 세션이없는 경우 서버가 수신 대기하는 것을 방지합니다. (Share session from express-session to ws)

아직 완전히 테스트하지 않았습니다.

var http = require('http'); 
var express = require('express'); 
var expressSession = require('express-session'); 
var router = express.Router(); 
var app = express(); 

const server = http.createServer(app); 

router.get('/', function(req, res, next) { 
    if(req.session.user_id) { 
     // Socket authenticated 
     server.listen(8080, function listening(){}); 
    } 
}); 
0

WS v3.0.0 이상은 동작이 변경되어 주어진 답변이 해당 버전의 상자에서 작동하지 않습니다. 현재 버전의 경우 연결 메소드의 서명은 [function (socket, request)]이며 소켓은 더 이상 요청에 대한 참조를 포함하지 않습니다.

ws.on(
    'connection', 
    function (socket, req) 
    { 
     sessionParser(
      req, 
      {}, 
      function() 
      { 
       console.log(req.session); 
      } 
     ); 
    } 
); 
0

ws의 버전 3.2.0에서는 약간 다르게해야합니다.

ws 리포에는 verifyClient이라는 새로운 기능을 사용하여 빠른 세션 구문 분석이 full working example 개 있습니다.

아주 간단한 사용법 요약 :

const sessionParser = session({ 
    saveUninitialized: false, 
    secret: '$eCuRiTy', 
    resave: false 
}) 

const server = http.createServer(app) 
const wss = new WebSocket.Server({ 
    verifyClient: (info, done) => { 
    console.log('Parsing session from request...') 
    sessionParser(info.req, {},() => { 
     console.log('Session is parsed!') 
     done(info.req.session.userId) 
    }) 
    }, 
    server 
}) 

wss.on('connection', (ws, req) => { 
    ws.on('message', (message) => { 
    console.log(`WS message ${message} from user ${req.session.userId}`) 
    }) 
})