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

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

由于之前项目中,已经用了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.rhkb.cn/news/275918.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Material UI 5 学习03-Text Field文本输入框

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 Text Field文本输入框 一、最基本的本文输入框1、基础示例2、一些表单属性3、验证 二、多行文本 一、最基本的本文输入框 1、基础示例 import {Box, TextField} from "…

【嵌入式】字体极限瘦身术:Fontmin在嵌入式UI中的魔法应用(附3500常用汉字)

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

C++类和对象一

#include <iostream> using namespace std;//设计一个学生类 class CStudent {public: //公有成员void InputData(){cout << "请输入学号";cin >> sno;cout << "请输入姓名";cin >> sname;cout << "请输入分…

Go——数组

Golang Array和以往认知的数组有很大的。 数组是同一种数据类型的固定长度的序列。数组定义&#xff1a;var a[len] int&#xff0c;比如&#xff1a;var a [5]int&#xff0c;数组长度必须是常量&#xff0c;且类型的组成部分。一旦定义&#xff0c;长度不能变。长度是数组类…

微服务之商城系统

文章目录 一、商城系统建立之前的一些配置1、nacos2、Mysql3、consul【暂时不使用consul注册服务】这个可以跳过4、redis 二、grpc环境搭建三、微服务架构使用的protobuf1、查看proto的版本号2、安装protoc-gen-go和protoc-gen-go-grpc3、生成protobuff以及grpc的文件 一、商城…

定档!首届百度智能云全球生态大会,4月9日成都见!

为了加快人工智能的发展步伐&#xff0c;进一步推动大模型产业的实际落地&#xff0c;促进AI原生应用的全面繁荣&#xff0c;百度智能云将于2024年4月9日在成都举办首届“百度智能云GENERATE全球生态大会”。 大会将带来百度智能云在大模型时代的全新生态战略&#xff0c;以及针…

使用 Docker 部署 Next Terminal 轻量级堡垒机

1&#xff09;Next Terminal 介绍 官网&#xff1a;https://next-terminal.typesafe.cn/ GitHub&#xff1a;https://github.com/dushixiang/next-terminal 想必经常玩服务器的都了解过 堡垒机&#xff0c;类似于跳板机&#xff0c;但与跳板机的侧重点不同。堡垒机的主要功能是…

【SSM】任务列表案例 基本CRUD SSM整合

文章目录 一、案例功能预览二、接口分析三、前端工程导入四、后端程序实现和测试4.1 准备4.2 功能实现4.2.1 分页查询显示4.2.2 添加计划4.2.2 删除计划4.2.3 修改计划 4.3 前后联调 一、案例功能预览 Github 地址 &#xff1a; ssm-integration-part 二、接口分析 学习计划…

Python 合并两张图片

发现一个很有意思的图片处理包PIL&#xff0c;可以将两张图片合并成一张&#xff0c;而且很好看。代码如下 from PIL import Image# 打开两张图片 image1 Image.open("1.jpg").convert("RGBA") image2 Image.open("2.jpg").convert("RGB…

【数据结构与算法】:插入排序与希尔排序

&#x1f525;个人主页&#xff1a; Quitecoder &#x1f525;专栏: 数据结构与算法 欢迎大家来到初阶数据结构的最后一小节&#xff1a;排序 目录 1.排序的基本概念与分类1.1什么是排序的稳定性&#xff1f;1.2内排序与外排序内排序外排序 2.插入排序2.1实现插入排序2.3稳定性…

C#操作像素替换图片中的指定颜色

待处理的图片&#xff0c;其特征是包含有限数量颜色&#xff0c;不同的颜色相互交叉使用&#xff0c;相同颜色并未完全连贯&#xff0c;需要将图片中的指定颜色替换为另一颜色。虽然很多图片处理工具都支持类似操作&#xff0c;最后还是自己动手编写简单的处理程序。   程序的…

grafana table合并查询

注&#xff1a;本文基于Grafana v9.2.8编写 1 问题 默认情况下table展示的是一个查询返回的多个field&#xff0c;但是我想要的数据在不同的metric上&#xff0c;比如我需要显示某个pod的读写IO&#xff0c;但是读和写这两个指标存在于两个不同的metirc&#xff0c;需要分别查…

Kotlin/Java中String的equals和==

Kotlin/Java中String的equals和 在Java中&#xff0c;如果定义一个常量String和new出一个String对象&#xff0c;是不同的&#xff1a; String s1 "zhang" String s2 new String("zhang") 因为在Java看来&#xff0c;s1只是一个常量&#xff0c;会放在…

ruoyi-vue插件集成websocket

链接&#xff1a;插件集成 | RuoYi WebSocketServer.java&#xff1a;补充代码 /*** 此为广播消息* param message 消息内容*/public void sendAllMessage(String message) {LOGGER.info("【websocket.sendAllMessage】广播消息:"message);try {for(String sessionI…

爬虫案例1

通过get请求直接获取电影信息 目标页面: https://spa6.scrape.center/在network中可以看到是通过Ajax发送的请求&#xff0c;这个请求在postman中也可以直接请求成功&#xff0c;这只是一个用来练习爬虫的&#xff0c;没有达到js逆向的过程&#xff0c;需要通过分析js 代码来获…

GPT出现Too many requests in 1 hour. Try again later.

换节点 这个就不用多说了&#xff0c;你都可以上GPT帐号了&#xff0c;哈…… 清除cooki 然后退出账号&#xff0c;重新登录即可

考研失败, 学点Java打小工——Day3

1 编码规范——卫语句 表达异常分支时&#xff0c;少用if-else方式。   比如成绩判断中对于非法输入的处理&#xff1a; /*>90 <100 优秀>80 <90 良好>70 <80 一般>60 <70 及格<60 不及格*/Testpu…

基于springboot+vue实现乌鲁木齐南山冰雪旅游服务网管理系统项目【项目源码+论文说明】

基于springbootvue实现南山冰雪旅游服务网演示 摘要 随着2022年北京冬奥会的成功举办&#xff0c;在冬天进行冰雪运动已经逐渐流行起来&#xff0c;人们慢慢享受到了冰雪活动给大家带来的欢乐&#xff0c;除此之外人们的身体素质也可以得到提升。虽然已经有一部分人可以接受并…

[剪藏] - 2024软科:中国大学排名榜(前100强)

2024年3月12日 排名 校名 城市 类型 总分 办学层次 1 北京 综合 1004.1 37.5 清华大学 Tsinghua University 双一流/985/211 2 北京 综合 910.5 35 北京大学 Peking University 双一流/985/211 3 浙江 综合 822.9 35.9 浙江大学 Zhejiang Un…

Leet code 三步问题

解题思路&#xff1a;动态规划 先观察 1级台阶 1种方法 2级台阶 2种方法 3级台阶 4种方法 4级台阶 7种方法 5级台阶 13种方法 可以看出规律 从3级台阶后 每级台阶需要从前三层台阶和相加 注意&#xff1a;后面值会过大 需要在相加之后就模运算1000000007 代码如下 clas…