首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用OAuth2/OpenId连接和微服务进行身份验证和授权

使用OAuth2/OpenId连接和微服务进行身份验证和授权
EN

Stack Overflow用户
提问于 2017-07-12 14:30:41
回答 1查看 1.9K关注 0票数 6

我试图将Oauth2/OpenId连接到基于Java/Spring的微服务体系结构中。我当前的问题是在微服务之间或通过像RabbitMQ这样的消息代理进行令牌传播。

很少有话题谈论这个问题。我只找到了这个堆栈过流线程,但我不喜欢建议的答案。

以下是不同的案例:

我的微服务A接收通过API网关并携带有效访问令牌的最终用户发起的请求(带有与最终用户对应的作用域/声明的JWT:用户名、id、电子邮件、权限等)。这个案子没问题。微型服务拥有处理请求所需的所有信息。

第一个问题:如果微服务A需要调用微服务B会发生什么?

  • 第一种解决方案:微服务A向微服务B发送接入令牌

==>,如果令牌在到达微服务B之前过期怎么办?

  • 第二个解决方案:使用OAuth (又名服务帐户)提出的“客户凭据授予”。它意味着微服务A用自己的凭证请求一个新的访问令牌,并使用它调用微服务B。

使用此解决方案的==>,所有与用户相关的数据(用户名、id、权限等)都迷失了。

例如,微服务B中被调用的方法需要用户id才能工作。可以将用户id值设置为查询字符串。如果使用用户访问令牌调用该方法,则微服务B可以验证查询字符串中的用户id值是否等于JWT令牌中的用户id值。如果使用服务访问令牌调用该方法,则微服务B无法验证查询字符串值,需要信任微服务A。

对于这个cas,我听说了来自OAuth 2的“OAuth”草稿,这个想法非常有趣。它允许微服务A将用户访问令牌转换成另一个权限较低的访问令牌,但对于微服务A却是伪造的。不幸的是,这种机制仍处于起草阶段,在许多产品中没有实现。

第二个问题:如果微服务A将消息推送给RabbitMQ,而微服务B接收到此消息,会发生什么?

  • 第一种解决方案:身份验证和授权由RabbitMQ (vhost、帐户等)管理。

再次==>,所有与用户相关的数据都会丢失。此外,我们还有两个存储库来管理身份验证和授权。

  • 第二个解决方案:与第一个问题一样,使用“客户凭据授予”

你对此有何看法?还有更好的解决办法吗?

提前谢谢。

EN

回答 1

Stack Overflow用户

发布于 2020-05-08 15:13:25

很简单。始终有两个用例,我们将称为最终用户和app2app。总是要处理好这两个问题。

考虑一个简化的体系结构:

代码语言:javascript
复制
         Internet                
User ----------------> Service A +-------> Service B
      HTTP request               |
                                 +-------> Service C

JWT 假设用户通过令牌进行身份验证。、、或其他任何东西都不重要.

服务A验证用户令牌并执行操作。它必须调用服务B和C,以便进行适当的请求,并且必须在这些请求中包含用户令牌。

可以进行一些转换。也许A从cookie读取用户令牌,但B从Authorization: Bearer xxx头读取令牌( HTTP中接受JWT令牌的一种常见方式)。也许C不是基于HTTP的,而是GRPC (或者开发人员现在使用的任何东西?),所以令牌必须通过该协议转发,不知道传递额外信息的一般做法是什么。

--它非常简单,而且对所有处理终端用户的服务都很好,只要协议能够使用上下文复用消息/请求。HTTP是一个理想的例子,因为每个请求都是完全独立的,web服务器可以处理每个路径和参数以及cookie等各种内容。

它也是一个非常安全的模型,因为操作必须由用户发起。要删除一个用户帐户吗?请求可以完全限于用户,不能只是有一个雇员/实习生/黑客调用https://internal.corp/users/delete/user123456https://internal.corp/transactions/views/user123456。实际上,例如,客户支持可能需要访问这些信息,因此除了用户之外,还必须有一些有限的访问权限。

考虑一种真实的体系结构:

代码语言:javascript
复制
         Internet                
User ----------------> Service A +-------> Service B --------> SQL Database
      HTTP request               |
                                 +-------> Service C --------> Kafka Queue
                                                                    |
                                                                    |
                                           Service X <--------------+
                                           Service Y <--------------+
                                           Service Z <--------------+

传递JWT用户令牌不适用于无法在最终用户基础上工作的中间件。特别是数据库和队列。

数据库不处理基于最终用户的访问(队列中的问题相同).访问通常需要专用的用户名/密码或SSL证书,这两种证书在数据库实例之外都没有任何意义。对每个表的访问都是完全读/写或只读的,不可能获得良好的权限(有行级权限的概念,但让我们忽略它)。

因此,服务B和服务C需要分别获得对SQL数据库和Kafka队列具有写权限的功能帐户。

服务X、Y、Z需要从队列中读取,它们都需要专用的只读访问。他们严格地不需要每个消息都有一个JWT用户令牌,他们可以相信队列中的内容是有意的,因为任何最初写到队列的东西都必须具有写入队列的显式权限。

如果服务X需要调用另一个需要用户令牌的HTTP服务,就会变得有点棘手。如果令牌没有被转发,那是很难做到的。可以沿着消息将令牌存储在队列中,但这确实是不明智的。人们不希望到处保存和持久化令牌( kafka队列写入消息,基本上会成为高度敏感的令牌数据库erf)。在此,用户令牌的转发显示了其局限性,在使用不同访问控制模型的不同协议的系统边界上。人们必须仔细考虑如何共同构建系统,以尽量减少这种麻烦。使用专用服务帐户来接口不理解终端用户令牌或没有终端用户令牌的特定系统。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45060577

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档