MVC架构后端JWT条件渲染实现及前端JWT解析用户ID问题
两个JWT相关问题的解决方案
问题1:MVC架构后端中用JWT实现条件渲染
条件渲染的核心是前端根据用户身份/权限展示不同内容,后端通过JWT验证用户身份并返回专属数据,配合前端逻辑完成渲染。结合你的现有代码,具体实现步骤如下:
1. 后端:用JWT保护需权限的路由
在mainRoutes.js中,将verifyToken中间件应用到需要用户身份的路由上(比如用户积分接口),确保只有携带有效JWT的请求才能访问:
// 修改user_points路由,添加JWT验证中间件 router.use("/user_points", jwtMiddleware.verifyToken, userPointsRoute);
此时后端会自动解码token,将用户ID存入res.locals.userId,后续控制器可直接使用该ID查询用户专属数据。
2. 后端控制器:返回用户专属积分数据
在userPointsController中,利用res.locals.userId查询当前登录用户的积分:
module.exports.getUserPoints = (req, res) => { const userId = res.locals.userId; // 数据库查询该用户的总积分 db.query("SELECT total_points FROM user_points WHERE user_id = ?", [userId], (err, results) => { if (err) return res.status(500).json({ error: "积分查询失败" }); res.status(200).json({ totalPoints: results[0].total_points }); }); };
3. 前端:携带JWT请求数据并做条件渲染
从localStorage取出token,通过你已有的fetchMethod请求接口,拿到数据后根据用户信息渲染页面:
document.addEventListener("DOMContentLoaded", function () { const token = localStorage.getItem("token"); if (token) { // 请求当前用户的积分数据 fetchMethod(currentUrl + "/api/user_points", (status, data) => { if (status === 200) { // 渲染用户积分 document.getElementById("userPoints").innerText = `总积分:${data.totalPoints}`; // 条件渲染示例:积分大于100时显示特权按钮 if (data.totalPoints > 100) { document.getElementById("vipButton").classList.remove("d-none"); } } }, "GET", null, token); } else { // 未登录状态:显示登录入口,隐藏用户专属内容 document.getElementById("loginSection").classList.remove("d-none"); document.getElementById("userSection").classList.add("d-none"); } });
问题2:前端从localStorage的JWT中获取user_id(无法访问Node.js模块)
你遇到的问题是浏览器环境(public目录)无法使用Node.js的jsonwebtoken模块,以下两种方案可以解决:
方案1:纯JS手动解码JWT(无需额外库)
JWT由header.payload.signature三部分组成,其中payload是Base64URL编码的JSON,可手动解码:
document.addEventListener("DOMContentLoaded", function () { const token = localStorage.getItem("token"); if (token) { try { // 拆分token,提取payload部分 const payloadBase64 = token.split(".")[1]; // 转换Base64URL为标准Base64并解码 const decodedPayload = JSON.parse(atob(payloadBase64.replace(/-/g, "+").replace(/_/g, "/"))); const userId = decodedPayload.userId; console.log("用户ID:", userId); // 拿到ID后请求用户积分(仍需携带完整token做后端验证) fetchMethod(currentUrl + "/api/user_points", (status, data) => { if (status === 200) { document.getElementById("userPoints").innerText = `总积分:${data.totalPoints}`; } }, "GET", null, token); } catch (err) { console.error("Token解码失败:", err); // 解码失败说明token无效,清除存储并跳转登录页 localStorage.removeItem("token"); window.location.href = "login.html"; } } else { console.error("未找到用户Token"); } });
⚠️ 注意:手动解码仅能获取payload内容,无法验证token的真实性,所有权限逻辑必须由后端的verifyToken中间件完成。
方案2:引入前端JWT解码库
使用轻量的前端解码库jwt-decode:
- 下载库的浏览器版本,放到
public/js目录 - 在HTML中引入脚本:
<script src="/js/jwt-decode.min.js"></script>
- 使用库解码token:
document.addEventListener("DOMContentLoaded", function () { const token = localStorage.getItem("token"); if (token) { try { const decodedToken = jwt_decode(token); const userId = decodedToken.userId; console.log("用户ID:", userId); // 后续请求逻辑... } catch (err) { console.error("Token解码失败:", err); localStorage.removeItem("token"); window.location.href = "login.html"; } } });
补充提示
- 前端不要依赖解码后的JWT做权限判断,所有权限验证必须由后端完成(前端可随意篡改JWT内容)。
- 可通过解码后的
exp字段(如果token包含)检查token是否过期,过期则清除存储并引导用户重新登录。
内容的提问来源于stack exchange,提问作者Arkar Phyo
相关产品推荐
相关产品推荐

