• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

java框架:使用 proguard-maven-plugin 对 Spring Boot 代码进行混淆

武飞扬头像
juejin
帮助504

什么是代码混淆?

就是将代码的通过工具使其可读性变差(越差越好😄)

Proguard是什么?

官网地址:www.guardsquare.com/proguard 该工具主要是为了实现Java以及Android App的代码混淆工作。 从官网的说明可以地址,该公司主要做手机应用保护的。proguard的使用手册是www.guardsquare.com/manual/home… guard官方其实并没有提供maven的插件依赖,官网默认的是gradle,不过官方推荐了两个maven插件 https://github.com/wvengen/proguard-maven-plugin https://github.com/dingxin/proguard-maven-plugin

本文目标

本文并不是介绍proguard如何使用(proguard有standalone模式,可以直接使用proguard.sh命令行进行混淆代码),而是使用wvengen的proguard-maven-plugin插件实现将一个spring boot项目进行混淆。

准备项目

我这里使用的是Spring Boot 2.7.x,JDK使用的是8. 

混淆前

首先打包看下未混淆前打包,查看反编译后的文件,这里需要使用反编译工具,可以去github.com/java-decomp… 打包:使用mvn clean package -DskipTests 或者直接使用IDEA的Build工具都可以。

#非必须选项,因为我电脑上安装多个版本的JDK。而环境变量中配置的不是jdk1.8,所有需要执行如下命令。
➜  Spring-Boot-Proguard git:(main) ✗ export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_333.jdk/Contents/Home
#我这里使用的是./mvnw,用mvn也可(只要你的电脑配置了环境变量,如果没配置,就可以使用spring boot项目下的mvnw)
➜  Spring-Boot-Proguard git:(main) ✗ ./mvnw clean package -DskipTestclears
[INFO] Scanning for projects...
[INFO] 
[INFO] -----------------< com.itlab1024:Spring-Boot-Proguard >-----------------
[INFO] Building Spring-Boot-Proguard 0.0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-clean-plugin:3.2.0:clean (default-clean) @ Spring-Boot-Proguard ---
^C%                                                                                                                ➜  Spring-Boot-Proguard git:(main) ✗ 
➜  Spring-Boot-Proguard git:(main) ✗ ./mvnw clean package -DskipTests     
[INFO] Scanning for projects...
[INFO] 
[INFO] -----------------< com.itlab1024:Spring-Boot-Proguard >-----------------
[INFO] Building Spring-Boot-Proguard 0.0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-clean-plugin:3.2.0:clean (default-clean) @ Spring-Boot-Proguard ---
[INFO] Deleting /Users/itlab/workspace/github/Spring-Boot-Proguard/target
[INFO] 
[INFO] --- maven-resources-plugin:3.2.0:resources (default-resources) @ Spring-Boot-Proguard ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Using 'UTF-8' encoding to copy filtered properties files.
[INFO] Copying 1 resource
[INFO] Copying 0 resource
[INFO] 
[INFO] --- maven-compiler-plugin:3.10.1:compile (default-compile) @ Spring-Boot-Proguard ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /Users/itlab/workspace/github/Spring-Boot-Proguard/target/classes
[INFO] 
[INFO] --- maven-resources-plugin:3.2.0:testResources (default-testResources) @ Spring-Boot-Proguard ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Using 'UTF-8' encoding to copy filtered properties files.
[INFO] skip non existing resourceDirectory /Users/itlab/workspace/github/Spring-Boot-Proguard/src/test/resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.10.1:testCompile (default-testCompile) @ Spring-Boot-Proguard ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /Users/itlab/workspace/github/Spring-Boot-Proguard/target/test-classes
[INFO] 
[INFO] --- maven-surefire-plugin:2.22.2:test (default-test) @ Spring-Boot-Proguard ---
[INFO] Tests are skipped.
[INFO] 
[INFO] --- maven-jar-plugin:3.2.2:jar (default-jar) @ Spring-Boot-Proguard ---
[INFO] Building jar: /Users/itlab/workspace/github/Spring-Boot-Proguard/target/Spring-Boot-Proguard-0.0.1-SNAPSHOT.jar
[INFO] 
[INFO] --- spring-boot-maven-plugin:2.7.4:repackage (repackage) @ Spring-Boot-Proguard ---
[INFO] Replacing main artifact with repackaged archive
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  4.584 s
[INFO] Finished at: 2022-10-15T17:31:08 08:00
[INFO] ------------------------------------------------------------------------

完成后,我们target下就能看到打好的jar文件。使用jd-gui打开查看。  可以看到,代码没有被混淆。

代码混淆

接下来我使用proguard实现代码混淆。主要是在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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.itlab1024</groupId>
    <artifactId>Spring-Boot-Proguard</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Spring-Boot-Proguard</name>
    <description>Spring-Boot-Proguard</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <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</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>com.github.wvengen</groupId>
                <artifactId>proguard-maven-plugin</artifactId>
                <version>2.6.0</version>
                <executions>
                    <!-- 以下配置说明执行mvn的package命令时候,会执行proguard-->
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>proguard</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <!-- 就是输入Jar的名称,我们要知道,代码混淆其实是将一个原始的jar,生成一个混淆后的jar,那么就会有输入输出。 -->
                    <injar>${project.build.finalName}.jar</injar>
                    <!-- 输出jar名称,输入输出jar同名的时候就是覆盖,也是比较常用的配置。 -->
                    <outjar>${project.build.finalName}.jar</outjar>
                    <!-- 是否混淆 默认是true -->
                    <obfuscate>true</obfuscate>
                    <!-- 配置一个文件,通常叫做proguard.cfg,该文件主要是配置options选项,也就是说使用proguard.cfg那么options下的所有内容都可以移到proguard.cfg中 -->
                    <proguardInclude>${project.basedir}/proguard.cfg</proguardInclude>
                    <!-- 额外的jar包,通常是项目编译所需要的jar -->
                    <libs>
                        <lib>${java.home}/lib/rt.jar</lib>
                        <lib>${java.home}/lib/jce.jar</lib>
                        <lib>${java.home}/lib/jsse.jar</lib>
                    </libs>
                    <!-- 对输入jar进行过滤比如,如下配置就是对META-INFO文件不处理。 -->
                    <inLibsFilter>!META-INF/**,!META-INF/versions/9/**.class</inLibsFilter>
                    <!-- 这是输出路径配置,但是要注意这个路径必须要包括injar标签填写的jar -->
                    <outputDirectory>${project.basedir}/target</outputDirectory>
                    <!--这里特别重要,此处主要是配置混淆的一些细节选项,比如哪些类不需要混淆,哪些需要混淆-->
                    <options>
                        <!-- 可以在此处写option标签配置,不过我上面使用了proguardInclude,故而我更喜欢在proguard.cfg中配置 -->
                    </options>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                        <configuration>
                            <mainClass>com.itlab1024.proguard.SpringBootProguardApplication</mainClass>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

再新建个mvc的controller。

package com.itlab1024.proguard.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class IndexController {
    /**
     * 主页Mapping
     * @return
     */
    @GetMapping
    public String index() {
        return "这是主页";
    }
}

proguard.cfg配置

#指定Java的版本
-target 1.8
#proguard会对代码进行优化压缩,他会删除从未使用的类或者类成员变量等
-dontshrink
#是否关闭字节码级别的优化,如果不开启则设置如下配置
-dontoptimize
#混淆时不生成大小写混合的类名,默认是可以大小写混合
-dontusemixedcaseclassnames
# 对于类成员的命名的混淆采取唯一策略
-useuniqueclassmembernames
#混淆时不生成大小写混合的类名,默认是可以大小写混合
-dontusemixedcaseclassnames
#混淆类名之后,对使用Class.forName('className')之类的地方进行相应替代
-adaptclassstrings

#对异常、注解信息予以保留
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
# 此选项将保存接口中的所有原始名称(不混淆)-->
-keepnames interface ** { *; }
# 此选项将保存所有软件包中的所有原始接口文件(不进行混淆)
#-keep interface * extends * { *; }
#保留参数名,因为控制器,或者Mybatis等接口的参数如果混淆会导致无法接受参数,xml文件找不到参数
-keepparameternames
# 保留枚举成员及方法
-keepclassmembers enum * { *; }
# 不混淆所有类,保存原始定义的注释-
-keepclassmembers class * {
                        @org.springframework.context.annotation.Bean *;
                        @org.springframework.beans.factory.annotation.Autowired *;
                        @org.springframework.beans.factory.annotation.Value *;
                        @org.springframework.stereotype.Service *;
                        @org.springframework.stereotype.Component *;
                        }

#忽略warn消息
-ignorewarnings
#忽略note消息
-dontnote
#打印配置信息
-printconfiguration
-keep public class com.itlab1024.proguard.SpringBootProguardApplication {
        public static void main(java.lang.String[]);
    }

混淆后反编译结果如下:

image-20221016164250423

可以看到IndexController被混淆了,Spring Boot的启动类SpringBootProguardApplication未被混淆。

对混淆的jar进行启动

➜  target git:(main) ✗ java -jar Spring-Boot-Proguard-0.0.1-SNAPSHOT.jar 

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.7.4)

2022-10-16 16:44:23.132  INFO 12416 --- [           main] c.i.p.SpringBootProguardApplication      : Starting SpringBootProguardApplication v0.0.1-SNAPSHOT using Java 17.0.3.1 on 192.168.0.100 with PID 12416 (/Users/itlab/workspace/github/Spring-Boot-Proguard/target/Spring-Boot-Proguard-0.0.1-SNAPSHOT.jar started by itlab in /Users/itlab/workspace/github/Spring-Boot-Proguard/target)
2022-10-16 16:44:23.138  INFO 12416 --- [           main] c.i.p.SpringBootProguardApplication      : No active profile set, falling back to 1 default profile: "default"
2022-10-16 16:44:24.406  INFO 12416 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2022-10-16 16:44:24.420  INFO 12416 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2022-10-16 16:44:24.420  INFO 12416 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.65]
2022-10-16 16:44:24.528  INFO 12416 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2022-10-16 16:44:24.528  INFO 12416 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1266 ms
2022-10-16 16:44:24.996  INFO 12416 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2022-10-16 16:44:25.007  INFO 12416 --- [           main] c.i.p.SpringBootProguardApplication      : Started SpringBootProguardApplication in 2.538 seconds (JVM running for 3.108)

访问主页:

image-20221016164530268

备注

  1. 上面知识简单的介绍了插件的使用,其实有很多选项,并未一一介绍,但是基本够用。
  2. 如果配置文件中一个-keep都没有设置,打包会报错的,要注意下。
  3. 对于Java项目,哪些class需要混淆,哪些不需要混淆,自己一定要清楚。比如AOP或者读取路径等的地方肯定是不能够混淆的。另外一般接口也不建议混淆。因为有些第三方工具接口的名称是有意义的,就比如Mybatis的接口以及参数名字,在xml(也可能没有xml)的sql中都是一一对应的,如果混淆就找不到了。
  4. 另外混淆后,强烈建议多测试,笔者就是在实际过程中混淆的时候发现了很多问题。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanegfa
系列文章
更多 icon
同类精品
更多 icon
继续加载