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
相关产品推荐
相关产品推荐

