如何将前端localStorage的Token传给NodeJS后端实现EJS渲染权限校验
实现方案
一、前端Token传递处理
1. 页面跳转(视图路由)
因为<a>标签是同步GET请求,localStorage的Token不会自动携带,将Token存入Cookie是最优方案(浏览器会自动在请求头里携带Cookie):
// 登录成功后,同时存入localStorage和Cookie localStorage.setItem('token', 'your-jwt-token'); document.cookie = `token=${your-jwt-token}; path=/; secure; SameSite=Strict`; // 生产环境开启secure,本地调试可关闭
若用户手动清除Cookie,可在公共页面脚本中自动补全:
// 页面加载时触发 window.addEventListener('load', () => { const token = localStorage.getItem('token'); if (token && !document.cookie.includes('token=')) { document.cookie = `token=${token}; path=/; secure; SameSite=Strict`; } });
2. API请求(异步接口)
用Fetch/AJAX发起请求时,在请求头中携带Token:
// Fetch示例 fetch('/api/users', { method: 'GET', headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } });
二、后端中间件实现
1. 依赖准备
安装必要工具库:
npm install cookie-parser jsonwebtoken
2. 全局中间件配置
在app.js中添加Cookie解析中间件,用于读取请求中的Cookie:
const cookieParser = require('cookie-parser'); app.use(cookieParser());
3. 权限校验中间件
编写通用校验逻辑,区分视图路由与API路由的错误处理:
// 可单独放在middleware/auth.js,或直接写入router.js const jwt = require('jsonwebtoken'); const User = require('../src/models/User'); // 你的用户模型 const authenticate = (req, res, next) => { // 优先从Authorization头取API用Token,再从Cookie取视图用Token let token = req.headers.authorization?.split(' ')[1]; if (!token) token = req.cookies.token; if (!token) { return req.path.startsWith('/api') ? res.status(401).json({ success: false, message: '未授权,请先登录' }) : res.redirect('/login'); } try { // 验证Token有效性,secret需与生成Token时一致 const decoded = jwt.verify(token, process.env.JWT_SECRET); // 从数据库校验用户状态(是否存在、是否禁用) User.findById(decoded.userId) .then(user => { if (!user || !user.isActive) throw new Error('用户不存在或已禁用'); req.user = user; // 将用户信息挂载到req,供后续路由使用 next(); }) .catch(err => { return req.path.startsWith('/api') ? res.status(403).json({ success: false, message: err.message }) : res.redirect('/login'); }); } catch (err) { return req.path.startsWith('/api') ? res.status(401).json({ success: false, message: 'Token无效或已过期' }) : res.redirect('/login'); } };
4. 路由中挂载中间件
在router.js中为需要权限的路由添加校验:
const express = require('express'); const router = express.Router(); const viewController = require('../src/controllers/viewController'); const apiController = require('../src/controllers/apiController'); const authenticate = require('./middleware/auth'); // 引入中间件 // 需权限的视图路由 router.get('/dashboard', authenticate, viewController.renderDashboard); router.get('/profile', authenticate, viewController.renderProfile); // 需权限的API路由 router.get('/api/users', authenticate, apiController.getUsers); router.post('/api/posts', authenticate, apiController.createPost); // 公开路由(如登录页) router.get('/login', viewController.renderLogin); router.post('/api/login', apiController.login);
三、双重安全策略落地
1. 视图层校验
- 中间件在EJS渲染前完成Token与权限校验,无权限直接跳转登录页,避免敏感页面泄露。
- 可通过
req.user在EJS模板中动态渲染内容(如角色专属菜单):
<!-- views/dashboard.ejs --> <% if (user.role === 'admin') { %> <li><a href="/admin">管理后台</a></li> <% } %>
2. API层校验
- 所有API接口通过
authenticate中间件校验Token,确保仅合法用户可访问。 - 控制器内可实现细粒度权限判断(如仅管理员可删除用户):
// apiController.js exports.deleteUser = (req, res) => { if (req.user.role !== 'admin') { return res.status(403).json({ success: false, message: '无权限执行此操作' }); } // 后续删除逻辑 };
四、注意事项
- 合理设置Token有效期,同时实现刷新Token机制,减少用户登录频率。
- 生产环境下Cookie需开启
secure(仅HTTPS传输),若无需前端读取Token可添加HttpOnly(防止XSS窃取)。 - JWT的Payload仅做Base64编码,不要存放敏感信息,敏感数据需从数据库读取。
内容的提问来源于stack exchange,提问作者D. Watson
相关产品推荐
相关产品推荐

