微服务和消费者的授权和认证系统


15

我们计划将公司系统重构为基于微服务的系统。该微服务将由我们自己的公司内部应用程序以及需要的第三方合作伙伴使用。一种用于预订,一种用于产品等。

我们不确定如何处理角色和范围。这个想法是创建3个基本用户角色,例如Admins,Agent和End-Users,并让消费者应用程序根据需要微调作用域。

  • 管理员可以默认(针对其公司)创建,更新,读取和删除所有资源。
  • 代理可以为其公司创建,更新和读取数据。
  • 最终用户可以创建,更新,删除和读取数据,但不能访问与代理或管理员相同的端点。他们也将能够创建或修改数据,而不必与代理或管理员处于同一级别。例如,最终用户可以更新或阅读他们的帐户信息,就像代理可以为他们完成此操作一样,但他们看不到或更新管理员注释。

假设代理默认情况下可以为其公司创建,读取和更新每个资源,这是可以为其令牌/会话请求的最大范围,但是客户端(API使用者)应用程序的开发人员已决定他们的代理之一可以仅读取和创建某些资源。

更好的做法是在我们的内部安全性中处理此问题,然后让他们在数据库中写入该数据,还是让客户端通过请求范围较小的令牌在内部进行处理,并让他们编写哪个代理在数据库中具有哪个范围?这样,我们仅需跟踪令牌范围。

不利的一面是,我们的团队还需要在内部应用程序中创建经过微调的访问机制。

用这种思维方式,微服务及其授权系统不应受到客户需求的困扰,因为它们只是消费者,而不是系统的一部分(即使其中一些消费者是我们自己的内部应用程序)?

这是一个好的方法吗?

Answers:


14

身份验证和授权始终是好话题

我将尝试向您解释我们如何处理当前正在使用的多租户服务中的授权。使用JSON Web令牌开放标准,身份验证和授权基于令牌。该服务公开了任何类型的客户端(Web,移动和桌面应用程序)都可以访问的REST API。成功验证用户身份后,服务将提供一个访问令牌,必须在每次请求时将其发送到服务器。

因此,让我介绍一些基于我们如何在服务器应用程序上感知和处理数据的概念。

资源:客户端可以通过服务访问的任何单位或一组数据。我们要为所有要控制的资源分配一个名称。例如,有了下一个端点规则,我们可以将它们命名为:

product

/products
/products/:id

payment

/payments/
/payments/:id

order

/orders
/orders/:id
/orders/:id/products
/orders/:id/products/:id

这么说吧,到目前为止,我们在服务中拥有三种资源productpaymentorder

动作:可以在资源上执行的操作,例如读取,创建,更新,删除等。不必只是经典的CRUD操作,您可以将一个名为follow例如,为希望公开使用WebSockets传播某种信息的服务。

能力actionresource。例如; 阅读产品,创建产品等。它基本上只是资源/操作对。但是您也可以为其添加名称和描述。

角色:用户可以拥有的一组功能。例如,一个角色Cashier可以具有“已读付款”,“创建付款”或某个角色的能力Seller可以具有能力“读取产品”,“读取订单”,“更新订单”,“删除订单”。

最后,用户可以分配各种角色。


说明

如前所述,我们使用JSON Web令牌,并且用户拥有的功能在令牌的有效载荷中声明。因此,假设我们有一个小型零售商店的用户同时具有出纳员和卖方的角色。有效负载如下所示:

{
    "scopes": {
        "payment": ["read", "create"],
        "order": ["read", "create", "update", "delete"]
    }
}

正如您在scopes声明中看到的那样,我们没有指定角色的名称(出纳员,卖方),而是仅指定了涉及的资源和操作。当客户端向端点发送请求时,服务应检查访问令牌是否包含所需的资源和所需的操作。例如,GET对端点的请求/payments/88将成功,但是DELETE对同一端点的请求必须失败。


  • 如何对资源进行分组和命名,以及如何对动作能力进行定义和命名,将由开发人员决定。

  • 角色由客户决定,角色是什么,角色将具有哪些能力。


当然,您必须将额外的属性添加到有效负载中,以识别发出令牌的用户和客户(租户)。

{
    "scopes": {
        ...
    },
    "tenant": "acme",
    "user":"coyote"
}

使用此方法,您可以微调任何用户帐户对服务的访问。最重要的是,您不必在问题中指出各种预定义和静态角色,例如Admin,Agent和End-Users。一个超级用户将是拥有一个用户role的所有resourcesactions分配给它的服务。

现在,如果有100种资源并且我们想要一个可以访问所有或几乎所有资源的角色,该怎么办?我们的令牌有效载荷将是巨大的。这可以通过嵌套资源并仅在访问令牌范围内添加父资源来解决。


授权是一个复杂的主题,必须根据每个应用程序的需求进行处理。


谢谢您的回复。这非常有帮助。我有一个与每个用户的多个角色有关的问题。您是否曾经遇到过角色权限重叠的情况?如收银员有payment:[read],卖方有payment: [create]。在这种情况下,您是否汇总权限?
罗伯特

如果您具有具有重复能力的角色(resource/action),则必须将它们合并。如果权限重叠,则必须对其进行汇总。其想法是仅定义令牌中允许的资源和操作,而将角色保留为用于向客户提供一种较简单的方式来处理授权的抽象方法。

1
如果用户只能对自己拥有的资源采取行动,该怎么办?例如,就像银行帐户一样,“ bank_account”:[“ read”,“ update”]当然也没有指定。另外,微服务系统中的授权过程到底发生在哪里?在集中式授权服务器上,还是每个服务都有自己的授权?
rocketspacer

@rocketspacer。这就是令牌user在其有效负载中具有属性的原因。锁定用户拥有的资源的方式是将user声明映射到URL。例如:/users/coyote/back-account只能由标称user等于的令牌访问coyote。希望对您有所帮助。

3

我认为,无论如何,您都希望您的服务接受您编写的用于验证用户的身份验证服务提供的身份验证令牌。这是防止滥用微服务的最直接/最安全的方法。同样,通常,如果您希望客户有良好的经验,则应自己实施关键功能并进行全面测试,以确保所提供的功能得到良好实施。

由于所有调用者都需要向您的微服务提供经过身份验证的证据,因此您最好将权限绑定到该身份验证。如果您能够将用户绑定到任意访​​问组(或多个组,如果您想花哨的话,尽管此处很难对权限进行添加或减少)。那么,来自客户的问题就更少了,为什么用户x能够执行意外操作。无论如何,都必须为每个服务进行访问列表检查,所以您也应该如此。在所有服务的开头,这很容易编码(if ( !TokenAuthorized(this.ServiceName, this.token) { Raise error }),您也可以这样做并自己跟踪用户组。的确,您必须拥有一个权限组管理器,并将其工作到用户管理UI中(使用现有的/创建新组来获得用户权限),在编辑定义时一定要列出与组绑定的用户,以避免混淆。但是,这并不是一项艰巨的任务。只需拥有所有服务的元数据,然后将组和服务之间的映射关系查找到auth令牌处理中即可。

好的,所以有很多细节,但是每个需要此功能的客户端在任何情况下都必须对此进行编码,并且如果您支持三级用户权限,则最好将其扩展为按用户访问组。基本组权限和用户特定权限之间的逻辑交集可能是正确的聚合,但是如果您希望能够添加和删除Admin,Agent和最终用户基本权限中的基本权限,则必须这样做权限组中的常用三态标志:添加权限,拒绝权限,默认权限,并适当组合权限。

(请注意,如果您担心会话两端的安全性,那么所有这些事情都应该在SSL甚至双向SSL上发生。如果您将这些令牌“泄漏”给攻击者,他就好像在d破解了密码。)


在考虑基础架构和实现时,我完全忘记了客户体验。.我喜欢创建一套规则的想法,这将对我们的业务产生更大的影响。管理员,代理和最终用户过于笼统,我们计划实施更多的用户类型,这些用户类型更具描述性,并与我们的业务和通用语言绑定在一起。
罗伯特

我无法纠正最后一句话中的“ anded”错字,因为我无法弄清楚。
图兰斯·科尔多瓦

不一定是错字,但我会更清楚一点。
一点。– BenPen

1

我认为您在这里有两个选择。

  • 如果您只需要对实质上相同的应用程序具有可配置的访问权限,则让服务检查权限,并为您的客户提供一个界面,使他们可以更改为每个角色分配的权限。这使大多数用户可以使用默认角色设置,“问题”客户可以通过该默认设置来调整角色或创建新角色以满足他们的需求。

  • 如果您的客户正在开发自己的应用程序,则应引入自己的中间api。哪个以管理员身份连接到您的服务器,但在调用服务之前对照传入的自定义身份验证要求检查传入的请求


1

安全考虑

如果我对您的设计很了解,那么您打算将一些资源访问控制机制委派给客户端,即,使用功能强大的应用程序会减少用户可以看到的项目。您的假设是:

微服务及其授权系统不应受到客户需求的困扰,因为它们只是消费者,而不是系统的一部分

我在这里看到了两个严肃的问题,正经得起生意:

  • 如果某个流氓用户(例如,在您伙伴的工厂之一中)对客户应用程序进行反向工程并找到有关API的信息,绕开了公司对客户的限制,并使用该信息危害您的公司怎么办?您的公司将要求赔偿损失,但保荐人公司将辩称您没有提供足够好的保护数据的方法。
  • 通常,滥用敏感数据(否则审计会发现风险)只是时间的问题,您的管理层最终将要求对这些数据进行更严格的控制。

这就是为什么我建议您预料此类事件并处理授权请求的原因。您正处于早期的重新设计阶段,在您的体系结构中考虑这些因素(即使您没有全部实现)要容易得多。

如果您现在就职,请至少咨询您的信息安全官。

如何实施

你有窍门:

通过这种方式,我们只需要跟踪令牌作用域。

好的,您打算使用客户端选择的一些通用令牌。在我看来,这又是一个弱点,因为有些客户可能会失去您的控制。

我不知道您是否已经使用JWT或是否使用其他技术。但是,如果您使用JWT,则可以使用带有用户身份的身份令牌(甚至还有可以安全地标识原始应用程序的第二个令牌),这可以使您区分内部客户端和外部客户端之间的信任级别)。

当您打算使用微服务体系结构时,我建议建议改变用户管理和身份验证过程(应作为专用服务运行)和访问控制(特定于每个微服务,并且应该区别对待)之间的区别。由每个人在本地处理)。当然,为了便于使用,某些管理员客户端应提供有关多种服务的全面概述)。


1
这里的建议很好。我喜欢第二个令牌的想法。
罗伯特

1

在这里,还有一个简短的答案。您应该自己实现要提供给“客户”的所有核心功能。让客户端自己添加诸如用户权限之类的基本行为是有问题的,因为您已经在进行用户身份验证。如果将其留给客户端来实施,则可能最终“支持”相同权限代码的多个实施。即使您不“拥有它”,他们的代码中也会有错误,并且您希望客户在合理的范围内拥有他们期望的功能,因此您支持解决客户遇到的问题。支持多个代码库并不是一件好事。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.