javascript - Express.js 中间件额外(第四个)参数

标签 javascript node.js express middleware

在 Express.js 中间件的可选参数上,可能是除了错误处理中间件之外的第四个参数,我有一个有用的用例。它可以通过不同的方式实现,但无论如何。

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

所有情况都和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 处的“应用程序级中间件”部分,从“此示例显示了一个处理对/user/:id 路径的 GET 请求的中间件子堆栈”开始。 但那里的文档没有显示您可以在 app.get() 中链接函数。您可以在

看到这一点

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

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

关于javascript - Express.js 中间件额外(第四个)参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40413917/

相关文章:

javascript - 如何在 HTML 中显示未找到数据

node.js - socket.io 客户端重新连接超时

node.js - 在 Meteor 或 Node 中批量插入 mongodb

node.js - 如何在一个请求中使用两次或多次回调发送响应

javascript - 惯用的 React 和大量 DOM 操作 (MathJax)

javascript history.back 丢失搜索结果

node.js - Phusion Passenger 上的 Express.js 应用程序 - 未及时编写启动响应

node.js - 在 mongoDB 中查询以获取具有不同值和最后添加的记录

javascript - Node.js: promise 内的响应

javascript - 每次有人连接到服务器时增加计数器