如何使用 spring-boot gradle 插件进行 proguard

Posted

技术标签:

【中文标题】如何使用 spring-boot gradle 插件进行 proguard【英文标题】:how to proguard with spring-boot gradle plugin 【发布时间】:2019-03-23 08:41:08 【问题描述】:

如何使用 spring boot 2 和 gradle build 设置 proguard 混淆?

你好。尝试使用其 gradle 插件和 Proguard gradle 插件设置 Spring Boot 应用程序的代码混淆。 Google 主要为旧版 spring-boot-gradle-plugin 提供了一些方法(即this closest one 使用不存在的 bootRepackage 任务),或使用 maven 插件(具有重新打包目标)。

据我了解,想法是在 jar 打包之前对类进行混淆,但我在当前的 gradle 插件版本中看不到任何入口点,并且希望避免手动提取和压缩。

有人在用那个组合吗? Spring Boot 版本 >=2.0.3。

【问题讨论】:

【参考方案1】:

我认为今天是不可能的,你必须手动提取并拉回。

一个可能有用的手动提取和拉回的示例:

build.gradle

version = '0.1.0'

buildscript 
    dependencies 
        classpath 'net.sf.proguard:proguard-gradle:6.0.3'
        classpath 'net.sf.proguard:proguard-base:6.0.3'
    


apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

task extractJar(type: Copy) 
    def zipFile = file("$buildDir/libs/your_project_name-$version.jar")
    def outputDir = file("$buildDir/unpacked/")

    from zipTree(zipFile)
    into outputDir


task proguard(type: proguard.gradle.ProGuardTask) 
    doFirst 
        tasks.extractJar.execute();
    
    configuration 'proguard.conf'
    injars  "$buildDir/unpacked/BOOT-INF/classes"
    outjars "$buildDir/obfClasses"

    libraryjars "$System.getProperty('java.home')/lib/rt.jar"
    libraryjars "$buildDir/unpacked/BOOT-INF/lib"

    doLast 
        tasks.deleteClasses.execute();
    


task deleteClasses(type: Delete) 
    delete "$buildDir/unpacked/BOOT-INF/classes/"

    doLast 
        tasks.copyObfuscatedClasses.execute()
    


task copyObfuscatedClasses(type: Copy) 
    from "$buildDir/obfClasses"
    into "$buildDir/unpacked/BOOT-INF/classes/"
    include 'com/**'
    include '*.properties'

    doLast 
        tasks.copyObfuscatedJars.execute()
    


task copyObfuscatedJars(type: Copy) 
    from "$buildDir/obfClasses"
    into "$buildDir/unpacked/BOOT-INF/lib/"
    include '*.jar'

    doLast 
        tasks.deleteObfuscated.execute()
    


task deleteObfuscated(type: Delete) 
    delete 'build/obfClasses'

    doLast 
        tasks.repackage.execute()
    


task repackage(type: Zip) 
    from  "$buildDir/unpacked"
    entryCompression ZipEntryCompression.STORED
    archiveName "your_project_name-$version-obf.jar"
    destinationDir(file("$buildDir/libs"))

proguard.conf

-ignorewarnings
-keepdirectories

-keep interface com.your_package.**  *; 
-keep class com.your_package.main *; 
-keep class com.your_package.model.**  *; 

-keepparameternames
-keepclassmembers @org.springframework.** class * 
    *;


-keepclassmembers @org.springframework.** interface * 
    *;


-keepclassmembers enum * 
    public static **[] values();
    public static ** valueOf(java.lang.String);


-keep @org.springframework.** class *
-keepclassmembers @javax.** class *  *; 

-dontwarn org.springframework.**
-dontwarn javax.**
-dontwarn org.yaml.snakeyaml.**
-dontwarn okhttp3.**

【讨论】:

谢谢。你是一个活生生的救星。基于Github上的这个解决方案,我已经为一般Java项目提供了一个解决方案。【参考方案2】:

您是否尝试过在 build.gradle 中为其编写任务?

task obfuscate(type: proguard.gradle.ProGuardTask, dependsOn: jar) 
    mustRunAfter ('javadoc')
    inputs.file  file("$jar.archivePath")
    outputs.file file("$buildDir/proguard/$project.name-$project.version.jar")

    injars  "$jar.archivePath"

    // JDK 8 and below use jars on the classpath
    if (JavaVersion.current().java8Compatible &&    !JavaVersion.current().java9Compatible) 
        println "Obfuscation inputs based on JDK 8 layout."
        libraryjars "$javaHome/lib/rt.jar"
        libraryjars "$javaHome/lib/jce.jar"
        libraryjars "$javaHome/lib/ext/jfxrt.jar"
     else 
        // JDK 9 and above use modules on the module-path
        println "Obfuscation inputs based on JDK 9+ module layout."
        def jdkModuleList = [
            'java.base', 'java.datatransfer', 'java.desktop',
            'java.instrument', 'java.logging',
            'java.management', 'java.prefs', 'java.rmi',
            'java.scripting', 'java.xml',
            'jdk.attach'
        ]
        jdkModuleList.forEach 
            libraryjars "$javaHome/jmods/$it.jmod", jarfilter: '!**.jar', filter: '!module-info.class'
    
        target '10' // JDK 9 is obsolete, would target 11, but Proguard can't deal with 11's class files yet
    
    // dependencies
    configurations.runtime.files.each 
        libraryjars it, filter: '!META-INF/versions/**'
    
    outjars "$buildDir/proguard/$project.name-$project.version.jar"
    printseeds "$buildDir/proguard/proguard_seeds.txt"
    printmapping "$buildDir/proguard/proguard_map.txt"

    configuration 'src/main/proguard/configuration.pro'

此线程可能对您的情况有所帮助: https://discuss.gradle.org/t/obfuscated-jars-what-are-the-best-practices/18834/6

【讨论】:

以上是关于如何使用 spring-boot gradle 插件进行 proguard的主要内容,如果未能解决你的问题,请参考以下文章

如何使用带有 gradle 的多个嵌入式服务器运行 spring-boot 集成测试

如何将 Gatling 与现有的 Spring-Boot + Gradle 应用程序集成

如何在 gradle 中获取 spring-boot 依赖版本?

使用gradle BOM和spring-boot(多模块应用程序)哪种方式更好

gradle spring-boot 本地 配置

intellij idea 2017 gradle构建spring-boot web项目