本文详细介绍 RuoYi-SpringBoot3-Pro[1] 如何使用 ClassFinal 插件保护 Java 项目的核心业务代码,防止反编译和代码泄露。
GitHub:
https://github.com/undsky/RuoYi-SpringBoot3-Pro
Java 是一门编译型语言,源代码编译后生成的 .class 字节码文件可以被轻松反编译还原为接近源代码的形式。这意味着:
ClassFinal 是一款 Java 字节码加密工具,通过对编译后的 class 文件进行深度加密,即使被反编译也只能看到乱码,从根本上保护代码安全。
| 特性 | 说明 |
|---|---|
| 字节码加密 | 对 .class 文件进行 AES 加密,反编译后无法查看源代码 |
| 配置文件加密 | 支持对 yml、properties 等配置文件加密 |
| 选择性加密 | 可指定需要加密的包,避免全量加密影响性能 |
| 排除机制 | 可排除第三方库,防止加密后启动失败 |
| 密码保护 | 运行时需要提供密码,防止未授权运行 |
| Maven 集成 | 打包时自动加密,无需额外操作 |
| Spring Boot 兼容 | 完美支持 Spring Boot 项目 |
┌─────────────────┐ Maven Package ┌─────────────────┐
│ 源代码 .java │ ──────────────────► │ 字节码 .class │
└─────────────────┘ └────────┬────────┘
│
▼
┌─────────────────┐
│ ClassFinal 加密 │
└────────┬────────┘
│
▼
┌─────────────────┐
│ 加密后的 .class │
│ (无法反编译) │
└─────────────────┘ClassFinal 在 Maven 打包阶段介入,对指定包下的 class 文件进行加密处理。加密后的 class 文件在运行时由 ClassFinal 的自定义类加载器解密并加载到 JVM 中。
在 ruoyi-admin/pom.xml 中添加 ClassFinal 插件:
<build>
<plugins>
<!-- Spring Boot 打包插件 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- ClassFinal 代码加密插件 -->
<plugin>
<groupId>com.gitee.lcm742320521</groupId>
<artifactId>classfinal-maven-plugin</artifactId>
<version>1.4.1</version>
<configuration>
<!-- 需要加密的 jar 包,多个用逗号分隔 -->
<libjars></libjars>
<!-- 需要加密的包,多个用逗号分隔 -->
<packages>com.ruoyi.biz</packages>
<!-- 需要加密的配置文件,支持通配符 -->
<cfgfiles>*.yml</cfgfiles>
<!-- 排除的包,不进行加密 -->
<excludes>org.spring</excludes>
<!-- 加密密码,运行时需要此密码 -->
<password>RuoyiSpringBoot3@123456!</password>
<!-- 机器码绑定(可选) -->
<code></code>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>classFinal</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<finalName>RuoyiSpringBoot3</finalName>
</build>| 参数 | 说明 | 示例 |
|---|---|---|
libjars | 需要加密的外部 jar 包 | lib/core.jar,lib/util.jar |
packages | 需要加密的包路径 | com.ruoyi.biz,com.ruoyi.core |
cfgfiles | 需要加密的配置文件 | *.yml,*.properties |
excludes | 排除不加密的包 | org.spring,org.apache |
password | 加密密码 | YourSecretPassword |
code | 机器码,绑定特定机器运行 | ABC123 |
如果需要加密多个包,使用逗号分隔:
<configuration>
<packages>com.ruoyi.biz,com.ruoyi.core,com.ruoyi.service</packages>
</configuration>支持加密敏感配置文件,防止数据库密码等信息泄露:
<configuration>
<!-- 加密所有 yml 和 properties 文件 -->
<cfgfiles>*.yml,*.properties</cfgfiles>
</configuration>执行 Maven 打包命令,ClassFinal 会自动在 package 阶段进行加密:
# 清理并打包
mvn clean package
# 跳过测试打包
mvn clean package -DskipTests打包完成后,在 target 目录下会生成两个文件:
target/
├── RuoyiSpringBoot3.jar # 原始 jar(未加密)
└── RuoyiSpringBoot3-encrypted.jar # 加密后的 jar加密后的 jar 需要提供密码才能运行:
# 方式一:命令行参数
java -jar RuoyiSpringBoot3-encrypted.jar -pwd=RuoyiSpringBoot3@123456!
# 方式二:使用 --classfinal.pwd 参数
java -jar RuoyiSpringBoot3-encrypted.jar --classfinal.pwd=RuoyiSpringBoot3@123456!使用反编译工具(如 JD-GUI、IDEA)打开加密后的 jar,查看加密包下的类:
加密前:
public class OrderService {
public void createOrder(Order order) {
// 完整的业务逻辑清晰可见
validateOrder(order);
calculatePrice(order);
saveToDatabase(order);
}
}加密后:
// 反编译结果为乱码或空方法体
public class OrderService {
public void createOrder(Order order) {
// 无法查看任何业务逻辑
}
}限制 jar 只能在特定机器上运行:
<configuration>
<password>YourPassword</password>
<!-- 绑定机器码,只有匹配的机器才能运行 -->
<code>MACHINE-CODE-123</code>
</configuration>获取机器码:
java -jar classfinal-fatjar.jar -C某些类不适合加密(如实体类、DTO),可以通过包路径排除:
<configuration>
<packages>com.ruoyi.biz</packages>
<!-- 排除实体类和 DTO -->
<excludes>com.ruoyi.biz.domain,com.ruoyi.biz.dto</excludes>
</configuration>开发阶段可以禁用加密,只在生产环境启用:
<profiles>
<profile>
<id>prod</id>
<build>
<plugins>
<plugin>
<groupId>com.gitee.lcm742320521</groupId>
<artifactId>classfinal-maven-plugin</artifactId>
<!-- 只在 prod profile 下启用 -->
</plugin>
</plugins>
</build>
</profile>
</profiles>打包时指定 profile:
mvn clean package -Pprod| 推荐加密 | 不建议加密 |
|---|---|
核心业务逻辑 (service) | 实体类 (domain/entity) |
| 加密算法实现 | DTO/VO 类 |
| 授权验证代码 | Controller 层 |
| 核心算法 | 第三方库 |
| 敏感配置文件 | 公共工具类 |
// ❌ 不要使用简单密码
<password>123456</password>
// ✅ 使用复杂密码
<password>RuoYi@SpringBoot3#2024!Secure</password>密码建议:
# 使用环境变量传递密码,避免密码出现在命令历史中
export CLASSFINAL_PWD="YourSecretPassword"
java -jar app.jar -pwd=$CLASSFINAL_PWD
# 或使用 nohup 后台运行
nohup java -jar app.jar -pwd=YourPassword > app.log 2>&1 &FROM openjdk:17-jdk-slim
WORKDIR /app
COPY target/RuoyiSpringBoot3-encrypted.jar app.jar
# 通过环境变量传递密码
ENV CLASSFINAL_PWD=""
ENTRYPOINT ["sh", "-c", "java -jar app.jar -pwd=${CLASSFINAL_PWD}"]运行容器:
docker run -e CLASSFINAL_PWD="YourPassword" -p 8080:8080 your-imageError: Invalid password解决方案: 检查运行时提供的密码是否与打包时配置的密码一致。
java.lang.ClassNotFoundException: com.xxx.XxxClass可能原因:
解决方案: 检查 excludes 配置,确保第三方库被排除。
可能原因: 加密了实体类或配置类,导致 Spring 无法正确解析。
解决方案:
@Entity、@Configuration 等注解的类解决方案: 确保运行时提供了正确的密码,ClassFinal 会自动解密配置文件。
加密后的代码不支持热部署,这是正常现象。开发阶段建议禁用加密。
⚠️ 重要提醒:
ClassFinal 代码加密特别适合以下场景:
| 场景 | 说明 |
|---|---|
| 商业软件交付 | 将软件交付给客户时保护源代码 |
| SaaS 私有化部署 | 私有化部署时防止代码泄露 |
| 核心算法保护 | 保护具有商业价值的算法实现 |
| 授权验证保护 | 防止授权验证逻辑被绕过 |
| 知识产权保护 | 保护公司的技术资产 |
RuoYi-SpringBoot3-Pro 集成的 ClassFinal 代码加密功能,为 Java 项目提供了企业级的代码保护方案:
通过合理配置 ClassFinal,可以有效保护核心业务代码,降低代码泄露风险,为商业项目提供安全保障。
[1] RuoYi-SpringBoot3-Pro: https://github.com/undsky/RuoYi-SpringBoot3-Pro
[2] RuoYi-SpringBoot3-Pro 文档: https://www.undsky.com/blog/?category=RuoYi-SpringBoot3-Pro#