创建一个接受参数的 Expressjs 中间件

我正在尝试创建一个可以接受参数的中间件。如何做到这一点?

例子

app.get('/hasToBeAdmin', HasRole('Admin'), function(req,res){


})


HasRole = function(role, req, res, next){
if(role != user.role){
res.redirect('/NotInRole);
}


next();
}
59315 次浏览
function HasRole(role) {
return function(req, res, next) {
if (role !== req.user.role) res.redirect(...);
else next();
}
}

我还要确保同一个函数不会有多个副本:

function HasRole(role) {
return HasRole[role] || (HasRole[role] = function(req, res, next) {
if (role !== req.user.role) res.redirect(...);
else next();
})
}
app.get('/hasToBeAdmin', (req, res, next) => {
hasRole(req, res, next, 'admin');
}, (req,res) => {
// regular route
});


const hasRole = (req, res, next, role) => {
if(role != user.role){
res.redirect('/NotInRole');
}
next();
};

或者,如果没有太多的用例,或者 role 不是字符串:

function HasRole(role) {
return function (req, res, next) {
if (role !== req.user.role) res.redirect(/* ... */);
else next();
}
}


var middlware_hasRoleAdmin = HasRole('admin'); // define router only once


app.get('/hasToBeAdmin', middlware_hasRoleAdmin, function (req, res) {


})

如果您有不同的权限级别,您可以像下面这样构造它们:

const LEVELS = Object.freeze({
basic: 1,
pro: 2,
admin: 3
});


/**
*  Check if user has the required permission level
*/
module.exports = (role) => {
return (req, res, next) => {
if (LEVELS[req.user.role] < LEVELS[role]) return res.status(401).end();
return next();
}
}

我使用这个解决方案,在 body req 中接收一个 jwt 令牌,并从中获取角色信息

//roleMiddleware.js


const checkRole = role => {
    

return (req, res, next) => {
if (req.role == role) {
console.log(`${role} role granted`)
next()
} else {
res.status(401).send({ result: 'error', message: `No ${role} permission granted` })
}
}
}


module.exports = { checkRole }

因此,首先使用 auth 中间件来了解用户是否有效,然后使用角色中间件来了解用户是否有权访问 api 路由

// router.js


router.post('/v1/something-protected', requireAuth, checkRole('commercial'), (req, res) => {
// do what you want...
})

我希望能帮上忙

既然我们已经到了2021年,为什么不使用 ES6语法呢?... 使用 NodeJS v14.16.1,下面的示例非常有效: -)

有快速路由器

const someFunc = ({ option1, option2 }) =>
router.get("/", (req, res, next) => {
    

// code
    

next();
});


module.exports = someFunc;

或者

const someFunc = ({ option1, option2 }) =>
(req, res, next) => {
        

// code
        

next();
};
    

module.exports = someFunc;

那就这么说吧:

const someFunc = require('./middlewares/someFunc.js');
app.use(someFunc({option1: 'test', option2: false ));

在遵循了 给你的文档之后,我能够解决这个问题,我制作了这个中间件并传递了一个 role _ ids 数组,这个数组被允许访问路由

exports.authorize = function (roles) {
return function (req, res, next) {
console.log(roles)
if (roles?.includes(req.user.role_id)) {
return next()
} else {
return res.status(403).send({
error: "Not Authorized to access this route"
})
}
}
}

像这样在路由文件中调用它

myRouter.get("/", authorize([USER_ROLES.OPERATOR]), getSomething);

如果您想知道用户角色是什么,那么它就像枚举一样

const USER_ROLES = Object.freeze({
ADMIN: 1,
HOST: 2,
OPERATOR: 3,
LOCKER_ADMIN: 4,
MERCHANT: 5,
CUSTOMER: 6,
COURIER: 7,
ECOMMERCE: 8
});

这是我的简单解决方案。基本上,我们不能将参数传递给中间件,但是使用包装函式我们可以实现这一点。

const restrictTo = (...roles) => {
return (req, res, next) => {
// roles are : ['admin', 'user'], role : req.user.role
if (!roles.includes(req.user.role)) // I am taking role from req.user you can get it from model
{
return new Error('You dont have permission to delete the tour', 404)
}
next();
}
};
Call it like ...


router.delete(restrictTo('admin', 'user'), handler);