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

Express使用JWT和auth中间件从/user/login重定向到/user/me报503错误如何解决

问题根因

  1. 核心逻辑误区:你在登录接口响应头中添加的Authorization是响应头,浏览器发起302重定向的GET请求时,不会自动把响应头的内容作为新请求的请求头传递。你在开发者工具中看到的是登录接口的响应头有值,并非/user/me的GET请求的请求头有值。
  2. 中间件容错缺失:当前auth中间件没有做空值判断,当Authorization请求头不存在时,直接调用.replace('Bearer ', '')会直接抛出异常,触发503错误。

解决方案

方案1:前后端分离场景(推荐)

不要使用服务端302重定向,改为前端处理跳转逻辑:

  1. 调整登录接口,返回token给前端:
router.post('/user/login', async (req, res) => {
    try {
        const user = await User.findByCredentials(req.body.email, req.body.password)
        const token = await user.generateAuthToken()
        res.send({ user, token })
    } catch (err) {
        res.status(400).send(err)
    }
})
  1. 前端拿到token后存入localStorage/sessionStorage,跳转到个人页时主动在请求头携带Authorization: Bearer ${token}即可。

方案2:服务端渲染场景(需保留服务端重定向)

将token存入Cookie,浏览器重定向时会自动携带Cookie:

  1. 先安装cookie-parser依赖,在express入口注册中间件:
const cookieParser = require('cookie-parser')
app.use(cookieParser())
  1. 调整登录接口,将token写入HttpOnly Cookie:
router.post('/user/login', async (req, res) => {
    try {
        const user = await User.findByCredentials(req.body.email, req.body.password)
        const token = await user.generateAuthToken()
        // 有效期可根据需求调整,此处为7天
        res.cookie('auth_token', token, { httpOnly: true, maxAge: 7 * 24 * 60 * 60 * 1000 })
        res.status(302).redirect('/user/me')
    } catch (err) {
        res.status(400).send(err)
    }
})
  1. 优化auth中间件,增加空值判断,优先从Cookie读取token:
const auth = async (req, res, next) => {
    try{
        // 优先从Cookie取token,不存在再读请求头
        let token = req.cookies.auth_token || req.header('Authorization')
        if (!token) throw new Error("No token provided")
        // 处理请求头带Bearer前缀的情况
        if (token.startsWith('Bearer ')) {
            token = token.replace('Bearer ', '')
        }
        const decoded = jwt.verify(token, SECRET_TOKEN)
        const user = await User.findOne({ _id: decoded._id, 'tokens.token': token})

        if(!user) {
            throw new Error("User not found")
        }

        req.token = token
        req.user = user
        next()

    } catch(err) {
        // 认证失败规范状态码为401,可替换原503
        res.status(401).send({error: 'Please authenticate'})
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 07:45:01