APIdevise:当API被authentication时,用户ID是否应该在url中?

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

试想一下,一个Web应用程序正在使用的API(都在同一个堆栈中),它使用一种authentication方法(cookie,基本authentication等)。

比方说,networkingpipe理用户所拥有的书籍。 当web应用程序调用/ users /:id_user / books列出属于id_user的书籍时。

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

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

路线:/用户/书籍(获取login用户的书籍)

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(使用显式用户标识从logging的用户获取书籍)

 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)}); 

}

更新:

由于乔纳森·P·迪亚兹回答谁build议使用“我”作为参数,我一直在尝试执行从req.params.id =“我”改变为req.params.id = req.user.id一个地方,而不是写在每一个路线的代码行。 也不可能修改中间件中的req.params(它不存在的地方),也不能在作为app.get / app.put / etc的第二个parameter passing的callback中。 当这个方法被调用的时候,req.params.id又是“我”,在执行数据库操作时显然失败了。

我find的解决scheme是这样的:

在你的路线文件中添加一个这样的function:

 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); } } 

然后用这种方法build立路线:

 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. 

好问题。 我认为解决scheme要更加干净。 在某些情况下,您需要指定实际调用服务的人员,因为这是一种共享方法(例如,您可以使用相同的方法访问其他用户的公共数据),可以是login用户或其他人员我们通常做的是使用相同的想法,正如你所说的“/ method /:id / books”但是当id等于“ ”(“ / users / me / books ”)时,我们假定是当前用户我们使用通过护照在请求上保存的值,如果没有,则:id参数是我们需要继续进行的过程。

 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()将其添加为中间件。 把它放在最上面,也许使用一个更具体的参数来清楚说明。 快速app.use()

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

取决于你的安全级别,但你有select。 风险包括:

  • 增加ID以访问其他用户数据
  • 修改请求以查看其他用户帐户(帐户所有权)
  • 将用户帐号和ID分配给浏览器和代理caching(存储在日志中的头文件)

一般来说,你有 – 身份validation(login或匿名)和 – 授权(权利,我可以看到这个页面。)

提供这些参数的url打开你,然后权利检查没有完成(常见的错误)。

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