如何将自定义参数从 req 对象传递到express中的中间件函数中?

问题描述 投票:0回答:1

尝试以 Express 方式编写自定义授权中间件,但在如何包含自定义参数(而不仅仅是标准 req、res、next)方面遇到了一些困惑。中间件将通过将用户的 req.user.id 与附加到相关资源的 userId 进行比较来检查用户是否拥有该资源。

基本上我有这个功能:


function verifyUserAuthorization(roles, resource){
    return (req, res, next) => {
        try{
            //Checks if the logged in user is the owner of the resource by comparing req.user.id to resource.userId
            if(roles.includes('owner')){
                //Handles cases where the resource is an array and checks ownership of all resources in the array
                if(Array.isArray(req[resource])){
                    let allAuthorized;
                    for(let item of req[resource]){
                        if(req.user.id !== item.userId){
                            allAuthorized = false;
                            break;
                        } 
                    }
                    if(allAuthorized !== false){
                        return next();
                    }
                //Handles cases of a single resource
                }else if(req.user.id === req[resource].userId){
                    return next();
                }
            }
            //A 401 error is thrown by default unless a valid authorized role is found
            throw new Error("Access denied", {statusCode: 401});
        }catch(err){
            next(err);
        }
    }
};

并且必须像这样调用它,使用字符串来访问存储资源的 req 属性:

verifyUserAuthorization(['owner'], 'invoices')

但理想情况下,我希望能够通过像这样直接传递资源来调用它,以便更容易地使用可能更加嵌套的数据。但是当然,当我重构中间件以使用新参数时,“req”是可以理解的未定义。

verifyUserAuthorization(['owner'], req.invoices)

有什么很酷的技巧可以实现这一目标吗?预先感谢!

node.js express middleware
1个回答
0
投票

您可以创建一个返回中间件函数的高阶函数,允许您直接传递资源,而不仅仅是表示 req 对象上的属性的字符串。值得尝试这样的事情,

function verifyUserAuthorization(roles, getResource) {
    return (req, res, next) => {
        try {
            const resource = getResource(req);

            // Checks if the logged-in user is the owner of the resource by comparing req.user.id to resource.userId
            if (roles.includes('owner')) {
                // Handles cases where the resource is an array and checks ownership of all resources in the array
                if (Array.isArray(resource)) {
                    let allAuthorized = true;
                    for (let item of resource) {
                        if (req.user.id !== item.userId) {
                            allAuthorized = false;
                            break;
                        }
                    }
                    if (allAuthorized) {
                        return next();
                    }
                // Handles cases of a single resource
                } else if (req.user.id === resource.userId) {
                    return next();
                }
            }
            // A 401 error is thrown by default unless a valid authorized role is found
            throw new Error("Access denied", { statusCode: 401 });
        } catch (err) {
            next(err);
        }
    };
};

然后你可以这样调用这个中间件,

app.use(verifyUserAuthorization(['owner'], req => req.invoices));

通过这种方式,您可以将函数传递给 verifyUserAuthorization 中间件,该中间件从 req 对象中提取资源,从而使您可以灵活地访问嵌套属性。

© www.soinside.com 2019 - 2024. All rights reserved.