使用JQuery携带请求头访问Node.js受保护路由问题
解决JWT Token在受保护路由跳转时的携带问题
你遇到的核心问题是:直接用window.location.pathname跳转时,浏览器发起的GET请求不会自动携带存在sessionStorage里的Token到请求头,导致服务器的verifyToken中间件无法验证身份,返回403错误。咱们一步步来解决这个问题:
1. 先修正sessionStorage的存储错误
你当前的代码里:
sessionStorage.setItem(token, token);
这里把Token的值同时作为键名和值存储了,后续很难正确取出Token。应该用一个固定的键名,比如authToken:
const token = response.token; sessionStorage.setItem('authToken', token); // 固定键名存储,方便后续取出
2. 选择合适的方式携带Token跳转受保护路由
根据你的应用场景,有两种常用方案:
方案一:用AJAX请求受保护路由并手动携带Token(推荐,适合前后端分离场景)
直接跳转的浏览器请求不会自动带Token,所以我们改用AJAX发起GET请求,手动在请求头里加入Token,然后渲染返回的页面内容:
// 登录成功后替换原来的window.location跳转代码 const token = response.token; sessionStorage.setItem('authToken', token); $.ajax({ url: '/LimeLINE/chatroom', type: 'GET', // 在请求头里加入Authorization,格式为「Bearer + 空格 + Token」 headers: { 'Authorization': `Bearer ${token}` }, success: function(htmlContent) { // 替换当前页面内容为服务器返回的chatroom页面 document.body.innerHTML = htmlContent; // 更新浏览器URL,让地址栏显示正确的路由(可选,优化用户体验) window.history.pushState({}, '', '/LimeLINE/chatroom'); }, error: function(xhr) { if (xhr.status === 403) { alert('身份验证失败,请重新登录'); window.location.pathname = '/'; // 跳回登录页 } else { alert('页面加载失败,请稍后重试'); } } });
方案二:将Token存在Cookie中,让浏览器自动携带
Cookie会在每次请求时自动发送给服务器,所以如果把Token存在Cookie里,直接跳转也能带上身份信息:
// 登录成功后存储Token到Cookie const token = response.token; // 可根据需求设置过期时间、secure(仅HTTPS下生效)、SameSite等参数 document.cookie = `authToken=${token}; path=/; SameSite=Strict`; // 然后直接跳转 window.location.pathname = '/LimeLINE/chatroom';
对应的,你需要修改verifyToken中间件,从Cookie中读取Token:
function verifyToken(req, res, next) { // 从Cookie中获取Token const token = req.cookies.authToken; if (!token) { return res.status(403).json({ message: "No token found" }); } req.token = token; next(); }
注意:如果用Cookie存储,建议开启
HttpOnly和Secure属性防止XSS攻击,比如:document.cookie = `authToken=${token}; path=/; HttpOnly; Secure; SameSite=Strict`;不过
HttpOnly的Cookie无法通过前端JS读取,后续如果需要前端用Token发起其他请求,就得从服务器端处理。
3. 修正服务器端的JWT生成代码
你的登录接口里有个小错误:res.statusCode(500)是无效的,应该用res.status(500)来设置状态码:
app.post('/login-user', (req, res) => { user.loginUser(req.body, (err, jResult) => { if (err) { return res.send(jResult); } jwt.sign({ user: jResult }, "supersecret", (err, token) => { if (err) { return res.status(500).json({ message: "生成Token失败" }); // 修正此处的状态码设置 } console.log(token); return res.json({ token: token }); }); }); });
4. 确认verifyToken中间件的实现(方案一对应)
如果用方案一的Authorization头方式,你的verifyToken中间件应该从请求头里解析Token:
function verifyToken(req, res, next) { const authHeader = req.headers['authorization']; // 提取Bearer后面的Token部分 const token = authHeader && authHeader.split(' ')[1]; if (!token) { return res.status(403).json({ message: "No token found" }); } req.token = token; next(); }
这样调整后,就能正确携带Token访问受保护路由了。
内容的提问来源于stack exchange,提问作者July333
相关产品推荐
相关产品推荐

