节点.js 使用护照进行身份验证:如果缺少字段,如何闪烁消息
Node.js Authentication with Passport: How to flash a message if a field is missing?
我正在使用护照.js如果我的表单字段为空,我想闪烁一条消息。但我不知道该怎么做,因为如果缺少这些,护照不会触发策略回调。我真的希望这个用例更清晰,我不想修改护照。我觉得有办法做到这一点,但我不知道在哪里!我尝试使用路由的回调(app.post
(,但它似乎没有按照我尝试的方式工作。
下面是身份验证函数原型:
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);
}
};
这是我的策略:
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);
});
}));
最后是我的路线:
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");
}));
您不应在验证回调中调用req.flash
。相反,您应该返回一条消息,如文档所示。护照将把返回的消息放到闪光消息时failureFlash: true
:
将
failureFlash
选项设置为true
指示 Passport 使用策略的验证回调(如果有(给出的消息闪烁错误消息。
修改后的验证回调:
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);
});
}));
和路线:
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
}));
编辑:
这是一个完全工作的示例:https://gist.github.com/vesse/9e23ff1810089bed4426
编辑:
这确实没有回答我正在使用护照的原始问题.js如果我的表单字段为空,我想闪烁一条消息。 passport-local
策略只是在表单字段为空的情况下执行fail
,因此应在身份验证中间件之前检查它们,并将闪存消息设置为护照之外。
这是一个老问题,但我很难找到答案。 希望这对其他人有所帮助。
我认为在使用connect-flash
时文档有点不完整。 他们说:
注意:使用 flash 消息需要 req.flash(( 函数。Express 2.x提供了此功能,但它已从Express 3.x中删除。使用 Express 3.x 时,建议使用连接闪存中间件来提供此功能。
然而,在done()
回调中没有提到使用 req.flash。 根据 scotch.io 教程,您实际上应该在回调中调用req.flash()
。 它对我有用。
// In your strategy
...
if (user) {
return done( null, false, req.flash('loginMessage','Pas d''utilisateur avec ce login.') );
...
当然,您将需要使用passReqToCallback
。 还要确保failureFlash
设置为 true
。 OP已经正确地做了这些。
现在,您可以检查路由中的闪烁消息。 请注意,connect-flash
会发送一系列消息。 这可能是OP的问题,如果他的模板需要一个字符串。
// 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!
});
});
如果页面上可能有多个登录消息,请传递整个req.flash('loginMessage')
数组并在模板中循环访问它。 下面是一个使用双节棍的示例。
专业提示:
如果有许多带有闪存消息的路由,则始终可以将它们设置为在中间件路由中res.locals
。 这不会干扰其他当地人,例如title
. 这是我使用引导警报的实现。
在我的策略中:
...
if (!user){
return done( null, false, req.flash('danger','No account exists for that email.') );
}
...
在我的路线中.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'});
});
在我的双节棍基本模板中:
<!--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 %}
设置badRequestMessage
并设置failureFlash: true
。
喜欢这个:
passport.authenticate('login', {
successRedirect : '/',
failureRedirect : '/login',
badRequestMessage : 'Missing username or password.',
failureFlash: true
})
经过几个月的断断续续地尝试让故障闪存工作,我终于找到了一个不使用故障闪存功能的解决方案。我基本上创建了一个新路由并发送了闪光消息。
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");
}
});
遇到了同样的问题,我解决了它。
您的成功消息和失败消息变量必须与护照 JS 使用的任何内容匹配。所以在玩了一会儿之后,我意识到护照JS正在使用变量成功来显示成功闪光灯和错误来显示失败闪光灯。
因此,首先,您可以在应用中创建一个这样的超级全局变量.js:
app.use(function(req, res, next) {
res.locals.error = req.flash("error");
res.locals.success = req.flash("success");
next();
});
然后在你的寺庙中使用这些变量。我正在使用 ejs,所以它看起来像这样:
<%if(error && error.length > 0){%>
<div class="alert alert-danger"><%=error%></div>
<%}%>
<%if(success && success.length > 0){%>
<div class="alert alert-success"><%=success%></div>
<%}%>
最后你的护照JS代码应该是这样的:
router.post("/login",passport.authenticate("local", {
successFlash : "Hey, Welcome back",
successRedirect : "/mountains",
failureFlash : true,
failureRedirect :"/login"
}), function(req, res){
});
我的解决方案
应用程序.js代码:
const flash = require('connect-flash');
app.use(flash());
require('./src/config/passport.js')(app);
local.strategy.js code
const passport = require('passport');
const { Strategy } = require('passport-local');
const userModel = require('./../../../models/userModel');
module.exports = function localStrategy() {
passport.use(new Strategy(
{
usernameField: "username",
passwordField: "password"
}, (username, password, done) => {
userModel.findOne({ username }, (err, user) => {
if (err) {
res.send(err);
}
if (user && (user.username == username && user.password == password)) {
done(null, user, { message: "Success" });
} else {
done(null, false, { message: "Invalid credentials!" });
}
});
}
));
}
身份验证控制器.js代码
function signIn(req, res) {
res.render('signin', {
nav,
title: "Sign in",
message: req.flash()
});
};
身份验证路由器.js代码
authRouter.route('/signin').get(signIn).post(passport.authenticate('local', {
successRedirect: '/admin',
failureRedirect: '/auth/signin',
failureFlash: true
}));
登录.js模板代码(我的视图引擎是 EJS(
<% if (message) { %>
<p style="color: red;" class="text-center"><%= message.error %></p>
<% } %>
当缺少身份验证所需的字段时,passport.authenticate
不会触发 OP 指出的策略回调。
这必须在身份验证函数的自定义回调(向下滚动页面(中使用 info
参数进行处理。
如果OP的代码如下所示:
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);
});
我知道这个问题很老了,但我自己偶然发现了这个问题,我看到仍然没有公认的答案。此外,我认为所有答案都误解了 OP 实际要求的内容 - 一种访问badRequestMessage
的方法。
PassportJS文档也不是很有帮助:
如果身份验证失败,用户将设置为 false。如果发生异常,将设置错误。将传递一个可选的 info 参数,其中包含策略的验证回调提供的其他详细信息。
这实际上意味着info
参数可以作为第三个参数从您的策略中传递,如下所示: done(error,user,info)
,但没有提及在缺少凭据的情况下默认使用此参数。总的来说,我认为 PassportJS 文档可以进行一些大修,因为它们缺乏细节并链接到不存在的示例。
这个答案帮助我了解缺少凭据消息是在 info
参数中传递的。
- 将输入字段中的文本提交到我的数据库,同时将其添加到我的列表中
- 而循环只设置php中输入字段中的第一个值
- 在输入字段中将最小金额设置为
- 从Rally获取一个特定的标记,以便计算另一个字段中的值
- 如何在输入字段中的按钮的帮助下打开日历,该字段的类型为“=”;日期”;
- JavaScript 检查隐藏字段中的值并将其设置为隐藏字段值
- 在wordpress一定时间后更改自定义字段
- 如何在HTML输入字段中添加不可删除的后缀
- Meteor-添加用户自定义字段的方法不起作用
- 互斥单选按钮和相应的输入字段
- 在IE9中的输入字段中输入焦点最近按钮
- 选中单选框时将属性添加到输入字段
- 带有验证和隐藏字段值的提交按钮
- 主干窗体隐藏字段未呈现
- 如何从只读字段中删除闪烁的光标
- 可编辑 - 输入字段上的最大长度,模糊时闪烁
- 如何修复使用我们的默认值/占位符插件的输入字段时的闪烁效果
- 节点.js 使用护照进行身份验证:如果缺少字段,如何闪烁消息
- 单击按钮可打开带有闪烁光标的输入字段
- 无论何时点击后退按钮,清除表单中的所有字段