使用proguard混淆你的spring boot應用
Proguard介紹
安卓開發(fā)的同學想必對Proguard
都是十分熟悉的,由于java的反編譯實在是太容易翔脱,使用它可以對java
源碼進行混淆處理柳沙,這樣即使反編譯之后也極大的降低了源碼的可讀性邑茄。當然除了混淆关顷,proguard
還有其余一些功能。
shrink: 檢測并移除沒有用到的類耘擂,變量摇庙,方法和屬性旱物;
optimize: 優(yōu)化代碼,非入口節(jié)點類會加上
private
/static
/final
, 沒有用到的參數會被刪除卫袒,一些方法可能-會變成內聯(lián)代碼宵呛。obfuscate: 使用短又沒有語義的名字重命名非入口類的類名,變量名夕凝,方法名宝穗。入口類的名字保持不變。
preverify: 預校驗代碼是否符合Java1.6或者更高的規(guī)范(唯一一個與入口類不相關的步驟)
環(huán)境準備
proguard plugin: 6.0.3
spring boot: 2.0.3
gradle 4.9
windows 10
引言
普通proguard
的使用方式非常簡單迹冤,只要下載proguard.jar
直接運行java -jar proguard.jar @progurad.pro
即可讽营。@后面指定的是規(guī)則文件。本篇著重講解如何通過gradle task
的方式來進行混淆打包泡徙。
這里以spring boot
為例,當然這并非僅限于spring boot
應用膜蠢,只要明白了原理堪藐,所有java
應用都可以如法炮制。最重要的是如何編制規(guī)則文件挑围,需要特別注意的是用到反射的類不要進行混淆礁竞。
有人說后端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 plugin
的bootjar
任務默認會打包所有runtime
期間的依賴以及$builddir\classes
下的class文件,這里為了讓spring boot
從混淆后的class中打包舞吭,所以自定義了bootPro
任務泡垃,該任務為bootJar
類型任務(這里可以理解為繼承)同時依賴于proguard
任務析珊,對bootInf
方法進行了重寫。如此可以在代碼混淆后將混淆后的class
文件打包到jar
包中蔑穴。
需要說明的是Proguard
任務內部可以直接編寫混淆規(guī)則忠寻,也可以引用外部規(guī)則文件,這里采用的是引用外部文件的方法存和。 具體規(guī)則可以參考文章尾部的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"
// 混淆規(guī)則文件
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()
}
}