API设计:当api经过身份验证后,用户ID应该在url中吗?

时间:2013-08-17 01:04:19

标签: node.js api

当正在处理的数据与正在调用api的用户相关时,需要身份验证的API应包含url调用中的用户ID?

想象一下Web应用程序正在使用的API(两者都在同一个堆栈中) 它使用身份验证方法(cookie,基本身份验证等)。

假设网络管理用户拥有的图书。 当网络应用程序调用/ users /:id_user / books时,会列出属于:id_user。

的书籍

在这种情况下,当处理请求时,应用程序已知用户ID。例如,在使用Express和Passport的node.js中,用户标识位于request.user.id中,例如

所以我想知道这是否是一个省略的好方法:id_user作为参数,因为代码可以做类似的事情:

路线:/ users / books(获取用户帐簿)

app.get('/users', auth(), function (req, res) {

var userId: req.user.id; // Get user id from authentication data.
// Find user's books
books.find({ _owner: req.user.id}, function(err, books){return res.send(books)});

}

而不是

路由:/ users /:id_user / books(使用显式用户ID从已登录用户获取图书)

app.get('/users/:id_user', auth(), function (req, res) {

var userId = req.params.id_user; // get param from the URI

// For security reasons: prevent the user to access other user books
// by providing another user id in the url by comparing logged user credentials to
// user id from URI.

if (req.params.id !== req.user.id) { return res.send(403); // Forbidden }

// Find user's books.
books.find({ _owner: userId}, function(err, books){return res.send(books)});

}

更新:

由于Jonathan P. Diaz回答谁建议使用“我”作为参数我一直在尝试执行从req.params.id =“me”到req.params.id = req.user的更改.id在一个地方而不是在每条路线中写入代码行。 此外,在作为app.get / app.put / etc的第二个参数传递的回调中,也无法修改中间件中的req.params(它在点上不存在)。当调用该方法时,req.params.id又是“我”,它在执行数据库操作时显然失败了。

我发现的解决方案是:

在您的路线文件中添加如下函数:

var callWrapper = function(callback) {

    return function(req, res) {

      if (req.params && req.params.id === "me") {
        req.params.id = req.user.id;
      }
      return callback(req, res);
    }
}

然后以这种方式建立路线:

app.get('/users/:id/books', securityProtectionApi, callWrapper(user.showUserBooks));

Note: user.showUserBooks is the controller method and securityProtectionApi is a check using passport for sending unauthorized when the user is not authenticated.

2 个答案:

答案 0 :(得分:1)

好问题。 我认为解决方案更加清洁。 在某些情况下,您需要指定实际调用服务的人,因为它是一个共享方法(例如,您可以使用相同的方法访问其他用户的公共数据),它可以是已登录用户或其他人,我们通常会使用相同的想法,就像你说“/ method /:id / books”但当:id 等于“ me “(” / users / me / books “)我们假设这是当前用户,我们使用护照上保存的值,如果没有,:id param是我们继续这个过程所需要的。

app.get "/users/:id/books", (req, res, next) ->
    if req.params.id and req.params.id == "me"
        req.params.id = req.user.id

修改 您可以使用app.use()将其添加为中间件。将其置于顶部,并可能使用更具体的参数名称以使其清楚。 Express app.use()

app.use(function(req, res, next){
 if (req.params && req.params.userId === "me") {
        req.params.id = req.user.id;
      }
next();
}

答案 1 :(得分:0)

取决于您的安全级别,但您有选择权。风险包括:

  • 增加ID以访问其他用户数据
  • 修改 请求查看其他用户帐户(帐户所有权)
  • 披露 用户帐号和浏览器和代理缓存的ID(标题 存储在日志中)

一般来说,你有   - 身份验证(登录或匿名)和   - 授权(授权,我可以查看此页面。)

将这些参数提供给网址会打开您,然后才能完成权利检查(常见错误)。

我对它的看法是:当用户上下文很重要时,不要使用它。 (配置文件,订单,帐户列表等)而是使用会话令牌并推断服务器上的权利。