Java反序列化JDK动态代理的关系

Java代理模式

为什么要学习代理模式?了解开发原理,才能明白漏洞的产生。这不仅仅是SpringAOP的底层!
[SpringAOP 和 SpringMVC]
代理模式的分类:

  • 静态代理
  • 动态代理

image.png

静态代理

角色分析:

  • 抽象角色:一般会使用接口或者抽象类来解决
  • 真实角色:被代理的角色
  • 代理角色:代理真是角色,代理真实角色后,我们一般会做一些附属操作
  • 客户:访问代理对象的人

代码步骤

接口

Rent.java

package Spring_Proxy.Demo01;//租房的接口
public interface Rent {public void rent();
}
真实角色

Host.java

  • 这是一个类,这个类就是房东,做为房东,他需要租房的接口,也就是Rent.java
package Spring_Proxy.Demo01;//房东
public class Host implements Rent{@Overridepublic void rent() {System.out.println("房东要出租房子!");}
}
代理角色

Proxy.java:这是一个类,这个类是中介,也就是代理,他需要有房东的房源,这里将房东类作为一个私有属性host,使用host.rent()来实现房东类的rent租房方法

package Spring_Proxy.Demo01;public class Proxy implements Rent{//房东的事情private Host host;public Proxy() {}public Proxy(Host host) {this.host = host;}//代理的事情@Overridepublic void rent() {host.rent();seeHouse();hetong();fare();}//看房public void seeHouse(){System.out.println("中介带你看房");}public void hetong(){System.out.println("签租凭合同");}//收中介费public void fare(){System.out.println("收中介费");}}
客户端访问代理角色

Client.java

  • 这是一个启动类,因为这里有main方法,这个类就是租客,租客需要先去找中介,然后才能租房,不能直接找房东是因为房东不想那么麻烦。
package Spring_Proxy.Demo01;public class Client {public static void main(String[] args) {//房东要租房子Host host = new Host();//代理,中介帮房东租房子,但是呢?代理角色一般会有一些附属操作!Proxy proxy = new Proxy(host);//你不用面对房东,直接找中介租房即可!proxy.rent();}
}

可以看见运行代码之后,都是代理的操作
image.png

案例演示

比如我们想做一个业务类的功能代码,需要增删改查,后面突然新增了一个功能,是需要日志的,记录增删改查的信息。那么我们肯定是不能再原来的业务代码进行修改了,因为不精简,不眼睛

定义接口代码
  • 这里定义了四个抽象方法
package Spring_Proxy.Demo02;public interface UserService {public void add();public void delete();public void update();public void query();
}
实现接口类代码
  • 这里使用一个实现接口类来完成增删改查的操作
package Spring_Proxy.Demo02;//实现接口类
public class UserServiceimpl implements UserService{@Overridepublic void add() {System.out.println("增加了一个用户");}@Overridepublic void delete() {System.out.println("删除了一个用户");}@Overridepublic void update() {System.out.println("修改了一个用户");}@Overridepublic void query() {System.out.println("查询一个用户");}//为什么不直接改实现类的代码?//1.改动原有的业务代码,在公司中是大忌,如果代码崩了呢?//2.业务是业务的方法,我们想添加其他的方法,我们用日志的方法}
接口类代理代码
  • 这里我们想实现一个新功能,每一次的操作都会有日志记录
  • 我们要在接口代理的代码中实现,这是因为横向开发的原因,不能改变缘来实现接口业务的代码的完整性
  • 缺点就是很麻烦,每一个方法都要添加log()
package Spring_Proxy.Demo02;public class UserSerivceProxy implements UserService {private UserServiceimpl userserivce;public void setUserserivce(UserServiceimpl userserivce) {this.userserivce = userserivce;}@Overridepublic void add() {log("add");userserivce.add();}@Overridepublic void delete() {log("delete");userserivce.delete();}@Overridepublic void update() {log("update");userserivce.update();}@Overridepublic void query() {log("query");userserivce.query();}//日志方法public void log(String msg){System.out.println("[Debug] 使用了"+msg+"方法");}
}
启动类代码
  • 启动类代码,这里有main方法
  • 我们需要实现接口类代码,所以new实现接口类的一个对象
  • 然后后面new了一个代理类的对象
  • 最好使用代理类里面的方法
package Spring_Proxy.Demo02;public class Client {public static void main(String[] args) {//代理类的一个对象 proxyUserSerivceProxy proxy = new UserSerivceProxy();//使用代理实现查询功能proxy.query();}
}

运行代码后可以发现,成功显示了
image.png

静态代理模式的好与坏

代理模式流程如图:讲究的是横向开发
image.png
好处:

  • 可以使真实角色的操作更加纯粹!不用去关注一些公共业务
  • 公共也就交给代理角色!实现了业务的分工!
  • 公共业务发生扩展的时候,方便集中管理!

缺点:

  • 一个真实角色就会产生一个代理角色;代码会翻倍开发效率会变低

动态代理

动态代理的了解

  • 动态代理和静态代理角色一样
  • 动态代理的代理类是动态生成的,不是我们直接写好的!
  • 动态代理分为两大类:基于接口的动态代理、基于类的动态代理
    • 基于接口—JDK 动态代理【我们在这里使用】
    • 基于类:cglib
    • java字节码实现:javasist

需要了解两个类:

  • Proxy:提供了创建动态代理类和实例的静态方法,
  • InvocationHandler:调用处理程序实现的接口
为什么需要动态代理

因为静态代理,如果需要添加什么方法,一个个的很麻烦,动态代理的本质就是利用了反射机制。动态代理能够灵活轻松的减少代码量

代码的实现

动态代理类代码

这是一个万能的动态代理类,固定的写法,我们只需要知道:

  • 有被代理的接口
  • 生成得到的代理类
  • 处理代理示例,并返回结果
  • 总的来说就是我们需要替换target变量就好了
  • 处理代理示例的时候,method方法invoke触发调用的是我们的变量target,args是固定的参数
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;//等我们会用这个类,自动生成代理类!
public class ProxyInvocatioinHandler implements InvocationHandler{//被代理的接口private Object target;public void setTarget(Object target) {this.target = target;}//生成得到代理类public Object getProxy(){return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);//这里最后面的this,指的是InvocationHandler}@Override//处理代理示例,并返回结果public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//log("add"); 太笨了这个方法log(method.getName());//动态代理的本质,就是使用反射机制实现!Object result = method.invoke(target, args);return result;}//日志方法需求(业务需求)public void log(String msg){System.out.println("[Debug]执行力"+msg+"方法");}
}
  • 可以发现不用重复添加log()
接口启动类代码
  • new一个接口实现类的对象 usersrrvice
  • 然后new一个动态代理类的对象 pih
  • 设置代理的对象为 代码实现类 usersrrvice
  • 最后动态生成这个代理类,使用强制类型转换 为 proxy变量
package Spring_Proxy.Demo04;import Spring_Proxy.Demo02.UserService;
import Spring_Proxy.Demo02.UserServiceimpl;public class Client {public static void main(String[] args) {//真实角色UserServiceimpl usersrrvice = new UserServiceimpl();//代理角色,不存在ProxyInvocatioinHandler pih = new ProxyInvocatioinHandler();//设置要代理的对象pih.setTarget(usersrrvice); //动态生成的代理类UserService proxy = (UserService) pih.getProxy();proxy.add();proxy.delete();}
}

运行之后可以看见自动日志方法成功了,这就是动态代理,不需要静态代理的手动重复添加,增加代码量
image.png

动态代理的好处

  • 可以使真实角色的操作更加纯粹!不用去关注一些公共业务
  • 公共也就交给代理角色!实现了业务的分工!
  • 公共业务发生扩展的时候,方便集中管理!
  • 一个动态代理类代理的是一个接口,一般就是对应的一类业务
  • 一个动态代理类可以代理多个类,只要实现了同一个接口即可

反序列化中动态代理的应用

我们知道反序列化漏洞,需要的是一个入口类。

  • 假设存在一个能够利用的类 为 B.f ,比如Runtime.exec
  • 入口类为 A,最理想情况下是 A[O] -> o.f,那么我们传进去的参数 O 替换为 B即可,但是实际情况下很少

实际情况下:

  • 入口类 A 存在 O.abc 这个方法,也就是 A[O] -> O.abc;如果O是一个动态代理类,O的 invoke方法存在 .f的方法,便可以漏洞利用了
A[O] -> O.abc
O[02] invoke -> 0.2f //此时将B 去替换为 O2
最后 --->
O[B] invoke -> b.f //达到漏洞利用效果

image.png
反序列化漏洞中的应用

  • readObject->反序列化自动执行
  • 而invoke->有调用函数
  • 拼接两条链:任意->固定
  • 在CC第一条链和jdk 7u21那两条链使用了动态代理。

属于这种类型:入口类参数中包含可控类,该类又调用其他危险方法的类,readObject时调用。

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

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

相关文章

关于网络丢包的一种可能性分析

最近我在工作中经常遇到有些客户的网络传输性能不理想。 通过wireshark抓包后我发现经常会有稍大的包timeout需要重传,这个现象导致了网络传输效率的大幅下降,因此我对网络丢包方面进行了进一步的研究。 根据我的经验总结,网络丢包有两种情况…

【微服务篇】深入理解RPC(远程调用)原理

什么是RPC RPC是一种通信机制,它使得在网络中的不同计算机之间可以像本地调用一样简单地进行函数或过程调用。RPC隐藏了底层的网络通信细节,使得开发者可以专注于业务逻辑,而不是处理网络通信的复杂性。RPC框架通常负责打包调用的参数&#…

A Simple Problem with Integers(线段树)

目录 描述 输入 输出 样例输入 样例输出 思路 建树 第一次错误解法(正确解法在下面,可跳过这一步) 正确解法 code 描述 You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of …

java中的单例模式

一、描述 单例模式就是程序中一个类只能有一个对象实例 举个例子: //引出单例模式,一个类中只能由一个对象实例 public class Singleton1 {private static Singleton1 instance new Singleton1();//通过这个方法来获取实例public static Singleton1 getInstance…

【文献分享】通过形态扫描仪阐明自组装肽聚集:蛋白质-肽结构表征的新工具

题目:Elucidating Self‐Assembling Peptide Aggregation via Morphoscanner: A New Tool for Protein‐Peptide Structural Characterization 通过形态扫描仪阐明自组装肽聚集:蛋白质-肽结构表征的新工具 自组装和分子折叠在自然界中无处不在&#xff…

你该选择哪个职业呢?数据科学家、数据分析师和数据工程师

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

CQ 社区版2.10.0 | 新增 SQL 审核、全新英文版上线…

三月中旬,我们预告了 CloudQuery 社区版即将上线的「SQL 审核」功能。现在,它来了! 本次社区版 v2.10.0,除了 SQL 审核功能,我们还在手动授权、连接分组等模块做了新功能和优化。 新增功能 新增 SQL 审核功能 支持…

路径规划——搜索算法详解(二):Floyd算法详解与MATLAB代码

上次总结了Dijkstra算法的案例原理与代码,本文分享第二种比较基础且易懂的方法为Floyd算法,该算法可以有效正确地处理有向图的最短路径问题,与Dijkstra算法不同,Floyd算法是一种动态规划算法,对于稠密图效果显著。原理…

安达发|APS计划排产系统帮助纺织业实现企业数字化管理

APS(高级计划排产系统)是一种基于供应链管理和约束理论的计划排产工具,它通过模拟和优化企业的生产、物流等运作过程,帮助企业实现精细化管理。在纺织业中,APS的应用可以极大地推动企业数字化管理的进程,具…

武汉星起航:各大企业力挺亚马逊,共筑跨境电商新生态

亚马逊电商平台作为全球领先的跨境电商巨头,一直以来都备受各大企业的青睐与支持。这些企业通过与亚马逊合作,共同拓展市场、提升品牌影响力,实现了互利共赢的局面。武汉星起航将浅析各大企业对亚马逊电商平台的支持,展现其共筑强…

Linux之时间子系统(四): tick 层模块(broadcast )

一、前言 在内核中,有cpuidle framework可以控制cpu的节电:当没有进程调度到该cpu上执行的时候,swapper进程粉墨登场,将该cpu会被推入到idle状态。当然CPU的idle状态有深有浅,当CPU睡的比较深入的时候,有可…

C++函数模板及类模板 ← 面向对象

【知识点】泛型编程,是 C 的一种重要编程思想,其利用的主要技术是模板。 C 提供两种模板机制:函数模板(function template)和类模板(class template)。【算法代码:函数模板】 ● 函数…

嵌入式C语言中头文件计设规则方法

我是阿梁,最近在负责的项目代码,也算是祖传代码了,里面有很多头文件嵌套的情况,即a.h包含b.h,b.h又包含c.h,c.h又包含d.h......遂找到一份华子的C语言编程规范学习一下,并结合自己的理解写成这篇文章,以规范自己的代码。 1. 头文件嵌套的缺点 依赖:若x.h包含了y.h,则…

005_index_in_Matlab中的数组索引

Matlab中的数组索引 1. 数组相关函数 前面我们已经介绍了关于向量、数组的一些基本约定,已经涉及了一些数组创建和操作的规则。 函数作用备注size返回数组的大小length返回数组的最大维度ndims返回数组的维度数numel返回数组的元素个数zeros创建全零数组ones创建…

vue3项目 引入unocss原子化

unocss是一个即时的原子CSS引擎,它可以让你用简短的类名来控制元素的样式,而不需要写复杂的CSS代码。 当然,原子样式也有很多选择,最著名的就是 Tailwind。但由于Tailwind 会生成大量样式定义,会导致全量的 CSS 文件往…

动态规划 Leetcode 674 最长连续递增序列

最长连续递增序列 Leetcode 300 学习记录自代码随想录 要点:1.dp[i]定义为nums[i]结尾的连续最长递增蓄力,则正向遍历,递推时,如果是连续序列,则只比较nums[i]和nums[i-1],若是可以不连续则可以&#xf…

组蛋白脱乙酰酶介导的胃癌肿瘤微环境特征及协同免疫治疗(多组学文献学习)

目录 ①HDAC转录组多数据NMF一次聚类 ②ACRG队列中HDAC单独NMF聚类 ③HDS评分在胃癌中的临床特征和基因组特征 ④高 HDS 可能提示胃癌的“热”肿瘤状态 ⑤HDS是胃癌免疫治疗效果的有力预测指标 ⑥单细胞转录组测序揭示了高HDS和低HDS患者的TME ⑦内皮细胞和成纤维细胞可…

Unity LineRenderer的基本了解

在Unity中,LineRenderer组件用于在场景中绘制简单的线条。它通常用于绘制轨迹、路径、激光等效果。 下面来了解下它的基本信息。 1、创建 法1:通过代码创建 using UnityEngine;public class CreateLineRenderer : MonoBehaviour {void Start(){// 创…

工作总结5

1.taro框架使用map标签出现的错误 这个问题困扰很长时间,在频繁切换页面渲染的时候出现左边不显示,我理解的是变量没有到达map标签的属性上,那我就想是不是setState太慢了,然后又用了变量,本地缓存等,都没有…

math模块篇(八)

文章目录 math.cosh(x)math.sinh(x)math.tanh(x) math.cosh(x) math.cosh(x) 是 Python 中 math 模块的一个函数,用于计算给定数值 x 的双曲余弦值。双曲余弦函数是双曲函数的一部分,它与普通的余弦函数有类似的性质,但定义在双曲空间中。 …