1.情景展示
我的需求是:为了将项目部署到机器上时,既不影响项目的正常运行,又可以做到降低项目源码(class文件)的可读性,其主要目的是为了防盗。
一般情况下是用不到混淆器的,但是实际生活中往往存在这样的问题或需求,比方说:由于时间紧迫,两家企业被迫联合共同上线一个产品,现在是虽是合作关系,他们又可以相互取缔,同样的市场,蛋糕就这么大,时间长了难免互生嫌隙,所以为了保护各自产品被窃取,就需要防盗神器proguard了。
2.proguard简介
ProGuard 是一个免费的 Java类文件的压缩,优化,混肴器。它删除没有用的类,字段,方法与属性。使字节码最大程度地优化,使用简短且无意义的名字来重命名类、字段和方法 。eclipse已经把Proguard集成在一起了。
吐槽:但说句实在话,proguard虽然降低了代码的可读性,但是,仍是能够读懂的,只是费点劲罢了。正所谓:防君子不防小人。
3.proguard教程
第一步:maven配置(pom.xml)
<!--构建工具-->
<build>
<!--自定义打包后的项目名称
可以无视默认的打包名称规则:${artifactId}-${version}-->
<finalName>bill</finalName>
<plugins>
<!--maven编译插件-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<!--二选一-->
<version>${spring.version}</version>
<!--<version>2.3.1.RELEASE</version>-->
</plugin>
<!--java混淆器插件-->
<plugin>
<groupId>com.github.wvengen</groupId>
<artifactId>proguard-maven-plugin</artifactId>
<version>2.3.1</version>
<executions>
<execution>
<!-- 混淆时刻:这里是打包的时候混淆 -->
<phase>package</phase>
<goals>
<!-- 使用插件的什么功能: 混淆-->
<goal>proguard</goal>
</goals>
</execution>
</executions>
<configuration>
<proguardVersion>${proguard.version}</proguardVersion>
<!--<proguardVersion>6.2.2</proguardVersion>-->
<!-- 是否混淆-->
<obfuscate>true</obfuscate>
<!--关键:引入配置文件,这里换成你的配置文件所在路径,一般情况下就是把proguard.cfg放到这个目录-->
<proguardInclude>${project.basedir}/src/main/resources/proguard.cfg</proguardInclude>
<!-- 混淆时需要引用的java库,这些库的类不会做混淆 -->
<libs>
<lib>${java.home}/lib/rt.jar</lib>
<lib>${java.home}/lib/jce.jar</lib>
</libs>
<!--当<injar></injar>的值为:classes时,可以结合该标签使用,作用:相关混淆配置只为指定目录下的class文件起效-->
<!--<inFilter>com/marydon/**</inFilter>-->
<!-- 需要做混淆的jar或class目录,也就是:选择对什么东西进行加载-->
<injar>classes</injar>
<!--<injar>${project.build.finalName}.jar</injar>-->
<!--class 混淆后输出的jar包,说明:这个输出格式可有可无,下面会讲 -->
<outjar>${project.build.finalName}-pd.jar</outjar>
<!-- 输出目录 -->
<outputDirectory>${project.build.directory}</outputDirectory>
</configuration>
<dependencies>
<dependency>
<groupId>net.sf.proguard</groupId>
<artifactId>proguard-base</artifactId>
<version>${proguard.version}</version>
<!--<version>6.2.2</version>-->
<scope>runtime</scope>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
这里需要注意的一点是:build标签需要在dependencies下方
第二步:插件下载
先不要管proguard.cfg文件怎么写,搞定这个插件才能继续往下走,不然就是浪费时间,即使你将配置文件写好,离开了这个插件,要配置文件有啥用?
为了搞定最新版的插件,浪费了我不少时间,下面科普一下,如果你引入以上配置文件后,proguard插件下载成功,就可以跳过这一步了。
上面这个插件,明确的告诉你:阿里云maven中央仓库有!!!
如果下载失败,说明:该项目使用的maven中央仓库不是阿里云的,怎么办?
很简单,不用去该maven下面的settings.xml,直接在项目中引入即可。
<!--配置项目的jar包仓库-->
<repositories>
<!--阿里云仓库,id=central,会覆盖掉setting.xml中配置的中央仓库-->
<repository>
<id>central</id>
<name>central maven</name>
<url>https://maven.aliyun.com/repository/central</url>
<!--<url>http://maven.aliyun.com/nexus/content/groups/public/</url>-->
</repository>
<!--maven官网-->
<repository>
<id>public</id>
<name>public maven</name>
<url>https://mvnrepository.com</url>
</repository>
</repositories>
这样,仓库配置仅对本项目生效,也不会影响到其它项目对于settings.xml的依赖。
这里需要注意的一点是:repositories标签需要在dependencies上方
点击右侧maven视图里的这个按钮,网络较好的情况下,很快就下载完成了。
如果插件不再报错,基本上就成了
如果该插件下载不成功,就没有继续进行下去的必要了,等搞定再往下看。
第三步:proguard.cfg配置文件
新建proguard.cfg文件,并将其放到src/main/resources目录下
第四步:打包
使用maven插件打包,打开maven视图,找到package,进行打包即可。
打包成功日志
成功后,target目录下会多出三个文件
bill-pd.jar,就是项目混淆后的jar包(
也就是说:混淆后的代码会被proguard插件单独打成一个jar包,与bill.jar的主要区别就是:前者是带有混淆的class文件,后者是正常的class文件
这里,讲一下前面在pom.xml中配置的<outjar>${project.build.finalName}-pd.jar</outjar>标签,这个标签可有可无。
如果去掉指定混淆文件的输出格式,打包后会是什么样的呢?
区别在于:原来的bill-pd.jar变成了classes_proguard_base目录
里面的内容没有区别。
第五步:injar与outjar
这两个标签如果不配合好,效率将会大打折扣,而且还容易出错。由上面我们知道,
injar:是在插件混淆的源目录,也就是,混淆前的代码来源,它有两种表现形式:第一种是class目录,第二种是${project.build.finalName}.jar;
outjar:插件执行混淆完毕后,将要输出的文件打包成什么样的格式,这里仅支持jar包,不支持war包,injar标签也一样;如果不声明该标签的话,将会默认生成classes_proguard_base目录。
第六步:部署项目
方式一:部署jar包
编译源目录格式使用:<injar>${project.build.finalName}.jar</injar>
输出目录格式使用:<outjar>${project.build.finalName}-pd.jar</outjar>
这样,即使没有前后端分离,我们也可以确保bill-pd.jar包含的是项目的完整代码,可以拿出直接使用
测试结果如下:
可能会报这个错:Unable to open nested entry ********.jar
分析:因为javaUtils.jar是我自己封装的一个jar包,混淆插件会将它单独抽出来再次压缩,导致java解析失败,所以我就想将输入输出名字保持一致。
测试结果如下:
使用将输出的jar包名称和输入jar包名称保持一致
即:<outjar>${project.build.finalName}.jar</outjar>,其执行结果是:生成的默认值(项目名称_proguard_base.jar)
项目启动成功,但仍无法访问项目,这个问题是idea maven插件自身package命令的bug
解决方案,就是使用原始的maven命令,手动将其打成jar包,不懂的可以见文末推荐
项目访问成功(<outjar>${project.build.finalName}.jar</outjar>,必须是这个)
方式二:部署war包
编译源目录格式使用:<injar>classes</injar>
输出目录格式使用:删除<outjar></outjar>标签
打包标签设置成war:<packaging>war</packaging>
将项目打成war包后,用压缩软件打开,依次打开WEB-INF/classes目录,删掉,再将生成的混淆文件里的class文件复制进去即可。
写在最后
哪位大佬如若发现文章存在纰漏之处或需要补充更多内容,欢迎留言!!!