fastjson-流程分析
参考视频:fasfjson反序列化漏洞1-流程分析
分析版本
fastjson1.2.24
JDK 8u65
分析过程
新建Person类
public class Person {private String name;private int age;public Person() {System.out.println("constructor_0");}public Person(String name, int age) {this.name = name;this.age = age;System.out.println("constructor_2");}public String getName() {System.out.println("getName");return name;}public void setName(String name) {this.name = name;System.out.println("setName");}public int getAge() {System.out.println("getAge");return age;}public void setAge(int age) {this.age = age;System.out.println("setAge");}
}
新建JSONTest
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;public class JSONTest {public static void main(String[] args) throws Exception {String s = "{\"@type\":\"Person\",\"age\":18,\"name\":\"tttt\"}";JSONObject jsonObject = JSON.parseObject(s);System.out.println(jsonObject);}
}

发现parseObject(s)过程还调用了get方法。详细的过程可以跟一下上面视频。
分析下fastjson的JSON.parseObject(s);逻辑
主要逻辑在DefaultJSONParser的parse方法
public static Object parse(String text, int features) {if (text == null) {return null;}DefaultJSONParser parser = new DefaultJSONParser(text, ParserConfig.getGlobalInstance(), features);Object value = parser.parse(); //主要的逻辑在这儿parser.handleResovleTask(value);parser.close();return value;
}
parse()先进行字符串的匹配
case LBRACE: //匹配到左大括号JSONObject object = new JSONObject(lexer.isEnabled(Feature.OrderedField));return parseObject(object, fieldName);
之后进入parseObject
key是@type,进入此循环,fastjson会尝试将字符串反序列化为输入的@type类。可以看到进入循环之后会调用loadCLass方法,加载类

TypeUtils.loadClass对输入进行了预处理,不处理的话loadClass默认是不能加载数组类的

加载完类之后,继续往下跟。到下面的位置会进行反序列化,跟进去

public ObjectDeserializer getDeserializer(Type type) {ObjectDeserializer derializer = this.derializers.get(type); //首先查看有没有符合条件的默认的反序列化器,我们自己写的类,肯定是返回nullif (derializer != null) {return derializer;}if (type instanceof Class<?>) {return getDeserializer((Class<?>) type, type); //之后进入这个方法}if (type instanceof ParameterizedType) {Type rawType = ((ParameterizedType) type).getRawType();if (rawType instanceof Class<?>) {return getDeserializer((Class<?>) rawType, type);} else {return getDeserializer(rawType);}}return JavaObjectDeserializer.instance;
}
getDeserializer((Class<?>) type, type);方法中,找不到符合条件的反序列化器,则把传入的默认当作JavaBean。

在createJavaBeanDeserializer中又调用到了JavaBeanInfo beanInfo = JavaBeanInfo.build(clazz, type, propertyNamingStrategy);
通过这个build方法去获取Person的信息,从而创建Person的反序列化器。
这里不详细写了
下面三个循环,第一个寻找public的set方法,第二个寻找public的属性,第三个寻找public的get方法(如果有了对应的set方法,那么这里不在创建get方法)

fastjson还有一个设定是,如果找到了某个属性的set方法,那么get方法就不再add。这个操作是在最后一个循环的下面这里实现的。

这里要说一下根据上面分析,如果针对某个属性只有getter方法,则会创建getter方法,但是fastjson对getter方法的返回值做了判断,需要满足下面条件

之后我们就拿到了需要的反序列化器(这有个关于debug的问题,大家看视频吧,这儿就不写了,更新了Person类)
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//import java.util.Map;public class Person {private String name;private int age;private Map map;public Person() {System.out.println("constructor_0");}public Person(String name, int age) {this.name = name;this.age = age;System.out.println("constructor_2");}public String getName() {System.out.println("getName");return this.name;}public void setName(String name) {this.name = name;System.out.println("setName");}public int getAge() {System.out.println("getAge");return this.age;}public void setAge(int age) {this.age = age;System.out.println("setAge");}public Map getMap() {System.out.println("getMap");return this.map;}
}
下面可以跟一下反序列化器JavaBeanDeserializer中,是如何调用构造函数,set和get方法的。
在反序列化器JavaBeanDeserializer中,只会调用setAge和setName。不会调用getAge和getName方法(上面讲了原因)和getMap(这是因为在JavaBeanDeserializer中做了判断)
} else if (fieldClass == float[][].class) { //上面还有很多类型的判断,但是没有Map类,所以这里为假fieldValue = lexer.scanFieldFloatArray2(name_chars);if (lexer.matchStat > 0) {matchField = true;valueParsed = true;} else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {continue;}
} else if (lexer.matchField(name_chars)) { //检查map是否在JSON中matchField = true;
} else {continue;
}
我们想要输出getMap改一下JSON就行了。String s = "{\"@type\":\"Person\",\"age\":18,\"name\":\"tttt\",\"map\":{}}";这样就能输出getMap了。
剩下的getAge和getName是在JSON.toJSON(obj);中完成输出的。
///JSON
public static JSONObject parseObject(String text) {Object obj = parse(text);if (obj instanceof JSONObject) {return (JSONObject) obj;}return (JSONObject) JSON.toJSON(obj);
}
///JSON
if (serializer instanceof JavaBeanSerializer) {JavaBeanSerializer javaBeanSerializer = (JavaBeanSerializer) serializer;JSONObject json = new JSONObject();try {Map<String, Object> values = javaBeanSerializer.getFieldValuesMap(javaObject);for (Map.Entry<String, Object> entry : values.entrySet()) {json.put(entry.getKey(), toJSON(entry.getValue()));}} catch (Exception e) {throw new JSONException("toJSON error", e);}return json;
}
利用
下面弹个计算器试试
一、注意类里面都没有定义map这个属性,但是因为fastjson是按set和get等方法寻找属性的,所以并不影响。
要注意setMap中参数必须为1,否则fastjson会报错
public class Test {public void setMap(String map) throws IOException {Runtime.getRuntime().exec("calc");}
}
public class JSONTest {public static void main(String[] args) throws Exception {String s = "{\"@type\":\"Test\",\"map\":\"aaaa\"}";JSONObject jsonObject = JSON.parseObject(s);System.out.println(jsonObject);}
}
二、get方法注意不能有参数
public class Test {public Map getMap() throws IOException { //如果返回类型改为int的话,需要在JSON语句中加入map的赋值,否则不会执行get方法。这样做程序可以在toJSON中执行get方法Runtime.getRuntime().exec("calc");return new HashMap();}
}
public class JSONTest {public static void main(String[] args) throws Exception {String s = "{\"@type\":\"Test\"}";JSONObject jsonObject = JSON.parseObject(s);System.out.println(jsonObject);}
}
如果getMap返回类型是Map,而且JSON中还给map赋值了。那么会运行两次getMap(我的Test类里面没有setMap方法)
第一次是在形成反序列化器时
第二次是在toJSON中。
相关文章:
fastjson-流程分析
参考视频:fasfjson反序列化漏洞1-流程分析 分析版本 fastjson1.2.24 JDK 8u65 分析过程 新建Person类 public class Person {private String name;private int age;public Person() {System.out.println("constructor_0");}public Person(String na…...
Linux 命令安装
系列文章目录 提示:仅用于个人学习,进行查漏补缺使用。 1.Linux介绍、目录结构、文件基本属性、Shell 2.Linux常用命令 3.Linux文件管理 4.Linux 命令安装 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助…...
清华和字节联合推出的视频理解大模型video-SALMONN(ICML 2024)
video-SALMONN: Speech-Enhanced Audio-Visual Large Language Models 论文信息 paper:https://arxiv.org/abs/2406.15704 code:https://github.com/bytedance/SALMONN/ AI也会「刷抖音」!清华领衔发布短视频全模态理解新模型 | ICML 2024 …...
从数据爬取到可视化展示:Flask框架与ECharts深度解析
目录 🔹 Flask框架源码解析 Flask应用初始化路由与视图函数请求与响应中间件 🔹 ECharts可视化精讲 ECharts安装与配置基本图表类型图表样式与交互高级图表配置与数据动态更新实战:结合Flask与ECharts展示爬取数据 Flask框架源码解析 &…...
【jvm】类加载分几步
目录 1. 加载(Loading)2. 链接(Linking)2.1 验证(Verification)2.2 准备(Preparation)2.3 解析(Resolution) 3. 初始化(Initialization࿰…...
使用Apache http client发送json数据(demo)
POM依赖 : <dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.12</version></dependency><dependency><groupId>com.alibaba</groupId&g…...
读零信任网络:在不可信网络中构建安全系统07设备信任
1. 设备信任 1.1. 在零信任网络中建立设备信任至关重要,这也是非常困难的一个环节 1.2. 建立设备信任是基石,直接影响零信任网络架构的成败 1.3. 大多数网络安全事件都和攻击者获得信任设备的控制权相关,这种情况一旦发生,信任…...
【Java算法专场】前缀和(下)
目录 和为 K 的子数组 算法分析 算法步骤 算法代码 算法示例 和可被 K 整除的子数组 算法分析 同余定理 负数取余 算法步骤 算法代码 算法示例 连续数组 算法分析 算法步骤 算法代码 算法示例 矩阵区域和 算法分析 算法步骤 算法代码 算法示例 算法分析 …...
音视频相关文章总目录
为了方便各位观看,本文置顶,以目录形式汇集我写过的大部分音视频专题文章。之后文章更新,本目录也会同步更新。写得不好和零零散散的文章就不放在这里了😅 : 音视频入门基础:像素格式专题系列文章&#x…...
7月31日MySQL学习笔记
今日内容: mysql: 行列转换 数据类型 函数 触发器 存储过程 事务 索引(还没讲) 三范式 JDBC连接数据库的6个步骤 三握四挥 行列转换 第一步 新建要转换的列 select name, 1 as 语文, 1 as 数学, 1 as 英语 from t_score GROUP BY name 第二步 对每一列填入值…...
什么是容器查询?分享 1 段优质 CSS 代码片段!
本内容首发于工粽号:程序员大澈,每日分享一段优质代码片段,欢迎关注和投稿! 大家好,我是大澈! 本文约 700 字,整篇阅读约需 1 分钟。 今天分享一段优质 CSS 代码片段,使用容器查询…...
【linux深入剖析】初识线程---线程概念
🍁你好,我是 RO-BERRY 📗 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 🎄感谢你的陪伴与支持 ,故事既有了开头,就要画上一个完美的句号,让我们一起加油 目录 1. Linux线程概念什么是线…...
【MySQL】索引——索引的引入、认识磁盘、磁盘的组成、扇区、磁盘访问、磁盘和MySQL交互、索引的概念
文章目录 MySQL1. 索引的引入2. 认识磁盘2.1 磁盘的组成2.2 扇区2.3 磁盘访问 3. 磁盘和MySQL交互4. 索引的概念4.1 索引测试4.2 Page4.3 单页和多页情况 MySQL 1. 索引的引入 海量表在进行普通查询的时候,效率会非常的慢,但是索引可以解决这个问题。 -…...
python部署flask项目
python部署flask项目 1. 准备服务器2. 设置服务器环境3. 创建虚拟环境并安装项目依赖4. 配置Gunicorn5. 配置Nginx6. 设置Supervisor(可选)7. 测试部署 将Flask项目部署到服务器的流程大致如下: 1. 准备服务器 首先,需要准备一台…...
数据建模标准-基于事实建模
前情提要 数据模型定义 DAMA数据治理体系中将数据模型定义为一种文档形式,数据模型是用来将数据需求从业务传递到IT,以及在IT内部从分析师、建模师和架构师到数据库设计人员和开发人员的主要媒介; 作用 记录数据需求和建模过程中产生的数据定义&…...
量产部落SM2258XT开卡软件,SM2258XT主控128G SSD固态卡死修复
故障现象:连接此固态硬盘后电脑就会卡死,拔掉重新连接概率性显示盘符,显示了之后也不能正常操作,一点击打开,电脑就立马卡死。 解决过程:下载了很多款量产工具,都不能开卡成功,点击…...
《零散知识点 · 自定义 HandleMapping》
📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗 🌻 CSDN入驻不久,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数…...
谈谈我对微服务的理解2.0
文章目录 一、引出问题二、微服务2-1、微服务的技术2-2、微服务的目的 三、微服务的拆分四、不连表查询五、微服务的好处六、微服务的坏处七、应付当下 这篇文章原本叫《如何做到不连表查询》,因为我对这个事一直耿耿于怀。在上家公司我经常被连表折磨(连…...
ECCV 2024前沿科技速递:GLARE-基于生成潜在特征的码本检索点亮低光世界,低光环境也能拍出明亮大片!
在计算机视觉与图像处理领域,低光照条件下的图像增强一直是一个极具挑战性的难题。暗淡的光线不仅限制了图像的细节表现,还常常引入噪声和失真,极大地影响了图像的质量和可用性。然而,随着ECCV 2024(欧洲计算机视觉会议…...
前端低代码必备:FrontendBlocks 4.0版本重磅发布,助力Uniapp-X原生APP开发
项目介绍 本软件是一款强大的所见即所得前端页面设计器,是低代码开发领域的基础设施,生成的代码不依赖于任何框架,实测可以将前端布局工作的耗时减少80%以上,最关键的是,它实现了人人都可以写前端页面的梦想。 不用写…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...
Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...
USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...
