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

使用Passport.js+EJS跳转报错:手动访问正常,登录重定向失败

问题分析与解决

核心问题

  1. 请求体编码不匹配:你用fetch直接传递JavaScript对象作为请求体,但后端配置的express.urlencoded只能解析application/x-www-form-urlencoded格式的表单数据,导致Passport无法获取用户名和密码,验证流程异常。
  2. Fetch重定向处理冲突:Passport的successRedirect/failureRedirect会返回3xx重定向响应,fetch会自动跟随重定向并获取目标页面的HTML内容,但前端尝试用response.json()解析HTML,必然抛出语法错误。

解决方案

1. 修正前端请求体格式

将请求体转换为URLSearchParams格式,匹配后端的解析规则:

const response = await fetch("/login", {
    method: "POST",
    headers: {
        "Content-Type": "application/x-www-form-urlencoded",
    },
    body: new URLSearchParams({
        [username.id]: usernameValue,
        [password.id]: passwordValue,
    }),
})

2. 调整后端验证逻辑,返回JSON响应

放弃Passport的自动重定向,改用自定义回调返回JSON,让前端控制页面跳转:

app.post("/login", (req, res, next) => {
    passport.authenticate("local", (err, user, info) => {
        if (err) return res.status(500).json({ error: err.message });
        if (!user) return res.status(401).json({ error: info?.message || "登录失败" });
        
        req.login(user, (loginErr) => {
            if (loginErr) return res.status(500).json({ error: loginErr.message });
            return res.json({ id: user.id, href: "/home" });
        });
    })(req, res, next);
});

3. 保留原有前端跳转逻辑

你前端代码中根据返回的href跳转的逻辑可以保留,现在能正确接收后端的JSON响应,不会再出现解析错误。

为什么手动访问正常?

手动在地址栏输入localhost:3000/home是直接发送GET请求,触发后端的res.render("home")直接渲染EJS模板,和登录的POST请求流程完全独立,因此不受Passport验证逻辑影响。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 20:55:21