使用 ClassFinal 加密 Java 项目发布包

   最近在工作中突起念头,我们做完项目给别人发布上线后,不就相当于给了对方源码嘛。除了没有注释以外,基本和源码没什么区别。自己能想到的自然是很多人遇到过的,然后在网上查找,发现了 ProGuard 和 ClassFinal 两种方式。

  ProGuard 是一个用于做代码的压缩、混淆的工具。在经过简单尝试后没成功,等以后有时间再鼓捣一下。

  ClassFinal 是一款 java class 文件安全加密工具。简单尝试就成功了,记录过程以备后用。


1. ClassFinal 介绍

  • 官网介绍:ClassFinal 是一款 java class 文件安全加密工具,支持直接加密 jar 包或 war 包,无需修改任何项目代码,兼容 spring-framework;可避免源码泄漏或字节码被反编译。
  • Gitee: https://gitee.com/roseboy/classfinal

2. 加密方式

2.1 Java 命令

a)下载工具: 点此下载

b)执行如下命令

1
java -jar classfinal-fatjar.jar -file yourpaoject.jar -libjars a.jar,b.jar -packages com.yourpackage,com.yourpackage2 -exclude com.yourpackage.Main -pwd 123456 -Y
1
2
3
4
5
6
7
8
9
10
参数说明
-file 加密的 jar/war 完整路径
-packages 加密的包名(可为空, 多个用 "," 分割)
-libjars jar/war 包 lib 下要加密 jar 文件名(可为空, 多个用 "," 分割)
-cfgfiles 需要加密的配置文件,一般是 classes 目录下的 yml 或 properties 文件(可为空, 多个用 "," 分割)
-exclude 排除的类名(可为空, 多个用 "," 分割)
-classpath 外部依赖的 jar 目录,例如 /tomcat/lib(可为空, 多个用 "," 分割)
-pwd 加密密码,如果是 #号,则使用无密码模式加密
-code 机器码,在绑定的机器生成,加密后只可在此机器上运行
-Y 无需确认,不加此参数会提示确认以上信息

2.2 maven 插件

a)在项目的 pom.xml 文件中增加插件配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<plugin>
<!-- https://gitee.com/roseboy/classfinal -->
<groupId>net.roseboy</groupId>
<artifactId>classfinal-maven-plugin</artifactId>
<version>${classfinal.version}</version><!-- 目前最新版本是:1.2.1 -->
<configuration>
<password>000000</password><!-- 加密打包之后 pom.xml 会被删除,不用担心在 jar 包里找到此密码 -->
<packages>com.yourpackage,com.yourpackage2</packages>
<cfgfiles>application.yml</cfgfiles>
<excludes>org.spring</excludes>
<libjars>a.jar,b.jar</libjars>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>classFinal</goal>
</goals>
</execution>
</executions>
</plugin>

b)运行 mvn package 时会在 target 下自动加密生成 yourpaoject-encrypted.jar。

2.3 说明事项

  • 对于开发者,个人觉得还是在 Maven 里配置更方便,因此 Java 命令的方式未尝试。
  • 对于 SpringBoot 项目,插件配置应放在 spring-boot-maven-plugin 插件后面,否则不能正常打包 SpringBoot 项目。
  • 对于 Maven 多模块项目,插件应配置在 SpringBoot 启动类的模块中。
  • 多模块项目,插件只会加密当前所在模块,可以通过 libjars 参数配置实现加密依赖模块。
  • 经简单测试,加密对 xml 无效,因此 Mybatis 的 Mapper 文件是未加密的。
  • 参数 code 可绑定机器码,实现只能在指定机器上运行。
  • 生成机器码,需要在被绑定机器上执行如下命令:java -jar classfinal-fatjar.jar -C
  • 加密后,原始的 class 文件并不会完全被加密,只是方法体被清空,保留方法参数、注解等信息。

3. 启动方式

3.1 启动时指定密码

  • 执行如下命令启动
1
java -javaagent:yourpaoject-encrypted.jar='-pwd 0000000' -jar yourpaoject-encrypted.jar
  • 由上看出,加密启动仅比常规启动多了 javaagent 参数。

3.2 启动后输入密码

  • 执行如下命令启动
1
java -javaagent:yourpaoject-encrypted.jar -jar yourpaoject-encrypted.jar
  • 开始启动后,会出现输入密码的提示。

3.3 无密码启动

  • 参数 <password>000000</password> 设置为<password>#</password>。或者 -pwd 参数设为 #。
  • 启动时便可以无密码启动。

3.4 Tomcat 运行 war 包

  • 将加密后的 war 放在 tomcat/webapps 下, tomcat/bin/catalina 增加以下配置:
1
2
3
4
5
6
7
8
9
10
//linux 下 catalina.sh
CATALINA_OPTS="$CATALINA_OPTS -javaagent:classfinal-fatjar.jar='-pwd 0000000'";
export CATALINA_OPTS;

//win 下 catalina.bat
set JAVA_OPTS="-javaagent:classfinal-fatjar.jar='-pwd 000000'"

// 参数说明
// -pwd 加密项目的密码
// -nopwd 无密码加密时启动加上此参数,跳过输密码过程

4. 总结

  • 文中记录内容主要来自于 ClassFinal 官网。结合自己试用过程中遇到的问题和想法,形成了本博客。也是为了以后需要使用时不用再冷启动。
  • 由上文可知,ClassFinal 使用起来还是比较简单的,而且官网上使用说明也比较完善。
  • 在加密的基础上,基本满足了无密码启动、输入密码启动及指定机器启动等各种场景。
  • 仅在 SpringBoot 2.5 项目上做了验证,其他环境和版本的支持情况有待验证。