SpringBoot Jar 包加密防止反编译实战

今天给大家分享一个 SpringBoot 程序 Jar 包加密的方式,通过代码加密可以实现无法反编译。

应用场景就是当需要把公司的产品部署到友方公司或者其他公司时,可以防止客户直接反编译出来源码,大大提升代码的安全性。

版本

  • springboot 2.6.8
  • jdk8

一、proguard-maven-plugin

第一种方式就是使用代码混淆的方式,可以参考proguard-maven-plugin插件使用,因为配置复杂,用起来太麻烦,本文不做重点介绍。

https://github.com/wvengen/proguard-maven-plugin

二、classfinal-maven-plugin

第二种方式就是使用代码加密的方式,classfinal-maven-plugin方式比较简单,只需要在pom.xml文件中引入一个plugin,然后简单的修改几项配置即可使用。

这种方式不仅可以对代码进行加密,对配置文件application.ymllib 下的依赖也可以加密。

还可以指定机器运行程序

https://gitee.com/roseboy/classfinal

三、实战

下面我们实战一下,首先创建一个 SpringBoot 程序,在 pom.xml 中加入。

需要注意的是,该插件需要放到spring-boot-maven-plugin后面

<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <!--
                        1. 加密后,方法体被清空,保留方法参数、注解等信息.主要兼容swagger文档注解扫描
                        2. 方法体被清空后,反编译只能看到方法名和注解,看不到方法体的具体内容
                        3. 加密后的项目需要设置javaagent来启动,启动过程中解密class,完全内存解密,不留下任何解密后的文件
                        4. 启动加密后的jar,生成xxx-encrypted.jar,这个就是加密后的jar文件,加密后不可直接执行
                        5. 无密码启动方式,java -javaagent:xxx-encrypted.jar -jar xxx-encrypted.jar
                        6. 有密码启动方式,java -javaagent:xxx-encrypted.jar='-pwd= 密码' -jar xxx-encrypted.jar
                    -->
                <groupId>net.roseboy</groupId>
                <artifactId>classfinal-maven-plugin</artifactId>
                <version>1.2.1</version>
                <configuration>
                    <password>#</password><!-- #表示启动时不需要密码,事实上对于代码混淆来说,这个密码没什么用,它只是一个启动密码 -->
                    <excludes>org.spring</excludes>
                    <packages>${groupId}</packages><!-- 加密的包名,多个包用逗号分开 -->
                    <cfgfiles>application.yml,application-dev.yml</cfgfiles><!-- 加密的配置文件,多个包用逗号分开 -->
                    <libjars>hutool-all.jar</libjars> <!-- jar包lib下面要加密的jar依赖文件,多个包用逗号分开 -->
                    <code>xxxxx</code> <!-- 指定机器启动,机器码 -->
                </configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>classFinal</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

上述代码中的机器码可以使用如下工具生成,进去之后点击下载。

https://repo1.maven.org/maven2/net/roseboy/classfinal-fatjar/1.2.1/classfinal-fatjar-1.2.1.jar

然后执行,注意最后参数为大写的C。

java -jar classfinal-fatjar-1.2.1.jar -C

最后将输出的机器码放入到上方的 code 中即可。

执行 Maven 命令打包即可,生成文件如下,其中EncryptDemo-0.0.1-SNAPSHOT-encrypted.jar为生成的加密jar 包。

如需提供给客户,提供该包即可。
在这里插入图片描述

使用反编译工具,查看 jar 包中配置文件,可以看到配置文件已经为空。

反编译工具我这里用的是 luyten

https://github.com/deathmarine/Luyten/releases/tag/v0.5.4_Rebuilt_with_Latest_depenencies

在这里插入图片描述

查看代码文件,可以看到方法体被清空,只保留了方法参数、注解等信息。

原理就是启动过程中进行解密,全是内存操作,非常安全。

在这里插入图片描述

  • 无密码启动

    java -javaagent:加密jar包的名称 -jar 加密jar包的名称
    

    例如我的 jar 包名称为EncryptDemo-0.0.1-SNAPSHOT-encrypted.jar,那么执行命令如下

    java -javaagent:EncryptDemo-0.0.1-SNAPSHOT-encrypted.jar -jar EncryptDemo-0.0.1-SNAPSHOT-encrypted.jar
    
  • 有密码启动

    有密码启动与无密码启动类似,只是启动之后会提示输入密码,按照提示输入密码即可。

    在这里插入图片描述

  • 如果机器码不匹配,会提示该项目不可在此机器上运行!

    在这里插入图片描述

  • 正常启动截图如下

    在这里插入图片描述

源代码如下:https://github.com/zuiyu-main/EncryptDemo.git

分支:jar-encry

最后介绍一下 ClassFinal ,ClassFinal 能够对class文件进行加密,支持直接加密jar包或者war包,无需修改任务代码,兼容spring framework,可避免源码泄露或者字节码被反编译。

目前看官方介绍支持的功能如下:

  • 支持编译好的jar/war加密。
  • 运行加密项目,无需修改源代码。
  • 支持普通jar 包。springboot的jar包,tomcat的war包。
  • 支持 spring framework、swagger等在启动过程中扫描注解或者生成字节码的框架。
  • 支持maven 插件,添加插件即可自动加密。
  • 支持加密lib文件下的依赖。
  • 支持绑定机器运行。
  • 支持加密 springboot 配置文件。

如有需求的小伙伴可以试试,用了一下,暂时还挺好用,不知道有没有坑,有用过的小伙伴或者有更好用的工具欢迎评论区交流一下。

公众号:醉鱼Java

如果这篇文章对您有所帮助或者启发,帮忙点个关注叭,您的支持是我坚持写作的最大动力。

求一键三连:点赞、收藏、关注。

谢谢支持哟 ( __ )。

<think>我们正在讨论Spring Boot应用使用Maven构建时如何加密代码以防止反编译。用户希望保护他们的Java代码,避免被反编译工具轻易逆向工程。下面我将逐步介绍几种可行的方案,并说明如何在Maven项目中实施。 ### 方案1: 使用代码混淆工具(如ProGuard) 代码混淆是最常用的保护Java代码的方法之一。它通过重命名类、方法和字段,删除无用的元数据,以及优化字节码来使反编译后的代码难以阅读。 **步骤:** 1. **在Maven项目中集成ProGuard** 首先,在`pom.xml`中添加ProGuard Maven插件: ```xml <build> <plugins> <plugin> <groupId>com.github.wvengen</groupId> <artifactId>proguard-maven-plugin</artifactId> <version>2.6.0</version> <executions> <execution> <phase>package</phase> <goals> <goal>proguard</goal> </goals> </execution> </executions> <configuration> <obfuscate>true</obfuscate> <injar>${project.build.finalName}.jar</injar> <outjar>${project.build.finalName}-small.jar</outjar> <outputDirectory>${project.build.directory}</outputDirectory> <proguardInclude>${basedir}/proguard.conf</proguardInclude> <libs> <lib>${java.home}/lib/rt.jar</lib> </libs> </configuration> </plugin> </plugins> </build> ``` 2. **配置ProGuard规则** 在项目根目录下创建`proguard.conf`文件,配置混淆规则。例如: ``` -dontshrink -dontoptimize -keepparameternames -keep public class com.example.MainApplication { public static void main(java.lang.String[]); } -keepclassmembers class * { @org.springframework.context.annotation.Bean *; @org.springframework.stereotype.Service *; @org.springframework.stereotype.Component *; } ``` 此配置保留Spring Boot的入口类和注解的Bean,避免破坏Spring的依赖注入。 3. **构建项目** 运行Maven命令打: ```bash mvn clean package ``` 构建完成后,会在`target`目录下生成混淆后的JAR文件(如`your-app-small.jar`)。 ### 方案2: 使用商业级代码保护工具(如Jscrambler, DexGuard) 对于更高级的保护(如控制流混淆、字符串加密等),可以考虑商业工具。这些工具提供更强大的保护,但通常需要付费。 **以Jscrambler为例:** 1. 在Jscrambler官网注册并获取配置。 2. 在Maven中集成Jscrambler插件(参考官方文档)。 3. 配置保护规则并构建。 ### 方案3: 使用类文件加密工具(如ClassFinal) [ClassFinal](https://github.com/roseboy/classfinal) 是一款基于字节码转换的Java类文件加密工具,支持Spring Boot项目。它通过对JAR中的类文件加密,并在启动时通过Java Agent解密,从而防止直接反编译。 **步骤:** 1. **在Maven项目中集成ClassFinal** ```xml <plugin> <groupId>net.roseboy</groupId> <artifactId>classfinal-maven-plugin</artifactId> <version>1.2.1</version> <configuration> <password>your-password</password> <!-- 加密密码 --> <packages>com.yourpackage</packages> <!-- 加密名 --> <excludes>org.spring</excludes> <!-- 排除的名 --> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>classFinal</goal> </goals> </execution> </executions> </plugin> ``` 2. **构建项目** 运行`mvn clean package`,会在`target`目录生成两个文件: - `original-your-app.jar`: 原始JAR - `your-app-encrypted.jar`: 加密后的JAR(内含启动代理) 3. **运行加密后的JAR** 使用以下命令运行: ```bash java -javaagent:your-app-encrypted.jar='-pwd your-password' -jar your-app-encrypted.jar ``` ### 方案4: 自定义类加载器加密 如果对安全性要求极高,可以自定义类加载器,在类加载时解密字节码。这种方法需要: 1. 编写一个自定义类加载器,重写`findClass`方法,在其中解密字节码。 2. 使用工具(如Maven插件)在构建时加密所有类文件。 3. 将自定义类加载器作为入口,启动应用。 ### 注意事项 - **性能影响**:混淆和加密可能影响启动速度和运行性能,需测试。 - **兼容性**:确保保护工具与Spring Boot、第三方库兼容。 - **备份**:保留未混淆/未加密的原始代码,避免丢失。 ### 总结 以上方案中,ProGuard和ClassFinal是较为常用的免费方案。ProGuard提供基础的混淆,而ClassFinal提供类文件加密。商业工具(如Jscrambler)则提供更全面的保护。 §§相关问题§§ 1. ProGuard在Spring Boot项目中如何避免混淆Spring的注解? 2. ClassFinal加密后的JAR文件如何防止内存dump? 3. 除了代码混淆和加密,还有哪些方法可以保护Java应用的安全?</think>### Spring Boot Maven项目代码加密防止反编译指南 在Spring Boot项目中,使用Maven构建时防止代码反编译的核心方案是**代码混淆**和**字节码加密**。以下是具体实现方案: #### 方案1:使用ProGuard进行代码混淆(推荐) ProGuard通过重命名类/方法/字段名、删除无用代码和优化字节码,使反编译后的代码难以阅读。 **实施步骤:** 1. 在`pom.xml`中添加ProGuard插件: ```xml <build> <plugins> <plugin> <groupId>com.github.wvengen</groupId> <artifactId>proguard-maven-plugin</artifactId> <version>2.6.0</version> <executions> <execution> <phase>package</phase> <goals><goal>proguard</goal></goals> </execution> </executions> <configuration> <obfuscate>true</obfuscate> <injar>${project.build.finalName}.jar</injar> <outjar>${project.build.finalName}-small.jar</outjar> <proguardInclude>${basedir}/proguard.conf</proguardInclude> <libs> <lib>${java.home}/lib/rt.jar</lib> </libs> </configuration> </plugin> </plugins> </build> ``` 2. 创建`proguard.conf`配置文件: ``` -keep public class com.example.MainApplication { public static void main(java.lang.String[]); } -keepclassmembers class * { @org.springframework.context.annotation.Bean *; @org.springframework.stereotype.* *; } ``` 3. 构建命令: ```bash mvn clean package ``` #### 方案2:使用ClassFinal进行字节码加密 [ClassFinal](https://github.com/roseboy/classfinal) 在启动时通过Java Agent动态解密类文件。 **实施步骤:** 1. 添加Maven插件: ```xml <plugin> <groupId>net.roseboy</groupId> <artifactId>classfinal-maven-plugin</artifactId> <version>1.2.1</version> <configuration> <password>yourPassword</password> <!-- 加密密钥 --> <packages>com.yourpackage.*</packages> <excludes>org.spring.*</excludes> </configuration> <executions> <execution> <phase>package</phase> <goals><goal>classFinal</goal></goals> </execution> </executions> </plugin> ``` 2. 启动加密后的JAR: ```bash java -javaagent:your-app-encrypted.jar='-pwd yourPassword' -jar your-app-encrypted.jar ``` #### 方案3:商业级保护工具(高安全性需求) | 工具 | 特点 | 费用 | |---------------|-----------------------------------|----------| | Jscrambler | 控制流混淆、字符串加密 | 商业授权 | | Zelix KlassMaster | 高级混淆、水印功能 | 商业授权 | | DashO | 预检分析、主动防御 | 商业授权 | #### 最佳实践建议 1. **分层保护**:结合ProGuard(基础混淆) + ClassFinal(启动时解密) 2. **密钥管理**:将加密密钥存储在环境变量中,避免硬编码 3. **排除配置**:不要混淆Spring Boot启动类和注解(如`@SpringBootApplication`) 4. **依赖处理**:排除第三方库的混淆(在配置中使用`-keep class com.fasterxml.**`) 5. **镜像加速**:在`settings.xml`配置阿里云镜像加速依赖下载[^5] #### 验证效果 反编译测试命令: ```bash # 使用JD-GUI验证 java -jar jd-gui.jar your-encrypted-app.jar ``` 成功保护的代码将显示为: - 类/方法名被重命名为`a`,`b`,`c`等无意义字符 - 核心逻辑代码无法直接阅读 > ⚠️ 注意:没有绝对安全的方案,但上述方法可显著提高反编译难度。商业项目建议使用商业级混淆工具。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值