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

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

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

(0)
上一篇 2022年7月20日 下午3:16
下一篇 2022年7月20日 下午3:16


相关推荐

  • pycharm教育版安装教程_pycharm专业版安装

    pycharm教育版安装教程_pycharm专业版安装1.打开百度搜索PyCharm进入官网,我们可以看到左边是专业版,右边是社区版,建议使用专业版,功能比较齐全。2. 双击安装包进行安装。自定义软件安装路径(建议路径中不要中文字符)。3.选择开始菜单文件夹(默认即可),点击安装。耐心等待安装。4.安装完成,勾选立即运行PyCharm。5.选择是否导入开发环境配置文件,我们选择不导入。6.阅读协议并同意7.如果有学生的edu邮箱的话可以免费使用…

    2025年6月7日
    5
  • js,timeout,promise执行顺序

    js,timeout,promise执行顺序

    2022年3月13日
    82
  • php mysql 经纬度_mysql,php和js根据经纬度计算距离

    php mysql 经纬度_mysql,php和js根据经纬度计算距离根据经纬度计算距离公式图片来自互联网对上面的公式解释如下:Lung1Lat1表示A点经纬度,Lung2Lat2表示B点经纬度;a=Lat1–Lat2为两点纬度之差b=Lung1-Lung2为两点经度之差;6378.137为地球半径,单位为千米;计算出来的结果单位为千米,若将半径改为米为单位则计算的结果单位为米。计算精度与谷歌地图的距离精度差不多,相差范围在0.2米以下。参数说明…

    2026年2月22日
    4
  • C++使用CreateMutex

    C++使用CreateMutex一 定义 HANDLECreate LPSECURITY ATTRIBUTESlp 指向安全属性的指针 BOOLbInitial 初始化互斥对象的所有者 LPCTSTRlpNam 指向互斥对象名的指针 第一个参数是一个指向 SECURITY ATTRIBUTES 结构体的指针 一般的情况下 可以是 nullptr 第二个参数类型为 BOOL 表示互斥锁创建出来后是否被当前线程持有 第三个参数类型为字符串 con

    2025年9月14日
    6
  • 3306端口被占用解决方式

    3306端口被占用解决方式3306 端口被占用解决方式打开 phpstudy 发现 3306 端口被占用了 win r 然后 cmd 进入命令行 输入 netstat ano 查看所有端口信息接着可以 netstat ano findstr 11412 输入对应端口的 PID 可以看到当前的端口被占用情况 打开任务管理器 在详细信息中找到对应 PID 结束该任务接着就可以成功开启了

    2025年12月6日
    7
  • 纳德拉AI言论引争议 "Microslop"成热词,呼吁行业构建新共识

    纳德拉AI言论引争议 "Microslop"成热词,呼吁行业构建新共识

    2026年3月14日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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