likes
comments
collection
share

SpringBoot3.2 Proguard代码混淆优化

作者站长头像
站长
· 阅读数 23

SpringBoot3.2 Proguard代码混淆优化

引言

近期项目做了SpringBoot3.2的升级,以前关于项目中混淆代码的配置也做了下优化。

在这里,与大家简单分享下相关配置,有什么问题欢迎讨论。

环境

组件名称版本
JDK17
SpringBoot3.2.0
Gradle8.5
ProGuard7.4.2

项目集成ProGuard

SpringBoot3.2 Proguard代码混淆优化

参考github上progaurd官方提供的配置,选择了7.4.2版本,但是使用此配置,项目编译直接失败。

报错信息:Could not get unknown property 'ProGuardTask' for project ':proguard-example-config' of type org.gradle.api.Project

SpringBoot3.2 Proguard代码混淆优化

于是根据相应的错误提示,修改了相关配置,修改后的配置关键点如下:

import proguard.gradle.ProGuardTask

buildscript {
    repositories {
        mavenCentral()
    }

    dependencies {
        classpath("com.guardsquare:proguard-gradle:7.4.2")
    }
}
tasks.register('proguard', ProGuardTask) {
    configuration file('proguard.pro')

    injars(tasks.named('jar').flatMap { it.archiveFile })

    def javaHome = System.getProperty('java.home')
    if (System.getProperty('java.version').startsWith('1.')) {
        libraryjars "${javaHome}/lib/rt.jar"
    } else {
        libraryjars "${javaHome}/jmods/java.base.jmod", jarfilter: '!**.jar', filter: '!module-info.class'
    }

    verbose()
    outjars layout.buildDirectory.file("libs/${project.name}-minified.jar")
}

引入之后,重新build一下,就可以看到proguard task了,执行该任务,就可以在build/libs下看到相应的混淆Jar包

混淆配置

好了,看到这,终于到了这篇文章的重点了。

在我们项目中,混淆的代码主要是一些自研中间件的相关配置。在对外项目中,只需要引入这个中间件Jar包即可,不需要做项目中做额外配置。

混淆原则

了解到此需要之后,我们就可以简单总结出几个原则对代码做混淆了。

  1. 对外使用的类不做混淆

  2. Spring相关的类不做混淆

  3. 重写的方法、get/set方法不做混淆

  4. 异常、注解、枚举不做混淆

混淆配置文件

混淆的配置文件如下:proguard.pro

# JDK目标版本17
-target 17

# 禁用shrink(删除未使用的类和成员)
-dontshrink

# 禁用优化(字节码级别的优化)
-dontoptimize

# 忽略打包时的警告信息
-ignorewarnings

# 不跳过非公共类文件和成员
-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers

# 类名不使用混合大小写
-dontusemixedcaseclassnames

# 优化时允许访问并修改有修饰符的类和类的成员
-allowaccessmodification

# 混淆类名之后,对使用Class.forName("className")之类的地方进行相应替代
-adaptclassstrings

# 保留所有包名
-keeppackagenames

# 使用唯一的类成员名称
-useuniqueclassmembernames

# 保留异常、注解等特殊信息,避免影响 Spring Boot 启动
-keepattributes Exceptions,InnerClasses,Signature?Deprecated,SourceFile,LineNumberTable,LocalVariable*Table,*Annotation*,SyntheticjEnclosingMethod

# 保留所有的set/get方法
-keepclassmembers public class * {
    void set*(***);
    *** get*();
}

## 保留外部调用类
-keep class com.zl.exaplme.util.MinIOUtil { *; }

# 保留带有 Spring 相关注解的类、字段和方法
-keepclassmembers class * {
    @org.springframework.beans.factory.annotation.Autowired *;
    @org.springframework.beans.factory.annotation.Qualifier *;
    @org.springframework.beans.factory.annotation.Value *;
    @org.springframework.beans.factory.annotation.Required *;
    @org.springframework.context.annotation.Bean *;
    @org.springframework.context.annotation.Primary *;
    @org.springframework.boot.context.properties.ConfigurationProperties *;
    @org.springframework.boot.context.properties.EnableConfigurationProperties *;
    @javax.annotation.PostConstruct *;
    @javax.annotation.PreDestroy *;
}

# 保留实现 Serializable 接口的类
-keep class * implements java.io.Serializable { *; }

# 保留实现 CommandLineRunner 接口的类
-keep class * implements org.springframework.boot.CommandLineRunner { *; }

## 保留使用 @Configuration 注解的类
#-keep @org.springframework.context.annotation.Configuration class * { *; }
#
## 保留使用 @Component 注解的类
#-keep @org.springframework.stereotype.Component class * { *; }
#
## 保留使用 @Service 注解的类
#-keep @org.springframework.stereotype.Service class * { *; }

# 保留使用 @ConfigurationProperties 注解的类
-keep @org.springframework.boot.context.properties.ConfigurationProperties class * { *; }

# 保留使用 @Slf4j 注解的类和生成的 log 字段
-keep @lombok.extern.slf4j.Slf4j class * {*;}
-keepclassmembers class * {
    lombok.extern.slf4j.Slf4j log;
}

# 保留枚举类的所有成员
-keepclassmembers enum * { *; }

# 保留主方法
-keepclasseswithmembers public class * { public static void main(java.lang.String[]); }

# 保留源文件和行号信息
-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable

# 忽略所有的警告信息
-dontwarn *

# 混淆字典
-applymapping mapping.map

SpringBoot自动注入与混淆Mapping映射

由于我们混淆的主要是中间件代码,使用了SpringBoot的自动注入机制,3.2版本的spring.factories变更为新的方式,这里需要额外注意一下。

SpringBoot3.2 Proguard代码混淆优化

在这里配置的是类的全路径,但是在混淆之后,类名发生了变化。

为了解决这个问题,以及做到更好的混淆,可以使用自定义的混淆字典,在proguard.pro同级目录下新增一个mapping.map文件,在这里定义混淆前后的类名映射。

com.zl.exaplme.config.MinIOAutoConfiguration -> com.zl.exaplme.config.xyz:

如将 MinIOAutoConfiguration 混淆成xyz

同时将自动注入的类全路径修改为混淆后的类名:com.zl.exaplme.config.xyz

总结

经过以上步骤,就大致完成了一个SpringBoot Starter的代码混淆。

转载自:https://juejin.cn/post/7376186315644174345
评论
请登录