SpringBoot结合ProGuard实现代码混淆(最新版)

 更新时间:2020年10月9日 15:06  
这篇文章主要介绍了SpringBoot结合ProGuard实现代码混淆(最新版),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言

研究ProGuard也花了两天时间,其实最主要的时间花在前面proguard读取jar包的时候相关jar冲突的问题,但是总的来说不用拆分SpringBoot项目并且实现代码混淆已经很舒服了。

ProGuard集成

 1.maven的配置

具体配置如下:

<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

2.相关异常解决

idea A required class was missing … org/apache/tools/ant/BuildListener
问题原因
这个问题就是上面提到的因为apache的编译用了一个ant-1.9.3的包,这个是级联引用的,开始我是内网maven私服,单纯的引入net.sf.proguard相关和com.github.wvengen相关的jar还是会缺少很多jar
解决方案
连上外网,配置你的maven的setting.xml 的mirror镜像地址,配置成Maven中央仓库的地址,将相关的jar都下下来,然后再通过命令把你本地maven仓库的jar上传到私服去

Can't process class [META-INF/versions/9/org/apache/logging/log4j/util/Base64Util.class]

Can't process class [META-INF/versions/11/module-info.class]
问题原因
这个问题的原因有很多方面,最主要的就是我们的jdk版本是1.8,我最开始用的ProGuard是5.3.3版本,然而我们SpringBoot的版本是2.3.3版本,SpringBoot2.3.3版本太新了,里面引用的相关包都是java9和java11的版本,这样ProGuard在读jar的时候会无法识别。这些问题在提升Proguard版本到6.2.2之后都解决了
解决方案
开始我的解决方案是忽略这些相关的jar, 例如在pom.xml的option配置:

<option>-libraryjars ${settings.localRepository}/com/zaxxer/HikariCP/3.4.5/HikariCP-3.4.5.jar(META-INF/versions/11/module-info.class)</option>

但是我这样配置之后,重新打包会提示:

The same input jar [E:\maven\repo\com\zaxxer\HikariCP\3.4.5\HikariCP-3.4.5.jar] is specified twice.
解决方案
而且我还尝试了maven引用的时候排除这些高版本的级联引用jar,单独引用低版本,但最终还是因为太繁琐而放弃了。直接提升Proguard版本到6.2.2 这些读jar的版本问题就解决了。Annotation-specified bean name ‘a' for bean class
问题原因
出现这个问题主要还是混淆之后,bean重名了,spring默认是把类名的首字母小写加载到容器里面,我们混淆类名之后,就容易造成beanName重复。
解决方案
庆幸的是,我们可以通过改变spring加载bean的命名策略来解决这个问题,把包名带上,同时在获取Spring上下文getBean的时候,加上包名路径即可
启动类配置,具体如下:

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

注意事项

基本上影响打包和启动的就上面一些问题了,其他的就是你们项目里面的细节了,

  • 比如DAO要保留,要和mybatis里面的Mapper映射对应,DAO里面的方法传参要改为map或者实体,另外序列化后的实体要保留
  • Controller里面的方法入参,如果用了实体,这部分实体也要保留(保证其变量不会被混淆,不然传值收不到)
  • 另外就是你们spring相关的XML里面,如果单独配置了Bean和Bean属性的,这类bean要保留,不能被混淆
  • 我这里保留了所有的接口和接口里面的方法,已经我们自定义的抽象类BaseService里面的方法名不会被混淆,这些你们可以自己定义,[email protected],按照我上面的配置,基本上可以不用重新构建beanName。正常的application启动就完事了
  • 其他的没了,就看你们还有没有什么特定的类不能被混淆,以及你们要混淆的力度(我们的要求是保留所有类名、接口信息和抽象类信息,除此之外的所有类和方法都被混淆!)

总的来说花了两天时间,有这样的成果也是值得高兴的,前一天解决jar冲突的比较多,主要原因就是最开始XX架构师搭建这个项目采用最新的SpringBoot版本,jdk确是1.8 , 很多不兼容。

来个最终的效果图吧:

在这里插入图片描述

参考案例

1、Springboot+proguard+maven 混淆.
2、proguard-spring-boot-example
3、官方解释
4、Proguard的Keep使用方法
5、ProGuard 最全混淆规则说明
6、ProGuard代码混淆技术详解
7、使用proguard混淆springboot代码

到此这篇关于SpringBoot结合ProGuard实现代码混淆(最新版)的文章就介绍到这了,更多相关SpringBoot ProGuard代码混淆内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞!

相关文章

  • 五分钟解锁springboot admin监控新技巧

    本文不会讲如何搭建企业的运维监控系统,有兴趣的可以去找找成熟的比如Zabbix、Prometheus,甚至比较简单的Wgcloud都能满足一定的需求,不在此赘述。本文讲解如何使用Springboot admin对spring boot项目进行应用监控,感兴趣的朋友一起看看吧...2021-06-20
  • Spring Boot如何通过java -jar启动

    大家开发的基于Spring Boot 的应用 ,jar形式, 发布的时候,绝大部分都是使用java -jar 启动。本文主要介绍了Spring Boot如何通过java -jar启动,一起来了解一下...2021-05-24
  • Java Springboot之Spring家族的技术体系

    今天带大家来学习Spring家族的技术体系,文中有非常详细的图文介绍及代码示例,对正在学习java的小伙伴们很有帮助,需要的朋友可以参考下...2021-05-22
  • java进阶之了解SpringBoot的配置原理

    今天带大家了解SpringBoot的相关知识,文中对SpringBoot的配置原理作了非常详细的图文示例及介绍,需要的朋友可以参考下...2021-06-04
  • springboot整合freemarker代码自动生成器

    最近做了一个工具,可以实现代码自动生成,今天整理出来分享给大家,需要的朋友们下面随着小编来一起学习学习吧...2021-05-27
  • 解决springboot利用ConfigurationProperties注解配置数据源无法读取配置信息问题

    今天在学习springboot利用ConfigurationProperties注解配置数据源的使用遇到一个问题无法读取配置信息,发现全部为null,纠结是哪里出了问题呢,今天一番思考,问题根源找到,下面把我的解决方案分享到脚本之家平台,感兴趣的朋友一起看看吧...2021-05-30
  • SpringBoot框架如何管理Xml和CSV

    XML是可扩展标记语言,是一种用于标记电子文件使其具有结构性的标记语言。CSV是一种通用的、相对简单的文件格式,通常被用在大数据领域,进行大规模的数据搬运操作,本文将介绍SpringBoot框架如何管理Xml和CSV...2021-06-17
  • SpringBoot配置ShedLock分布式定时任务

    ShedLock是一个在分布式环境中使用的定时任务框架,这篇文章主要介绍了SpringBoot配置ShedLock分布式定时任务,需要的朋友们下面随着小编来一起学习学习吧...2021-05-24
  • 使用SpringBoot自定义starter详解

    这篇文章主要介绍了使用Spring Boot自定义starter详解,文中有非常详细的代码示例,对正在学习java的小伙伴们有很好地帮助哟,需要的朋友可以参考下...2021-05-10
  • SpringBoot整合JWT的入门指南

    JWT全称是json web token,它将用户信息加密到 token 里,服务器不保存任何用户信息,服务器通过使用保存的密钥验证 token 的正确性,只要正确即通过验证,这篇文章主要给大家介绍了关于SpringBoot整合JWT的相关资料,需要的朋友可以参考下...2021-06-29
  • SpringBoot集成Druid连接池连接MySQL8.0.11

    这篇博客简单介绍spring boot集成druid连接池的简单配置和注意事项,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧...2021-07-02
  • Springboot基础之RedisUtils工具类

    本文来说下RedisUtils工具类,主要介绍了整合Redis、MyBatis,封装RedisUtils工具类等知识,文中有非常详细的代码示例,对正在学习java的小伙伴们有很好的帮助,需要的朋友可以参考下...2021-05-15
  • springboot集成opencv实现人脸识别功能的详细步骤

    大家都知道OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉和机器学习软件库,可以运行在Linux、Windows、Android和Mac OS操作系统上今天通过本文给大家分享springboot集成opencv实现人脸识别,感兴趣的朋友一起看看吧...2021-06-10
  • springboot+vue实现登录功能

    这篇文章主要为大家详细介绍了springboot+vue实现登录功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-05-27
  • Spring\SpringBoot配置连接数据库的方法

    最近在学习SpringBoot,第一步就是要配置数据库,本文详细的介绍了Spring\SpringBoot配置连接数据库的方法,有需要的朋友们下面随着小编来一起学习学习吧...2021-06-02
  • SpringBoot+MyBatisPlus+MySQL8实现树形结构查询

    这篇文章主要为大家详细介绍了SpringBoot+MyBatisPlus+MySQL8实现树形结构查询,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-06-07
  • SpringBoot框架如何操作Excel和PDF

    Excel和PDF都是常见的办公文件类型,在实际需求中有着较多的应用,excel经常用来处理数据,PDF文件格式可以将文字、字型、格式、颜色及独立于设备和分辨率的图形图像等封装在一个文件中,本文就讲述下SpringBoot框架如何操作这两种类型的文件...2021-06-17
  • springboot bean循环依赖实现以及源码分析

    最近在使用Springboot做项目的时候,遇到了一个循环依赖的 问题,所以下面这篇文章主要给大家介绍了关于springboot bean循环依赖实现以及源码分析的相关资料,需要的朋友可以参考下...2021-06-27
  • springboot实现发送QQ邮箱

    这篇文章主要为大家详细介绍了springboot实现发送QQ邮箱,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-06-06
  • SpringBoot如何优雅的整合Swagger Api自动生成文档

    在多人协作的开发过程中,API文档不仅可以减少等待,也能保证开发的持续进行,这篇文章主要给大家介绍了关于SpringBoot如何优雅的整合Swagger Api自动生成文档的相关资料,需要的朋友可以参考下...2021-07-08