Ich verwende passport.js und ich möchte eine Nachricht flashen, wenn die Felder meines Formulars leer sind. Aber ich weiß nicht, wie das geht, da der Pass nicht den Strategie-Callback auslöst, wenn er fehlt. Ich möchte, dass dieser Anwendungsfall klarer wird, und ich möchte keinen Pass ändern. Ich habe das Gefühl, dass es einen Weg gibt, aber ich weiß nicht wo! Ich habe versucht, den Rückruf der Route (app.post
) zu verwenden, aber es scheint nicht so zu funktionieren, wie ich es versucht habe.
Hier ist der Prototyp der Authentifizierungsfunktion:
Strategy.prototype.authenticate = function(req, options) {
options = options || {};
var username = lookup(req.body, this._usernameField) || lookup(req.query, this._usernameField);
var password = lookup(req.body, this._passwordField) || lookup(req.query, this._passwordField);
// here is my problem
if (!username || !password) {
return this.fail({ message: options.badRequestMessage || 'Missing credentials' }, 400);
}
var self = this;
function verified(err, user, info) {
if (err) { return self.error(err); }
if (!user) { return self.fail(info); }
self.success(user, info);
}
try {
if (self._passReqToCallback) {
this._verify(req, username, password, verified);
} else {
this._verify(username, password, verified);
}
} catch (ex) {
return self.error(ex);
}
};
Hier ist meine Strategie:
passport.use('local-login', new LocalStrategy({
usernameField : 'email',
passwordField : 'password',
passReqToCallback : true
},
function(req, email, password, done) {
// ...
console.log("Hello");
User.findOne({ 'local.email' : email }, function(err, user) {
if (err)
return done(err);
// if no user is found, return the message
if (!user)
return done(null, false, req.flash('loginMessage', 'Pas d\'utilisateur avec ce login.')); // req.flash is the way to set flashdata using connect-flash
// if the user is found but the password is wrong
if (!user.validPassword(password))
return done(null, false, req.flash('loginMessage', 'Oops! Mauvais password.')); // create the loginMessage and save it to session as flashdata
// all is well, return successful user
return done(null, user);
});
}));
Und zum Schluss meine Route:
app.get('/login', function(req, res) {
// render the page and pass in any flash data if it exists
res.render('login', { title: "Connexion", message: req.flash('loginMessage') });
});
// process the login form
app.post('/login', passport.authenticate('local-login', {
successRedirect : '/profile', // redirect to the secure profile section
failureRedirect : '/login', // redirect back to the signup page if there is an error
failureFlash : true // allow flash messages
}, function(err, user, info) {
// Was trying this callback, does'nt work, post callback maybe ?
console.log("Hello");
}));
Sie sollten in Ihrem Überprüfungsrückruf nicht req.flash
aufrufen. Stattdessen sollten Sie eine Nachricht wie in der Dokumentation gezeigt zurückgeben. Passport legt die Nachricht als Flash-Nachricht zurück, wenn failureFlash: true
.
Ihr überarbeiteter Überprüfungsrückruf:
passport.use('local-login', new LocalStrategy({...},
function(email, password, done) {
User.findOne({ 'local.email' : email }, function(err, user) {
if (err)
return done(err);
if (!user)
return done(null, false, {message: 'Pas d\'utilisateur avec ce login.'});
if (!user.validPassword(password))
return done(null, false, {message: 'Oops! Mauvais password.'});
return done(null, user);
});
}));
Und Routen:
app.get('/login', function(req, res) {
console.log(req.flash('error'));
res.send();
});
app.post('/login', passport.authenticate('local-login', {
successRedirect : '/profile',
failureRedirect : '/login',
failureFlash : true
}));
Bearbeiten:
Hier ein voll funktionsfähiges Beispiel: https://Gist.github.com/vesse/9e23ff1810089bed4426
Es ist eine alte Frage, aber ich hatte Schwierigkeiten, eine Antwort zu finden. Hoffentlich hilft das anderen.
Ich denke, die Dokumentation ist ein wenig unvollständig, wenn es um die Verwendung von connect-flash
geht. Man sagt:
Hinweis: Die Verwendung von Flash-Nachrichten erfordert eine Funktion req.flash (). Express 2.x stellte diese Funktionalität zur Verfügung, wurde jedoch aus Express 3.x entfernt. Es wird empfohlen, Connect-Flash-Middleware zu verwenden, um diese Funktionalität bei der Verwendung von Express 3.x bereitzustellen.
Die Verwendung von req.flash im done()
-Rückruf wird jedoch nicht erwähnt. Basierend auf dem scotch.io-Tutorial , müssen Sie tatsächlich sollte Aufruf req.flash()
direkt im Callback aufrufen. Für mich geht das.
// In your strategy
...
if (user) {
return done( null, false, req.flash('loginMessage','Pas d\'utilisateur avec ce login.') );
...
Sie müssen natürlich passReqToCallback
verwenden. Stellen Sie außerdem sicher, dass failureFlash
auf true
eingestellt ist. OP macht das schon richtig.
Jetzt können Sie die Flash-Nachricht in der Route überprüfen. Beachten Sie, dass connect-flash
ein Array von Nachrichten sendet. Das könnte das Problem von OP sein, wenn seine Vorlage eine Zeichenfolge erwartet.
// In your routes
app.get('/login', function(req, res) {
// Test flash messages in the console
console.log( req.flash('loginMessage') ); // This returns an array
console.log( req.flash('loginMessage')[0] ); // This returns a string
// render the page and pass in any flash data if it exists
res.render('login', {
title: "Connexion",
message: req.flash('loginMessage')[0] // Don't forget the index!
});
});
Wenn die Möglichkeit besteht, dass mehrere Anmeldungsnachrichten auf einer Seite angezeigt werden, übergeben Sie das gesamte req.flash('loginMessage')
-Array und durchlaufen Sie es in Ihrer Vorlage. Unten ist ein Beispiel mit nunjucks .
Protip:
Wenn Sie viele Routen mit Flash-Nachrichten haben, können Sie diese immer in einer Middleware-Route auf res.locals
setzen. Dies wirkt sich nicht auf andere Einheimische aus, wie title
. Hier ist meine Implementierung mit bootstrap alerts .
In meiner Strategie:
...
if (!user){
return done( null, false, req.flash('danger','No account exists for that email.') );
}
...
In meinen routen.js:
// Set flash messages
router.get('*', function(req,res,next){
res.locals.successes = req.flash('success');
res.locals.dangers = req.flash('danger');
res.locals.warnings = req.flash('warning');
next();
});
// Login route
app.get('/login', function(req, res) {
res.render('login', { title: 'Login'});
});
In meiner Nunjucks-Basisvorlage:
<!--Messages-->
{% for danger in dangers %}
<div class='header alert alert-danger alert-dismissible'>
<strong><i class="fa fa-exclamation-circle"></i> ERROR:</strong> {{ danger | safe }}
<a href="#" class='close' data-dismiss="alert" aria-label="close"><i class='fa fa-times'></i></a>
</div>
{% endfor %}
{% for warning in warnings %}
<div class='header alert alert-warning alert-dismissible'>
<strong><i class="fa fa-check-circle"></i> Warning:</strong> {{ warning | safe }}
<a href="#" class='close' data-dismiss="alert" aria-label="close"><i class='fa fa-times'></i></a>
</div>
{% endfor %}
{% for success in successes %}
<div class='header alert alert-success alert-dismissible'>
<strong><i class="fa fa-check-circle"></i> Success!</strong> {{ success | safe }}
<a href="#" class='close' data-dismiss="alert" aria-label="close"><i class='fa fa-times'></i></a>
</div>
{% endfor %}
Sie müssen badRequestMessage
und failureFlash: true
einstellen.
So was:
passport.authenticate('login', {
successRedirect : '/',
failureRedirect : '/login',
badRequestMessage : 'Missing username or password.',
failureFlash: true
})
Nach monatelangem Ein- und Ausschalten des Versagens von Failure Flash habe ich endlich eine Lösung gefunden, die die FailureFlash-Funktion nicht verwendet. Ich habe im Grunde eine neue Route erstellt und die Flash-Nachricht gesendet.
app.post('/login',
passport.authenticate('local', {failureRedirect: "/loginfailed"}),
function(req, res) {
if (!req.user.isActive){
req.flash("success","Your account needs to be verified. Please check your email to verify your account");
req.logout();
res.redirect("back")
}else{
res.redirect("/");
}
});
//Route to login page if user failed to login. I created this to allow flash messages and not interfere with regular login route
app.get("/loginfailed", function(req, res){
if (!req.user){
req.flash("success", "Username or password is incorrect.");
res.redirect("/login");
}
});
Wenn Felder fehlen, die für die Authentifizierung erforderlich sind, löst passport.authenticate
den Strategie-Callback nicht aus, wie das OP zeigt.
Dies muss innerhalb der benutzerdefinierten Rückruf (Seite nach unten rollen) der Authentifizierungsfunktion mit dem Parameter info
behandelt werden.
Falls der OP-Code wie folgt lautet:
app.post('/login', function (req, res, next) {
passport.authenticate('local-login',
{
successRedirect: '/profile',
failureRedirect: '/login',
failureFlash: true,
},
function (error, user, info) {
//This will print: 'Missing credentials'
console.log(info.message);
//So then OP could do something like
req.flash(info.message);
//or in my case I didn't use flash and just did
if (info)
res.status(400).send(info.message);
...
})(req, res, next);
});
Ich weiß, dass diese Frage alt ist, aber ich bin selbst auf dieses Thema gestoßen und sehe, dass es immer noch keine akzeptierte Antwort gibt. Des Weiteren denke ich, dass alle Antworten falsch interpretiert haben, wonach das OP eigentlich gefragt hat - eine Möglichkeit, auf badRequestMessage
zuzugreifen.
PassportJS-Dokumente sind auch nicht sehr hilfreich:
Wenn die Authentifizierung fehlgeschlagen ist, wird der Benutzer auf "false" gesetzt. Wenn eine Ausnahme aufgetreten ist, wird err gesetzt. Es wird ein optionales Info-Argument übergeben, das zusätzliche Informationen enthält, die vom Überprüfungsrückruf der Strategie bereitgestellt werden.
Dies bedeutet eigentlich, dass der Parameter info
als dritter Parameter aus Ihrer Strategie übergeben werden kann, wie folgt: done(error,user,info)
. Er erwähnt jedoch nicht, dass dieser Parameter standardmäßig verwendet wird, wenn Anmeldeinformationen fehlen. Insgesamt denke ich, dass PassportJS-Dokumente mit einigen Überholungen fertig werden könnten, da ihnen Details und Link zu nicht vorhandenen Beispielen fehlen.
Diese Antwort hat mir geholfen zu verstehen, dass die fehlende Anmeldeinformationsnachricht im Parameter info
übergeben wird.
Ich hatte das gleiche Problem und ich habe es gelöst.
Ihre Erfolgs- und Misserfolgsmeldungsvariablen müssen mit dem von JS verwendeten Pass übereinstimmen. Nach dem Herumspielen stelle ich fest, dass Passport JS die Variable Erfolg verwendet, um den Erfolgsblitz anzuzeigen, und Fehler, um den Fehlerblitz anzuzeigen.
Als erstes können Sie eine super globale Variable wie diese in Ihrer app.js erstellen:
app.use(function(req, res, next) {
res.locals.error = req.flash("error");
res.locals.success = req.flash("success");
next();
});
Dann benutze diese Variablen in deinem Tempel. Ich benutze EJS, so sieht es so aus:
<%if(error && error.length > 0){%>
<div class="alert alert-danger"><%=error%></div>
<%}%>
<%if(success && success.length > 0){%>
<div class="alert alert-success"><%=success%></div>
<%}%>
Und schließlich sollte Ihr Passport-JS-Code so lauten:
router.post("/login",passport.authenticate("local", {
successFlash : "Hey, Welcome back",
successRedirect : "/mountains",
failureFlash : true,
failureRedirect :"/login"
}), function(req, res){
});