proguard 混淆代码,踩坑记录
原文:https://blog.csdn.net/MyOracleFei/article/details/108261813
一、开始原因
因公司需要,故研究 proguard 混淆代码,期间踩了不少坑,记录一下过程,避免下次再次踩坑,也希望可以帮到大家。代码环境: spring-boot 2.2.5, jdk 1.8, maven 3.6
二 、proguard 使用 (使用 xml ,maven插件的形式配置使用,以下配置为最终配置)
1、在需要混淆的代码 pom.xml 中添加以下 plugin
<plugin> <groupId>com.github.wvengen</groupId> <artifactId>proguard-maven-plugin</artifactId> <executions> <execution> <!--混淆时刻,这里是打包的时候混淆--> <phase>package</phase> <!--使用插件的什么功能,当然是混淆--> <goals> <goal>proguard</goal> </goals> </execution> </executions> <configuration> <proguardVersion>6.2.2</proguardVersion> <!--是否将生成的PG文件安装部署--> <!--<attach>true</attach>--> <!--是否混淆--> <!--<obfuscate>true</obfuscate>--> <!--指定生成文件分类--> <!--<attachArtifactClassifier>pg</attachArtifactClassifier>--> <!-- 加载配置文件 --> <proguardInclude>../proguard.cfg</proguardInclude> <!-- 对什么东西进行加载,这里仅有classes成功,毕竟你也不可能对配置文件及JSP混淆吧--> <injar>classes</injar> <!--class 混淆后输出的jar包 或 文件夹--> <outjar>${project.build.finalName}.jar</outjar> <!-- <outjar>${project.build.finalName}-pg</outjar>--> <!-- 输出目录--> <outputDirectory>${project.build.directory}</outputDirectory> <libs> <!-- Include main JAVA library required.--> <lib>${java.home}/lib/rt.jar</lib> <!-- Include crypto JAVA library if necessary.--> <lib>${java.home}/lib/jce.jar</lib> </libs> </configuration> <dependencies> <dependency> <groupId>net.sf.proguard</groupId> <artifactId>proguard-base</artifactId> <version>5.3.3</version> </dependency> </dependencies> </plugin>
2、上面配置中 <proguardInclude>../proguard.cfg</proguardInclude>,proguard.cfg 这个文件。
# -keep {Modifier} {class_specification} 防止类和成员被移除或者被重命名 # -keepclassmembers {modifier} {class_specification} 防止成员被移除或者被重命名 # -keepclasseswithmembers {class_specification} 防止拥有该成员的类和成员被移除或者被重命名 # -keepnames {class_specification} 防止成员被重命名 # -keepclasseswithmembernames {class_specification} 防止拥有该成员的类和成员被重命名 # -keepclasseswithmembers # -basedirectory directoryname 在配置文件中出现的相对路径均是相对于该路径 # JDK目标版本1.8 -target 1.8 # 不做收缩(删除注释、未被引用代码) -dontshrink # 不做优化(变更代码实现逻辑) -dontoptimize # 不用大小写混合类名机制 -dontusemixedcaseclassnames # 不去忽略非公共的库类 -dontskipnonpubliclibraryclasses -dontskipnonpubliclibraryclassmembers # 确定统一的混淆类的成员名称来增加混淆 -useuniqueclassmembernames # 优化时允许访问并修改有修饰符的类和类的成员 -allowaccessmodification # 不混淆所有包名 #-keeppackagenames # 指定要保留在输出文件内的目录(解决 spring autowire 装配失败的问题) -keepdirectories #-keepdirectories target\classes\cn\XXX\busi\online\cgform\business\RestBusiness.class #-keepdirectories cn.XXX.busi.online.cgform.business.* # 需要保持的属性:异常,注解等 -keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,LocalVariable*Table,*Annotation*,Synthetic,EnclosingMethod #混淆时是否记录日志 #-verbose # 不混淆所有的set/get方法 -keepclassmembers public class * {void set*(***);*** get*();} -keep class cn.XXX.codegenerate.generate.** { *;} -keep class cn.XXX.codegenerate.SettingUtils { *;} -keep class cn.XXX.codegenerate.database.** { *;} -keepclassmembers class cn.XXX.busi.online.cgform.controller.** { private *;} -keep class cn.XXX.busi.online.config.** { *;} -keep class cn.XXX.busi.online.cgreport.entity.** { *;} -keep class cn.XXX.busi.online.cgreport.mapper.** { *;} -keep class cn.XXX.busi.online.cgform.mapper.** { *;} -keep class cn.XXX.busi.online.cgform.business.** { *;} -keep class cn.XXX.busi.online.cgform.enums.ExecuteSqlEnum { *;} -keep class cn.XXX.busi.online.cgform.util.SqlParamUtil { *;} -keep class cn.XXX.busi.client.impl.* { *;} -keep class cn.XXX.busi.client.aop.* { !private <methods>; } # 指定IOnlCgformHeadService类名不被混淆,且IOnlCgformHeadService 的executeSelectSql方法不被混淆 # 注意:返回值 和 参数的 类型要写全路径 -keep class cn.XXX.busi.online.cgform.service.IOnlCgformHeadService { cn.XXX.XXX.framework.common.api.RestResponse* execute*Sql(com.alibaba.fastjson.JSONObject); }
3、以上proguard.cfg 这个文件的内容也可以直接写在pom.xml 中,以个人喜好和需要选择
<plugin> <groupId>com.github.wvengen</groupId> <artifactId>proguard-maven-plugin</artifactId> <executions> <execution> <!--混淆时刻,这里是打包的时候混淆--> <phase>package</phase> <!--使用插件的什么功能,当然是混淆--> <goals> <goal>proguard</goal> </goals> </execution> </executions> <configuration> <proguardVersion>6.2.2</proguardVersion> <!--是否将生成的PG文件安装部署--> <!-- <attach>true</attach>--> <!--是否混淆--> <!-- <obfuscate>true</obfuscate>--> <!--指定生成文件分类--> <!-- <attachArtifactClassifier>pg</attachArtifactClassifier>--> <options> <!-- JDK目标版本1.8--> <option>-target 1.8</option> <!-- 不做收缩(删除注释、未被引用代码)--> <option>-dontshrink</option> <!-- 不做优化(变更代码实现逻辑)--> <option>-dontoptimize</option> <!-- 不去忽略非公用类文件及成员--> <option>-dontskipnonpubliclibraryclasses</option> <option>-dontskipnonpubliclibraryclassmembers</option> <!--不用大小写混合类名机制--> <option>-dontusemixedcaseclassnames</option> <!-- 优化时允许访问并修改有修饰符的类和类的成员 --> <!-- <option>-allowaccessmodification</option>--> <!-- 确定统一的混淆类的成员名称来增加混淆--> <option>-useuniqueclassmembernames</option> <!-- 不混淆所有包名--> <!-- <option>-keeppackagenames</option>--> <!-- 需要保持的属性:异常,注解等--> <!-- Error: You have to specify '-keep' options if you want to write out kept elements with '-printseeds'.--> <option>-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LocalVariable*Table,*Annotation*,Synthetic,EnclosingMethod</option> <!-- <option>-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,*Annotation*,Synthetic,EnclosingMethod</option>--> <!-- 不混淆所有的set/get方法--> <option>-keepclassmembers public class * {void set*(***);*** get*();}</option> <!-- 不混淆包下的所有类名,且类中的方法也不混淆--> <option>-keep class cn.xxx.codegenerate.generate.** { *;}</option> <option>-keep class cn.xxx.codegenerate.SettingUtils { *;}</option> <option>-keep class cn.xxx.codegenerate.database.** { *;}</option> <option>-keep class cn.xxx.busi.online.cgform.mapper.** { *;}</option> <option>-keep class cn.xxx.busi.online.cgform.business.RestBusiness { *;}</option> <option>-keep class cn.xxx.busi.online.cgform.enums.ExecuteSqlEnum { *;}</option> <option>-keep class cn.xxx.busi.online.cgform.util.SqlParamUtil { *;}</option> <option>-keep class cn.xxx.busi.client.impl.SysBaseApiImpl { *;}</option> <option>-keep class cn.xxx.busi.online.cgform.service.IOnlCgformHeadService { *;} </option> <option>-keep class cn.xxx.busi.online.cgform.service.impl.OnlCgformHeadServiceImpl {*;}</option> <option>-printseeds ${project.build.directory}</option> </options> <!-- 加载配置文件 --> <proguardInclude>E:\ideaProject\busi-base-common\proguard.cfg</proguardInclude> <!-- 对什么东西进行加载,这里仅有classes成功,毕竟你也不可能对配置文件及JSP混淆吧--> <injar>classes</injar> <!--class 混淆后输出的jar包 或 文件夹--> <outjar>${project.build.finalName}.jar</outjar> <!-- <outjar>${project.build.finalName}-pg</outjar>--> <!-- 输出目录--> <outputDirectory>${project.build.directory}</outputDirectory> <libs> <!-- Include main JAVA library required.--> <lib>${java.home}/lib/rt.jar</lib> <!-- Include crypto JAVA library if necessary.--> <lib>${java.home}/lib/jce.jar</lib> </libs> </configuration> <dependencies> <dependency> <groupId>net.sf.proguard</groupId> <artifactId>proguard-base</artifactId> <version>6.2.2</version> </dependency> </dependencies> </plugin>
4、配置完之后用maven 直接打包即可。options中是配置的混淆方式和忽略的类或方法
三、踩坑记录(废话不多说,直接上坑坑)
1、报错:(Can't process class [META-INF/versions/9/module-info.class] (Unsupported class version number [53.0] (maximum 52.0, Java 1.8))
解决方式:<proguardVersion>6.2.2</proguardVersion> 版本改为了 最新的 6.2.2,
<dependencies> <dependency> <groupId>net.sf.proguard</groupId> <artifactId>proguard-base</artifactId> <version>6.2.2</version> </dependency> </dependencies> 依赖改为同样的版本,刷新maven,即可。
2、报错:Error: You have to specify '-keep' options if you want to write out kept elements with '-printseeds'.
翻译一下:如果要用'-printseeds'写出保留的元素,则必须指定'-keep'选项。
解决方式:根据需求 配置 -keep 要保留的元素

3、 <proguardInclude>../proguard.cfg</proguardInclude> 配置文件未生效
解决:是因为 路径写的有问题,此路径是相对于 编译后的 target 文件的路径,如果是maven多模块,这些配置又写在父模块的目录下,重点来了,想要混淆子模块的代码,那么这个路径就是相对于子模块的target文件夹的路径
4、想要混淆 某个类,但是这个类里面的 几个方法不能混淆,怎么配置都不行,那么 如下:
返回值和入参 一定要写全包名,要不然无效
# 指定IOnlCgformHeadService类名不被混淆,且IOnlCgformHeadService 的executeSelectSql方法不被混淆
# 注意:返回值 和 参数的 类型要写全路径
-keep class cn.xxx.busi.online.cgform.service.IOnlCgformHeadService {
cn.xxx.xxx.framework.common.api.RestResponse* execute*Sql(com.alibaba.fastjson.JSONObject);
}
5、混淆之后 其他项目调用 @Autowired 注入失败,找不到这个bean
解决方式: -keepdirectories ,配置文件里加入此项目,可解决问题。网上说 这个配置后面可以加 包名或加目录,但我试了没有效果,这个之后再研究一下,解决问题最重要嘛!
6、打包之后 不知道混淆成功了没,或者混淆配置生效了没,查看这个jar包里的代码又很麻烦。那么:
outjar 配置一个目录即可。如果要上传私服,打包之后却有两个包,混淆的那个包无法直接上传私服,那么 outjar 配置的jar包名称 和 ${project.build.finalName} 一致,即可覆盖。然后 一键轻松上传私服。
<!--class 混淆后输出的jar包 或 文件夹--> <!-- <outjar>${project.build.finalName}.jar</outjar>--> <outjar>${project.build.finalName}-pg</outjar>
最后配上 几个配置文件的指令参数说明的文章:
https://www.cnblogs.com/hanschen-coder/p/6528828.html
https://blog.csdn.net/byhook/article/details/52529617
其它参考地址:
https://www.6hu.cc/archives/112073.html
https://mp.weixin.qq.com/s/15tIWg8ZsTs7qbtLlBsH6g
https://www.cnblogs.com/welhzh/p/6017434.html

浙公网安备 33010602011771号