代码混淆常见于安卓的
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