使用redis制作一个简单的防御模块 抵御恶意http请求攻击

2023-10-14 23:30

本文主要是介绍使用redis制作一个简单的防御模块 抵御恶意http请求攻击,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

使用redis制作一个简单的防御模块 抵御恶意http请求攻击


前言

本人是个菜鸡大学仔,平时也没有写csdn的习惯,刚刚做完一个小型外包项目不久没什么事,突然心血来潮,突发大胆想法。多年来由于始终不敢相信2G+1M的阿里云服务器的性能,一直想要自己尝试做一个简单的HTTP安全模块,防止好事者通过浏览器或者程序使用http访问刷我的服务器,恰逢今日有空,打算在原本的一个自己开发的二手市场springboot项目上使用刚学不久的redis进行恶意http攻击检测.,现在在csdn上做这光荣一刻的伟大记录,我习惯于把代码当做文章口述的一部分,而不会大规模复制代码,所以springboot基础薄弱的看着可能会有一些不适. 请见谅


提示:以下是本篇文章正文内容,下面案例可供参考

一、原理和思路

由于redis是基于内存的缓存服务器,性能高,稳定性也经住了市场的考验,自定义拦截器,连接请求,使用redis来记录每个http请求ip的近期访问次数,w如果发现了异常情况(短时间内发送了大量请求)则可以认为是恶意的HTTP请求攻击.可以对该IP进行封锁处理.并且可以记录该IP到日志上.

二、程序步骤

1.引入依赖和配置redis

为了方便测试,我使用工作电脑调试和运行springboot项目,而redis服务器搭建在阿里云上. 

<!--redis 依赖-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>#redis配置
spring.redis.host = ...
spring.redis.port = ... [默认6379]
spring.redis.password = [如果你的redis服务器有密码]
 

2.自定义redis的序列化器和RedisTemplate

我们需要一种<String, Integer>类型的RedisTemplate,并且要求他的value能够灵活地在java中作为integer 而在redis中作为string,而不用通过我们手工转换,同时也能保证在redis服务器上的可读性.  springboot上的redis整合api中提供了愚蠢的RedisTemplate<String, Integer> 由于Integer的序列化等问题显然不符合我们的要求,只能定制 一个自己的RedisTemplate 和序列化器,我习惯建一个config包,在该包的类中通过bean方法创建自己的配置bean

2.1.序列化器

  定义一个类 实现RedisSerializer<Integer>接口,重写其序列化和反序列化方法

实现思路很简单,因为我们的目的是在redis中以string字符储存, 在java中以integer的形式出现,在序列化时候将integer转换为string再进行序列化,反序列化时将序列化后的string转换成integer即可

@Override
public byte[] serialize(@Nullable Integer integer) throws SerializationException {return integer== null ? null : integer.toString().getBytes(StandardCharsets.UTF_8);
}@Override
public Integer deserialize(@Nullable byte[] bytes) throws SerializationException {return bytes == null ? null : Integer.valueOf(new String(bytes, StandardCharsets.UTF_8));
}

2.2.RedisTemplate

我们可以简单地创建一个RedisTemplate<String, Integer> 对象,对其key采用string序列化策略(注意,不要使用愚蠢的jdk默认序列化器,其序列化策略并不会原原本本地将string对象作为字符地byte数组存储,而且将其序列化为一种远古人类使用地奇怪符号) 对其value采用我们上文自定义的序列化器,所以核心的操作是

setKeySerializer(new StringRedisSerializer());

setValueSerializer(intRedisSerializer);

全部代码如下

@Configuration
public class RedisConfig {@AutowiredRedisSerializer<Integer> intRedisSerializer;@Bean("intRedisTemplate")public RedisTemplate<String, Integer> IntRedisTemplate(RedisConnectionFactory rcf){RedisTemplate<String, Integer> re = new RedisTemplate();re.setConnectionFactory(rcf);re.setKeySerializer(new StringRedisSerializer());re.setValueSerializer(intRedisSerializer);return re;}
}

说明:我将前面的integer序列化器命名为intRedisSerializer,注入了该RedisTemplate中

 

3.侦探类实现检测http攻击的核心功能

聪明的你可能已经发现字体的颜色变深了,这并不是因为我不知道怎么改字体颜色,而是我们的核心代码要开始了!!!

侦探(HttpDetective)这个名字花了我近10分钟, 该接口只声明了一个inspection(String ip)方法, 决定这个ip是否能访问你的服务器, 然后我们再创建HttpDetectiveImpl来具体实现他的功能,我们使用了一种简单可容错的策略,忽略了异步可能导致的实际参数误差,但是这并不会影响我们的功能和安全性. 具体代码如下

@Component("httpDetective")
public class HttpDetectiveImpl implements HttpDetective {@Autowiredprivate RedisTemplate<String, Integer> intRedisTemplate;/**单位均为毫秒*/private final int RECORD_TIME = 1000;private final int ALLOW_TIMES = 6;private final int REFUSE_TIME = 180000;@Overridepublic boolean inspection(String ip) {Integer times = intRedisTemplate.opsForValue().get(ip);if(times == null){System.out.println("有正常人进入");intRedisTemplate.opsForValue().set(ip, 1, RECORD_TIME, TimeUnit.MILLISECONDS);return true;}else{if(times >= ALLOW_TIMES){System.out.println("认定为入侵行为 拦截访问 并且禁止目标短时间内再次访问并且记录 入侵者ip"+ ip);intRedisTemplate.opsForValue().set(ip, ALLOW_TIMES, REFUSE_TIME, TimeUnit.MILLISECONDS);return false;}else{System.out.println("有可疑人进入.  "+times);intRedisTemplate.opsForValue().increment(ip);return true;}}}
}

 

我们将前面的RedisTemplate注入侦探类作为侦探类的工具,为了方便后面的修改,我们定义了三个常量,单位都是毫秒

    RECORD_TIME:  检查http访问的时间间隔
    ALLOW_TIMES :  检测时间间隔内的访问的次数
    REFUSE_TIME:   对判定为入侵者的封禁时间

我们将客户端传入的ip作为redis的键,当客户端首次访问时候,会创建该键值对,并且设置其生存周期 也就是RECORD_TIME,我们这里设置为一秒,这一秒内 用户每当再次访问接口,对应的value就会自己加一,如果在生存周期内值加到ALLOW_TIMES时,会将其设为入侵者,并且其在REFUSE_TIME时间内无法再访问我们的url.即对该ip封禁的时间内都会返回false,并且若入侵者继续尝试访问http接口时都会刷新封禁时间,这里将其注册为名字为httpDetective的bean

 

 

4.拦截器中挂载该侦探类,实现http拦截检测

4.1 自定义拦截器

由于拦截器通过返回true和false来决定是否发行,这里只需要直接注入上面的侦探类返回其inspection方法即可.

@Autowired
HttpDetective httpDetective;@Bean
public HandlerInterceptor visitorRegistration(){return new HandlerInterceptor(){@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {return httpDetective.inspection(request.getRemoteAddr());}};
}

4.3 在springboot中注册拦截器

springboot注册拦截器非常方便,只要继承了WebMvcConfigurer并且在其 addInterceptors(InterceptorRegistry registry) 方法中添加改拦截器即可,注意把该类注解为@Configuratio, 这里不必多说

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {@ResourceHandlerInterceptor visitorRegistration;@Overridepublic void addInterceptors(InterceptorRegistry registry) {System.out.println("添加拦截器");// TODO Auto-generated method stubregistry.addInterceptor(visitorRegistration)// 拦截路劲.addPathPatterns("/**");}
}

三、功能测试

我使用已经开发出雏形的二手商城为例子,先开启服务器

服务器正常启动

打开浏览器,疯狂刷http(很多人可能远远达不到我的手速,也可以选择通过编写程序刷url)

 

我们可以看到 在我一秒20刷的http请求中,在第六次之后的请求全部被拦截下来,并且3分钟内无法再访问

服务器中的redis也有对应的redis记录

四、总结和后语

虽然用屁股想都知道肯定有相关功能而且稳定高效的框架,但是我仍然喜欢自己亲自动手实现自己突然的想法或者以前的想法,代码中可能会因为springboot框架整体的异步结构会出现一定的偏差,但是这点并不会对其安全性有影响,而且有兴趣的人也可以对HttpDetective接口做更加稳定或者高效的实现,这是我认真写的第一张csdn 由于不怎么熟练,花了我快三个小时的时间完成.文章中出现的错别字请见谅,作者技术较菜,有什么说的不对的地方或者建议请大佬们多指教

这篇关于使用redis制作一个简单的防御模块 抵御恶意http请求攻击的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/213856

相关文章

C语言中联合体union的使用

本文编辑整理自: http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=179471 一、前言 “联合体”(union)与“结构体”(struct)有一些相似之处。但两者有本质上的不同。在结构体中,各成员有各自的内存空间, 一个结构变量的总长度是各成员长度之和。而在“联合”中,各成员共享一段内存空间, 一个联合变量

Tolua使用笔记(上)

目录   1.准备工作 2.运行例子 01.HelloWorld:在C#中,创建和销毁Lua虚拟机 和 简单调用。 02.ScriptsFromFile:在C#中,对一个lua文件的执行调用 03.CallLuaFunction:在C#中,对lua函数的操作 04.AccessingLuaVariables:在C#中,对lua变量的操作 05.LuaCoroutine:在Lua中,

一份LLM资源清单围观技术大佬的日常;手把手教你在美国搭建「百万卡」AI数据中心;为啥大模型做不好简单的数学计算? | ShowMeAI日报

👀日报&周刊合集 | 🎡ShowMeAI官网 | 🧡 点赞关注评论拜托啦! 1. 为啥大模型做不好简单的数学计算?从大模型高考数学成绩不及格说起 司南评测体系 OpenCompass 选取 7 个大模型 (6 个开源模型+ GPT-4o),组织参与了 2024 年高考「新课标I卷」的语文、数学、英语考试,然后由经验丰富的判卷老师评判得分。 结果如上图所

Vim使用基础篇

本文内容大部分来自 vimtutor,自带的教程的总结。在终端输入vimtutor 即可进入教程。 先总结一下,然后再分别介绍正常模式,插入模式,和可视模式三种模式下的命令。 目录 看完以后的汇总 1.正常模式(Normal模式) 1.移动光标 2.删除 3.【:】输入符 4.撤销 5.替换 6.重复命令【. ; ,】 7.复制粘贴 8.缩进 2.插入模式 INSERT

Lipowerline5.0 雷达电力应用软件下载使用

1.配网数据处理分析 针对配网线路点云数据,优化了分类算法,支持杆塔、导线、交跨线、建筑物、地面点和其他线路的自动分类;一键生成危险点报告和交跨报告;还能生成点云数据采集航线和自主巡检航线。 获取软件安装包联系邮箱:2895356150@qq.com,资源源于网络,本介绍用于学习使用,如有侵权请您联系删除! 2.新增快速版,简洁易上手 支持快速版和专业版切换使用,快速版界面简洁,保留主

如何免费的去使用connectedpapers?

免费使用connectedpapers 1. 打开谷歌浏览器2. 按住ctrl+shift+N,进入无痕模式3. 不需要登录(也就是访客模式)4. 两次用完,关闭无痕模式(继续重复步骤 2 - 4) 1. 打开谷歌浏览器 2. 按住ctrl+shift+N,进入无痕模式 输入网址:https://www.connectedpapers.com/ 3. 不需要登录(也就是

Windows/macOS/Linux 安装 Redis 和 Redis Desktop Manager 可视化工具

本文所有安装都在macOS High Sierra 10.13.4进行,Windows安装相对容易些,Linux安装与macOS类似,文中会做区分讲解 1. Redis安装 1.下载Redis https://redis.io/download 把下载的源码更名为redis-4.0.9-source,我喜欢跟maven、Tomcat放在一起,就放到/Users/zhan/Documents

Toolbar+DrawerLayout使用详情结合网络各大神

最近也想搞下toolbar+drawerlayout的使用。结合网络上各大神的杰作,我把大部分的内容效果都完成了遍。现在记录下各个功能效果的实现以及一些细节注意点。 这图弹出两个菜单内容都是仿QQ界面的选项。左边一个是drawerlayout的弹窗。右边是toolbar的popup弹窗。 开始实现步骤详情: 1.创建toolbar布局跟drawerlayout布局 <?xml vers

回调的简单理解

之前一直不太明白回调的用法,现在简单的理解下 就按这张slidingmenu来说,主界面为Activity界面,而旁边的菜单为fragment界面。1.现在通过主界面的slidingmenu按钮来点开旁边的菜单功能并且选中”区县“选项(到这里就可以理解为A类调用B类里面的c方法)。2.通过触发“区县”的选项使得主界面跳转到“区县”相关的新闻列表界面中(到这里就可以理解为B类调用A类中的d方法

自制的浏览器主页,可以是最简单的桌面应用,可以把它当成备忘录桌面应用

自制的浏览器主页,可以是最简单的桌面应用,可以把它当成备忘录桌面应用。如果你看不懂,请留言。 完整代码: <!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><ti