本文主要研究下如何使用proguard混淆springboot代碼html
<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>5.3.3</proguardVersion> <injar>${project.build.finalName}.jar</injar> <outjar>${project.build.finalName}.jar</outjar> <obfuscate>true</obfuscate> <proguardInclude>${project.basedir}/proguard.cfg</proguardInclude> <libs> <!-- Include main JAVA library required.--> <lib>${java.home}/lib/rt.jar</lib> <!-- Include crypto JAVA library if necessary.--> <lib>${java.home}/lib/jce.jar</lib> </libs> </configuration> <dependencies> <dependency> <groupId>net.sf.proguard</groupId> <artifactId>proguard-base</artifactId> <version>5.3.3</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>com.example.demo.MvcDemoApplication</mainClass> </configuration> </execution> </executions> </plugin>
這裏引用了com.github.wvengen的proguard-maven-plugin插件,使用的proguard-base版本是5.3.3
這裏使用java8,所以libs那裏照常配置rt.jar,jce.jar,若是是java9的話,則須要換成相應的模塊。
另外指定proguard的階段爲package,springboot打包在repackage階段
主要的重點在這個proguard.cfg配置
-target 1.8 ##指定java版本號 -dontshrink ##默認是開啓的,這裏關閉shrink,即不刪除沒有使用的類/成員 -dontoptimize ##默認是開啓的,這裏關閉字節碼級別的優化 -useuniqueclassmembernames ##對於類成員的命名的混淆採起惟一策略 -adaptclassstrings ## 混淆類名以後,對使用Class.forName('className')之類的地方進行相應替代 -dontusemixedcaseclassnames ## 混淆時不生成大小寫混合的類名,默認是能夠大小寫混合 -keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod ##對異常、註解信息在runtime予以保留,否則影響springboot啓動 -keepclasseswithmembers public class * { public static void main(java.lang.String[]);} ##保留main方法的類及其方法名 -keepclassmembers enum * { *; } ##保留枚舉成員及方法
因爲proguard混淆貌似不能指定在basePackages下面類名混淆後惟一,不一樣包名常常有a.class,b.class,c.class之類重複的類名,所以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] at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:181) ~[spring-context-4.3.10.RELEASE.jar!/:4.3.10.RELEASE] at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:308) ~[spring-context-4.3.10.RELEASE.jar!/:4.3.10.RELEASE] at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:228) ~[spring-context-4.3.10.RELEASE.jar!/:4.3.10.RELEASE] at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:270) ~[spring-context-4.3.10.RELEASE.jar!/:4.3.10.RELEASE] at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:93) ~[spring-context-4.3.10.RELEASE.jar!/:4.3.10.RELEASE] at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:687) ~[spring-context-4.3.10.RELEASE.jar!/:4.3.10.RELEASE] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:525) ~[spring-context-4.3.10.RELEASE.jar!/:4.3.10.RELEASE] at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) ~[spring-boot-1.5.5.RELEASE.jar!/:1.5.5.RELEASE] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) [spring-boot-1.5.5.RELEASE.jar!/:1.5.5.RELEASE] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) [spring-boot-1.5.5.RELEASE.jar!/:1.5.5.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) [spring-boot-1.5.5.RELEASE.jar!/:1.5.5.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118) [spring-boot-1.5.5.RELEASE.jar!/:1.5.5.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107) [spring-boot-1.5.5.RELEASE.jar!/:1.5.5.RELEASE] at com.example.demo.MvcDemoApplication.main(MvcDemoApplication.java:10) [classes!/:0.0.1-SNAPSHOT] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_151] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_151] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_151] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_151] at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48) [app.jar:0.0.1-SNAPSHOT] at org.springframework.boot.loader.Launcher.launch(Launcher.java:87) [app.jar:0.0.1-SNAPSHOT] at org.springframework.boot.loader.Launcher.launch(Launcher.java:50) [app.jar:0.0.1-SNAPSHOT] at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51) [app.jar:0.0.1-SNAPSHOT]
慶幸的是,咱們能夠經過改變spring的bean的命名策略來解決這個問題,把包名帶上,就惟一了
@SpringBootApplication public class MvcDemoApplication { public static class CustomGenerator implements BeanNameGenerator { @Override public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) { return definition.getBeanClassName(); } } public static void main(String[] args) { new SpringApplicationBuilder(MvcDemoApplication.class) .beanNameGenerator(new CustomGenerator()) .run(args); } }
至此大功告成
本文的proguard配置僅僅是根據自身工程的狀況來量身定作的,不是通用的,具體的場景還須要根據具體狀況對proguard參數進行調整。java