管理员用户验证"/>
Passport JS管理员用户验证
我在前端有一个带有EJS的Node,Express应用程序。
我具有带有通行证的中间件功能,该功能在所有创建,编辑,删除路由之前运行。
function isLoggedIn(req, res, next) {
if (req.isAuthenticated()) {
if (req.user._id != "12345") {
res.redirect("/error");
}
return next();
}
res.redirect("/error");
}
我想出最好的方法来验证我的管理员用户是否是尝试访问该路由的人,是使用req.user._id通过mongo db中的用户ID进行检查
是否有更好的方法来处理管理员用户对路由和html组件的访问?
回答如下:这对我来说基本上是正确的重要的是要注意有两层:authentication
和authorization
。
身份验证实际上是一个布尔值:用户是否已身份验证?您在这里有功能req.isAuthenticated()
。对于用户是否通过身份验证(即:已登录),这可能在逻辑上返回布尔值,true或false。
授权可能采用多种形式,但实际上又是一个布尔值:此用户是否符合访问此资源的条件。
身份验证通常在中间件中很好地进行,中间件在“端点”之前运行的中央位置,但是授权不是那么简单,因为任何端点都可以允许操作或拒绝该操作,或者它可以根据用户的特权做出不同的响应。
整个对话在角色和权限讨论中可能非常深入。
我认为答案取决于应用程序。您的应用程序有两个要求:一,用户必须经过身份验证,二,用户可能需要是管理员。
答案将在某处:实现此目的的最简单方法是什么?
我认为,您将考虑SOLID原则,并注意到您拥有一个中间件,因此它应该负有一项责任:检查用户是否已通过身份验证。接下来,也许您应该有一个名为isAdmin
的中间件,该中间件可在需要此额外条件的每个端点上运行。真的就足够了-额外检查。您不应该用这些额外的东西污染您的isLoggedIn
中间件,因为这会使中间件的可重用性和可组合性降低。
isAdmin
中间件将是一个好主意,但简单地将其作为需要管理员检查的every端点内的一个函数也可能是一个好主意。哪种方法更好?首先,哪种方法更简单。更少的代码,但仍然很容易理解。
由于这是角色和权限,也许有更健壮的方法来跟踪哪些用户是管理员?如果您的代码像if (req.user._id === 12345) {}
一样运行,则需要特殊的知识来记住该位置在代码中的位置,因此它很脆弱并且“更有可能”失败。将is_admin
的列添加到您的用户表中可能是一个好主意,对于您可能具有null
的用户,每个用户的列可以为0
或1
。然后您可以检查if (req.user.is_admin) {}
。
这可能会导致我们进入中间件功能,例如:
function isAdmin(req, res, next) {
if (req.isAuthenticated() && (req.user.is_admin === 1)) {
return next();
}
return res.redirect(403, "/error");
}
[您还可以执行类似的操作,将is_admin
数据库列更改为role
,对于每个用户,可以将1
设置为每个用户,但您的管理员用户可能具有2
。这将使您可以执行以下操作:
function hasAuthorization(req, res, next) {
if (req.isAuthenticated() && (req.user.role >= 2)) {
return next();
}
return res.redirect(403, "/error");
}
这种逻辑可以使您拥有越来越多的特权角色:也许1是常规用户,2是管理员,3是管理员,4是超级管理员。如果用户角色小于4,则他们没有权限。
我认为,这种增加特权的想法很棒,除了在重构路线或角色时稍后可能会出现严重缺陷。您必须记住所有拥有> 3
的地方并将其更改为> 4
。如果您忘记了任何内容,那将立即构成安全漏洞,因此我相信您在那里理解我的观点。
而不是看到像<
和>
这样的运算符。我宁愿查看对特定角色的检查,例如:
if ((req.user.role === 'ADMIN') || (req.user.role === 'MANAGER')) {}
我们必须继续回到想法:最简单的是什么?制作isAdmin
中间件,然后将所有管理路由归为中间件,是否更简单?还是将授权检查放在每个路由中更简单?
在此处检查此示例:
import isAdmin from '../auth/isAdmin.js'
app.get('/admin', (req, res) => {
if (!isAdmin(req.user)) {
return res.redirect(403, '/error')
}
return res.render('admin')
})
这可能需要更多的工作,但是也可能更细粒度,因此您拥有更多的控制权。
app.get('/foobars', (req, res) => {
if (isAdmin(req.user)) {
return res.json(/* all foobar records from all accounts */)
}
if (isManager(req.user)) {
return res.json(/* all foobar records from the user's account */)
}
return res.json({ error: 'Insufficient privileges for this operation' })
})
我的最终想法是,您应该具有两个功能:一个检查用户是否已通过身份验证,另一个检查用户是否被授权。然后,您可以将它们堆叠在一个中间件或两个中间件中,或者在一条路由中。
我还认为您应该找到一种更强大的方法来检查用户是否是您自己。如果将应用程序从一台计算机移动到另一台计算机,则下次填充用户表时,用户ID可能会更改,因此id
不是锁定用户的有效方法。
更多推荐
Passport JS管理员用户验证
发布评论