我已经像这样配置了 Express 和 Passport:
var express = require("express");
var site = express();
var flash = require("connect-flash");
var passport = require("passport");
site.use(require("cookie-parser")());
site.use(require("body-parser").urlencoded({extended:false}));
site.use(require("express-session")(...));
site.use(flash());
site.use(passport.initialize());
site.use(passport.session());
我有一个非常常用的 deserializeUser
实现(我正在使用由 MySQL 通过 Bookshelf 支持的 local
身份验证):
var db = require("./database.js"); // exports models e.g. db.User
passport.deserializeUser(function(id, done) {
db.User.findById(id).then(function (user) {
done(null, user);
}).catch(function (err) {
done(err, null);
});
});
我遇到了以下特定问题:当登录用户从数据库中删除时(例如,站点管理员删除用户时发生),反序列化失败,如预期的那样,出现 CustomError ("EmptyResponse")
来自 Bookshelf。但是,我不知道如何处理它; done(err, null)
最终只会导致错误消息和堆栈跟踪以 HTML 格式发送回客户端。
问题是:如何在失败时从 deserializeUser
提供自定义的、优雅的错误处理?
现在,如果它简化了事情,我可以将 {require:false}
添加到 db.User.findById
调用中给我一个 null
用户而不是错误,但我仍然不知道如何处理它(而且我仍然需要处理错误对象,例如,如果数据库服务器关闭并且存在连接错误)。
我想在失败时采取的行动是将用户重定向回登录页面,可能带有描述性的闪存消息,但我无权访问 deserializeUser
中的请求/响应> 我不确定如何回复。
最佳答案
我找到了一个解决方案。这里的错误可以在 Express 中间件错误处理程序中处理。所以,例如:
// Note: Must be used *after* passport middleware.
site.use(function(err, req, res, next) {
if (err) {
// Handle deserialization errors here.
} else {
next();
}
});
一个重要的警告是,如果反序列化失败不可恢复,所有通过 Passport 访问的路由(即使是不需要身份验证的路由)将继续失败,这很可能还包括您的登录和注销端点,从而永久中断访问,直到用户清除他们的 cookie。所以你必须强制注销,这是唯一真正的恢复方法:
site.use(function(err, req, res, next) {
if (err) {
req.logout(); // So deserialization won't continue to fail.
} else {
next();
}
});
在此基础上进一步构建,在我的例子中,我想用一条闪现消息重定向回登录页面。但您必须小心:如果登录页面本身发生错误,您需要避免无限重定向,因此:
site.use(function(err, req, res, next) {
if (err) {
req.logout();
if (req.originalUrl == "/loginpage") {
next(); // never redirect login page to itself
} else {
req.flash("error", err.message);
res.redirect("/loginpage");
}
} else {
next();
}
});
当然,您可能只想对 CustomError("EmptyResponse")
执行此操作,或者甚至在反序列化实现中重做错误处理,让它抛出您自己的更具体的错误。
有点奇怪的方法,但似乎可以完成工作。接受更清洁的建议。
关于javascript - 如何处理 passport.deserializeUser() 中的错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41069593/