Spring-Cloud-Gateway

使用 Keycloak 为 Spring Cloud Gateway 和 Spring Boot 微服务启用 OAuth2

本文将带你了解如何使用 Keycloak 为 Spring Cloud Gateway 和 Spring Boot 微服务启用 OAuth2。本文是 上一篇文章 的扩展,并分析了 Spring Security 项目中提供的一些最新功能。 我们的架构由两个 Spring Boot 微服务组成、一个基于 Spring Cloud Gateway 的 API 网关和一个 Keycloak 授权服务器。Spring Cloud Gateway 在此充当 OAuth2 客户端和 OAuth2 资源服务器。对于任何传入请求,它都会在将流量转发到下游服务之前验证 Access Token。对于任何未经验证的请求,它都会使用 Keycloak 初始化一个授权码授权的流程。我们的方案需要包括内部微服务之间的通信。它们都隐藏在 API 网关后面。caller 应用调用 callme 应用暴露的端点。通信中使用的 HTTP 客户端必须使用网关发送的 Access Token。 源码 本文中的代码托管在 Github,你可以克隆这个 Repository,进入到 oauth 目录,其中包含了两个 Spring Boot 微服务:callme 和 caller。当然,还有构建在 Spring Cloud Gateway 之上的 gateway 应用。之后,只需按照说明操作即可。 运行并配置 Keycloak 我们以 Docker 容器的形式运行 Keycloak。默认情况下,Keycloak 在 8080 端口上公开 API 和 Web 控制台。还需要通过环境变量设置管理员用户名和密码。下面是运行 Keycloak 容器的命令:

启用 Spring Cloud Gateway 的 OAuth2 支持,并将其与 Keycloak 集成

Spring Cloud Gateway 的 OAuth2 支持是微服务安全流程的关键部分。当然,使用 API 网关模式的主要原因是将服务隐藏起来,不对外部客户端可见。然而,在隐藏服务时,并没有对其进行安全保护。本文将带你了解如何使用 Spring Security 和 Keycloak 设置 Spring Cloud Gateway 的 OAuth2 功能。 源码 本文中的源码托管在 Github 上,你可以克隆 sample-spring-security-microservices 仓库,然后按照说明进行安装和部署即可。 在 Spring Cloud Gateway 中启用 OAuth2 要为 Spring Cloud Gateway 应用启用 OAuth2 支持,除了启用网关功能所必需的 spring-cloud-starter-gateway 依赖外,还需要添加 spring-boot-starter-oauth2-client 以启用 Spring Security 对 OAuth 2.0 授权框架和 OpenID Connect Core 1.0 的客户端支持,以及 spring-cloud-starter-security 来激活 TokenRelay Filter。 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-security</artifactId> </dependency> 接下来为 OAuth2 客户端提供配置设置。因为要与 Keycloak 集成,所以应将 registrationId 的名称(spring.

Spring Cloud Gateway 全局异常处理

1、概览 本文将带你了解如何在 Spring Cloud Gateway 中实现全局异常处理。 在现代软件开发中,尤其是在微服务中,API 的高效管理至关重要。这正是 Spring Cloud Gateway 作为 Spring 生态系统的关键组件发挥重要作用的地方。它就像一个门卫,将流量和请求引导到适当的微服务,并提供跨切面的关注点,如安全性、监控/指标和弹性。 然而,在如此复杂的环境中,由于网络故障、服务宕机或应用错误而产生的异常是必然的,这就需要一个强大的异常处理机制。Spring Cloud Gateway 的全局异常处理可确保在所有服务中采用一致的错误处理方法,并增强整个系统的弹性和可靠性。 2、全局异常处理的必要性 Spring Cloud Gateway 是 Spring 生态系统中的一个项目,旨在作为微服务架构中的 API 网关,其主要作用是根据预先制定的规则将请求路由到相应的微服务。网关提供安全(认证和授权)、监控和熔断(Circuit Breakers)等功能。通过处理请求并将其导向适当的后端服务,它有效地管理了诸如安全性和流量管理等横切关注点。 在微服务等分布式系统中,异常可能来自多个方面,如网络问题、服务不可用、下游服务错误和应用级错误,这些都是常见的罪魁祸首。在这种环境下,以本地化方式(即在每个服务内)处理异常可能会导致零散和不一致的错误处理。这种不一致性会使调试工作变得繁琐,并降低用户体验: 全局异常处理通过提供集中的异常管理机制,确保所有异常(无论其来源如何)都能得到一致的处理,并提供标准化的错误响应,从而应对这一挑战。 这种一致性对于系统恢复能力、简化错误跟踪和分析至关重要。它还能提供精确一致的错误格式,帮助用户了解出错的原因,从而提升用户体验。 3、在 Spring Cloud Gateway 中实现全局异常处理 在 Spring Cloud Gateway 中实现全局异常处理涉及几个关键步骤,每个步骤都能确保建立一个强大而高效的异常管理系统。 3.1、创建自定义全局异常处理器 全局异常处理器对于捕获和处理网关中发生的异常至关重要。为此,需要继承 AbstractErrorWebExceptionHandler 并将其添加到 Spring Context 中。这样,就创建了一个能拦截所有异常的集中式处理器。 @Component public class CustomGlobalExceptionHandler extends AbstractErrorWebExceptionHandler { // 构造函数和其他方法 } 该类应能处理各种类型的异常,从 NullPointerException 等一般异常到 HttpClientErrorException 等更具体的异常。目标是涵盖各种可能的错误。该类的核心方法如下所示。 @Override protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) { return RouterFunctions.

自定义 Spring Cloud Gateway 过滤器(Filter)

1、概览 上一篇文章《Spring Cloud Gateway 教程》中介绍了 Spring Cloud Gateway 网关框架。本文将带你了解如何在 Spring Cloud Gateway 中自定义 Filter。以及如何在 Filter 中修改请求和响应数据。 2、项目设置 创建一个基本应用,并将其用作 API 网关。 2.1、Maven 配置 在使用 Spring Cloud 时,往往通过 <dependencyManagement> 来管理组件的版本: <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.SR4</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> 添加 Spring Cloud Gateway,无需指定使用的实际版本: <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> 最新的 Spring Cloud 版本可通过 Maven Central 中找到。当然,需要注意使用的 Spring Cloud 版本需要与 Spring Boot 版本兼容。 2.2、API 网关配置 假设 API 服务在本地 8081 端口运行,在 /resource 端点暴露了一个简单的字符串资源。 接下来,配置网关,把请求代理到该服务。简而言之,当请求网关的 URI 路径中带有 /service 前缀的请求时,网关将把请求转发给该服务。

Spring Cloud Gateway 教程

1、概览 本文将带你了解 Spring Cloud Gateway 的主要功能,它是一个基于 Spring Boot 和 Project Reactor 的网关。 Spring Cloud Gateway 提供开箱即用的路由机制,通常用于微服务应用中,把多个服务隐藏在 “Facade”(门面设计模式)后面。 2、路由处理器 Spring Cloud Gateway 专注于路由请求,它将请求转发给网关 Handler Mapping,由其决定如何处理与特定路由相匹配的请求。 从一个快速示例开始,看看 Gateway Handler 如何使用 RouteLocator 解析路由配置: @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { return builder.routes() .route("r1", r -> r.host("**.baeldung.com") .and() .path("/baeldung") .uri("http://baeldung.com")) .route(r -> r.host("**.baeldung.com") .and() .path("/myOtherRouting") .filters(f -> f.prefixPath("/myPrefix")) .uri("http://othersite.com") .id("myOtherID")) .build(); } 注意,有几个核心的 API: Route - 网关的主要 API。它由给定的标识(ID)、目的地(URI)和一组 Predicate 和 Filter 定义 Predicate - Java 8 Predicate ,用于使用 Header、方法或参数匹配 HTTP 请求 Filter - 标准的 Spring WebFilter 3、动态路由 与 Zuul 一样,Spring Cloud Gateway 也提供了将请求路由到不同服务的方法。

Spring Cloud Gateway 和 Oauth2

1、概览 Spring Cloud Gateway 是一个响应式的轻量级网关,是 Spring Cloud 体系中一个比较重要的组件。本文将带你了解如何在其基础上快速实现 OAuth 2.0 认证、授权。 2、OAuth 2.0 快速回顾 OAuth 2.0 标准是一个成熟的标准,在互联网上广泛使用,是用户和应用安全访问资源的一种安全机制。 其中涉及的关键术语如下: Resource(资源):只有经过授权的客户端才能检索的任何类型的信息。 Client(客户端):消费资源的应用,通常通过 REST API 消费资源。 Resource Server(资源服务器):负责向授权客户端提供资源的服务。 Resource Owner(资源所有者):实体(人或应用),拥有资源,并最终负责向客户端授予对该资源的访问权限。 Token(令牌):客户端获取的一段信息,并作为请求的一部分发送给资源服务器以进行身份验证。 Identity Provider(身份提供商,即 IDP):验证用户凭证并向客户端发放 Access Token。 Authentication Flow(认证模式/流程):客户端获得有效 Token 必须经过的一系列步骤。 你可以通过 Auth0 的相关文档了解更多详细内容。 3、OAuth 2.0 模式 Spring Cloud Gateway 主要用于以下用途之一: OAuth Client(客户端) OAuth Resource Server(资源服务器) 我们来逐个了解。 3.1、Spring Cloud Gateway 作为 OAuth 2.0 客户端 在这种情况下,任何未经身份认证的传入请求都将触发授权码流程。一旦网关获取到 Token,它将在向后端服务发起请求时使用该 Token。 在实际应用中,一个很好的例子是聚合了 “社交应用” 的应用:对于每个支持的社交应用,网关将充当 OAuth 2.0 客户端。 因此,前端(通常是使用 Angular、React 或类似 UI 框架构建的 SPA 应用)可以代表终端户无缝访问这些应用上的数据。更重要的是:用户无需暴露自己的凭证。

Spring Cloud Gateway 重写 URL

1、简介 Spring Cloud Gateway 的常见用例是作为一个网关,代理一个或多个服务,从而为客户端提供更简单的消费方式。 本文将带你了解如何在将请求发送到后端之前,通过重写 URL 来自定义暴露的 API 的不同方式。 2、Spring Cloud Gateway 快速回顾 Spring Cloud Gateway 项目是在流行的 Spring Boot 2 和 Project Reactor 的基础上构建的,因此继承了其主要特性: 响应式,资源占用低 支持 Spring Cloud 生态系统的所有功能(服务发现、配置等) 使用标准 Spring 模式轻松扩展和/或定制 这里只列出它的主要概念,更多详细信息请参阅 中文文档: Route:路由,在网关中,匹配的传入请求会经历一系列的处理步骤。 Predicate:针对 ServerWebExchange 进行评估的 Java 8 Predicate。 Filters:可以检查、更改 ServerWebExchange 的 GatewayFilter 实例。网关支持全局 Filter 和按路由的 Filter。 简而言之,接收请求的处理顺序如下: 网关使用与每条路由相关的 Predicate 来查找哪条路由可以处理请求。 一旦找到路由,请求(ServerWebExchange 实例)就会通过每个配置的 Filter,直到最终发送到后端。 当后端发送回响应或出现错误(例如超时或连接重置)时,Filter 可以再次处理响应,然后再将其发送回客户端。 3、基于配置的 URL 重写 回到本文的主题,让我们看看如何定义一个路由,在将请求发送到后端之前重写传入的 URL。例如,假设输入的请求格式为 /api/v1/customer/*,后端 URL 应为 http://v1.customers/api/*。这里,使用 “*” 来表示 “在此之后的任何内容”。

在 Spring Cloud Gateway 中修改响应体

1、简介 本文将带你了解如何在 Spring Cloud Gateway 中读取、修改响应体,然后再响应给客户端。 2、Spring Cloud Gateway 快速回顾 Spring Cloud Gateway(简称 SCG)是 Spring Cloud 系列中的一个子项目,它提供了一个构建在响应式 Web 栈之上的 API 网关。关于它的更多详细信息和用法,你可以参考 官方文档。 设计 API Gateway 解决方案时经常出现的一种特殊使用场景:如何在将后端响应的 Body 发送回客户端之前对其进行处理? 下面列出了一些可能会用到这种功能的场景: 保持与现有客户端的兼容性,同时允许后台不断迭代 需要屏蔽响应中的某些敏感字段(脱敏) 实现这个需求,只需要实现一个 Filter 来处理后台响应即可。Filter 是 SCG 的核心概念。 Filter 组件创建后就可以将其应用于任何已声明的路由(Route)。 3、实现数据过滤 Filter 创建一个简单的 Filter 来屏蔽 JSON 响应中的某些值。 例如,给定的 JSON 有一个名为 “ssn” 的字段: { "name" : "John Doe", "ssn" : "123-45-9999", "account" : "9999888877770000" } 我们希望用一个固定的值进行替换,从而防止数据泄漏: { "name" : "John Doe", "ssn" : "****", "account" : "9999888877770000" } 3.

Spring Cloud 2023 新特性:支持同步网关

网关不支持传统 Servlet 容器 Spring Cloud Gateway 需要运行在提供的 Netty 运行时。它不能在传统的 Servlet 容器中工作,也不能在构建为 WAR 时工作。WebFlux 使用了异步非阻塞的编程模型,相较于传统的 MVC Servlet 需要理解和适应新的编程范式和响应式编程概念,因此学习曲线可能较陡峭。 如果在 spring-cloud-gateway 引入了 tomcat 等传统容器会抛出如下异常: 14 Caused by: org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat 15 at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:124) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE] 16 at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.<init>(TomcatWebServer.java:86) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE] 17 at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getTomcatWebServer(TomcatServletWebServerFactory.java:414) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE] 18 at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getWebServer(TomcatServletWebServerFactory.java:178) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE] 19 at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:179) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE] 20 at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:152) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE] 21 ... 8 common frames omitted MVC Servlet 支持 在 SpringCloud 2023 版本(Spring Cloud Gateway 4.

Spring Cloud Gateway 根据客户端 IP 限制请求速率

1、简介 在本教程中,我们将学习如何在 Spring Cloud Gateway 中根据客户端的实际 IP 地址来限制请求速率。 简而言之,我们将在路由上设置 RequestRateLimiter Filter,然后配置网关根据 IP 地址来限制客户端的请求。 2、路由配置 首先,我们需要配置 Spring Cloud Gateway 以对特定路由进行速率限制。为此,我们将使用由 spring-boot-starter-data-redis-reactive 实现的经典 令牌桶(Token Bucket) Rate Limiter。简而言之, Rate Limiter 创建一个带有唯一 Key 的 Bucket,该 Key 用于标识 Bucket 自身,并具有固定的初始 Token 容量,随时间自动生成 Token。然后,对于每个请求,Rate Limiter 会获取其关联的 Bucket,并试图减少其 Bucket 中的一个 Token。如果 Bucket 中的 Token 数量不足,将拒绝传入的请求。 在分布式系统中,我们希望所有系统对同一客户端的请求都采用相同的限速策略。所以,我们使用分布式缓存 Redis 来存储 Bucket。在本例中,我们预先配置了一个 Redis 实例。 接下来,配置一个带有 Rate Limiter 的路由。监听 /example 端点,并将请求转发至 http://example.org: @Bean public RouteLocator myRoutes(RouteLocatorBuilder builder) { return builder.routes() .route("requestratelimiter_route", p -> p .