代碼混淆常見于安卓的
apk安裝文件, 服務(wù)端的代碼因為不易被普通用戶接觸到, 所以混淆不多。但是某些場景下, 比如:項目需要部署到客戶機器上, 就會有泄露代碼邏輯的風(fēng)險。
不過需要知道的是:使用proguard混淆代碼只能增加閱讀和理解的難度, 并不能百分百保證代碼安全。也即是達到讓開發(fā)人員看到這頭痛的代碼有99.99999%的沖動放棄閱讀,拍桌子說還不如我重寫一遍邏輯。
一、 ProGuard簡介
因為Java代碼是非常容易反編譯,況且Springboot和Android開發(fā)的應(yīng)用程序都是用Java代碼寫的,為了很好的保護Java源代碼,我們需要對編譯好后的class文件進行混淆。
ProGuard是一個混淆代碼的開源項目,它的主要作用是混淆代碼,殊不知ProGuard還包括以下4個功能:
- 壓縮(Shrink):檢測并移除代碼中無用的類、字段、方法和特性(Attribute)。
- 優(yōu)化(Optimize):對字節(jié)碼進行優(yōu)化,移除無用的指令。
- 混淆(Obfuscate):使用a,b,c,d這樣簡短而無意義的名稱,對類、字段和方法進行重命名。
- 預(yù)檢(Preveirfy):在Java平臺上對處理后的代碼進行預(yù)檢,確保加載的class文件是可執(zhí)行的。
二、混淆配置要點
- 建議逐個java包定義混淆規(guī)則,這樣思路更清晰 ;
- repository(dao)層需要保存包名和類名,因為Mybatis的xml文件中引用了dao層的接口 ;
- controller層注意在使用@PathVariable、@RequestParam時需要顯式聲明參數(shù)名 ;
- dao層用于映射數(shù)據(jù)庫表的類和controller層映射前臺參數(shù)的類,都需要保留類成員 ;
- 修改spring的bean命名策略,改成按類的全限定名來命名。
三、快速開始
本文基于springboot2.x + maven + proguard進行代碼混淆。
將源碼打包做代碼混淆還有其他方案,但是沒成功,最終選擇proguard,開始使用遇到各種問題,各種jar包版本問題,嘗試了5次不同方案,費了十牛二虎之力最終成功,Mark一下。
3.1 方案
proguard是最為廣為使用的工具之一,可是用他的客戶端方式來混淆springboot項目的時候最后總得不到可執(zhí)行的jar。后來發(fā)現(xiàn)了proguard-maven-plugin這個插件,所有proguard的指令都可以在pom中定義實現(xiàn),本文采用proguard-maven-plugin方案。
3.2 POM文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.erbadagang.data.jpa</groupId>
<artifactId>jpa</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>jpa</name>
<description>JPA project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.3.0.RELEASE</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--MySQL數(shù)據(jù)庫連接-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- proguard混淆插件-->
<plugin>
<groupId>com.github.wvengen</groupId>
<artifactId>proguard-maven-plugin</artifactId>
<version>2.2.0</version>
<executions>
<execution>
<!-- 打包的時候開始混淆-->
<phase>package</phase>
<goals>
<goal>proguard</goal>
</goals>
</execution>
</executions>
<configuration>
<injar>${project.build.finalName}.jar</injar>
<!--輸出的jar-->
<outjar>${project.build.finalName}.jar</outjar>
<!-- 是否混淆-->
<obfuscate>true</obfuscate>
<options>
<option>-target 1.8</option> <!--指定java版本號-->
<option>-dontshrink</option> <!--默認(rèn)開啟,不做收縮(刪除注釋、未被引用代碼)-->
<option>-dontoptimize</option><!--默認(rèn)是開啟的,這里關(guān)閉字節(jié)碼級別的優(yōu)化-->
<option>-adaptclassstrings</option><!--混淆類名之后,對使用Class.forName('className')之類的地方進行相應(yīng)替代-->
<option>-ignorewarnings
</option><!-- 忽略warn消息,如果提示org.apache.http.* 這個包里的類有問題,那么就加入下述代碼:-keep class org.apache.http.** { *; } -dontwarn org.apache.http.**-->
<option>-keep class org.apache.logging.log4j.util.* { *; }</option>
<option>-dontwarn org.apache.logging.log4j.util.**</option>
<option>-keepattributes
Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
</option><!--對異常、注解信息在runtime予以保留,不然影響springboot啟動-->
<!--不混淆所有interface接口-->
<!-- <option>-keepnames interface **</option>-->
<option>-keepclassmembers enum * { *; }</option><!--保留枚舉成員及方法-->
<option>-keepparameternames</option>
<option>-keepclasseswithmembers public class * {
public static void main(java.lang.String[]);}
</option> <!--保留main方法的類及其方法名-->
<!--忽略note消息,如果提示javax.annotation有問題,那麼就加入以下代碼-->
<option>-dontnote javax.annotation.**</option>
<option>-dontnote sun.applet.**</option>
<option>-dontnote sun.tools.jar.**</option>
<option>-dontnote org.apache.commons.logging.**</option>
<option>-dontnote javax.inject.**</option>
<option>-dontnote org.aopalliance.intercept.**</option>
<option>-dontnote org.aopalliance.aop.**</option>
<option>-dontnote org.apache.logging.log4j.**</option>
<!-- ##### 以下為需要根據(jù)項目情況修改 comment by 郭秀志 20200719 ##### -->
<!--入口程序類不能混淆,混淆會導(dǎo)致springboot啟動不了-->
<option>-keep class com.erbadagang.data.jpa.JpaApplication</option>
<option>-keep class com.erbadagang.data.jpa.base.* {*;}</option>
<option>-keep class com.erbadagang.data.jpa.entity.* {*;}</option>
<option>-keep class com.erbadagang.data.jpa.model.* {*;}</option>
<option>-keep class com.erbadagang.data.jpa.controller.* {*;}</option>
<!-- ##### 以上為需要根據(jù)項目情況修改 comment by 郭秀志 20200719 ##### -->
<option>-keep interface * extends * { *; }</option>
<!--不混淆所有類,保存原始定義的注釋-->
<option>-keepclassmembers class * {
@org.springframework.beans.factory.annotation.Autowired *;
@org.springframework.beans.factory.annotation.Value *;
}
</option>
</options>
<libs>
<!-- 添加依賴 java8-->
<lib>${java.home}/lib/rt.jar</lib>
<lib>${java.home}/lib/jce.jar</lib>
</libs>
</configuration>
<dependencies>
<!-- https://mvnrepository.com/artifact/net.sf.proguard/proguard-base -->
<dependency>
<groupId>net.sf.proguard</groupId>
<artifactId>proguard-base</artifactId>
<version>6.1.1</version>
</dependency>
</dependencies>
</plugin>
<!--Springboot repackage 打包-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<!-- spingboot 打包需要repackage否則不是可執(zhí)行jar -->
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<mainClass>com.erbadagang.data.jpa.JpaApplication</mainClass>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
直接在項目中將自己打包部分<build>......</build>的maven plugin(插件)替換成上面的代碼即可,各個插件的作用已經(jīng)注釋。
下面這些代碼是用來指定哪些包不被混淆,注意將包路徑改為你自己的,為了紀(jì)念小時候的神車“二八大杠”,我的包名統(tǒng)統(tǒng)以erbadagang作為前綴。
<!-- ##### 以下為需要根據(jù)項目情況修改 comment by 郭秀志 20200719 ##### -->
<!--入口程序類不能混淆,混淆會導(dǎo)致springboot啟動不了-->
<option>-keep class com.erbadagang.data.jpa.JpaApplication</option>
<option>-keep class com.erbadagang.data.jpa.base.* {*;}</option>
<option>-keep class com.erbadagang.data.jpa.entity.* {*;}</option>
<option>-keep class com.erbadagang.data.jpa.model.* {*;}</option>
<option>-keep class com.erbadagang.data.jpa.controller.* {*;}</option>
<!-- ##### 以上為需要根據(jù)項目情況修改 comment by 郭秀志 20200719 ##### -->
說明:
-keep class 類/包.** 表示保留類名;
-keepclassmembers class 類/包.**{ *;} 表示保留類下邊的所有變量,均不混淆。
另外需要注意的點, shrink這個功能一般最好別用,所以這里添加了<option>-dontshrink</option>,我就遇到過啟動jar的時候不支持壓縮jar的問題。
在使用客戶端的時候經(jīng)常會出現(xiàn)warings之類的提示,大多數(shù)處理方式都是使用-ignorewarings這個被官方指令來解決的,但是好多文章或參考資料中都有說明,這可能會帶來一些問題。
網(wǎng)上很多地方是把指令寫在一個外部proguard.conf來實現(xiàn)的,但是我用那些方法的一直沒有成功,所以直接把配置寫在了pom文件。
3.3 更換bean命名策略(本文未使用)
bean命名重復(fù)異常,由于proguard混淆貌似不能指定在basePackages下面類名混淆后唯一,不同包名經(jīng)常有a.class,b.class,c.class之類重復(fù)的類名,因此spring容器初始化bean的時候會報錯。
org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [com.example.demo.MvcDemoApplication]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'a' for bean class [com.example.demo.c.a] conflicts with existing, non-compatible bean definition of same name and class [com.example.demo.b.a]
我們可以通過改變spring的bean的命名策略來解決這個問題,把包名帶上,就唯一了。本文添加此功能導(dǎo)致jar無法啟動,這個解決方案僅作為參考,本文的源代碼無這部分功能。
3.4編譯打包
3.4.1 命令行打包
可以使用命令行方式打包,在項目的pom文件所在文件夾執(zhí)行mvn clean package -DskipTests。
3.4.2 工具打包
使用maven進行編譯打包,如圖選擇clean和package,然后點擊運行Maven編譯按鈕。

如果沒有錯誤,控制臺會輸出proguard的日志及最后的BUILD SUCCESS提示:
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ jpa ---
[INFO] Building jar: D:\dev\GitRepository\jpa\target\jpa-0.0.1-SNAPSHOT.jar
[INFO]
[INFO] --- proguard-maven-plugin:2.2.0:proguard (default) @ jpa ---
[INFO] execute ProGuard [-injars, 'D:\dev\GitRepository\jpa\target\jpa-0.0.1-SNAPSHOT_proguard_base.jar'(!META-INF/maven/**), -libraryjars, 'D:\dev\mvnRespo\org\springframework\boot\spring-boot-starter-data-jdbc\2.3.0.RELEASE\spring-boot-starter-data-jdbc-2.3.0.RELEASE.jar', -libraryjars, 'D:\dev\mvnRespo\org\springframework\boot\spring-boot-starter-jdbc\2.3.0.RELEASE\spring-boot-starter-jdbc-2.3.0.RELEASE.jar', -libraryjars, 'D:\dev\mvnRespo\com\zaxxer\HikariCP\3.4.5\HikariCP-3.4.5.jar', -libraryjars, 'D:\dev\mvnRespo\org\springframework\spring-jdbc\5.2.6.RELEASE\spring-jdbc-5.2.6.RELEASE.jar', -libraryjars, 'D:\dev\mvnRespo\org\springframework\data\spring-data-jdbc\2.0.0.RELEASE\spring-data-jdbc-2.0.0.RELEASE.jar', -libraryjars, 'D:\dev\mvnRespo\org\springframework\data\spring-data-relational\2.0.0.RELEASE\spring-data-relational-2.0.0.RELEASE.jar', -libraryjars, 'D:\dev\mvnRespo\org\springframework\data\spring-data-commons\2.3.0.RELEASE\spring-data-commons-2.3.0.RELEASE.jar', -libraryjars, 'D:\dev\mvnRespo\org\springframework\spring-tx\5.2.6.RELEASE\spring-tx-5.2.6.RELEASE.jar', -libraryjars, 'D:\dev\mvnRespo\org\springframework\spring-context\5.2.6.RELEASE\spring-context-5.2.6.RELEASE.jar', -libraryjars, 'D:\dev\mvnRespo\org\springframework\spring-beans\5.2.6.RELEASE\spring-beans-5.2.6.RELEASE.jar', -libraryjars, 'D:\dev\mvnRespo\org\slf4j\slf4j-api\1.7.30\slf4j-api-1.7.30.jar', -libraryjars, 'D:\dev\mvnRespo\org\springframework\boot\spring-boot-starter-data-jpa\2.3.0.RELEASE\spring-boot-starter-data-jpa-2.3.0.RELEASE.jar', -libraryjars, 'D:\dev\mvnRespo\org\springframework\boot\spring-boot-starter-aop\2.3.0.RELEASE\spring-boot-starter-aop-2.3.0.RELEASE.jar', -libraryjars, 'D:\dev\mvnRespo\org\springframework\spring-aop\5.2.6.RELEASE\spring-aop-5.2.6.RELEASE.jar', -libraryjars, 'D:\dev\mvnRespo\org\aspectj\aspectjweaver\1.9.5\aspectjweaver-1.9.5.jar', -libraryjars, 'D:\dev\mvnRespo\jakarta\transaction\jakarta.transaction-api\1.3.3\jakarta.transaction-api-1.3.3.jar', -libraryjars, 'D:\dev\mvnRespo\jakarta\persistence\jakarta.persistence-api\2.2.3\jakarta.persistence-api-2.2.3.jar', -libraryjars, 'D:\dev\mvnRespo\org\hibernate\hibernate-core\5.4.15.Final\hibernate-core-5.4.15.Final.jar', -libraryjars, 'D:\dev\mvnRespo\org\jboss\logging\jboss-logging\3.4.1.Final\jboss-logging-3.4.1.Final.jar', -libraryjars, 'D:\dev\mvnRespo\org\javassist\javassist\3.24.0-GA\javassist-3.24.0-GA.jar', -libraryjars, 'D:\dev\mvnRespo\net\bytebuddy\byte-buddy\1.10.10\byte-buddy-1.10.10.jar', -libraryjars, 'D:\dev\mvnRespo\antlr\antlr\2.7.7\antlr-2.7.7.jar', -libraryjars, 'D:\dev\mvnRespo\org\jboss\jandex\2.1.3.Final\jandex-2.1.3.Final.jar', -libraryjars, 'D:\dev\mvnRespo\com\fasterxml\classmate\1.5.1\classmate-1.5.1.jar', -libraryjars, 'D:\dev\mvnRespo\org\dom4j\dom4j\2.1.3\dom4j-2.1.3.jar', -libraryjars, 'D:\dev\mvnRespo\org\hibernate\common\hibernate-commons-annotations\5.1.0.Final\hibernate-commons-annotations-5.1.0.Final.jar', -libraryjars, 'D:\dev\mvnRespo\org\glassfish\jaxb\jaxb-runtime\2.3.3\jaxb-runtime-2.3.3.jar', -libraryjars, 'D:\dev\mvnRespo\org\glassfish\jaxb\txw2\2.3.3\txw2-2.3.3.jar', -libraryjars, 'D:\dev\mvnRespo\com\sun\istack\istack-commons-runtime\3.0.11\istack-commons-runtime-3.0.11.jar', -libraryjars, 'D:\dev\mvnRespo\org\springframework\data\spring-data-jpa\2.3.0.RELEASE\spring-data-jpa-2.3.0.RELEASE.jar', -libraryjars, 'D:\dev\mvnRespo\org\springframework\spring-orm\5.2.6.RELEASE\spring-orm-5.2.6.RELEASE.jar', -libraryjars, 'D:\dev\mvnRespo\org\springframework\spring-aspects\5.2.6.RELEASE\spring-aspects-5.2.6.RELEASE.jar', -libraryjars, 'D:\dev\mvnRespo\org\springframework\boot\spring-boot-starter-web\2.3.0.RELEASE\spring-boot-starter-web-2.3.0.RELEASE.jar', -libraryjars, 'D:\dev\mvnRespo\org\springframework\boot\spring-boot-starter\2.3.0.RELEASE\spring-boot-starter-2.3.0.RELEASE.jar', -libraryjars, 'D:\dev\mvnRespo\org\springframework\boot\spring-boot\2.3.0.RELEASE\spring-boot-2.3.0.RELEASE.jar', -libraryjars, 'D:\dev\mvnRespo\org\springframework\boot\spring-boot-autoconfigure\2.3.0.RELEASE\spring-boot-autoconfigure-2.3.0.RELEASE.jar', -libraryjars, 'D:\dev\mvnRespo\org\springframework\boot\spring-boot-starter-logging\2.3.0.RELEASE\spring-boot-starter-logging-2.3.0.RELEASE.jar', -libraryjars, 'D:\dev\mvnRespo\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar', -libraryjars, 'D:\dev\mvnRespo\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar', -libraryjars, 'D:\dev\mvnRespo\org\apache\logging\log4j\log4j-to-slf4j\2.13.2\log4j-to-slf4j-2.13.2.jar', -libraryjars, 'D:\dev\mvnRespo\org\apache\logging\log4j\log4j-api\2.13.2\log4j-api-2.13.2.jar', -libraryjars, 'D:\dev\mvnRespo\org\slf4j\jul-to-slf4j\1.7.30\jul-to-slf4j-1.7.30.jar', -libraryjars, 'D:\dev\mvnRespo\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar', -libraryjars, 'D:\dev\mvnRespo\org\yaml\snakeyaml\1.26\snakeyaml-1.26.jar', -libraryjars, 'D:\dev\mvnRespo\org\springframework\boot\spring-boot-starter-json\2.3.0.RELEASE\spring-boot-starter-json-2.3.0.RELEASE.jar', -libraryjars, 'D:\dev\mvnRespo\com\fasterxml\jackson\core\jackson-databind\2.11.0\jackson-databind-2.11.0.jar', -libraryjars, 'D:\dev\mvnRespo\com\fasterxml\jackson\core\jackson-annotations\2.11.0\jackson-annotations-2.11.0.jar', -libraryjars, 'D:\dev\mvnRespo\com\fasterxml\jackson\core\jackson-core\2.11.0\jackson-core-2.11.0.jar', -libraryjars, 'D:\dev\mvnRespo\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.11.0\jackson-datatype-jdk8-2.11.0.jar', -libraryjars, 'D:\dev\mvnRespo\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.11.0\jackson-datatype-jsr310-2.11.0.jar', -libraryjars, 'D:\dev\mvnRespo\com\fasterxml\jackson\module\jackson-module-parameter-names\2.11.0\jackson-module-parameter-names-2.11.0.jar', -libraryjars, 'D:\dev\mvnRespo\org\springframework\boot\spring-boot-starter-tomcat\2.3.0.RELEASE\spring-boot-starter-tomcat-2.3.0.RELEASE.jar', -libraryjars, 'D:\dev\mvnRespo\org\apache\tomcat\embed\tomcat-embed-core\9.0.35\tomcat-embed-core-9.0.35.jar', -libraryjars, 'D:\dev\mvnRespo\org\glassfish\jakarta.el\3.0.3\jakarta.el-3.0.3.jar', -libraryjars, 'D:\dev\mvnRespo\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.35\tomcat-embed-websocket-9.0.35.jar', -libraryjars, 'D:\dev\mvnRespo\org\springframework\spring-web\5.2.6.RELEASE\spring-web-5.2.6.RELEASE.jar', -libraryjars, 'D:\dev\mvnRespo\org\springframework\spring-webmvc\5.2.6.RELEASE\spring-webmvc-5.2.6.RELEASE.jar', -libraryjars, 'D:\dev\mvnRespo\org\springframework\spring-expression\5.2.6.RELEASE\spring-expression-5.2.6.RELEASE.jar', -libraryjars, 'D:\dev\mvnRespo\jakarta\xml\bind\jakarta.xml.bind-api\2.3.3\jakarta.xml.bind-api-2.3.3.jar', -libraryjars, 'D:\dev\mvnRespo\jakarta\activation\jakarta.activation-api\1.2.2\jakarta.activation-api-1.2.2.jar', -libraryjars, 'D:\dev\mvnRespo\org\springframework\spring-core\5.2.6.RELEASE\spring-core-5.2.6.RELEASE.jar', -libraryjars, 'D:\dev\mvnRespo\org\springframework\spring-jcl\5.2.6.RELEASE\spring-jcl-5.2.6.RELEASE.jar', -libraryjars, 'D:\dev\mvnRespo\org\projectlombok\lombok\1.18.12\lombok-1.18.12.jar', -outjars, 'D:\dev\GitRepository\jpa\target\jpa-0.0.1-SNAPSHOT.jar', -libraryjars, 'D:\Program Files\Java\jdk1.8.0_231\jre/lib/rt.jar', -libraryjars, 'D:\Program Files\Java\jdk1.8.0_231\jre/lib/jce.jar', -printmapping, 'D:\dev\GitRepository\jpa\target\proguard_map.txt', -printseeds, 'D:\dev\GitRepository\jpa\target\proguard_seed.txt', -target 1.8, -dontshrink, -dontoptimize, -adaptclassstrings, -ignorewarnings, -keep class org.apache.logging.log4j.util.* { *; }, -dontwarn org.apache.logging.log4j.util.**, -keepattributes
Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod, -keepclassmembers enum * { *; }, -keepparameternames, -keepclasseswithmembers public class * {
public static void main(java.lang.String[]);}, -dontnote javax.annotation.**, -dontnote sun.applet.**, -dontnote sun.tools.jar.**, -dontnote org.apache.commons.logging.**, -dontnote javax.inject.**, -dontnote org.aopalliance.intercept.**, -dontnote org.aopalliance.aop.**, -dontnote org.apache.logging.log4j.**, -keep class com.erbadagang.data.jpa.JpaApplication, -keep class com.erbadagang.data.jpa.base.* {*;}, -keep class com.erbadagang.data.jpa.entity.* {*;}, -keep class com.erbadagang.data.jpa.model.* {*;}, -keep class com.erbadagang.data.jpa.controller.* {*;}, -keep interface * extends * { *; }, -keepclassmembers class * {
@org.springframework.beans.factory.annotation.Autowired *;
@org.springframework.beans.factory.annotation.Value *;
}]
[INFO] proguard jar: D:\dev\mvnRespo\net\sf\proguard\proguard-base\6.1.1\proguard-base-6.1.1.jar
[proguard] ProGuard, version 6.1.1
......
[proguard] Preparing output jar [D:\dev\GitRepository\jpa\target\jpa-0.0.1-SNAPSHOT.jar]
[proguard] Copying resources from program jar [D:\dev\GitRepository\jpa\target\jpa-0.0.1-SNAPSHOT_proguard_base.jar] (filtered)
[INFO]
[INFO] --- spring-boot-maven-plugin:2.3.1.RELEASE:repackage (default) @ jpa ---
[INFO] Replacing main artifact with repackaged archive
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
3.4.3 target下文件
在target目錄下會生成5個文件:
-
jpa-0.0.1-SNAPSHOT.jar混淆后的Spring boot jar,里面包含完整的項目結(jié)構(gòu),可以運行,這個就是我們本文的產(chǎn)出物; - proguard_map.txt 混淆內(nèi)容的映射;
- proguard_seed.txt 參與混淆的類;
- 還有2個未混淆的原始jar包。

四、 測試jar
4.1 啟動
命令java -jar jpa-0.0.1-SNAPSHOT.jar啟動混淆后的jar,驗證是否正常運行。
D:\dev\GitRepository\jpa\target>java -jar jpa-0.0.1-SNAPSHOT.jar
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.3.0.RELEASE)
2020-07-19 09:12:33.766 INFO 9024 --- [ main] com.erbadagang.data.jpa.JpaApplication : Starting JpaApplication on guoxiuzhi with PID 9
024 (D:\dev\GitRepository\jpa\target\jpa-0.0.1-SNAPSHOT.jar started by guoxiuzhi in D:\dev\GitRepository\jpa\target)
2020-07-19 09:12:33.766 INFO 9024 --- [ main] com.erbadagang.data.jpa.JpaApplication : No active profile set, falling back to default
profiles: default
......
4.2 請求Controller
訪問URL:http://localhost:8080/user/selectOne?id=5,來測試功能是否正常。

返回了id=5的梅西相關(guān)的數(shù)據(jù),證明混合后的代碼無問題:
GET http://localhost:8080/user/selectOne?id=5
HTTP/1.1 200
Content-Type: application/json
Transfer-Encoding: chunked
Date: Sun, 19 Jul 2020 01:29:24 GMT
Keep-Alive: timeout=60
Connection: keep-alive
{
"id": 5,
"name": "Messi",
"age": 24,
"email": "look@erbadagang.com",
"createTime": null,
"updateTime": null,
"operator": null,
"deleteFlag": null,
"version": null
}
五、混淆效果
有幾次混淆后代碼可以正常運行,但是通過反編譯工具發(fā)現(xiàn)代碼根本就沒混淆,然后需再調(diào)整代碼達到混淆的目的,所以需要用反編譯工具進行驗證是否真的被混淆過。
java class的反編譯工具使用jd-gui。下載地址:http://java-decompiler.github.io/。
原來我是通過解壓工具把jar文件解壓到文件夾,看一下目錄結(jié)構(gòu)后再復(fù)制路徑到jd-gui進行反編譯,其實更便捷的方式是,直接拖動jar文件到jd-gui窗口即可。
源代碼的Service實現(xiàn)類包及類名稱:

如圖:可以看到混淆后service的實現(xiàn)類的
包名和類名已經(jīng)變成了a、b之類的短名稱,達到了混淆的效果。
底線
本文源代碼使用 Apache License 2.0開源許可協(xié)議,可從Gitee代碼地址通過git clone命令下載到本地或者通過瀏覽器方式查看源代碼。