SpringBoot防止大量请求攻击

SpringBoot防止大量请求攻击我们使用Jmeter测试同学的网站时,就会出现网站无法访问,403等错误。Anerroroccurred.Sorry,thepageyouarelookingforiscurrentlyunavailable.Pleasetryagainlater.Ifyouarethesystemadministratorofthisresourcethenyoushouldchecktheerrorlogfordetails.Faithfull

大家好,又见面了,我是你们的朋友全栈君。

我们使用Jmeter测试同学的网站时,就会出现网站无法访问,403等错误。

An error occurred. Sorry, the page you are looking for is currently unavailable. Please try again later. If you are the system administrator of this resource then you should check the error log for details. Faithfully yours, nginx.

所以我们需要加上IP访问时间限制,防止一个IP多次访问请求,导致整个网站崩溃。

  • 自定义注解:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/** * 自定义注解,用于拦截过于频繁的请求 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AccessLimit { 
   
    int seconds();
    int maxCount();
    boolean needLogin() default true;
}
  • 自定义拦截器:
    我采用了抛出自定义异常的方式来解决相同IP多次访问的问题:
    throw new DujiaoshouException(20001,"操作过于频繁");
import com.qykhhr.dujiaoshouservice.exceptionhandler.DujiaoshouException;
import com.qykhhr.dujiaoshouservice.mycomment.AccessLimit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.concurrent.TimeUnit;
/** * 自定义拦截器 */
@Component
public class AccessLimtInterceptor implements HandlerInterceptor { 

@Autowired
private RedisTemplate redisTemplate;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 

if (handler instanceof HandlerMethod) { 

HandlerMethod hm = (HandlerMethod) handler;
AccessLimit accessLimit = hm.getMethodAnnotation(AccessLimit.class);
if (null == accessLimit) { 

return true;
}
int seconds = accessLimit.seconds();
int maxCount = accessLimit.maxCount();
boolean needLogin = accessLimit.needLogin();
if (needLogin) { 

//判断是否登录
}
String ip=request.getRemoteAddr();
String key = request.getServletPath() + ":" + ip ;
Integer count = (Integer) redisTemplate.opsForValue().get(key);
if (null == count || -1 == count) { 

redisTemplate.opsForValue().set(key, 1,seconds, TimeUnit.SECONDS);
return true;
}
if (count < maxCount) { 

count = count+1;
redisTemplate.opsForValue().set(key, count,0);
return true;
}
// response 返回 json 请求过于频繁请稍后再试
throw new DujiaoshouException(20001,"操作过于频繁");
}
return true;
}
}
  • 在webconfig中配置拦截器

import com.qykhhr.dujiaoshouservice.Interceptor.AccessLimtInterceptor;
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.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
/** * 在webconfig中配置拦截器 */
@Configuration
public class MyWebMvcConfigurer extends WebMvcConfigurerAdapter { 

@Autowired
private AccessLimtInterceptor accessLimtInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) { 

registry.addInterceptor(accessLimtInterceptor);
super.addInterceptors(registry);
}
}
  • 在Controller前面加上注解就可以生效了
@RestController
public class AppHomeController { 

@GetMapping("/index")
@AccessLimit(seconds = 1, maxCount = 3) //1秒内 允许请求3次
public R getImageList(){ 

return R.ok().data("appHome","hahaha");
}
}

使用python发送100次请求,可以发现请求被拦截了多少
在这里插入图片描述
对于注解,我们也可以不使用它,但是我们需要在拦截器中写入固定的参数。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/162102.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 前端页面图片加载失败显示默认图片

    前端页面图片加载失败显示默认图片方法有多种:1.首先说我用的,看代码//页面图片加载失败时默认显示统一处理document.addEventListener("error",function(e){  varelem=e.target;  if(elem.tagName.toLowerCase()=="img"){    elem.src="/image/General/errorDef…

  • python3.9多线程_python多线程原理

    python3.9多线程_python多线程原理什么是线程?线程也叫轻量级进程,是操作系统能够进行运算调度的最小单位,它被包涵在进程之中,是进程中的实际运作单位。线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其

  • c51单片机流水灯程序汇编语言,基于51单片机的流水灯程序

    c51单片机流水灯程序汇编语言,基于51单片机的流水灯程序LED流水灯的开发在51单片机中再常见不过了,主要是让大家掌握IO的操作是单片机控制最基本的要求。根据开发流程,我们先查看选型的单片机的资源和控制寄存器,然后在软件上实现控制。在这里芯片我们采用STC15W404AS作为开发的硬件平台,在这里我们用该单片机的P1引脚来驱动LED实现流水灯的功能。如图是LED连接的硬件电路,可以看到8颗LED是阳极通过限流电阻共同连接到VCC上的,也就是说当LED…

  • 怎么用python连接数据库_python连接pg数据库

    怎么用python连接数据库_python连接pg数据库实现步骤:一、使用mysql.connector1、导入msql的包2、创建连接对象3、使用cursor方法获取操作游标4、fetchall方法获取数据,for循环进行输出5、最后关闭连接对象importmysql.connector#创建连接对象#参数分别为:ip地址,用户名,密码,库名mydb=mysql.connector.connector(host=”192.168.139.128″,user=”root”,passwd=”root”,

    2022年10月23日
  • mysql 取模分区_MySQL分区

    mysql 取模分区_MySQL分区分表是将一个大表按照一定的规则分解成多张具有独立存储空间的实体表,app读写的时候根据事先定义好的规则得到对应的子表名,然后去操作它。而分区是将数据分段划分在多个位置存放,分区后,表面上还是一张表,但数据散列到多个位置了。app读写的时候操作的还是大表名字,db自动去组织分区的数据。分区类型主要有range、list、hash、key以常规hash举例说明分区是如何创建的常规hash是取模运算创建…

  • awvs11安装教程_ajax使用步骤

    awvs11安装教程_ajax使用步骤Awvs12.x安装及使用教程Awvs12.x安装1.下载Awvs12.x版本和对应补丁2.安装AwvsAwvs12.x使用Awvs12.x导出渗透结果报表Awvs12.x下载链接Awvs12.x安装1.下载Awvs12.x版本和对应补丁2.安装Awvs1.双击acunetix_12.0.180911134.exe进行安装2.然后选择我同意该条款3.随便填写对应邮箱如xxx@qq.com,账号密码一定要记住如果出现下图,是密码设置太简单了,需要设置含三种规则以上的密码如Abc12345

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号