如果利用AOP/Aspect来修改方法的入参

news2024/11/15 11:17:57

问题描述:
最近项目代码过三方测试(国企项目),在一系列代码扫描审计检查下,代码发现一部分修改,例如请求参数发生了编码/加密,导致后台需要对请求的参数进行解码/解密,后端那么接口,总不能挨个,挨个的去修改。

由于之前项目中,已经用了AOP进行代码日志的记录,日志记录如下
在这里插入图片描述
原本代码的核心逻辑如下:因此想着,既然这里已经拿到请求参数了,直接在这里统一解码/加密,就不用对每个接口解码了

        MethodSignature ms = (MethodSignature) joinPoint.getSignature();
        methodApiOperation = ms.getMethod().getDeclaredAnnotation(ApiOperation.class);
        if (methodApiOperation != null) {
        	apiOperationDes = methodApiOperation.value();
        }
        logger.info("start-->请求{}模块的[{}]服务",apiDes, apiOperationDes);
        logger.info("  请求地址:{}",url);
        logger.info("  请求方法:{}.{}", abbreviateName(joinPoint.getSignature().getDeclaringTypeName()), methodName);
        Object[] args = joinPoint.getArgs();
        for (int i = 0; i < args.length; i++) {
        	if( !(args[i] instanceof StatHttpServletResponseWrapper)) {
        		logger.info("  请求参数{}:{}",i+1,JsonUtils.javaBeanToString(args[i]));
        	}
        }

修改思路1(利用Json格式化)(失败)

这里的请求参数是args 是Object类型,但是原始方法的请求类型肯定是各种自定的VO类
以解码html为例,我这里首先将Object[]挨个元素转成字符串,然后对整个字符串做html解码,将加码后的字符串,在创建一个新的对象赋joinPoint.getArgs的参数。结果发现修改并没有成功。

DecodeURL decodeURL = ms.getMethod().getDeclaredAnnotation(DecodeURL.class);
if(decodeURL != null) {
	Object[] args = joinPoint.getArgs();
	for (int i = 0; i < args.length; i++) {
	if( !(args[i] instanceof StatHttpServletResponseWrapper)) {
		String decode = StringEscapeUtils.unescapeHtml(JsonUtils.javaBeanToString(args[i]));
		logger.info("  解码Html请求参数{}",decode);
		//修改请求入参
		joinPoint.getArgs()[i] = JsonUtils.stringToJavaBean(decode, args[i].getClass());
		}
	}
}

代码执行逻辑是:

  1. 切面中记录请求参数-----》原始文本
  2. 切面中修改请求参数-----》修改后的文本
  3. 实际请求的controller-----》原始文本(也就是修改没有生效)
  4. 切面中调用请求参数-----》修改后的文本
    在这里插入图片描述

修改思路2(原始对象Set值)(有效,但没意义)

思路1中,我们是重新创建一个请求入参,然后把新的请求入参赋值给原始请求入参(Json格式化返回新的对象)
思路2,我们直接在原始的对象进行set值

DecodeURL decodeURL = ms.getMethod().getDeclaredAnnotation(DecodeURL.class);
if(decodeURL != null) {
	for (int i = 0; i < args.length; i++) {
	/*if( !(args[i] instanceof StatHttpServletResponseWrapper)) {
		String decode = StringEscapeUtils.unescapeHtml(JsonUtils.javaBeanToString(args[i]));
		logger.info("  解码Html请求参数{}",decode);
		//修改请求入参
		joinPoint.getArgs()[i] = JsonUtils.stringToJavaBean(decode, args[i].getClass());
	}*/
		if( (args[i] instanceof QueryResult)) {
			QueryResult query = (QueryResult)args[i];
			//修改请求入参
			query.setName(StringEscapeUtils.unescapeHtml(query.getName()));
		}
	}
}

此时查看实际的请求接口,发现值真的被修改了。
在这里插入图片描述
但是这里有个问题,上诉我是通过直接指定类型,然后强转类型,接着调用原对象的set方法,这是是我已知具体类型,具体字段,这样修改,我还不如直接找到原始的接口,在原来的接口里面修改。
AOP

QueryResult query = (QueryResult)args[i];
query.setName(StringEscapeUtils.unescapeHtml(query.getName()));

实际接口

@GetMapping
@DecodeURL
public void exportNxauto(HttpServletResponse response, QueryResult queryResult) {
	queryResult.setName(StringEscapeUtils.unescapeHtml(queryResult.getName()));
}

修改思路3(反射)

总结下思路1,思路1不用类型转换,也不用指定属性,格式化整个Json,然后对整个Json进行中文解码,但是转Json以后,导致重新创建了一个对象。思路2里面虽然没有创建新的对象,但是需要我们强制转化为某个类型,然后调用某个方式,实际请用场景,每个接口的入参的类型都不一样,具体是那个参数需要解码,所以也不知道调用那个Set方法。

Object[] args = joinPoint.getArgs();
for (int i = 0; i < args.length; i++) {
	if( !(args[i] instanceof StatHttpServletResponseWrapper)) {
    	logger.info("  请求参数{}:{}",i+1,JsonUtils.javaBeanToString(args[i]));
    }
}
ecodeURL decodeURL = ms.getMethod().getDeclaredAnnotation(DecodeURL.class);
if(decodeURL != null) {
	for (int i = 0; i < args.length; i++) {
		/*if( !(args[i] instanceof StatHttpServletResponseWrapper)) {
			String decode = StringEscapeUtils.unescapeHtml(JsonUtils.javaBeanToString(args[i]));
			logger.info("  解码Html请求参数{}",decode);
			//修改请求入参 失败:这里创建了一个新的对象,原始对象没有修改,修改的是新的对象。
			joinPoint.getArgs()[i] = JsonUtils.stringToJavaBean(decode, args[i].getClass());
		}*/
		/*if( (args[i] instanceof QueryResult)) {
			QueryResult query = (QueryResult)args[i];
			//修改请求入参 修改成功,但是太过于狭义,需要知道类型和具体的属性,然后调用Set方法
			query.setName();
		}*/
		if( !(args[i] instanceof StatHttpServletResponseWrapper)) {
			Class<? extends Object> classz = args[i].getClass();
			//使用反射改成功
			for (Field field : classz.getDeclaredFields()) {
				if(field.getType() == String.class) {
					ReflectionUtils.makeAccessible(field);
					Object value = field.get(args[i]);
					if(value != null) {
						ReflectionUtils.setField(field, args[i], StringEscapeUtils.unescapeHtml(value.toString()));
					}
				}else if (Collection.class.isAssignableFrom(field.getType())) {
				    // 字段是集合类型
				}else if (List.class.isAssignableFrom(field.getType())) {
				    // 字段是List类型
				}else if (field.getType().isArray()) {
				    // 字段是数组类型
				}else if (field.getType().isPrimitive()) {
				    // 字段是基本类型
				}
			}
		}
	}
}

接下来,我们看下运行的日志,可以看到,在我们的实际controller接口中,可以看到字符串类型的已经被html进行解码。
在这里插入图片描述

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

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

相关文章

【Git版本控制系统】:起步

目录 前言 版本控制 集中式与分布式的区别 Windows安装Git 核心 文件状态 工作区域 基本工作流程 配置用户信息 获取帮助 在线资源 前言 本篇文件的环境是Windows环境下实现。 在日常工作中git少不了&#xff0c;所以编写本篇文章介绍Git基础&#xff0c;专栏会不…

武汉星起航:创新驱动,共赢未来,引领跨境电商新潮流

在跨境电商这个充满挑战与机遇的领域&#xff0c;武汉星起航凭借其创新思维和共赢理念&#xff0c;正引领着行业发展的新潮流。 武汉星起航深知创新是企业在激烈竞争中立于不败之地的关键。公司始终关注市场动态&#xff0c;紧跟行业趋势&#xff0c;不断探索新的商业模式和运…

玩转 Spring 状态机:更优雅的实现订单状态流转

说起 Spring 状态机&#xff0c;大家很容易联想到这个状态机和设计模式中状态模式的区别是啥呢&#xff1f;没错&#xff0c;Spring 状态机就是状态模式的一种实现&#xff0c;在介绍 Spring 状态机之前&#xff0c;让我们来看看设计模式中的状态模式。 1. 状态模式 状态模式…

leetcode刷题(javaScript)——堆相关场景题总结

堆是什么&#xff1f;堆都能用树表示&#xff0c;并且一般树的实现都是利用链表。平时使用的最多的是二叉堆&#xff0c;它可以用完全二叉树表示&#xff0c;二叉堆易于存储&#xff0c;并且便于索引。在堆的实现时注意&#xff1a;因为是数组&#xff0c;所以父子节点的关系就…

学习SSM的记录(六)-- Spring MVC

目录 Spring MVC 简介和体验 Spring MVC原理简单解析 Spring MVC涉及的组件 Spring MVC 快速体验 Spring MVC 接收数据 访问路径设置 接收参数&#xff08;重点&#xff09; param和json参数比较 param参数接收 路径参数接收 json参数接收 EnableWebMvc注解 接收C…

探秘知乎的排名算法:知乎撰写高质量内容的秘诀

知乎作为一个知识问答社区&#xff0c;用户众多、内容繁杂&#xff0c;那么究竟是什么样的原则决定了知乎上的排名呢&#xff1f;腾轩科技传媒探讨知乎排名的规则&#xff0c;并分享如何撰写高质量的文章。 知乎排名的算法 在知乎这个巨大的社交平台上&#xff0c;任何一个用户…

DDL - 建立数据库,建表代码版(Way 2)

一、DB操作 show databases; create database DBOFRYX; drop database DBOFRYX; use DBOFRYX; 二、表操作&#xff08;表和表结构、字段是A、B两姐妹&#xff09; (1) use DBOFRYX; show tables; (2) create table TABOFRYX( name varchar(50) comment "姓名"…

ChatGPT提问技巧——对话提示

ChatGPT提问技巧——对话提示 对话提示是一种允许模型生成模拟两个或多个实体之间对话的文本的技术。 通过向模型提供上下文和一组角色或实体&#xff0c;以及他们的角色和背景&#xff0c;并要求模型生成他们之间的对话。 因此&#xff0c;应向模型提供一个上下文和一组角色…

大语言模型智能体简介

大语言模型&#xff08;LLM&#xff09;智能体&#xff0c;是一种利用大语言模型进行复杂任务执行的应用。这种智能体通过结合大语言模型与关键模块&#xff0c;如规划和记忆&#xff0c;来执行任务。构建这类智能体时&#xff0c;LLM充当着控制中心或“大脑”的角色&#xff0…

浏览器设置字体1px时,不能正常显示

问题如下&#xff0c;某版本浏览器&#xff0c;字体很小时&#xff0c;无法正常显示&#xff0c;解决方案有三种。 解决方案1 解决方案2 解决方案3

WebServer -- 面试题(下)

&#x1f442; 夏风 - Gifty - 单曲 - 网易云音乐 目录 &#x1f33c;前言 &#x1f382;面试题(下) 4&#xff09;HTTP报文解析 为什么要用状态机 状态转移图画一下 https 协议为什么安全 https 的 ssl 连接过程 GET 和 POST 的区别 5&#xff09;数据库注册登录 登…

十五、软考-系统架构设计师笔记-面向服务架构设计理论与实践

1、SOA相关概念 面向服务的架构(SOA)的定义 SOA 是一个组件模型&#xff0c;它将应用程序的不同功能单元(称为服务)通过这些服务之间定义良好的接口和契约联系起来。接口是采用中立的方式进行定义的&#xff0c;它应该独立于实现服务的硬件平台、操作系统和编程语言。这使得构…

[RoarCTF 2019]Easy Java -不会编程的崽

考察一下大家对java-web知识点的掌握 熟悉的登录界面让你想起了某位故人没有&#xff0c;哈哈&#xff0c;但是并非sql注入。一番基础尝试无果后&#xff0c;看看help吧 这个url让你想起某位故人了吗&#xff1f;对文件下载。但是似乎没有响应。改成post请求即可。 我看见pk了&…

unity3d Animal Controller的Animal组件中General基础部分理解

控制器介绍 动物脚本负责控制动物的所有运动逻辑.它管理所有的动画师和刚体参数,以及所有的状态和模式,动物可以做。 动物控制器 是一个动画框架控制器,根动或到位,为任何生物或人形。它利用刚体与物理世界的互动和动画师的玩动画。 States States 是不互相重叠的动画。例如…

canvas绘制圆形进度条

canvas绘制圆形进度条 用canvas绘制了一个圆形进度条&#xff0c;记录一下&#xff1a; 效果如下&#xff1a; 感觉效果还行&#xff0c;不过有待优化 代码如下&#xff1a; 我是用Vue写的 组件的代码&#xff1a; progressCanvas.vue <template><div><can…

Linux VM虚拟环境 设置静态IP

目录 查看自己的网卡配置说明重启网卡实例测试配置情况测试网络 查看自己的网卡 ip a配置文件 vim /etc/sysconfig/network-scripts/ifcfg-ens32配置说明 [rootlinux-server ~]# cd /etc/sysconfig/network-scripts/ #网卡配置文件存放路径 [rootlinux-server network-scri…

C/C++中{}的用法总结(全)

C基础专栏&#xff1a;http://t.csdnimg.cn/UjhPR 目录 1.定义初始化列表&#xff08;Initializer List&#xff09; 2.类成员初始化列表 3.无默认构造函数的类的默认初始化&#xff08;C11 及以后版本&#xff09; 4.初始化器列表构造函数&#xff08;C11 及以后版本&…

js判断对象是否有某个属性

前端判断后端接口是否返回某个字段的时候 <script>var obj { name: "John", age: 30 };console.log(obj.hasOwnProperty("name")); // 输出 trueconsole.log(obj.hasOwnProperty("email")); // 输出 falselet obj11 { name: "Joh…

一文搞懂多模态:BeiT-3之前的14个多模态+4个周边原理解读

在人工智能的世界里&#xff0c;多模态学习不断地展现出其重要性。这个领域的迅速发展不仅促进了不同类型数据之间的深度融合&#xff0c;还为机器理解世界提供了更加丰富和细腻的视角。随着科技的不断演进&#xff0c;人工智能模型已经开始渐渐具备处理和理解从文本、图像&…

MySQL主从复制的原理

MySQL 主从复制是一种数据复制技术&#xff0c;用于在多个数据库服务器之间的数据同步。在主从复制架构中&#xff0c;一个服务器被设置为主服务器&#xff0c;充当数据源&#xff0c;其他服务器被设置为从服务器&#xff0c;用来复制主服务器的数据。 1.主从复制优点 主从复…