前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >最火的Spring Cloud Gateway 为经过身份验证的用户启用速率限制实践-spring cloud 入门教程

最火的Spring Cloud Gateway 为经过身份验证的用户启用速率限制实践-spring cloud 入门教程

作者头像
jack.yang
发布于 2025-04-05 11:10:45
发布于 2025-04-05 11:10:45
12600
代码可运行
举报
运行总次数:0
代码可运行

在本文中,您将学习如何使用 Spring Cloud Gateway 为经过身份验证的用户启用速率限制。为什么重要?API 网关是您的微服务系统的入口点。因此,您应该提供适当的安全级别。速率限制可以防止您的 API 遭受 DoS 攻击并限制网络抓取。

您可以使用 Spring Cloud Gateway 轻松配置速率限制。这个特性的基本介绍可以参考我的文章基于Redis做Spring Cloud Gateway 中的速率限制实践-spring cloud 入门教程。同样,今天我们也将使用 Redis 作为速率限制器的后端。此外,我们将配置 HTTP 基本身份验证。当然,您可以提供一些更高级的身份验证机制,例如 X509 证书或 OAuth2 登录。如果您考虑一下,请阅读我的文章Spring Cloud Gateway OAuth2 with Keycloak。

1. 依赖

让我们从依赖开始。由于我们将创建一个集成测试,我们需要一些额外的库。首先,我们将使用 Testcontainers 库。它允许我们在 JUnit 测试期间运行 Docker 容器。我们将使用它来运行 Redis 和一个模拟服务器,它负责模拟下游服务。当然,我们需要包含一个带有 Spring Cloud Gateway 和 Spring Data Redis 的 starter。要实现 HTTP 基本身份验证,我们还需要包含 Spring Security。这是 Maven 中所需依赖项的完整列表pom.xml

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
</dependency>
<dependency>
   <groupId>org.testcontainers</groupId>
   <artifactId>mockserver</artifactId>
   <scope>test</scope>
</dependency>
<dependency>
   <groupId>org.mock-server</groupId>
   <artifactId>mockserver-client-java</artifactId>
   <scope>test</scope>
</dependency>

2. 配置 HTTP 基本身份验证

为了配置 HTTP 基本身份验证,我们需要创建@Configuration带有@EnableWebFluxSecurity. 这是因为 Spring Cloud Gateway 建立在 Spring WebFlux 和 Netty 之上。此外,我们将创建一组测试用户MapReactiveUserDetailsService

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {

   @Bean
   public SecurityWebFilterChain filterChain(ServerHttpSecurity http) {
      http.authorizeExchange(exchanges -> 
         exchanges.anyExchange().authenticated())
            .httpBasic();
      http.csrf().disable();
      return http.build();
   }

   @Bean
   public MapReactiveUserDetailsService users() {
      UserDetails user1 = User.builder()
            .username("user1")
            .password("{noop}1234")
            .roles("USER")
            .build();
      UserDetails user2 = User.builder()
            .username("user2")
            .password("{noop}1234")
            .roles("USER")
            .build();
      UserDetails user3 = User.builder()
            .username("user3")
            .password("{noop}1234")
            .roles("USER")
            .build();
      return new MapReactiveUserDetailsService(user1, user2, user3);
   }
}

3.配置Spring Cloud Gateway Rate Limiter key

需要使用名为 的组件启用请求速率限制器功能GatewayFilter。此过滤器采用可选 keyResolver 参数。该 KeyResolver 接口允许您创建可插拔策略,派生出限制请求的密钥。在我们的例子中,它将是一个用户登录。一旦用户成功通过身份验证,其登录信息就会存储在 Spring 中SecurityContext。为了检索响应式应用程序的上下文,我们应该使用ReactiveSecurityContextHolder.

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Bean
KeyResolver authUserKeyResolver() {
   return exchange -> ReactiveSecurityContextHolder.getContext()
           .map(ctx -> ctx.getAuthentication()
              .getPrincipal().toString());
}

4. 测试场景

在测试场景中,我们将模拟传入流量。每个请求都需要有一个Authorization包含用户凭据的标头。单个用户每分钟可以发送 4 个请求。超过该限制后,Spring Cloud Gateway 将返回 HTTP 代码HTTP 429 - Too Many Requests。流量被寻址到下游服务。因此,我们使用 Testcontainers 运行模拟服务器。

5. 测试 Spring Cloud Gateway 安全限速器

最后,我们可以进行测试实现。我将使用 JUnit4,因为我之前在示例存储库中的其他示例中使用过它。我们有三个用于速率限制器配置的参数:replenishRateburstCapacityrequestedTokens。由于我们还允许每秒少于 1 个请求,因此我们需要为burstCapacity和设置正确的值requestedTokens。简而言之,该requestedTokens属性设置请求花费多少令牌。另一方面,burstCapacity属性是允许用户的最大请求数(或成本)。

在测试过程中,我们在user1user2和之间随机设置用户名user3。测试重复 20 次。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@SpringBootTest(webEnvironment = 
   SpringBootTest.WebEnvironment.DEFINED_PORT,
                properties = {"rateLimiter.secure=true"})
@RunWith(SpringRunner.class)
public class GatewaySecureRateLimiterTest {

   private static final Logger LOGGER = 
      LoggerFactory.getLogger(GatewaySecureRateLimiterTest.class);
   private Random random = new Random();

   @Rule
   public TestRule benchmarkRun = new BenchmarkRule();

   @ClassRule
   public static MockServerContainer mockServer = 
      new MockServerContainer();
   @ClassRule
   public static GenericContainer redis = 
      new GenericContainer("redis:5.0.6").withExposedPorts(6379);

   @Autowired
   TestRestTemplate template;

   @BeforeClass
   public static void init() {
      System.setProperty("spring.cloud.gateway.routes[0].id", "account-service");
      System.setProperty("spring.cloud.gateway.routes[0].uri", "http://" + mockServer.getHost() + ":" + mockServer.getServerPort());
      System.setProperty("spring.cloud.gateway.routes[0].predicates[0]", "Path=/account/**");
      System.setProperty("spring.cloud.gateway.routes[0].filters[0]", "RewritePath=/account/(?<path>.*), /$\\{path}");
      System.setProperty("spring.cloud.gateway.routes[0].filters[1].name", "RequestRateLimiter");
      System.setProperty("spring.cloud.gateway.routes[0].filters[1].args.redis-rate-limiter.replenishRate", "1");
      System.setProperty("spring.cloud.gateway.routes[0].filters[1].args.redis-rate-limiter.burstCapacity", "60");
      System.setProperty("spring.cloud.gateway.routes[0].filters[1].args.redis-rate-limiter.requestedTokens", "15");
      System.setProperty("spring.redis.host", redis.getHost());
      System.setProperty("spring.redis.port", "" + redis.getMappedPort(6379));
      new MockServerClient(mockServer.getContainerIpAddress(), mockServer.getServerPort())
            .when(HttpRequest.request()
                    .withPath("/1"))
            .respond(response()
                    .withBody("{\"id\":1,\"number\":\"1234567890\"}")
                    .withHeader("Content-Type", "application/json"));
   }

   @Test
   @BenchmarkOptions(warmupRounds = 0, concurrency = 1, benchmarkRounds = 20)
   public void testAccountService() {
      String username = "user" + (random.nextInt(3) + 1);
      HttpHeaders headers = createHttpHeaders(username,"1234");
      HttpEntity<String> entity = new HttpEntity<String>(headers);
      ResponseEntity<Account> r = template
         .exchange("/account/{id}", HttpMethod.GET, entity, Account.class, 1);
      LOGGER.info("Received({}): status->{}, payload->{}, remaining->{}",
            username, r.getStatusCodeValue(), r.getBody(), r.getHeaders().get("X-RateLimit-Remaining"));
    }

   private HttpHeaders createHttpHeaders(String user, String password) {
      String notEncoded = user + ":" + password;
      String encodedAuth = Base64.getEncoder().encodeToString(notEncoded.getBytes());
      HttpHeaders headers = new HttpHeaders();
      headers.setContentType(MediaType.APPLICATION_JSON);
      headers.add("Authorization", "Basic " + encodedAuth);
      return headers;
   }

}

让我们运行测试。感谢junit-benchmarks库,我们可以配置测试的轮数。每次我记录来自网关的响应时,包括用户名、HTTP 状态、有效负载和X-RateLimit-Remaining显示剩余令牌数量的标头。 结果如下。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-08-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
基于Redis做Spring Cloud Gateway 中的速率限制实践-spring cloud 入门教程
目前Spring Cloud Gateway是仅次于 Spring Cloud Netflix 的第二大最受欢迎的 Spring Cloud 项目(就 GitHub 上的 Star 数而言)。它是作为 Spring Cloud 家族中 Zuul 代理的继任者而创建的。该项目为微服务架构提供了一个 API 网关,并建立在反应式Netty和 Project Reactor之上。它旨在提供一种简单但有效的方法来路由到 API 并解决诸如安全性、监控/指标和弹性等常见问题。 Spring Cloud Gateway 为您提供了许多功能和配置选项。今天我将专注于网关配置的一个但非常有趣的方面——速率限制。速率限制器可以定义为一种控制网络上发送或接收流量速率的方法。我们还可以定义几种类型的速率限制。Spring Cloud Gateway 目前提供了一个Request Rate Limiter,它负责将每个用户限制为每秒 N 个请求。与 Spring Cloud Gateway 一起 使用时RequestRateLimiter,我们可能会利用 Redis。Spring Cloud 实现使用令牌桶算法做限速。这个算法有一个集中的存储桶主机,你可以在每个请求上获取令牌,然后慢慢地将更多的令牌滴入桶中。如果桶为空,则拒绝请求。
jack.yang
2025/04/05
950
基于Redis做Spring Cloud Gateway 中的速率限制实践-spring cloud 入门教程
Spring Cloud Gateway 限流详解
Spring Cloud Gatway内置的 RequestRateLimiterGatewayFilterFactory 提供限流的能力,基于令牌桶算法实现。目前,它内置的 RedisRateLimiter ,依赖Redis存储限流配置,以及统计数据。当然你也可以实现自己的RateLimiter,只需实现 org.springframework.cloud.gateway.filter.ratelimit.RateLimiter 接口,或者继承 org.springframework.cloud.gateway.filter.ratelimit.AbstractRateLimiter 。
用户1516716
2019/09/19
5.4K0
spring cloud gateway 之限流篇
在高并发的系统中,往往需要在系统中做限流,一方面是为了防止大量的请求使服务器过载,导致服务不可用,另一方面是为了防止网络攻击。
方志朋
2019/06/21
1.8K0
spring cloud gateway 之限流篇
Spring Cloud Gateway 之 限流
在高并发的系统中,往往需要在系统中做限流,一方面是为了防止大量的请求使服务器过载,导致服务不可用,另一方面是为了防止网络攻击。
程序员果果
2019/05/21
1.4K0
Spring Cloud Gateway简单使用
Gateway网关是我们服务的守门神,所有微服务的统一入口。Spring Cloud Gateway 是 Spring Cloud的一个全新项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。在Gateway之前,SpringCloud并不自己开发网关,可能是觉得Netflflix公司的Zuul不行吧,然后自己就写了一个,也是替代Netflflix Zuul。其不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。
ha_lydms
2023/08/10
6280
Spring Cloud Gateway简单使用
springcloud(十三):服务网关 Spring Cloud GateWay 熔断、限流、重试
上篇文章介绍了 Gataway 和注册中心的使用,以及 Gataway 中 Filter 的基本使用,这篇文章我们将继续介绍 Filter 的一些常用功能。
DencyCheng
2019/03/19
2.8K0
SpringCloud 2.x学习笔记:16、Spring Cloud Gateway之限流(Greenwich版本)
1、令牌桶算法 2、简单例子 2.1 pom <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.or
程裕强
2019/07/02
9700
SpringCloud 2.x学习笔记:16、Spring Cloud Gateway之限流(Greenwich版本)
Spring Cloud Gateway基于内置过滤工厂实现限流
本文使用 gateway 内置的过滤工厂 -RequestRateLimiter 实现限流的。
胖虎
2019/06/26
1.2K0
Spring Cloud Gateway基于内置过滤工厂实现限流
微服务网关组件 - Spring Cloud Gateway 扩展(二十五)
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
用户1212940
2019/11/13
1.6K0
限流措施
一般而言,正常的流量越多越好,比如用户快速增长、热点事件带来的蜂拥的人流。但在实际的网络流量中,除正常的流量外,还有很多非正常的流量,比如网络攻击、恶意爬虫。所以在高并发的应用中,需要通过限流来保障服务对所有用户的可用性。限流和缓存、降级一样,也是保护高并发系统的利器。
星哥玩云
2022/09/15
7890
Spring Cloud Gateway实战案例(限流、熔断回退、跨域、统一异常处理和重试机制)
Spring Cloud Gateway 作为新一代网关,在性能上有很大提升,并且附加了诸如限流等实用的功能。
chenchenchen
2022/03/09
5K0
Spring Cloud Gateway实战案例(限流、熔断回退、跨域、统一异常处理和重试机制)
Spring Cloud Gateway限流实战
本篇概览 本文是《Spring Cloud Gateway实战》系列的第八篇,经过前面的学习,咱们对过滤器已了解得差不多,今天来补全过滤器的最后一个版块:限流(RequestRateLimiter ) 默认的限流器是基于redis实现的,限流算法是大家熟悉的令牌桶(Token Bucket Algorithm),关于令牌捅的原理就不在此展开了,聪明的您看一眼下图应该就懂了:装令牌的桶容量有限,例如最多20个,令牌进入桶的速度恒定(注意,这里是和漏桶算法的区别),例如每秒10个,底部每个请求能拿到令牌才会被处
程序员欣宸
2021/12/07
1.5K0
Spring Cloud Gateway限流实战
Spring Cloud Gateway 原生的接口限流该怎么玩
基于Spring Cloud、oAuth2.0开发基于Vue前后分离的开发平台,支持账号、短信、SSO等多种登录,提供配套视频开发教程。
冷冷
2019/05/26
9530
Spring Cloud 之 Gateway.
Zuul 基于servlet 2.5 (works with 3.x),使用阻塞API。它不支持任何长期的连接,如websocket。
JMCui
2019/07/29
1.4K0
Spring Cloud Gateway 原生支持接口限流该怎么玩
基于Spring Cloud、oAuth2.0开发基于Vue前后分离的开发平台,支持账号、短信、SSO等多种登录,提供配套视频开发教程。
冷冷
2018/07/01
1.4K0
Spring Cloud Gateway 限流操作
API网关作为所有请求的入口,请求量大,我们可以通过对并发访问的请求进行限速来保护系统的可用性。
猿天地
2018/08/06
2.3K0
Spring Cloud Gateway 限流操作
SpringCloud详细教程 | 第六篇:Gateway之路由器和过滤器、熔断、降级、限流(Greenwich版本)
Spring Cloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Netflix Zuul,其不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流
小东啊
2019/06/26
6.2K0
SpringCloud详细教程 | 第六篇:Gateway之路由器和过滤器、熔断、降级、限流(Greenwich版本)
gateway(网关)基于Filter限流
SpringCloudGateway官方就提供了基于令牌桶的限流支持。基于其内置的过滤器工厂 RequestRateLimiterGatewayFilterFactory 实现。在过滤器工厂中是通过Redis和lua脚本结合的方式进行流量控制
蚊子.
2023/08/10
3990
gateway(网关)基于Filter限流
服务网关Spring Cloud Gateway
Spring Cloud Gateway是Spring Cloud官方推出的第二代网关框架,取代Zuul网关。网关作为流量的,在微服务系统中有着非常作用,网关常见的功能有路由转发、权限校验、限流控制等作用。
chenchenchen
2022/01/05
9730
服务网关Spring Cloud Gateway
Spring Cloud Gateway 参考指南
该项目提供了一个基于Spring生态的API网关。Spring Cloud Gateway。Spring Cloud Gateway旨在提供一个种简单有效的方式去路由API,并给API提供相应关注点:如:security、monitoring/metrics和resiliency。
阿提说说
2022/12/02
4.4K0
推荐阅读
相关推荐
基于Redis做Spring Cloud Gateway 中的速率限制实践-spring cloud 入门教程
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验