效果展示
使用步骤
1/3·首先在pom.xml中添加ProGuard的版本属性
<properties>
<proguard.version>7.1.1</proguard.version>
<proguard.maven.plugin.version>2.5.1</proguard.maven.plugin.version>
</properties>
2/3·最后在POM.xml中配置build标签,添加ProGuard配置
<build>
<plugins>
<!-- 代码混淆 -->
<plugin>
<groupId>com.github.wvengen</groupId>
<artifactId>proguard-maven-plugin</artifactId>
<version>${proguard.maven.plugin.version}</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>proguard</goal>
</goals>
</execution>
</executions>
<configuration>
<proguardVersion>${proguard.version}</proguardVersion>
<injar>${project.build.finalName}.jar</injar>
<outjar>${project.build.finalName}.jar</outjar>
<obfuscate>true</obfuscate>
<options>
<option>-dontshrink</option>
<option>-dontoptimize</option>
<!-- 此选项将用新的类名替换反射方法调用中的所有字符串。例如,调用Class.forName('className')-->
<option>-adaptclassstrings</option>
<!-- 此选项将保存所有原始注解等。否则,将从文件中删除所有注解。-->
<option>-keepattributes
Exceptions,
InnerClasses,
Signature,
Deprecated,
SourceFile,
LineNumberTable,
*Annotation*,
EnclosingMethod
</option>
<!-- 此选项将保存接口中的所有原始名称(不混淆)-->
<option>-keepnames interface **</option>
<!-- 此选项将将所有原始方法参数-->
<option>-keepparameternames</option>
<!-- 此选项将保存所有原始类文件(不混淆),一般是混淆领域或者服务包中的文件。-->
<option>-keep
class x.x.x.Application {
public static void main(java.lang.String[]);
}
</option>
<!-- 此选项忽略警告,例如重复的类定义和命名不正确的文件中的类-->
<option>-ignorewarnings</option>
<!-- 此选项将保存服务包中的所有原始类文件(不进行混淆)-->
<!-- <option>-keep class com.waylau.proguard.service { *; }</option>-->
<!-- 此选项将保存所有软件包中的所有原始接口文件(不进行混淆)-->
<option>-keep interface * extends * { *; }</option>
<!-- 此选项将保存所有包中所有类中的所有原始定义的注解-->
<option>-keep class com.fasterxml.jackson.** { *; }</option>
<option>-keep class org.json.JSONObject.** {** put(java.lang.String,java.util.Map);}</option>
<option>-keepclassmembers class * {
@org.springframework.context.annotation.Bean *;
@org.springframework.beans.factory.annotation.Autowired *;
@org.springframework.beans.factory.annotation.Value *;
}
</option>
<option>-dontwarn com.fasterxml.jackson.databind.**</option>
<option>-dontwarn com.fasterxml.jackson.**</option>
</options>
<injarNotExistsSkip>true</injarNotExistsSkip>
<libs>
<!--在此添加需要的类库-->
<!--<lib>${java.home}/lib/rt.jar</lib>-->
</libs>
</configuration>
<dependencies>
<dependency>
<groupId>com.guardsquare</groupId>
<artifactId>proguard-base</artifactId>
<version>${proguard.version}</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<mainClass>xx.xx.Application</mainClass>
</configuration>
</execution>
</executions>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
接着执行mvn package 来编译工程,编译的时候就会自动进行混淆。
3/3·检查:
1·运行jar包检查程序是否正常运行;
2·反编译jar包检查是否成功进行代码混淆;
两件事都没问题那就OK了。
遇到的问题
1·.BeanDefinitionStoreException: Failed to parse configuration class [xxx.xx]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name ‘a’ for bean class [xx.xx.a.a] conflicts with existing, non-compatible bean definition of same name and class [xx.xx.a]
从错误信息来看,应该是bean 重名冲突。
最简单的解决办法是保留bean的名字不混淆:
keep 'public @org.springframework.stereotype.Component class **'
一定要混淆的话,那么就必须得指定bean的名字:
@Component("myBeanName")
2·第一个问题我采用“指定bean”的方式解决后,又遇到新的问题:Parameter 0 of constructor in xx.x.A required a bean of type ‘xx.xx.B’ that could not be found.
我这里的情况是:A类在不属于被混淆的jar包,而A依赖的B在被混淆的包中,这就导致A使用的B其名字是未混淆的,但在混淆的包中B名字已经变化了,所以提示找不到。
目前的解决办法就是,让被混淆的包中的B保持不变,这样A就能找到B了。
<option>-keep class xx.xx.B { *; }</option>
本方法存在的问题
仅混淆了启动类所在的包,而依赖的包则没能混淆。