我们提供安全,免费的手游软件下载!

安卓手机游戏下载_安卓手机软件下载_安卓手机应用免费下载-先锋下载

当前位置: 主页 > 软件教程 > 软件教程

Java基础语法与Fastjson漏洞分析

来源:网络 更新时间:2024-06-19 15:32:03

此篇系列文章将从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的格式来指定项目的各个方面。

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

Java的项目目录结构

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

下图通过创建一个名为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启动时首先调用的方法。

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,其中定义了两个字段和三个方法。Computer方法为类的构造方法。

在入口函数中,我们创建了一个名为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")将dkSize与diskSize相关联。在主函数中,我们即使在反序列化的时候使用dkSize也能够同样获得正确的映射了。运行结果如下。

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