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

Node.js+Express实现角色差异化页面跳转及登录鉴权

Express 简易角色授权实现方案

核心问题修正

你现有代码存在2个核心逻辑错误:

  • GET 请求不存在请求体,在app.get('/categories')中读取req.body永远拿不到账号密码,无法完成校验
  • 没有持久化存储登录状态,表单提交后重定向会丢失用户登录信息,无法复用鉴权逻辑到多个路由

实现步骤

1. 安装会话依赖

要跨请求保存用户登录状态,需要使用express-session存储会话信息:

npm install express-session

2. 配置会话中间件

在app.js中、所有路由定义前,添加session配置:

const session = require('express-session');
// 注意该配置要写在express.urlencoded等请求体解析中间件之后
app.use(session({
  secret: 'replace_with_your_own_random_secret', // 自定义加密密钥,生产环境不要硬编码
  resave: false,
  saveUninitialized: false,
  cookie: { maxAge: 3600000 } // 登录态有效期1小时,单位毫秒
}));

3. 修改登录表单

不要把表单action固定写为业务路由/categories,统一提交到专用登录处理接口:

<form action='/login' method='post'>
  <div class="form-group">
    <input class="form-control item" type="text" name="username"
    maxlength="15" minlength="4" pattern="^[a-zA-Z0-9_.-]*$"
    id="username" required autocomplete="off">
  </div>
  <div class="form-group">
    <input class="form-control item" type="password" name="password"
    minlength="8" id="password" required autocomplete="off">
  </div>
  <div class="form-group text-center">
    <button class="btn btn-primary btn-block save-profile"
    type="submit">Enter</button>
  </div>
</form>

4. 编写通用鉴权中间件

把登录校验、角色校验逻辑抽成可复用的中间件,不用在每个路由重复写代码:

// 登录状态校验中间件
function authRequired(req, res, next) {
  if (!req.session.currentUser) {
    return res.status(401).send("You are not authorized!");
  }
  next();
}

// 角色权限校验中间件,传入允许访问的角色列表
function roleRequired(allowedRoles) {
  return function(req, res, next) {
    if (!allowedRoles.includes(req.session.currentUser.role)) {
      return res.status(403).send("You have no permission to access this page!");
    }
    next();
  }
}

5. 编写统一登录处理接口

处理/login的POST请求,校验账号密码、存储登录态、按角色跳转:

// 原有模拟用户数据库数组保持不变
const users = [{
  info: 'First person',
  login: 'firstPerson',
  password: '11111111',
  role: 'member'
}, {
  info: 'Second person',
  login: 'secondPerson',
  password: '22222222',
  role: 'admin'
}];

app.post('/login', function(req, res) {
  const { username, password } = req.body;
  // 匹配账号密码
  const matchedUser = users.find(user => user.login === username && user.password === password);
  if (!matchedUser) {
    return res.redirect('/alert');
  }
  // 登录成功,把用户信息存入session
  req.session.currentUser = matchedUser;
  // 按角色跳转对应页面
  if (matchedUser.role === 'member') {
    res.redirect('/categories');
  } else if (matchedUser.role === 'admin') {
    res.redirect('/choice');
  }
});

6. 编写受保护的业务路由

所有需要登录才能访问的路由,直接套用之前写的鉴权中间件即可,不需要重复写校验逻辑:

// 登录页路由
app.get("/", function(req, res) {
  // 已登录用户访问登录页直接跳对应首页
  if (req.session.currentUser) {
    return req.session.currentUser.role === 'member' ? res.redirect('/categories') : res.redirect('/choice');
  }
  res.render("autorization");
});

// 会员页面,需要登录+member角色
app.get("/categories", authRequired, roleRequired(['member']), function(req, res){   
  res.render("categories1");
});

// 管理员页面,需要登录+admin角色
app.get("/choice", authRequired, roleRequired(['admin']), function(req, res){
  res.render("choice"); // 替换为你自己的管理员页面对应的ejs文件名
});

// 可选:登出接口
app.get('/logout', function(req, res) {
  req.session.destroy();
  res.redirect('/');
});

逻辑说明

  • 所有登录请求统一打到/login接口处理,不需要让表单适配多个提交地址
  • 登录状态存在session中,后续所有请求都会自动携带登录信息,不需要重复传账号密码
  • 鉴权逻辑抽成中间件,新增受保护路由时直接挂载即可,不需要重复写校验代码
  • 增加角色校验层,从根源避免普通用户越权访问管理员页面、管理员误访问普通用户页面的问题

内容的提问来源于stack exchange,提问作者Andy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 19:03:42