使用Proguard混淆Spring Boot项目代码

简介: 使用Proguard混淆Spring Boot项目代码

项目中需要对代码进行混淆处理,由于项目是标准的maven项目,便使用了proguard-maven-plugin来自动化混淆过程,但是在使用过程中也不免踩到了一些坑,网上也很少有提及,在此记录一下。

踩过的坑

spring bean名称冲突问题

默认proguard混淆后的类名类似a.class,b.class,但是不同包路径下类名可能发生重名,在spring中默认会把类名作为bean的名称,导致会报spring bean名称冲突的问题,可以通过重新实现BeanNameGenerator接口来解决:

@SpringBootApplication
@ComponentScan("com.abc.def")
public class Application {

    public static void main(String[] args) {
        new SpringApplicationBuilder(Application.class)
                .beanNameGenerator(new CustomBeanNameGenerator())
                .run(args);
    }

    private static class CustomBeanNameGenerator implements BeanNameGenerator {
        @Override
        public String generateBeanName(BeanDefinition d, BeanDefinitionRegistry r) {
            return d.getBeanClassName();
        }
    }
}

spring获取不到jar包里的包路径

spring boot启动后实现ApplicationRunner接口的初始化类并没有执行,也没有错误日志产生。后来把spring容器注册的Bean打印出来发现除了入口类和spring自己的类都没有加载。spring启动debug模式并调整日志级别为TRACE,发现spring没有解析出包含basePackage的jar包来,假设basePackage为com/abc/def/,不混淆代码的日志如下:

2019-11-24 19:33:49.703 [TRACE] [main] [o.s.c.i.s.PathMatchingResourcePatternResolver : 323] Resolved classpath location [com/abc/def/] to resources [URL [jar:file:/tmp/foo/lib/service-facade-1.0.jar!com/abc/def/], URL [jar:file:/tmp/foo/lib/service-impl-1.0.jar!com/abc/def/]]

经proguard混淆后日志如下:

2019-11-24 19:33:49.703 [TRACE] [main] [o.s.c.i.s.PathMatchingResourcePatternResolver : 323] Resolved classpath location [com/abc/def/] to resources []

但是将混淆后jar包先解压后再压缩处理,却可以正常加载。也就是说proguard在打包过程中把包路径信息丢失了。需要配置keepdirectories参数。

JDK9编译的jar包类冲突

JDK9编译出来的jar包会和一些类冲突,需要配置inLibsFilter排除掉。

多jar包混淆

默认proguard-maven-plugin插件只能通过injar参数将一个jar包混淆,而常见的项目都是多模块项目,这时就需要通过配置assembly参数来实现。

参考配置

Pom.xml:

<plugin>
  <groupId>com.github.wvengen</groupId>
  <artifactId>proguard-maven-plugin</artifactId>
  <version>2.2.0</version>
  <executions>
    <execution>
      <id>release</id>
      <phase>package</phase>
      <goals>
        <goal>proguard</goal>
      </goals>
      <configuration>
        <assembly>
          <inclusions>
            <inclusion>
              <groupId>com.abc.def</groupId>
              <artifactId>lib1</artifactId>
            </inclusion>
            <inclusion>
              <groupId>com.abc.def</groupId>
              <artifactId>lib2</artifactId>
            </inclusion>
          </inclusions>
        </assembly>
        <!--exclude jdk9-->
        <inLibsFilter>!META-INF/versions/9/**.class</inLibsFilter>
        <proguardInclude>proguard.conf</proguardInclude>
        <libs>
          <lib>${java.home}/lib/rt.jar</lib>
          <lib>${java.home}/lib/jce.jar</lib>
        </libs>
        <!--<silent>true</silent>-->
      </configuration>
    </execution>
  </executions>
  <dependencies>
    <dependency>
      <groupId>net.sf.proguard</groupId>
      <artifactId>proguard-base</artifactId>
      <version>6.2.0</version>
    </dependency>
  </dependencies>
</plugin>

proguard.conf:

-dontshrink
-dontoptimize
-keepdirectories
-adaptclassstrings
-dontusemixedcaseclassnames
-flattenpackagehierarchy 'com.abc.def'
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,LocalVariable*Table,*Annotation*,Synthetic,EnclosingMethod

-keep class com.abc.def.Application
-keep class * extends org.springframework.boot.ApplicationRunner

# Keep - Applications. Keep all application classes, along with their 'main'
# methods.
-keepclasseswithmembers public class * {
    public static void main(java.lang.String[]);
}

# Also keep - Enumerations. Keep the special static methods that are required in
# enumeration classes.
-keepclassmembers enum  * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

# Keep names - Native method names. Keep all native class/method names.
-keepclasseswithmembers,includedescriptorclasses,allowshrinking class * {
    native <methods>;
}

参考

  1. Proguard官方文档
  2. proguard-maven-plugin
  3. proguard-spring-boot-example
  4. 基于ProGuard-Maven-Plugin的自定义代码混淆插件
  5. 解决Proguard5.3版本不支持含有JDK9代码的Jar包混淆问题
  6. Bug#35 Missing directory entries in jars
相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
目录
相关文章
|
10月前
|
安全 Java 应用服务中间件
Spring Boot + Java 21:内存减少 60%,启动速度提高 30% — 零代码
通过调整三个JVM和Spring Boot配置开关,无需重写代码即可显著优化Java应用性能:内存减少60%,启动速度提升30%。适用于所有在JVM上运行API的生产团队,低成本实现高效能。
1123 3
|
9月前
|
人工智能 监控 Java
零代码改造 + 全链路追踪!Spring AI 最新可观测性详细解读
Spring AI Alibaba 通过集成 OpenTelemetry 实现可观测性,支持框架原生和无侵入探针两种方式。原生方案依赖 Micrometer 自动埋点,适用于快速接入;无侵入探针基于 LoongSuite 商业版,无需修改代码即可采集标准 OTLP 数据,解决了原生方案扩展性差、调用链易断链等问题。未来将开源无侵入探针方案,整合至 AgentScope Studio,并进一步增强多 Agent 场景下的观测能力。
3160 98
|
监控 Java 数据安全/隐私保护
阿里面试:SpringBoot启动时, 如何执行扩展代码?你们项目 SpringBoot 进行过 哪些 扩展?
阿里面试:SpringBoot启动时, 如何执行扩展代码?你们项目 SpringBoot 进行过 哪些 扩展?
|
9月前
|
安全 Java 测试技术
《深入理解Spring》单元测试——高质量代码的守护神
Spring测试框架提供全面的单元与集成测试支持,通过`@SpringBootTest`、`@WebMvcTest`等注解实现分层测试,结合Mockito、Testcontainers和Jacoco,保障代码质量,提升开发效率与系统稳定性。
|
10月前
|
安全 IDE Java
Spring 的@FieldDefaults和@Data:Lombok 注解以实现更简洁的代码
本文介绍了如何在 Spring 应用程序中使用 Project Lombok 的 `@Data` 和 `@FieldDefaults` 注解来减少样板代码,提升代码可读性和可维护性,并探讨了其适用场景与限制。
343 0
Spring 的@FieldDefaults和@Data:Lombok 注解以实现更简洁的代码
|
12月前
|
Java 关系型数据库 数据库连接
Spring Boot项目集成MyBatis Plus操作PostgreSQL全解析
集成 Spring Boot、PostgreSQL 和 MyBatis Plus 的步骤与 MyBatis 类似,只不过在 MyBatis Plus 中提供了更多的便利功能,如自动生成 SQL、分页查询、Wrapper 查询等。
1065 2
|
12月前
|
安全 Java Nacos
0代码改动实现Spring应用数据库帐密自动轮转
Nacos作为国内被广泛使用的配置中心,已经成为应用侧的基础设施产品,近年来安全问题被更多关注,这是中国国内软件行业逐渐迈向成熟的标志,也是必经之路,Nacos提供配置加密存储-运行时轮转的核心安全能力,将在应用安全领域承担更多职责。
|
前端开发 Java API
酒店管理系统基于 JavaFX Spring Boot 和 React 经典项目重构实操
本文介绍了基于现代技术栈的酒店管理系统开发方案,整合了JavaFX、Spring Boot和React三大技术框架。系统采用前后端分离架构,JavaFX构建桌面客户端,React开发Web管理界面,Spring Boot提供RESTful API后端服务。核心功能模块包括客房管理和客户预订流程,文中提供了JavaFX实现的客房管理界面代码示例和React开发的预订组件代码,展示了如何实现客房信息展示、添加修改操作以及在线预订功能。
747 0
|
12月前
|
Java 测试技术 Spring
简单学Spring Boot | 博客项目的测试
本内容介绍了基于Spring Boot的博客项目测试实践,重点在于通过测试驱动开发(TDD)优化服务层代码,提升代码质量和功能可靠性。案例详细展示了如何为PostService类编写测试用例、运行测试并根据反馈优化功能代码,包括两次优化过程。通过TDD流程,确保每项功能经过严格验证,增强代码可维护性与系统稳定性。
416 0