Express使用JWT和auth中间件从/user/login重定向到/user/me报503错误如何解决
问题根因
- 核心逻辑误区:你在登录接口响应头中添加的
Authorization是响应头,浏览器发起302重定向的GET请求时,不会自动把响应头的内容作为新请求的请求头传递。你在开发者工具中看到的是登录接口的响应头有值,并非/user/me的GET请求的请求头有值。 - 中间件容错缺失:当前auth中间件没有做空值判断,当
Authorization请求头不存在时,直接调用.replace('Bearer ', '')会直接抛出异常,触发503错误。
解决方案
方案1:前后端分离场景(推荐)
不要使用服务端302重定向,改为前端处理跳转逻辑:
- 调整登录接口,返回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) } })
- 前端拿到token后存入localStorage/sessionStorage,跳转到个人页时主动在请求头携带
Authorization: Bearer ${token}即可。
方案2:服务端渲染场景(需保留服务端重定向)
将token存入Cookie,浏览器重定向时会自动携带Cookie:
- 先安装
cookie-parser依赖,在express入口注册中间件:
const cookieParser = require('cookie-parser') app.use(cookieParser())
- 调整登录接口,将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) } })
- 优化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
相关产品推荐
相关产品推荐

