Comment utiliser passeport avec express et socket.io?

j'essaie actuellement de configurer un système d'authentification de base pour mon noeud.js app. Pour l'instant j'utilise express (3.0.0rc5), passeport (0.1.12) et douille.io (0.9.10) with Mongoose as Store for session data. J'ai également été jouer avec <!-Mais je n'aimais pas travailler avec des promesses.

situation actuelle:

L'authentification par passeport (stratégie facebook) est réussie, un session.sid cookie est défini sur le client après la redirection et je suis en mesure de voir un document de session dans ma base de données. Je peux accéder au cookie de session en socket.iosocket.handshake.headers.cookie.

si j'ai bien compris le concept de passeport, après avoir réussi authentication passport.serializeUser est appelé, ce qui me permet d'ajouter des informations à la session. Dans mon cas, l'information la plus importante est l'e-mail, j'ai donc mis le sérialiseur sous la forme suivante:

passport.serializeUser(function(user, done) {
  done(null, user.email);
});

maintenant je suis au point où je dois utiliser seulement les informations de cookie dans ma socket.événement io pour extraire l'email discours de la session.

var connect = require('connect'),
    parseSignedCookie = connect.utils.parseSignedCookie,
    cookie            = require('express/node_modules/cookie');

io.on('connection', function(socket) {
    if(socket.handshake.headers.cookie) {
        var cookie = cookie.parse(socket.handshake.headers.cookie);
        var sessionID = parseSignedCookie(cookie['connect.sid'], 'secret');
    }
});

passport.deserializeUser(function(id, done) {
    // so, what is supposed to be done here?
});

Donc, si je ne me trompe pas, la tâche est maintenant d'utiliser deserializeUser pour accéder à l'adresse mail correspondant à.

comment je ferais ça? Tout pointeur est très apprécié.

36
demandé sur laggingreflex 2012-10-27 02:44:42

3 réponses

Voici une solution en utilisant Socket.IO 1.0 et Express 4.0. L'esprit est semblable à celui de la réponse de Patrick. L'astuce est que depuis Socket.IO 1.0 a une nouvelle API middleware, nous pouvons envelopper L'middleware D'Express et le mettre dans la Socket.Io sans se pencher sur la mise en œuvre de bas niveau des stocks de la session.

// Set up the Session middleware using a MongoDB session store
expressSession = require("express-session");
var sessionMiddleware = expressSession({
    name: "COOKIE_NAME_HERE",
    secret: "COOKIE_SECRET_HERE",
    store: new (require("connect-mongo")(expressSession))({
        url: "mongodb://localhost/DATABASE_NAME_HERE"
    })
});

// Set up the Express server
var app = require("express")()
    .use(sessionMiddleware)
    .use(passport.initialize())
    .use(passport.session())
    // ... more middleware ...
    .listen(8000);

// Set up the Socket.IO server
var io = require("socket.io")(app)
    .use(function(socket, next){
        // Wrap the express middleware
        sessionMiddleware(socket.request, {}, next);
    })
    .on("connection", function(socket){
        var userId = socket.request.session.passport.user;
        console.log("Your User ID is", userId);
    });

la variable sessionMiddleware est une fonction conçue pour s'insérer directement dans le pipeline Express. Il faut exactement trois arguments: l'objet request, l'objet response, et un callback.

Socket.Le pipeline D'IO s'attend à ce que son middleware ne prenne que deux arguments, cependant: l'objet socket (qui contient l'objet request à socket.demande) et un rappel. Heureusement sessionMiddleware n'a pas besoin de l'objet response pour lire la session depuis le magasin, donc nous lui passons simplement un objet vide comme second argument.

Notez que certains les commentaires ci-dessous font remarquer que ce code rend la session en lecture seule. C'est la fonctionnalité que nous perdons en n'ayant pas unréponse objet avec Socket.IO.

dans l'exemple ci-dessus, j'utilise un magasin de session MongoDB (connect-mongo). Vous pouvez utiliser n'importe quel magasin de session qui vous convient. Reportez-vous à le wiki Connect pour une liste des magasins de session.

54
répondu sffc 2015-06-23 05:26:01

Je l'ai obtenu pour travailler. Ce que j'ai dû faire, c'est accéder au magasin. Voici le code au cas où quelqu'un d'autre bute sur ce problème particulier:

// # app.js

var express     = require('express'),
    routes      = require('./routes'),
    http        = require('http'),
    path        = require('path'),
    app         = express(),
    passport    = require('passport'),
    SessionMongoose = require("session-mongoose"),
    mongooseSessionStore = new SessionMongoose({
        url: "mongodb://localhost/login",
        interval: 120000 
    });

var config       = require('game/config.js'), // holds my whole server configuration
    server       = require('game/lib/server.js');

// save sessionStore to config for later access
config.setSessionStore(mongooseSessionStore);

// configure express to use passport and mongooseSessionStore
app.configure(function(){
    app.set('port', config.port);
    app.set('env', config.environment);
    app.set('dbPrefix', config.dbPrefix);
    app.set('views', __dirname + '/views');
    app.set('view engine', 'jade');
    app.use(express.favicon());
    app.use(express.bodyParser());
    app.use(express.cookieParser());
    app.use(express.session({secret : 'totallysecret', store : mongooseSessionStore })),
    app.use(express.methodOverride());
    app.use(passport.initialize());
    app.use(passport.session());    
    app.use(app.router);
    app.use(express['static'](path.join(__dirname, 'public')));
});

app.get('/', routes.index);

app.get('/auth/facebook', passport.authenticate('facebook', { scope: 'email' }));
app.get('/auth/facebook/callback', 
    passport.authenticate('facebook', { successRedirect: '/',
                                        failureRedirect: '/' })); 

// #### Init httpserver
var httpServer = http.createServer(app);
httpServer.listen(app.get('port'));

// #### Server startup
server.init(httpServer);

mes fonctions de sérialisation semblent simples comme ceci:

passport.serializeUser(function(user, done) {
    // saves user.email to session.passport.user
    done(null, user.email);
});

passport.deserializeUser(function(obj, done) {
    done(null, obj);
});

et enfin la prise.mise en œuvre:

var util              = require('util'),
    connect           = require('connect'),
    parseSignedCookie = connect.utils.parseSignedCookie,
    cookie            = require('express/node_modules/cookie'),
    io                = require('socket.io').listen(httpServer);

var config = require('../config.js');  

io.configure(function () {
    io.set('authorization', function (data, callback) {
        if(data.headers.cookie) {
            // save parsedSessionId to handshakeData
            data.cookie = cookie.parse(data.headers.cookie);
            data.sessionId = parseSignedCookie(data.cookie['connect.sid'], 'totallysecret');
        }
        callback(null, true);
    });

    io.on('connection', function(socket) {
        // reference to my initialized sessionStore in app.js
        var sessionStore = config.sessionStore;
        var sessionId    = socket.handshake.sessionId;

        sessionStore.get(sessionId, function(err, session) {
            if( ! err) {
                if(session.passport.user) {
                    console.log('This is the users email address %s', session.passport.user);
            }
        });
    });
});

Utilisation de la session-mangouste module, j'ai accès à:

sessionStore.get(sessionId, callback)
sessionStore.set(sessionId, data, callback) 
sessionStore.destroy(sessionId, callback) 
sessionStore.all(callback)    // returns all available sessions
sessionStore.clear(callback)  // deletes all session data
sessionStore.length(callback) // returns number of sessions in the 
31
répondu Patrick 2012-10-27 09:10:06

Vous pouvez faire usage de express-prise.io-session. Vous pouvez obtenir le passeport de la session de l'utilisateur socket.handshake.session.passport.user. Il prend en charge la lecture et l'écriture à la boutique de session.

NB: Fonctionne avec express > 4.0.0 et de la prise.io > 1.0.0 et ne sera pas rétro-compatible

0
répondu nonybrighto 2017-11-29 04:29:50