Spring Boot 防止接口被恶意刷新、暴力请求
在实际项目使用中,必须要考虑服务的安全性,当服务部署到互联网以后,就要考虑服务被恶意请求和暴力攻击的情况,下面的教程,通过Spring Boot提供的HandlerInterceptor和Redis 针对 Url + ip在一定时间内访问的次数来将ip禁用,可以根据自己的业务需求进行相应的修改,以达到自己的目的。
首先创建一个自定义的拦截器类,也是最核心的代码。
/**
* @ProjectName: cdkj-framework
* @Package: com.cdkjframework.core.spring.filter
* @ClassName: FilterHandlerInterceptor
* @Description: 拦截过滤
* @Author: xiaLin
* @Date: 2022/6/22 13:36
* @Version: 1.0
*/
public class FilterHandlerInterceptor implements HandlerInterceptor { /**
* 日志
*/
private LogUtils logUtils = LogUtils.getLogger(FilterHandlerInterceptor.class); /**
* redis锁
*/
private final RedisLettuceLock redisLettuceLock; /**
* IP头部变量(可能通过Nginx代理后)
*/
private static final String HEADER_IP = "X-Real-IP"; /**
* 锁IP请求URL地址KEY
*/
private static final String LOCK_IP_URL_KEY = "lock_ip_"; /**
* IP请求URL地址时间
*/
private static final String IP_URL_REQ_TIME = "ip_url_times_"; /**
* 极限时间
*/
private static final long LIMIT_TIMES = 5; /**
* IP锁定时间 秒
*/
private static final int IP_LOCK_TIME = 60; /**
* 构建函数
*/
public FilterHandlerInterceptor(RedisLettuceLock redisLettuceLock) {
this.redisLettuceLock = redisLettuceLock;
} /**
* 预处理
*
* @param request 请求
* @param response 响应
* @param o 参数
* @return 返回结果
* @throws Exception 异常信息
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
String ip = request.getHeader(HEADER_IP);
if (StringUtils.isNullAndSpaceOrEmpty(ip)) {
ip = request.getRemoteAddr();
}
logUtils.info("request 请求地址 Uri={},ip={}", request.getRequestURI(), ip);
if (ipIsLock(ip)) {
logUtils.info("ip访问被禁止={}", ip);
ResponseBuilder builder = ResponseBuilder.failBuilder("ip访问被禁止");
returnJson(response, builder);
return false;
}
if (!addRequest(ip, request.getRequestURI())) {
ResponseBuilder builder = ResponseBuilder.failBuilder("ip访问被禁止");
returnJson(response, builder);
return false;
}
return true;
} @Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { } @Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { } /**
* IP 是否已锁
*
* @param ip IP 地址
* @return 返回是否成功
*/
private Boolean ipIsLock(String ip) {
if (redisLettuceLock.lock(LOCK_IP_URL_KEY + ip)) {
return true;
}
return false;
} /**
* 添加请求信息
*
* @param ip IP 地址
* @param uri 请求路径
* @return 返回是否成功
*/
private Boolean addRequest(String ip, String uri) {
String key = IP_URL_REQ_TIME + ip + uri;
if (RedisUtils.syncExists(key)) {
long time = RedisUtils.syncIncr(key, IntegerConsts.ONE);
if (time >= LIMIT_TIMES) {
redisLettuceLock.lock(LOCK_IP_URL_KEY + ip, IP_LOCK_TIME, ip);
return false;
}
} else {
redisLettuceLock.lock(key, (long) IntegerConsts.ONE, IntegerConsts.ONE);
}
return true;
} /**
* 返回结果
*
* @param response 响应
* @param builder 返回结果
* @throws Exception 异常信息
*/
private void returnJson(HttpServletResponse response, ResponseBuilder builder) throws Exception {
ResponseUtils.out(response, builder);
}
}
最后将上面自定义的拦截器通过WebMvcConfigurer下的registry.addInterceptor添加一下,就生效了。
/**
* @ProjectName: cdkj-framework
* @Package: com.cdkjframework.core.spring.filter
* @ClassName: WebMvcFilterConfigurerAdapter
* @Description: java类作用描述
* @Author: xiaLin
* @Date: 2022/6/22 13:37
* @Version: 1.0
*/
@RequiredArgsConstructor
public class WebMvcFilterConfigurerAdapter implements WebMvcConfigurer { /**
* redis锁
*/
private final RedisLettuceLock redisLettuceLock; /**
* 过虑句柄拦截器
*
* @return 返回拦截器
*/
@Bean
private FilterHandlerInterceptor filterHandlerInterceptor() {
return new FilterHandlerInterceptor(redisLettuceLock);
} /**
* 添加 拦截器
*
* @param registry 拦截器注册
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(filterHandlerInterceptor()).addPathPatterns("/**");
}
}
自己可以写一个for循环来测试改功能,这里就不具体详细介绍了。
文章中的工具类可参考:https://gitee.com/cdkjframework/common/tree/1.0.2/
Spring Boot 防止接口被恶意刷新、暴力请求的更多相关文章
- spring boot rest 接口集成 spring security(2) - JWT配置
Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...
- spring boot rest 接口集成 spring security(1) - 最简配置
Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...
- Spring Boot Web应用开发 CORS 跨域请求支持:
Spring Boot Web应用开发 CORS 跨域请求支持: 一.Web开发经常会遇到跨域问题,解决方案有:jsonp,iframe,CORS等等CORS与JSONP相比 1. JSONP只能实现 ...
- 46. Spring Boot中使用AOP统一处理Web请求日志
在之前一系列的文章中都是提供了全部的代码,在之后的文章中就提供核心的代码进行讲解.有什么问题大家可以给我留言或者加我QQ,进行咨询. AOP为Aspect Oriented Programming的缩 ...
- Spring boot CommandLineRunner接口使用例子
前言 Spring boot的CommandLineRunner接口主要用于实现在应用初始化后,去执行一段代码块逻辑,这段初始化代码在整个应用生命周期内只会执行一次. 如何使用CommandLineR ...
- spring boot: 设计接口站api的版本号,支持次版本号(spring boot 2.3.2)
一,为什么接口站的api要使用版本号? 1,当服务端接口的功能发生改进后, 客户端如果不更新版本, 则服务端返回的功能可能不能使用, 所以在服务端功能升级后, 客户端也要相应的使用 ...
- spring boot:给接口增加签名验证(spring boot 2.3.1)
一,为什么要给接口做签名验证? 1,app客户端在与服务端通信时,通常都是以接口的形式实现, 这种形式的安全方面有可能出现以下问题: 被非法访问(例如:发短信的接口通常会被利用来垃圾短信) 被重复访问 ...
- 寻找写代码感觉(三)之使用 Spring Boot 编写接口
一.前言 项目配置完之后,接着就是写接口了,那咱们就开始吧. 二.项目配置补充知识点 上篇文章写的是关于项目属性配置的一些知识,这里针对上次遗忘内容进行补充如下: 2.1.获取配置文件的值 在appl ...
- spring boot:使接口返回统一的RESTful格式数据(spring boot 2.3.1)
一,为什么要使用REST? 1,什么是REST? REST是软件架构的规范体系,它把资源的状态用URL进行资源定位, 以HTTP动作(GET/POST/DELETE/PUT)描述操作 2,REST的优 ...
- spring boot 统一接口异常返回值
创建业务 Exception 一般在实际项目中,推荐创建自己的 Exception 类型,这样在后期会更容易处理,也比较方便统一,否则,可能每个人都抛出自己喜欢的异常类型,而造成代码混乱 Servic ...
随机推荐
- centos8 telnet安装
1. 装包 yum -y install telnet telnet-server 2. 启服务 systemctl enable telnet.socket --now 3. 防火墙开放端口 fir ...
- cJson 学习笔记
cJson 学习笔记 一.前言 思考这么一个问题:对于不同的设备如何进行数据交换?可以考虑使用轻量级别的 JSON 格式. 那么需要我们手写一个 JSON 解析器吗?这大可不必,因为已经有前辈提供了开 ...
- apktool回编译报错
报错 error: No resource identifier found for attribute 'XXX' in package 'XXX' 解决 将xml文件中 "http:// ...
- 关于mysql远程连接失败的问题解决
解决办法 mysql 数据库user表配置密码 mysql 数据库user表配置plugin字段为mysql_native_password mysql 数据库user表host字段更改为% mysq ...
- node学习01
1.前言 Node.js 是一个开源和跨平台的 JavaScript 运行时环境 Node.js 在浏览器之外运行 V8 JavaScript 引擎(Google Chrome 的内核). 这使得 N ...
- 【每日一题】【使用list&使用辅助栈实现】2022年2月11日-NC90 包含min函数的栈
描述定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的 min 函数,输入操作时保证 pop.top 和 min 函数操作时,栈中一定有元素. 此栈包含的方法有:push(value): ...
- 【Spark】Day02:Spark-Core:RDD概述、RDD编程(转换算子、Action)、序列化、依赖关系、持久化、数据读取保存、累加器、广播变量、top10、转化率
总结:https://www.cnblogs.com/qingyunzong/p/8899715.html 一.RDD概述 1.引入:IO流 按行.按字节.字节缓冲 调用read方法读取流,均为惰性加 ...
- 动手实验查看MySQL索引的B+树的高度
一:文中几个概念 h:统称索引的高度: h1:主键索引的高度: h2:辅助索引的高度: k:非叶子节点扇区个数. 二:索引结构 叶子节点其实是双向链表,而叶子节点内的行数据是单向链表,该图未体现. 磁 ...
- webShell攻击及防御
最近公司项目也是经常被同行攻击,经过排查,基本定位都是挂马脚本导致,所以针对webShell攻击做一下记录. 首先简单说下 什么是webShell? 利用文件上传,上传了非法可以执行代码到服务器,然后 ...
- Java基于内存的消息队列实现
Java基于内存的消息队列实现 有需要源码的同学可以去Gitee上下载: https://gitee.com/hyxl-520/memory_message_queue 先看测试情况 需求背景 需求来 ...