如何保护 express.js 中的路由?

Posted

技术标签:

【中文标题】如何保护 express.js 中的路由?【英文标题】:How to protect routes in express.js? 【发布时间】:2016-06-07 13:00:17 【问题描述】:

例如,在 Meteor 中,有类似的东西

Router.plugin('ensureSignedIn');
Router.plugin('ensureSignedIn', 
  except: ['home', 'atSignIn', 'atSignUp', 'atForgotPassword']
);

所以未签名的用户不能访问除以上四个之外的其他路由。

如何在 express.js 中做到这一点?我也在使用passport.js。

【问题讨论】:

【参考方案1】:

我不熟悉 Meteor,但您可以执行以下操作,假设您想让页面仅对经过身份验证的用户(护照)可用。

function ensureAuthenticated(req, res, next) 
  if (req.isAuthenticated())
    return next();
  else
    // Return error content: res.jsonp(...) or redirect: res.redirect('/login')


app.get('/account', ensureAuthenticated, function(req, res) 
  // Do something with user via req.user
);

ensureAuthenticated 函数只是一个示例,您可以定义自己的函数。调用next() 继续请求链。

【讨论】:

是否有任何 npm 库?通过使用上述函数,我必须在每个 app.get 中添加此函数 不知道,如果你想保护设置的路径,你可以使用中间件,例如 app.use('/user/*', ensureAuthenticated) 将保护任何匹配的路由。 你如何为这条路线编写单元测试,因为它受到保护,你不能通过下一个......【参考方案2】:

我应该使用中间件来保护我的路由,甚至保护同一路由中的某些动词:

例如:在my endpoint/route.js

 // the require sentences are omitted 

const express = require('express');
const  /*controllerFunctions*/  = require('./controller');
const routeGuard = require('/*must create a route guard*/');
const router = express.Router();


router.route('')
  .get(getAllResources) 
;

 router.route('/:id') // 
     .get(validateParam,getOneResource);


 router.use(routeGuard);

 router.route('/:id')
    .post(validateParam,validateBody,postResource)
    .patch(validateParam,validateBody,patchProblemById) 
    .delete(validateParam,deleteResource)    
    ;

 module.exports = router;

而我的routeGuard 文件应该是这样的:

 const  promisify  = require('util');
 const jwt = require("jsonwebtoken");
 const AppError = require('./appError');
 const User = require('./../endpoints/users/model');
 const wrapper = require('./try-wrapper');//try catch wrapper

 module.exports.routeGuard = wrapper(async function (req, res, next)
    // the err message is the same on purpose
    const notAllowed = new AppError('Unauthorized: Invalid or Nonexistent credentials',401);

    let token = null;
    if (req.headers.authorization && req.headers.authorization.startsWith('Bearer'))
        token = req.headers.authorization.split(' ')[1];
    
    if (!token) return next(notAllowed );

    const payload = await promisify(jwt.verify)(token,process.env.KEY);
    const user = await User.findById(payload.id);

    if (!user) return next( notAllowed);
    if ( ! user.hasSamePasswordSince(payload.iat) )return next( notAllowed ); 
    req.user = user; // further use...
    next(); 
);

【讨论】:

以上是关于如何保护 express.js 中的路由?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 express.js 在 Ajax 调用中实现 CSRF 保护(寻找完整示例)?

jQuery 函数不适用于 node.js 中的 express.js 路由

使用 express js、passport s 保护 GraphQL 查询

使用 Express JS 路由中的 Socket.io

如何在 express.js 中创建注册路由?

如何将参数传递给 MEAN.js 包的 express.js 服务器端路由。