Proguard+Maven混淆java web项目## 标题
这里用到的是常用配置,更多详细配置方法和参数信息见官网:https://www.guardsquare.com/en/products/proguard/manual/usage#keepoptions
-
proguard常用关键字
dontshrink 不压缩
dontoptimize 不优化
keep 保留类和类中的成员,防止被混淆或移除
keepclassmembers 只保留类中的成员,防止被混淆或移除
dontwarn 一个和keep可以说是形影不离,尤其是处理引入的library时,不显示警告信息 -
proguard通配符
*匹配任意长度字符,不包含包名分隔符(.)
** 匹配任意长度字符,包含包名分隔符(.)
*** 匹配任意参数类型 -
哪些不应该混淆
a. 使用了枚举要保证枚举不被混淆
b. 对第三方库中的类不进行混淆
c. 运用了反射的类也不进行混淆
d. 交给Spring管理的类
e. JNI中调用的类
f. Test类 -
混淆模板
a. 在需要被混淆工程的pom文件中加入以下配置,具体配置的参数意义已注释。
<plugins>
<!-- ProGuard混淆插件-->
<plugin>
<groupId>com.github.wvengen</groupId>
<artifactId>proguard-maven-plugin</artifactId>
<version>2.0.11</version>
<executions>
<execution>
<!-- 混淆时刻,这里是打包的时候混淆-->
<phase>package</phase>
<goals>
<!-- 使用插件的什么功能,当然是混淆-->
<goal>proguard</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- 是否将生成的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>-allowaccessmodification</option>
<!-- 确定统一的混淆类的成员名称来增加混淆-->
<option>-useuniqueclassmembernames</option>
<!-- 不混淆所有包名,本人测试混淆后WEB项目问题实在太多,毕竟Spring配置中有大量固定写法的包名-->
<option>-keepdirectories</option>
<!-- 排除所有注解类 -->
<option>-keep class * extends java.lang.annotation.Annotation { *; }</option>
<option>-keep interface * extends java.lang.annotation.Annotation { *; }</option>
<option>-keeppackagenames</option>
<option>-keepnames interface **</option>
<!-- 不混淆所有特殊的类-->
<option>-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,LocalVariable*Table,*Annotation*,Synthetic,EnclosingMethod</option>
<!-- 不混淆所有的set/get方法,毕竟项目中使用的部分第三方框架会用到大量的set/get映射-->
<option>-keepclassmembers public class * {void set*(***);void set*(int,***);*** get*();*** get*(int);boolean is*();boolean is*(int);}</option>
<option>-ignorewarnings</option> <!--忽略所有告警-->
<!-- 不混淆lib下jar包里面的class文件,保留第三方jar包 -->
<option>-keep class WebRoot.WEB-INFO.lib.*</option>
<!-- 保留实现了java.beans.BeanInfo接口的类 -->
<option>-keep class * implements java.beans.BeanInfo</option>
<!-- 保留所有公共类中的main方法 -->
<option>-keepclasseswithmembers public class * { public static void main(java.lang.String[]);}</option>
<!-- 保留枚举中的指定的静态方法 -->
<option>-keepclassmembers enum * {public static **[] values(); public static ** valueOf(java.lang.String);} </option>
<!-- 保持测试相关的代码 -->
<option>-dontnote junit.framework.**</option>
<option>-dontnote junit.runner.**</option>
<option>-dontwarn android.test.**</option>
<option>-dontwarn android.support.test.**</option>
<option>-dontwarn org.junit.**</option>
<!-- 保留所有序列化相关内容 -->
<option>-keepclassmembers class * extends java.io.Serializable {
static final long serialVersionUID;
static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}</option>
<!-- 保留所有方法名以class结尾的方法, 这可能导致已被混效过的将被再次混淆 -->
<option>-keepclassmembernames class * {
java.lang.Class class$(java.lang.String);
java.lang.Class class$(java.lang.String,boolean);
}</option>
<!-- 不显示warnning -->
<!-- <option>-dontwarn</option> -->
<!--以下配置为暴露在外被别的工程调用的类,不参与混淆-->
<option>-keepclassmembers class 《包名》.** {public *; private *** *;}</option>
<option>-keep class 《包名》.**</option>
</options>
<!-- 添加运行依赖,不混淆 -->
<libs>
<lib>${java.home}/lib/rt.jar</lib>
<lib>${java.home}/lib/jsse.jar</lib>
<lib>${java.home}/lib/jce.jar</lib>
<lib>${java.home}/lib/charsets.jar</lib>
<lib>${java.home}/lib/jfr.jar</lib>
<lib>${java.home}/lib/ext/access-bridge-64.jar</lib>
<lib>${java.home}/lib/ext/cldrdata.jar</lib>
<lib>${java.home}/lib/ext/dnsns.jar</lib>
<lib>${java.home}/lib/ext/jaccess.jar</lib>
<lib>${java.home}/lib/ext/jfxrt.jar</lib>
<lib>${java.home}/lib/ext/localedata.jar</lib>
<lib>${java.home}/lib/ext/nashorn.jar</lib>
<lib>${java.home}/lib/ext/sunec.jar</lib>
<lib>${java.home}/lib/ext/sunjce_provider.jar</lib>
<lib>${java.home}/lib/ext/sunmscapi.jar</lib>
<lib>${java.home}/lib/ext/sunpkcs11.jar</lib>
<lib>${java.home}/lib/ext/zipfs.jar</lib>
</libs>
<addMavenDescriptor>false</addMavenDescriptor>
<!-- 输入 -->
<injar>${project.build.finalName}.jar</injar>
<!-- 输出 -->
<outjar>${project.build.finalName}-pg.jar</outjar>
<outputDirectory>${project.build.directory}</outputDirectory>
</configuration>
</plugin>
</plugins>
b. 配置完成后,maven clean compile install到本地仓库,以备被其他工程依赖。
- 工程相互依赖(A依赖混淆后的B工程)
在A工程的pom文件中的依赖中加入如下配置
<dependency>
<groupId>com.iflytek</groupId>
<artifactId>B</artifactId>
<!—如果需要依赖被混淆过后的B工程,需要用此分类标识,否则则不用 -->
<classifier>pg</classifier>
<version>${ version}</version>
</dependency>