Sto cercando di implementare l’autenticazione e le sessioni con socket.io.
Dopo un sacco di ricerche 1 , ho impostato quanto segue che si avvale di express ed express session.
Il problema è che, le connessioni express e socket.io sembrano avere sessioni diverse dal momento che l’ id
che sto ottenendo è diverso.
Inoltre, nessun cookie è impostato nel browser dalla mia applicazione (che è probabilmente il motivo per cui entrambi i componenti creano sessioni diverse?)
Sto usando express express 4.13.3
1.12.1
e socket.io 1.3.7
.
Di seguito è riportato il codice lato server che ho impostato:
var app = require('express')(); var server = app.listen(80); var parser = require('body-parser'); var Session = require('express-session'); var io = require('socket.io')(server); var game = require('./game.js'); var session = Session({ secret: 'some secret', resave: false, saveUninitialized: false, cookie: { 'name': 'test', httpOnly: false, secure: false, maxAge: ((60 * 1000) * 60) } }); app.use(parser.urlencoded({ extended: false })); app.use(session); app.use(function(req, res, next) { res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); next(); }); app.post('/login', function(req, res) { console.log('login %s', req.session.id); console.dir(req.session, { color: true }); res.json({ status: 'success' }); }); io.use(function(socket, next) { session(socket.handshake, {}, next); }); console.log('socket server started @ %s !', 80); io.on('connection', function(socket) { console.log('user connected %s', socket.handshake.session.id); console.dir(socket.handshake.session, { color: true }); socket.on('disconnect', function() { console.log('user disconnected'); console.dir(socket.handshake.session, { color: true }); }); });
e il codice al client per scopi di test:
$.ajax({ url: 'http://127.0.0.1:80/login', type:'post', success: function(response) { var socket = io('http://127.0.0.1:80'); } });
Di seguito è riportato l’output in console:
e questa è la sezione delle risorse nel browser:
Sono persino confuso vedendo che l’object della session
non ha alcuna proprietà id
quando si accede alla console, ma session.id
stampa valori diversi. Forse questo proviene dalla catena del prototipo di oggetti o qualcosa del genere.
L’unica differenza che posso pensare con il mio codice e le esercitazioni là fuori è che stanno tutti servendo la pagina index.html
dallo stesso server express. Nel mio caso ho il file localmente.
Ho letto da qualche parte che in questi casi devo inviare una richiesta http
per esprimere prima di stabilire la connessione socket.io.
La libreria laterale del client socket.io.js
viene servita dallo stesso server condiviso da express e socket.io ( ), oltre a questo sto anche premendo il percorso express
/login
per testare lo scopo prima che venga stabilita la connessione socket.
Quindi mi chiedo perché nessun cookie viene impostato sul lato client e perché le richieste express e socket hanno creato sessioni diverse …? Cosa mi manca qui ..?
1 Il codice si basa principalmente su:
PS: Quello che sto cercando di fare è, quando un client socket si ricollega, ho bisogno di riportarlo dove era con i dettagli della sessione. Non voglio davvero condividere le sessioni con Express, ma il middleware express è l’unico modo in cui mi sono imbattuto per implementare le sessioni con socket.io.
Il problema non aveva nulla a che fare con express o socket.io.
Il problema è che stavo caricando il progetto da un server locale diverso dal server express e socket.io.
Quindi è una richiesta di ajax interdominio, nel qual caso alcuni browser si rifiutano di gestire l’intestazione Set-Cookie
.
Possiamo aggiustarlo aggiungendo
xhrFields: { withCredentials: true },
nelle opzioni Ajax come menzionato in questa risposta
O se stai lavorando con angular, {withCredentials: true}
inviato {withCredentials: true}
come
$http({withCredentials: true, ...}).get(...)
come menzionato in questa risposta .
Sul lato server, imposta questa intestazione:
res.header("Access-Control-Allow-Credentials", 'true');
Se lo aggiungi, Chrome non ti consentirà più di utilizzare il carattere jolly *
nell’intestazione Access-Control-Allow-Origin
.
Dovresti anche impostarlo su specifici domini consentiti.
res.header("Access-Control-Allow-Origin", "allowed domains");
Non dovresti
res.session.save(); // add this line res.json({ status: 'success' }); // or just res.send({status:success});
?
Inoltre, ti consiglio di utilizzare il modulo passport-local
strategia passport-local
per questo scopo, quindi non devi preoccuparti del perché le tue sessioni non funzionino. Una volta mi ha risparmiato un sacco di tempo.