You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何出现Error [ERR_HTTP_HEADERS_SENT]错误?多角色管理员博客问题

问题描述

我正在开发一个多角色管理员的博客网站,此前功能正常,添加用于校验登录状态的中间件后,出现Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client错误。当已登录的管理员访问登录页面,或未登录用户访问受保护的管理员页面时,都会触发该错误。


管理员路由代码(Admin Route JS)

const adminController = require("../controllers/adminController");
const adminAuth = require("../middlewares/adminAuth");

// Register new admin
adminRouter.get("/register", adminAuth.isLogin, adminController.register);
adminRouter.post("/register", adminController.registerSave);

// Login
adminRouter.get("/login", adminAuth.isLogout, adminController.login);
adminRouter.post("/login", adminController.loginSave);

// Logout
adminRouter.get("/logout", adminAuth.isLogin, adminController.logOut);

// Other pages
adminRouter.get("/dashboard", adminAuth.isLogin, adminController.dashboard);
adminRouter.get("/all-admin", adminAuth.isLogin, adminController.allAdmin);
adminRouter.get("/all-post", adminAuth.isLogin, adminController.allPost);

管理员控制器代码(Admin Controller JS)

const login = async (req, res) => {
  res.render("admin/login", { title: "Log in" });
};
const loginSave = async (req, res) => {
  try {
    const email = req.body.adminEmail;
    const password = req.body.adminPassword;

    const adminEmailFind = await adminUser.findOne({ email: email });

    if (adminEmailFind) {
      const adminPassMatch = await bcrypt.compare(
        password,
        adminEmailFind.password
      );

      if (adminPassMatch) {
        req.session.user_id = adminEmailFind._id;
        req.session.isSuperAdmin = adminEmailFind.isSuperAdmin;
        req.session.isAdmin = adminEmailFind.isAdmin;

        if (adminEmailFind.isSuperAdmin == 1) {
          res.redirect("/admin/dashboard");
        } else if (adminEmailFind.isSuperAdmin == 0 && userData.isAdmin == 1) {
          res.redirect("/admin/dashboard");
        } else {
          res.render("admin/login", {
            title: "Login",
            statusColor: "#ef4444",
            message: "Sorry !! Admins can proceed only",
          });
        }
      } else {
        res.render("admin/login", {
          title: "Login",
          statusColor: "#ef4444",
          message: "Email or Password does not match !!!",
        });
      }
    } else {
      res.render("admin/login", {
        title: "Login",
        statusColor: "#ef4444",
        message: "Email could not be found !!!",
      });
    }
  } catch (error) {
    console.log(error.message);
  }
};

const dashboard = async (req, res) => {
  res.render("admin/index", { title: "Dashboard" });
};

管理员认证中间件代码(Admin Auth middleware)

const isLogin = async (req, res, next) => {
  try {
    if (
      !req.session.user_id &&
      !req.session.isSuperAdmin &&
      !req.session.isAdmin
    ) {
      res.redirect("/admin/login");
    }
    next();
  } catch (error) {
    console.log(error.message);
  }
};
const isLogout = async (req, res, next) => {
  try {
    if (
      req.session.user_id &&
      req.session.isSuperAdmin &&
      req.session.isAdmin
    ) {
      res.redirect("/admin/dashboard");
    }
    next();
  } catch (error) {
    console.log(error.message);
  }
};

module.exports = { isLogin, isLogout };

问题原因及解决方案

核心原因

中间件中执行res.redirect()后未终止后续逻辑,next()仍会继续执行,导致控制器再次发送响应(res.render()或res.redirect()),引发重复发送HTTP头的错误。

修复步骤

  1. 修正isLogin中间件:在res.redirect()后添加return,阻止后续next()执行
const isLogin = async (req, res, next) => {
  try {
    if (
      !req.session.user_id &&
      !req.session.isSuperAdmin &&
      !req.session.isAdmin
    ) {
      return res.redirect("/admin/login");
    }
    next();
  } catch (error) {
    console.log(error.message);
  }
};
  1. 修正isLogout中间件:同样在res.redirect()后添加return
const isLogout = async (req, res, next) => {
  try {
    if (
      req.session.user_id &&
      req.session.isSuperAdmin &&
      req.session.isAdmin
    ) {
      return res.redirect("/admin/dashboard");
    }
    next();
  } catch (error) {
    console.log(error.message);
  }
};
  1. 额外修复控制器bug:loginSave中存在未定义变量userData,需替换为adminEmailFind
// 原代码
else if (adminEmailFind.isSuperAdmin == 0 && userData.isAdmin == 1) {
// 修改为
else if (adminEmailFind.isSuperAdmin == 0 && adminEmailFind.isAdmin == 1) {

内容的提问来源于stack exchange,提问作者Amit Deka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 11:45:34