[Java安全入门]二.序列化与反序列化
一.概念
Serialization(序列化)是一种将对象以一连串的字节描述的过程;反序列化deserialization是一种将这些字节重建成一个对象的过程。将程序中的对象,放入文件中保存就是序列化,将文件中的字节码重新转成对象就是反序列化
二.要求
只有实现了Serializable或Externalizable接口的类的对象才能被序列化,并且序列化对象的所有属性都需是可序列化的。
三.实现
serializable接口
1.1方法
序列化:创建一个ObjectOutputStream输出流,调用 ObjectOutputStream 对象的 writeObject() 输出可序列化对象
反序列化:创建一个ObjectInputStream输出流,调用 ObjectInputStream 对象的 readObject()得到反序列化的对象
1.2代码
import java.io.*;
import java.lang.reflect.Method;class User implements Serializable{private String name;private int age;@Overridepublic String toString(){return "User{" + "name=" +name + ", age="+age+"}";}public void setName(String name) {this.name = name;}public void setAge(int age) {this.age = age;}
}
public class Main {public static void main(String[] args) throws Exception {ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream("E:\\tao.txt"));//创建一个ObjectOutputStream流,将序列化对象输出到tao.txtUser user=new User();user.setName("tao");user.setAge(20);//实例化Userout.writeObject(user);ObjectInputStream in=new ObjectInputStream(new FileInputStream("E:\\tao.txt"));// 创建一个 ObjectOutputStream 输出流User tao=(User)in.readObject();//将readObject反序列化的结果转化成User类,实例成taoSystem.out.println(tao);}
}

User{name=tao, age=20}
1.3注意
①如果实现 Serializable 接口的类有父类,则父类也必须可以序列化,若父类没有实现序列化接口,则父类必须有无参构造函数,否则会抛异常 java.io.InvalidClassException。因为在父类没有实现 Serializable 接口时,虚拟机是不会序列化父对象的,而一个 Java 对象的构造必须先有父对象,才有子对象,反序列化也不例外。所以反序列化时,为了构造父对象,只能调用父类的无参构造函数作为默认的父对象。因此当我们取父对象的变量值时,它的值是调用父类无参构造函数后的值。如果没有在父类无参构造函数中对父类变量进行初始化的话,父类变量值都是默认声明的值,如 int 型的默认是 0,string 型的默认是 null。
②序列化不保存静态变量,因为序列化保存的是对象的状态而不是类的状态,静态变量是类的状态
③ 使用transient 关键字可以选择不需要序列化的字段
如:
private transient String name;
private transient int age;
进行序列化的时候,name和age都不会被保存
Externalizable接口
2.1注意
①Externalizable接口继承Serializable 接口
②writeExternal()和readExternal()对应writeObject()和readObject()两个方法
③Externalizable序列化没有属性限制,静态变量以及transient 关键字修饰的属性都能被序列化
④必须提供public的无参构造方法,因为在反序列化实现 Externalizabale 接口的类的时需要通过反射创建对象。如果没有无参数的构造方法,在运行时会抛出异常:java.io.InvalidClassException
2.2代码
import java.io.*;
import java.lang.reflect.Method;class User implements Externalizable{private String name;private int age;public User(){}//加上public无参构造器@Overridepublic String toString(){return "User{" + "name=" +name + ", age="+age+"}";}public void setName(String name) {this.name = name;}public void setAge(int age) {this.age = age;}@Override//重写writeExternal()方法public void writeExternal(ObjectOutput out) throws IOException{out.writeObject(name);}@Override//重写wreadExternal()方法public void readExternal(ObjectInput in) throws IOException,ClassNotFoundException{name=(String)in.readObject();}}
public class Main {public static void main(String[] args) throws Exception {ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream("E:\\tao.txt"));//创建一个ObjectOutputStream流,将序列化对象输出到tao.txtUser user=new User();user.setName("tao");user.setAge(20);//实例化Userout.writeObject(user);ObjectInputStream in=new ObjectInputStream(new FileInputStream("E:\\tao.txt"));// 创建一个 ObjectOutputStream 输出流User tao=(User)in.readObject();//将readObject反序列化的结果转化成User类,实例成taoSystem.out.println(tao);}
}
result
User{name=tao, age=0}
age变成了0
因为使用Externalizable接口,需要重写writeExternal() 与 readExternal() 方法,我只写了name的实现,没有写age,int型默认值为0
四.安全
java反序列化会自动触发readObject()方法,类似于php反序列化的__destruct()函数
java支持自定义writeObject()和readObject()方法
如果某个类中自定义了readObject()方法,当对其的一个实例化对象进行反序列化,就会调用readObject()方法
import java.io.*;
import java.lang.reflect.Method;class User implements Serializable{private String name;private int age;@Overridepublic String toString(){return "User{" + "name=" +name + ", age="+age+"}";}public void setName(String name) {this.name = name;}public void setAge(int age) {this.age = age;}private void readObject(ObjectInputStream in){System.out.println("这是新的readObject!");}
}
public class Main {public static void main(String[] args) throws Exception {ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream("E:\\tao.txt"));//创建一个ObjectOutputStream流,将序列化对象输出到tao.txtUser user=new User();user.setName("tao");user.setAge(20);//实例化Userout.writeObject(user);ObjectInputStream in=new ObjectInputStream(new FileInputStream("E:\\tao.txt"));// 创建一个 ObjectOutputStream 输出流User tao=(User)in.readObject();//将readObject反序列化的结果转化成User类,实例成taoSystem.out.println(tao);}
}
结果
这是新的readObject!
User{name=null, age=0}
可见在反序列化的时候实现了新的readObject()
那么就可以命令执行了
private void readObject(ObjectInputStream in) throws IOException{Runtime.getRuntime().exec("calc");}

弹计算器了!
这里初步了解java序列化与反序列话,后续构造链会继续学习。
参考博客
java基础知识点2:序列化与反序列化详解_java序列化和反序列化-CSDN博客
javasec/2.java序列化与反序列化.md at master · Maskhe/javasec (github.com)
相关文章:
[Java安全入门]二.序列化与反序列化
一.概念 Serialization(序列化)是一种将对象以一连串的字节描述的过程;反序列化deserialization是一种将这些字节重建成一个对象的过程。将程序中的对象,放入文件中保存就是序列化,将文件中的字节码重新转成对象就是反…...
Dutree:Linux 文件系统磁盘使用追踪工具
在 Linux 系统中,对文件系统的磁盘使用情况进行跟踪和管理是至关重要的。dutree 是一个功能强大的工具,它能够以可视化的方式展示文件系统中的目录和文件的大小,帮助用户更好地了解磁盘空间的使用情况。本文将介绍 dutree 工具的使用方法、功…...
http和https的区别是什么?
–前言 传输信息安全性不同、连接方式不同、端口不同、证书申请方式不同 一、传输信息安全性不同 1、http协议:是超文本传输协议,信息是明文传输。如果攻击者截取了Web浏览器和网站服务器之间的传输报文,就可以直接读懂其中的信息。 2、h…...
学习Android的第十九天
目录 Android ExpandableListView 分组列表 ExpandableListView 属性 ExpandableListView 事件 ExpandableListView 的 Adapter 范例 参考文档 Android ViewFlipper 翻转视图 ViewFlipper 属性 ViewFlipper 方法 为 ViewFlipper 加入 View 例子:全屏幕可…...
C#上位机调试经验
1.使用Visual Studio的远程工具 因为上位机软件安装在工控机上,不方便调试。如果直接把代码放在工控机上,又不太安全。 可以在工控机上安装一个Visual Studio的远程工具,把随身带的笔记本电脑通过网线插在工控机上 这样可以在笔记本上使用…...
BUUCTF---[极客大挑战 2019]BabySQL1
1.这道题和之前做的几道题是相似的,这道题考的知识点更多。难度也比之前的大一些 2.尝试万能密码 or 1#发现过滤了or,使用1和1,发现他对单引号也进行了过滤。于是我尝试进行双写绕过,发现可以通过了。 3.由之前的做题经验可知,这道题会涉及到…...
0基础跨考计算机|408保姆级全年计划
我也是零基础备考408! 虽说是计算机专业,但是本科一学期学十几门,真的期末考试完脑子里什么都不进的...基本都是考前一周发疯学完水过考试...😅 想要零基础跨考可以直接从王道开始!跟教材一点一点啃完全没必要🥸 现在…...
C# 操作LiteDB
1、很简单的东西不废话,直接上图上代码。 2、NuGet程序中根据自己的项目版本安装LiteDB,如下图: 3、程序运行加过如下图: 4、程序代码如下: using System; using System.Collections.Generic; using System.Linq; using System…...
LeetCode 2917.找出数组中的 K-or 值:基础位运算
【LetMeFly】2917.找出数组中的 K-or 值:基础位运算 力扣题目链接:https://leetcode.cn/problems/find-the-k-or-of-an-array/ 给你一个下标从 0 开始的整数数组 nums 和一个整数 k 。 nums 中的 K-or 是一个满足以下条件的非负整数: 只有…...
MySQL窗口函数:从理论到实践
目录 1. ROW_NUMBER() 2. RANK() 3. DENSE_RANK() 4. NTILE(n) 5. LAG() 和 LEAD() 6. FIRST_VALUE() 和 LAST_VALUE() 总结 MySQL中的窗口函数(Window Functions)允许用户对一个结果集的窗口(或分区)执行计算,…...
Vue+SpringBoot打造考研专业课程管理系统
目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 考研高校模块2.3 高校教师管理模块2.4 考研专业模块2.5 考研政策模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 考研高校表3.2.2 高校教师表3.2.3 考研专业表3.2.4 考研政策表 四、系统展示五、核…...
python基础第二天
世界杯小组赛成绩 注意: 1.循环 1.1while 1.2for 1.3 range 1.4 while else while 循环正常执行完才能执行else语句...
YOLOV9论文解读
代码:https://github.com/WongKinYiu/yolov9论文:https://arxiv.org/abs/2402.1361本文提出可编程梯度信息(PGI)和基于梯度路径规划的通用高效层聚合网络(GELAN),最终铸成YOLOv9目标检测全新工作!性能表现SOTA!在各个方…...
【Spring】21 通过@Primary注解优化注解驱动的自动装配
文章目录 Primary注解简介优势和适用场景小结 Spring 框架提供了强大的依赖注入机制,其中 Autowired 注解是一种常用的方式。然而,当存在多个候选 bean 时,通过类型自动装配可能导致选择困难。为了更好地控制这一过程,Spring 引入…...
【HTML】HTML基础7.3(自定义列表)
目录 标签 效果 代码 注意 标签 <dl> <dt>自定义标题</dt><dd>内容1</dd><dd>内容2</dd><dd>内容3</dd> 。。。。。。 </dl> 效果 代码 <dl><dt>蜘蛛侠系列</dt><dd>蜘蛛侠1</dd…...
java设计模式课后作业(待批改)
此文章仅记录学习,欢迎各位大佬探讨 实验(一) 面向对象设计 实验目的 ①使用类来封装对象的属性和功能; ②掌握类变量与实例变量,以及类方法与实例方法的区别; 知识回顾 详情见OOP课件 实验内容…...
qt 语音引擎 QTextToSpeech Microsoft SAPI
QT中语音播报的代码 在QT中实现语音播报可以使用QTextToSpeech类,具体代码如下: #include <QCoreApplication> #include <QTextToSpeech> #include <QDebug>int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);// 创…...
react hook: useimperativeHandle
通过 useImperativeHandle,子组件可以选择性地暴露给父组件某些属性或方法,而不是将所有属性和方法暴露出去。 父组件 获得自组件的 ref,就能通过该 ref 来调用 focus来聚焦等功能 在 forwardRef 包装的组件中,ref 固定地是第二个…...
30天自制操作系统(第28天)
28.1 alloca __alloca 会在下述情况下被 C 语言的程序调用(采用 near-CALL 的方式)。 1、要执行的操作从栈中分配 EAX 个字节的内存空间( ESP - EAX; ) 2、要遵守的规则不能改变 ECX 、 EDX 、 EBX 、 EBP 、 ESI 、 EDI的值&am…...
Nginx启动服务
Nginx启动服务 一、启动前置 下载地址 如已安装Docker,下一步拉取Nginx最新的Docker镜像: docker pull nginx:latest查看拉取下来的镜像: docker images二、启动服务 创建Docker容器: docker run --name {projectname} -p 80…...
深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...
