尝试以 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)
有什么很酷的技巧可以实现这一目标吗?预先感谢!
您可以创建一个返回中间件函数的高阶函数,允许您直接传递资源,而不仅仅是表示 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 对象中提取资源,从而使您可以灵活地访问嵌套属性。