【问题标题】:Node.js API - Allow users to only update and delete their own objectNode.js API - 只允许用户更新和删除他们自己的对象
【发布时间】:2015-03-18 12:50:45
【问题描述】:

我正在尝试使用带有 Express 的 Node.js 构建一个 RESTful API。我对 MEAN 堆栈相当陌生,并且想使用最佳实践。我难以理解和实施的概念如下:

限制用户对象上的 PUT 和 DELETE 等路由,只允许来自“拥有”该对象的用户的请求。

我想到的一种可能性:

为与数据库中的令牌匹配的用户创建秘密令牌

因此,在创建用户时,我为他们分配了一个令牌,将其存储在数据库中并将其附加到他们的会话数据中。

然后我的中间件看起来像:

router.put('/api/users/:user_id', function(req, res, next) {
  // already unclear how this token should be transfered 
  var token = req.headers['x-access-token'] || req.session.token;

  // update user (PUT /api/users/:user_id)
  User.findById(req.params.user_id, function(err, user) {
    if (err) {
      res.send(err);
    } else if (user.token != token) {
      res.json({ sucess: false, message: 'User not same as authenticated user.' });
    } else {

      // set new information only if present in request
      if (req.body.name) user.name         = req.body.name;
      if (req.body.username) user.username = req.body.username;
      ...

      // save user
      user.save(function(err) {
        if (err) res.send(err);

        // return message
        res.json({ message: 'User updated.' });
      });
    }
});

我对最佳做法的疑问

  • 我想到的场景是否可信?
  • 我应该使用哪些数据来为用户创建唯一令牌?
  • 将令牌存储在会话中是最佳解决方案吗?

旁注

这对我来说是一个学习项目,我知道像 Passport.js 这样的库。我想先学习基础知识。

如果您需要查看我正在使用的一些周边代码,我有这个项目的 repo:https://github.com/messerli90/node-api-ownership

编辑

我会接受一本很好的 RESTful API 书籍推荐,其中涵盖了这些要点,作为答案。

编辑 2

我实际上在本教程中找到了很多我正在寻找的答案:http://scottksmith.com/blog/2014/05/29/beer-locker-building-a-restful-api-with-node-passport/

我试图在不使用 passport.js 的情况下做到这一点,但文章中介绍的许多概念让我清楚地了解了授权 API 的一些机制。

【问题讨论】:

  • 我不太清楚在您的场景中用户 id 和访问令牌之间的区别在哪里?
  • @mvuajua 如果我理解你的问题。正在定义的令牌从 req.session.token 中提取并与用户对象中的令牌进行比较。
  • 是的,但是为什么不使用用户 ID(数据库中已经存在并且很可能在会话中需要)?您认为使用访问令牌的优势在哪里?
  • 我个人认为这没有任何风险(除非您打算让令牌有点可访问性 - 是吗?),因为您甚至可以在查询数据库之前进行检查,因此风险可能更小,但也许有更多知识的其他人可以详细说明:)
  • 只要会话 id 不是用户 id 就可以了,另请参见 this answer(php,但原理相同)——尽管访问令牌也是如此

标签: node.js rest express restful-authentication


【解决方案1】:

如果我理解您的问题,这是一个 API,客户端(不是浏览器)在请求的标头中传递秘密令牌(api 密钥)。似乎有道理。当然,你必须要求 https 来保护 api 密钥。而且,您应该有一种方法让用户撤销/重新生成他们的 API 密钥。

到目前为止,我认为您不需要在会话中存储任何内容。似乎将令牌存储在会话中只会使事情复杂化。据推测,如果您要建立会话,客户端必须在第一个请求中包含令牌。那么,为什么不在每个请求上都需要它而忘记会话呢?我认为这让 api 客户端的工作变得更简单。

【讨论】:

  • 另外,根据定义,REST 在任何情况下都不应该知道会话。
【解决方案2】:

有点晚了,但如果有人还在寻找答案,我就是这样做的:

router.put('/', function(req, res) {
    var token = req.headers['x-access-token'];
    if (!token) return res.status(401).send({auth:false, message:'No token provided'});
    jwt.verify (token, process.env.SECRET, function (err, decoded) {
        if(err) return res.status(500).send({auth:false, message:'failed to auth token'});
        User.findByIdAndUpdate({_id: decoded.user_id}, req.body, function(err, user) {
            if (err)
                res.send(err);
            res.json({username: user.username, email: user.email});
        });
    });
});

只需将存储在令牌中的用户 ID 传递给 mongoose 函数。这样发送请求的用户只能用他的 ID 更新或删除模型。

【讨论】:

    【解决方案3】:

    阅读材料: Implementing Access Control in Node.JS

    找到这篇关于如何允许用户只删除他们拥有的回复的超级清晰的文章。希望对您有所帮助。

    什么对我有用:

    .delete(requireAuth, async (req, res, next) => {
        const knexInstance = req.app.get("db");
        const comment = await CommentsService.getById(knexInstance, req.params.id);
    
        if (comment === undefined) {
          return res.status(404).json({
            error: {
              message: `Comment doesn't exist.`
            },
          });
        }
    
        if (comment.users_id !== req.users.id) {
          return res.status(401).json({
            error: {
              message: `You can only delete your own comments.`
            },
          });
        }
    
        CommentsService.deleteComment(knexInstance, req.params.id)
          .then((numRowsAffected) => {
            res.status(204).end();
          })
          .catch(next);
      })
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-01-12
      • 1970-01-01
      • 1970-01-01
      • 2021-12-03
      • 1970-01-01
      • 2017-11-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多