[Gradle中文教程系列]-跟我學Gradle-使用proguard混淆你的spring boot應用

使用proguard混淆你的spring boot應用

Proguard介紹

本文示例源碼

安卓開發的同學想必對Proguard都是十分熟悉的,由于java的反編譯實在是太容易,使用它可以對java源碼進行混淆處理,這樣即使反編譯之后也極大的降低了源碼的可讀性。當然除了混淆,proguard還有其余一些功能。

  • shrink: 檢測并移除沒有用到的類,變量,方法和屬性;

  • optimize: 優化代碼,非入口節點類會加上private/static/final, 沒有用到的參數會被刪除,一些方法可能-會變成內聯代碼。

  • obfuscate: 使用短又沒有語義的名字重命名非入口類的類名,變量名,方法名。入口類的名字保持不變。

  • preverify: 預校驗代碼是否符合Java1.6或者更高的規范(唯一一個與入口類不相關的步驟)

proguard.png

環境準備

  • proguard plugin: 6.0.3

  • spring boot: 2.0.3

  • gradle 4.9

  • windows 10

引言

普通proguard的使用方式非常簡單,只要下載proguard.jar直接運行java -jar proguard.jar @progurad.pro即可。@后面指定的是規則文件。本篇著重講解如何通過gradle task的方式來進行混淆打包。

這里以spring boot為例,當然這并非僅限于spring boot應用,只要明白了原理,所有java應用都可以如法炮制。最重要的是如何編制規則文件,需要特別注意的是用到反射的類不要進行混淆。

有人說后端java應用部署在服務器端,對代碼進行混淆并沒有太大意義,關于此點不在本文討論范圍之內,本文僅提供純技術層面的探討,喜者自取,惡者輕噴。

步驟

引入方式有兩種,第一種是自行下載后采用本地引用,第二種只直接去中央倉庫加載依賴。 這里采用法二的方式

法一:

buildscript {
    repositories {
        flatDir dirs: '/usr/local/java/proguard/lib'
    }
    dependencies {
        classpath ':proguard:'
    }
}

法二:

buildscript {
    repositories {
        mavenCentral()
    }

    dependencies {
        classpath 'net.sf.proguard:proguard-gradle:6.0.3'
    }
}

具體做法比較簡單,這里直接貼出完整構建文件如下

spring boot pluginbootjar任務默認會打包所有runtime 期間的依賴以及$builddir\classes下的class文件,這里為了讓spring boot從混淆后的class中打包,所以自定義了bootPro任務,該任務為bootJar類型任務(這里可以理解為繼承)同時依賴于proguard任務,對bootInf方法進行了重寫。如此可以在代碼混淆后將混淆后的class文件打包到jar包中。

需要說明的是Proguard任務內部可以直接編寫混淆規則,也可以引用外部規則文件,這里采用的是引用外部文件的方法。 具體規則可以參考文章尾部的proguard鏈接。

buildscript {
    repositories {
        mavenCentral()
    }

    dependencies {
        classpath 'net.sf.proguard:proguard-gradle:6.0.3'
    }
}
plugins {
    id 'org.springframework.boot' version '2.0.3.RELEASE'
}

import proguard.gradle.ProGuardTask
import org.springframework.boot.gradle.tasks.bundling.BootJar

apply plugin: 'io.spring.dependency-management'

dependencies {
    compile "org.springframework.boot:spring-boot-starter-web:${bootVersion}",
            "org.apache.tomcat.embed:tomcat-embed-jasper:${tomcat_embed}"
    compileOnly "org.projectlombok:lombok:1.16.10"

    compile    project(":webpage")
}

// 不混淆打普通jar
bootJar {
  mainClassName = 'org.pkaq.Booter'
}
// 混淆任務
task proguard(type: ProGuardTask, dependsOn: compileJava) {
    // 輸出混淆前->混淆后的映射
    printmapping "$buildDir/mapping.txt"
    // 混淆規則文件
    configuration 'proguard-rules.pro'

    // 混淆時依賴的庫
    libraryjars files(configurations.compile.findAll {}.collect())
    libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
    libraryjars "${System.getProperty('java.home')}/lib/jce.jar"

    // 混淆輸入
    injars sourceSets.main.output
    // 混淆輸出
    outjars "$buildDir/classes-pro"
}

// 混淆打包
task bootPro(type: BootJar){
  dependsOn 'proguard'
  // 重新組織boot-inf下的文件
  bootInf {
    into('classes') {
        from "$buildDir/classes-pro"
    }

    into('lib') {
        from configurations.runtime
    }

  }
  // 包名
  baseName = "web"
  // 入口
  mainClassName = 'org.pkaq.Booter'

  doLast {
      new File("$buildDir/classes-pro").deleteDir()
  }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。