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

Express登录中间件异常:登出后无法渲染登录页面

问题:登出后登录页面无法渲染的排查与解决

我是一名Web开发新手,开发了一个登录页面(将用户输入的邮箱保存为Cookie)和账户页面(点击登出按钮删除该Cookie),并编写了中间件,试图在Cookie被删除(用户登出)时将用户重定向到登录页面。Cookie存在时一切功能正常,但点击登出按钮后,登录页面无法渲染。

相关代码

登录路由代码

const fs = require('fs');
const path = require('path');
const { v4 } = require('uuid');
const express = require("express");
const cookieParser = require('cookie-parser'); 

const { containsObject, getUsers } = require('../Auth/auth.cjs');
const {userExists} = require('./signin.cjs')

const router = express.Router();

router.get('/', (req, res) => {
    const {cookies} = req;
    if(cookies['email']){
        res.redirect('/main');
    }
    else{
        res.render('SignIn/signin');
    }
})

router.post('/', async (req, res) => {
    const user = {
        email:req.body.email,
        password:req.body.password,
    }
        
    const result = await userExists(user);
    if(result){
        res.cookie('email', req.body.email);
        res.redirect('/main');
    }
    else{
        res.render('SignIn/signin', user)
    }
})

module.exports = router;

登出按钮表单

<form method="post">
    <input type="submit" value="Log out"/>
</form>

登出路由代码

const fs = require('fs');
const path = require('path');
const { v4 } = require('uuid');
const express = require('express');
const { route } = require('../SignIn/signin');
const { compile } = require('ejs');

const {getUser, getPostsFromUser} = require('./account.cjs')

const router = express.Router();

router.get("/", async (req, res) => {
    const {cookies} = req;
    const email = cookies['email'];
    const userResponse = await getUser(email);

    const user = {
        username:userResponse['username'],
        email:userResponse['email'],
    }

    console.log(await getPostsFromUser(user));
    res.render('Account/account', user);
})

router.post('/', (req, res) => {
    res.cookie('email', '', {expires: new Date(0)});
    res.clearCookie("email");
    res.redirect('/sign')
})

module.exports = router;

主文件代码

const { localsName } = require("ejs");
const express = require("express");
const app = express();
const cookieParser = require('cookie-parser');

const users = []
let loggedIn = false

app.set('view engine', 'ejs');

app.use(cookieParser());
app.use(express.static('public'));
app.use(express.urlencoded({extended:true}))

app.use((req, res, next) => {
    const {cookies} = req;
    console.log(cookies['email'])
    if(cookies['email'] == undefined){
        return res.redirect('/sign');
    }
    else{
        next();
    }
})

app.get('/', (req, res) =>{
    res.redirect('/sign')
})

const signRouter = require('./views/SignIn/signin.js');
app.use('/sign', signRouter);

const authRouter = require('./views/Auth/auth.js');
app.use('/auth', authRouter);

const mainRouter = require('./views/Main/main.js');
app.use('/main', mainRouter);

const addPostRouter = require('./views/Add_post/add_post.js');
app.use('/add-post', addPostRouter);

const accountRouter = require('./views/Account/account.js');
app.use('/account', accountRouter);

app.listen(3000)

问题原因

核心问题是全局中间件的位置错误:你在主文件中定义的全局中间件会拦截所有请求,包括登录路由(/sign)的请求。当用户登出后,Cookie被清除,此时访问/sign时,全局中间件检测到cookies['email']不存在,会再次重定向到/sign,形成无限重定向循环,导致浏览器无法正常渲染页面。

另外,登出路由中同时使用res.cookie('email', '', {expires: new Date(0)})和res.clearCookie("email")属于重复操作,没必要同时执行。

解决方案

1. 调整全局中间件的作用范围

将全局中间件移到登录路由之后,只对需要登录验证的路由(如/main、/account等)生效,避免拦截登录页面的请求:

修改后的主文件代码:

const { localsName } = require("ejs");
const express = require("express");
const app = express();
const cookieParser = require('cookie-parser');

const users = []
let loggedIn = false

app.set('view engine', 'ejs');

app.use(cookieParser());
app.use(express.static('public'));
app.use(express.urlencoded({extended:true}))

// 先挂载登录路由,避免被中间件拦截
app.get('/', (req, res) =>{
    res.redirect('/sign')
})

const signRouter = require('./views/SignIn/signin.js');
app.use('/sign', signRouter);

const authRouter = require('./views/Auth/auth.js');
app.use('/auth', authRouter);

// 定义登录验证中间件,只对后续路由生效
app.use((req, res, next) => {
    const {cookies} = req;
    if(cookies['email'] == undefined){
        return res.redirect('/sign');
    }
    next();
})

// 挂载需要登录验证的路由
const mainRouter = require('./views/Main/main.js');
app.use('/main', mainRouter);

const addPostRouter = require('./views/Add_post/add_post.js');
app.use('/add-post', addPostRouter);

const accountRouter = require('./views/Account/account.js');
app.use('/account', accountRouter);

app.listen(3000)

2. 优化登出逻辑

删除重复的Cookie设置代码,只保留res.clearCookie("email")即可:

修改后的登出路由post方法:

router.post('/', (req, res) => {
    res.clearCookie("email");
    res.redirect('/sign')
})

原理说明

调整中间件位置后,登录路由(/sign)不会被登录验证中间件拦截,用户登出后重定向到/sign时,能正常进入登录路由的get方法,渲染登录页面。而需要登录的路由(如/main、/account)会先经过中间件验证,未登录时自动重定向到登录页,逻辑正常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 21:17:53