使用Proguard混淆Spring Boot项目代码

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 使用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
相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
29天前
ext portal+dwr+spring实现个性主页面拖拉效果的核心代码
ext portal+dwr+spring实现个性主页面拖拉效果的核心代码
40 6
|
18天前
|
设计模式 前端开发 Java
Spring MVC——项目创建和建立请求连接
MVC是一种软件架构设计模式,将应用分为模型、视图和控制器三部分。Spring MVC是基于MVC模式的Web框架,通过`@RequestMapping`等注解实现URL路由映射,支持GET和POST请求,并可传递参数。创建Spring MVC项目与Spring Boot类似,使用`@RestController`注解标记控制器类。
30 1
Spring MVC——项目创建和建立请求连接
|
18天前
|
Java 关系型数据库 MySQL
Maven——创建 Spring Boot项目
Maven 是一个项目管理工具,通过配置 `pom.xml` 文件自动获取所需的 jar 包,简化了项目的构建和管理过程。其核心功能包括项目构建和依赖管理,支持创建、编译、测试、打包和发布项目。Maven 仓库分为本地仓库和远程仓库,远程仓库包括中央仓库、私服和其他公共库。此外,文档还介绍了如何创建第一个 SpringBoot 项目并实现简单的 HTTP 请求响应。
85 1
Maven——创建 Spring Boot项目
|
1天前
|
缓存 监控 Java
|
1天前
|
缓存 监控 Java
|
21天前
|
Java 关系型数据库 MySQL
如何使用 maven 创建一个 Spring Boot项目
Maven 是一个强大的项目管理工具,通过配置 `pom.xml` 文件自动获取所需的 jar 包,提高开发效率。其核心功能包括项目构建和依赖管理。项目构建支持编译、测试、打包和发布等流程,而依赖管理则通过中央仓库、本地仓库和私有服务器获取和管理项目依赖。示例中展示了如何创建第一个 SpringBoot 项目并实现简单接口。
20 1
如何使用 maven 创建一个 Spring Boot项目
|
23天前
|
Java 数据库连接 Maven
mybatis使用一:springboot整合mybatis、mybatis generator,使用逆向工程生成java代码。
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和MyBatis Generator,使用逆向工程来自动生成Java代码,包括实体类、Mapper文件和Example文件,以提高开发效率。
68 2
mybatis使用一:springboot整合mybatis、mybatis generator,使用逆向工程生成java代码。
|
28天前
|
Java 应用服务中间件 Android开发
Eclipse创建Spring项目
本文介绍了在Eclipse中创建Spring项目的步骤,包括如何配置Tomcat服务器、创建项目、部署项目到Tomcat以及添加Spring框架所需的JAR包。
43 1
Eclipse创建Spring项目
|
30天前
|
前端开发 Java Apache
Springboot整合shiro,带你学会shiro,入门级别教程,由浅入深,完整代码案例,各位项目想加这个模块的人也可以看这个,又或者不会mybatis-plus的也可以看这个
本文详细讲解了如何整合Apache Shiro与Spring Boot项目,包括数据库准备、项目配置、实体类、Mapper、Service、Controller的创建和配置,以及Shiro的配置和使用。
211 1
Springboot整合shiro,带你学会shiro,入门级别教程,由浅入深,完整代码案例,各位项目想加这个模块的人也可以看这个,又或者不会mybatis-plus的也可以看这个
|
18天前
|
Java Apache Maven
Java/Spring项目的包开头为什么是com?
本文介绍了 Maven 项目的初始结构,并详细解释了 Java 包命名惯例中的域名反转规则。通过域名反转(如 `com.example`),可以确保包名的唯一性,避免命名冲突,提高代码的可读性和逻辑分层。文章还讨论了域名反转的好处,包括避免命名冲突、全球唯一性、提高代码可读性和逻辑分层。最后,作者提出了一个关于包名的问题,引发读者思考。
Java/Spring项目的包开头为什么是com?