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

一、前言

     外部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. 备份和恢复
    • 定期备份敏感信息,并确保备份数据的安全性。
    • 制定灾难恢复计划,以便在发生安全事件或数据丢失时能够迅速恢复敏感信息。

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

时序预测 | Matlab灰色-马尔科夫预测

目录 预测效果基本介绍程序设计参考资料 预测效果 基本介绍 Matlab灰色-马尔科夫预测 灰色马尔科夫预测&#xff08;Grey-Markov Prediction&#xff09;是一种用于时间序列预测的方法&#xff0c;它结合了灰色系统理论和马尔科夫链模型。灰色系统理论是一种非参数化的预测方法…

必看!硬核科普!什么是冻干?可以当主食喂的猫咪冻干分享

冻干猫粮作为近年来备受推崇的高品质选择&#xff0c;吸引了越来越多养猫人的目光。有着丰富养猫经验的我&#xff0c;早已开始采用冻干喂养。新手养猫的人可能会对冻干猫粮感到陌生&#xff0c;并产生疑问&#xff1a;这到底是什么&#xff1f;猫咪冻干可以天天喂吗&#xff1…

重新定义你的上网体验,微软WowTab助你一臂之力!

大家好&#xff0c;我是 Java陈序员。 浏览器是我们日常生活工作中必备的工具软件&#xff0c;使用非常频繁。 目前很多浏览器的新标签页虽然说功能齐全&#xff0c;但是充斥着广告和各种无效的信息&#xff0c;十分影响体验&#xff01; 今天&#xff0c;给大家安利一个浏览…

react 中使用 swiper

最近项目中需要用到轮播图&#xff0c;我立马想起了 swiper &#xff0c;那么本文就来带大家体验一下如何在 React 中使用这个插件&#xff0c;使用的是 函数组 hooks 的形式。 需求非常简单&#xff0c;就是一个可以自动播放、点击切换的轮播图&#xff08;跑马灯&#xff0…

基于jeecgboot-vue3的Flowable流程-待办任务(二)

因为这个项目license问题无法开源&#xff0c;更多技术支持与服务请加入我的知识星球。 接下来讲待办的流程处理 1、根据这个vue3新的框架&#xff0c;按钮代码如下&#xff1a; /*** 操作栏*/function getTableAction(record) {return [{label: 处理,onClick: handleProcess…

洗地机品牌哪个牌子好?避坑必读精析4大热门品牌优缺点

科技越发达&#xff0c;生活就越便捷。以打扫卫生为例&#xff0c;越来越多的人放弃了传统的扫把和拖把&#xff0c;转而选择更轻松的清洁家电&#xff0c;比如洗地机。洗地机不仅高效&#xff0c;还具有智能化设计&#xff0c;可以让清洁变得轻松。它强大的吸尘功能能够轻松应…

水位雨量监测站解析

水位雨量监测站是一种集水位和雨量监测功能于一体的重要气象和水文监测设备。其设计和功能旨在实时、准确地监测和记录河流水位、降雨量等关键数据&#xff0c;为气象、水文、环保等领域提供重要的信息支持。以下是关于水位雨量监测站的详细扩写&#xff1a; 系统组成 水位雨…

Midjourney绘画参数设置详解

在数字艺术和设计领域&#xff0c;Midjourney是一款强大的绘画工具&#xff0c;它允许艺术家和设计师以数字方式创作出精美的图像。为了充分发挥Midjourney的潜力&#xff0c;正确设置其绘画参数至关重要。本文将深入探讨Midjourney的绘画参数设置&#xff0c;帮助用户更好地掌…

掌握Element UI:加速你的网页设计过程!

Element UI 是一套为开发者、UI/UX设计师和产品经理准备的采用Vue 2.0作为基础框架实现的组件库&#xff0c;提供配套的设计资源&#xff0c;可以帮助设计快速成型。即时设计也内置Element UI Kit资源&#xff0c;但有些小伙伴还是对此不太了解&#xff0c;接下来本文会详细带你…

discuz论坛怎么修改备案信息

大家好&#xff0c;今天给大家分享下discuz如何填写备案信息并且展示在网站首页。大家都知道国内网站都需要备案&#xff0c;不通过备案的网站上是没办法通过域名打开的。大家也可以通过搜索网创有方&#xff0c;或者直接点击网创有方 查看悬挂备案号后的效果。 首先大家可以看…

STM32--ESP8266 WiFi模块

前言&#xff1a;此文所述模块为正点原子出版的ATK-ESP8266模块 一、特性参数 ATK-ESP8266 是 ALIENTEK 推出的一款高性能的 UART-WiFi&#xff08;串口-无线&#xff09;模块&#xff0c;ATK-ESP8266 板载了正点原子公司自主开发的 ATK-ESP-01 模块。 该模块是 ATK_ESP8266 的…

Flutter:革新移动开发的开源框架

在今天的移动应用开发领域&#xff0c;Flutter 已成为最受欢迎的开源框架之一。由 Google 开发并在 2017 年发布&#xff0c;Flutter 允许开发者使用单一代码库来构建跨平台的高性能应用&#xff0c;有效地覆盖了 iOS 和 Android 两大平台。接下来&#xff0c;我们将深入探索 F…

使用软件分享--剪映(不需要会员版)剪映 Jianying_pro_3_2_0_8778_beta9_jianyingpro_beta(Windows)

专栏介绍&#xff1a;本专栏主要分享一些实用的软件&#xff08;Po Jie版&#xff09;&#xff1b; 声明1&#xff1a;软件不保证时效性&#xff1b;只能保证在写本文时&#xff0c;该软件是可用的&#xff1b;不保证后续时间该软件能一直正常运行&#xff1b;不保证没有bug&am…

RocketMQ发送顺序消息原理与代码demo

RocketMQ 的顺序消息功能允许消息以发送的顺序被消费&#xff0c;这对于很多业务场景&#xff08;如交易处理、订单生成等, 或某些需要按照一定顺序执行的业务场景&#xff09;至关重要&#xff0c;因为这些场景下操作的执行顺序不能被打乱。顺序消息的实现需要确保消息在发送和…

【30天精通Prometheus:一站式监控实战指南】第10天:blackbox_exporter从入门到实战:安装、配置详解与生产环境搭建指南,超详细

亲爱的读者们&#x1f44b;   欢迎加入【30天精通Prometheus】专栏&#xff01;&#x1f4da; 在这里&#xff0c;我们将探索Prometheus的强大功能&#xff0c;并将其应用于实际监控中。这个专栏都将为你提供宝贵的实战经验。&#x1f680;   Prometheus是云原生和DevOps的…

【51单片机】智能百叶窗项目

文章目录 功能演示&#xff1a;前置要求&#xff1a;主要功能&#xff1a;主要模块&#xff1a;主函数代码&#xff1a; 具体的仿真程序和代码程序已经免费放置在资源中&#xff0c;如有需要&#xff0c;可以下载进行操作。 功能演示&#xff1a; 前置要求&#xff1a; 编译软…

Linux - 文件管理高级 find、grep

0.管道 | 将前面命令的标准输出传递给管道作为后面的标准输入 1.文件查找 find find 进行文件查找时&#xff0c;默认进行递归查找&#xff0c;会查找隐藏目录下的文件 1.1 用法 # find 查找路径 查找条件... -type // 文件类型 f 普通文件 b 设备 d …

MacOS13-将数据库转为markdown,docx格式

MacOS13-将数据库转为markdown&#xff0c;docx格式 文章目录 先说踩坑点各种模块缺失 代码效果总结参考 先说踩坑点 各种模块缺失 tkinter mysql 没错&#xff0c;你可以直接点击安装&#xff1b; 如果还出现报错 你需要打开终端 pip install mysqlclient再次点进去安…

C语言| 输出菱形*(梳理篇II)

C语言| 输出菱形*-CSDN博客 凡事还是得自己独立思考后&#xff0c;写一遍程序才能发现问题所在。 容易犯的错误&#xff1a; 【完整程序注释】 运行结果 /* 输出菱形 1 总行数 n为奇数&#xff0c;分上三角形下三角形&#xff0c;只考虑左边的空格和星号* 2 上三角形 行数…

toefl listening_托福听力

x.1 课程介绍 x.1.1 课程介绍 考试介绍 注意事项如下&#xff0c; x.1.2 分数设定和方法论 x.2.1 细节题解法 x.2.2 对话主旨题解法 听力对话不要扣分&#xff1b; 内容主旨题&#xff0c;以what开头&#xff1b; 目的主旨题&#xff0c;以why开头&#xff1b; 目的主旨题…