Fastjson基础环境配置与Java基础概念

fastjson,java · 浏览次数 : 0

小编点评

本文将从 Java 基础语法入手,逐步深入探讨 Fastjson 反序列化漏洞,并带领读者从零基础开始,最终成为能够熟练利用 Fastjson 的网络安全专家。 **环境配置** - **IDE**: IntelliJ IDEA 2024.1.3 或更高版本 **Java 项目目录结构** - `src/main/java/`: 存放主要 Java 源代码 - `src/test/java/`: 存放测试代码 - `src/test/resources/`: 存放测试时需要的资源文件 - `test-config.properties`: 测试环境的配置文件 - `test-data.xml`: 测试数据文件 **Fastjson Demo** 1. 定义一个名为 `Computer` 的静态类,包含 `computerName` 和 `ramSize` 字段。 2. 使用 `@JSONField(name = "dkSize")` 注解指定 `dkSize` 属性与 `diskSize` 相关联。 3. 在主函数中,创建 `macBookAir` 对象并将其序列化为 JSON 字符串。 4. 反序列化一个 JSON 字符串,将其转换为 `Computer` 对象,并输出相关信息。 **Fastjson 映射机制** 1. **字段名匹配**: 默认采用字段名匹配方式,将 JSON 中的键与 Java 对象的属性进行映射。 2. **注解方式**: 如果 JSON 中的字段名无法与 Java 对象的属性名对应,可使用注解建立映射关系。 **进阶学习** - **@JSONType**: 设置属性的序列化顺序,使其按照属性在类中的声明顺序生成 JSON 字符串。 通过本文的学习和实践,读者将掌握 Java 和 Fastjson 的基础知识和高级特性,为成为一名合格的网络安全专家打下坚实的基础。

正文

Preface

此篇系列文章将会从 Java 的基础语法开始,以 Fastjson 的各个反序列化漏洞分析为结尾,详细记录如何从一个具有基础面向对象编程但毫无 Java 基础的小白成长为了解 Fastjson 的各个漏洞并能够熟练利用的网络安全人员。

环境配置

我们使用 IDEA 作为开发的 IDE(社区版或专业版均可,我使用的是IDEA 2024.1.3版本)。

打开 IDEA ,新建项目,按下图设置项目名称、构建系统、以及JDK。

不了解 Java 的同学此时会问,Maven是什么?

什么是Maven?

Maven 是一个广泛运用于 Java 项目中的管理工具,它通过一个标准的项目结构和一套定义良好的生命周期来简化项目的构建、依赖管理和发布过程。Maven 的主要功能包括项目构建、依赖管理、项目报告和文档生成等。

我们在此引用 Maven 主要是能够快速地将 Fastjson 引用到我们的项目中。Maven 通过 POM (Project Object Model) 这一核心文件来定义项目的基本信息、依赖关系、构建命令以及插件管理。而 POM 则是以 XML 的格式来指定项目的各个方面。

  • <groupId>: 项目组的唯一标识。

  • <artifactId>: 项目的唯一标识。

  • <version>: 项目的版本号。

那么接下来我们就要通过 Maven 引入 Fastjson,通过将以下代码加入到 pom.xml ,在 IDEA 的右侧边栏单击 Maven 的图标,刷新Maven 既可将 Fastjson 的指定版本引入项目。

Java的项目目录结构

在通过 Maven 构建项目后,项目下会自动生成一些目录,标准的项目目录结构不仅使项目更容易理解和管理,也能更好地支持各种构建工具和 IDE。

  • src/

    • src 目录用于存放项目的主要源代码文件,通常遵循包结构,典型的目录组织如下:

    • src/main/java/:存放主要的 Java 源代码。

      • org/example/:按包名组织的源代码文件。比如我们的包名是 org.example,对应的目录结构会是 org/example/。其虽然不会在 IDEA 中这么显示,但是在实际的文件系统目录中是这样组织的。
  • test/

    • test 目录用于存放测试代码,目录结构与 src 类似,但用于存放单元测试和集成测试代码。

    • src/test/java/:存放测试代码。

      • org/example/:按包名组织的测试代码文件。
    • src/test/resources/:存放测试时需要的资源文件。

      • test-config.properties:测试环境的配置文件。
      • test-data.xml:测试数据文件。

下图通过创建一个名为 org.example 的包,在其中添加一个名为 Main 的类,在其中创建一个名为 main 的方法,调用 Java 本身的标准输出函数将 HelloWorld 输出到屏幕。

我们可以来简要分析一下下面的代码。

package org.example;

public class Main {
    public static void main(String[] args){
        System.out.println("Hello World!");
    }
}

Main类,通过 package 定义该类处于 org.example 包中,在 Java 中每个 .java 文件只能有一个 public 类,且该类名需要与 .java 的文件名相一致。

Java 程序的入口点是一个具有特定样式的 main 方法:public static void main(String[] args),这个方法会是 JVM 启动时首先调用的方法。其 :

  • public:表示方法是公开的,JVM 可以从任何地方调用它。
  • static:表示方法是静态的,不需要创建类的实例就可以调用。
  • void:表示方法不返回任何值。
  • main:方法的名称,JVM 识别的入口点。
  • String[] args:表示接受一个字符串数组,一般用于传递命令行参数。
  • System.out.println("Hello World!")
    • System 是 Java 标准库中的一个类,属于 java.lang 包,无需导入就可以直接使用。
      • 它提供了一些标准输出与输入、错误输出等方法。
    • outSystem 类中的一个静态字段,在 JVM 启动时,它是PrintStream 实例化的对象,连接到控制台。
    • println()PrintStream 的一个方法,是重载的,可以打印不同类型的数据。

Fastjson Demo

在拥有了上面的基础知识后,我们可以开始写一个 fastjson 的 Demo 了。代码如下。

package org.example;
import com.alibaba.fastjson.JSON;

public class FastJsonDemo {
    public static void main(String[] args){
        // 将一个Java对象序列化为字符串
        Computer macBookAir = new Computer("RichardLuo's Macbook Air", 16384);
        String preSend = JSON.toJSONString(macBookAir);
        System.out.println(preSend);

        // 将一个字符串反序列化为Java对象
        String preReceive = "{\"computerName\":\"RichardLuo's Macbook Pro\",\"ramSize\":\"8192\"}";
        Computer macBookPro = JSON.parseObject(preReceive,Computer.class);
        System.out.println(macBookPro.getComputerName() + " with " + macBookPro.getRamSize());
    }

    public static class Computer{
        private String computerName;
        private int ramSize;
        public Computer(String computerName, int ramSize){
            this.computerName = computerName;
            this.ramSize = ramSize;
        }
        public String getComputerName(){
            return computerName;
        }
        public String getRamSize(){
            return Integer.toString(ramSize);
        }
    }
}

上述代码首先定义了一个静态类 Computer ,其中定义了两个字段和三个方法(其中getComputerName()getRamSize()方法较为简单不过赘述),Computer 方法为类的构造方法,关于 Java 类的构造方法:

  1. 名称与类相同:构造方法的名称必须与类完全相同。
  2. 没有返回类型:构造方法没有返回类型,void 也没有。
  3. 自动调用:当使用 new 关键字创建对象时,构造函数会被自动调用。
  4. 可以重载:一个类可以有多个构造函数,通过不同的参数列表来进行重载。

在入口函数中,我们创建了一个名为 macBookAir 的 Java 对象,并将其通过 fastjson 的 toJSONString 函数序列化成 json 样式的字符串并输出。随后我们又定义了一个 json 样式的字符串反序列化为 Java 对象。程序输出如下。

可见,Fastjson 能够简单、快速的将 Java 对象转换为 json 字符串。

深入理解Fastjson映射

那么,fastjson 是如何将字符串与 Java 对象对应起来的呢?

字段名匹配

fastjson 默认采用字段名匹配的方式,将 json 中的键与 Java 对象的属性进行映射。它会遍历 Java 类中的所有字段,并尝试从 json 中找到与字段名相同的键。如果找到,就将 json 中的值赋给 Java 对象的对应字段。这里的例子就是我们上面样例代码的方式。

注解

但如果 json 中的字段名和对象中的属性名无法对应上呢?fastjson 提供了注解的方式来建立映射关系,代码如下。

package org.example;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONField;

public class FastJsonDemo {
    public static void main(String[] args){
        // 将一个Java对象序列化为字符串
        Computer macBookAir = new Computer("RichardLuo's Macbook Air", 16384, 1024);
        String preSend = JSON.toJSONString(macBookAir);
        System.out.println(preSend);

        // 将一个字符串反序列化为Java对象
        String preReceive = "{\"computerName\":\"RichardLuo's Macbook Pro\",\"ramSize\":\"8192\",\"dkSize\":\"1024\"}";
        Computer macBookPro = JSON.parseObject(preReceive,Computer.class);
        System.out.println(macBookPro.getComputerName() + " with " + macBookPro.getRamSize() + "MB of Ram and " + macBookPro.getDiskSize() + "GB storage");
    }

    public static class Computer{
        private String computerName;
        private int ramSize;
        @JSONField(name = "dkSize")
        private int diskSize;
        public Computer(String computerName, int ramSize, int diskSize){
            this.computerName = computerName;
            this.ramSize = ramSize;
            this.diskSize = diskSize;
        }
        public String getComputerName(){
            return computerName;
        }
        public String getRamSize(){
            return Integer.toString(ramSize);
        }
        public String getDiskSize(){
            return Integer.toString(diskSize);
        }
    }
}

在上面的代码中,我们为Computer类添加了diskSize属性,并通过 @JSONField(name = "dkSize")dkSizediskSize 相关联。在主函数中,我们即使在反序列化的时候使用 dkSize 也能够同样获得正确的映射了。运行结果如下。

但是我们发现,在从 Java 对象序列化为 json 字符串后,其字段名称重新排序了,这是因为 fastjson 在默认情况下,生成字符串的顺序是按照属性的字母进行排序的,而不是按照属性在类中的声明顺序。如果我们希望按照属性在类中的声明顺序来生成 json 字符串,可以通过在类中使用@JSONType注解来设置属性的序列化顺序,示例如下。

与Fastjson基础环境配置与Java基础概念相似的内容:

Fastjson基础环境配置与Java基础概念

Preface 此篇系列文章将会从 Java 的基础语法开始,以 Fastjson 的各个反序列化漏洞分析为结尾,详细记录如何从一个具有基础面向对象编程但毫无 Java 基础的小白成长为了解 Fastjson 的各个漏洞并能够熟练利用的网络安全人员。 环境配置 我们使用 IDEA 作为开发的 IDE

Java反射与Fastjson的危险反序列化

Preface 在前文中,我们介绍了 Java 的基础语法和特性和 fastjson 的基础用法,本文我们将深入学习fastjson的危险反序列化以及预期相关的 Java 概念。 什么是Java反射? 在前文中,我们有一行代码 Computer macBookPro = JSON.parseObje

[转帖]fastJson与一起堆内存溢出'血案'

https://www.jianshu.com/p/876d443c2162 现象 QA同学反映登录不上服务器 排查问题1--日志级别 查看log,发现玩家登录的时候抛出了一个java.lang.OutOfMemoryError 大概代码是向Redis序列化一个PlayerMirror镜像数据,但是

FastJson不成想还有个版本2啊:序列化大字符串报错

# 背景 发现陷入了一个怪圈,写文章的话,感觉只有大bug或比较值得写的内容才会写,每次一写就是几千字,争取写得透彻一些,但这样,我也挺费时间,读者也未必有这么多时间看。 我想着,日常遇到的小bug、平时工作中的一些小的心得体会,都还是可以写写,这样也才是最贴近咱们作为一线开发生活的,也不必非得是个

Jackson--FastJson--XStream--代码执行&&反序列化

Jackson--FastJson--XStream--代码执行&&反序列化 Jackson代码执行 (CVE-2020-8840) 影响范围 2.0.0 <= FasterXML jackson-databind Version <= 2.9.10.2 不受影响版本 FasterXML jacks

【Java】使用fastjson进行序列化时出现空指针异常问题研究

最近在使用fastjson的`JSONObject.toJSONString()`方法将bean对象转为字符串的时候报如下错误: com.alibaba.fastjson.JSONException: write javaBean error, fastjson version 1.2.58, class com.sun.proxy.$Proxy395, fieldName : 0 Caused by: java.lang.NullPointerException: null

Web攻防--JNDI注入--Log4j漏洞--Fastjson反序列化漏洞

JNDI注入 什么是JNDI JNDI全称为 Java Naming and Directory Interface(Java命名和目录接口),是一组应用程序接口,为开发人员查找和访问各种资源提供了统一的通用接口,可以用来定义用户、网络、机器、对象和服务等各种资源。 JNDI支持的服务主要有:DNS

Maven进阶学习指南

当我们在开发项目时,有时需要用到外部依赖组件,例如当我们需要Json序列化的时候需要用到FastJson组件,我们可以通过下载对应jar包加载到项目中。但当一个大的项目同时需要依赖各种各样的外部服务,就存在着配置繁琐、依赖冲突等问题,因此可以通过maven来完成对应的依赖管理功能。

ElasticSearch 实现分词全文检索 - 测试数据准备

String json = JSON.toJSONStringWithDateFormat(sms, "yyyy-MM-dd HH:mm:ss"); FastJson 将日期格式化 BulkRequest bulkRequest = new BulkRequest(); Integer idx = 1; for (String json : jsonList) {

Dubbo3应用开发—Dubbo序列化方案(Kryo、FST、FASTJSON2、ProtoBuf序列化方案的介绍和使用)

Dubbo序列化方案(Kryo、FST、FASTJSON2、ProtoBuf序列化方案的介绍和使用) 序列化简介 序列化是Dubbo在RPC中非常重要的一个组成部分,其核心作用就是把网络传输中的数据,按照特定的格式进行传输。减小数据的体积,从而提高传输效率。 Dubbo制定了Serializatio