Express.js中间件extra(第四个)参数

Express.js中间件可选参数上 ,除了是一个error handling中间件之外,可能还有第四个参数 ,所以我有一个用例。 这可能是通过不同的方式来实现的,但无论如何。

我想要检查一些api路由权限,我希望写入的中间件应该为请求用户查找他/她有多less信誉点(整数)的数据库。 我定义了一个对象来保存作为关键值对需要的权限和信誉点。 之后,中间件应该查找这个特权对象来查看用户是否具有大于或等于相应操作的信誉点。 我想传递这个相应的动作名称作为每个路由的不同string在特权对象中的一个键。 这可以通过发送stringactionName通过请求到路由来实现,但是我发现它不太安全(请求中的数据可能被篡改为具有恶意用户可以访问的操作名称并且为其他所需的数据字段但不允许采取行动)。

所有的情况都和SE一样。

顺便说一下,显然我也需要基于路由的(不是基于路由器的)中间件安装,我不确定Express.js是否支持,但这是另一回事。

也许可以描述和问这个用例, 我可以用我的参数来参数化一个中间件函数,而不仅仅是传入的req和res对象吗?

我如何用Express.js中间件实现这个用例? 或者我应该使用另一种机制?

 /// Privilege Check middleware // used per route with corresponding actionName // signature function (request, response, next, actionNameOneOfKeysInPrevilegesObject::String) var privilegeCheck = function (req, res, next, actionName) { db.one( ` SELECT reputation FROM users WHERE id = $(id) `, {id: req.user.id} // remember req.user was set by jwt.sign(data) during login or signup with demanded data; here it is {id:, name:, username:,} ) .then(function (data) { if(data >= privileges[actionName]) { next(); } else { res.status(403).json({errorMessage: "You need to have " + privileges.questionUpvote + " reputation to upvote."}); } }) .catch(function (error) { console.error(error); }) }; // reputations needed for privileged actions var privileges = { questionAsk: 5, answer: 15, acceptAnswer: 0, comment: 5, questionEdit: 20, answerEdit: 20, commentsEdit: 0, postsUpvote: 30, postsDownvote: 30, commentsUpvote: 5, questionUpvote: 10, questionDownvote: 125, } 

使用路由特定的中间件如下所示:

 function privilegeCheck(actionName) { return function (req, res, next) { db.one( ` SELECT reputation FROM users WHERE id = $(id) `, {id: req.user.id} // remember req.user was set by jwt.sign(data) during login or signup with demanded data; here it is {id:, name:, username:,} ) .then(function (data) { if(data >= privileges[actionName]) { next(); } else { res.status(403).json({errorMessage: "You need to have " + privileges.questionUpvote + " reputation to upvote."}); } }) .catch(function (error) { console.error(error); }) ; } }; // Then, for each of your routes, invoke your privilegeCheck() function // as an "in-between" argument between your path and your route handler // function. app.get('/my/route', privilegeCheck("myActionName"), (req, res) => { res.status(200).send('handled /my/route'); }); 

请参阅http://expressjs.com/en/guide/using-middleware.html中的“应用程序级中间件”部分,从“此示例显示处理GET请求到/ user /:id的中间件子堆栈path。” 但是那里的文档没有显示你可以在app.get()中链接函数。 你可以看到

https://scotch.io/tutorials/route-middleware-to-check-if-a-user-is-authenticated-in-node-js

事实上,你可以根据需要为Express的路由处理函数(get(),put(),post(),delete())提供任意数量的“中间件”(即三参数函数)参数。

不幸的是,Express是编码的,所以如果你的中间件函数只有四个参数,那么它被认为是error handling中间件。 海事组织这不是一个好的devise决定。

要做你想做的事,规范的方法是将数据附加到请求stream(req)。

例如:

 app.use(function(req,res,next){ req.data = {foo:'bar'}; }); app.use(function(req,res,next){ const data = req.data; }): 

来自Java等语言,我认为这是有史以来最疯狂的编码,但它的工作原理是因为req是唯一的要求+ JS是“单线程”。