java反序列化-开发基础篇


视频

1.什么是序列化?
这个不多说了,之前学过了php的序列化和反序列化
2.序列化的好处
3.序列化实现
需要实现Serializeable接口

1.序列化和反序列化协议

  • XML:常用序列化和反序列化协议 跨机器 跨语言等优点
  • Soap:基于XML为序列化和反序列协议的结构化消息传递协议

1.Serializable基本使用 class Student implent Serializable·Java提供的一个序列化接口(接口为空)I实现Serializable 表示当前类可以被ObjectOutPutStream序列化以及反序列化
2.接口特点
·如果序列化类的属性没有实现此接口那么序列化的时候就会报错
注意:Serializable在序列化和反序列化过程中用到了很多反射
会产生很多内存碎片

1.序列化ID
·序列化时使用字段serialVersionuID此id决定是否能够成功反序列化2. 生成 serialVersionUID
·使用AS plugin插件
使用jdk中bin目录下的工具产生id3.兼容性问题
·主要发生在序列化阶段检测到 serialVersionUID不一致

·1.serialVersionUID改变的情况·手动修改导致id与序列化之前的id不一致·没有写入serialVersionUID
·序列化与反序列化操作的虚拟机不一致·2.序列化与反序列化实现·ObjectOutputStream:对象输出流·ObjectlnputStream:对象输入流

1.为什么要进行代码审计
一种对软件代码进行全面检查和评估的过程,主要发现潜在的安全漏洞和代码质量问题。查找潜在的安全漏洞对代码提出改进建议一增强系统的安全性:
2.审计方向
安全漏洞 top10 spring springboot
代码质量 高内聚低耦合
第三方组件和库的使用 pom文件引入的不安全版本Jackson log4j
权限和访问控制
shiro jwt
代码质量以及合规性

1.审计步骤
·收集代码资料:开发文档源代码
搭建审计环境:配置系统所使用的开发环境jdkmaven第三方组件使用静态代码审计工具可检查常见的安全漏洞静态代码分析:动态代码审计:模拟实际运行环境包括输入输出验证会话管理安全漏洞验证:对应静态代码跑出来的安全漏洞进行手动验证
第三方组件:查看系统所使用的第三方组件版本
业务逻辑分析:需要针对系统功能场景进行分析
编写代码审计报告漏洞修复重新审计
Java开发文档

黑马程序员

就是一些简单的开发基础,有关反序列化的,后面的cc链其他什么的,我会马上写出文章的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# 3. 序列化

## 3.1 概述

Java 提供了一种对象**序列化**的机制。用一个字节序列可以表示一个对象,该字节序列包含该`对象的数据`、`对象的类型`和`对象中存储的属性`等信息。字节序列写出到文件之后,相当于文件中**持久保存**了一个对象的信息。

反之,该字节序列还可以从文件中读取回来,重构对象,对它进行**反序列化**。`对象的数据`、`对象的类型`和`对象中存储的数据`信息,都可以用来在内存中创建对象。看图理解序列化: ![](img/3_xuliehua.jpg)

## 3.2 ObjectOutputStream类

`java.io.ObjectOutputStream ` 类,将Java对象的原始数据类型写出到文件,实现对象的持久存储。

### 构造方法

* `public ObjectOutputStream(OutputStream out) `: 创建一个指定OutputStream的ObjectOutputStream。

构造举例,代码如下:

ava
FileOutputStream fileOut = new FileOutputStream("employee.txt");
ObjectOutputStream out = new ObjectOutputStream(fileOut);


### 序列化操作

1. 一个对象要想序列化,必须满足两个条件:

* 该类必须实现`java.io.Serializable ` 接口,`Serializable` 是一个标记接口,不实现此接口的类将不会使任何状态序列化或反序列化,会抛出`NotSerializableException` 。
* 该类的所有属性必须是可序列化的。如果有一个属性不需要可序列化的,则该属性必须注明是瞬态的,使用`transient` 关键字修饰。

java
public class Employee implements java.io.Serializable {
public String name;
public String address;
public transient int age; // transient瞬态修饰成员,不会被序列化
public void addressCheck() {
System.out.println("Address check : " + name + " -- " + address);
}
}


2.写出对象方法

* `public final void writeObject (Object obj)` : 将指定的对象写出。

ava
public class SerializeDemo{
public static void main(String [] args) {
Employee e = new Employee();
e.name = "zhangsan";
e.address = "beiqinglu";
e.age = 20;
try {
// 创建序列化流对象
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("employee.txt"));
// 写出对象
out.writeObject(e);
// 释放资源
out.close();
fileOut.close();
System.out.println("Serialized data is saved"); // 姓名,地址被序列化,年龄没有被序列化。
} catch(IOException i) {
i.printStackTrace();
}
}
}
输出结果:
Serialized data is saved


## 3.3 ObjectInputStream类

ObjectInputStream反序列化流,将之前使用ObjectOutputStream序列化的原始数据恢复为对象。

### 构造方法

* `public ObjectInputStream(InputStream in) `: 创建一个指定InputStream的ObjectInputStream。

### 反序列化操作1

如果能找到一个对象的class文件,我们可以进行反序列化操作,调用`ObjectInputStream`读取对象的方法:

- `public final Object readObject ()` : 读取一个对象。

java
public class DeserializeDemo {
public static void main(String [] args) {
Employee e = null;
try {
// 创建反序列化流
FileInputStream fileIn = new FileInputStream("employee.txt");
ObjectInputStream in = new ObjectInputStream(fileIn);
// 读取一个对象
e = (Employee) in.readObject();
// 释放资源
in.close();
fileIn.close();
}catch(IOException i) {
// 捕获其他异常
i.printStackTrace();
return;
}catch(ClassNotFoundException c) {
// 捕获类找不到异常
System.out.println("Employee class not found");
c.printStackTrace();
return;
}
// 无异常,直接打印输出
System.out.println("Name: " + e.name); // zhangsan
System.out.println("Address: " + e.address); // beiqinglu
System.out.println("age: " + e.age); // 0
}
}


**对于JVM可以反序列化对象,它必须是能够找到class文件的类。如果找不到该类的class文件,则抛出一个 `ClassNotFoundException` 异常。**

### **反序列化操作2**

**另外,当JVM反序列化对象时,能找到class文件,但是class文件在序列化对象之后发生了修改,那么反序列化操作也会失败,抛出一个`InvalidClassException`异常。**发生这个异常的原因如下:

* 该类的序列版本号与从流中读取的类描述符的版本号不匹配
* 该类包含未知数据类型
* 该类没有可访问的无参数构造方法

`Serializable` 接口给需要序列化的类,提供了一个序列版本号。`serialVersionUID` 该版本号的目的在于验证序列化的对象和对应类是否版本匹配。

java
public class Employee implements java.io.Serializable {
// 加入序列版本号
private static final long serialVersionUID = 1L;
public String name;
public String address;
// 添加新的属性 ,重新编译, 可以反序列化,该属性赋为默认值.
public int eid;

public void addressCheck() {
System.out.println("Address check : " + name + " -- " + address);
}
}



## 3.4 练习:序列化集合

1. 将存有多个自定义对象的集合序列化操作,保存到`list.txt`文件中。
2. 反序列化`list.txt` ,并遍历集合,打印对象信息。

### 案例分析

1. 把若干学生对象 ,保存到集合中。
2. 把集合序列化。
3. 反序列化读取时,只需要读取一次,转换为集合类型。
4. 遍历集合,可以打印所有的学生信息

### 案例实现

java
public class SerTest {
public static void main(String[] args) throws Exception {
// 创建 学生对象
Student student = new Student("老王", "laow");
Student student2 = new Student("老张", "laoz");
Student student3 = new Student("老李", "laol");

ArrayList<Student> arrayList = new ArrayList<>();
arrayList.add(student);
arrayList.add(student2);
arrayList.add(student3);
// 序列化操作
// serializ(arrayList);

// 反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("list.txt"));
// 读取对象,强转为ArrayList类型
ArrayList<Student> list = (ArrayList<Student>)ois.readObject();

for (int i = 0; i < list.size(); i++ ){
Student s = list.get(i);
System.out.println(s.getName()+"--"+ s.getPwd());
}
}

private static void serializ(ArrayList<Student> arrayList) throws Exception {
// 创建 序列化流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("list.txt"));
// 写出对象
oos.writeObject(arrayList);
// 释放资源
oos.close();
}
}



文章作者: wuk0Ng
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 wuk0Ng !
评论
  目录