Express如何将用户会话存入request对象及req.user的来源解析
req.user._id的来源
你学习的这个MERN项目采用JWT(JSON Web Token)身份验证方案,没有使用服务端会话存储机制,因此不需要安装express-session、cookie-session这类依赖,req.user是由自定义的身份校验中间件挂载到请求对象上的:
- 用户登录时,后端校验账号密码无误后,会生成携带用户ID信息的JWT返回给前端
- 前端后续发起需要登录权限的请求(比如下单接口)时,会把JWT放到
Authorization请求头中,格式为Bearer <token值> - 请求到达下单接口前,会先经过全局/路由绑定的身份校验中间件,中间件会取出请求头的JWT做有效性校验,校验通过后会根据JWT内的用户ID查询对应用户信息,挂载到
req.user属性上,再放行到后续的接口逻辑 - 因此你在
addOrderItems接口中可以直接读取req.user._id获取当前登录用户的ID
对应身份校验中间件的示例代码如下:
const jwt = require('jsonwebtoken') const User = require('../models/userModel') const asyncHandler = require('express-async-handler') // 身份校验中间件 const protect = asyncHandler(async (req, res, next) => { let token // 读取请求头中的JWT if (req.headers.authorization?.startsWith('Bearer')) { try { token = req.headers.authorization.split(' ')[1] // 解密JWT,校验有效性 const decoded = jwt.verify(token, process.env.JWT_SECRET) // 查询用户信息,排除密码字段后挂载到req.user req.user = await User.findById(decoded.id).select('-password') // 放行到下一个中间件/路由处理器 next() } catch (err) { res.status(401) throw new Error('Token无效,无权访问') } } if (!token) { res.status(401) throw new Error('未提供Token,无权访问') } })
路由层会把这个中间件绑定到需要登录的接口上,示例如下:
// 只有经过protect中间件校验通过的请求,才能进入addOrderItems逻辑 router.post('/api/orders', protect, addOrderItems)
Express中将用户信息存入request对象的实现方式
核心是通过Express中间件机制实现,中间件可以在请求的生命周期内修改req对象,所有后续执行的中间件、路由处理器都能访问到修改后的内容,常见实现方案分为两种:
- 会话存储方案:引入express-session等中间件,用户登录校验通过后,将用户信息存入
req.session.user,也可以额外加一层中间件把req.session.user赋值到req.user简化调用 - JWT无状态方案:和上面的项目逻辑一致,自定义JWT校验中间件,校验通过后把用户信息直接挂载到
req.user上即可
需要注意中间件的注册/绑定顺序必须早于对应的路由处理器,否则路由执行时还未挂载对应的用户信息。
内容的提问来源于stack exchange,提问作者juexu
相关产品推荐
相关产品推荐

