主頁 > 軟體設計 > 使用redis制作一個簡單的防御模塊 抵御惡意http請求攻擊

使用redis制作一個簡單的防御模塊 抵御惡意http請求攻擊

2020-11-01 12:20:19 軟體設計

使用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 {

    @Autowired
    RedisSerializer<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 {


    @Autowired
    private RedisTemplate<String, Integer> intRedisTemplate;

    /**單位均為毫秒*/
    private final int RECORD_TIME = 1000;
    private final int ALLOW_TIMES = 6;
    private final int REFUSE_TIME = 180000;


    @Override
    public 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(){
        @Override
        public 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 {

    @Resource
    HandlerInterceptor visitorRegistration;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        System.out.println("添加攔截器");
        // TODO Auto-generated method stub
        registry.addInterceptor(visitorRegistration)
                // 攔截路勁
                .addPathPatterns("/**");

    }
}

三、功能測驗

我使用已經開發出雛形的二手商城為例子,先開啟服務器

服務器正常啟動

打開瀏覽器,瘋狂刷http(很多人可能遠遠達不到我的手速,也可以選擇通過撰寫程式刷url)

我們可以看到 在我一秒20刷的http請求中,在第六次之后的請求全部被攔截下來,并且3分鐘內無法再訪問

服務器中的redis也有對應的redis記錄

四、總結和后語

雖然用屁股想都知道肯定有相關功能而且穩定高效的框架,但是我仍然喜歡自己親自動手實作自己突然的想法或者以前的想法,代碼中可能會因為springboot框架整體的異步結構會出現一定的偏差,但是這點并不會對其安全性有影響,而且有興趣的人也可以對HttpDetective介面做更加穩定或者高效的實作,這是我認真寫的第一張csdn 由于不怎么熟練,花了我快三個小時的時間完成.文章中出現的錯別字請見諒,作者技術較菜,有什么說的不對的地方或者建議請大佬們多指教

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/198056.html

標籤:其他

上一篇:2020-10-31

下一篇:JVM深度好文,CMS 收集器與 GC 日志分析定位問題詳解

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more