springboot限制ip并发,springboot限制请求次数
墨初 知识笔记 117阅读
有些时候为了防止我们上线的网站被攻击或者被刷取流量我们会对某一个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 */Componentpublic 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<>(); Override public 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() { Override public 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;Configurationpublic class WebMvcConfig implements WebMvcConfigurer { private final RateLimitInterceptor rateLimitInterceptor; Autowired public WebMvcConfig(RateLimitInterceptor rateLimitInterceptor) { this.rateLimitInterceptor rateLimitInterceptor; } Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(rateLimitInterceptor); }}
在本段代码中我们通过构造函数注入 RateLimitInterceptor
然后在 addInterceptors
方法中将拦截器添加到拦截器注册表中。
现在当同一 IP 地址在同一时间段内的请求数达到最大限制时它将收到一个 429的响应。你可以根据自己的需求调整最大请求数和时间段。
需要注意的是这个小案例只是简答实现了对IP地址的拦截在实际开发中我们需要做的东西更加多考虑的情况也需要更加全面利用更加复杂的逻辑和持久化的存储来处理IP地址的请求限制。
接下来我们通过Controller类来测试我们的写的案例是否实现这个功能
RestControllerRequestMapping(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; } Override public 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); } Override public 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; }}
最终结果展示