nodejs passport - 在 api 中使用相同的路由,但 return 基于权限的不同数据集
nodejs passport - use same routes in api but return different sets of data based on permissions
不确定如何处理他的问题。假设我有这个端点:
GET /api/Books/
对于网络服务上的用户,这将return 仅 用户的资源。它可能看起来有点像这样:
exports.getBooks = function(req, res) {
// find all books for user
BookModel.find({ userId: req.user._id }, function(err, books) {
if (err)
res.send(err);
res.json(books);
});
};
使用api的网络服务需要用户先登录。我可以使用基本的护照策略来确保身份验证来实现这一点。但是假设我有一个管理员帐户需要查看所有记录过的书籍。更重要的是,管理员帐户和用户帐户具有完全不同的属性,因此分配 Boolean
权限是不够的。使用相同的端点:
GET /api/Books
我认为没有理由编写另一个端点来实现此目的。然而,差异看起来像这样:
exports.getBooks = function(req, res) {
// find all books in the database
BookModel.find({}, function(err, books) {
if (err)
res.send(err);
res.json(books);
});
};
但是我无法想出一个干净的方法来实现这一点,同时还按预期使用护照中间件:
router.route('/books')
.post(authController.isAuthenticated, bookController.postBooks)
.get(authController.isAuthenticated, bookController.getBooks);
函数isAuthenticated
只会验证请求资源的用户是否有权限,不会改变控制器的行为方式。我乐于接受想法。
回答
用户@ZeroCho 建议检查 req.user
对象中的用户属性以确定应发回的内容。这比我预想的要简单。在 passport.BasicAuth
策略的实施中,我检查了哪个 table 有匹配的文档。一旦在普通用户或管理员用户 table 中找到用户,您所做的就是在 isMatch
return 对象中添加一个 属性。
// Basic strategy for users
passport.use('basic', new BasicStrategy(
function(email, password, done) {
verifyUserPassword(email, password,
function(err, isMatch) {
if(err) { return done(err); }
// Password did not match
if(!isMatch) { return done(null, false); }
// Success
var userInfo = {
email: email,
isAdmin: isMatch.isAdmin || false,
businessID: isMatch.businessID || false
};
return done(null, userInfo);
});
})
);
然后您可以检查 .isAdmin
或 .businessID
在您的请求中是否有效。
只需通过 if 语句分隔您的控制器
exports.getBooks = function(req, res) {
if (req.user.isAdmin) { // or some other code to check user is admin
// find all books in the database
BookModel.find({}, function(err, books) {
if (err)
res.send(err);
res.json(books);
});
} else {
BookModel.find({ userId: req.user._id }, function(err, books) {
if (err)
res.send(err);
res.json(books);
});
}
};
不确定如何处理他的问题。假设我有这个端点:
GET /api/Books/
对于网络服务上的用户,这将return 仅 用户的资源。它可能看起来有点像这样:
exports.getBooks = function(req, res) {
// find all books for user
BookModel.find({ userId: req.user._id }, function(err, books) {
if (err)
res.send(err);
res.json(books);
});
};
使用api的网络服务需要用户先登录。我可以使用基本的护照策略来确保身份验证来实现这一点。但是假设我有一个管理员帐户需要查看所有记录过的书籍。更重要的是,管理员帐户和用户帐户具有完全不同的属性,因此分配 Boolean
权限是不够的。使用相同的端点:
GET /api/Books
我认为没有理由编写另一个端点来实现此目的。然而,差异看起来像这样:
exports.getBooks = function(req, res) {
// find all books in the database
BookModel.find({}, function(err, books) {
if (err)
res.send(err);
res.json(books);
});
};
但是我无法想出一个干净的方法来实现这一点,同时还按预期使用护照中间件:
router.route('/books')
.post(authController.isAuthenticated, bookController.postBooks)
.get(authController.isAuthenticated, bookController.getBooks);
函数isAuthenticated
只会验证请求资源的用户是否有权限,不会改变控制器的行为方式。我乐于接受想法。
回答
用户@ZeroCho 建议检查 req.user
对象中的用户属性以确定应发回的内容。这比我预想的要简单。在 passport.BasicAuth
策略的实施中,我检查了哪个 table 有匹配的文档。一旦在普通用户或管理员用户 table 中找到用户,您所做的就是在 isMatch
return 对象中添加一个 属性。
// Basic strategy for users
passport.use('basic', new BasicStrategy(
function(email, password, done) {
verifyUserPassword(email, password,
function(err, isMatch) {
if(err) { return done(err); }
// Password did not match
if(!isMatch) { return done(null, false); }
// Success
var userInfo = {
email: email,
isAdmin: isMatch.isAdmin || false,
businessID: isMatch.businessID || false
};
return done(null, userInfo);
});
})
);
然后您可以检查 .isAdmin
或 .businessID
在您的请求中是否有效。
只需通过 if 语句分隔您的控制器
exports.getBooks = function(req, res) {
if (req.user.isAdmin) { // or some other code to check user is admin
// find all books in the database
BookModel.find({}, function(err, books) {
if (err)
res.send(err);
res.json(books);
});
} else {
BookModel.find({ userId: req.user._id }, function(err, books) {
if (err)
res.send(err);
res.json(books);
});
}
};