一、前言

日常开发部署SpringBoot项目中,打包后的Jar极易通过JD-GUI、IDEA直接反编译,核心业务逻辑、计费算法、权限校验代码逻辑完全泄露,自研功能代码被外包客户逆向、篡改、抄袭。本文选用开源免费 ClassFinal 1.2.1 插件,零代码入侵、纯Maven插件配置,Maven打包自动加密,适配JDK8全套SpringBoot2项目,支持免密一键启动 / 自定义密码启动 双模式;服务器硬件机器码绑定,限制专属设备运行;内存动态解密,磁盘不落地明文Class文件,安全性极高。

开源官方地址:https://gitee.com/roseboy/classfinal
机器码生成工具包:https://repo1.maven.org/maven2/net/roseboy/classfinal-fatjar/1.2.1/classfinal-fatjar-1.2.1.jar

二、加密核心原理&优势

2.1 加密底层逻辑

  1. 打包阶段:清空业务方法体代码,保留类注解、方法名、参数、Swagger注解,不影响接口扫描;
  2. 反编译效果:仅能看到空方法壳,无法查看业务执行逻辑;
  3. 运行阶段:javaagent代理内存实时解密,全程无明文缓存文件。

2.2 核心功能优势

特性 详情说明
无代码侵入 仅配置Maven插件,无需修改一行业务代码
多重安全防护 免密/密码校验/机器绑定,可组合使用
框架兼容性 完美兼容Swagger、Spring注解扫描
精细化加密 自定义加密业务包、过滤系统框架包、加密依赖Jar
适配系统 Windows / Linux 服务器全适配

2.3 打包产物区分

  • service01.jar:原始未加密Jar|可直接启动|生产务必删除
  • service01-encrypted.jar:加密成品Jar|部署专用|禁止直接java -jar启动

在这里插入图片描述

三、环境准备

3.1 环境要求

  • JDK版本:JDK8
  • 构建工具:Maven3.6+
  • 项目框架:SpringBoot2.x

3.2 可选前置:获取服务器机器码(绑定专属设备)

如需项目打包后 仅能在指定服务器运行,提前获取服务器机器码,步骤如下:

  1. 下载工具Jar:classfinal-fatjar-1.2.1.jar
  2. classfinal-fatjar-1.2.1.jar 放入服务器无中文、无空格目录
  3. 终端执行生成编码命令: java -jar classfinal-fatjar-1.2.1.jar -C
  4. 复制输出超长机器编码,填入pom <code> 标签即可

提示:不绑定机器则删除code配置项,任意服务器均可启动项目

在这里插入图片描述

四、pom.xml 插件配置

强制硬性规则:classfinal加密插件 必须放在spring-boot打包插件最后面,否则丢失启动主清单,启动报错!

<build>
    <finalName>service01</finalName>

    <plugins>
      <!-- 1. SpringBoot打包插件(必须放在最前面,生成可执行Jar写入主清单) -->
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <executions>
          <execution>
            <goals>
              <goal>repackage</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

      <!-- 2. Maven清理插件:文件占用删不掉target,也不终止打包 -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-clean-plugin</artifactId>
        <version>3.1.0</version>
        <configuration>
          <failOnError>false</failOnError>
        </configuration>
      </plugin>

      <!-- 3. 单元测试插件:打包跳过测试,加速构建 -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <configuration>
          <skip>true</skip>
        </configuration>
      </plugin>

      <!-- 4. ClassFinal加密插件 官方最终稳定版1.2.1 -->
      <plugin>
        <groupId>net.roseboy</groupId>
        <artifactId>classfinal-maven-plugin</artifactId>
        <version>1.2.1</version>
        <configuration>
          <!-- 启动密码配置:# 代表无密码启动;自定义密码直接填写,例如123456 -->
          <password>#</password>
          <!-- 排除加密包:系统框架包不加密,避免启动报错,多个逗号分隔 -->
          <excludes>org.springframework.*,jdk.nashorn,javax.*,org.slf4j.*</excludes>
          <!-- 业务加密包:项目核心业务包,按需修改为自己项目包名,多个逗号分隔 -->
          <packages>com.zhang</packages>
          <!-- 需要加密的配置文件:加密数据库、密钥配置,避免yml明文泄露 -->
          <!-- cfgfiles注释不用,规避打包报ClassPathResource异常 -->
<!--          <cfgfiles>-->
<!--            application.yml,-->
<!--            application-dev.yml-->
<!--          </cfgfiles>-->
          <!-- 第三方依赖加密:加密项目引入的自定义业务依赖Jar,通配符批量匹配 -->
          <libjars>demo-*.jar,service01.jar</libjars>
          <!-- 服务器机器绑定编码,无需绑定直接删除整行 -->
          <code>531B70EFD32B070236EEEFDF9EF5548DD41D8CD98F00B204E9800998ECF8427ED41D8CD98F00B204E9800998ECF8427E</code>
        </configuration>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>classFinal</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

配置快速自定义修改

  • 改业务包:修改 <packages> 为项目自身根包
  • 改启动模式:<password>#</password> 切换免密启动
  • 取消机器绑定:直接删除 <code> 整行配置
  • 取消依赖加密:清空 <libjars> 内部内容

五、项目打包

5.1 Maven打包命令

IDE终端 / 服务器执行打包命令,自动完成编译+打包+加密:

# 清理+打包加密
mvn clean package '-Dmaven.test.skip=true'

5.2 打包后文件区分

  • 原始Jar:xxx.jar 【可直接启动,无加密,建议删除】
  • 加密Jar:xxx-encrypted.jar 【业务部署使用,加密成品】

六、加密Jar三种启动命令

加密Jar 禁止直接java -jar启动,必须通过javaagent代理启动,三种场景命令使用:

6.1 无密码启动(password配置为#)

# Windows CMD
java -javaagent:xxx-encrypted.jar -jar xxx-encrypted.jar
# 项目实测完成
java -javaagent:service01-encrypted.jar -jar service01-encrypted.jar

# Linux后台守护启动
nohup java -javaagent:service01-encrypted.jar -jar service01-encrypted.jar > run.log 2>&1 

在这里插入图片描述

6.2 自定义密码启动(password设置指定密码)

格式铁律:Windows双引号 + -pwd空格密码 ❌禁止使用等号=

# Windows CMD
# 格式:-pwd 后跟自定义密码
java -javaagent:xxx-encrypted.jar="-pwd 123456" -jar xxx-encrypted.jar
# 项目实测完成
java -javaagent:service01-encrypted.jar="-pwd 123456" -jar service01-encrypted.jar

配置加入密码<password>123456</password>,如果启动命令没设置密码,则会提示输入密码,如下图所示(输入密码直接回车【密码输入不显示】):
在这里插入图片描述
如果密码输入错误,回车会提示密码错误:ERROR: Startup failed, invalid password.
在这里插入图片描述
密码输入正确,回车直接启动项目
在这里插入图片描述

七、常见报错&避坑总结

问题1:打包阶段报错

javassist.NotFoundException: org.springframework.core.io.ClassPathResource
原因:开启cfgfiles加密yml配置文件,1.2.1版本硬编码依赖Spring类,打包独立加载器找不到类,excludes过滤无效;
解决方案:注释/删除 节点,重新打包。

问题2:Failed to delete xxx/target 清理目录失败 BUILD FAILURE

原因:IDEA、Java残留进程、文件资源管理器占用target文件,Windows文件锁拦截目录删除,maven-clean-plugin默认删失败直接终止打包;
解决方案:

  1. 任务管理器结束所有java.exe / javaw.exe 后台进程;
  2. cmd强制解锁删除目录:rmdir /s /q target
  3. 保留pom固定配置:<failOnError>false</failOnError>,删目录失败不中断打包流程。

问题3:xxx-encrypted.jar 中没有主清单属性

原因:插件顺序颠倒,加密插件排在boot打包插件前方,覆盖SpringBoot启动主类MANIFEST清单;硬性排序规则:spring-boot-maven-plugin 首位 → clean → surefire → classfinal加密插件(末尾)
解决方案:调整插件顺序,清空旧target,重新执行 mvn clean package 打包

问题4:Unrecognized option: -pwd=123456

ClassFinal1.2.1 核心解析类:net.roseboy.classfinal.util.CmdLineOption

  1. 源码仅分割【空格】作为参数分隔符,没有编写等号=分割逻辑;
  2. 传入 -pwd=123456 时,程序判定这是一整条陌生指令,并非「指令+参数」;
  3. 免密模式下,哪怕格式写对,携带-pwd参数依旧报错。

格式对错对标
❌ 错误写法(全部禁用):
java -javaagent:jar=“-pwd=123456” -jar jar
java -javaagent:jar=-pwd=123456 -jar jar
✅ 正确写法(唯一标准):
java -javaagent:service01-encrypted.jar=“-pwd 123456” -jar service01-encrypted.jar
系统引号规则
Windows CMD/PowerShell:外层必须双引号
Linux CentOS/Ubuntu:外层必须单引号

问题5:FATAL ERROR:processing of -javaagent failed 代理启动失败

排查原因:

  1. pom配置为免密模式<password>#</password>,启动强行携带任意-pwd参数,解析冲突报错;
  2. 命令行传入密码、pom打包密码不一致,校验直接终止代理;
  3. -javaagent 加载原始service01.jar,必须加载后缀encrypted加密包;
  4. 机器码绑定不匹配、文件损坏、打包中途中断,加密包残缺。

问题6:绑定机器后,其他服务器启动直接报错退出

正常现象:机器码校验拦截,仅生成机器码的服务器可启动,如需更换机器,重新生成机器码修改pom重打包即可
修改非本机机器码,再次重写启动项目,直接提示不可运行。如下图所示:
在这里插入图片描述

八、插件配置参数说明

配置参数 作用说明 取值示例
password 启动密码,#为免密 # / 123456
excludes 排除不加密包 org.springframework.,jdk.nashorn,javax.,org.slf4j.*
packages 业务加密根包 com.zhang
cfgfiles 加密配置文件 application.yml
code 绑定服务器机器码 一串加密编码
libjars 加密第三方依赖Jar business-*.jar

九、总结

ClassFinal 1.2.1为适配JDK8、SpringBoot2.x生态的开源Jar加密组件,无水印、无功能收费、业务代码零侵入;依托JVM javaagent内存解密机制,不落地明文Class字节码,具备密码校验、服务器硬件机器码双重安全校验能力。该版本存在生态局限,暂不兼容SpringBoot3高阶版本,加密Jar包必须依托代理参数启动,且原生存在配置文件加密Bug,不可启用yml资源加密功能。

业务适配场景适用于企业内网业务服务、外包交付项目、商用自研系统部署场景,可有效防范Jar包反编译溯源、核心业务逻辑篡改、数据库及第三方密钥泄露风险,同时可限制项目跨设备非法部署、私自拷贝流转,保障项目源码资产安全。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐