如何对Spring Boot应用及其关联的内部依赖Jar包进行代码混淆
基于Proguard实现Spring Boot + Gradle项目全代码(含内部Jar依赖)混淆方案
注:以下方案仅适用于混淆团队自行维护的私有内部Jar,第三方公共Jar不建议参与混淆,否则会引发不可预知的兼容问题
1. 核心配置逻辑
常规示例仅能混淆自有代码的核心原因是默认将所有依赖都归为无需处理的库依赖,只要把需要混淆的内部Jar从库依赖中拆分出来,加入Proguard的输入处理范围即可实现同步混淆。
2. 完整Gradle配置示例
2.1 插件与基础配置
plugins { id 'org.springframework.boot' version '2.7.14' id 'io.spring.dependency-management' version '1.0.15.RELEASE' id 'java' id 'com.guardsquare.proguard' version '7.3.2' } group = 'com.yourcompany' version = '1.0.0' sourceCompatibility = '1.8' repositories { mavenCentral() // 私有内部Jar对应的 Maven 仓库地址 maven { url 'http://your-private-repo.com/releases' } }
2.2 依赖拆分配置
自定义配置项标记需要混淆的内部Jar,和普通第三方依赖做隔离:
configurations { // 自定义配置,存放所有需要参与混淆的内部Jar internalLib implementation.extendsFrom internalLib } dependencies { // Spring 基础依赖,不参与混淆 implementation 'org.springframework.boot:spring-boot-starter-web' testImplementation 'org.springframework.boot:spring-boot-starter-test' // 第三方公共依赖,不参与混淆 implementation 'com.alibaba:fastjson:1.2.83' // 需要同步混淆的内部Jar,全部归入internalLib配置 internalLib 'com.yourcompany:common-utils:1.2.0' internalLib 'com.yourcompany:business-core:2.1.0' }
2.3 Proguard核心混淆规则
proguard { configurations { release { // 输入1:项目自有编译后的代码 injars sourceSets.main.output // 输入2:所有需要混淆的内部Jar injars configurations.internalLib // 库依赖:排除内部Jar后的其他所有依赖、JDK核心库 libraryjars configurations.runtimeClasspath.filter { !configurations.internalLib.contains(it) } libraryjars "${System.getProperty('java.home')}/lib/rt.jar" libraryjars "${System.getProperty('java.home')}/lib/jce.jar" // 混淆后输出文件路径 outjars layout.buildDirectory.file("libs/${project.name}-${project.version}-proguarded.jar") // Spring 相关保留规则,避免反射调用失败 keep 'public class com.yourcompany.xxx.Application { *; }' keep '@org.springframework.stereotype.* class * { *; }' keep '@org.springframework.context.annotation.Configuration class * { *; }' keep '@org.springframework.beans.factory.annotation.Autowired *;', '@org.springframework.web.bind.annotation.* *;', '@org.springframework.scheduling.annotation.Scheduled *;' // 内部Jar需要暴露的接口/注解/实体类保留规则,按需调整 keep 'public @interface com.yourcompany.common.annotation.PublicApi { *; }' keep 'public class * { @com.yourcompany.common.annotation.PublicApi *; }' keep 'class com.yourcompany.common.entity.** { *; }' // 序列化相关保留规则 keep 'class * implements java.io.Serializable { *; }' keepclassmembers class * implements java.io.Serializable { static final long serialVersionUID; private static final java.io.ObjectStreamField[] serialPersistentFields; private void writeObject(java.io.ObjectOutputStream); private void readObject(java.io.ObjectInputStream); } // 通用基础配置 keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod dontshrink dontoptimize dontwarn ignorewarnings // 可选:生成混淆映射表,方便排查线上问题 printmapping layout.buildDirectory.file("outputs/mapping.txt") } } } // 配置BootJar任务默认使用混淆后的产物 bootJar { dependsOn proguardRelease from zipTree(layout.buildDirectory.file("libs/${project.name}-${project.version}-proguarded.jar")) }
3. 验证步骤
- 执行
./gradlew bootJar命令完成构建 - 解压构建出来的Jar包,使用JD-GUI等反编译工具查看,确认自有代码和内部Jar的代码均已被重命名为无意义的短名称
- 执行
java -jar 构建产物.jar验证服务启动正常、所有业务功能运行无异常
内容的提问来源于stack exchange,提问作者Priyanka
相关产品推荐
相关产品推荐

