2016-04-25 5 views
2

Ich habe eine Anwendung auf Express, Express-Sitzung und WS (für die Websocket-Unterstützung) gebaut.Node.js, ws und express-session: Wie bekomme ich ein Session-Objekt von ws.upgradeReq

Ich habe diesen Code verwendet, um die Session-Middleware zu aktivieren:

app.use(session({secret: 'mysecret',resave: true,saveUninitialized: true,cookie: {}})); 

Und ich kann mit Session-Variablen in einem get-Handler lesen und speichern:

app.get('/', function (req, res) { 
    res.send('Hello World!'); 
    console.log(req.session.test); 
    req.session.test="OK"; 
    req.session.save(); 
}); 

(das erste Mal, er druckt " undefined "und das zweite Mal druckt" OK "wie erwartet)

Jetzt habe ich einen Websocket-Server, der von Express auch in der gleichen App behandelt wird, und ich möchte diebekommenObjekt innerhalb der ws.on("connection",...) und in ws.on("message",...).

Das Problem ist, dass es keinen Verweis auf das ursprüngliche Objekt req gibt, nur eine Referenz auf eine upgradeReq, die ein Wrapper des Verbindungshandlers der Websocket ist. Überprüfen dieses upgradeReq Ich kann die connect.sid in ws.upgradeReq.headers.cookie finden, die den Session-Cookie-Wert enthält.

wss.on('connection', function connection(ws) { 
    var location = url.parse(ws.upgradeReq.url, true); 
    console.log(ws.upgradeReq.headers.cookie); 
    //.... 
}); 

In meiner Idee möglich sein, könnte die ursprüngliche req.session daraus in irgendeiner Weise zu erhalten.

Wie kann ich das erreichen?

Antwort

6

Ok, ich habe einen undokumentierten Weg gefunden, den Quellcode von Express-Session zu studieren.

Zuerst müssen Sie cookie und cookie-parser als Ihre Abhängigkeit.

so, importieren Sie die Module

var cookie = require('cookie'); 
var cookieParser = require('cookie-parser') 

Dann wird der Trick ist, die unterzeichnet Cookie in den ws "Verbindung" Event-Handler zu entschlüsseln, das ist, wenn es der websocket Händedruck ist. Zunächst einmal müssen Sie die connect.sid aus dem Cookie entschlüsseln, die die Session-ID ist

wss.on('connection', function connection(ws) { 
    var cookies=cookie.parse(ws.upgradeReq.headers.cookie); 
    var sid=cookieParser.signedCookie(cookies["connect.sid"],secret); 
    ... 

kümmern uns (nur, wenn Sie Express-Sitzung für die Sitzungsverwaltung verwenden), dass das Geheimnis der gleiche ist, dass Sie haben für die Signatur in Express-Sitzung festgelegt (das ist in app.use(session({secret: secret, resave: true, saveUninitialized: true, cookie: {},store:store}));) An dieser Stelle haben Sie die SessoinID in SID, die Sie das Session-Objekt von Express-Sitzung erhalten möchten, die Sie asynchron aus dem Speicher (dort sind viele, lies das doc, im moment habe ich nur mit dem MemoryStore von express-session getestet).

Um die Sitzung dann verwenden Sie diesen Code zu bekommen, gleich nach den Linien über

... 
store.get(sid,function(err, ss){ 
     store.createSession(ws.upgradeReq,ss) 
    }); 

die Callback-Funktion werden Ihnen das Sitzungsobjekt geben (ss) direkt aus dem Laden, aber es ist allein und ohne Methoden (ist nur ein deserialisierter JSON). Aus diesem Grund verwenden wir wieder die store.createSession, der wir das upgradeReq und das ss-Objekt übergeben. Auf diese Weise habe ich ein Session-Objekt, das alle dokumentierten Methoden enthält (so kann ich auch die Session aus WS-Callbacks modifizieren).

Das neue Session-Objekt ist verfügbar in:

ws.upgradeReq.session 

Vorsicht: Das Session-Objekt nicht zur Verfügung steht, bis der Speicher asynchron das ss-Objekt zurück, so wäre es eine gute Praxis, das websocket Ereignis zu beenden Bindungen (wie on('message',...) innerhalb des Rückrufs an den store.get geben

Dies ist der vollständige Code:.

wss.on('connection', function connection(ws) { 
    var location = url.parse(ws.upgradeReq.url, true); 
    //get sessionID 
    var cookies = cookie.parse(ws.upgradeReq.headers.cookie); 
    var sid = cookieParser.signedCookie(cookies["connect.sid"], secret); 
    //get the session object 
    store.get(sid, function (err, ss) { 
     //create the session object and append on upgradeReq 
     store.createSession(ws.upgradeReq, ss) 
     //setup websocket bindings 
     ws.on('message', function incoming(message) { 
      console.log('received: %s', message); 
      //.......... 
     }); 

    }); 
}); 

SO, jetzt können Sie Sitzungsdaten mit ws und express-session zusammen verwalten.

Ich hoffe, es wird helfen!

+1

FYI, das für mich gearbeitet, wenn sie in Verbindung mit Passport zum Einsatz. In diesem Fall endete ich mit te Benutzer in ws.upgradeReq.session.passport.user. Vielen Dank! – logidelic

+1

Hallo, Ich versuche das gleiche zu tun, aber ich kann nicht verstehen, warum ws.upgradeReq nicht definiert ist. Kann mir jemand helfen? – dritan

+2

@dritan gab es eine kürzlich brechende Änderung in WS 3.0. ws.upgradeReq wurde entfernt. Wenn Sie nach "ws breaking change upgradeReq" suchen, erhalten Sie weitere Informationen. – user1562766

3

Ich habe gerade herausgefunden, dass upgradeReq bei Version 3.0.0 aus WebSocket entfernt wurde. Eine Abhilfe für vorhandenen Code von alexroat:

wss.on('connection', function connection(ws, req) { 
    ws.upgradeReq = req; 
    var location = url.parse(ws.upgradeReq.url, true); 
    //get sessionID 
    var cookies = cookie.parse(ws.upgradeReq.headers.cookie); 
    var sid = cookieParser.signedCookie(cookies["connect.sid"], secret); 
    //get the session object 
    store.get(sid, function (err, ss) { 
     //create the session object and append on upgradeReq 
     store.createSession(ws.upgradeReq, ss) 
     //setup websocket bindings 
     ws.on('message', function incoming(message) { 
      console.log('received: %s', message); 
      //.......... 
     }); 
    }); 
}); 
Verwandte Themen