React+Express实现JWT认证出现Cannot read property 'token' of undefined报错咨询
问题排查及解决方法
错误产生原因
- Cookie读写逻辑理解错误:
res.cookie()是将Cookie写入响应头返回给浏览器,仅会在后续客户端请求中被携带到服务端,本次请求的req.cookies是本次请求发起时浏览器携带的Cookie,刚设置完就从req.cookies读取必然返回undefined。 - 缺少Cookie解析中间件:Express默认不会解析请求头中的Cookie,未安装配置
cookie-parser中间件的情况下,req.cookies本身就是undefined,所有Cookie字段都无法读取。 - 跨域配置不符合要求:前端运行在
localhost:3000、后端运行在localhost:5000属于跨域场景,默认情况下浏览器不会写入跨域响应的Set-Cookie,也不会在跨域请求中自动携带Cookie;如果后端CORS配置未开启凭证支持、允许源配置为*,也会导致Cookie读写失败。 - 登录接口重定向逻辑错误:跨域场景下
res.redirect('/')是跳转到后端服务的根路径,和前端路由无关,会导致前端逻辑异常。 - 前端fetch未配置凭证参数:默认fetch请求不会携带Cookie,必须显式配置
credentials参数才会触发Cookie的读写和携带。
具体修复方案
- 安装配置Express基础中间件
首先安装依赖:
在Express入口文件中引入并配置:npm install cookie-parser corsconst cookieParser = require('cookie-parser'); const cors = require('cors'); // 配置CORS,必须指定明确的前端源、开启凭证支持 app.use(cors({ origin: 'http://localhost:3000', credentials: true })); // 解析请求Cookie app.use(cookieParser()); - 修复登录接口逻辑
app.post('/login',async (req,res)=>{ const {login, pwd } = req.body const isUserExist = await User.findOne({login:login}) if(!isUserExist){ return res.status(400).json({msg: '账号不存在'}) } const match = await bcrypt.compare(pwd,isUserExist.pwd) if(!match){ return res.status(400).json({msg: '密码错误'}) } const accessToken = createToken(user) // 配置Cookie属性,httpOnly可防止前端JS读取,降低XSS风险 res.cookie("token",accessToken,{ maxAge:60*60*24*30*1000, sameSite: 'Lax', httpOnly: true }) // 不要用后端重定向,返回状态让前端自行跳转 res.json({code: 0, msg: '登录成功'}) }) - 给userData接口添加异常处理
router.get("/userData",async (req, res) => { try { const accessToken = req.cookies["token"] if(!accessToken) return res.status(401).json({msg: '未登录'}) const validtoken = verify(accessToken,"jwt-secret") const user = await User.findOne({login:validtoken.login}) res.send(user) } catch (err) { res.status(401).json({msg: '认证失效'}) } }); - 修复前端fetch请求配置
所有和后端交互的fetch请求都要添加credentials: 'include'配置,登录请求和用户数据请求都需要添加:takeUserData = async() =>{ // 注意要写全后端接口地址,同时添加credentials配置 const response = await fetch('http://localhost:5000/userData', { credentials: 'include' }); const body = await response.json(); if (response.status !== 200) { throw Error('1234') } return body; }
内容的提问来源于stack exchange,提问作者GDTyka
相关产品推荐
相关产品推荐

