Spring Cloud - 如何仅允许访问特定微服务的端点?

Posted

技术标签:

【中文标题】Spring Cloud - 如何仅允许访问特定微服务的端点?【英文标题】:Spring Cloud - how to allow access to endpoint for specific microservice only? 【发布时间】:2017-12-12 19:07:41 【问题描述】:

我有简单的微服务架构:

边缘服务 服务注册表 身份验证服务(我使用的是 JWT 和 OAuth2) 用户服务 前端和一些核心服务

当用户尝试登录时,凭据会从边缘服务传递到身份验证服务。 Auth 服务从用户服务中获取用户数据(使用 @FeignClient),如果用户名/密码匹配,它会生成令牌。没什么好看的。

这种方法有一个“小”问题:用户服务中的端点/api/user/username 被身份验证服务用来获取用户数据,任何用户都可能使用它来获取任何其他用户的数据(密码、角色等) .)。一种解决方案是以某种方式为身份验证服务创建 JWT 令牌,角色为 AUTH_SERVICE,并在用户服务端检查 JWT,如果角色不同于 AUTH_SERVICE,则拒绝请求。

还有其他解决方案吗?

编辑

我认为我的设计很常见,但显然我一开始就应该更具体:

Auth-servie 是我的授权服务器,其他服务是资源服务器 我使用 API 网关模式,并且我的身份验证服务也在代理后面 客户端应用程序获得 JWT 后,会将其添加到每个请求中,并在此基础上执行身份验证和授权;每个资源服务器都有一个用于验证签名的公钥;如果有效,则服务知道 JWT 已由受信任的身份验证服务生成,并且基于 JWT 的服务会创建包含所有用户信息的 OAuth2Authenication 对象

EDIT2:

我最终将 auth-service 合并到 user-service,这是几个 SO 用户给出的建议。经过考虑,似乎没有必要为 JWT 生成单独的身份验证服务。我接受了@Abhijit Sarkar 的回答,因为它有一些有效点,即使他对额外调用 auth-service 来验证令牌的有效性是不正确的。

【问题讨论】:

不应允许用户一开始就检索其他用户数据。要调用 /api/user 端点,首先必须授权用户,以便他只能检索自己的数据。授权由 auth 服务完成,因此请考虑将该功能从 userservice 移至 auth 服务。从其他服务检索密码/角色听起来很糟糕,这应该是身份验证服务的责任。 这些都是有效的,我很清楚。只是我有一个上面描述的架构,并且对是否可以保持用户服务和身份验证服务分开并且仍然具有安全应用程序感兴趣。我认为这是可能的(我已经阅读了有关 OAuth 范围的信息,就是这样),但现在我开始怀疑改变架构是否会更好。我会考虑的 - 谢谢。 除了下面我的回答,你可能还想看看这篇文章:baeldung.com/sso-spring-security-oauth2 谢谢。但只是在您编辑后澄清一下:我真的知道我的授权服务器在哪里。我试图解释它,但显然我失败了 - 这是身份验证服务。另外,在我们聊天之后,我运行了我的应用程序,结果证明我是对的:在 auth-service 生成 JWT 之后,我可以将其关闭,然后使用 JWT,我可以访问其他服务中的一些安全资源(即 Resources服务器)。这种架构的最佳示例可以在这里找到github.com/mavogel/uaa-behind-zuul-sample/tree/… 【参考方案1】:

在身份验证和用户服务中使用相同的数据库会更好。身份验证服务只需要访问凭证。

您甚至可以在用户服务中设置一个安全层来根据角色实现对 URI 的访问控制。

你需要这样的东西:

    在边缘服务中定义预过滤器 边缘服务获取身份验证请求并将其转发给身份验证服务。 身份验证服务使用与用户服务相同的数据库对用户进行身份验证并生成 JWT 令牌。 所有其他请求都将在请求标头中包含令牌。 边缘服务共享创建 JWT 令牌所用的密钥或具有用于验证签名的公钥。 Edge 服务在其预过滤器中验证令牌,并在明文的请求标头中添加用户信息。将请求重定向到所需的服务。 服务接受请求,并在其安全过滤器中使用来自标头的用户信息来实施对资源的访问控制。

【讨论】:

这是一个很酷的答案,赞成 - 谢谢。实际上我已经在我的另一个项目中成功地使用了这种方法。最后,在我目前的项目中,我决定将 auth-service 合并到 user-service。 我不会在身份验证和授权中涉及这么多服务。在这种方法中,每个服务都必须进行某种安全处理才能成功执行请求。如果发生变化(如 JWT 令牌格式),所有服务都会受到影响,这是耦合的明显迹象。 不,只是边缘服务需要具备处理 JWT 令牌的能力。正如我在回答中提到的,所有其他服务都会以纯格式(不是令牌)获取用户信息。他们可以参考他们需要的任何信息(如 UserId、角色)并使用它来加强安全性。根据您的评论每个服务都必须进行某种安全处理我想说在每个服务中都有一个安全层是最佳实践,但服务不应该依赖于 JWT。【参考方案2】:

在我看来,您将服务拆分得太细了;这种情况发生了,随着时间的推移,您开始意识到由于维护和性能问题,服务需要更加粗粒度。从身份验证到用户服务的另一个 HTTP 调用的成本,以及维护服务间身份验证的开销并非微不足道。

IMO,如果存在其他用户信息,例如地址等,则用户服务可以存在,但身份验证服务应负责管理自己的数据。这正是 Spring Security 有 UserDetailsService 的原因。

这实际上是一个设计选择,用户凭据和其他用户信息是否应该在同一个表中,甚至是同一个数据库中。不同的人会给你不同的答案,但根据我的观点和经验,少量 相关服务之间的共享数据库是可以接受的,尤其是因为这些表是相关的通过外键(userId)。分布式事务对于微服务来说是纯粹的邪恶,所以我什至不会去那里。当您删除/更新用户时,请使用事件实现最终一致性。

编辑

在和 OP 聊天之后,我了解到用户服务在他的设计中确实是 OAuth 资源服务器。他不清楚,因此对我来说,OAuth 授权服务器在哪里。无论如何,我支持合并用户服务和身份验证服务的建议。

【讨论】:

实际上,因为我使用 JWT,所以 auth-service 和 user-service 之间的调用次数应该不是问题:一旦 auth-service 生成 JWT,我就拥有了授权和验证我的用户所需的一切. 从身份验证到用户服务的调用发生在您的设计中,无论您是否使用 JWT 或其他方式。我上面所说的一切仍然有效。 JWT 是在 header 中传递的令牌,仅此而已。 没错,我在处理微服务方面没有太多经验,但我已经阅读了两本关于它的书和一些文章,所以幸运的是我能够避免分布式事务的问题。您对共享数据库的想法很有趣,我必须考虑一下。谢谢 啊,城里的新流行词,现在每个公司都想转向微服务,但如果你问他们,大多数人都无法形容:) 是的,有点像 :) 但这不一定是个坏主意。可能我并不了解所有微服务架构,但它仍然是一个有趣的概念,也是探索新技术、新方法的机会。肯定是一次很好的体验。

以上是关于Spring Cloud - 如何仅允许访问特定微服务的端点?的主要内容,如果未能解决你的问题,请参考以下文章

仅使用承载保护 Spring Cloud Gateway

Spring Security仅允许匿名访问

spring cloud各个微服务之间如何相互调用(FeignFeign带token访问服务接口)

如何允许 Spring Boot 应用程序使用具有 Spring Cloud 依赖关系的自定义 jar

服务门户:Spring Cloud Gateway 如何把好微服务的大门

spring bootspring cloud下spring boot微服务启动没有报错,但是访问访问不到