Node.js API - 允许用户仅更新和删除自己的对象

时间:2015-01-20 10:20:56

标签: node.js rest express restful-authentication

我正在尝试使用带有Express的Node.js构建RESTful API。我是MEAN堆栈的新手,并希望使用最佳实践。我在掌握和实施方面遇到的问题如下:

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

我想到的一种可能性:

为与DB

中的令牌匹配的用户创建机密令牌

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

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

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这样的库。我想先学习基础知识。

如果你需要查看我正在使用的一些代码,我有一个这个项目的回购: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的一些机制对我来说很清楚。

3 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)

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

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更新或删除模型。

答案 2 :(得分:0)

阅读材料: 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);
  })