假设我有两个用户,A 和 B。
A 可以访问所有可用的资源,但 B 只能访问它们的一部分。
防止 B 访问 B 没有权限的资源的正确方法是什么?
我应该创建某种白名单来指定只有 URL B 可以访问吗?
以下代码段是我目前拥有的。它是一个中间件,用于检查是否允许每个请求访问特定的 URL。
const ALLOWED_URLS = ['api/resource1', 'api/resource2', 'api/resource3'];
const sessionCheck = (req, res, next) => {
const url = req.originalUrl;
// check whether accessing URL is allowed
}
Run Code Online (Sandbox Code Playgroud)
还有比这更好的方法吗?
您要问的是 IAM(身份和访问管理)。特定资源的角色、所有权和权限通常作为它们自己的业务域对象保存在您的数据库中。这是语言不可知的,并不特定于 node 或 express。您不应该构建 URL 白名单。您要保护的资源在您的数据库中。您应该将它们映射到权限对象,然后再映射到用户。你不保护 URL,你保护资源。每个人都可以访问任何 URL,但它们背后的资源是您要保护的资源,并且这些规则/权限会保存在您的数据库中。
如果您正在寻找行业标准,那么这里有一些将保留在您的数据库中的 IAM 对象的常用名称/术语:
用户 A 的访问权限通常取决于他们拥有的角色或他们所属的组。无论你给用户 A 一个角色,把他们放在一个授权的组中,还是给他们直接的权限都没有关系,这些分组的存在是为了减少重复,这样你就可以一次传递或取消多个权限。但总体思路是一样的;您的资源存在于数据库中,您指定可以访问这些资源的所需或允许的角色、组和用户,并将用户映射到组、角色等作为简单的表条目。这意味着真正的授权逻辑不在 Node 或 Express 中,甚至不在您的 web 应用程序中,它内置于资源本身并与数据的检索方式相关联。
资源检索代码
当任何人对给定资源发出请求时,无论您的数据库类型如何,如果用户未经授权,查询都会失败。这意味着您检索数据的方式必须与其授权方式直接相关,而不是两个单独的步骤;这意味着您不应该获取资源,然后检查用户是否被授权,并且在获取资源之前不应该检查用户是否被授权。最佳实践是融合/加入两者,这样除非您授权,否则您无法获得资源,因为我们使用您的角色寻找资源,如果您没有正确的角色,我们将无法找到资源。
例如:
function getAccount(userId,accountId) {
makeSQLCall(userId,accountId)
}
SELECT *
FROM accounts a
WHERE a.accountId = accountId AND u.userId = userId
JOIN users u ON a.allowedRole = u.role
Run Code Online (Sandbox Code Playgroud)
SQL 无关紧要,因为其他技术也可以做到这一点,但最后一行是最重要的(account.allowedRole = user.role)。您实际上是使用用户角色从数据库中提取资源,这样如果他们未经授权,就会失败并且不会返回任何数据。这也是您的基本/父数据检索功能,因此其他不了解授权的功能可以使用此功能,授权将在后台处理。
快速伪代码
router.get('/api/resource1',function(req,res){
var user = utility.getUserFromRequest(req)
var resource = accountService.getAccount(user,req.body.accountId)
sendResponse(resource)
})
Run Code Online (Sandbox Code Playgroud)
查看上面的代码,授权内置于您的域模型中,而不是您的 Web 应用程序中。如果提出上述请求的用户未经授权,他们将不会获得任何数据。您必须在自己的业务用例中弄清楚返回空结果是否足够,或者是否需要返回 401 HTTP 错误代码。如果您需要通知您的非恶意用户他们未经授权,您可以isAuthoriized(user,accountId)在运行之前简单地执行accountService.getAccount,以方便 UI。这种方法的优势在于,如果您或其他一些开发人员忘记检查 isAuthorized 1st,调用仍然不会返回任何数据,因为 isAuthorized() 只是为了用户的利益而不是安全性。安全性位于域/数据库层。
| 归档时间: |
|
| 查看次数: |
2052 次 |
| 最近记录: |