我被恐吓了,对方扬言要压测我的网站

大家好我是聪,昨天真是水逆,在技术群里交流问题,竟然被人身攻击了!骂的话太难听具体就不加讨论了,人身攻击我可以接受,我接受不了他竟然说要刷我接口!!!!这下激发我的灵感来写一篇如何抵御黑子的压测攻击,还真得要谢谢他。

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.mzph.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…