JDK反序列化时修改类的全限定性名解析
应用场景
SpringSecurityOAuth2有一个奇葩的设计,那就是它将与access_token相关的所有属于都封装到OAuth2AccessToken中,然后保存时会直接将该对象序列化成字节写入数据库。我们在资源服务器中想要直接读数据库来取出access_token来验证令牌的有效性,然而又不想引入SpringSecurity的相关依赖污染jar包。这时可以将SpringSecurity中OAuth2AccessToken的唯一实现类DefaultOAuth2AccessToken的源码copy到我们的项目中,然后通过JDBC读取byte[],通过JDK自带的反序列化机制来还原DefaultOAuth2AccessToken对象。这时就会遇到问题,即原来的OAuth2AccessToken所在包是以org.springframework.security开头的,而我们copy过来源码后,包名是以我们自己定义的包cn.com.XXXX开头的,这样在反序列化时,即使两个类的字段完全一样,但由于字节流中存储的类信息的全限定性名不同,也会导致反序列化失败。
解决方案
我们可以定义子类继承JDK的ObjectInputStream,然后重写readClassDescriptor()方法:
@Override protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException { ObjectStreamClass read = super.readClassDescriptor(); if (read.getName().startsWith("原包名")) { Class type = Class.forName(read.getName().replace("新包名")); return ObjectStreamClass.lookup(type); } return read; }
这样在反序列化时就不会报错了。原理并不复杂,其实就是在解析字节流时,将解析后应为org.springframework.security.oauth2.common.DefautOAuthToken的class,替换成了我们自己copy过来源码的cn.com.XXXXXX.DefaultOAuthToken从而达到”欺骗”的目的。在该场景下,我们就可以做到在资源提供方不引入SpringSecurity框架而只使用SpringSecurityOAuth2的授权服务。资源提供方直接读数据库来验证令牌的有效性,而不是向授权服务查询。
总结
以上就是本文关于JDK反序列化时修改类的全限定性名解析的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其它相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!
相关推荐
-
JDK1.7以上javaFTP上传删除文件的实现方法
实例如下: packagecom.itv.launcher.util; importjava.io.File; importjava.io.FileInputStream; importjava.io.FileNotFoundException; importjava.io.IOException; importjava.net.InetSocketAddress; importjava.util.Properties; importjava.util.StringTokenizer; impo
-
如何为Spark Application指定不同的JDK版本详解
前言 随着企业内部业务系统越来越多,基于JVM的服务,通常情况线上环境可能会有多套JDK跑不同的服务.大家都知道基于高版本的Java规范编写的服务跑在低版本的JVM上会出现:java.lang.UnsupportedClassVersionError的异常. Spark 2.2开始移除了对Java 7的支持,大多数情况下,我们的Spark Application是和Hadoop系统公用的JDK,如果Hadoop依赖的JDK版本是7,那我们基于JDK 8编写的Application跑在上面就会出问
-
JDK1.7 之java.nio.file.Files 读取文件仅需一行代码实现
JDK1.7中引入了新的文件操作类java.nio.file这个包,其中有个Files类它包含了很多有用的方法来操作文件,比如检查文件是否为隐藏文件,或者是检查文件是否为只读文件.开发者还可以使用Files.readAllBytes(Path)方法把整个文件读入内存,此方法返回一个字节数组,还可以把结果传递给String的构造器,以便创建字符串输出.此方法确保了当读入文件的所有字节内容时,无论是否出现IO异常或其它的未检查异常,资源都会关闭.这意味着在读文件到最后的块内容后,无需关闭文件.要注意
-
通过JDK源码角度分析Long类详解
概况 Java的Long类主要的作用就是对基本类型long进行封装,提供了一些处理long类型的方法,比如long到String类型的转换方法或String类型到long类型的转换方法,当然也包含与其他类型之间的转换方法.除此之外还有一些位相关的操作. Java long数据类型 long数据类型是64位有符号的Java原始数据类型.当对整数的计算结果可能超出int数据类型的范围时使用. long数据类型范围是-9,223,372,036,854,775,808至9,223,372,036,85
-
基于编译虚拟机jvm—openjdk的编译详解
java只所以被推广,实际上很大原因是因为本身是跨平台的,很大作用是因为虚拟机的关系. 一般情况下开发人员不需要关注虚拟机内部实现就可以日常开发了,但是有时候涉及到性能的时候就需要了解虚拟机的实现机制了. 那么今天写的内容更多的是关于编译一套自己的虚拟机,为日后了解虚拟机底层原理铺铺路. 编译虚拟机可能会遇到很多坑,也很花费时间.也因大家的环境的差异,可能遇到的问题都不一致. 我只能说把自己遇到的问题都列出来,权当抛砖引玉了. 1首先我们应该下载openjdk的源码,这个openjdk实际上是有
-
详解IntelliJ IDEA 中如何配置多个jdk版本即(1.7和1.8两个jdk都可用)
有时候需要看Java源码,但是 Java 1.7 和 Java 1.8的差别的关系,有时候你想查看不同jdk版本的Java源码. 或者你的项目需要测试不同Java jdk 版本的通用与否.那么这个编辑器支持多个版本的jdk同时存在,可以自由的切换 具体实现,看下图,一次配置,可以随便使用,省事 安心. 这是选择的是1.8版本的jdk 这是选择的是1.7的版本的jdk 一般像使用eclipse的时候,还得整个环境变量,但是我的这个1.7的时候,好像也没修改环境变量,我的那个测试用 的hellowo
-
JDK1.7 Paths,Files类实现文件夹的复制与删除的实例
实例如下所示: public static void copyFolder(String srcFolder, String destFolder) throws IOException { long startTime = System.currentTimeMillis(); final Path srcPath = Paths.get(srcFolder); // 这里多创建一级,就解决了没有外壳的问题 final Path destPath = Paths.get(destFolder,
-
CentOS 7下JDK8的详细安装步骤
本文为大家分享了CentOS 7下安装JDK8的详细步骤,供大家参考,具体内容如下 一.下载JDK 至oracle官网下载,如图所示 二.安装JDK 把rpm文件拷贝至/usr/java,如果没有java文件夹, mkdir /usr/java/ 使用npm -ivh jdk文件名安装,如图所示 三.配置环境变量 使用命令 vi /etc/profile,插入图中红色部分: 注意=两边不要有空格 使用:wq保存退出,然后输入source /etc/profile和java -version,如图
-
JDK反序列化时修改类的全限定性名解析
应用场景 SpringSecurityOAuth2有一个奇葩的设计,那就是它将与access_token相关的所有属于都封装到OAuth2AccessToken中,然后保存时会直接将该对象序列化成字节写入数据库.我们在资源服务器中想要直接读数据库来取出access_token来验证令牌的有效性,然而又不想引入SpringSecurity的相关依赖污染jar包.这时可以将SpringSecurity中OAuth2AccessToken的唯一实现类DefaultOAuth2AccessToken的源
-
JDK源码Enum类原理及代码实例解析
正文 一 概述 枚举类型是 JDK 5 之后引进的一种非常重要的引用类型,可以用来定义一系列枚举常量,使用 enum 来表示枚举可以更好地保证程序的类型安全和可读性 实际上在使用关键字enum创建枚举类型并编译后,编译器会为我们生成一个相关的类,这个类继承了Java API中的java.lang.Enum类, 也就是说通过关键字enum创建枚举类型在编译后事实上也是一个类类型而且该类继承自java.lang.Enum类 使用举例 public class EnumTest { enum MyCo
-
JVM类运行机制实现原理解析
1.一段java程序是如何运行起来的呢? Java源文件,通过编译器,产生.Class字节码文件,字节码文件通过Java虚拟机中的解释器,编译成特定及其上的机器码,那Java虚拟机又是怎样加载java程序并执行起来的呢? 简单来说:通过类加载器加载字节码文件,被分配到JVM的运行时数据区的字节码会被执行引擎执行. (1)类加载器,加载.class文件 (2)运行数据区:栈区.堆区.PC寄存器.本地方法栈.方法区 (3)执行引擎:执行包在装载类方法中的指令 2. 类加载器 类的加载是指将类的.cl
-
SpringBoot高版本修改为低版本时测试类报错的解决方案
目录 高版本改低版本时测试类报错 比如在创建项目时默认的版本为2.2.2版本 然后我们修改为1.5.10的低版本 此时可以做如下修改 1.删除高版本默认导入的org.junit.jupiter.api.Test类 2.在类上添加注释@RunWith(SpringRunner.class) 3.将测试类和测试方法都修改为public 4.最后修改的测试类如下所示 高版本改低版本时测试类报错 有时在使用idea通过Spring Initailizr创建项目时,默认只能创建最近的版本的SpringBo
-
泛型的类型擦除后fastjson反序列化时如何还原详解
目录 铺垫 错误写法1 错误写法2 正确写法 TypeReference 验证 扩展 铺垫 在前面的文章中,我们讲过Java中泛型的类型擦除,不过有小伙伴在后台留言提出了一个问题,带有泛型的实体的反序列化过程是如何实现的,今天我们就来看看这个问题. 我们选择fastjson来进行反序列化的测试,在测试前先定义一个实体类: @Data public class Foo<T> { private String val; private T obj; } 如果大家对泛型的类型擦除比较熟悉的话,就会知
-
Java-String类最全汇总(上篇)
目录 创建字符串 字符串比较相等 代码1 代码2 代码3 代码4 代码1内存布局 代码4内存布局 字符串常量池 a) 直接赋值 b) 采用构造方法 理解字符串不可变 a) 常见办法: 借助原字符串, 创建新的字符串 b) 特殊办法: 使用 “反射” 这样的操作可以破坏封装, 访问一个类内部的 private 成员. 创建字符串 常见的构造 String 的方式 // 方式一 String str = "Hello Bit"; // 方式二 String str2 = new Strin
-
JDK动态代理之ProxyGenerator生成代理类的字节码文件解析
通过前面几篇的分析,我们知道代理类是通过Proxy类的ProxyClassFactory工厂生成的,这个工厂类会去调用ProxyGenerator类的generateProxyClass()方法来生成代理类的字节码.ProxyGenerator这个类存放在sun.misc包下,我们可以通过OpenJDK源码来找到这个类,该类的generateProxyClass()静态方法的核心内容就是去调用generateClassFile()实例方法来生成Class文件.我们直接来看generateClas
-
走进JDK之不可变类String
文中相关源码: String.java 今天来说说 String. 贯穿全文,你需要始终记住这句话,String 是不可变类 .其实前面说过的所有基本数据类型包装类都是不可变类,但是在 String 的源码中,不可变类 的概念体现的更加淋漓尽致.所以,在阅读 String 源码的同时,抽丝剥茧,你会对不可变类有更深的理解. 什么是不可变类 ? 首先来看一下什么是不可变类?Effective Java 第三版 第 17 条 使不可变性最小化 中对 不可变类 的解释: 不可变类是指其实例不能被修改的
-
java注解之运行时修改字段的注解值操作
今天遇到需求:导入Excel时候列头会发生变化,客户是大爷要求你改代码, 导入Excel是用easypoi做的,识别表头是用注解@Excel(name = "xxx")通过这个name来匹配 那你表头要动,我这个注解是硬编码 所以就有动态设置这个表头 public class JavaVo{ @Excel(name = "xxx") private String userName; //省略getset方法 } ExcelImportUtil.importExcel
-
java中abstract修改类的实例方法
abstract是一种修饰类,经过修改的类会变成抽象类.除了类之外还可以修改方法,考虑到类的模块是小伙伴们常接触的,今天来小编带大家一起找寻使用abstract修改类的方法.这里需要我们先从abstract丁酉.特点.方法.注释进行学习,然后在实例中体会修改类的用法. 1.abstract定义 abstract关键字可以修改类或方法. abstract 类可以扩展(增加子类),但不能直接实例化. abstract 方法不在声明它的类中实现,但必须在某个子类中重写. 2.特点 可以声明引用不能创建
随机推荐
- PerlScript编写ASP(转载)
- PowerShell管道入门必看篇(管道例子大全)
- PowerShell脚本开发尝试登录SQL Server
- Kvmon.exe远程控制病毒清除指南
- 用Python实现一个简单的能够上传下载的HTTP服务器
- php Apache+phpMyAdmin配置方法
- 简单介绍线性表以及如何实现双链表
- js 表格隔行颜色
- 使用透明叠加法美化文件上传界面
- C++实现图的邻接表存储和广度优先遍历实例分析
- C#创建IIS虚拟目录的方法
- React Native 使用Fetch发送网络请求的示例代码
- 解决新django中的path不能使用正则表达式的问题
- JavaSwing后台播放音乐mp3
- C#中explicit与implicit的深入理解
- vue分页器组件编写方法详解
- thinkphp3.2框架中where条件查询用法总结
- Java LinkedList的实现原理图文详解
- Java8的常用时间api实用指南
- 浅析Python pandas模块输出每行中间省略号问题