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.rhkb.cn/news/291746.html

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

相关文章

ElasticSearch、java的四大内置函数式接口、Stream流、parallelStream背后的技术、Optional类

第四周笔记 一、ElasticSearch 1.安装 apt-get install lrzsz adduser -m es 创建用户组: useradd *-m* xiaoming(用户名) *PS:追加参数-m* passwd xiaoming(用户名) passwd xiaoming 输入新的 UNIX 密码: 重新输入新的 UNIX 密码&…

帆软报表踩坑日记

最近公司项目要是使用报表,公司使用的是帆软这个国产软件,自己也是学习使用,在使用的过程中记一下问题以及解决方式 公司使用的是帆软8这个版本,比较老了。 首先是表格中的扩展,就是当我们根据数据库查询数据然后放到表…

Redis入门三(主从复制、Redis哨兵、Redis集群、缓存更新策略、缓存穿透、缓存击穿、缓存雪崩)

文章目录 一、主从复制1.单例redis存在的问题2.主从复制是什么?3.主从复制的原理4.主从搭建1)准备工作2)方式一3)方式二 5.python中操作1)原生操作2)Django的缓存操作 二、Redis哨兵(Redis-Sent…

Nginx负载均衡 ,6种常用方式。(新手必看)

nginx的负载均衡策略有六种: 1、轮询(默认策略,nginx自带策略):我上面的例子就是轮询的方式,它是upstream模块默认的负载均衡默认策略。会将每个请求按时间顺序分配到不同的后端服务器。 http {upstream …

腾讯 tendis 替代 redis linux安装使用

下载地址 Tendis存储版 点击下载 linux 解压 tar -zxvf 安装包.tgz cd 解压安装包/scripts 启动 ./start.sh 停止 ./stop.sh 详细配置 修改 /scripts tendisplus.conf # tendisplus configuration for testing # 绑定本机IIP bind 192.168.31.112 port 51002 #设…

【CANN训练营笔记】Atlas 200I DK A2体验手写数字识别模型训练推理

环境介绍 开发板:Huawei Atals 200I DK A2 内存:4G NPU:Ascend 310B4 准备环境 下载编译好的torch_npu wget https://obs-9be7.obs.cn-east-2.myhuaweicloud.com/wanzutao/torch_npu-2.1.0rc1-cp39-cp39-linux_aarch64.whl pip3 install …

简易TCP服务器通信、IO多路复用(select、poll、epoll)以及reactor模式。

网络编程学习 简单TCP服务器通信TCP三次握手和四次挥手三次握手(如下图)常见问题? 四次挥手 client和server通信写法server端client端 通信双方建立连接到断开连接的状态转换怎么应对多用户连接?缺点 IO多路复用select优缺点 poll…

游戏行业行业竞争越来越激烈,遇到DDoS攻击遭受严重损失该如何解决

近年来,我们见证了数字化的快速发展,随着这样的发展,网络的威胁也逐渐增多,在网络攻击门槛不断降低,行业竞争越来越激烈,游戏行业的DDoS攻击如雨点般密集,在整个DDoS攻击的份额中,游…

前端日期组件layui使用,月模式

初学前端,实战总结 概要 有一个日期组件,我的谷歌浏览器选完日期后,偶尔获取不到最新数据,有一个客户,是经常出不来数据。 日期组件是Wdate:调用的方法是WdatePicker onpicking,代码片段如下…

ubuntu 安装 cloudcompare(两种方法)

方法一 :从 snap 安装 (推荐) 安装简单,基本上功能都有(读写保存las,pcd,标注等) 安装: sudo apt-get update sudo apt install snap sudo snap install cloudcompare…

c++使用类的一些注意事项

前言: 本篇内容为前面的补充,介绍了我们使用类时需要注意些什么以及一些编译器的优化,可能有些理解不到位或者错误,请斧正。 目录 前言: 1.再谈构造函数 2.(c98)隐式类型转换中的编译器的优…

【并发】第二篇 ThreadLocal详解

导航 一. ThreadLocal 简介二. ThreadLocal 源码解析1. get2. set3 .remove4. initialValue三. ThreadLocalMap 源码分析1. 构造方法2. getEntry()3. set()4. resize()5. expungeStaleEntries()6. cleanSomeSlots()7. nextIndex()8. remove()9. 总结ThreadLocalMap四. 内存泄漏…

UI的设计

一、RGB888的显示 即红色,绿色,蓝色都为8位,即通常说的24位色。可以很好显示各种过渡颜色。从硬件上,R、G、B三基色的连接线各需要有8根,即24根数据线;软件上存储的数据量也需要24位,即3个字节&…

环境影响与碳排放生命周期评估应用及案例分析

生命周期分析 (Life Cycle Analysis, LCA) 是评价一个产品系统生命周期整个阶段——从原材料的提取和加工,到产品生产、包装、市场营销、使用、再使用和产品维护,直至再循环和最终废物处置——的环境影响的工具。这种方法被认为是一种“从摇篮到坟墓”的…

哔哩哔哩直播姬有线投屏教程

1 打开哔哩哔哩直播姬客户端并登录(按下图进行操作) 2 手机用usb数据线连接电脑(若跳出安装驱动的弹窗点击确定或允许),usb的连接方式为仅充电(手机差异要求为仅充电),不同品牌手机要求可能不一样,根据实际的来 3 在投屏过程中不要更改usb的连接方式(不然电脑会死机需要重启) …

07-工作流设计:如何设计合理的多人开发模式?

一个企业级项目是由多人合作完成的,不同开发者在本地开发完代码之后,可能提交到同一个代码仓库,同一个开发者也可能同时开发几个功能特性。这种多人合作开发、多功能并行开发的特性如果处理不好,就会带来诸如丢失代码、合错代码、…

ES6 学习(二)-- 字符串/数组/对象/函数扩展

文章目录 1. 模板字符串1.1 ${} 使用1.2 字符串扩展(1) ! includes() / startsWith() / endsWith()(2) repeat() 2. 数值扩展2.1 二进制 八进制写法2.2 ! Number.isFinite() / Number.isNaN()2.3 inInteger()2.4 ! 极小常量值Number.EPSILON2.5 Math.trunc()2.6 Math.sign() 3.…

python电商结合双轨制

最近又重新整合翻看以前的数据,图片,绘画,还有各种编程代码,python,leetcode,还有关于商业方面的一些见解,想起了大学时候和同学们并肩作战,熬夜编码的时光。还有大数据,八爪鱼爬虫。 下面是我的手稿电商打…

Spring Boot 使用过滤器、拦截器、监听器

前言 作用 过滤器(Filter):当有一堆请求,只希望符合预期的请求进来。拦截器(Interceptor):想要干涉预期的请求。监听器(Listener):想要监听这些请求具体做了…

【剑指offer】顺时针打印矩阵

题目链接 acwing leetcode 题目描述 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。 数据范围矩阵中元素数量 [0,400]。 输入: [ [1, 2, 3, 4], [5, 6, 7, 8], [9,10,11,12] ] 输出:[1,2,3,4,8,12,11,10,9,5,6,7] 解题 …