SpringBoot实现基于URL和IP的访问频率限制

2025-01-08 15:50

本文主要是介绍SpringBoot实现基于URL和IP的访问频率限制,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《SpringBoot实现基于URL和IP的访问频率限制》在现代Web应用中,接口被恶意刷新或暴力请求是一种常见的攻击手段,为了保护系统资源,需要对接口的访问频率进行限制,下面我们就来看看如何使用...

1. 引言

在现代 Web 应用中,接口被恶意刷新或暴力请求是一种常见的攻击手段。为了保护系统资源,防止服务器过载或服务不可用,需要对接口的访问频率进行限制。本文将介绍如何使用 Spring Boot 实现基于 URL 和 IP 的访问频率限制,具体步骤包括:

使用拦截器拦截请求:在每个请求到达控制器之前进行拦截。

China编程

使用 Redis 存储访问记录:利用 Redis 的高性能特性来存储每个 IP 对每个 URL 的访问次数。

检测访问频率:判断 IP 在一定时间内对特定 URL 的访问次数是否超过限制。

禁用恶意 IP:如果超过限制,则将 IP 列入黑名单,禁止其后续访问。

2. 项目依赖

首先,在 pom.XML 中添加必要的依赖,包括 Spring Boot Web、Spring Boot Starter Data Redis 和 Lombok(用于简化代码)。

<!-- Spring Boot Starter Data Redis -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>3.4.1</version>
</dependency>

<!-- Lombok (可选,用于简化代码) -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

3. 配置 Redis

在 applicationChina编程.properties 中配置 Redis 连接信息:

server.port=8080
# Redis 配置
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.database=0
# 可选:设置密码
# spring.redis.password=yourpassword

或在 application.yml 中配置Redis连接信息:

server:
  port: 8080

spring:
  application:
    name: urlInterceptorDemo

  data:
    # redis 配置
    redis:
      www.chinasem.cn# 地址
      host: 127.0.0.1
      # 端口,默认为6379
      port: 6379
      # 数据库索引
      database: 0
      # 密码
      password: "123456"
      # 连接超时时间
      timeout: 10s

4. 创建拦截器

创建一个拦截器 RateLimitInterceptor,用于拦截每个请求并执行访问频率限制逻辑。

package com.yyqq.urlinterceptordemo.Interceptor;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import Java.util.concurrent.TimeUnit;

@Component
public class RateLimitInterceptor implements HandlerInterceptor {

    @Autowired
    public RedisTemplate redisTemplate;

    // 访问频率限制:每个 IP 每个 URL 最多访问 100 次 / 分钟
    private static final int MAX_REQUESTS = 10;
    private static final int TIME_WINDOW = 60; // 秒

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String ip = getClientIP(request);
        String url = request.getRequestURI();

        String key = "rate_limit:"http://www.chinasem.cn + url + ":" + ip;
        long count = redisTemplate.opsForValue().increment(key, 1);
        if (count == 1) {
            // 设置键的过期时间为 TIME_WINDOW 秒
            redisTemplate.expire(key, TIME_WINDOW, TimeUnit.SECONDS);
        }

        if (count > MAX_REQUESTS) {
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            response.setContentType("text/html;charset=UTF-8");
            response.getWriter().write("请求过于频繁,请稍后再试。");
            return false;
        }

        return true;
    }

    private String getClientIP(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCasChina编程e(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }
}

代码说明

RedisTemplate:用于与 Redis 进行交互。

MAX_REQUESTS 和 TIME_WINDOW:定义每个 IP 在每个 URL 上的最大访问次数和时间窗口(60 秒)。

preHandle 方法:

获取客户端 IP 和请求的 URL。

构建 Redis 键,例如 rate_limit:/api/data:192.168.1.1。

使用 increment 方法对键进行递增,并设置过期时间。

如果访问次数超过 MAX_REQUESTS,则返回 403 状态码,并返回错误信息。

getClientIP 方法:获取客户端的真实 IP,处理代理和负载均衡的情况。

5. 注册拦截器

创建一个配置类 WebConfig,将拦截器注册到 Spring MVC 中。

package com.yyqq.urlinterceptordemo.config;


import com.yyqq.urlinterceptordemo.Interceptor.RateLimitInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.*;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private RateLimitInterceptor rateLimitInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(rateLimitInterceptor)
                .addPathPatterns("/**") // 拦截所有路径
                .excludePathPatterns("/error"); // 排除错误路径
    }
}

代码说明

  • addInterceptors 方法:将自定义的拦截器添加到拦截器链中,并指定拦截的路径模式。
  • addPathPatterns("/")**:拦截所有路径。
  • excludePathPatterns(“/error”):排除错误路径,避免拦截器影响错误处理。

6. 创建控制器

创建一个简单的控制器 DemoController,包含一个示例接口用于测试。

package com.yyqq.urlinterceptordemo.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/test")
public class DemoController {

    @GetMapping("/getData")
    public String getData() {
        return "这是数据接口,现在访问正常!";
    }
}

8. 测试

启动 Spring Boot 应用后,可以进行以下测试:

1.正常访问:

访问 http://localhost:8080/test/getData,应返回 “这是数据接口,现在访问正常!”。

多次快速刷新,访问次数达到 10 次后,应返回 “请求过于频繁,请稍后再试。”,并返回 403 状态码。

SpringBoot实现基于URL和IP的访问频率限制

2.禁用 IP:

在达到限制后,等待一段时间(60 秒),再次访问应恢复正常。

SpringBoot实现基于URL和IP的访问频率限制

9. 总结

通过结合使用 Spring Boot 拦截器和 Redis,本文实现了一种基于 URL 和 IP 的访问频率限制机制。这种机制能够有效地防止接口被恶意刷新和暴力请求,保护系统资源,提高应用的安全性和稳定性。在实际应用中,可以根据具体需求调整访问频率限制的参数,如最大访问次数和时间窗口。此外,还可以结合其他安全措施,如 IP 黑名单、验证码等,进一步增强系统的防护能力。

到此这篇关于SpringBoot实现基于URL和IP的访问频率限制的文章就介绍到这了,更多相关SpringBoot访问频率限制内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程China编程(www.chinasem.cn)!

这篇关于SpringBoot实现基于URL和IP的访问频率限制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1152978

相关文章

Spring Security常见问题及解决方案

《SpringSecurity常见问题及解决方案》SpringSecurity是Spring生态的安全框架,提供认证、授权及攻击防护,支持JWT、OAuth2集成,适用于保护Spring应用,需配置... 目录Spring Security 简介Spring Security 核心概念1. ​Securit

Python实现终端清屏的几种方式详解

《Python实现终端清屏的几种方式详解》在使用Python进行终端交互式编程时,我们经常需要清空当前终端屏幕的内容,本文为大家整理了几种常见的实现方法,有需要的小伙伴可以参考下... 目录方法一:使用 `os` 模块调用系统命令方法二:使用 `subprocess` 模块执行命令方法三:打印多个换行符模拟

SpringBoot+EasyPOI轻松实现Excel和Word导出PDF

《SpringBoot+EasyPOI轻松实现Excel和Word导出PDF》在企业级开发中,将Excel和Word文档导出为PDF是常见需求,本文将结合​​EasyPOI和​​Aspose系列工具实... 目录一、环境准备与依赖配置1.1 方案选型1.2 依赖配置(商业库方案)二、Excel 导出 PDF

Python实现MQTT通信的示例代码

《Python实现MQTT通信的示例代码》本文主要介绍了Python实现MQTT通信的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 安装paho-mqtt库‌2. 搭建MQTT代理服务器(Broker)‌‌3. pytho

SpringBoot改造MCP服务器的详细说明(StreamableHTTP 类型)

《SpringBoot改造MCP服务器的详细说明(StreamableHTTP类型)》本文介绍了SpringBoot如何实现MCPStreamableHTTP服务器,并且使用CherryStudio... 目录SpringBoot改造MCP服务器(StreamableHTTP)1 项目说明2 使用说明2.1

spring中的@MapperScan注解属性解析

《spring中的@MapperScan注解属性解析》@MapperScan是Spring集成MyBatis时自动扫描Mapper接口的注解,简化配置并支持多数据源,通过属性控制扫描路径和过滤条件,利... 目录一、核心功能与作用二、注解属性解析三、底层实现原理四、使用场景与最佳实践五、注意事项与常见问题六

Spring的RedisTemplate的json反序列泛型丢失问题解决

《Spring的RedisTemplate的json反序列泛型丢失问题解决》本文主要介绍了SpringRedisTemplate中使用JSON序列化时泛型信息丢失的问题及其提出三种解决方案,可以根据性... 目录背景解决方案方案一方案二方案三总结背景在使用RedisTemplate操作redis时我们针对

Java中Arrays类和Collections类常用方法示例详解

《Java中Arrays类和Collections类常用方法示例详解》本文总结了Java中Arrays和Collections类的常用方法,涵盖数组填充、排序、搜索、复制、列表转换等操作,帮助开发者高... 目录Arrays.fill()相关用法Arrays.toString()Arrays.sort()A

Spring Boot Maven 插件如何构建可执行 JAR 的核心配置

《SpringBootMaven插件如何构建可执行JAR的核心配置》SpringBoot核心Maven插件,用于生成可执行JAR/WAR,内置服务器简化部署,支持热部署、多环境配置及依赖管理... 目录前言一、插件的核心功能与目标1.1 插件的定位1.2 插件的 Goals(目标)1.3 插件定位1.4 核

如何使用Lombok进行spring 注入

《如何使用Lombok进行spring注入》本文介绍如何用Lombok简化Spring注入,推荐优先使用setter注入,通过注解自动生成getter/setter及构造器,减少冗余代码,提升开发效... Lombok为了开发环境简化代码,好处不用多说。spring 注入方式为2种,构造器注入和setter