Java反序列化—基础部分

                                        Java反序列化(基础)

0x01、基本概念

1. 序列化和反序列化:

    Serialization(序列化)是指把Java对象保存为二进制字节码的过程;

    Deserialization(反序列化)是把二进制码重新转换成Java对象的过程。

2. 什么情况下需要序列化

     a)当你想把内存中的对象保存到数据库中或者一个文件中时;

     b)当你想用套接字在网络上传送对象时;

     c)当你想通过RMI传输对象的时候;

总之,序列化的作用就是传递和存储!

3.  如何实现序列化

     将需要序列化的类实现Serializable接口就可以了,Serializable接口中没有任何方法,可以理解为一个标记,即表明这个类可以被序列化。序列化和反序列化都可以理解为“读”和“写”操作,通过如下两个方法可以将对象进行“序列化”和“反序列化”的操作。

 4. 需要的接口和方法:

     java.io.Serialize 接口 (可以理解为一个标记,通过此标记可以表明这个类可以被序列化)

     writeObjec 方法(对象进行序列化的方法)

     readObjec t方法(进行反序列的方法)

     serialVersionUID  (表明了序列化版本的id,确定了序列化版本的唯一性)

00x2、java.io.Serializable 接口

1. java.io.Serializable包  是一个没有任何方法的接口,可以理解为序列化的标识,一个类若需要序列化,则必须被标识。

     

2.  按住 ctrl + Serializable可以查看这个接口,发现这个接口没有任何方法

     

0x03、writeObject() 、readObject()方法

1. writeObejct(): 对象序列化,要调用ObjectOutputStream输出流的wirteObject()方法;通过调用类的构造方法,传递字节输出流,包装一     个文件;

    序列化流,将对象中的数据写到字节输出流中,字节输出流写到文件中。

2. readObject(): 对象反序列化,需要调用ObjectInputStream输入流的readObject()方法。

    反序列化流,通过Object 的一个对象接收来自反序列化流的数据。

0x04、serialVersionUID

     序列化版本ID,具有唯一性,需要序列化的对象的成员属性,表示该对象的序列化版本id,反序列化的接收对象的serialVersionUID必须保持和序列化对象的serialVersionUID一致,这样才能正常反序列化。

0x05、下面的代码表示的是:需要被序列化的 Student 类,和  writeObejct()方法、readObject()  方法

package com.java.serialize;

import java.io.*;

//可以直接这么写: public class Student implements java.io.Serializable {}

public class Student implements Serializable {

    private static final long serialVersionUID = -2550501340827203332L;

    public int id;

    public String name;

    public Student(int id,String name) {
        this.id=id;
        this.name=name;
    }

    public String toString() {
        return "id="+id+" "+"name="+name+" ";
    }

}

class test {
    // 通过writeObject() 方法序列化对象
    public static void writeObj() throws IOException {

        // 对象序列化,输出流ObjectOutputStream,通过写对象流,传递字节输出流,包装到 test.txt 文件中
        FileOutputStream file = new FileOutputStream("D:\\test.txt");
        ObjectOutputStream oos = new ObjectOutputStream(file);

        // 调用Student类的构造方法,通过writeObject()方法序列化流,将对象中的数据写到字节输出流中,字节输出流写到文件中
        Student s = new Student(1,"john");
        oos.writeObject(s);

        //打印输出语句,关闭流
        System.out.println("Serialize success!");
        oos.close();
    }

    // 通过readObject() 方法序反列化对象
    public static void readObject() throws IOException, ClassNotFoundException {

        //对象反序列化,输出流ObjectInputStream, 传递字节输入流,包装一个文件
        FileInputStream file = new FileInputStream("D:\\test.txt");
        ObjectInputStream ois = new ObjectInputStream(file);

        // readObject()方法反序列化流,从文件中读取对象中的数据,通过Object类的一个对象,接收来自字节输入流中的传递的字节数组
        Object o = ois.readObject();

        // 打印序列化后接受的数据,关闭流
        System.out.println(o);
        ois.close();
    }

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        writeObj();
        //readObject();
    }
}

 

在上述代码块中的main方法里调用 writeObject() 方法(即对象序列化)后的结果:

在D盘可以看到文件test.txt,打开后是一对乱码,原因是,java序列化后的保存的形式是二进制的,又通过字节数组打印出来。

在上述代码块中的main方法里调用 readObject() 方法(即对象反序列化)后的结果:

 

0x06、反序列化漏洞

话题太高端,简单的来说,在Server服务端的代码,程序员在写代码时没有进行严格的过滤,写类时调用了java.io.Serializable接口,此时,客户端Client的攻击者可以通过序列化,将自己的恶意代码上通过传参到类序列化出来,Server接收到来自Client后的类,进行了反序列化,此时,攻击者上传的恶意代码被反序列后开始执行。一般这个漏洞出现在框架中,比如我们最常用的,写jsp一句话木马的命令: 如果把这一句作为参数,直接传递给 Runtime.getRuntime().exec(String cmd),就执行了。

Over!

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值