检查 Node.js Rest API 上的资源所有权

Vek*_*r88 5 rest mongoose node.js express

我正在尝试使用express 和mongoose 开发Node.js 后端。

网络上有很多关于如何实现正确的身份验证层的示例,但我找不到任何关于如何正确实现授权层的示例。

在我的具体情况下,我正在创建多用户应用程序的后端,我希望每个用户只能看到他/她自己插入的数据。

我有三个模型:

  1. 用户
  2. 类别
  3. 文档

用户拥有一个或多个类别,类别包含零个或多个文档。

CRUD 操作在以下端点上实现:

/user/:userid
/user/:userid/category
/user/:userid/category/:categoryid
/user/:userid/category/:categoryid/document
/user/:userid/category/:categoryid/document/:documentid
Run Code Online (Sandbox Code Playgroud)

在身份验证部分,我为每个请求设置了当前登录的用户 ID,这样我就可以轻松检查

jsonwebtoken.userId == req.params.userid
Run Code Online (Sandbox Code Playgroud)

否则返回403错误。

检查类别的所有权非常容易,因为每个类别都包含对创建它们的用户的引用。

var CategorySchema = mongoose.Schema({
    name: {
        type: String,
        required: true,
        trim: true
    },
    user_id: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'User',
        index: true
    }
});
Run Code Online (Sandbox Code Playgroud)

然而,在文档模型中,我只有对其所属类别的引用,但没有添加对用户的引用。

因此,我想知道如何处理“嵌套”关系。我是否需要user_id在任何深度级别添加对所有这些内容的引用?有没有最佳实践?

此外,这是做我需要的事情的正确方法吗?或者是否有任何官方/成熟的库已经做同样的事情?

Vek*_*r88 0

经过一番修改,我最终得到了以下中间件。

\n\n

它基本上按预期顺序检查路由参数并检查一致的成员资格。

\n\n

不确定这是否是实现这一目标的最佳方法,但它有效:

\n\n
var Category = require('../category/Category'),\n    Document = require('../document/Document'),\n    unauthorizedMessage = 'You are not authorized to perform this operation.',\n    errorAuthorizationMessage = 'Something went wrong while validating authorizations.',\n    notFoundMessage = ' not found.';\n\nvar isValidMongoId = function (id) {\n    if (id.match(/^[0-9a-fA-F]{24}$/)) {\n        return true;\n    }\n    return false;\n}\n\nvar verifyPermissions = function (req, res, next)\xc2\xa0{\n    if (req.userId) {\n        if (req.params.userid && isValidMongoId(req.params.userid)) {\n            if (req.userId != req.params.userid) {\n                return res.status(403).send({error: 403, message: unauthorizedMessage});\n            }\n\n            if (req.params.categoryid && isValidMongoId(req.params.userid)) {\n                Category.findOne({_id: req.params.categoryid, user_id: req.params.userid}, function(err, category){\n                    if (err) {\n                        return res.status(500).send({error: 500, message: errorAuthorizationMessage})\n                    }\n                    if (!category) {\n                        return res.status(404).send({error: 404, message: 'Category' + notFoundMessage});\n                    }\n\n                    if (req.params.documentid && isValidMongoId(req.params.documentid)) {\n                        Document.findOne({_id: req.params.documentid, category_id: req.params.categoryid}, function(err, document){\n                            if (err) {\n                                return res.status(500).send({error: 500, message: errorAuthorizationMessage})\n                            }\n                            if (!document) {\n                                return res.status(404).send({error: 404, message: 'Document' + notFoundMessage});\n                            }\n                        });\n                    }\n                });\n            }\n        }\n\n        next();\n    } else {\n        return res.status(403).send({error: 403, message: unauthorizedMessage});\n    }\n};\n\nmodule.exports = verifyPermissions;\n
Run Code Online (Sandbox Code Playgroud)\n