node.js - Node.js:授权路由与授权方法
问题描述
快速背景
我正在使用Node.js
和Express
构建API Mongoose
。我实施的身份验证适用于该passport-headerapikey
包。我使用 api-key 在数据库中搜索用户并将该用户添加到req
对象中。从而确保我在请求结束之前一直了解身份。
授权
让我们谈谈这个问题。
到目前为止,我authorize() function
在做任何事情之前手动调用了每个端点。像这样:
router.post('/', (req, res) => {
autorize('admin', req.user.role) // method is called at every route manually
.then(() => {
... do stuff here
})
.catch(err => req.status(403).send())
}
我的同事对我说这不是一个好的解决方案,我应该有一个会话管理,使当前用户在全球范围内可用,这样我就可以在每个功能的任何时候单独授权,而不是仅仅保护端点本身。
含义:
然后方法createUser(obj)
可以在自身内部调用授权方法或检查如下条件:
createUser(obj) {
if (currentUser.role !== 'admin') {
return false
}
obj = new User(obj)
return obj.save()
}
这意味着return false
如果满足条件,我会在每个函数中。访问该会话的全局可用 currentUser。(例如globalCurrentUser.role !== admin
或类似的东西)
我的问题
- 只保护端点而不保护功能是不好的做法吗?
- 我不能只为每个函数都需要一个额外的参数“auth”,以便在调用它时需要
currentUser.role
在我的authorize()
函数中接收类似的内容,否则它返回 false?这意味着我将用户手动传递给每个功能,否则它将失败 - 如果我应该在请求期间对用户的全局访问进行会话管理:您对框架有建议吗?
提前致谢, 本诺
解决方案
认证和授权是两个不同的东西,应该分开处理。身份验证说“你是谁?” 和授权说“你有许可吗?”。考虑到 Express 是完全围绕中间件设计的,我会做以下事情。
- 将您的身份验证抽象为一个中间件,该中间件
app.use()
在您安装路由器/路由之前为您的所有端点运行。 - 创建一个可以从任何地方调用的授权函数,它需要一个用户(或 id 或任何你拥有的)和一个角色,然后检查用户是否具有该角色。
这样想,你的授权永远不会改变,它是你应用程序的核心。如果你决定放弃 Expressjs 并使用 Koa 或从传统的 HTTP 请求转移到 Web Sockets,你就不想改变你的授权逻辑。但是您的身份验证可能会发生变化,您可能希望不再使用标头来存储令牌,也许您完全切换到 cookie 或其他东西,您可能希望更改此设置。
您最终会得到一个全局中间件,它检查身份验证令牌并将user
对象附加到req
. 然后,您将拥有一个名为类似的实用函数userHasRole
,它将在任何需要应用程序中特定角色的端点调用。然后,您可以在应用程序中的任何位置自由检查权限。这可能在您的应用程序中位于非常不同的位置,例如,您可能会在对某个管理仪表板的请求开始时检查他们是否是管理员,但如果他们尝试访问特定资源,您可能会稍后检查权限。在访问特定资源时,您可能希望让他们通过并在最后一刻确定他们是否有权访问该资源。(它'
在某些情况下,在业务逻辑开始时检查可能是合适的,在其他地方,稍后检查可能是有意义的。这无关紧要,您应该能够在需要时运行此检查。这将完全取决于业务逻辑,如果只是格式化字符串输出,将其放置在每个函数中可能是无用的,但在尝试提取数据库记录时可能很有用。
推荐阅读
- ios - 即使只有一项更改,完整列表也会重新创建所有视图
- java - 如何在数据库中存储工作日数据以及开始时间和结束时间?
- python - 如何沿着由 3 个点和一个长度给出的弧移动鼠标?
- php - DateTime::setTime() 期望参数 1 为 int,给定字符串,但在尝试观察时消失
- php - 我可以设置选中或未选中的复选框来读取字符串值吗?
- jenkins - Gitlab Webhooks(同一个 repo 上有 2 个 Webhooks)
- java - Spring with MongoTemplate:java.lang.String com.mongodb.connection.ClusterSettings.getDescription()
- java - MVC - Spring Boot 和 Angular - Spring 中的视图是什么?
- html - 根据图像描述文本过滤以在浏览器中隐藏/显示图像
- ios - 当用户摇动手机而不在 iOS 中打开应用程序时,我们可以向用户显示弹出窗口吗?