Node.js+Express中如何区分带/不带中间件的路由并实现登录渲染
问题分析与解决方案
1. 重复根路由的核心问题
你定义了两个完全相同的GET /路由,Express会按照路由定义的顺序进行匹配,第一个无中间件的路由会被优先命中,带checklogin的路由永远不会被执行。必须合并为一个路由,通过中间件判断用户登录状态,在同一个路由逻辑中处理两种场景。
修改home/home.js的路由:
router.get('/', checklogin, (req,res)=>{ // 登录状态下req会携带用户信息,未登录则无对应字段 res.render('home/index',{ email: req.email, name: req.username, role: req.role }) })
2. 修复checklogin中间件的逻辑错误
你的中间件在catch块中调用了两次next(),且错误处理逻辑混乱。正确的逻辑应该是:
- 验证token成功:将用户信息挂载到
req对象,调用next()继续执行路由 - 验证失败/无token:不挂载用户信息,直接调用
next()让路由自行处理未登录状态
修改后的中间件代码:
const checklogin = (req, res, next) => { const token = req.cookies.ntoken; try { if (token) { // 先判断是否存在token const decoded = jwt.verify(token, process.env.JWT_SECRET); const {username, email, role} = decoded; req.username = username; req.email = email; req.role = role; } next(); // 无论是否有有效token,都继续执行后续逻辑 } catch (err) { console.log(err); // token无效时,不挂载用户信息,直接放行 next(); } } module.exports = checklogin;
3. Handlebars模板适配登录状态
在home/index.hbs中需要判断用户信息是否存在,再决定展示内容:
{{#if name}} <p>欢迎回来,{{name}}!</p> {{#if role '===' 'admin'}} <a href="/admin/dashboard">进入管理员面板</a> {{else if role '===' 'user'}} <a href="/user/dashboard">进入用户面板</a> {{/if}} {{else}} <p>请<a href="/login">登录</a>后访问更多功能</p> {{/if}}
4. 修复user路由的拼写错误
user.js中的路由存在拼写错误,checlogin改为checklogin:
router.get("/dashboard", checklogin, async (req, res) => { // 你的业务逻辑 })
5. 额外优化:拦截未登录用户访问dashboard
可以在checklogin中间件中添加逻辑,禁止未登录用户直接访问dashboard路由:
const checklogin = (req, res, next) => { const token = req.cookies.ntoken; try { if (token) { const decoded = jwt.verify(token, process.env.JWT_SECRET); const {username, email, role} = decoded; req.username = username; req.email = email; req.role = role; } // 访问dashboard且未登录时,重定向到登录页 if ((req.path.includes('/dashboard')) && !req.username) { return res.redirect('/login'); } next(); } catch (err) { console.log(err); if (req.path.includes('/dashboard')) { return res.redirect('/login'); } next(); } }
完成以上调整后,用户登录后重定向到/就能正确展示用户名,不同角色的用户也能访问对应的dashboard路由。
内容的提问来源于stack exchange,提问作者Shabnam Sabah
相关产品推荐
相关产品推荐

