首页 > 解决方案 > Passport JS 身份验证问题 - 在 NodeJS 上运行 - 在 Heroku 上出现错误 503 - H13

问题描述

我已经搜索并阅读了许多类似的情况,但没有一个与我的非常相似。我用 PostgreSQL 数据库创建了一个在 NodeJS 上运行的 API。我已经使用护照与本地护照进行身份验证。

这是我声明 Passport 配置的地方:

const express = require("express");

const auth = express.Router();

const bcrypt = require("bcrypt");
const pool = require("../../config/dbConfig");
require("dotenv").config();
const session = require("express-session");
const flash = require("express-flash");
const passport = require("passport");

const initializePassport = require("../../config/passportConfig");

initializePassport(passport);

auth.use(express.urlencoded({ extended: false }));
auth.use(
  session({
    secret: process.env.SESSION_SECRET,
    resave: false,
    saveUninitialized: false,
  })
);

auth.use(passport.initialize());
auth.use(passport.session());
auth.use(flash());

const checkAuthenticated = (req, res, next) => {
  if (req.isAuthenticated()) {
    return res.redirect("/api/auth/dashboard");
  }
  next();
};

const checkNotAuthenticated = (req, res, next) => {
  if (req.isAuthenticated()) {
    next();
  }
  res.redirect("/api/auth/login");
};

auth.get("/", (req, res) => {
  res.redirect("/api/auth/login");
});
auth.get("/login", checkAuthenticated, (req, res) => {
  res.render("login");
});
auth.get("/signup", checkAuthenticated, (req, res) => {
  res.render("signup");
});
auth.get("/dashboard", checkNotAuthenticated, (req, res) => {
  res.render("dashboard", { user: req.user.first_name });
});

auth.post("/signup", async (req, res) => {
  const { email, first_name, last_name, username, password, password2 } =
    req.body;

  let errors = [];

  if (
    !email ||
    !first_name ||
    !last_name ||
    !username ||
    !password ||
    !password2
  ) {
    errors.push({ message: "All fields need to be filled." });
  }

  if (password.length < 6) {
    errors.push({ message: "Password needs to be 6 characters or more." });
  }

  if (password !== password2) {
    errors.push({
      message: "The two passwords do not match. Please try again.",
    });
  }

  if (errors.length > 0) {
    res.render("signup", { errors });
  } else {
    //Form validation passed

    let hashedPassword = await bcrypt.hash(password, 10);

    pool.query(
      "SELECT * FROM users WHERE email = $1",
      [email],
      (err, results) => {
        if (err) {
          throw err;
        }
        if (results.rows.length > 0) {
          errors.push({
            message:
              "The email has already been used. Please login or use a different email.",
          });
          res.render("signup", { errors });
        } else {
          pool.query(
            "INSERT INTO users (email, password, first_name, last_name, username) VALUES ($1, $2, $3, $4, $5);",
            [email, hashedPassword, first_name, last_name, username],
            (err, results) => {
              if (err) {
                throw err;
              }
              req.flash(
                "success_msg",
                "You are now registered. Please login to continue."
              );
              res.redirect("/api/auth/login");
            }
          );
        }
      }
    );
  }
});

auth.post(
  "/login",
  passport.authenticate("local", {
    successRedirect: "/api/auth/dashboard",
    failureRedirect: "/api/auth/login",
    failureFlash: true,
  })
);

auth.get("/logout", (req, res) => {
  req.logOut();
  req.flash("success_msg", "You have been succesfuly logged out.");
  res.redirect("/api/auth/login");
});

module.exports = auth;

一切都在本地运行顺利,但是一旦我在 Heroku 上部署,我得到一个错误 503/H13:

heroku[router]: at=error code=H13 desc="Connection closed without response" method=GET path="/api/auth/dashboard" host=salty-ridge-11669.herokuapp.com request_id=5344a940-61ab-4f35-bb49-68a05b76ea12 fwd="94.4.235.211" dyno=web.1 connect=0ms service=8ms status=503 bytes=0 protocol=https

我尝试使用自定义函数并将 req.redirect 传递给 passport.authenticate(而不是 successRedirect)。从我可以在线收集的信息来看,https 存在某种问题?但是请求只是重定向,所以我真的无法理解。

标签: node.jsexpressauthenticationherokupassport.js

解决方案


好的,谜团解开了。这只是我创建的中间件中缺少的 else 语句:

  const checkAuthenticated = (req, res, next) => {
  if (req.isAuthenticated()) {
    return res.redirect("/api/auth/dashboard");
  } else { //HERE
  next();
 }
};

const checkNotAuthenticated = (req, res, next) => {
  if (req.isAuthenticated()) {
    next();
  }else{ //AND HERE
}
  res.redirect("/api/auth/login");
};

出于某种原因,我调用 next() 的事实在我的大脑中已经足够了。

现在本地和 Heroku 部署的版本都在工作:)


推荐阅读