javascript - 如何处理 passport.deserializeUser() 中的错误?

标签 javascript node.js passport.js

我已经像这样配置了 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/

相关文章:

javascript - 使用不同颜色的标记在 <canvas> 上绘图 html2canvas.js

node.js - 如何使用 Electron 运行tensorflow.js?

node.js - 保存首次登录历史记录后 ExpressJS 应用程序登录失败

javascript - Passport 文档中的 var User 来自哪里

javascript - 可以从点击的类中获取 ID,但不能从点击的 ID 中获取类

javascript - 从另一个数组中存在的数组中获取所有相同元素的最快方法

javascript - 如何使用 for Each 在 json 中添加特定值

node.js - Docker-compose up 以代码 1 退出,但 docker-compose build 成功

javascript - 如何在每个新月安排 node-cron 作业?

javascript - Passport 身份验证回调挂起