springboot的maven多模块如何混淆jar包

springboot的maven多模块如何混淆jar包

    • 一.简介
    • [二. 示例](#二. 示例)
      • [2.1 基本配置](#2.1 基本配置)
      • [2.2 结果](#2.2 结果)
    • [三. 错误](#三. 错误)
      • [3.1 错误1](#3.1 错误1)
      • [3.2 错误2](#3.2 错误2)
    • [四. 参考文章](#四. 参考文章)

前言

这是我在这个网站整理的笔记,有错误的地方请指出,关注我,接下来还会持续更新。

作者:神的孩子都在歌唱

一.简介

proguard 是广为使用的混淆工具之一:

  • 它检测并删除未使用的类、字段、方法和属性。
  • 它优化字节码并删除未使用的指令。
  • 它使用简短的无意义名称重命名其余的类、字段和方法。

springboot可以使用proguard-maven-plugin 这个插件 在 pom.xml 中自定义proguard 的指令,本文基于 springboot + maven + proguard 的maven多模块架构进行代码混淆。

二. 示例

我的项目模块如下

html 复制代码
chen-common  --公共模块
chen-start  --启动模块 里面有启动类ChenApplication
chen-system --逻辑处理模块

2.1 基本配置

你需要在你的启动类模块 的pom.xml文件中添加如下配置,具体的配置解释可以去proguard-maven-plugin 官方文档了解

xml 复制代码
    <build>
        <finalName>cyz_navigate</finalName>
        <plugins>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <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>
                    <!-- 防止本地编译的时候路径太长编译失败-->
                    <putLibraryJarsInTempDir>true</putLibraryJarsInTempDir>
                    <!-- 就是输入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>
                    <!--                    子模块-->
                    <assembly>
                        <inclusions>
                            <inclusion>
                                <groupId>com.chen</groupId>
                                <artifactId>chen-system</artifactId>
                            </inclusion>
                            <inclusion>
                                <groupId>com.chen</groupId>
                                <artifactId>chen-common</artifactId>
                            </inclusion>
                        </inclusions>
                    </assembly>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>com.guardsquare</groupId>
                        <artifactId>proguard-base</artifactId>
                        <version>7.1.0</version>
                        <scope>runtime</scope>
                    </dependency>
                    <dependency>
                        <groupId>com.guardsquare</groupId>
                        <artifactId>proguard-core</artifactId>
                        <version>7.1.0</version>
                        <scope>runtime</scope>
                    </dependency>
                </dependencies>
            </plugin>
            <!--  proguard 代码混淆配置  结束-->

            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring-boot.version}</version>
                <configuration>
                    <fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
                    <mainClass>
                        com.chen.ChenApplication
                    </mainClass>
                    <excludeGroupIds>com.chen</excludeGroupIds>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        
        </plugins>
    </build>

编写proguard.cfg文件,需要放在和启动类的pom.xml同级

css 复制代码
#指定Java的版本
-target 1.8
#proguard会对代码进行优化压缩,他会删除从未使用的类或者类成员变量等
-dontshrink
#是否关闭字节码级别的优化,如果不开启则设置如下配置  不做优化(变更代码实现逻辑)
-dontoptimize
#混淆时不生成大小写混合的类名,默认是可以大小写混合
-dontusemixedcaseclassnames
# 对于类成员的命名的混淆采取唯一策略
-useuniqueclassmembernames
#混淆类名之后,对使用Class.forName('className')之类的地方进行相应替代
-adaptclassstrings
#保持目录结构
-keepdirectories
#对异常、注解信息予以保留
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod,Qualifier
# 此选项将保存接口中的所有原始名称(不混淆)-->
#-keepnames interface ** { *; }

# 此选项将保存所有软件包中的所有原始接口文件(不进行混淆)
#-keep interface * extends * { *; }
#保留参数名,因为控制器,或者Mybatis等接口的参数如果混淆会导致无法接受参数,xml文件找不到参数
-keepparameternames
# 保留枚举成员及方法
#-keepclassmembers enum * { *; }
# 不混淆所有类,保存原始定义的注释-
-keepclassmembers class * {
                        @org.springframework.context.annotation.Bean *;
                        @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 *;
                        @org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration *;
                        @org.springframework.boot.context.properties.ConfigurationProperties *;
                        @org.springframework.web.bind.annotation.RestController *;
                        @org.springframework.beans.factory.annotation.Qualifier *;
                        @io.swagger.annotations.ApiParam *;
                        @org.springframework.validation.annotation.Validated *;
                        @io.swagger.annotations.ApiModelProperty *;
                        @javax.validation.constraints.NotNull *;
                        @javax.validation.constraints.Size *;
                        @javax.validation.constraints.NotBlank *;
                        @javax.validation.constraints.Pattern *;

                        }
-keep class org.springframework.** {*;}
-keep public class ch.qos.logback.**{*;}
-keep class com.fasterxml.jackson.** { *; }

#忽略warn消息
-ignorewarnings
#打印配置信息
-printconfiguration

#入口程序类不能混淆,混淆会导致springboot启动不了
-keep public class com.chen.ChenApplication { *;}
#mybatis的mapper/实体类不混淆,否则会导致xml配置的mapper找不到 ( 保持该目录下所有类及其成员不被混淆)
-keep class com.chen.system.mapper.** {*;}

# 实体类,枚举方法不能混淆
-keep class com.chen.common.enums.** {*;}
-keep class com.chen.common.domain.** {*;}
# 保留特定框架或库的类,注解类
-keep class com.chen.common.elasticsearch.** { *; }
-keep class com.chen.common.annotation.** {*;}

#还有一些配置类和Bean不能混淆 比如logPointCut   prefix 这些   @Pointcut  @ConfigurationProperties(prefix = "redisson")
-keep class com.chen.common.aspectj.** {*;}

# 全放开
#-keep class com.ugdsec.** {*;}
#保留Serializable序列化的类不被混淆
# controller 层映射前台参数的类、后端返回的 bean 属性类等,不能混淆类的成员属性(如变成 string a;)
#-keepclassmembers  class * implements java.io.Serializable {*;}
-dontwarn

通过maven clean install 打包完后就可以了,切记一定要通过java -jar跑一下,看能否正常运行

2.2 结果

打开jar包发现文件名都变成了abcd的字母,说明已经混淆成功了

三. 错误

3.1 错误1

java 复制代码
com.alibaba.fastjson.JSONException: default constructor not found. class com.ugdsec.lams.admin.audit.plugin.d.a
        at com.alibaba.fastjson.util.JavaBeanInfo.build(JavaBeanInfo.java:574)
        at com.alibaba.fastjson.parser.ParserConfig.createJavaBeanDeserializer(ParserConfig.java:993)
        at com.alibaba.fastjson.parser.ParserConfig.getDeserializer(ParserConfig.java:879)
        at com.alibaba.fastjson.parser.ParserConfig.getDeserializer(ParserConfig.java:584)
        at com.alibaba.fastjson.parser.DefaultJSONParser.parseObject(DefaultJSONParser.java:696)
        at com.alibaba.fastjson.JSON.parseObject(JSON.java:394)
        at com.alibaba.fastjson.JSON.parseObject(JSON.java:298)
        at com.alibaba.fastjson.JSON.parseObject(JSON.java:588)
        at com.ugdsec.lams.admin.common.g.f.a.b(FastJsonUtils.java:69)
        at com.ugdsec.lams.admin.audit.plugin.shared.kafka.consumer.KafkaConsumer.beatsUdp(KafkaConsumer.java:110)

代码中使用这种工具类通过反射赋值参数,不能将这个RawMessage混淆,不然找不到

java 复制代码
            RawMessage raw = FastJsonUtils.toObject(String.valueOf(rawMessage), RawMessage.class);

给他放开了

css 复制代码
-keep class com.ugdsec.lams.admin.audit.plugin.journal.RawMessage {*;}

3.2 错误2

java 复制代码
"Name for argument of type [java.lang.Long] not specified, and parameter name information not found in class file either."

这个报错是因为混淆后前端传入参数的值也变了,需要通过@PathVariable指定以下就好

修改前

java 复制代码
public ResultData<Boolean> delete(Long id) 

修改后

java 复制代码
public ResultData<Boolean> delete(@PathVariable Long id) {

这是个接口,混淆后id就变成其他值了,前端找不到这个值

四. 参考文章

springboot+proguard+maven 实现代码混淆 看这一篇就够了

github文档

作者:神的孩子都在歌唱

本人博客:https://blog.csdn.net/weixin_46654114

转载说明:务必注明来源,附带本人博客连接。

相关推荐
用户908324602732 天前
Spring AI 1.1.2 + Neo4j:用知识图谱增强 RAG 检索(上篇:图谱构建)
java·spring boot
用户8307196840823 天前
Spring Boot 集成 RabbitMQ :8 个最佳实践,杜绝消息丢失与队列阻塞
spring boot·后端·rabbitmq
Java水解3 天前
Spring Boot 视图层与模板引擎
spring boot·后端
Java水解3 天前
一文搞懂 Spring Boot 默认数据库连接池 HikariCP
spring boot·后端
洋洋技术笔记3 天前
Spring Boot Web MVC配置详解
spring boot·后端
初次攀爬者4 天前
Kafka 基础介绍
spring boot·kafka·消息队列
用户8307196840824 天前
spring ai alibaba + nacos +mcp 实现mcp服务负载均衡调用实战
spring boot·spring·mcp
Java水解4 天前
SpringBoot3全栈开发实战:从入门到精通的完整指南
spring boot·后端
初次攀爬者5 天前
RocketMQ在Spring Boot上的基础使用
java·spring boot·rocketmq
花花无缺5 天前
搞懂@Autowired 与@Resuorce
java·spring boot·后端