前置知识

Fastjson 是一个 Java 库,可以将 Java 对象转换为 JSON 格式,当然它也可以将 JSON 字符串转换为 Java 对象。

Fastjson 可以操作任何 Java 对象,即使是一些预先存在的没有源码的对象(通过远程调用的方式)

  1. //序列化
  2. String text = JSON.toJSONString(obj);
  3. //反序列化
  4. VO vo = JSON.parse(); //解析为JSONObject类型或者JSONArray类型
  5. VO vo = JSON.parseObject("{...}"); //JSON文本解析成JSONObject类型
  6. VO vo = JSON.parseObject("{...}", VO.class); //JSON文本解析成VO.class类

对象转字符串(序列化)

实体类User

  1. package org.example;
  2. public class User {
  3. public int id;
  4. public String name;
  5. public int age;
  6. public User() {
  7. }
  8. public User(int id, String name, int age) {
  9. this.id = id;
  10. this.name = name;
  11. this.age = age;
  12. }
  13. @Override
  14. public String toString() {
  15. return "User{" +
  16. "id=" + id +
  17. ", name='" + name + '\'' +
  18. ", age=" + age +
  19. '}';
  20. }
  21. public int getId() {
  22. return id;
  23. }
  24. public void setId(int id) {
  25. this.id = id;
  26. }
  27. public String getName() {
  28. return name;
  29. }
  30. public void setName(String name) {
  31. this.name = name;
  32. }
  33. public int getAge() {
  34. return age;
  35. }
  36. public void setAge(int age) {
  37. this.age = age;
  38. }
  39. }

定义一个测试类

  1. package org.example;
  2. import org.example.User;
  3. import com.alibaba.fastjson.JSON;
  4. import com.alibaba.fastjson.serializer.SerializerFeature;
  5. public class Test {
  6. public static void main(String[] args) {
  7. User user = new User();
  8. user.setId(1);
  9. user.setName("zhangsan");
  10. user.setAge(18);
  11. //对象转字符串
  12. String s1 = JSON.toJSONString(user);
  13. String s2 = JSON.toJSONString(user, SerializerFeature.WriteClassName);
  14. System.out.println(s1);
  15. System.out.println(s2);
  16. }
  17. }

输出结果

  1. {"age":18,"id":1,"name":"zhangsan"}
  2. {"@type":"org.example.User","age":18,"id":1,"name":"zhangsan"}

字符串转对象(反序列化)

  1. package org.example;
  2. import org.example.User;
  3. import com.alibaba.fastjson.JSON;
  4. import com.alibaba.fastjson.JSONObject;
  5. import com.alibaba.fastjson.serializer.SerializerFeature;
  6. public class fastjsonTest {
  7. public static void main(String[] args) {
  8. User user = new User();
  9. user.setId(1);
  10. user.setName("zhangsan");
  11. user.setAge(18);
  12. //对象转字符串
  13. String s1 = JSON.toJSONString(user);
  14. String s2 = JSON.toJSONString(user, SerializerFeature.WriteClassName);
  15. System.out.println(s1);
  16. System.out.println(s2);
  17. System.out.println("s1==========================s1");
  18. //字符串转对象
  19. Object o1 = JSON.parse(s1);
  20. JSONObject jo1 = JSON.parseObject(s1);
  21. User user1 = JSON.parseObject(s1, User.class);
  22. System.out.println(o1);
  23. System.out.println(jo1);
  24. System.out.println(user1);
  25. System.out.println("s2=========================s2");
  26. Object o2 = JSON.parse(s2);
  27. JSONObject jo2 = JSON.parseObject(s2);
  28. User user2 = JSON.parseObject(s2, User.class);
  29. System.out.println(o2);
  30. System.out.println(jo2);
  31. System.out.println(user2);
  32. }
  33. }

输出结果

  1. {"age":18,"id":1,"name":"zhangsan"}
  2. {"@type":"org.example.User","age":18,"id":1,"name":"zhangsan"}
  3. s1==========================s1
  4. {"name":"zhangsan","id":1,"age":18}
  5. {"name":"zhangsan","id":1,"age":18}
  6. User{id=1, name='zhangsan', age=18}
  7. s2=========================s2
  8. User{id=1, name='zhangsan', age=18}
  9. {"name":"zhangsan","id":1,"age":18}
  10. User{id=1, name='zhangsan', age=18}

fastjson通过JSON.toJSONString()将对象转为字符串(序列化),当使用SerializerFeature.WriteClassName参数时会将对象的类名写入@type字段中,在重新转回对象时会根据@type来指定类,进而调用该类的setget方法。因为这个特性,我们可以指定@type为任意存在问题的类,造成一些问题

利用

漏洞是利用fastjson autotype在处理json对象的时候,未对@type字段进行完全的安全性验证,攻击者可以传入危险类,并调用危险类连接远程rmi主机,通过其中的恶意类执行代码。攻击者通过这种方式可以实现远程代码执行漏洞的利用,获取服务器的敏感信息泄露,甚至可以利用此漏洞进一步对服务器数据进行修改,增加,删除等操作,对服务器造成巨大的影响。

set,get,is自动调用问题

构造Evil类

  1. package org.example;
  2. public class Evil {
  3. private String cmd;
  4. public Evil(){
  5. System.out.println("Evil()"+ this.hashCode());
  6. }
  7. public String getCmd() {
  8. System.out.println("getCmd()"+this.hashCode());
  9. return cmd;
  10. }
  11. public void setCmd(String cmd) {
  12. System.out.println("setCmd"+this.hashCode());
  13. this.cmd = cmd;
  14. }
  15. }

写一个test测试下

  1. package org.example;
  2. import com.alibaba.fastjson.JSON;
  3. public class Test {
  4. public static void main(String[] args) {
  5. String evil = "{\"@type\":\"org.example.Evil\",\"cmd\":\"calc\"}";
  6. JSON.parse(evil);
  7. System.out.println("-------------------");
  8. JSON.parseObject(evil);
  9. System.out.println("------------------");
  10. JSON.parseObject(evil, Object.class);
  11. }
  12. }

跟进parseObject(evil)发现其方法发现也是使用parse解析的,但是多了一个(JSONObject)toJSON(obj)

这个方法调用的get,堆栈如下

  1. getCmd:11, Evil (org.example)
  2. invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
  3. invoke:62, NativeMethodAccessorImpl (sun.reflect)
  4. invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
  5. invoke:498, Method (java.lang.reflect)
  6. get:451, FieldInfo (com.alibaba.fastjson.util)
  7. getPropertyValue:105, FieldSerializer (com.alibaba.fastjson.serializer)
  8. getFieldValuesMap:439, JavaBeanSerializer (com.alibaba.fastjson.serializer)
  9. toJSON:902, JSON (com.alibaba.fastjson)
  10. toJSON:824, JSON (com.alibaba.fastjson)
  11. parseObject:206, JSON (com.alibaba.fastjson)
  12. main:13, Test (org.example)

那么setter在哪调用的?

com.alibaba.fastjson.util.JavaBeanInfo#build

在通过@type拿到类之后,通过反射拿到该类所有的方法存入methods,接下来遍历methods进而获取get、set方法,如上图。总结set方法自动调用的条件为:

  1. 方法名长度大于4
  2. 非静态方法
  3. 返回值为void或当前类
  4. 方法名以set开头
  5. 参数个数为1

当满足条件之后会从方法名截取属性名,截取时会判断_,如果是set_name会截取为name属性,具体逻辑如下:

当截取完但是找不到这个属性

会判断传入的第一个参数类型是否为布尔型,是的话就在截取完的变量前加上is,截取propertyName的第一个字符转大写和第二个字符,并且然后重新尝试获取属性字段。

比如:public boolean setBoy(boolean t) 会寻找isBoy字段。

set的整个判断就是:如果有setCmd()会绑定cmd属性,如果该类没有cmd属性会绑定isCmd属性。

get的判断

总结下就是:

  1. 方法名长度大于等于4
  2. 非静态方法
  3. 以get开头且第4个字母为大写
  4. 无传入参数
  5. 返回值类型继承自Collection Map AtomicBoolean AtomicInteger AtomicLong

当程序绑定了对应的字段之后,如果传入json字符串的键值中存在这个值,就会去调用执行对应的setter、构造方法

小结:

  1. parse(jsonStr) 构造方法+Json字符串指定属性的setter()+特殊的getter()
  2. parseObject(jsonStr) 构造方法+Json字符串指定属性的setter()+所有getter() 包括不存在属性和私有属性的getter()
  3. parseObject(jsonStr,Object.class) 构造方法+Json字符串指定属性的setter()+特殊的getter()

Fastjsonfan反序列化(一)的更多相关文章

  1. C#反序列化XML异常:在 XML文档(0, 0)中有一个错误“缺少根元素”

    Q: 在反序列化 Xml 字符串为 Xml 对象时,抛出如下异常. 即在 XML文档(0, 0)中有一个错误:缺少根元素. A: 首先看下代码: StringBuilder sb = new Stri ...

  2. C# 序列化与反序列化几种格式的转换

    这里介绍了几种方式之间的序列化与反序列化之间的转换 首先介绍的如何序列化,将object对象序列化常见的两种方式即string和xml对象; 第一种将object转换为string对象,这种比较简单没 ...

  3. 迟来的Json反序列化

    源码发布 搞了一个下午,终于搞定了这个号称中国的github...以后源码直接在这里发布了(github实在用不来,英文实在太烂了) https://code.csdn.net/jy02305022/ ...

  4. .Net使用Newtonsoft.Json.dll(JSON.NET)对象序列化成json、反序列化json示例教程

    JSON作为一种轻量级的数据交换格式,简单灵活,被很多系统用来数据交互,作为一名.NET开发人员,JSON.NET无疑是最好的序列化框架,支持XML和JSON序列化,高性能,免费开源,支持LINQ查询 ...

  5. 使用Newtonsoft.Json.dll(JSON.NET)动态解析JSON、.net 的json的序列化与反序列化(一)

    在开发中,我非常喜欢动态语言和匿名对象带来的方便,JSON.NET具有动态序列化和反序列化任意JSON内容的能力,不必将它映射到具体的强类型对象,它可以处理不确定的类型(集合.字典.动态对象和匿名对象 ...

  6. 【.NET深呼吸】如何反序列化动态JSON

    .net本身除了支持SOAP.XML.二进制等序列化和反序列化,后来也加入了对JSON的序列化的支持.然而,在实际开发中,常常会遇到结构不确定的JSON对象,这些对象可能是其他代码动态生成的,你事先无 ...

  7. Java 序列化与反序列化

    1.什么是序列化?为什么要序列化? Java 序列化就是指将对象转换为字节序列的过程,而反序列化则是只将字节序列转换成目标对象的过程. 我们都知道,在进行浏览器访问的时候,我们看到的文本.图片.音频. ...

  8. C#中怎样实现序列化和反序列化

    我们想要将数据进行持久化的操作的话,也就是将数据写入到文件中,我们在C#中可以通过IO流来操作,同时也可以通过序列化来操作,本人是比较推荐使用序列化操作的 因为我们如果想要将一个对象持久化到文件中 如 ...

  9. Java序列化与反序列化

    Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java序列化与反序列化?本文围绕这些问题进行了探讨. 1.Java序列化与反序列化 Java序列化是指把Java对象转换为字节序列 ...

  10. 让Visual Studio 2013为你自动生成XML反序列化的类

    Visual Sutdio 2013增加了许多新功能,其中很多都直接提高了对代码编辑的便利性.如: 1. 在代码编辑界面的右侧滚动条上显示不同颜色的标签,让开发人员可以对所编辑文档的修改.查找.定位情 ...

随机推荐

  1. CentOS7部署FastDFS+nginx模块

    软件下载 # 已经事先把所需软件下载好并上传到/usr/local/src目录了 https://github.com/happyfish100/libfastcommon/archive/V1.0. ...

  2. 使用python连接elasticsearch

    官方文档地址:https://www.elastic.co/guide/en/elasticsearch/client/python-api/current/overview.html 安装的时候注意 ...

  3. 在CentOS 8服务器上搭建FastDFS环境

    什么是FastDFS? 这里,我就摘录下百度百科上对于FastDFS的描述. FastDFS是一个开源的轻量级分布式文件系统,它对文件进行管理,功能包括:文件存储.文件同步.文件访问(文件上传.文件下 ...

  4. Failed to find a valid digest in the 'integrity' attribute for resource

    一.Bootstrap  引入报错 在使用bootstrap过程中发现无法使用下拉导航栏,或者是显示不出效果. Failed to find a valid digest in the 'integr ...

  5. 计算机网络(Learning Records)

    背景:没想到本专业并不开设这门课程,感觉过于逆天,之前开发的时候了解过相关知识 但是从来没有系统地学过,就自己看了书,总结一下 参考:<TCP/IP详解 卷1:协议> 概述 大多数网络应用 ...

  6. you-get安装及使用

    you-get安装及使用 1.安装python 下载地址:https://www.python.org/downloads/ 配置环境变量:我的电脑 --> 属性 --> 高级系统设置 - ...

  7. Pycharm安装使用

    目录 使用pycharm软件 配置调整 下载链接地址:https://www.jetbrains.com/pycharm/download/#section=windows 根据自己的系统需要安装对应 ...

  8. Vue中使用Switch开关用来控制商品的上架与下架情况、同时根据数据库商品的状态反应到前台、前台修改商品状态保存到数据库

    一般后台对商品的信息管理.包含商品的上架与下架.为了提高用户的体验.将商品上下架的操作做成开关的形式.同时后台数据库中保存的商品状态能够根据开关状态改变. 1.效果展示 这种效果:== 当开关是开启状 ...

  9. Vue学习之--------组件的基本使用(非单文件组件)(代码实现)(2022/7/22)

    文章目录 1.为啥要使用组件 2.基本使用 3.代码实例 4.测试效果 5.注意点 1.为啥要使用组件 好用啊.像堆积木一样 2.基本使用 Vue中使用组件的三大步骤: 一.定义组件(创建组件) 二. ...

  10. 靶机: medium_socnet

    靶机: medium_socnet 准备工作 需要你确定的事情: 确定 kali 已经安装,并且能正常使用[本文不涉及 kali 安装配置] VirtualBox 以前能正常导入虚拟文件 ova 能正 ...