当前位置: 首页 > news >正文

使用Spring Boot限制在一分钟内某个IP只能访问10次

有些时候,为了防止我们上线的网站被攻击,或者被刷取流量,我们会对某一个ip进行限制处理,这篇文章,我们将通过Spring Boot编写一个小案例,来实现在一分钟内同一个IP只能访问10次,当然具体数值,是您来决定,废话不多说,上代码。

首先,我们需要在Spring Boot的pom.xml文件中插入我们需要的依赖。具体的依赖部分我给出如下,也是Spring Boot常用的依赖,当然我并未在pom文件中给出Spring Boot的使用版本,因为我觉得并不是每个人都使用同样的版本,这是我使用的:
在这里插入图片描述

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-core</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId></dependency>

既然说到是对ip访问的限制,那么我们可以通过拦截器来实现对同一个ip地址在同一段时间段内的多次访问进行限制。具体代码如下:

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;/*** @author Miaow.Y.Hu* @date 2023年10月24日 19:01* @description*/@Component
public class RateLimitInterceptor implements HandlerInterceptor {private static final int MAX_REQUESTS = 10; // 同一时间段内允许的最大请求数private static final long TIME_PERIOD = 60 * 1000; // 时间段,单位为毫秒 在一分钟内限制ip访问次数为10次private Map<String, Integer> requestCounts = new HashMap<>();@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String ipAddress = request.getRemoteAddr();System.out.println(ipAddress);// 检查 IP 地址是否已经达到最大请求数if (requestCounts.containsKey(ipAddress) && requestCounts.get(ipAddress) >= MAX_REQUESTS) {response.setStatus(429); //设置响应状态码response.getWriter().write("Too many requests from this IP address");return false;}// 更新 IP 地址的请求数requestCounts.put(ipAddress, requestCounts.getOrDefault(ipAddress, 0) + 1);// 在指定时间后清除 IP 地址的请求数new Timer().schedule(new TimerTask() {@Overridepublic void run() {requestCounts.remove(ipAddress);}},TIME_PERIOD);return true;}
}

在这段代码中,我们使用了一个Map来存储每个IP地址的请求数,在preHandle方法中,我们首先检查IP地址的请求数是否已经达到最大请求数,如果是,则返回一个429当前IP地址的请求次数太多,一分钟只能请求10次,当然这决定权在你,然后我们更新IP地址的请求数,并在指定的时间段后清除该IP地址的请求数。

接下来,我们需要在配置类中注册拦截器,我采用的事WebMvcConfig:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class WebMvcConfig implements WebMvcConfigurer {private final RateLimitInterceptor rateLimitInterceptor;@Autowiredpublic WebMvcConfig(RateLimitInterceptor rateLimitInterceptor) {this.rateLimitInterceptor = rateLimitInterceptor;}@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(rateLimitInterceptor);}
}

在本段代码中,我们通过构造函数注入 RateLimitInterceptor,然后在 addInterceptors 方法中将拦截器添加到拦截器注册表中。

现在,当同一 IP 地址在同一时间段内的请求数达到最大限制时,它将收到一个 429的响应。你可以根据自己的需求调整最大请求数和时间段。

需要注意的是,这个小案例只是简答实现了对IP地址的拦截,在实际开发中,我们需要做的东西更加多,考虑的情况也需要更加全面,利用更加复杂的逻辑和持久化的存储来处理IP地址的请求限制。

接下来,我们通过Controller类来测试我们的写的案例是否实现这个功能:

@RestController
@RequestMapping("user/")
public class UserController {@RequestMapping("demo")public String test(){return "测试";}@RequestMapping("userDemo")public User userDemo(User user){return  user;}
}

User其实可写可不写,但是便于重复利用,我这里给出User的实体类吧:

public class User {private Long id;private String name;private Integer age;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;User user = (User) o;return Objects.equals(id, user.id) && Objects.equals(name, user.name) && Objects.equals(age, user.age);}@Overridepublic int hashCode() {return Objects.hash(id, name, age);}public User() {}public User(Long id, String name, Integer age) {this.id = id;this.name = name;this.age = age;}
}

最终结果展示:
在这里插入图片描述

在这里插入图片描述

相关文章:

使用Spring Boot限制在一分钟内某个IP只能访问10次

有些时候&#xff0c;为了防止我们上线的网站被攻击&#xff0c;或者被刷取流量&#xff0c;我们会对某一个ip进行限制处理&#xff0c;这篇文章&#xff0c;我们将通过Spring Boot编写一个小案例&#xff0c;来实现在一分钟内同一个IP只能访问10次&#xff0c;当然具体数值&am…...

ES 数据迁移最佳实践

ES 数据迁移最佳实践与讲解 数据迁移是 Elasticsearch 运维管理和业务需求中常见的操作之一。以下是不同数据迁移方法的最佳实践和讲解&#xff1a; 一、数据迁移需求梳理 二、数据迁移方法梳理 三、各方案对比 方案 优点 缺点&#xff08;限制&#xff09; 适用场景 是否有…...

C++中低级内存操作

C中低级内存操作 C相较于C有一个巨大的优势&#xff0c;那就是你不需要过多地担心内存管理。如果你使用面向对象的编程方式&#xff0c;你只需要确保每个独立的类都能妥善地管理自己的内存。通过构造和析构&#xff0c;编译器会帮助你管理内存&#xff0c;告诉你什么时候需要进…...

Linux硬盘大小查看命令全解析 (linux查看硬盘大小命令)

Linux操作系统是一款广泛应用于服务器和嵌入式设备的操作系统&#xff0c;相比于Windows等其他操作系统&#xff0c;Linux的优点之一就是支持强大的命令行操作。在日常操作中&#xff0c;了解和掌握一些简单但实用的命令可以提高工作效率。比如硬盘大小查看命令&#xff0c;在L…...

什么是供应链金融?

一、供应链金融产生背景 供应链金融兴起的起源来自于供应链管理一个产品生产过程分为三个阶段&#xff1a;原材料 - 中间产品 - 成产品。由于技术进步需求升级&#xff0c;生产过程从以前的企业内分工&#xff0c;转变为企业间分工。那么整个过程演变了如今的供应链管理流程&a…...

Qt之实现支持多选的QCombobox

一.效果 1.点击下拉列表的复选框区域 2.点击下拉列表的非复选框区域 二.实现 QHCustomComboBox.h #ifndef QHCUSTOMCOMBOBOX_H #define QHCUSTOMCOMBOBOX_H#include <QLineEdit> #include <QListWidget> #include <QCheckBox> #include <QComboBox>…...

【UI设计】Figma_“全面”快捷键

目录 1.快捷键与键位&#xff08;mac与windows&#xff09;2.基础快捷键3.操作区快捷键3.1视图3.2文字3.3选项3.4图层3.5组件 4.特殊技巧 Figma 是一个 基于浏览器 的协作式 UI 设计工具。【https://www.figma.com/】 Figma Sketch&#xff08;UI 设计&#xff09; InVision&a…...

计算机网络(谢希仁)第八版课后题答案(第一章)

1.计算机网络可以向用户提供哪些服务 连通性:计算机网络使上网用户之间可以交换信息&#xff0c;好像这些用户的计算机都可以彼此直接连通一样。 共享:指资源共享。可以是信息、软件&#xff0c;也可以是硬件共享。 2.试简述分组交换的要点 采用了存储转发技术。把报文(要发…...

argparse模块介绍

argparse是一个Python模块&#xff1a;命令行选项、参数和子命令解析器。argparse 模块可以让人轻松编写用户友好的命令行接口。程序定义了所需的参数&#xff0c;而 argparse 将找出如何从 sys.argv &#xff08;命令行&#xff09;中解析这些参数。argparse 模块还会自动生成…...

分布式、集群、微服务

分布式是以缩短单个任务的执行时间来提升效率的&#xff1b;而集群则是通过提高单位时间内执行的任务数来提升效率。 分布式是指将不同的业务分布在不同的地方。 集群指的是将几台服务器集中在一起&#xff0c;实现同一业务。 分布式中的每一个节点&#xff0c;都可以做集群…...

Android Studio的debug和release模式及签名配置

Android Studio的两种模式及签名配置 使用Android Studio 运行我们的app&#xff0c;无非两种模式&#xff1a;debug和release模式。 https://www.cnblogs.com/details-666/p/keystore.html...

【深蓝学院】手写VIO第8章--相机与IMU时间戳同步--笔记

0. 内容 1. 时间戳同步问题及意义 时间戳同步的原因&#xff1a;如果不同步&#xff0c;由于IMU频率高&#xff0c;可能由于时间戳不同步而导致在两帧camera之间的时间内用多了或者用少了IMU的数据&#xff0c;且时间不同步会导致我们首尾camera和IMU数据时间不同&#xff0c;…...

【Java集合类面试二十一】、请介绍TreeMap的底层原理

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a;请介绍TreeMap的底层原理…...

Go语言Channel

在本教程中&#xff0c;我们将讨论Channel以及 Goroutines 如何使用Channel进行通信。 什么是Channel Channel可以被认为是 Goroutine 用来进行通信的管道。与水在管道中从一端流向另一端的方式类似&#xff0c;可以使用Channel从一端发送数据并从另一端接收数据。 声明Chan…...

java 编译 引用 jar 包进行编译和执行编译后的class文件

编译java文件 javac -encoding UTF-8 -Djava.ext.dirs./ -d . ./FtpTest.java 执行编译class文件 java -Djava.ext.dirs./ com.util.FtpTest com.util为包路径...

Linux系统之部署Tale个人博客系统

Linux系统之部署Tale个人博客系统 一、Tale介绍1.1 Tale简介1.2 Tale特点 二、本地环境介绍2.1 本地环境规划2.2 本次实践介绍 三、检查本地环境3.1 检查本地操作系统版本3.2 检查系统内核版本 四、部署Tale个人博客系统4.1 下载Tale源码4.2 查看Tale源码目录4.3 查看安装脚本内…...

【跟小嘉学 Rust 编程】三十三、Rust的Web开发框架之一: Actix-Web的基础

系列文章目录 【跟小嘉学 Rust 编程】一、Rust 编程基础 【跟小嘉学 Rust 编程】二、Rust 包管理工具使用 【跟小嘉学 Rust 编程】三、Rust 的基本程序概念 【跟小嘉学 Rust 编程】四、理解 Rust 的所有权概念 【跟小嘉学 Rust 编程】五、使用结构体关联结构化数据 【跟小嘉学…...

算法通关村|黄金挑战|K个一组进行反转

K个一组进行反转 1.头插法 public ListNode reverseKGroup(ListNode head, int k) {ListNode dummyNode new ListNode(0);dummyNode.next head;ListNode cur head;// 计算链表长度int len 0;while (cur ! null) {len;cur cur.next;}// 计算有几组int n len / k;ListNod…...

【Android Studio】工程中文件Annotate with Git Blame 不能点击

问题描述 工程文件中想要查看代码提交信息但是相关按钮不可点击 解决方法 Android Studio -> Preferences -> Version Control-> 在Unregistered roots里找到你想要的工程文件 点击左上角➕号 然后右下角Apply即可...

Ant Design Vue

2222222222222...

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周&#xff0c;有很多同学在写期末Java web作业时&#xff0c;运行tomcat出现乱码问题&#xff0c;经过多次解决与研究&#xff0c;我做了如下整理&#xff1a; 原因&#xff1a; IDEA本身编码与tomcat的编码与Windows编码不同导致&#xff0c;Windows 系统控制台…...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

在软件开发中正确使用MySQL日期时间类型的深度解析

在日常软件开发场景中&#xff0c;时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志&#xff0c;到供应链系统的物流节点时间戳&#xff0c;时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库&#xff0c;其日期时间类型的…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?

Redis 的发布订阅&#xff08;Pub/Sub&#xff09;模式与专业的 MQ&#xff08;Message Queue&#xff09;如 Kafka、RabbitMQ 进行比较&#xff0c;核心的权衡点在于&#xff1a;简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...

视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)

前言&#xff1a; 最近在做行为检测相关的模型&#xff0c;用的是时空图卷积网络&#xff08;STGCN&#xff09;&#xff0c;但原有kinetic-400数据集数据质量较低&#xff0c;需要进行细粒度的标注&#xff0c;同时粗略搜了下已有开源工具基本都集中于图像分割这块&#xff0c…...