[英]Express Passport (node.js) error handling
I've looked at how error handling should work in node via this question Error handling principles for Node.js + Express.js applications?我已经通过这个问题Error handling principles for Node.js + Express.js applications? 研究了错误处理应该如何在节点中工作? , but I'm not sure what passport's doing when it fails authentication.
,但我不确定护照在身份验证失败时在做什么。 I have the following LocalStrategy:
我有以下 LocalStrategy:
passport.use(new LocalStrategy({ usernameField: 'email', passwordField: 'password' },
function(email, password, next) {
User.find({email: UemOrUnm}, function(err, user){
if (err) { console.log('Error > some err'); return next(err); }
if (!user) { console.log('Error > no user'); return next('Incorrect login or password'); }
if (password != user.password) {
return next(Incorrect login or password);
}
return next(null, user);
});
}
));
After I see 'Error > some err' console printout, nothing else happens.在我看到“Error > some err”控制台打印输出后,没有其他事情发生。 I would think it should continue on the the next path with an error parameter, but it doesn't seem to do that.
我认为它应该在带有错误参数的下一条路径上继续,但它似乎并没有这样做。 What's going on?
这是怎么回事?
The strategy-implementation works in conjunction with passport.authenticate
to both authenticate a request, and handle success/failure.策略实现与
passport.authenticate
结合使用以验证请求并处理成功/失败。
Say you're using this route (which is passed an e-mail address and a password):假设您正在使用此路由(通过电子邮件地址和密码):
app.post('/login', passport.authenticate('local', {
successRedirect: '/loggedin',
failureRedirect: '/login', // see text
failureFlash: true // optional, see text as well
});
This will call the code in the strategy, where one of three conditions can happen:这将调用策略中的代码,其中可能发生以下三种情况之一:
next(err)
;next(err)
; this will be handled by Express and generate an HTTP 500 response;false
as the user object: next(null, false)
;false
作为用户对象传递: next(null, false)
; this will trigger the failureRedirect
(if you don't define one, a HTTP 401 Unauthorized response will be generated);failureRedirect
(如果您没有定义,则会生成 HTTP 401 Unauthorized 响应);next(null, user)
;next(null, user)
; this will trigger the successRedirect
;successRedirect
; In case of an invalid authentication (but not an internal error), you can pass an extra message along with the callback:如果身份验证无效(但不是内部错误),您可以随回调传递额外的消息:
next(null, false, { message : 'invalid e-mail address or password' });
If you have used failureFlash
and installed the connect-flash middleware , the supplied message is stored in the session and can be accessed easily to, for example, be used in a template.如果您使用了
failureFlash
并安装了 connect-flash 中间件,则提供的消息将存储在会话中,并且可以轻松访问,例如,在模板中使用。
EDIT: it's also possible to completely handle the result of the authentication process yourself (instead of Passport sending a redirect or 401):编辑:也可以自己完全处理身份验证过程的结果(而不是 Passport 发送重定向或 401):
app.post('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) {
return next(err); // will generate a 500 error
}
// Generate a JSON response reflecting authentication status
if (! user) {
return res.send({ success : false, message : 'authentication failed' });
}
// ***********************************************************************
// "Note that when using a custom callback, it becomes the application's
// responsibility to establish a session (by calling req.login()) and send
// a response."
// Source: http://passportjs.org/docs
// ***********************************************************************
req.login(user, loginErr => {
if (loginErr) {
return next(loginErr);
}
return res.send({ success : true, message : 'authentication succeeded' });
});
})(req, res, next);
});
What Christian was saying was you need to add the function Christian 所说的是你需要添加函数
req.login(user, function(err){
if(err){
return next(err);
}
return res.send({success:true});
});
So the whole route would be:所以整个路线将是:
app.post('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) {
return next(err); // will generate a 500 error
}
// Generate a JSON response reflecting authentication status
if (! user) {
return res.send(401,{ success : false, message : 'authentication failed' });
}
req.login(user, function(err){
if(err){
return next(err);
}
return res.send({ success : true, message : 'authentication succeeded' });
});
})(req, res, next);
});
source: http://passportjs.org/guide/login/来源: http : //passportjs.org/guide/login/
You need to add req.logIn(function (err) { });
您需要添加
req.logIn(function (err) { });
and do the success redirect inside the callback function并在回调函数中执行成功重定向
Some time has passed and now the most right code will be:一段时间过去了,现在最正确的代码是:
passport.authenticate('local', (err, user, info) => {
if (err) {
return next(err); // will generate a 500 error
}
// Generate a JSON response reflecting authentication status
if (!user) {
return res.status(401).send({ error: 'Authentication failed' });
}
req.login(user, (err) => {
if (err) {
return next(err);
}
return res.status(202).send({ error: 'Authentication succeeded' });
});
});
I found this thread very useful!我发现这个线程非常有用!
https://github.com/jaredhanson/passport-local/issues/2 https://github.com/jaredhanson/passport-local/issues/2
You could use this to return error and render it in form.您可以使用它来返回错误并以形式呈现。
app.post('/login',
passport.authenticate('local', { successRedirect: '/home', failWithError: true }),
function(err, req, res, next) {
// handle error
return res.render('login-form');
}
);
This is what I got after console.log(req)
at the failler route.这是我在 failler 路由的
console.log(req)
之后得到的。
const localStrategy = new LocalStrategy({ usernameField: "email" }, verifyUser);
passport.use(localStrategy);
const authenticateWithCredentials = passport.authenticate("local", {
failureRedirect: "/api/auth/login-fail",
failureMessage: true,
});
validation method find your user from db and throw error to the cb if there is any验证方法从 db 中找到您的用户,如果有任何错误,则向 cb 抛出错误
const verifyUser = async (email, password, cb) => {
const user = await User.findOne({ email });
if (!user) return cb(null, false, { message: "email/password incorrect!" });
const isMatched = await user.comparePassword(password);
if (!isMatched)
return cb(null, false, { message: "email/password incorrect!" });
cb(null, {
id: user._id,
email,
name: user.name,
});
};
now setup your route现在设置你的路线
router.post("/sign-in", authenticateWithCredentials,(req, res) => {
res.json({user: req.user})
});
router.get("/login-fail", (req, res) => {
let message = "Invalid login request!";
// if you are using typescript cast the sessionStore to any
const sessions = req.sessionStore.sessions || {};
for (let key in sessions) {
const messages = JSON.parse(sessions[key])?.messages;
if (messages.length) {
message = messages[0];
break;
}
}
res.status(401).json({ error: message });
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.