You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将前端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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 05:12:45