J'ai une application MEAN avec des fonctionnalités CRUD entièrement testée avec postman. J'essaie de continuer à me connecter depuis un certain temps, sans succès. J'ai lu et essayé ce qui suit
Mais j’ai seulement été capable d’enregistrer et de connecter un utilisateur, et non de rester connecté avec une session.
Ici est un lien vers le dépôt complet de github (si vous recherchez les dernières modifications, vérifiez développer une branche)
Voici ma compréhension de la connexion de l'utilisateur avec des exemples de code de mon projet et une capture d'écran des résultats du facteur ainsi que les journaux de la console.
J'ai le fichier auth.js suivant, il configure le passeport
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);
});
});
};
Ceci est appelé dans le fichier serveur comme
//code before
var user = require('./models/user.js');
var auth = require('./modules/auth.js')(app, user);
// code after
Dans mes itinéraires, j'ai l'itinéraire de connexion comme suit
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);
});
Cette route fonctionne telle que testée avec le facteur. J'entre les détails 'joe' et 'pass' et j'obtiens la réponse suivante.
Lorsque cette route est atteinte, nous pouvons également voir dans la console que l’utilisateur est sérialisé.
C'est là que je me perds. J'ai quelques questions.
req.session.passport.user
au client?J'ai une deuxième configuration de route pour tester la session:
router.get('/checkauth', passport.authenticate('local'), function(req, res){
res.status(200).json({
status: 'Login successful!'
});
});
La partie passport.authenticate('local')
(je pensais) est là pour tester si la session utilisateur existe avant de donner accès à la route, mais je ne reçois jamais de réponse 200 lorsque je lance ceci, même après une connexion.
Est-ce que cette route attend un req.session.passport.user
passé en tête ou un argument de données sur une requête http nécessitant une autorisation?
Si quelque chose me manque ou si je comprends quelque chose qui ne va pas, dites-le-moi, toute contribution est la bienvenue. Merci a tous.
L'utilisateur est-il maintenant en session sur mon serveur?
Non, vous devez utiliser le middleware express-session
avant app.use(passport.session());
pour stocker la session dans la mémoire/la base de données. Ce middleware est responsable de la configuration des cookies pour les navigateurs et convertit les cookies envoyés par les navigateurs en un objet req.session
. PassportJS utilise uniquement cet objet pour désérialiser davantage l'utilisateur.
Devrais-je envoyer le req.session.passport.user au client?
Si votre client attend une ressource user
lors de la connexion, vous devriez le faire. Sinon, je ne vois aucune raison d'envoyer l'objet utilisateur au client.
Ai-je besoin de l'identifiant de session pour toutes les futures demandes?
Oui, pour toutes les futures demandes, l'identifiant de session est requis. Mais si votre client est un navigateur, vous n'avez rien à envoyer. Le navigateur stockera l'identifiant de session en tant que cookie et l'enverra pour toutes les demandes ultérieures jusqu'à l'expiration du cookie. express-session
lira ce cookie et joindra l'objet de session correspondant sous la forme req.session
.
Tester la session
passport.authenticate('local')
sert à authentifier les informations d'identification de l'utilisateur à partir du corps POST. Vous devriez utiliser ceci uniquement pour la route de connexion.
Mais pour vérifier si l'utilisateur est authentifié sur toutes les autres routes, vous pouvez vérifier si req.user
est défini.
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!'
});
});
Comme @hassansin dit que vous devez utiliser un middleware qui implémente la gestion de session. Le middleware passport.session () consiste à connecter la structure de passeport à la gestion de session et à ne pas implémenter la session elle-même. Vous pouvez utiliser le middleware express-session
pour implémenter la gestion de session. Vous devez modifier votre auth.js de la manière suivante
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);
});
});
};
Notez que dans ce cas, le moteur de session utilise le magasin en mémoire et ne fonctionne pas si vous redimensionnez votre application et appliquez un équilibrage de charge. Lorsque vous atteignez cet état de développement, il vous faudra quelque chose comme le connect-redis
session store .
Notez également que vous devez modifier la valeur secrète utilisée lors de l'appel du midleware de session et utiliser la même valeur sur toutes les instances d'application.
Conformément à la documentation passport , req.user
sera défini sur l'utilisateur authentifié. Pour que cela fonctionne, vous aurez besoin du module express-session
. Vous ne devriez avoir besoin de rien d'autre que ce que vous avez déjà pour que votre passeport fonctionne.
En ce qui concerne le test de la session, vous pouvez avoir une fonction middleware qui vérifie si req.user est défini. Si c'est le cas, nous savons que l'utilisateur est authentifié et si ce n'est pas le cas, vous pouvez le rediriger.
Vous pouvez par exemple avoir une fonction de middleware que vous pouvez utiliser sur toutes les routes que vous souhaitez authentifier.
authentifié.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');
}
};
manette
var authenticated = require('./authenticated');
router.get('/protectedpage', authenticated, function(req, res, next) {
//Do something here
});