2012-08-29 12 views
17

Ich versuche, eine Chat-Anwendung basierend auf Node.js zu machen. Ich möchte WebSocket-Server (WS-Bibliothek) zwingen, ExpressJS Sitzungssystem zu verwenden. Leider bin ich steckengeblieben. MemoryStore-Hashes zum Abrufen von Sitzungsdaten unterscheiden sich von Sitzungs-IDs in Cookies. Könnte mir jemand erklären, was ich falsch mache?ExpressJS & Websocket & Sitzung teilen

Websocket Server-Code-Teil:

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() {...}); 
     }); 
    }); 
}); 
} 

store Objektdefinition:

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

app Konfiguration:

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" 
    })); 
}); 

Teil des Hauptcode:

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

Beispiel Debugging-Ausgabe:

- 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

Einfach, hässlich Abhilfe hilft: sessionID = sessionID.match (/: [a-zA-Z0-9/+] + \ ./) [0]. slice (1, -1), aber ich möchte dieses Problem lösen. – skorczan

+0

Danke für die Problemumgehung, hat mir geholfen :) Hast du jemals eine passende Lösung gefunden? – Tim

Antwort

16

konnte ich diese Arbeit bekommen. Ich denke, Sie müssen das Geheimnis auf CookieParser statt Sitzungsspeicher angeben.

Beispiel aus meiner App:

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

fand ich das für mich arbeitet. Nicht sicher, es ist der beste Weg, dies zu tun. Initialisieren Sie zuerst Ihre Express-Anwendung:

Rufen Sie jetzt explizit die Sitzungs-Middleware von der WS-Verbindung auf. Wenn Sie das Modul express-session verwenden, analysiert die Middleware die Cookies selbst. Andernfalls müssen Sie es möglicherweise zuerst über Ihre Middleware für die Analyse von Cookies senden.

Wenn Sie mit dem websocket Modul:

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

Wenn Sie das ws Modul verwenden:

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

Für Ihre Bequemlichkeit hier ist ein voll funktionsfähiges Beispiel mit express, express-session und ws:

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

Möchten Sie den Downvote erklären? – Azmisov

+0

Ein bisschen spät auf die Party, aber Ihr Code wird nicht kompilieren. Die Zeile vor dem letzten fehlt eine ')' –

+0

@matejkramny Danke, jetzt behoben – Azmisov

0

Derzeit ist unten meine Problemumgehung, die gut funktioniert. Ich weiß nur nicht, dass es Nachteile und Sicherheit ist. Ich verhindere nur, dass der Server hört, wenn es keine Sitzung hat. (Share session from express-session to ws)

Ich habe dies jedoch noch nicht vollständig getestet.

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 und höher, hat das Verhalten so geändert, dass die angegebenen Antworten für diese Versionen nicht funktionieren. Bei aktuellen Versionen lautet die Signatur der Verbindungsmethode [function (socket, request)] und der Socket enthält keinen Verweis mehr auf die Anfrage.

0

In Version 3.2.0 von ws müssen Sie es ein bisschen anders machen.

Es gibt eine full working example der Express-Session-Parsing in der ws Repo, speziell mit einem neuen Feature verifyClient.

Eine sehr kurze Nutzungsübersicht:

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}`) 
    }) 
})