Classfinal问题处理及改造升级(一)

classfinal介绍

ClassFinal是一款java class文件安全加密工具,支持直接加密jar包或war包,无需修改任何项目代码,兼容spring-framework;可避免源码泄漏或字节码被反编译。

Gitee : ClassFinal: Java字节码加密工具

  • 无需修改原项目代码,只要把编译好的jar/war包用本工具加密即可。
  • 运行加密项目时,无需求修改tomcat,spring等源代码。
  • 支持普通jar包、springboot jar包以及普通java web项目编译的war包。
  • 支持spring framework、swagger等需要在启动过程中扫描注解或生成字节码的框架。
  • 支持maven插件,添加插件后在打包过程中自动加密。
  • 支持加密WEB-INF/lib或BOOT-INF/lib下的依赖jar包。
  • 支持绑定机器,项目加密后只能在特定机器运行。
  • 支持加密springboot的配置文件。

背景

接到一项任务,由于涉及知识产权保护,需要对关键代码片段进行加密处理(核心库)。因此,我选择了ClassFinal工具来实现字节码层面的加密。

使用步骤

  1. 核心库工程引入插件依赖
    <plugin>
        <!-- https://gitee.com/roseboy/classfinal -->
        <groupId>net.roseboy</groupId>
        <artifactId>classfinal-maven-plugin</artifactId>
        <version>1.2.1</version>
        <configuration>
            <password>000000</password><!--加密打包之后pom.xml会被删除,不用担心在jar包里找到此密码-->
            <packages>com.yourpackage,com.yourpackage2</packages>
        </configuration>
        <executions>
            <execution>
                <phase>package</phase>
                <goals>
                    <goal>classFinal</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
  2. 运行mvn package时会在target下自动加密生成yourproject-encrypted.jar
  3. 将核心库依赖到spring boot项目中
  4. 配置启动命令
    -javaagent:yourproject-encrypted.jar="-pwd 000000"

问题改造

        IDEA中启动运行一切正常,打包成jar包启动后运行到核心包代码块解密失败,代码无法正常执行?

问题原理

        Spring FatJar使用了LaunchedURLClassLoader去加载FatJar中的class和jar嵌套的jar(即jar in jar),显然按照这个逻辑核心包代码块也交由LaunchedURLClassLoader去加载。但是我们使用了javaagent:yourproject-encrypted.jar去执行字节码解密,而代理包中的class是默认交由AppClassloader去加载的,Classfinal默认生成的代理包又包含了所有的核心包代码块(只需用到Classfinal解密代码),这就导致了问题的出现。因为LaunchedURLClassLoader是AppClassLoader的子类加载器,当核心包里面的类调用到被LaunchedURLClassLoader加载的类时会报ClassNoFound。

举个例子:
一、核心库代码String2DateConvert

public class String2DateConvert implements Converter<String, Date> {
    @Override
    public Date convert(String s) {
        if (StringUtils.isNotBlank(s)) {
            DateFormat dtf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            try {
                return dtf.parse(s);
            } catch (ParseException e) {
                log.error("日期格式转换失败; {}", e.getMessage());
            }
        }
        return null;
    }
}

二、spring boot项目引用核心包代码

 public void test() {
        String2DateConvert string2DateConvert = new String2DateConvert();
        string2DateConvert.convert("2023-01-01");
 }

三、其中核心库引用的StringUtils来自apache.commons.lang3包,该第三方包是交由外部LaunchedURLClassLoader。根据双亲委派机制,是无法从AppClassLoader拿到LaunchedURLClassLoader加载的类,因此会报:org.apache.commons.lang.StringUtils NoClassDefFoundError

解决方式

其实就是将代理包中的非解密代码删除掉

源码修改如下:先打包核心包,再打包代理包

预告:如何支持多重jar包解密,即spring boot包也进行一层加密?Classfinal问题处理及改造升级(二)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值