写点什么

详解微服务中的三种授权模式

  • 2022-01-10
  • 本文字数:3902 字

    阅读完需:约 13 分钟

详解微服务中的三种授权模式

在过去的 5 个月里,我与 50 多家公司讨论了他们的授权系统。其中超过一半的公司以某种形式使用微服务,我对它们带来的授权挑战非常感兴趣。在面向服务的后端进行授权这一问题上,似乎没有公认的最佳实践。我与很多团队进行了交谈,有的团队将用户角色附加到身份验证令牌上,有的将所有内容存储在专门用于授权的图数据库中,还有的团队在 Kubernetes 边车(sidecars)中自动执行授权检查。这些解决方案中都沉淀了数月或数年的工程工作,每个团队都发明了自己的轮子。这是为什么?


当你有一个单体应用时,你通常只需要访问一个数据库来决定是否允许用户做某些事情。单体应用的授权策略本身不需要太关心在哪里找到数据(比如用户角色)——你可以假设所有数据都可用,如果需要加载额外数据,它也可以很容易地从单体应用数据库中获取。


但是这个问题在分布式架构中变得困难了许多。也许你正在将单体应用拆分为多个微服务,或者你正在开发一个新的计算密集型的服务,在运行作业之前需要检查用户权限。现在,决定谁可以做什么的数据可能不那么容易获取。你需要新的 api,以便你的服务能够相互谈论权限:“谁是这个组织的管理员?谁可以编辑这个文档?他们可以编辑哪些文档?”为了在服务 A 中做出决策,我们需要服务 B 中的数据,服务 A 的开发人员如何请求这些数据?服务 B 的开发人员如何使这些数据可用?


这些问题有很多答案,所以我试图将这些答案归纳为几个广泛的模式。这些模式不一定能覆盖所有解决方案(解决方案的世界很复杂),但我发现它们能帮助我与不同的人谈论他们所构建的东西。当我与一个新团队进行对话时,它们让我更容易对解决方案进行分类。


在构建微服务时,我看到了处理授权数据的三种主要模式。我将在这篇文章中讨论这三种方法:


  1. 将数据留在原处,让服务直接请求它。

  2. 使用网关将数据附加到所有请求,以使其随处可用。

  3. 将授权数据集中到一个地方,并将所有决策转移到那个地方。

为什么微服务中的授权更困难?


让我们以某个授权场景为例,这是一个用于编辑文档的应用程序。它很简单,但应该能说明问题:


  • 有用户、组织和文档。

  • 用户在组织中拥有角色,包括成员和管理员。

  • 文档属于组织。

  • 如果用户在组织中的角色为成员,则可以阅读文档。

  • 如果用户在组织中的角色为管理员,则可以阅读或编辑文档。


在一个单体应用中,用一种清晰的方式表达这种逻辑并不太难。当你需要检查用户是否可以阅读文档时,你可以检查该文档属于哪个组织,加载该组织中用户的角色,并检查该角色是成员还是管理员。这些检查可能需要额外的一两行 SQL 语句,但数据都在一个地方。


当你将应用程序拆分为不同的服务时,会发生什么情况?也许你已经剥离了一个新的“文档服务”——现在,检查特定文档的读权限需要检查位于该服务数据库之外的用户角色。文档服务如何访问它所需要的角色数据?


模式 1:将数据留在原处


通常,最简单的解决方案是将数据留在原处,并让服务在需要时请求它所需要的数据。对于上述问题,你可能认为这是最明显的解决方案。


你可以将数据模型和逻辑分开,这样文档服务就可以控制向哪个角色授予哪些文档相关的权限(管理员可以编辑,成员可以读取,等等),然后用户服务公开一个 API 来获取组织中用户的角色。有了这个 API,权限检查可以像这样进行:



尽管有变得混乱的风险,但这种模式可以让你走得很远。无需部署和维护额外的授权基础设施可能是一个巨大的优势,如果具有数据的服务能够处理来自需要数据的服务的负载,那么将它们串在一起就是一个很好的解决方案。

 

有一些团队遵循这种通用模式,但他们认为应该用某种专门的授权服务替换所有这些请求流,我和这些团队有过交谈。我总是问他们真正的问题是什么。如果问题是时延,也许在正确的位置添加缓存可以解决这个问题。如果授权逻辑在服务中变得越来越混乱,那么可能需要强制采用标准策略格式。(Oso 是一个解决方案;还有其他解决方案。)

 

但是,如果问题是你的数据模型变得过于复杂,或者你在重复实现相同的 api,或者权限检查需要与太多不同的服务通信,那么也许是时候重新考虑架构了。

模式 2:请求网关


解决授权数据问题的一个优雅的解决方案是将用户角色包含在对服务(这些服务可能需要做出授权决策)的请求中。如果文档服务在请求中获得有关于用户角色的信息,那么它可以基于这些信息做出自己的授权决策。



在这种模式中,“网关”位于 API 和其最终用户之间。网关可以访问用户信息和角色信息,它可以在将请求传递给 API 本身之前将这些信息附加到请求中。当 API 接收到请求时,它可以使用来自请求的角色数据(例如在请求头中)来检查用户行为是否被允许。

 

网关通常同时负责身份验证和授权。例如,网关可能使用 Authorization 头对特定用户进行身份验证,然后另外获取该用户的角色信息。然后网关将带有用户 ID 和角色信息的请求代理给下游服务(上面示例中的文档服务)。



网关模式的主要好处是其架构简单。它使下游服务(如文档服务)的开发人员不必关心角色数据来自哪里。授权数据在请求中始终是可用的,因此可以立即执行权限检查,而不需要任何额外的调用。

 

请注意,在这里使用明文头信息开辟了新的攻击途径——你需要确保恶意客户端不能注入它们自己的头信息。作为一种替代方法,用户角色或其他访问控制数据可以包含在他们的身份验证令牌中,通常表示为JWT

 

如果授权数据由少量角色组成(例如,每个用户在一个组织中只能有一个角色),网关模式的效果最好。当权限开始不仅仅依赖于用户在组织中的角色时,请求的规模就会激增。也许用户可以有不同的角色,这取决于他们试图访问的资源类型(特定事件的组织者,或特定文件夹的编辑器)。有时,这些数据太大以至于无法放入请求头中,而其他时候,一次获取所有数据效率很低。如果是这种情况,将所有相关的授权数据塞到令牌或请求头中并不能完全解决问题。

模式 3:集中存放所有授权数据

 

另一种解决方案是将所有授权数据和逻辑放在一个地方,与需要实施授权的所有服务分开。实现此模式的最常见方法是构建专用的“授权服务”。然后,当其他服务需要执行权限检查时,它们会转向询问授权服务:



在这个模型中,文档服务根本不关心用户的角色:它只需要询问授权服务,用户是否可以编辑文档,或者用户是否可以查看文档。授权服务本身包含做出该决策所需的所有内容(包括角色数据)。

 

这可能非常有吸引力:你现在有一个负责授权的系统,这符合微服务的哲学。以这种方式进行责任分离有一些好处:团队中的其他开发人员不需要关心授权是如何工作的。因为它是独立的,所以你对授权服务所做的任何优化都有助于加速整个系统的其余部分。

 

当然,这种责任分离是有代价的。现在,所有授权数据都必须保存在一个地方。决策中可能使用的所有内容都必须保存在一个集中式服务中,这些内容包括用户在组织中的身份、文档与其组织的关系。要么授权服务成为该数据的唯一真实来源,要么必须将数据从应用程序复制并同步到该中心(可能性更大)。授权系统必须理解作为所有权限基础的整个数据模型:组、共享、文件夹、来宾、项目。如果这些模型经常改变,授权系统可能成为新的开发任务的瓶颈。任意微服务中的任何更改都可能需要对授权服务进行更新,从而打破你在最 初转向微服务时可能寻求的关注点分离效果。

 

还有其他因素会使授权服务变得棘手:部署这一负责保护每个请求的服务意味着你要负责实现高可用和低延迟。如果系统出现故障,则所有请求都会被拒绝。如果授权系统系统的响应很慢,那么每个请求都很慢。

 

谷歌的Zanzibar论文概述了这种模式的一种实现,但它也带来了挑战。你必须将所有数据以“元组”的形式插入到 Zanzibar 中(Alice 拥有这个文档,这个文件夹包含另一个文件夹,等等)。由于它限制了可以存储的数据,有些规则实际上不能仅用 Zanzibar 来表示,例如一些必须与时间、请求上下文有关的规则,或者依赖于某种计算的规则。有人将这些称之为“基于属性”的规则。例如,用户每周只允许创建 10 个文档,或者管理员可以将某些文件夹设置为“只读”,以防止对其中文档的编辑。在这些情况下,开发人员必须在 Zanzibar 之外编写自己的策略逻辑。

 

集中式授权存在的挑战往往会阻止大多数团队采用这种模式。采用该模式的应用往往有很多服务和足够复杂的数据模型,接受授权服务本身增加的复杂性对它们来说是有意义的。例如,为了从单体应用向微服务转型,Airbnb建立了一个名为Himeji的授权服务以支持他们的授权模式。已经有一个专门的工程师团队为它工作了两年,而且可能会无限期地工作下去。

 

但是,如果你能够去除一些这类开销,那么对于许多使用微服务架构的团队来说,集中式授权服务可能是一个很有吸引力的选择。我的团队正在努力构建一个授权服务,力求避免集中所有授权数据的挑战。如果这是你所面临的问题,请联系我们

你应该用哪一个?

 

当与工程师团队交谈时,我的指导意见总是“围绕应用程序构建授权,而不是反过来。”对于简单系统,维护大量额外基础设施代价高昂,最好将数据保存在其所在的位置,并将服务与专用 api 放在一起。某些应用程序可以通过基本用户角色(可使用 GWT)扩展到大规模,在这种情况下,授权网关可能是最佳的。一些拥有各种产品、授权模式和用户类型的公司可能更愿意将其数据集中到专用的授权服务中。

 

如果你对讨论你的授权系统感兴趣——例如你正在考虑进行一些重构,或者只是对它的工作方式不太满意,请与我们联系。你可以与Oso工程师安排1x1讨论,或者加入我们的slack。我们喜欢讨论授权。

 

如果你曾经对混乱的授权系统感到沮丧,或者和我一样喜欢好的分布式系统问题,欢迎加入我们团队!我们正在招聘,来帮助我们推动进一步的思考。

 

原文链接:https://www.osohq.com/post/microservices-authorization-patterns

2022-01-10 18:106960

评论 6 条评论

发布
用户头像
老三样吧,认证,授权,目前方案采用的是集中认证授权服务的方式,在网关层进行用户认证和授权,信息通过请求头或者参数的方式传递,防止构造请求头的方法是直接覆盖掉前端传递过来的相同请求头的值,请求头的key的名称起的比较特殊。
2022-01-25 10:46
回复
用户头像
全球独家授权。
2022-01-15 10:57
回复
用户头像
是的,这些都是联邦上杭云计算信息服务科技有限公司独家授权。
2022-01-15 10:57
回复
用户头像
有两个疑问:
1:题中和文中的“授权”修改为“用户认证”是否更准确,因为文中没有一处讲到授权,而是用户权限管理和认证
2:第一张图和第三张图是不是反了?
2022-01-12 14:47
回复
1:这个文章是在讲授权,而不是认证。认证是解决“你是谁”,授权是解决“你能做什么不能做什么”。这篇文章都是在说后者。
2:我看这图没有反啊
2022-01-12 16:39
回复
应该算鉴权模式,授权应该是oauth相关的
2022-02-12 11:34
回复
没有更多了
发现更多内容

Day232&233

爱好编程进阶

Java 程序员 后端开发

docker的网络管理

爱好编程进阶

程序员 后端开发

dubbo 长连接

爱好编程进阶

Java 程序员 后端开发

elasticsearch各种问题总结

爱好编程进阶

Java 程序员 后端开发

不要再焦虑了,进大厂真的没你想象的那么困难

Java架构追梦

2021年最新调查:86% 的 Java 开发人员 依赖 Spring 框架

爱好编程进阶

Java 程序员 后端开发

3分钟带你彻底搞懂 Kafka

爱好编程进阶

程序员 后端开发

Dockerfile 搭建tomcat基础镜像与项目镜像

爱好编程进阶

Java 程序员 后端开发

千万级学生管理系统的考试试卷存储方案

凯博无线

五分钟搞懂分布式流控算法

俞凡

架构 算法

阿里架构师花两个月时间整理出来的Java独家面试题(Java岗)

Java架构追梦

Java 程序员 后端开发

2020年最全Java面试汇总整理(含答案)

爱好编程进阶

Java 程序员 后端开发

@Autowire和@Resource注解使用的正确姿势

爱好编程进阶

Java 程序员 后端开发

Elasticsearch Query DSL之Compound queries(复合查询)

爱好编程进阶

Java 程序员 后端开发

ElasticSearch中DSL高级检索(Query)

爱好编程进阶

Java 程序员 后端开发

Centos7安装JDK和Tomcat详细步骤

爱好编程进阶

Java 程序员 后端开发

Day163

爱好编程进阶

Java 程序员 后端开发

20多年的岁月里一路走来满是辜负与遗憾,从双非到阿里SP,收到offer的那天我哭惨了

爱好编程进阶

Java 程序员 后端开发

3 面蚂蚁,一路过关斩将 成功拿到 offer 定级 P6,大厂面试雀食有点难

爱好编程进阶

Java 程序员 后端开发

5 年 Java 经验,字节、美团

爱好编程进阶

Java 程序员 后端开发

9000字通俗易懂的讲解下Java注解,你还看不明白?

爱好编程进阶

Java 程序员 后端开发

2021阿里总监最新整理:初级-中级-高级大厂面试真题(附答案解析

爱好编程进阶

Java 程序员 后端开发

Apache负载均衡与Tomcat集群配置学习(Windows环境)

爱好编程进阶

Java 程序员 后端开发

头一次见这么牛的的SpringBoot从入门到实战文档

Java架构追梦

spring java面试 后端开发

2020,微服务降温了?

爱好编程进阶

Java 程序员 后端开发

Activiti6

爱好编程进阶

Java 程序员 后端开发

Drools规则引擎实践直白总结

爱好编程进阶

Java 程序员 后端开发

GitHub已置顶!Alibaba最终版Java面试小抄+架构师系统进阶指南

Java架构追梦

Java 后端开发 程序员面试

Elasticsearch中的Term查询和全文查询

爱好编程进阶

Java 程序员 后端开发

9 个 Java 性能调优技巧,YYDS!

爱好编程进阶

Java 程序员 后端开发

Nacos在企业生产中如何使用集群环境?

牧小农

nacos SpringCloud Alibaba

详解微服务中的三种授权模式_架构_Graham Kaemmer_InfoQ精选文章