node.js - node - Pasaporte de inicio de sesión y sesión persistente
passport local mongoose (5)
Como dice @hassansin, debe usar un middleware que implemente la administración de sesiones. El middleware passport.session () es conectar el marco del pasaporte a la administración de la sesión y no implementar la sesión por sí solo. Puede utilizar el middleware de express-session
rápida para implementar la administración de la sesión. Necesitas modificar tu auth.js de la siguiente manera
var passport = require(''passport'');
var session = require(''express-session'');
var LocalStrategy = require(''passport-local'').Strategy;
module.exports = function(app, user){
app.use(session({secret: ''some secret value, changeme''}));
app.use(passport.initialize());
app.use(passport.session());
// passport config
passport.use(new LocalStrategy(user.authenticate()));
passport.serializeUser(function(user, done) {
console.log(''serializing user: '');
console.log(user);
done(null, user._id);
});
passport.deserializeUser(function(id, done) {
user.findById(id, function(err, user) {
console.log(''no im not serial'');
done(err, user);
});
});
};
Tenga en cuenta que, en este caso, el motor de sesión está utilizando el almacén de memoria y no funcionó si escala su aplicación y aplica el equilibrio de carga. Cuando llegue a este estado de desarrollo, se necesitará algo como el almacén de sesión de connect-redis
.
También tenga en cuenta que necesita cambiar el valor secreto utilizado en la sesión de midleware de sesión y usar el mismo valor en todas las instancias de la aplicación.
Fondo
Tengo una aplicación MEAN con capacidades CRUD completamente probada con cartero. He intentado persistir el inicio de sesión durante bastante tiempo sin suerte. He leído y probado lo siguiente
- documentos de pasaporte
- El blog de toon io sobre login
- Sesion express
- Scotch io, la autenticación de nodo hecho fácil
- Más un montón de otros materiales de lectura ligeros (muchas preguntas SO)
Pero solo he podido registrar e iniciar sesión en un usuario, no persistir el inicio de sesión con una sesión.
Mi app
Here hay un enlace al repositorio completo de github (si está buscando los últimos cambios verifique la rama de desarrollo)
Mi comprensión de la autenticación / inicio de sesión
Esta es mi comprensión del inicio de sesión del usuario con ejemplos de código de mi proyecto y captura de pantalla de los resultados del cartero, así como los registros de la consola.
Configuración de pasaporte
Tengo el siguiente archivo auth.js, que configura el pasaporte
var passport = require(''passport'');
var LocalStrategy = require(''passport-local'').Strategy;
module.exports = function(app, user){
app.use(passport.initialize());
app.use(passport.session());
// passport config
passport.use(new LocalStrategy(user.authenticate()));
passport.serializeUser(function(user, done) {
console.log(''serializing user: '');
console.log(user);
done(null, user._id);
});
passport.deserializeUser(function(id, done) {
user.findById(id, function(err, user) {
console.log(''no im not serial'');
done(err, user);
});
});
};
Esto se llama en el archivo del servidor como
//code before
var user = require(''./models/user.js'');
var auth = require(''./modules/auth.js'')(app, user);
// code after
Enrutamiento para inicio de sesión
En mis rutas tengo la ruta de inicio de sesión de la siguiente manera
router.post(''/login'', function(req, res, next) {
passport.authenticate(''local'', function(err, user, info) {
if (err) {
return next(err);
}
if (!user) {
return res.status(401).json({
err: info
});
}
req.logIn(user, function(err) {
if (err) {
return res.status(500).json({
err: ''Could not log in user''
});
}
res.status(200).json({
status: ''Login successful!''
});
});
})(req, res, next);
});
Esta ruta funciona según lo probado con el cartero. Ingreso los detalles ''joe'' y ''pass'' y obtengo la siguiente respuesta.
Cuando se llega a esta ruta, también podemos ver en la consola que el usuario está serializado.
Entonces, ¿qué sigue?
Aquí es donde me pierdo. Tengo algunas preguntas.
- ¿Está el usuario ahora en una sesión en mi servidor?
- ¿Debo enviar el
req.session.passport.user
nuevo al cliente? - ¿Necesito el ID de sesión en todas las solicitudes futuras?
Probando la sesión
Tengo una segunda configuración de ruta para probar la sesión es la siguiente
router.get(''/checkauth'', passport.authenticate(''local''), function(req, res){
res.status(200).json({
status: ''Login successful!''
});
});
La parte passport.authenticate(''local'')
(pensé) está ahí para probar si la sesión del usuario existe antes de dar acceso a la ruta, pero nunca obtengo una respuesta 200 cuando ejecuto esto, incluso después de iniciar sesión.
¿ req.session.passport.user
esta ruta un req.session.passport.user
pasado en la cabeza o como un argumento de datos en una solicitud http que requiere autenticación?
Si me he perdido algo o estoy entendiendo algo mal, por favor, dígame, cualquier comentario es apreciado. Gracias a todos.
No conozco una forma de verificar todas las sesiones existentes, pero Passport está manejando la emisión de identificadores de sesión. Intente verificar que tiene el usuario requerido en su punto final de prueba después de iniciar sesión
Passport.js no funciona bien ya que almacena la sesión en el servidor (mal y no es escalable). No desea almacenar ningún dato de sesión en el servidor (manteniéndolo sin estado) ya que puede ampliar sus clústeres y manejar más solicitudes.
Si observa el código en la biblioteca Passport.js, no hay mucho ... Construirlo usted mismo puede ser más rápido y más eficiente.
Aquí hay un tutorial que escribí sobre la conexión a Google de una manera mucho mejor .
Según la documentación del pasaporte , req.user
se configurará para el usuario autenticado. Sin embargo, para que esto funcione, necesitará el módulo de express-session
rápida. No debe necesitar nada más que lo que ya tiene para que el pasaporte funcione.
En lo que respecta a la prueba de la sesión, puede tener una función de middleware que verifique si req.user está configurado, si lo está, sabemos que el usuario está autenticado y si no lo está, puede redirigirlo.
Por ejemplo, podría tener una función de middleware que pueda usar en cualquier ruta que desee autenticar.
authenticated.js
module.exports = function (req, res, next) {
// if user is authenticated in the session, carry on
if (req.user) {
next();
}
// if they aren''t redirect them to the login page
else {
res.redirect(''/login'');
}
};
controlador
var authenticated = require(''./authenticated'');
router.get(''/protectedpage'', authenticated, function(req, res, next) {
//Do something here
});
¿Está el usuario ahora en una sesión en mi servidor?
No, debe usar el middleware de express-session
app.use(passport.session());
antes de app.use(passport.session());
para almacenar realmente la sesión en la memoria / base de datos. Este middleware es responsable de configurar las cookies para los navegadores y convierte las cookies enviadas por los navegadores en req.session
objeto req.session
. PassportJS solo usa ese objeto para deserializar aún más al usuario.
¿Debo enviar el req.session.passport.user de nuevo al cliente?
Si su cliente espera un recurso de user
al iniciar sesión, debería hacerlo. De lo contrario, no veo ninguna razón para enviar el objeto de usuario al cliente.
¿Necesito el ID de sesión en todas las solicitudes futuras?
Sí, para todas las solicitudes futuras, se requiere el ID de sesión. Pero si su cliente es un navegador, no necesita enviar nada. El navegador almacenará el ID de sesión como cookie y lo enviará para todas las solicitudes posteriores hasta que la cookie caduque. express-session
leerá esa cookie y adjuntará el objeto de sesión correspondiente como req.session
.
Probando la sesión
passport.authenticate(''local'')
es para autenticar las credenciales de usuario del cuerpo de POST. Debe usar esto solo para la ruta de inicio de sesión.
Pero para verificar si el usuario está autenticado en todas las demás rutas, puede verificar si req.user
está definido.
function isAuthenticated = function(req,res,next){
if(req.user)
return next();
else
return res.status(401).json({
error: ''User not authenticated''
})
}
router.get(''/checkauth'', isAuthenticated, function(req, res){
res.status(200).json({
status: ''Login successful!''
});
});