1.前言
遇到ctf题目里面需要反序列化transient关键字的变量
但是transient关键字修饰的变量是不进入反序列的
下面是部分代码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
57public class testC implements Serializable {
private String name;
private String age;
private transient String height;
public testC(String name, String age, String height) {
this.name = name;
this.age = age;
this.height = height;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return this.age;
}
public void setAge(String age) {
this.age = age;
}
public String getHeight() {
return this.height;
}
public void setHeight(String height) {
this.height = height;
}
private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
s.defaultReadObject();
this.height = (String)s.readObject();
}
public boolean equals(Object obj) {
if (obj == null) {
return false;
} else if (this == obj) {
return true;
} else if (obj instanceof testC) {
testC user = (testC)obj;
return user.getAge().equals(this.age) && user.getHeight().equals(this.height) && user.getName().equals(this.name);
} else {
return false;
}
}
public String toString() {
return "User{name='" + this.name + '\'' + ", age='" + this.age + '\'' + ", height='" + this.height + '\'' + '}';
}
}
2.transient关键字的作用
在java中,transient主要用来防止成员变量被反序列化。
使用语法如下1
2
3
private String var1;
private transient String var2;@transient
用于hibernate entity class中,使用后就会忽略掉这个字段不会让这些变量写入数据库中
3.让transient变量进入反序列化
用下面的代码来解释一下readObject和writeObject方法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
36public class User implements Serializable {
private String firstName;
private String lastName;
private int accountNumber;
private Date dateOpened;
public User(String firstName, String lastName, int accountNumber, Date dateOpened) {
super();
this.firstName = firstName;
this.lastName = lastName;
this.accountNumber = accountNumber;
this.dateOpened = dateOpened;
}
public User() {
super();
}
//Setters and Getters
private void readObject(ObjectInputStream aInputStream) throws ClassNotFoundException, IOException
{
firstName = aInputStream.readUTF();
lastName = aInputStream.readUTF();
accountNumber = aInputStream.readInt();
dateOpened = new Date(aInputStream.readLong());
}
private void writeObject(ObjectOutputStream aOutputStream) throws IOException
{
aOutputStream.writeUTF(firstName);
aOutputStream.writeUTF(lastName);
aOutputStream.writeInt(accountNumber);
aOutputStream.writeLong(dateOpened.getTime());
}
}
writeXXX由ObjectOutputStream提供,readXXX同理
读取和写入的顺序必须是一样的
序列化的时候会调用writeXXX把其中的字段写入
反序列化的时候就会调用readXXX,按写入顺序读取(类型要相同)
writeUTF是写入字符串,Int是整数,等等
writeObject可以写入任意的类型
那么在看回最开始的题目,显而易见,只需要在testC中这个类加入writeObject,在进行序列化就可以了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
62public class testC implements Serializable {
private String name;
private String age;
private transient String height;
public testC(String name, String age, String height) {
this.name = name;
this.age = age;
this.height = height;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return this.age;
}
public void setAge(String age) {
this.age = age;
}
public String getHeight() {
return this.height;
}
public void setHeight(String height) {
this.height = height;
}
private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
s.defaultReadObject();
this.height = (String)s.readObject();
}
public boolean equals(Object obj) {
if (obj == null) {
return false;
} else if (this == obj) {
return true;
} else if (obj instanceof testC) {
testC user = (testC)obj;
return user.getAge().equals(this.age) && user.getHeight().equals(this.height) && user.getName().equals(this.name);
} else {
return false;
}
}
private void writeObject(ObjectOutputStream s) throws IOException{
s.defaultWriteObject();
s.writeObject(this.height);
}
public String toString() {
return "User{name='" + this.name + '\'' + ", age='" + this.age + '\'' + ", height='" + this.height + '\'' + '}';
}
}
参考链接
https://www.delftstack.com/howto/java/transient-in-java/
https://howtodoinjava.com/java/serialization/custom-serialization-readobject-writeobject/