¿Qué hace el middleware passport.session ()?


125

Estoy construyendo un sistema de autenticación usando Passport.js usando Easy Node Authentication: Setup and Local tutorial .

Estoy confundido acerca de lo que passport.session()hace.

Después de jugar con los diferentes middleware, llegué a comprender que express.session()es lo que envía una ID de sesión a través de cookies al cliente, pero estoy confundido acerca de lo que passport.session()hace y por qué se requiere además de express.session().

Así es como configuro mi aplicación:

// Server.js configura la aplicación y configura el servidor web

//importing our modules
var express = require('express');
var app = express();
var port = process.env.PORT || 8080;
var mongoose = require('mongoose');
var passport = require('passport');
var flash = require('connect-flash');

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

//Configuration of Databse and App

mongoose.connect(configDB.url); //connect to our database

require('./config/passport')(passport); //pass passport for configuration

app.configure(function() {

    //set up our express application

    app.use(express.logger('dev')); //log every request to the console
    app.use(express.cookieParser()); //read cookies (needed for auth)
    app.use(express.bodyParser()); //get info from html forms

    app.set('view engine', 'ejs'); //set up ejs for templating

    //configuration for passport
    app.use(express.session({ secret: 'olhosvermelhoseasenhaclassica', maxAge:null })); //session secret
    app.use(passport.initialize());
    app.use(passport.session()); //persistent login session
    app.use(flash()); //use connect-flash for flash messages stored in session

});

//Set up routes
require('./app/routes.js')(app, passport);

//launch
app.listen(port);
console.log("Server listening on port" + port);

Respuestas:


139

passport.session() actúa como un middleware para alterar el objeto req y cambiar el valor de 'usuario' que es actualmente el ID de sesión (de la cookie del cliente) en el verdadero objeto de usuario deserializado.

Si bien las otras respuestas hacen algunos buenos puntos, pensé que se podrían proporcionar algunos detalles más específicos.

app.use(passport.session());

es equivalente a

app.use(passport.authenticate('session'));

Donde 'sesión' se refiere a la siguiente estrategia que se incluye con passportJS.

https://github.com/jaredhanson/passport/blob/master/lib/strategies/session.js

Específicamente líneas 59-60:

var property = req._passport.instance._userProperty || 'user';
req[property] = user;

Donde esencialmente actúa como un middleware y altera el valor de la propiedad 'usuario' en el objeto req para contener la identidad deserializada del usuario. Para permitir que esto funcione correctamente, debe incluir serializeUsery deserializeUserfunciones en su código personalizado.

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

passport.deserializeUser(function (user, done) {
    //If using Mongoose with MongoDB; if other you will need JS specific to that schema.
    User.findById(user.id, function (err, user) {
        done(err, user);
    });
});

Esto encontrará al usuario correcto de la base de datos y lo pasará como una variable de cierre a la devolución de llamada done(err,user);para que el código anterior en el passport.session()pueda reemplazar el valor de 'usuario' en el objeto req y pasar al siguiente middleware en la pila.


hey, ¿cómo puedo almacenar los detalles del usuario en la sesión solo? No quiero almacenarlos directamente en la base de datos
Novato

1
"en los encabezados de la solicitud"? no solo en el objeto de solicitud
caub

He notado que si la estrategia de sesión es capaz de restaurar la autenticación y deserializar al usuario. Pero a pesar de eso, la autenticación todavía se mueve a la siguiente estrategia, que es la autenticación de Facebook en mi escenario. Me pregunto cuál es el punto de la estrategia de sesión si aún continúa invocando las siguientes estrategias incluso cuando la sesión puede recuperar al usuario.
nishant

15

De la documentación

En una aplicación basada en Connect o Express, se requiere el middleware passport.initialize () para inicializar Passport. Si su aplicación utiliza sesiones de inicio de sesión persistentes, también se debe utilizar el middleware passport.session ().

y

Sesiones

En una aplicación web típica, las credenciales utilizadas para autenticar a un usuario solo se transmitirán durante la solicitud de inicio de sesión. Si la autenticación tiene éxito, se establecerá y mantendrá una sesión a través de una cookie establecida en el navegador del usuario.

Cada solicitud posterior no contendrá credenciales, sino la cookie única que identifica la sesión. Para admitir las sesiones de inicio de sesión, Passport serializará y deserializará las instancias de usuario desde y hacia la sesión.

y

Tenga en cuenta que habilitar el soporte de sesión es completamente opcional, aunque se recomienda para la mayoría de las aplicaciones. Si está habilitado, asegúrese de usar express.session () antes de passport.session () para asegurarse de que la sesión de inicio de sesión se restaure en el orden correcto.


1
Gracias por su rápida respuesta, pero eso no responde a mi pregunta. Además, tenga en cuenta que si tiene una aplicación express y usa express.session (), en cualquier cliente que se conecte a su servidor express (ya sea que esté autenticado o no), se le dará una sesión a través de una cookie. Eso es independiente de si está en una página protegida de inicio de sesión de su aplicación o no. Todavía me gustaría saber la diferencia entre ambos middleware.
Georges Krinker

1
@GeorgesKrinker son los métodos serializeUser () y deserializeUser. El middleware express restaurará la información de la sesión, pero eso no está necesariamente relacionado con la forma en que Passport gestiona la información del usuario. Eso debe hacerse después de que la sesión sea rehidratada por express.
Josh C.

Bueno, tenía la impresión de que los métodos serializeUser () y deserializeUser se ejecutaban en authenticate () dentro de las rutas.
Georges Krinker

@GeorgesKrinker No lo creo. Cuando usé el pasaporte, solo llamé a .authenticate al iniciar sesión.
Josh C.

app.post('/login', passport.authenticate('local'), ...
Josh C.

11

Mientras estarás usando PassportJs para validar al usuario como parte de su URL de inicio de sesión, aún necesita algún mecanismo para almacenar esta información de usuario en la sesión y recuperarla con cada solicitud posterior (es decir, serializar / deserializar el usuario).

Entonces, en efecto, está autenticando al usuario con cada solicitud, aunque esta autenticación no necesita buscar una base de datos u oauth como en la respuesta de inicio de sesión. Por lo tanto, el pasaporte tratará la autenticación de sesión también como otra estrategia de autenticación.

Y para usar esta estrategia, que se nombra session, simplemente use un atajo simple app.use(passport.session()). También tenga en cuenta que esta estrategia particular querrá que implemente funciones de serialización y deserialización por razones obvias.


11

Simplemente autentica la sesión (que está poblada por express.session()). Es equivalente a:

passport.authenticate('session');

como se puede ver en el código aquí:

https://github.com/jaredhanson/passport/blob/42ff63c/lib/authenticator.js#L233


6
¿Qué quieres decir? Se ejecuta en cada solicitud y no necesariamente tiene credenciales para autenticarse. ¿Le importaría darme un poco más de detalles sobre el flujo de trabajo que ocurre en cada solicitud?
Georges Krinker

6
Sí, se ejecuta en cada solicitud. El ID de sesión que genera Express es un ID único que equivale aproximadamente a un token de autenticación que el navegador envía con cada solicitud. Los datos almacenados en esta sesión se utilizan para restaurar el estado de autenticación del usuario.
Jared Hanson

Hola @JaredHanson ¿Podrías echarle un vistazo a esto ? ¿No pude encontrar la respuesta en ninguna parte?
Saras Arya

@JaredHanson Estoy tratando de usar passport.js para autenticarme con un servidor de autorización de código abierto ampliamente utilizado que cumple con OAuth2. Pero recibo un error. ¿Está dispuesto a ayudar a resolver el problema? Aquí está el enlace: stackoverflow.com/questions/38176236/…
DollarCoffee

@JaredHanson: Lo que observo es que el objeto req aumentado con información de passport.user justo después de iniciar sesión a través de google-oauth, se pierde cuando se realiza la siguiente solicitud de una nueva página en el sitio. ¿Es este el comportamiento esperado? ¿Entonces no sé cómo recuperar la información de usuario que inició sesión recientemente?
user1102171
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.