ProGuard能够通过压缩、优化、混淆、预检等操作,检测并删除未使用的类,字段,方法和属性,分析和优化字节码,使用简短无意义的名称来重命名类,字段和方法。从而使代码更小、更高效、更难进行逆向工程。
<!-- ProGuard混淆插件-->
<plugin>
<groupId>com.github.wvengen</groupId>
<artifactId>proguard-maven-plugin</artifactId>
<version>2.6.0</version>
<executions>
<!-- package时执行proguard -->
<execution>
<phase>package</phase>
<goals>
<goal>proguard</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- 输入的jar包 -->
<injar>${project.build.finalName}.jar</injar>
<!-- 输出的jar包 -->
<outjar>${project.build.finalName}.jar</outjar>
<!-- 是否进行混淆,默认为true -->
<obfuscate>true</obfuscate>
<!-- 配置文件,通常为proguard.cfg,主要对options选项进行配置,所有的options选项都可以进行配置 -->
<proguardInclude>${project.basedir}/proguard.cfg</proguardInclude>
<!-- 额外的jar,项目编译所需的jar -->
<libs>
<lib>${java.home}/lib/rt.jar</lib>
<!--<lib>${java.home}/lib/jce.jar</lib>-->
<lib>${java.home}/lib/jsse.jar</lib>
</libs>
<!-- 对输入jar进行过滤,如对META-INFO文件不处理 -->
<inLibsFilter>!META-INF/**,!META-INF/versions/**</inLibsFilter>
<!-- 输出路径配置,必须包含injar标签中填写的jar -->
<outputDirectory>${project.build.directory}</outputDirectory>
<!-- 因为window的cmd有长度限制,而proguard混淆时依赖太多的jar包导致命令行过长在proguard-maven-plugin的configuration中加入下面配置,这个配置会把jar包放到临时目录以便缩短命令行-->
<putLibraryJarsInTempDir>true</putLibraryJarsInTempDir>
</configuration>
</plugin>
文件位置和pom.xml文件同级别
# 指定 java 版本
-target 1.8
-keepdirectories
# 关闭对代码进行优化压缩,开启会删除从未使用的类或者类成员变量等
-dontshrink
# 列出未使用的代码,可打印到标准输出或写入指定文件
#-printusage
# 关闭字节码级别的优化,如果不开启则设置如下配置,默认开启。
-dontoptimize
# 关闭预检,预检主要针对JavaME,Java6以后都不用预检,不关闭启动会报错: Expected stackmap frame at this location.
-dontpreverify
# 不生成大小写混写的类名
-dontusemixedcaseclassnames
# 对类成员的命名混淆采取唯一策略
-useuniqueclassmembernames
# 混淆类名之后,对使用Class.forName('className')之类的地方进行相应替代
-adaptclassstrings
#对异常、注解信息予以保留
#MethodParameters: #所有类(包括接口)的方法参数不混淆(包括没被keep的) 如果参数混淆了 mybatis mapper 参数绑定会出错(如#{id}
-keepattributes MethodParameters,Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
# 此选项将保存接口中的所有原始名称(不混淆)-->
-keepnames interface ** { *; }
#保留参数名,因为控制器,或者Mybatis等接口的参数如果混淆会导致无法接受参数,xml文件找不到参数
-keepparameternames
# 保留枚举成员及方法
-keepclassmembers enum * { *; }
#忽略warn消息
-ignorewarnings
#忽略note消息
-dontnote
#打印配置信息
-printconfiguration
# 排除混淆 指定的类名且类中的方法也不混淆
-keep class com.test.ac.processing.Application{<methods>;}
#配置不混淆
-keep class com.test.ac.config.** {*;}
#实体不混淆
-keep class com.test.ac.entity.** {*;}
#配置包路径不混淆
-keeppackagenames com.test.ac.config
#注解了Aspect的都不混淆,由于把framework下的所有类都不混淆,所以此配置就可有可无了
-keep @org.aspectj.lang.annotation.Aspect class * {*;}
配置完之后执行package命令就会有混淆之后的jar包了.
-keep [,modifier,...] class_specification; 指定该类以及类的成员和方法为entry points,不被ProGuard混淆
-keepclassmembers [,modifier,...] class_specification: 指定类的某些成员不被混淆,注意类名还是会被混淆
-keepnames class_specification: -keepclassmembers,allowshrinking class_specification的别名,保留名称不被混淆,但可以被压缩
-keepclassmembernames class_specification; -keepclasseswithmembers,allowshrinking class_specification的别名,保留名称不被混淆,但可以被压缩
-keeppackagenames [package_filter]: 保持包路径名称不混淆
class文件的一些变量名称也会发生变化,让代码可读性更差.
原因: proguard-maven-plugin插件放到了spring-boot-maven-plugin插件后面
解决:把proguard-maven-plugin插件放到spring-boot-maven-plugin前面
因为混淆之后类的命名就会发生重复了,导致bean名称也会重复,导致启动报错,在启动类做以下改动,重新bean名称.
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class)
.beanNameGenerator(new AnnotationBeanNameGenerator() {
@Override
protected String buildDefaultBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
return definition.getBeanClassName();
}
}).run(args);
}
因为window的cmd有长度限制,而proguard混淆时依赖太多的jar包导致命令行过长;
在proguard-maven-plugin的configuration中加入下面配置,这个配置会把jar包放到临时目录以便缩短命令行 <putLibraryJarsInTempDir>true</putLibraryJarsInTempDir>
如果想让代码更安全,也可以先混淆再使用classFinal加密:?classFinal使用