前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringBoot防止大量请求攻击

SpringBoot防止大量请求攻击

作者头像
全栈程序员站长
发布2022-09-13 16:59:21
1.1K0
发布2022-09-13 16:59:21
举报
文章被收录于专栏:全栈程序员必看

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

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

代码语言:javascript
复制
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多次访问请求,导致整个网站崩溃。

  • 自定义注解:
代码语言:javascript
复制
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,"操作过于频繁");
代码语言:javascript
复制
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中配置拦截器
代码语言:javascript
复制
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前面加上注解就可以生效了
代码语言:javascript
复制
@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.cn/162102.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档