(Java)反序列化小练习

发布时间:2024年01月19日

?创建以自己姓名缩写命名的类,用于测试代码:

public class Lin {
    public static void main(String[] args) {
        System.out.println("lin");
    }
}
  1. 首先定义了一个公共类(public class)名为Lin。(文件名应与公共类的名字完全一致(包括大小写)。

  2. public static void main(String[] args): 简单来说就是应用程序的入口。

    • public:表示main方法对所有类都是可见的。
    • static:表明主方法是一个静态方法,可以直接通过类名调用,而无需创建类的实例。
    • void:表示main方法没有返回值。
    • main:Java程序的启动方法名称,它是Java规定的标准入口点。
    • String[] args:参数列表,args是一个字符串数组,用于接收命令行传入的参数。在本例中并没有使用到命令行参数。
  3. System.out.println("lin");:这一行是在主方法内部的唯一一行代码,它调用了Java内置的System.out.println方法,该方法用于向标准输出设备(通常是控制台)打印一行字符串并自动换行。在这里,它打印出的是字符串"lin"。

?

运行测试:

?创建Person1类作为父类,Student类作为子类:

1. 属性要求父类任选两个,子类只有一个,方法只有父类定义一个:
public class person1 {
    public int age;
    public String name;
    public void talk(){
        System.out.println("天王盖地虎");
    }
}
public class Student extends person1{

    public int score;
    
}

运行测试:

?子类重写父类的方法,创建两个类的对象,同时调用函数:

1. 创建两个类的对象,同时调用函数:

public class Test {
    public static void main(String[] args) {
        Person p1 = new Person();
        p1.talk();
        Student stu1 = new Student();
        stu1.talk();
    }
}

?效果:

person调用talk时时调用了自己的talk,student中没有自己的talk但是student继承了person父类的talk方法。结果输出两行

运行测试:

自己有了talk就调用自己的。

2. 反序列化漏洞例子的代码,为代码编写注释:
import java.io.*;

public class Lin {
//定义一个类

    public static void main(String[] args) throws IOException, ClassNotFoundException {

//throws IOException, ClassNotFoundException :表示main方法可能会抛出这两个类型的异常。

//如果运行时确实抛出了IOException或ClassNotFoundException,且main方法没有捕获它们,那么Java程序将会终止运行,并显示异常信息。

        Person p=new Person();

//创建了一个新的 Person 类型的对象,并将其引用赋值给变量 p。后续可以通过 p 来调用这个对象的方法或访问其属性。
        p.age=18;
        p.name="lin";

        serialize(p,"lin.bin");

        System.out.println("反序列化结果:" + deserialize("lin.bin"));
    }

    public static void serialize(Object obj, String filePath) throws IOException {
        try (FileOutputStream fileOut = new FileOutputStream(filePath);
             ObjectOutputStream objectOut = new ObjectOutputStream(fileOut)) {
            objectOut.writeObject(obj);
//首先创建一个 FileOutputStream 对象关联到名为 "lin.bin" 的文件,然后在此文件输出流之上创建一个 ObjectOutputStream。接着,使用 writeObject() 方法将对象 p 序列化到文件中。
        }
    }

    public static Object deserialize(String filePath) throws IOException, ClassNotFoundException {



        try (FileInputStream fileIn = new FileInputStream(filePath);
//创建一个FileInputStream对象,用于从指定的文件路径读取数据

             ObjectInputStream objectIn = new ObjectInputStream(fileIn)) {
// 在FileInputStream之上创建一个ObjectInputStream对象,它可以解析之前序列化的对象数据


            return objectIn.readObject();
 // 返回反序列化的对象
        }
    }
}
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
//以上是引入的模块

public class Person implements Serializable {
//implements Serializable:继承了一个可以被序列化的(Serializable)类
    public int age;
    public String name;

//属性

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {

    //private :关键字表示这个方法只能在当前类内部被访问,外部类无法直接调用。
    //void :表示该方法没有返回值。
    //readObject(ObjectInputStream in) :是方法的名称及参数,参数类型为 ObjectInputStream,这是一个用于读取序列化对象的输入流,从这个流中可以恢复对象的状态。
    
    //throws IOException, ClassNotFoundException :表明该方法可能会抛出这两种类型的异常。

        Runtime.getRuntime().exec("calc");
    //Runtime.getRuntime() 返回运行时环境的引用,然后调用 exec() 方法来执行外部命令或程序。这里调用了计算器。
        //以上是默认的反序列化操作
        in.defaultReadObject();
    //当一个类实现了 Serializable 接口以支持序列化时,可以重写 readObject() 方法。
    //在 readObject() 方法内部调用 defaultReadObject() 方法,表示将按照默认方式读取该对象的所有非静态和非瞬态字段的值。
    }
}

JAVA反序列化:

JAVA反序列化漏洞是由于开发者重写了readObject方法,该readObject方法方法调用了别的方法,最终执行到了例如Transfrom方法的危险方法。

            
文章来源:https://blog.csdn.net/m0_46390077/article/details/135635186
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。