2014-10-30 4 views
5

Sto utilizzando Koa, Passport.js e koa-session per autenticare gli utenti. in modo che appaia fondamentalmente come:Ottieni ID utente socket.io, passport, koa

// session 
var session = require('koa-session'); 
app.keys = [config.secret]; 
app.use(session()); 


// auth 
require(__dirname+'/lib/auth'); // de/serializeUser, strategies etc.. 
var passport = require('koa-passport'); 
app.use(passport.initialize()); 
app.use(passport.session()); 

questo funziona bene. Su richieste, ho lo req.user, con l'id utente. Ma quando si utilizzano i socket, che posso fare:

io.on('connection', function(socket) { 
    console.log(socket.request.headers.cookie), 
}); 

Ma naturalmente è solo l'ID di sessione crittografata, come potrei deserializzare l'utente e ottenere l'user.id proprio come faccio io quando ho la req.user su ottenere o richiesta?

Grazie in anticipo.

risposta

10

Questa è una risposta molto tardiva, ma spero che sarà utile per voi. Ho appena trascorso circa quattro ore cercando di risolvere questo problema.

Il primo problema che si verificherà è che koa-session non utilizza archivi di sessione reali. Incorpora tutte le informazioni nel cookie stesso e quindi lo analizza da e verso il client. Mentre questo può essere conveniente, funziona contro di te quando si tenta di incorporare Socket.IO, come Socket.IO non ha accesso a koa-session.

È necessario migrare a koa-generic-session e utilizzare un archivio di sessioni per tenere traccia delle sessioni. Questa è, a mio avviso, una mossa migliore a prescindere. Attualmente sto usando koa-redis per i miei negozi di sessione.

Per accedere alle sessioni in Socket.IO, è necessario impostare un negozio globale. Ecco come appare il mio negozio globale.

// store.js 

var RedisStore = require('koa-redis'), 
    store = undefined; // global 

module.exports = function(app, settings) { 
    // Where (app) is Koa and (settings) is arbitrary information 
    return (function(app, settings) { 
     store = store || new RedisStore(); 
     return store; 
    })(app, settings); 
} 

Successivamente, l'installazione iniziale è semplice.

// app.js 

... arbitrary code here ... 

var session = require('koa-generic-session'); 

app.keys = [config.secret]; 
app.use(session({ 
    store: require('./store')(app, settings) 
})); 

... arbitrary code here ... 

Ora che avete un deposito della sessione globale, è quindi possibile accedere a Socket.IO. Tieni presente che dovrai installare i moduli cookie e co.

// io.js 

var cookie = require('cookie'), 
    co = require('co'), 
    store = require('./store')(null, settings); // We don't require the Koa app 

io.use(function(socket, next){ 
    // Now you will need to set up the authorization middleware. In order to 
    // authenticate, you will need the SID from the cookie generated by 
    // koa-generic-session. The property name is by default 'koa.sid'. 

    var sid = cookie.parse(socket.handshake.headers.cookie)['koa.sid']; 

    // We need co to handle generators for us or everything will blow up 
    // when you try to access data stores designed for Koa. 

    co(function*(){ 
     // 'koa:sess:' is the default prefix for generic sessions. 
     var session = yield store.get('koa:sess:' + sid); 

     // At this point you can do any validation you'd like. If all is well, 
     // authorize the connection. Feel free to add any additional properties 
     // to the handshake from the session if you please. 

     if (session) next(null, true) // authenticated 
     else throw new Error('Authentication error.'); 
    }); 
}); 

io.on('connection', function(socket){ 
    // Access handshake here. 
}); 

Ho modificato il codice per Socket.IO v1. Spero che aiuti.

+0

Sembra che Firefox (v. 36) non invii cookie con richieste di websocket, quindi non funzionerà lì. Sto cercando una soluzione al momento in cui la pagina web riceve un token che i socket possono quindi inviare di nuovo al server con ogni richiesta e può con tali mezzi essere convalidati. –

+0

Mille grazie, ha funzionato per me !!! – amd

0

Ho usato un'espressione regolare per prelevare l'ID utente e trovato poi nel mio database. Non è l'approccio più pulito ma funziona bene. Sto solo usando koa-session-store come sessione con passaporto js.

var cookies = socket.request.headers.cookie; 
    var regEx = /passport"\:\{"user"\:"(.+?)"\}/g 
    var userIdMatches = regEx.exec(cookies);