当前位置: 首页 > 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...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告&#xff08;肿瘤大小、血液指标&#xff09;&#xff0c;你需要做出一个**决定性判断**&#xff1a;恶性还是良性&#xff1f;这种“非黑即白”的抉择&#xff0c;正是**逻辑回归&#xff08;Logistic Regression&#xff09;** 的战场&a…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?

在大数据处理领域&#xff0c;Hive 作为 Hadoop 生态中重要的数据仓库工具&#xff0c;其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式&#xff0c;很多开发者常常陷入选择困境。本文将从底…...

MySQL 部分重点知识篇

一、数据库对象 1. 主键 定义 &#xff1a;主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 &#xff1a;确保数据的完整性&#xff0c;便于数据的查询和管理。 示例 &#xff1a;在学生信息表中&#xff0c;学号可以作为主键&#xff…...

【LeetCode】算法详解#6 ---除自身以外数组的乘积

1.题目介绍 给定一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O…...

云安全与网络安全:核心区别与协同作用解析

在数字化转型的浪潮中&#xff0c;云安全与网络安全作为信息安全的两大支柱&#xff0c;常被混淆但本质不同。本文将从概念、责任分工、技术手段、威胁类型等维度深入解析两者的差异&#xff0c;并探讨它们的协同作用。 一、核心区别 定义与范围 网络安全&#xff1a;聚焦于保…...

相关类相关的可视化图像总结

目录 一、散点图 二、气泡图 三、相关图 四、热力图 五、二维密度图 六、多模态二维密度图 七、雷达图 八、桑基图 九、总结 一、散点图 特点 通过点的位置展示两个连续变量之间的关系&#xff0c;可直观判断线性相关、非线性相关或无相关关系&#xff0c;点的分布密…...

Python爬虫实战:研究Restkit库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的有价值数据。如何高效地采集这些数据并将其应用于实际业务中,成为了许多企业和开发者关注的焦点。网络爬虫技术作为一种自动化的数据采集工具,可以帮助我们从网页中提取所需的信息。而 RESTful API …...

如何把工业通信协议转换成http websocket

1.现状 工业通信协议多数工作在边缘设备上&#xff0c;比如&#xff1a;PLC、IOT盒子等。上层业务系统需要根据不同的工业协议做对应开发&#xff0c;当设备上用的是modbus从站时&#xff0c;采集设备数据需要开发modbus主站&#xff1b;当设备上用的是西门子PN协议时&#xf…...