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

news2024/11/28 14:48:46

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{
    @Override
    public 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;
    }

//代理的事情
    @Override
    public 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{


    @Override
    public void add() {
        System.out.println("增加了一个用户");
    }

    @Override
    public void delete() {
        System.out.println("删除了一个用户");
    }

    @Override
    public void update() {
        System.out.println("修改了一个用户");
    }

    @Override
    public 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;
    }

    @Override
    public void add() {
        log("add");
        userserivce.add();
    }

    @Override
    public void delete() {
        log("delete");
        userserivce.delete();

    }

    @Override
    public void update() {
        log("update");
        userserivce.update();
    }

    @Override
    public 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) {
        
        //代理类的一个对象 proxy
        UserSerivceProxy 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.coloradmin.cn/o/1556479.html

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

相关文章

【vue】一个小bug和key的引入

点击master Vue!删除后该list后输入框中的Jerry消失了 原因:vue当你更改元素时会在真实的dom中渲染并更新list。这两个goal是两个dom元素,触发点击事件后,vue并不会删除第一个dom元素,而是把第二个dom元素的动态内容({{ goal }} - {{ index }})复制到第一个dom元素…

Logback日志框架(超详细)

logback-classic-1.2.3.jarhttp://链接: https://pan.baidu.com/s/1cA3gVB_6DEA-cSFJN6MDGw 提取码: sn8i 复制这段内容后打开百度网盘手机App,操作更方便哦 logback-core-1.2.3.jarhttp://链接: https://pan.baidu.com/s/19eCsvsO72a9PTqpXvXxrgg 提取码: 5yp…

JHY-31复合电压继电器 额定电压Un=110VDC 板后接线 JOSEF约瑟

用途: JHY-31复合电压继电器使用于电力系统的继电保护线路中,作为各种类型故障的判别元件和电压闭锁元件。 继电器型号名称: 例:辅助直流工作电压为110V的复合电压继电器的订货代号为: JHY-31/110V。 工作原理: 继电器内部具有负…

云架构(二) 大使模式

Ambassador pattern (https://learn.microsoft.com/en-us/azure/architecture/patterns/ambassador) 简单描述 创建一个助手服务,这个服务代表消费服务或者应用程序发送网络请求。大使服务可以看做是与客户机同一个位置的进程外代理。 这种…

【JDK常用的API】包装类

🍬 博主介绍👨‍🎓 博主介绍:大家好,我是 hacker-routing ,很高兴认识大家~ ✨主攻领域:【渗透领域】【应急响应】 【Java】 【VulnHub靶场复现】【面试分析】 🎉点赞➕评论➕收藏 …

微服务(基础篇-007-RabbitMQ)

目录 初识MQ(1) 同步通讯(1.1) 异步通讯(1.2) MQ常见框架(1.3) RabbitMQ快速入门(2) RabbitMQ概述和安装(2.1) 常见消息模型(2.2) 快速入门&#xff…

精品丨PowerBI负载测试和容量规划

当选择Power BI作为业务报表平台时,如何判断许可证的选择是否符合业务需求,价格占了主导因素。 Power BI的定价是基于SKU和服务器内核决定的,但是很多IT的负责人都不确定自己公司业务具体需要多少。 不幸的是,Power BI的容量和预期…

短剧App开发:打造移动端的精彩剧情盛宴

在快节奏的生活中,人们对于娱乐内容的需求日益旺盛,短剧作为一种新兴的影视形式,以其紧凑的剧情、生动的表演和精彩的情节,受到了广大观众的喜爱。为了满足广大用户对短剧内容的渴望,我们倾力打造了一款全新的短剧App&…

02_在VM虚拟机创建Win7系统

一、镜像 Windows 7 Ultimate with Service Pack 1 (x64) - DVD (Chinese-Simplified) 二、新建虚拟机 选择下载的win7系统镜像,.ISO结尾的文件。 选择系统版本 选择名称和位置

概率论经典题目-二维随机变量及分布--求离散型的联合分布律和边缘分布律问题

题目:一整数N等可能地在1,2,3,…,10十个值中取一个值设DD(N)是能整除N的正整数的个数,FF(N)是能整除N的素数的个数(注意1不是素数).试写出D和F的联合分布律,并求边缘分布律? 解答: 1)要确定整数 N 能够被整除的正整数个数 D 和素…

线上废品回收小程序开发,线上回收成为大众“新宠”

随着全球回收意识的提高,废品回收已经成为了一个热门话题,在可持续发展下,回收市场领域有着巨大的发展前景。 如今,回收市场也进入到了互联网潮流中,互联网和数字化技术的发展对回收行业的发展起到了很大推动作用。回…

【Go】三、Go指针

文章目录 1、指针2、说明 1、指针 &符号变量 就可以获取这个变量内存的地址*int 是一个指针类型 (可以理解为 指向int类型的指针) package main import("fmt" ) func main(){var age int 18//&符号变量 就可以获取这个变量内存的地…

聚观早报 | 小米SU7正式发布;xAI推出Grok-1.5

聚观早报每日整理最值得关注的行业重点事件,帮助大家及时了解最新行业动态,每日读报,就读聚观365资讯简报。 整理丨Cutie 3月30日消息 小米SU7正式发布 xAI推出Grok-1.5 红魔9 Pro新品亮相 长城汽车2023年营收 快狗打车2023年度业绩 小…

UWB辅助RTK如何应对极端环境

1.UWB定位 - UWB(Ultra-Wideband)是一种无线通信技术,其特点是具有较宽的频带,可以提供0.1-0.5m高精度的距离测量。 - UWB定位需要四台基站(每台基站视距间隔50-100米)呈矩形安装部署,以实现…

springboot婚庆系统

摘 要 随着科学技术的飞速发展,各行各业都在努力与现代先进技术接轨,通过科技手段提高自身的优势;对于婚庆系统当然也不能排除在外,随着网络技术的不断成熟,带动了婚庆系统,它彻底改变了过去传统的管理方式…

vue3+vite 模板vue3-element-admin框架如何关闭当前页面跳转 tabs

使用模版: 有来开源组织 / vue3-element-admin 需要关闭的.vue 页面增加以下方法 //setup 里import {LocationQuery, useRoute, useRouter} from "vue-router"; const router useRouter(); function close() {console.log(|--router.currentRoute.value, router.cur…

五、postman基础使用案例

postman基础使用 相关案例【传递查询参数】【提交表单数据】【提交JSON数据】 注:postman⼀款⽀持调试和测试的⼯具,开发、测试⼯程师都可以使⽤。方法一般统一为:方法→请求头→请求体→断言 相关案例 【传递查询参数】 访问TPshop搜索商品的…

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 密码&…

基于springboot+vue实现的养老服务管理系统

作者主页:Java码库 主营内容:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 技术选型 【后端】:Java 【框架】:spring…

【考研数学】《660题》 和《1800 题》完美搭配方法

别等二战才搞懂! 学长我23年二战143,逆袭上岸211! 但是我一战数学83,总分没过线,一战就用的1800660,当时刷1800的时候整个人都麻了。二战通过调整刷题方法,才顺畅的把基础打牢。⚠️ 660建议全…