我被恐嚇了,對方揚言要壓測我的網站

大家好我是聰,昨天真是水逆,在技術群里交流問題,竟然被人身攻擊了!罵的話太難聽具體就不加討論了,人身攻擊我可以接受,我接受不了他竟然說要刷我接口!!!!這下激發我的靈感來寫一篇如何抵御黑子的壓測攻擊,還真得要謝謝他。

image-20240523081706355.png

🔥本次的自動加入黑名單攔截代碼已經上傳到短鏈狗,想學習如何生成一個短鏈可以去我的 Github 上面查看哦,項目地址:https://github.com/lhccong/short-link-dog-backend

思維發散

如果有人要攻擊我的網站,我應該從哪些方面開始預防呢,我想到了以下幾點,如何還有其他的思路歡迎大家補充:

  1. 從前端開始預防!

    聰 A🧑:確實是一種辦法,給前端 ? 驗證碼、短信驗證,或者加上谷歌認證(用戶說:我謝謝你哈,消防栓)。

    聰 B🧑:再次思考下還是算了,這次不想動我的前端加上如何短信驗證還消耗我的💴,本來就是一個練手項目,打住?。

  2. 人工干預!

    聰 A🧑:哇!人工干預很累的欸,拜托。

    聰 B🧑:那如果是定時人工檢查進行干預處理,輔助其他檢測手段呢,是不是感覺還行!

  3. 使用網關給他預防!

    聰 A🧑:網關!好像聽起來不錯。

    聰 B🧑:不行!我項目都沒有網關,單單為了黑子增加一個網關,否決?。

  4. 日志監控!

    聰 A🧑:日志監控好像還不錯欸,可以讓系統日志的輸出到時候統一監控,然后發短信告訴我們。

    聰 B🧑:日志監控確實可以,發短信還是算了,拒絕一切花銷哈?。

  5. 我想到了!后端 AOP 攔截訪問限流,通過自動檢測將 IP + 用戶ID 加入黑名單,讓黑子無所遁形。

    聰 A🧑:我覺得可以我們來試試?

    聰 B🧑:還等什么!來試試吧!

功能實現

設置 AOP 注解

1)獲取攔截對象的標識,這個標識可以是用戶 ID 或者是其他。

2)限制頻率。舉個例子:如果每秒超過 10 次就直接給他禁止訪問 1 分鐘或者 5 分鐘。

3)加入黑名單。舉個例子:當他多次觸發禁止訪問機制,就證明他還不死心還在刷,直接給他加入黑名單,可以是永久黑名單或者 1 天就又給他放出來。

4)獲取后面回調的方法,會用反射來實現接口的調用。

有了以上幾點屬性,那么注解設置如下:

/*** 黑名單攔截器** @author cong* @date 2024/05/23*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface BlacklistInterceptor {
?/*** 攔截字段的標識符** @return {@link String }*/String key() default "default";;
?/*** 頻率限制 每秒請求次數** @return double*/double rageLimit() default 10;
?/*** 保護限制 命中頻率次數后觸發保護,默認觸發限制就保護進入黑名單** @return int*/int protectLimit() default 1;
?/*** 回調方法** @return {@link String }*/String fallbackMethod();
}

設置切面具體實現

@Aspect
@Component
@Slf4j
public class RageLimitInterceptor {private final Redisson redisson;
?private RMapCache<String, Long> blacklist;// 用來存儲用戶ID與對應的RateLimiter對象private final Cache<String, RRateLimiter> userRateLimiters = CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES).build();
?public RageLimitInterceptor(Redisson redisson) {this.redisson = redisson;if (redisson != null) {log.info("Redisson object is not null, using Redisson...");// 使用 Redisson 對象執行相關操作// 個人限頻黑名單24hblacklist = redisson.getMapCache("blacklist");blacklist.expire(24, TimeUnit.HOURS);// 設置過期時間} else {log.error("Redisson object is null!");}}
?
?@Pointcut("@annotation(com.cong.shortlink.annotation.BlacklistInterceptor)")public void aopPoint() {}
?@Around("aopPoint() && @annotation(blacklistInterceptor)")public Object doRouter(ProceedingJoinPoint jp, BlacklistInterceptor blacklistInterceptor) throws Throwable {String key = blacklistInterceptor.key();
?// 獲取請求路徑RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();HttpServletRequest httpServletRequest = ((ServletRequestAttributes) requestAttributes).getRequest();//獲取 IPString remoteHost = httpServletRequest.getRemoteHost();if (StringUtils.isBlank(key)) {throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "攔截的 key 不能為空");}// 獲取攔截字段String keyAttr;if (key.equals("default")) {keyAttr = "SystemUid" + StpUtil.getLoginId().toString();} else {keyAttr = getAttrValue(key, jp.getArgs());}
?log.info("aop attr {}", keyAttr);
?// 黑名單攔截if (blacklistInterceptor.protectLimit() != 0 && null != blacklist.getOrDefault(keyAttr, null) && (blacklist.getOrDefault(keyAttr, 0L) > blacklistInterceptor.protectLimit()||blacklist.getOrDefault(remoteHost, 0L) > blacklistInterceptor.protectLimit())) {log.info("有小黑子被我抓住了!給他 24 小時封禁套餐吧:{}", keyAttr);return fallbackMethodResult(jp, blacklistInterceptor.fallbackMethod());}
?// 獲取限流RRateLimiter rateLimiter;if (!userRateLimiters.asMap().containsKey(keyAttr)) {rateLimiter = redisson.getRateLimiter(keyAttr);// 設置RateLimiter的速率,每秒發放10個令牌rateLimiter.trySetRate(RateType.OVERALL, blacklistInterceptor.rageLimit(), 1, RateIntervalUnit.SECONDS);userRateLimiters.put(keyAttr, rateLimiter);} else {rateLimiter = userRateLimiters.getIfPresent(keyAttr);}
?// 限流攔截if (rateLimiter != null && !rateLimiter.tryAcquire()) {if (blacklistInterceptor.protectLimit() != 0) {//封標識blacklist.put(keyAttr, blacklist.getOrDefault(keyAttr, 0L) + 1L);//封 IPblacklist.put(remoteHost, blacklist.getOrDefault(remoteHost, 0L) + 1L);}log.info("你刷這么快干嘛黑子:{}", keyAttr);return fallbackMethodResult(jp, blacklistInterceptor.fallbackMethod());}
?// 返回結果return jp.proceed();}
?private Object fallbackMethodResult(JoinPoint jp, String fallbackMethod) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {Signature sig = jp.getSignature();MethodSignature methodSignature = (MethodSignature) sig;Method method = jp.getTarget().getClass().getMethod(fallbackMethod, methodSignature.getParameterTypes());return method.invoke(jp.getThis(), jp.getArgs());}
?/*** 實際根據自身業務調整,主要是為了獲取通過某個值做攔截*/public String getAttrValue(String attr, Object[] args) {if (args[0] instanceof String) {return args[0].toString();}String filedValue = null;for (Object arg : args) {try {if (StringUtils.isNotBlank(filedValue)) {break;}filedValue = String.valueOf(this.getValueByName(arg, attr));} catch (Exception e) {log.error("獲取路由屬性值失敗 attr:{}", attr, e);}}return filedValue;}
?/*** 獲取對象的特定屬性值** @param item 對象* @param name 屬性名* @return 屬性值* @author tang*/private Object getValueByName(Object item, String name) {try {Field field = getFieldByName(item, name);if (field == null) {return null;}field.setAccessible(true);Object o = field.get(item);field.setAccessible(false);return o;} catch (IllegalAccessException e) {return null;}}
?/*** 根據名稱獲取方法,該方法同時兼顧繼承類獲取父類的屬性** @param item 對象* @param name 屬性名* @return 該屬性對應方法* @author tang*/private Field getFieldByName(Object item, String name) {try {Field field;try {field = item.getClass().getDeclaredField(name);} catch (NoSuchFieldException e) {field = item.getClass().getSuperclass().getDeclaredField(name);}return field;} catch (NoSuchFieldException e) {return null;}}
?
?
}

這段代碼主要實現了幾個方面:

  • 獲取限流對象的唯一標識。如用戶 Id 或者其他。
  • 將標識來獲取是否觸發限流 + 黑名單 如果是這兩種的一種,直接觸發預先設置的回調(入參要跟原本接口一致喔)。
  • 通過反射來獲取回調的屬性以及方法名稱,觸發方法調用。
  • 封禁 標識 、IP 。

代碼測試

@BlacklistInterceptor(key = "title", fallbackMethod = "loginErr", rageLimit = 1L, protectLimit = 10)@PostMapping("/login")public String login(@RequestBody UrlRelateAddRequest urlRelateAddRequest) {log.info("模擬登錄 title:{}", urlRelateAddRequest.getTitle());return "模擬登錄:登錄成功 " + urlRelateAddRequest.getTitle();}
?public String loginErr(UrlRelateAddRequest urlRelateAddRequest) {return "小黑子!你沒有權限訪問該接口!";}
  • key:需要攔截的標識,用來判斷請求對象。
  • fallbackMethod:回調的方法名稱(這里需要注意的是入參要跟原本接口保持一致)。
  • rageLimit:每秒限制的訪問次數。
  • protectLimit:超過每秒訪問次數+1,當請求超過 protectLimit 值時,進入黑名單封禁 24 小時。

以下是具體操作截圖:

Snipaste_2024-05-23_11-28-41.png

到這里這個黑名單的攔截基本就實現啦,大家還有什么具體的補充點都可以提出來,一起學習一下,經過這次”恐嚇風波“,讓我知道互聯網上的人戾氣還是很重的,只要堅持好做自己,管他別人什么看法!!

我是聰ζ希望可以跟大家一起學習,我的 Github:https://github.com/lhccong,如果里面有你感興趣的項目不妨給我點個星星?和關注🔥,未來我還會持續寫新的好玩的小項目。

參考文章:https://juejin.cn/post/7309921545638854665

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/17654.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/17654.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/17654.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

啟用標準大頁后內存使用率下降了

未啟用前 [rootol819c ~]# free -htotal used free shared buff/cache available Mem: 9.3Gi 984Mi 379Mi 1.5Gi 8.0Gi 6.8Gi Swap: 15Gi 3.0Mi 15Gi [rootol819c ~]# free -htotal …

【NumPy】掌握NumPy的histogram函數:數據直方圖的生成與應用詳解

&#x1f9d1; 博主簡介&#xff1a;阿里巴巴嵌入式技術專家&#xff0c;深耕嵌入式人工智能領域&#xff0c;具備多年的嵌入式硬件產品研發管理經驗。 &#x1f4d2; 博客介紹&#xff1a;分享嵌入式開發領域的相關知識、經驗、思考和感悟&#xff0c;歡迎關注。提供嵌入式方向…

速度百倍提升,高性能 Python 編譯器 Codon 火了

引言 在當下的編程世界里&#xff0c;Python由于其易用性和強大的庫支持在數據科學、人工智能和網頁開發等多個領域占據著舉足輕重的地位。然而&#xff0c;Python的執行速度往往成為開發者的一大痛點。 針對 這一問題&#xff0c;Codon項目正試圖提供一個高效的解決方案。Codo…

java新特性(Stream API)

什么是 Stream API? Stream API 是 Java 8 引入的一個用于對集合數據進行函數式編程操作的強大的庫。它允許我們以一種更簡潔、易讀、高效的方式來處理集合數據,可以極大提高 Java 程序員的生產力,是目前為止對 Java 類庫最好的補充。 Stream API 的核心思想是將數據處理操作…

小識MFC,一套設計優雅與不優雅并存的類庫----小話MFC(2)

Q1&#xff1a; CPoint繼承于POINT&#xff0c;這樣有什么好處&#xff1f; A&#xff1a; 繼承的一個最基本的好處當然就是減少代碼量。CPoint和POINT內部數據一樣&#xff0c;只是一個提供了更多的方法來操作對象。 typedef struct tagPOINT {LONG x;LONG y; } POINT, *P…

【Flutter】動畫介紹隱式動畫

&#x1f525; 本文由 程序喵正在路上 原創&#xff0c;CSDN首發&#xff01; &#x1f496; 系列專欄&#xff1a;Flutter學習 &#x1f320; 首發時間&#xff1a;2024年5月28日 &#x1f98b; 歡迎關注&#x1f5b1;點贊&#x1f44d;收藏&#x1f31f;留言&#x1f43e; 目…

SpringMvc-restful設計風格

Restful 1、入門1.1 簡介1.2 實例 1、入門 1.1 簡介 RESTFul是什么 RESTFul是WEB服務接口的一種設計風格。 RESTFul定義了一組約束條件和規范&#xff0c;可以讓WEB服務接口更加簡潔、易于理解、易于擴展、安全可靠。 1.2 實例 web.xml <?xml version"1.0"…

5、xss-labs之level6

一、level6-----大小寫繞過 1、測試分析 測試了之前用過的payload&#xff0c;發現都不行&#xff0c;并且level4使用的Java偽協議也不行&#xff0c;可以得出<>、script、onclick都被過濾 2、構造payload 因為href被過濾&#xff0c;可以試一下大寫HREF 初試payload…

沒人愿意和我們最好的工程師一起工作

幾年前&#xff0c;有一位技術非常好的工程師&#xff08;我們叫他“喬恩”&#xff09;為我工作。 他的代碼寫得很好&#xff0c;代碼審查&#xff08;PRs&#xff09;也完成得很快。從技術角度來看&#xff0c;他是個出色的工程師。 但是我們從其他工程師那里得到了一些關于…

Python實現解碼二進制數據以匹配給定的C++結構體

要在Python中實現解碼二進制數據以匹配給定的C結構體Ytest&#xff0c;你需要了解每個字段在結構體中的偏移量&#xff08;由于結構體內存對齊&#xff0c;這些偏移量可能與字段的順序和大小不完全對應&#xff09;。不過&#xff0c;在沒有指定內存對齊的情況下&#xff0c;我…

使用nvm管理node多版本(安裝、卸載nvm,配置環境變量,更換npm淘寶鏡像)淘寶的鏡像域名更換

最近 使用nvm 管理 node 的時候發現nvm install node版本號 總是失敗。 nvm install 20.12.2Error retrieving "http://npm.taobao.org/mirrors/node/latest/SHASUMS256.txt": HTTP Status 404查看原因&#xff0c;因為淘寶的鏡像域名更換&#xff0c;由于 npm.taob…

2020職稱繼續教育--發揮好“顯著優勢”,堅持和完善生態文明制度體系,促進人與自然和諧共生

單選題&#xff08;共7題&#xff0c;每題5分&#xff09; 1、我國生態脆弱區廣布&#xff0c;適宜生存的空間不足&#xff08;&#xff09;。 B、三分之一 2、按照傳統文化的說法&#xff0c;制度體系與治理體系&#xff0c;是“體”和“用”的關系&#xff0c;強調&#xff…

BI系統:數據驅動的決策利器,引領企業走向智能化

在當今這個數據驅動的時代&#xff0c;商業智能&#xff08;BI&#xff09;系統已成為企業不可或缺的工具。BI系統不僅提高了數據處理和分析的效率&#xff0c;更重要的是&#xff0c;它能夠幫助企業做出更加明智和精準的決策。在數聚多年的從業經驗來看&#xff0c;BI系統的重…

基于直接二元搜索的片上偏振分束器設計 (Nature Photonics, 9, 6, (2015))案例復現

時間—2024.6.08 騰訊會議 智能算法驅動的光子學設計與應用

Dream

好像很多人夢寐以求的都是別人已經擁有的&#xff0c;多少人奮斗一生的目標&#xff0c;卻只是別人的起點&#xff0c;人生而自由&#xff0c;只是不在枷鎖之中&#xff0c;生活中沒有人不遺憾&#xff0c;只是沒有人喊疼&#xff0c;時間不會重來&#xff0c;已經過去了就讓它…

內存泄露問題? 怎么解決

內存泄漏在Android應用開發中是一個常見問題&#xff0c;它發生在對象不再被使用時&#xff0c;但仍然被引用&#xff0c;導致垃圾回收器無法釋放其占用的內存。這會逐漸消耗應用可用內存&#xff0c;最終可能導致應用運行緩慢、崩潰或被系統終止。以下是一些常見的內存泄漏場景…

vue3 使用vant

使用前提&#xff1a; vite創建的vue3項目 vanthttps://vant-ui.github.io/vant/#/zh-CN/home npm i vant 引入樣式&#xff1a; main.js import vant/lib/index.css vant封裝 import { showLoadingToast,closeToast,showDialog,showConfirmDialog } from vant;export func…

Typora圖床配置優化(PicGo-Core(command line) 插件 + gitee)

Typora圖床配置優化&#xff08;PicGo-Core(command line) 插件 gitee&#xff09; 前言 在日常使用Typora編寫markdown筆記時&#xff0c;經常需要插入圖片來幫助理解和整理邏輯。然而&#xff0c;由于圖片保存在本地&#xff0c;上傳到網上時經常出現圖片不見或錯誤警告的…

育菁桌面式數控機床助力教育裝備

桌面式數控機床是一種小型化的數控機床&#xff0c;它通常具有緊湊的設計和較小的體積&#xff0c;可以放置在桌面上進行操作。 這種車床結合了數控技術&#xff0c;通過計算機編程來控制機床的運動和加工過程&#xff0c;以實現高精度、高效率的工件加工。 桌面式數控車床是一…

如何部署一套高可用性的醫院信息管理系統?基于華為云、SpringBoot、Vue及Jenkins、Gitlab的CI/CD流程

目錄 一、項目背景 二、項目架構 三、項目部署流程 1、前端部署 2、后端部署 3、監控與運維 四、項目過程 一、項目背景 隨著醫療信息化程度的不斷加深&#xff0c;醫院信息管理系統的穩定性和可用性成為了醫療機構日常運營的關鍵。在這個數字化時代&am…