Запутать код Springboot с помощью proguard

задняя часть GitHub Spring maven

последовательность

В этой статье в основном изучается, как использовать proguard для запутывания кода Springboot.

maven

			<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>

Здесь упоминается подключаемый модуль proguard-maven-plugin для com.github.wvengen, а используемая версия proguard-base — 5.3.3. Здесь используется Java8, поэтому rt.jar и jce.jar настраиваются как обычно в либах, если это java9, то его нужно заменить на соответствующий модуль. Кроме того, в качестве package указана стадия proguard, а в стадии repackage запакована springboot.

proguard.cfg

Основное внимание уделяется этой конфигурации 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 слишком много, на всякий случай закройте сжатие и оптимизацию, начиная с базовой конфигурации
  • Следует отметить 2 момента: 1 — сохранить имя класса и метода основного метода, иначе он не запустится; 2 — сохранить исходную информацию, такую ​​как аннотации, через keepattributes, иначе это повлияет на запуск Springboot
  • Здесь, поскольку в примере проекта используется перечисление, оно также сохраняется.

Исключение повторяющегося имени компонента

Поскольку путаница 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]

Измените стратегию именования компонентов

К счастью, мы можем решить эту проблему, изменив стратегию именования bean-компонента Spring и указав имя пакета, оно уникально.

@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 в соответствии с конкретной ситуацией.

doc