1、Springboot+proguard+maven 混淆.
2、proguard-spring-boot-example
3、官方解釋
4、Proguard的Keep使用方法
5、ProGuard 最全混淆規則說明
6、ProGuard程式碼混淆技術詳解
7、使用proguard混淆springboot程式碼
研究ProGuard也花了兩天時間,其實最主要的時間花在前面proguard讀取jar包的時候相關jar衝突的問題,但是總的來說不用拆分SpringBoot專案並且實現程式碼混淆已經很舒服了。
具體設定如下:
<build>
<finalName>${artifactId}</finalName>
<plugins>
<plugin>
<groupId>com.github.wvengen</groupId>
<artifactId>proguard-maven-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals><goal>proguard</goal></goals>
</execution>
</executions>
<configuration>
<proguardVersion>6.2.2</proguardVersion>
<injar>${project.build.finalName}.jar</injar>
<outjar>${project.build.finalName}.jar</outjar>
<!--<proguardInclude>${project.basedir}/proguard.cfg</proguardInclude>-->
<obfuscate>true</obfuscate>
<options>
<!-- 不做收縮(刪除註釋、未被參照程式碼)-->
<option>-dontshrink</option>
<!-- 不做優化(變更程式碼實現邏輯)-->
<option>-dontoptimize</option>
<!--保持目錄結構,否則spring的自動注入無法使用-->
<!--<option>-keepdirectories</option>-->
<option>-keepattributes Exceptions,InnerClasses,Signature,Deprecated,
SourceFile,LineNumberTable, *Annotation*,EnclosingMethod
</option>
<option>-adaptclassstrings</option>
<option>
<!-- 保護程式入口 -->
-keep class com.jingchen.ccny.CmepApplication { *; }
</option>
<option>-keepnames interface ** { *; }</option>
<!-- 固定幾個類不能混淆-->
<option>-keepnames class com.jingchen.ccny.base.BaseService { *; }</option>
<option>-keep class com.jingchen.ccny.common.cache.ConvertorNewCache { *; }</option>
<option>-keep class com.jingchen.ccny.base.ControllerContext { *; }</option>
<option>-keep class * extends com.jingchen.ccny.base.BaseService</option>
<option>-keep class * implements com.jingchen.ccny.common.service.CallBackGuiService</option>
<option>-keep class * implements com.jingchen.ccny.common.service.CallBackUDService</option>
<option>-keep class com.jingchen.ccny.util.SpringUtil</option>
<!--<option>-keep interface * extends * { *; }</option>-->
<!-- 此選項將在所有包的所有類中儲存所有原始定義的註釋.-->
<option>
-keep class * {
@org.springframework.beans.factory.annotation.Autowired *;
@org.springframework.beans.factory.annotation.Value *;
@org.springframework.stereotype.Service *;
@org.springframework.stereotype.Component *;
@org.springframework.scheduling.annotation.Scheduled *;
}
</option>
</options>
<libs>
<!-- Include main JAVA library required.-->
<lib>${java.home}/lib/rt.jar</lib>
<lib>${java.home}/lib/jce.jar</lib>
</libs>
</configuration>
<dependencies>
<dependency>
<groupId>net.sf.proguard</groupId>
<artifactId>proguard-base</artifactId>
<version>6.2.2</version>
</dependency>
</dependencies>
</plugin>
<!-- Maven assembly must be run after proguard obfuscation so it take already obfuscated files.-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<mainClass>com.jingchen.ccny.CcnyApplication</mainClass>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
這裡裡面級聯參照的jar很多,建議設定了私服的人先把映象地址設定成maven中央倉庫地址,這樣先下下來相關依賴的包,然後再上傳到你們的私服上去。據我研究中知道的jar就有:
注意:不連外網設定maven中央倉庫的話,少了jar你們會很頭疼的。而且不止net.sf.proguard相關包,還包括了com.guardsquare.proguard-base 和 com.guardsquare.proguard-core 相關的jar,所以真的連外網下包很重要!!!!
推薦一個IDEA解決maven參照衝突的外掛:Maven Helper
<option>-libraryjars ${settings.localRepository}/com/zaxxer/HikariCP/3.4.5/HikariCP-3.4.5.jar(META-INF/versions/11/module-info.class)</option>
但是我這樣設定之後,重新打包會提示:
@SpringBootApplication
public class CcnyApplication{
public static class CustomGenerator implements BeanNameGenerator {
@Override
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
return definition.getBeanClassName();
}
}
public static void main(String[] args) {
SpringApplicationBuilder sab=new SpringApplicationBuilder(CcnyApplication.class)
.beanNameGenerator(new CustomGenerator());
//這裡如果想列印你載入的Spring的bean,可以這樣做:
ApplicationContext ac =sab.run(args);
Arrays.stream(ac.getBeanDefinitionNames()).forEach(System.out::println);
}
}
這樣設定,你啟動的時候就能看到載入的所有的beanName(這裡Service會帶上package路徑)
其他地方getBean的用法:
//這裡的packagePath = com.jingchen.ccny.service
CallBackGuiService callBackGuiService = (CallBackGuiService) SpringUtil.getBean(packagePath+serviceName);
callBackResult = callBackGuiService.excute(convertMap);
這樣你就能正常的獲取到Spring容器載入的beanName了
總的來說花了兩天時間,有這樣的成果也是值得高興的,前一天解決jar衝突的比較多,主要原因就是最開始XX架構師搭建這個專案採用最新的SpringBoot版本,jdk確是1.8 , 很多不相容。
來個最終的效果圖吧: