基于网关的ip频繁访问web限制

news2024/11/25 0:39:19

一、前言

     外部ip对某一个web进行频繁访问,有可能是对web进行攻击,现在提供一种基于网关的ip频繁访问web限制策略,犹如带刀侍卫,审查异常身份人员。如发现异常或者暴力闯关者,即可进行识别管制。

二、基于网关的ip频繁访问web限制策略

1、ServerHttpReques的方式t获取

获取访问端ip地址

/**
	 * 获取客户端IP地址
	 * 
	 * @param request
	 * @return
	 */
	public String getIpAddress(ServerHttpRequest request) {
		 
		String ip = getHeaderValue(request, "x-forwarded-for");
	    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
	      ip = getHeaderValue(request, "Proxy-Client-IP");
	    }
	    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
	      ip = getHeaderValue(request, "X-Forwarded-For");
	    }
	    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
	      ip = getHeaderValue(request, "WL-Proxy-Client-IP");
	    }
	    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
	      ip = getHeaderValue(request, "X-Real-IP");
	    }
	    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
	      ip = request.getRemoteAddress().getAddress().getHostAddress();
	    }
	    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
	      ip = request.getLocalAddress().getAddress().getHostAddress();
	    }

	    return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
 
	}
	
	 public static String getHeaderValue(ServerHttpRequest request, String name) {
		    List<String> stringList = request.getHeaders().get(name);
		    if (!CollectionUtils.isEmpty(stringList)) {
		      return stringList.get(0);
		    }
		    return "";
		  }
/**
	 * 判断大规模异常请求是否受限(同一个IP)
	 * 
	 * @param count   1分钟内限制次数
	 * @param request
	 * @return
	 */
	public boolean isLimit(ServerHttpRequest request, int count) {
		String clientIp = getIpAddress(request);
		String noPermissIP = redisUtils.get(RedisKeys.getNoPermissClientIP(clientIp));
		if (!StringUtils.isEmpty(noPermissIP)) {

			String noPermissIPLog = redisUtils.get(RedisKeys.getNoPermissIPLog(clientIp));
			if (!StringUtils.isEmpty(noPermissIPLog)) {
				log.info("ip:" + clientIp + "访问系统接口频繁,被限制访问1天!");
				redisUtils.set(RedisKeys.getNoPermissIPLog(clientIp), "1", RedisUtils.DEFAULT_A_DAY);
			}
			return false;
		}
		String stratTime = redisUtils.get(RedisKeys.getRequestIPStartTime(clientIp));

		if (StringUtils.isEmpty(stratTime)) {
			stratTime = String.valueOf(System.currentTimeMillis());
			redisUtils.set(RedisKeys.getRequestIPPermiss(clientIp), "1", RedisUtils.DEFAULT_A_DAY);
			redisUtils.set(RedisKeys.getRequestIPStartTime(clientIp), stratTime, RedisUtils.DEFAULT_A_MIN);
		}
		Long interval = System.currentTimeMillis() - Long.parseLong(stratTime);
		String reqCount = redisUtils.get(RedisKeys.getRequestIPPermiss(clientIp));
		if (StringUtils.isEmpty(reqCount)) {
			redisUtils.set(RedisKeys.getRequestIPPermiss(clientIp), "1", RedisUtils.DEFAULT_A_DAY);
		} else {
			redisUtils.set(RedisKeys.getRequestIPPermiss(clientIp), (Integer.parseInt(reqCount) + 1) + "",
					RedisUtils.DEFAULT_A_DAY);
		}

		if (interval < 60000) { // 一分钟
			if (!StringUtils.isEmpty(reqCount)) {
				if (Integer.parseInt(reqCount) > count) {
					redisUtils.set(RedisKeys.getNoPermissIP(clientIp), clientIp, RedisUtils.DEFAULT_A_DAY);
					log.info(clientIp + "在最近" + (double) (Math.round(interval / 1000) / 100.0) + "秒内访问系统接口累计" + reqCount
							+ "次");
					log.info("ip:" + clientIp + "访问系统接口频繁,被限制访问1天!");
					return false;
				}
			}

		}
		return true;
	}

2、HttpServletReques的方式

	/**
	 * 获取客户端IP地址
	 * 
	 * @param request
	 * @return
	 */
	public String getIpAddress(HttpServletRequest request) {

		String ip = request.getHeader("x-forwarded-for");
		
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_CLIENT_IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_X_FORWARDED_FOR");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
		}
		 
		String [] ipArr = ip.split(",");
		
		ip = ipArr[0];
		
		ip.replaceAll("0:0:0:0:0:0:0:1", "127.0.0.1");
	 
		return  ip;
	}

ip频繁访问限制

这里需要借助redis缓存

	/**
	 * 判断大规模异常请求是否受限(同一个IP)
	 * 
	 * @param request
	 * @return
	 */
	public boolean isLimit(HttpServletRequest request) {

		String clientIp = getIpAddress(request);
		String noPermissIP = redisUtils.get(RedisKeys.getNoPermissIP(clientIp));
		if (!StringUtils.isEmpty(noPermissIP)) {

			String noPermissIPLog = redisUtils.get(RedisKeys.getNoPermissIPLog(clientIp));
			if (!StringUtils.isEmpty(noPermissIPLog)) {
				log.info("ip:" + clientIp + "访问系统接口频繁,被限制访问1天!");
				redisUtils.set(RedisKeys.getNoPermissIPLog(clientIp), "1", RedisUtils.DEFAULT_A_DAY);
			}
			return false;
		}
		String stratTime = redisUtils.get(RedisKeys.getRequestIPStartTime(clientIp));

		if (StringUtils.isEmpty(stratTime)) {
			stratTime = String.valueOf(System.currentTimeMillis());
			redisUtils.set(RedisKeys.getRequestIPPermiss(clientIp), "1", RedisUtils.DEFAULT_A_DAY);
			redisUtils.set(RedisKeys.getRequestIPStartTime(clientIp), stratTime, RedisUtils.DEFAULT_A_MIN);
		}
		Long interval = System.currentTimeMillis() - Long.parseLong(stratTime);
		String reqCount = redisUtils.get(RedisKeys.getRequestIPPermiss(clientIp));
		if (StringUtils.isEmpty(reqCount)) {
			redisUtils.set(RedisKeys.getRequestIPPermiss(clientIp), "1", RedisUtils.DEFAULT_A_DAY);
		} else {
			redisUtils.set(RedisKeys.getRequestIPPermiss(clientIp), (Integer.parseInt(reqCount) + 1) + "",
					RedisUtils.DEFAULT_A_DAY);
		}

		if (interval < 60000) { // 一分钟
			if (!StringUtils.isEmpty(reqCount)) {
				if (Integer.parseInt(reqCount) > 2000) {
					redisUtils.set(RedisKeys.getNoPermissIP(clientIp), clientIp, RedisUtils.DEFAULT_A_DAY);
					log.info(clientIp + "在最近" + (double) (Math.round(interval / 1000) / 100.0) + "秒内访问系统接口累计" + reqCount
							+ "次");
					log.info("ip:" + clientIp + "访问系统接口频繁,被限制访问1天!");
					return false;
				}
			}

		}
		return true;
	}

三、制作开关

对策略应该增加开关,作为启用策略和关闭策略使用

    /**
     * 1为开启,其他都是关闭
     */
    @Value("${interceptor.isAccLimit:-1}")
    private String isAccLimit;

四、对敏感性信息进行识(扩展)

  1. 定义敏感信息
    • 首先,明确哪些信息被认为是敏感的。这通常包括但不限于:密码、信用卡信息、社会保险号、个人身份信息(如全名、地址、电话号码、电子邮件地址)、医疗记录等。
  2. 输入验证
    • 使用输入验证来确保用户输入的数据符合预期的格式和类型。这可以防止恶意用户输入可能导致安全漏洞的数据。
    • 对于密码,确保它们足够复杂,并符合安全标准(如长度、特殊字符、大小写等)。
  3. 加密存储
    • 不要以明文形式存储敏感信息。使用加密算法(如AES、RSA等)对敏感信息进行加密,并确保密钥得到妥善保管。
    • 对于密码,使用哈希算法(如SHA-256、bcrypt等)进行存储,并加入“盐”(salt)来增加哈希的复杂性。
  4. 传输安全
    • 使用HTTPS来加密用户与Web服务器之间的通信,确保敏感信息在传输过程中不被窃取或篡改。
    • 避免在URL或GET请求中传递敏感信息,因为它们可能会被记录在浏览器历史、服务器日志或代理缓存中。
  5. 访问控制
    • 实现严格的访问控制策略,确保只有授权的用户和应用程序可以访问敏感信息。
    • 使用身份验证和授权机制(如OAuth、JWT等)来验证用户身份并授予相应的权限。
  6. 日志和监控
    • 记录与敏感信息相关的所有活动,包括访问、修改和删除等。这有助于在发生安全事件时进行调查和追溯。
    • 使用日志分析工具来监控潜在的安全威胁,并设置警报以在发现异常活动时进行通知。
  7. 定期审查
    • 定期对代码和配置进行安全审查,以确保没有意外的敏感信息泄露或安全漏洞。
    • 遵循最新的安全标准和最佳实践来更新和加固应用程序。
  8. 使用安全框架和库
    • 利用现有的安全框架和库(如Spring Security、OWASP等)来简化安全性的实现和维护。
    • 这些框架和库通常提供了许多内置的安全功能和防护措施,可以大大降低安全风险。
  9. 培训和教育
    • 对开发人员和管理员进行安全培训和教育,使他们了解如何识别和处理敏感信息以及如何遵循最佳的安全实践。
  10. 备份和恢复
    • 定期备份敏感信息,并确保备份数据的安全性。
    • 制定灾难恢复计划,以便在发生安全事件或数据丢失时能够迅速恢复敏感信息。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1718213.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

面向Java程序员的Go工程开发入门流程

对于一个像我这样没有go背景的java程序员来说&#xff0c;使用go开发一个可用的程序的速度是肉眼可见的缓慢。 其难点不在于go语言本身&#xff0c;而是搭建整个工程链路的过程&#xff0c;即所谓的“配环境”。 本文主要讲述如何配出一个适合go开发的环境&#xff0c;以免有同…

STL:vector

文章目录 标准库中的vectorvector的构造vector的迭代器vector的容量vector的元素访问data vector的修改 vector和string的迭代器失效问题resize、reserve、insert、push_back、assigneraseg 和 vs 的区别string解决迭代器失效的方法 标准库中的vector vector是表示可变大小数组…

【学习Day3】计算机基础

✍&#x1f3fb;记录学习过程中的输出&#xff0c;坚持每天学习一点点~ ❤️希望能给大家提供帮助~欢迎点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;指点&#x1f64f; 1.5.4 Cache替换算法 Cache的页面淘汰算法 常用替换算法有&#xff1a; • 随机替换算法RA…

浏览器【详解】Cookie(含Cookie的起源,属性,个数和大小限制,作用,优点,缺点,JS 的操作方法等)

什么是 Cookie &#xff1f; Cookie 是一段不超过 4KB 的小型文本数据&#xff0c;由一个名称&#xff08;Name&#xff09;、一个值&#xff08;Value&#xff09;和其它几个用于控制 Cookie 有效期、安全性、使用范围的可选属性组成。 浏览器为什么需要 Cookie &#xff1f; …

atk-esp8266-01刷新固件-链接-配置

1.刷新固件 加载固件&#xff1a; 编写地址&#xff1a; 2.链接IO-->GND 关闭其他所有占用此串口的软件&#xff1b; 重新上电 开始刷新固件&#xff1a; 刷新完成&#xff1b; 拆掉IO与GND链接。 3.配置 ATCWMODE_DEF3 //配置模式 ATRST //重启 …

Linux学习笔记(清晰且清爽)

本文首次发布于个人博客 想要获得最佳的阅读体验&#xff08;无广告且清爽&#xff09;&#xff0c;请访问本篇笔记 Linux安装 关于安装这里就不过多介绍了&#xff0c;安装版本是CentOS 7&#xff0c;详情安装步骤见下述博客在VMware中安装CentOS7&#xff08;超详细的图文教…

3d模型移动中心点偏移太远怎么解决?---模大狮模型网

在3D建模和动画制作中&#xff0c;移动模型时确保中心点的准确性至关重要。然而&#xff0c;有时候在移动模型时&#xff0c;中心点可能会偏移得太远&#xff0c;导致操作不便甚至影响到后续的工作流程。本文将介绍在3D模型移动中心点偏移太远时的常见原因&#xff0c;并提供解…

基于Linux的文件操作(socket操作)

基于Linux的文件操作&#xff08;socket操作&#xff09; 1. 文件描述符基本概念文件描述符的定义&#xff1a;标准文件描述符&#xff1a;文件描述符的分配&#xff1a; 2. 文件描述符操作打开文件读取文件中的数据 在linux中&#xff0c;socket也被认为是文件的一种&#xff…

JSON源码类学习

json源码学习 parse把json转换成Object parseObject转换为jsonObject parseArray从字符串数组解析成真正的数组 tojsonString把真正的json解析json 数组的方法 作用&#xff1a;类型转换 为什么要做类型转换 开发一个方法验证 这个方法先封装方法&#xff0c;是否为json …

长难句打卡5.31

In a workplace that’s fundamentally indifferent to your life and its meaning, office speak can help you figure out how you relate to your work—and how your work defines who you are. 在一个对你的生活和生活意义漠不关心的工作场所中&#xff0c;办公室语言可以…

绿色积分合法化 时代牺牲品!云联惠

各位朋友&#xff0c;我是吴军&#xff0c;在科技产业界从事多年市场分析工作。今天&#xff0c;我想与你们共同探讨一个曾引起广泛关注的企业案例——云联惠。 云联惠&#xff0c;这个曾被誉为商业创新典范的平台&#xff0c;一度风光无限。在其鼎盛时期&#xff0c;它不仅吸引…

【Python】解决Python报错:IndexError: queue index out of range

&#x1f9d1; 博主简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟&#xff0c;欢迎关注。提供嵌入式方向…

让WSL内核使用BBR拥塞控制算法

使用git命令从Linux内核的Git仓库中获取源代码,$ git clone --depth 1 https://github.com/microsoft/WSL2-Linux-Kernel.git,找到对应的内核版本$ git log --grep="5.15.146.1-microsoft-standard-WSL2",回退到本机安装的内核版本$ git checkout <commit-id&…

失之毫厘差之千里之load和loads

起源 最近在读pandas库的一些文档的时候&#xff0c;顺便也会将文档上的一些demo在编辑器中进行运行测试&#xff0c;其中在读到pandas处理Json数据这一节的时候&#xff0c;我还是像往常一样&#xff0c;将文档提供的demo写一遍&#xff0c;结果在运行的时候&#xff0c;直接…

Linux - 磁盘管理1

1.磁盘的分区 1.1 磁盘的类型&#xff08;标签&#xff09; MBR&#xff1a; ① 最大支持2T以内的硬盘 ② 有主分区p 拓展分区e 逻辑分区l之分 > 主分区编号1-4&#xff0c;主分区可以格式化使用 拓展分区编号1-4&#xff0c;拓展分区不能格式化 拓展分区最多能有1个&…

01Linux以及操作系统概述

课程目标 1.了解现代操作系统的整体构成及发展历史 2.了解Linux操作系统及其分支版本 3.直观上理解服务器端与桌面端版本的区别 课程实验 1.通过对CentOS和Ubuntu的演示&#xff0c;直观理解Linux与Windows的异同 课堂引入 本章内容主要为大家详细讲解Linux操作系统(以下简…

STM32—USART 串口通讯

目录 1 、 电路构成及原理图 2 、编写实现代码 main.c usart.c 3、代码讲解 4、烧录到开发板调试、验证代码 5、检验效果 STM32F103RCT6开发板——全集成开发板,让开发更简单&#xff01; 此笔记基于朗峰 STM32F103 系列全集成开发板的记录。 1 、 电路构成及原理图 …

香橙派OrangePi AIpro上手笔记——之USB摄像头目标检测方案测试(二)

整期笔记索引 香橙派OrangePi AIpro上手笔记——之USB摄像头目标检测方案测试&#xff08;一&#xff09; 香橙派OrangePi AIpro上手笔记——之USB摄像头目标检测方案测试&#xff08;二&#xff09; 香橙派OrangePi AIpro上手笔记——之USB摄像头目标检测方案测试&#xff08;…

安防监控视频平台LntonCVS视频监控汇聚平台遏制校园暴力保护校园学生安全应用方案

未成年人被誉为祖国的花朵&#xff0c;是我们国家的未来。然而&#xff0c;最近频繁曝出的未成年霸凌事件却引发了社会的广泛关注。这些事件手段残忍&#xff0c;事态恶劣&#xff0c;引发了全社会对如何保护未成年身心健康、规避霸凌事件发生的深刻思考。 为了更好地保障学生的…

Vitalik:Layer2 是以太坊社区文化的延伸

原文标题&#xff1a;《Layer 2s as cultural extensions of Ethereum》 撰文&#xff1a;Vitalik Buterin&#xff0c;以太坊联合创始人 编译&#xff1a;Chris&#xff0c;Techub News 在我最近关于 L1 和 L2 扩容差异的文章中&#xff0c;我最终得出的结论是&#xff0c; …