2013-08-15 16 views
7

Sto provando a creare un'applicazione di chat basata su sails.js. L'URL per i messaggi da una specifica chat di simile a questa:Autorizzazione Sails.js per richieste socket

/api/chat/:id/messages

Quando chiedo questo URL con XHR, fornisce un cookie di sessione e sails.js costruisce un oggetto di sessione. Posso facilmente controllare i diritti degli utenti per leggere i messaggi dalla chat specifica.

Tuttavia, ho bisogno di richiedere questo URL con socket.io in modo che il client possa sottoscrivere tutte le future modifiche della collezione messages.

Quando richiedo questo URL con socket.io, non viene impostato alcun cookie di sessione e la sessione sails.js è vuota. Quindi, non posso controllare i diritti utente sul lato server.

Capisco che le richieste di socket non siano richieste HTTP. Non forniscono alcun cookie per conto proprio.

C'è qualche soluzione semplice?

+0

Per chiarire, stai riscontrando questo problema tra domini, giusto? Come in hai incorporato uno script su www.foo.com e aprendo un socket su www.bar.com? – mikermcneil

+0

No, Mike: non è un problema inter-dominio. Ho finalmente trovato la risposta e l'ho pubblicata qui sotto. Devi accedere al tuo oggetto sessione socket in un modo diverso. P.S. Forse dovresti implementare questa soluzione alternativa nel core sails.js. – alevkon

risposta

5

Ho trovato un modo per ottenere l'oggetto di sessione impostato durante l'handshaking di socket.io. nel controller, si dovrebbe fare qualcosa di simile:

myControllerAction: function(req, res) { 
    var session = req.session; 
    if (req.isSocket) { 
     var handshake = req.socket.manager.handshaken[req.socket.id]; 
     if (handshake) { 
      session = handshake.session; 
     } 
    } 
    //session now contains proper session object 
} 

è possibile implementare questa nella politica sails.js, e collegare questa politica per alcuni controller. Ma non scrivere la tua sessione socket in req.session! In caso contrario, si verificherà un errore nel tentativo di rispondere al client (l'originale req.session è ancora utilizzato in qualche modo). Invece, salvalo come req.socketSession o qualcosa del genere.

3

inviare una richiesta JSONP dall'applicazione prima di inviare una richiesta socket, che creerà un cookie e accetta richieste socket.

+0

Come dovrebbe essere d'aiuto? Ho già un cookie prima di inizializzare l'handshake di socket.io. Quale indirizzo devo richiedere con JSONP? Perché JSONP, non semplice Ajax? – alevkon

+0

potresti incollare il tuo errore qui? È il tuo client e il server sono nello stesso dominio, si prega di fornire ulteriori dettagli. –

+1

Questa risposta è ciò che il resto della squadra e io abbiamo fatto in passato ... per chiarire, sembra che tu stia facendo i socket cross-domain, sì? Il problema è che il browser non invia cookie quando stabilisce la connessione web socket. Sfortunatamente, potresti scoprire che ci sono ancora problemi in Safari. @alevkon Non sarà possibile utilizzare AJAX di base perché è un dominio incrociato: sarà necessario utilizzare JSONP o CORS (e CORS non è completamente supportato mikermcneil

0

alevkon, nel metodo sopra indicato è necessario implementare lo stesso in tutti i controller, perché non si conosce a quale controller si accede per la prima volta ... ma inviando solo una richiesta jsonp è possibile creare un cookie tra client e server, lo stesso cookie viene utilizzato fino alla sessione successiva.

+1

Shiva, Non si tratta di un problema relativo ai cookie. Ho alcune richieste AJAX già inviate prima del socket handshaking, quindi il cookie sails.sid è già impostato. Il problema non riguardava i cookie, il problema era come accedere all'oggetto sessione dai controllori. se il tuo req.isSocket è vero, non troverai la sessione corretta nel tuo oggetto req.session, ma puoi comunque accedervi come descritto. – alevkon

1

È possibile eseguire l'accesso iniziale tramite socket.post() anziché XHR, le successive richieste di socket saranno autorizzate.