最近想把代码进行混淆,研究了一下proguard,把配置保留一下
有两个类
TestOne.java
package com.levin.proguard;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import com.levin.proguard.pojo.Person;
import lombok.extern.slf4j.Slf4j;
/**
* @program: proguardTest
* @description:
* @create: 2022-02-17 17:13
*/
@Slf4j
public class TestOne {
public Person newPerson() {
return new Person();
}
public static void main(String[] args)
throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException,
InvocationTargetException {
log.info("打印日志测试");
Class cls = Class.forName("com.levin.proguard.pojo.Person");
Method method = cls.getDeclaredMethod("say");
method.invoke(cls.newInstance());
}
}
Person.java
package com.levin.proguard.pojo;
import lombok.extern.slf4j.Slf4j;
/**
* @program: proguardTest
* @description:
* @create: 2022-02-17 17:17
*/
@Slf4j
public class Person {
private String name;
private String age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public void say() {
log.info("我是一个人");
}
}
pom.xml
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>proguardTest</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<slf4j.version>1.7.21</slf4j.version>
<logback.version>1.2.3</logback.version>
</properties>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency>
</dependencies>
<build>
<finalName>proguard</finalName>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<archive>
<manifest>
<mainClass>com.levin.proguard.TestOne</mainClass>
</manifest>
</archive>
<descriptors>
<!-- 指定assembly配置文件路径 -->
<descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 代码混淆 -->
<plugin>
<groupId>com.github.wvengen</groupId>
<artifactId>proguard-maven-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>proguard</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- 是否将生成的PG文件安装部署-->
<attach>true</attach>
<!-- 是否混淆-->
<obfuscate>true</obfuscate>
<attachArtifactClassifier>pg</attachArtifactClassifier>
<injar>classes</injar>
<inFilter>com/levin/proguard/**</inFilter>
<outputDirectory>${project.build.directory}</outputDirectory>
<outjar>classes-autotest.jar</outjar>
<!-- 添加依赖,这里你可以按你的需要修改,这里测试只需要一个JRE的Runtime包就行了 -->
<libs>
<lib>${java.home}/lib/rt.jar</lib>
</libs>
<options>
<!-- JDK目标版本1.7-->
<option>-target 1.8</option>
<!-- 不做收缩(删除注释、未被引用代码)-->
<option>-dontshrink</option>
<!-- 不做优化(变更代码实现逻辑)-->
<option>-dontoptimize</option>
<!-- 不路过非公用类文件及成员-->
<option>-dontskipnonpubliclibraryclasses</option>
<option>-dontskipnonpubliclibraryclassmembers</option>
<!-- 优化时允许访问并修改有修饰符的类和类的成员 -->
<option>-allowaccessmodification</option>
<!-- 确定统一的混淆类的成员名称来增加混淆,防止冲突-->
<option>-useuniqueclassmembernames</option>
<!-- 不混淆所有包名,Spring配置中有大量固定写法的包名-->
<option>-keeppackagenames</option>
<!-- 不混淆所有特殊的类-->
<option>-keepattributes
Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,LocalVariable*Table,*Annotation*,Synthetic,EnclosingMethod
</option>
<!-- 不混淆所有的set/get方法,毕竟项目中使用的部分第三方框架(例如Shiro)会用到大量的set/get映射-->
<option>-keepclassmembers public class * {void set*(***);*** get*();}</option>
<!-- 不混淆main方法-->
<option>-keepclasseswithmembers public class * {
public static void main(java.lang.String[]);
}
</option>
</options>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
混淆命令
# 进入项目目录
cd $project_home
# 将com.levin.proguard下的class文件进行混淆,最终输出到classes-pg.jar中
mvn clean package assembly:single proguard:proguard
cd target
# 解压未混淆的jar包将混淆后的类重新打包
mkdir package
unzip proguard.jar -d package
rm -rf package/com
unzip classes-pg.jar -d package
cd package
zip -r proguard-finish.jar *
混淆后的结果中,get和set方法被保留了,Persion中的say方法混淆了
结论
混淆对于本地云部署避免代码泄漏是有作用的,但是如果将整个项目进行混淆,那么会造成日志无法分析,如果涉及到反射那么还需要进行工程改造,个人觉得针对关键逻辑代码进行混淆是有必要的,否则弊大于利