一个Starter搞定六种防护,Spring Boot API的超强护盾来了

15 阅读10分钟

一个Starter搞定六种防护,Spring Boot API的超强护盾来了

开篇引入

在当今微服务架构盛行的时代,Spring Boot 凭借其快速开发、便捷部署等特性,成为了众多开发者构建应用的首选框架。随着业务的不断发展和用户量的增长,API 作为应用对外提供服务的重要接口,面临着各种各样的挑战。从用户频繁操作导致的重复提交,到恶意攻击引发的流量洪峰,再到接口响应缓慢影响用户体验,这些问题都亟待解决。今天,就给大家介绍一款强大的六合一 Spring Boot API 防护框架,只需一个 Starter,就能一站式搞定防重、限流、幂等、自动 Trim、慢接口检测、链路追踪这些关键功能 ,为你的 API 保驾护航。

主角登场:六合一防护框架

这款强大的框架名为 Guardian,它是一个轻量级的 Spring Boot 接口防护框架,目前已在 Maven Central 开源 。它的出现,就像是为 Spring Boot 应用打造了一个全能保镖,全方位守护 API 的安全与稳定。无论是小型项目还是大型企业级应用,Guardian 都能轻松适配,为你的开发工作提供高效、便捷的防护方案。如果你也想为自己的 Spring Boot 项目增添一层坚实的防护,不妨前往项目地址一探究竟。项目的所有源码、示例以及详细文档都在其中,GitHub 地址为:github.com/BigGG-Guard… ,Gitee 镜像同步地址为:gitee.com/BigGG-Guard… ,大家顺手点个 Star,后续使用不迷路。

功能大揭秘

(一)防重复提交

在日常开发中,我们经常会遇到用户重复提交表单或请求的情况。比如在电商系统里,用户下单时,由于网络延迟,用户没有及时看到提交结果,就可能会多次点击提交按钮 。这时,如果后端没有相应的防重机制,就可能会创建多个重复订单,给用户和商家都带来困扰。

使用 Guardian 的防重复提交功能非常简单。首先,引入guardian-repeat-submit-spring-boot-starter依赖:


<dependency>
    <groupId>io.github.biggg-guardian</groupId>
    <artifactId>guardian-repeat-submit-spring-boot-starter</artifactId>
    <version>1.5.0</version>
</dependency>

然后,在需要防重的接口方法上添加@RepeatSubmit注解:


@PostMapping("/submit")
@RepeatSubmit(interval = 10, message = "订单正在处理,请勿重复提交")
public Result submitOrder(@RequestBody OrderDTO order) {
    return orderService.submit(order);
}

上述代码中,interval表示防重的时间间隔,单位为秒;message则是重复提交时返回给用户的提示信息。这样,10 秒内同一个用户、同一个接口、同样的请求参数,第二次请求就会被直接拦截。

如果有多个接口都需要配置防重,一个个加注解会比较繁琐,此时可以在 YAML 文件里用 AntPath 通配符进行批量配置:


guardian:
  repeat-submit:
    storage: redis
    key-encrypt: md5
    urls:
      - pattern: /api/order/**
        interval: 10
        key-scope: user
        message: "订单正在处理,请勿重复提交"
      - pattern: /api/sms/send
        interval: 60
        key-scope: ip
    exclude-urls:
      - /api/public/**
      - /api/health

这里的key-scope控制防重维度,可选user(按用户)、ip(按 IP)、global(全局)。YAML 规则的优先级高于注解,白名单exclude-urls优先级最高,命中直接放行。

Guardian 在设计上还有很多贴心的细节。比如在生成防重 Key 时,会把请求参数也计算进去。对于 POST 请求,框架内置的RepeatableRequestFilter会自动缓存请求体,将请求参数做 JSON 序列化 + Base64 编码拼进 Key 。对于未登录用户,框架采用已登录用userId → 没登录用sessionId → 没 session 用客户端 IP 的三级降级策略,保证不会出现null。此外,拦截器在afterCompletion里做了处理,若请求抛异常,自动释放锁,正常完成的请求才让锁自然过期。通过开启log-enabled: true,可以记录拦截日志,前缀为[Guardian-Repeat-Submit],还能通过 Actuator 端点GET /actuator/guardianRepeatSubmit获取防重统计信息。

(二)接口限流

随着业务的发展,系统可能会面临高并发的挑战。当大量请求同时涌入时,如果没有限流措施,系统很容易因为资源耗尽而崩溃。比如在秒杀活动中,大量用户同时请求下单接口,可能会导致服务器负载过高,甚至宕机。

Guardian 的接口限流功能支持滑动窗口和令牌桶双算法,能灵活应对各种场景。滑动窗口算法通过统计一段时间内的请求数量来判断是否超过限流阈值,它可以有效应对突发流量,并且能够精确控制单位时间内的请求数量 。令牌桶算法则是按照固定速率生成令牌,请求到达时需要获取令牌才能继续处理,如果桶中没有令牌,则请求被拒绝。这种算法允许一定程度的突发流量,因为桶中可以积累一定数量的令牌。

使用时,先引入guardian-rate-limit-spring-boot-starter依赖:


<dependency>
    <groupId>io.github.biggg-guardian</groupId>
    <artifactId>guardian-rate-limit-spring-boot-starter</artifactId>
    <version>1.5.0</version>
</dependency>

接着,在需要限流的接口上添加@RateLimit注解:


@GetMapping("/list")
@RateLimit(value = 10, timeUnit = TimeUnit.SECONDS, algorithm = RateLimitAlgorithm.SLIDING_WINDOW)
public Result listGoods() {
    return goodsService.listGoods();
}

value表示时间窗口内允许的最大请求数,timeUnit是时间单位,algorithm指定限流算法,这里选择了滑动窗口算法,也可以根据实际需求切换为令牌桶算法。

(三)接口幂等

在分布式系统中,由于网络波动、重试机制等原因,同一个请求可能会被多次执行。对于一些对数据一致性要求较高的操作,如支付接口,如果不保证幂等性,可能会导致用户重复扣费。

Guardian 通过 Token 机制来保证接口幂等性。在请求处理前,先获取一个 Token,这个 Token 可以是从请求头、参数或者其他地方获取。然后,将 Token 存入缓存(如 Redis)。当相同的请求再次到来时,先检查缓存中是否存在该 Token,如果存在,则说明该请求已经被处理过,直接返回之前的处理结果,不再重复执行实际的业务逻辑 。此外,Guardian 还支持结果缓存,对于一些耗时较长且结果不经常变化的接口,可以将结果缓存起来,后续相同请求直接返回缓存结果,提高响应速度。

使用接口幂等功能,只需引入guardian-idempotent-spring-boot-starter依赖:


<dependency>
    <groupId>io.github.biggg-guardian</groupId>
    <artifactId>guardian-idempotent-spring-boot-starter</artifactId>
    <version>1.5.0</version>
</dependency>

然后在接口方法上添加@Idempotent注解:


@PostMapping("/pay")
@Idempotent
public Result pay(@RequestBody PayDTO payDTO) {
    return payService.pay(payDTO);
}

(四)参数自动 Trim

在接收用户输入时,我们经常会遇到参数前后带有空格或不可见字符的情况。这些多余的字符可能会影响业务逻辑的正常处理,比如在用户登录时,用户名前后的空格可能导致用户名匹配失败。

Guardian 的参数自动 Trim 功能可以自动去除请求参数首尾的空格,并将不可见字符替换为可见字符。它会在请求到达 Controller 之前,对所有请求参数进行处理,确保参数的纯净。

使用该功能,只需要引入guardian-auto-trim-spring-boot-starter依赖,无需额外配置或注解,框架会自动生效:


<dependency>
    <groupId>io.github.biggg-guardian</groupId>
    <artifactId>guardian-auto-trim-spring-boot-starter</artifactId>
    <version>1.5.0</version>
</dependency>

(五)慢接口检测

在系统运行过程中,慢接口会严重影响用户体验,甚至导致整个系统性能下降。比如一个订单查询接口,如果响应时间过长,用户就会失去耐心,从而降低对系统的满意度。

Guardian 的慢接口检测功能可以帮助我们及时发现这些问题接口。它会自动统计接口的响应时间,当接口响应时间超过设定的阈值时,会触发告警通知,让我们能够及时排查问题。同时,它还支持 Top N 统计,方便我们快速定位响应最慢的几个接口 。通过 Actuator 端点,我们可以方便地查看慢接口的统计信息,了解系统的性能状况。

使用慢接口检测功能,先引入guardian-slow-api-spring-boot-starter依赖:


<dependency>
    <groupId>io.github.biggg-guardian</groupId>
    <artifactId>guardian-slow-api-spring-boot-starter</artifactId>
    <version>1.5.0</version>
</dependency>

然后在需要检测的接口上添加@SlowApiThreshold注解:


@GetMapping("/order/{id}")
@SlowApiThreshold(value = 500, timeUnit = TimeUnit.MILLISECONDS)
public Result getOrder(@PathVariable Long id) {
    return orderService.getOrder(id);
}

这里表示当该接口响应时间超过 500 毫秒时,就会被认定为慢接口。

(六)请求链路追踪

在分布式系统中,一个请求可能会经过多个服务节点,涉及多个接口调用。当出现问题时,很难快速定位到问题所在。比如一个用户请求出现错误,但我们不知道是哪个服务节点、哪个接口出了问题,排查起来非常困难。

Guardian 的请求链路追踪功能可以自动生成 TraceId,并在整个请求链路中进行透传。每个请求都有唯一的 TraceId,通过这个 TraceId,我们可以串联起该请求在各个服务节点的调用日志,清晰地看到请求的处理流程 。结合 MDC(Mapped Diagnostic Context)日志,我们可以在日志中方便地记录和查询 TraceId,大大提高了问题排查的效率。

使用请求链路追踪功能,只需引入guardian-trace-spring-boot-starter依赖,框架会自动配置好相关的过滤器和 MDC:


<dependency>
    <groupId>io.github.biggg-guardian</groupId>
    <artifactId>guardian-trace-spring-boot-starter</artifactId>
    <version>1.5.0</version>
</dependency>

引入依赖后,在日志配置中添加对 TraceId 的记录,就可以在日志中看到每个请求的 TraceId,方便后续的问题排查。

使用案例展示

为了让大家更直观地感受到 Guardian 框架的强大威力,下面给大家分享一个实际项目中的使用案例。这是一个电商平台,在业务快速发展的过程中,面临着诸多 API 相关的问题。用户在下单、支付等操作时,经常出现重复提交的情况,导致订单数据混乱 ;在促销活动期间,高并发的请求使得系统频繁出现卡顿甚至崩溃,接口响应时间大幅延长,严重影响了用户体验;此外,由于分布式系统的复杂性,当出现问题时,很难快速定位到问题的根源。

在引入 Guardian 框架后,这些问题得到了有效解决。通过防重复提交功能,避免了用户重复下单,保证了订单数据的准确性;接口限流功能成功应对了高并发场景,确保系统在大流量下依然稳定运行;接口幂等性保证了支付等关键操作的一致性,避免了用户重复扣费;参数自动 Trim 功能使得接收的用户参数更加规范,减少了因参数问题导致的业务错误;慢接口检测功能及时发现并优化了响应缓慢的接口,提升了整体的系统性能;请求链路追踪功能则在出现问题时,能够快速定位到问题所在,大大缩短了问题排查的时间 。

使用 Guardian 框架后,电商平台的订单重复提交率从原来的 5% 降低到了几乎为 0,接口响应时间平均缩短了 30%,系统的稳定性和用户满意度得到了显著提升。