代碼混淆常見於安卓的
apk
安裝文件, 服務端的代碼因為不易被普通用戶接觸到, 所以混淆不多。但是某些場景下, 比如:項目需要部署到客戶機器上, 就會有泄露代碼邏輯的風險。
不過需要知道的是:使用proguard
混淆代碼只能增加閱讀和理解的難度, 並不能百分百保證代碼安全。也即是達到讓開發人員看到這頭痛的代碼有99.99999%的沖動放棄閱讀,拍桌子說還不如我重寫一遍邏輯。
一、 ProGuard簡介
因為Java代碼是非常容易反編譯,況且Springboot和Android開發的應用程序都是用Java代碼寫的,為了很好的保護Java源代碼,我們需要對編譯好后的class文件進行混淆。
ProGuard是一個混淆代碼的開源項目,它的主要作用是混淆代碼,殊不知ProGuard還包括以下4個功能:
- 壓縮(Shrink):檢測並移除代碼中無用的類、字段、方法和特性(Attribute)。
- 優化(Optimize):對字節碼進行優化,移除無用的指令。
- 混淆(Obfuscate):使用a,b,c,d這樣簡短而無意義的名稱,對類、字段和方法進行重命名。
- 預檢(Preveirfy):在Java平台上對處理后的代碼進行預檢,確保加載的class文件是可執行的。
二、混淆配置要點
- 建議逐個java包定義混淆規則,這樣思路更清晰 ;
- repository(dao)層需要保存包名和類名,因為Mybatis的xml文件中引用了dao層的接口 ;
- controller層注意在使用@PathVariable、@RequestParam時需要顯式聲明參數名 ;
- dao層用於映射數據庫表的類和controller層映射前台參數的類,都需要保留類成員 ;
- 修改spring的bean命名策略,改成按類的全限定名來命名。
三、快速開始
本文基於springboot2.x + maven + proguard
進行代碼混淆。
將源碼打包做代碼混淆還有其他方案,但是沒成功,最終選擇proguard,開始使用遇到各種問題,各種jar包版本問題,嘗試了5次不同方案,費了十牛二虎之力最終成功,Mark一下。
3.1 方案
proguard是最為廣為使用的工具之一,可是用他的客戶端方式來混淆springboot項目的時候最后總得不到可執行的jar。后來發現了proguard-maven-plugin
這個插件,所有proguard的指令都可以在pom中定義實現,本文采用proguard-maven-plugin
方案。
3.2 POM文件
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.erbadagang.data.jpa</groupId> <artifactId>jpa</artifactId> <version>0.0.1-SNAPSHOT</version> <name>jpa</name> <description>JPA project for Spring Boot</description> <properties> <java.version>1.8</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <spring-boot.version>2.3.0.RELEASE</spring-boot.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!--MySQL數據庫連接--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test