Spring Boot 防止介面被惡意刷新、暴力請求

来源:https://www.cnblogs.com/cdkj/archive/2023/02/19/17134389.html
-Advertisement-
Play Games

介紹 棧(stack)又名堆棧,它是一種運算受限的線性表。限定僅在表尾進行插入和刪除操作的線性表。這一端被稱為棧頂,相對地,把另一端稱為棧底。向一個棧插入新元素又稱作進棧、入棧或壓棧,它是把新元素放到棧頂元素的上面,使之成為新的棧頂元素;從一個棧刪除元素又稱作出棧或退棧,它是把棧頂元素刪除掉,使其相 ...


​在實際項目使用中,必須要考慮服務的安全性,當服務部署到互聯網以後,就要考慮服務被惡意請求和暴力攻擊的情況,下麵的教程,通過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/

維基框架


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前言 本文主要作為本人學習C\C++歷程的的一種記錄,以期望通過這種方式加深對知識點的記憶,查漏補缺。如有寫得不對的地方,歡迎大家批評改正。 模板概論 模板是泛型編程的基礎,是創建泛型類或函數的藍圖或公式。 C++提供了兩種模板機制:函數模板和類模板。函數模板,實際上是建立了一個通用函數,其函數類型 ...
  • 定義 1.排列 排列,一般地,從n個不同元素中取出m(m≤n)個元素,按照一定的順序排成一列,叫做從n個元素中取出m個元素的一個排列。特別地,當m=n時,這個排列被稱作全排列。 用Αnm表示“從n個元素里取m個元素,排成一排的方案數”,也就是Αnm=n!/(n-m)! ,將它稱為排列數。 註:n!即 ...
  • 這次設計一個DDS信號發生器。該設計的特點有: 雙通道的DA輸出,可以調節頻率、相位、和波形(正弦波、方波、三角波)。 擁有相位重置的功能,能夠同時重置兩個輸出波形的相位。 本次採用的是小梅哥的ACM2108模塊。該模塊有兩個通道的ADC和兩個通道的DAC。 本次設計的前置是DDS基本模塊,具體可點 ...
  • Requests 是一個 Python 的一個第三方庫,通過發送 HTTP 請求獲取響應數據,一般應用於編寫網路爬蟲和介面測試等。 相比 urllib 庫,它語法簡單,更容易上手。 官方中文文檔地址:Requests: 讓 HTTP 服務人類 離線文檔下載地址:Requests document d ...
  • 背景 golang可以獲取命令執行的輸出結果,但要執行完才能夠獲取。 如果執行的命令是ssh,我們要實時獲取,並執行相應的操作呢? 示例 func main() { user := "root" host := "172.16.116.133" //獲取執行命令 cmd := exec.Comman ...
  • IDEA如何使用Maven不通過模板創建javaWeb項目 1.創建項目 進入IDEA,點擊“項目”>“新建項目”,填寫項目信息,最後點擊“創建”。 點擊“創建”後,自動進入新創建的項目。 2.給項目配置Web框架 點擊 “文件”>“項目結構”,自動跳轉到項目結構。 點擊 “模塊” > “+” > ...
  • 給大家推薦一個比Redis性能更強的數據:KeyDB KeyDB是Redis的高性能分支,側重於多線程、記憶體效率和高吞吐量。除了性能改進外,KeyDB還提供主動複製、快閃記憶體和子密鑰過期等功能。KeyDB具有MVCC架構,允許您在不阻塞資料庫和降低性能的情況下執行密鑰和掃描等查詢。 KeyDB與Redi ...
  • ​ 函數的調用、定義、參數 ​編輯 #######命名關鍵字參數沒完 abs()函數:絕對值 >>> abs(100) 100 >>> abs(-20) 20 max()函數:接收任意多個參數,並返回最大的那個 >>> max(1, 2) 2 >>> max(2, 3, 1, -5) 3 數據類型轉 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...