当正在处理的数据与调用 api 的用户相关时,需要身份验证的 API 应该在 url 调用中包含用户 ID?
想象一个被 Web 应用程序使用的 API(两者都在同一个堆栈中)并且它使用一种身份验证方法(cookie、基本身份验证等)。
假设网络管理用户拥有的书籍。当 Web 应用调用 /users/:id_user/books 时,会列出属于 :id_user 的书籍。
在这种情况下,当处理请求时,应用程序知道用户 ID。例如,在使用 Express 和 Passport 的 node.js 中,用户 ID 在 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 回答建议使用“me”作为参数,我一直在尝试执行从 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.