5.4 KiB
id, title, challengeType, forumTopicId, dashedName
id | title | challengeType | forumTopicId | dashedName |
---|---|---|---|---|
589fc831f9fc0f352b528e77 | Autenticazione con Socket.IO | 2 | 301548 | authentication-with-socket-io |
--description--
Al momento, non puoi determinare chi sia connesso alla tua socket web. req.user
contiene l'oggetto utente, ma solo quando l'utente interagisce con il server web. Con le web sockets non hai req
(richiesta) e di conseguenza, nessun dato utente. Un modo per risolvere il problema di sapere chi sia connesso alla tua web socket è di analizzare e decodificare il cookie che contiene la sessione passport, per poi deserializzarlo e ottenere l'oggetto utente. Fortunatamente, c'è un pacchetto su NPM fatto per questo, che trasforma un compito una volta complesso, in qualcosa di semplice!
Aggiungi passport.socketio@~3.7.0
, connect-mongo@~3.2.0
, e cookie-parser@~1.4.5
come dipendenze e richiedile rispettivamente come passportSocketIo
, MongoStore
, e cookieParser
. Inoltre, dobbiamo inizializzare un nuovo archivio di memoria da express-session
che abbiamo richiesto in precedenza. Dovrebbe assomigliare a questo:
const MongoStore = require('connect-mongo')(session);
const URI = process.env.MONGO_URI;
const store = new MongoStore({ url: URI });
Ora dobbiamo solo dire a Socket.IO di utilizzarlo e impostare le opzioni. Assicurati che venga aggiunto prima del codice socket esistente, e non nel listener di connessione esistente. Per il tuo server, dovrebbe assomigliare a questo:
io.use(
passportSocketIo.authorize({
cookieParser: cookieParser,
key: 'express.sid',
secret: process.env.SESSION_SECRET,
store: store,
success: onAuthorizeSuccess,
fail: onAuthorizeFail
})
);
Nota che la configurazione dell'autenticazione Passport per Socket.IO è molto simile a quella che abbiamo preparato per il middleware session
per l'API. Questo perché utilizzano lo stesso metodo di autenticazione - ottenere l'id di sessione da un cookie e convalidarlo.
In precedenza, quando abbiamo configurato il middleware session
, non abbiamo esplicitamente impostato il nome del cookie per la sessione (key
). Questo perché il pacchetto session
usava il valore predefinito. Ora che abbiamo aggiunto un altro pacchetto che necessita di accedere allo stesso valore dai cookie, abbiamo bisogno di impostare esplicitamente il valore key
in entrambi gli oggetti di configurazione.
Assicurati di aggiungere la key
con il nome del cookie al middleware session
che corrisponde alla chiave Socket.IO. Inoltre, aggiungi il riferimento store
alle opzioni, vicino a dove abbiamo impostato saveUninitialized: true
. Questo è necessario per dire a Socket.IO a quale sessione deve fare riferimento.
Ora definisci le funzioni di callback per success
e fail
:
function onAuthorizeSuccess(data, accept) {
console.log('successful connection to socket.io');
accept(null, true);
}
function onAuthorizeFail(data, message, error, accept) {
if (error) throw new Error(message);
console.log('failed connection to socket.io:', message);
accept(null, false);
}
L'oggetto utente è ora disponibile sul tuo oggetto socket come socket.request.user
. Per esempio, ora puoi aggiungere quanto segue:
console.log('user ' + socket.request.user.name + ' connected');
Scriverà sulla console del server chi si è connesso!
Invia la tua pagina quando pensi di averlo fatto correttamente. Se dovessi incontrare degli errori, puoi controllare il progetto fino a questo punto qui.
--hints--
passport.socketio
dovrebbe essere una dipendenza.
(getUserInput) =>
$.get(getUserInput('url') + '/_api/package.json').then(
(data) => {
var packJson = JSON.parse(data);
assert.property(
packJson.dependencies,
'passport.socketio',
'Your project should list "passport.socketio" as a dependency'
);
},
(xhr) => {
throw new Error(xhr.statusText);
}
);
cookie-parser
dovrebbe essere una dipendenza.
(getUserInput) =>
$.get(getUserInput('url') + '/_api/package.json').then(
(data) => {
var packJson = JSON.parse(data);
assert.property(
packJson.dependencies,
'cookie-parser',
'Your project should list "cookie-parser" as a dependency'
);
},
(xhr) => {
throw new Error(xhr.statusText);
}
);
passportSocketIo dovrebbe essere richiesto correttamente.
(getUserInput) =>
$.get(getUserInput('url') + '/_api/server.js').then(
(data) => {
assert.match(
data,
/require\((['"])passport\.socketio\1\)/gi,
'You should correctly require and instantiate "passport.socketio"'
);
},
(xhr) => {
throw new Error(xhr.statusText);
}
);
passportSocketIo dovrebbe essere configurato correttamente.
(getUserInput) =>
$.get(getUserInput('url') + '/_api/server.js').then(
(data) => {
assert.match(
data,
/io\.use\(\s*\w+\.authorize\(/,
'You should register "passport.socketio" as socket.io middleware and provide it correct options'
);
},
(xhr) => {
throw new Error(xhr.statusText);
}
);
--solutions--
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/