首屏渲染时Token显示undefined的原因及解决办法(原生JS)
Token认证首屏渲染时Token先输出undefined后显示真实值的问题分析与解决
问题原因
- 首次输出
undefined的请求是浏览器加载页面时发起的初始GET请求:此时前端代码还未执行,无法从localStorage读取Token并设置到请求头中,后端接收到的请求没有Authorization头,解析后得到undefined。 - 第二次输出真实Token的请求是前端
app.js中执行的axios请求:此时前端已完成初始化,成功从localStorage读取Token并添加到请求头,后端就能解析到有效的Token值。
解决办法
1. 拆分页面路由与数据路由
避免用同一个路由既返回页面又处理数据请求,将数据请求改为专属路由,页面加载请求不触发Token校验:
- 后端
server.js修改:
app.get('/', (req, res) => { res.sendFile(__dirname + '/views/index.html'); }); // 新增数据请求路由 app.get('/api/user-info', loginRequired, (req, res) => { res.json({ status: 'success', data: '用户数据' }); });
- 前端
app.js修改:
const userToken = localStorage.getItem('token'); const headers = { authorization: `Bearer ${userToken}`, }; // 请求专属数据路由 axios.get('/api/user-info', { headers, withCredentials: true }) .then(response => { console.log(response.data); }) .catch(error => { console.error(error); });
2. 中间件中跳过页面请求的Token校验
如果必须共用路由,可通过请求头判断是否为页面加载请求,跳过Token校验:
修改后端login-required.js:
const jwt = require('jsonwebtoken'); const loginRequired = (req, res, next) => { // 浏览器加载页面时Accept头包含text/html,跳过校验 if (req.headers.accept?.includes('text/html')) { return next(); } const userToken = req.headers["authorization"]?.split(' ')[1]; console.log(userToken + ' TEST===1'); // 此处可添加JWT验证逻辑 next(); } module.exports = loginRequired;
3. 前端先校验Token存在性再发起请求
前端先判断localStorage中是否存在Token,不存在则跳转登录页,避免无意义请求:
修改前端app.js:
const userToken = localStorage.getItem('token'); if (!userToken) { window.location.href = '/login'; } else { const headers = { authorization: `Bearer ${userToken}`, }; axios.get('/', { headers, withCredentials: true }) .then(response => { console.log(response.data); }) .catch(error => { console.error(error); }); }
内容的提问来源于stack exchange,提问作者김현수
相关产品推荐
相关产品推荐

