在项目中,接口的暴露在外面,很多人就会恶意多次快速请求,那我们开发的接口和服务器在这样的频率下的话,服务器和数据库很快会奔溃的,那我们该怎么防止接口防刷呢?由于博主小白,很多都不懂,都是从网上一点一点的找资料最后成功的。

看效果

解决方案:采用注解方式

其实也就是spring拦截器来实现。在需要防刷的方法上,加上防刷的注解,拦截器拦截这些注解的方法后,进行接口存储到redis中。当用户多次请求时,我们可以累积他的请求次数,达到了上限,我们就可以给他提示错误信息。

具体实现

一、写一个注解,注解怎么写传送门:SpringBoot开发自定义注解_springboot 格式化 自定义注解_庸人1396的博客-CSDN博客

1、在进行开发自定义注解前需要在POM文件中添加aop依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2、写上自己的注解

package com.hi.rongyao.base.annotation;import java.lang.annotation.*;@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AccessLimit {int seconds();int maxCount();
}

如图所示

二、重点是写下面的拦截器

package com.hi.rongyao.interceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;import com.alibaba.fastjson.JSONObject;
import com.hi.rongyao.base.annotation.AccessLimit;
import com.hi.rongyao.base.bean.ReturnCode;
import com.hi.rongyao.base.bean.ReturnObject;
import com.hi.rongyao.base.exception.UserException;
import com.hi.rongyao.base.utils.RedisKey;
import com.hi.rongyao.base.utils.RedisUtil;
import com.hi.rongyao.user.UserContext;
import com.hi.rongyao.user.service.UserAuthService;public class SessionInterceptor extends HandlerInterceptorAdapter {private static final Logger logger = LoggerFactory.getLogger(SessionInterceptor.class);@Autowiredprivate UserAuthService userAuthService;@Autowiredprivate UserContext userContext;@Autowiredprivate RedisUtil redisUtil;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String session = request.getHeader("Authorization");if (StringUtils.isEmpty(session)) {throw new UserException(ReturnCode.PARAMETERS_ERROR, "缺少session");}HandlerMethod hm = (HandlerMethod) handler;//获取方法中的注解,看是否有该注解AccessLimit accessLimit = hm.getMethodAnnotation(AccessLimit.class);if(accessLimit != null){int seconds = accessLimit.seconds();int maxCount = accessLimit.maxCount();//从redis中获取用户访问的次数String ip = request.getHeader("x-forwarded-for");      // 有可能ip是代理的if(ip ==null || ip.length() ==0 || "unknown".equalsIgnoreCase(ip)) {      ip = request.getHeader("Proxy-Client-IP");      }      if(ip ==null || ip.length() ==0 || "unknown".equalsIgnoreCase(ip)) {      ip = request.getHeader("WL-Proxy-Client-IP");      }      if(ip ==null || ip.length() ==0 || "unknown".equalsIgnoreCase(ip)) {      ip = request.getRemoteAddr();      } Integer count = (Integer)redisUtil.get(RedisKey.SECOND_ACCESS + ip);if(count == null){//第一次访问redisUtil.set(RedisKey.SECOND_ACCESS + ip, 1, seconds);}else if(count < maxCount){//加1count = count + 1;redisUtil.incr(RedisKey.SECOND_ACCESS + ip, count);}else{//超出访问次数logger.info("访问过快ip  ===> " + ip + " 且在   " + seconds + " 秒内超过最大限制  ===> " + maxCount + " 次数达到    ====> " + count);response.setCharacterEncoding("UTF-8");response.setContentType("application/json; charset=utf-8");ReturnObject result = new ReturnObject();result.setCode(ReturnCode.OPERATION_FAILED.getCode());result.setData("操作太快了");Object obj = JSONObject.toJSON(result);response.getWriter().write(JSONObject.toJSONString(obj));return false;}}Integer userId = userAuthService.getUserIdBySession(session);//获取登录的session进行判断if (userId == null || userId == 0) {throw new UserException(ReturnCode.BAD_REQUEST, "无效session");}userContext.setUserId(userId);return super.preHandle(request, response, handler);}
}
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {@Autowiredprivate FangshuaInterceptor interceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(interceptor);}
}

三、在controller中调用这个注解

@Controller
public class FangshuaController {@AccessLimit(seconds=5, maxCount=5)@RequestMapping("/fangshua")@ResponseBodypublic Result<String> fangshua(){return Result.success("请求成功");}

总结

这里采用了注解方式(拦截器),结合redis来存储请求次数,达到上限就不让用户操作。当然,redis有时间限制,到了时间用户可以再次请求接口的。

参考文章一:springboot项目中接口防止恶意请求多次 - 简书
参考文章二:https://www.cnblogs.com/wanjun-top/p/12974538.html
感谢这两位大神的分享

springboot项目中接口防止恶意请求多次,重复请求的解决办法,适合小白相关推荐

  1. java抢购防止多次请求_springboot项目中接口防止恶意请求多次

    springboot项目中接口防止恶意请求多次 在项目中,接口的暴露在外面,很多人就会恶意多次快速请求,那我们开发的接口和服务器在这样的频率下的话,服务器和数据库很快会奔溃的,那我们该怎么防止接口防刷 ...

  2. SpringBoot项目启动后网页显示【Please sign in】的解决办法

    Springboot启动项目后网页显示[Please sign in] 遇到的情况 解决办法 解决效果 根本原因(依赖导错了) 根本解决办法 遇到的情况 启动SpringBoot后,访问http:// ...

  3. vue 项目中使用svga格式动画图标效果 incorrect header check解决办法

    1. 什么是SVGA SVGA 是一种跨平台的开源动画格式,同时兼容 iOS / Android / Web.SVGA 除了使用简单,性能卓越,同时让动画开发分工明确,各自专注各自的领域,大大减少动画 ...

  4. springboot项目中使用shiro 自定义过滤器和token的方式___shiro使用token登录流程

    springboot项目中使用shiro 自定义过滤器和token的方式 实现步骤主要是以下几步: 1. 在项目中导入maven依赖 <dependency><groupId> ...

  5. SpringBoot项目中遇到的BUG

    1.启动项目的时候报错 1.Error starting ApplicationContext. To display the auto-configuration report re-run you ...

  6. pycharm项目中如何安装包_如何将Thymeleaf技术集成到SpringBoot项目中

    给天气预报一个"面子" 截至目前,不仅有了天气预报的API接口,也有了数据的缓存方案.现在,就要进行天气预报服务的实现,也就是说,这里需要一个面向用户的应用.这个应用应该拥有友好的 ...

  7. 关于webservice服务在springboot项目中的开发的介绍

    在springboot项目中搭建webservice服务端及使用客户端进行请求的介绍 一.引包 二.搭建webservice服务 (一)使用CXF搭建webservice服务 (二)webservic ...

  8. Springboot项目中使用Kafka

    Springboot项目中使用Kafka 第一步:安装好Kafka服务器 具体可参考: https://blog.csdn.net/weixin_40990818/article/details/10 ...

  9. springboot项目中利用@WebFilter注解和@Bean配置类两种方式实现Filter过滤器

    过滤器(Filter) 过滤器实际上就是对web资源进行拦截,做一些处理后再交给下一个过滤器或servlet处理.通常都是用来拦截request进行处理的,也可以对返回的response进行拦截处理 ...

最新文章

  1. 由1433端口入侵,浅谈sqlserver安全 (转)
  2. boost::process::posix相关的测试程序
  3. 问题 A: 青蛙约会(数学)
  4. CSDN博客文章阅读模式插件(附源码)
  5. 苹果确认部分AirPods Pro存在静电噪音等声音问题 将免费更换
  6. 052011GR2 _optimizer_null_aware_antijoin
  7. Java基础continue语句
  8. python科学计算库
  9. 一梦江湖获取服务器信息卡住,一梦江湖手游2021年8月6日更新公告
  10. Linux 命令大全
  11. python中的complex()函数
  12. AWB调试中(Tuning)的几个问题
  13. CentOS 7 添加新硬盘
  14. 2022 年十大最佳网络分析工具介绍
  15. 数分下第11讲(9.5节) 多变量函数的Taylor公式与极值
  16. java-php-python-ssm运动场所预约管理网站计算机毕业设计
  17. 知网html阅读需要花钱么,自己花钱怎么在知网上查重
  18. mht文件无法打开的解决办法
  19. 输入一个整数判断其是否是回文数
  20. Flutter 手写板 签名

热门文章

  1. java怎么实现踢掉在线用户_Java多人在线聊天室(3)— 踢人下线功能
  2. Spring 中使用了哪些设计模式?
  3. 如何安装python3.80_编程零基础应当如何开始学习 Python?为80%迷茫的人指明道路...
  4. 比亚迪“仰望”真正的卖点并非技术
  5. 红队眼中主要的安全防御能力怎样突破
  6. Eclipse篇.在线安装CodeMix插件
  7. Python:中文分词库jieba安装使用
  8. 数字IC经典电路(1)——经典加法器的实现(加法器简介及Verilog实现)
  9. CSS3全屏星空动态特效代码
  10. 三星N148上网本上安装windows 2000