授权服务如何在基于角色的微服务架构中实现所有权检查

Posted

技术标签:

【中文标题】授权服务如何在基于角色的微服务架构中实现所有权检查【英文标题】:How an authorization service implements ownership checks in a role-based microservice architecture 【发布时间】:2018-03-09 07:15:11 【问题描述】:

假设我在博客应用上有三种类型的用户

    作者(可以修改自己的帖子,但不能修改其他人) 管理员(可以修改所有帖子) 读者(不能修改任何帖子)

为了管理这个系统,我想要三个主要的服务:

API 网关 公开所有客户端将使用的 API,并根据需要组合服务。 一个帖子管理服务,为博客帖子提供CRUD操作(包括谁拥有什么帖子的数据) 一个授权服务,它存储角色和权限,公开一个 API,它接受一组角色(请求用户拥有的角色)和一组权限(访问 API 所需的权限) ) 并确定这些输入的角色是否涵盖所有输入的权限。

现在我正在努力解决的是资源的所有权(以及应该检查所有权的位置)。

在不与其他服务通信的情况下,授权服务如何在不知道如何确定用户是否拥有给定资源的情况下确定用户是否应该能够访问他们拥有的东西。

我想出了几个不同的解决方案来解决这个问题,尽管我对其中任何一个都不太满意。

    API 网关将查询管理帖子的不同服务,以确定请求用户是否拥有他们尝试访问的帖子,这意味着授权逻辑发生在授权服务之外。 管理博客文章的服务将根据所有权处理授权,这也意味着授权逻辑发生在授权服务之外以及未经授权的请求最初被标记为授权的事实(因为它们仍将通过授权服务) 授权服务可以知道如何检查所有权,API 必须能够被告知它是否应该检查所有权以及权限。这将增加授权服务的复杂性并增加我希望尽可能多地委托给 API 网关的跨服务通信,因为它应该是主要的服务编写器。

寻找有关替代方法的想法或洞察该问题的最佳解决方案可能是什么。

【问题讨论】:

【参考方案1】:

既然是外部化的,授权服务就应该尽可能的“哑”。有时,基于业务逻辑和数据的“授权”会变得非常复杂。我认为业务逻辑属于负责管理它的服务。此外,API 网关可能需要向客户端提供所有权状态(来自管理这些博客文章的服务?),以便客户端知道要公开什么。因此,请保持授权简单,并封装更复杂的业务检查,以查看可以在服务本身内完成的操作。

另一种方法是加强授权服务以采用另一个参数,在本例中为所有权状态。 API网关或其他服务检查授权(Blog Post Manager?)可以首先从服务了解所有权的业务中获取所有权状态,然后使用提供角色和所有权状态的授权服务。权限规则将(可选地)基于角色和真/假指示符。授权服务不知道真/假的含义,只是为角色“读者”+指示符=true和角色“管理员”+指示符=假授予权限“编辑帖子” strong> 角色“管理员”+indicator=true 等

【讨论】:

我一直倾向于您的第一个建议,我一直在实施的是允许授权服务接收一组权限数组(允许访问管理员/作者之间的路由的备用权限集) 和“元权限”普通用户通常不会拥有它作为 API 网关检查请求用户是否拥有资源的标志,如果他们这样做,它将在授权服务获得之前“删除”元权限请求(有效地让授权人在不知情的情况下拒绝/接受基于所有权的请求)【参考方案2】:

在我看来,您正在苦苦挣扎,因为您一次没有获得所有需要的信息。

为什么不使用 JWT(JSON Web 令牌)?

他们可以存储有效负载(例如用户权限、权限等),您可以轻松检查他们声称的内容是否属实。

https://auth0.com/learn/json-web-tokens/

【讨论】:

【参考方案3】:

通常对资源的访问是基于资源的所有权。例如,代表保险报价的资源。要访问保险报价,您必须是报价的用户。

我们的方法是通过网关公开 /quotes 资源,路径如下:

GET /quotes/quoteId

但是要让引号微服务将用户 ID 引入引号资源路径,例如:

GET /quotes/userId/quoteId

这允许引号微服务在用户上下文中搜索引号,如果此路径无效,则返回 404。

为了启用这种架构,网关需要根据调用者的承载令牌为调用者收集声明,并将 userId 声明的值注入下游路径。如下图所示:

这种基于所有权的访问方法可以很容易地扩展到包括其他声明(例如管理声明等)。

【讨论】:

以上是关于授权服务如何在基于角色的微服务架构中实现所有权检查的主要内容,如果未能解决你的问题,请参考以下文章

graphql 基于角色的授权

如何使用新的 Spring Authorization Server 在资源服务器上实现基于角色的授权

Spring Boot中基于​​角色的授权

如何在 WCF 服务中实现自定义身份验证

如何在 Firebase 中实现基于角色的访问控制

如果我们已经在 .Net Core 微服务 API 网关中实现了授权,我们还需要在所有微服务中实现吗?