首页 > 解决方案 > Node.js:授权路由与授权方法

问题描述

快速背景

我正在使用Node.jsExpress构建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或类似的东西)

我的问题

  1. 只保护端点而不保护功能是不好的做法吗?
  2. 我不能只为每个函数都需要一个额外的参数“auth”,以便在调用它时需要currentUser.role在我的authorize()函数中接收类似的内容,否则它返回 false?这意味着我将用户手动传递给每个功能,否则它将失败
  3. 如果我应该在请求期间对用户的全局访问进行会话管理:您对框架有建议吗?

提前致谢, 本诺

标签: node.jsexpresssessionmongooseauthorization

解决方案


认证和授权是两个不同的东西,应该分开处理。身份验证说“你是谁?” 和授权说“你有许可吗?”。考虑到 Express 是完全围绕中间件设计的,我会做以下事情。

  1. 将您的身份验证抽象为一个中间件,该中间件app.use()在您安装路由器/路由之前为您的所有端点运行。
  2. 创建一个可以从任何地方调用的授权函数,它需要一个用户(或 id 或任何你拥有的)和一个角色,然后检查用户是否具有该角色。

这样想,你的授权永远不会改变,它是你应用程序的核心。如果你决定放弃 Expressjs 并使用 Koa 或从传统的 HTTP 请求转移到 Web Sockets,你就不想改变你的授权逻辑。但是您的身份验证可能会发生变化,您可能希望不再使用标头来存储令牌,也许您完全切换到 cookie 或其他东西,您可能希望更改此设置。

您最终会得到一个全局中间件,它检查身份验证令牌并将user对象附加到req. 然后,您将拥有一个名为类似的实用函数userHasRole,它将在任何需要应用程序中特定角色的端点调用。然后,您可以在应用程序中的任何位置自由检查权限。这可能在您的应用程序中位于非常不同的位置,例如,您可能会在对某个管理仪表板的请求开始时检查他们是否是管理员,但如果他们尝试访问特定资源,您可能会稍后检查权限。在访问特定资源时,您可能希望让他们通过并在最后一刻确定他们是否有权访问该资源。(它'

在某些情况下,在业务逻辑开始时检查可能是合适的,在其他地方,稍后检查可能是有意义的。这无关紧要,您应该能够在需要时运行此检查。这将完全取决于业务逻辑,如果只是格式化字符串输出,将其放置在每个函数中可能是无用的,但在尝试提取数据库记录时可能很有用。


推荐阅读