如何使用Maven混淆包含多个依赖JAR的WAR项目?
Maven WAR项目ProGuard混淆实战方案
直接混淆WAR包之所以会爆几万条警告,本质是WAR里的WEB-INF/lib包含大量第三方依赖,ProGuard默认会尝试处理所有类,而这些公共库要么不需要混淆,要么本身存在ProGuard无法处理的依赖关系。下面是一套可落地的Maven流程,在JAR打包和WAR打包之间插入混淆步骤,精准处理你的代码和需要保护的依赖:
步骤1:把Web代码打包成独立JAR
先把WEB-INF/classes里的业务代码单独打包成一个JAR,方便后续单独混淆。在pom.xml中添加maven-jar-plugin配置:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <executions> <execution> <id>package-web-classes</id> <phase>package</phase> <goals> <goal>jar</goal> </goals> <configuration> <classesDirectory>${project.build.outputDirectory}</classesDirectory> <finalName>app-web-core</finalName> </configuration> </execution> </executions> </plugin>
执行mvn package后,会在target目录生成app-web-core.jar。
步骤2:筛选需要混淆的依赖JAR
不是所有依赖都要混淆——Servlet API、数据库驱动、Spring这类公共库完全没必要,只混淆你自己开发的内部依赖。用maven-dependency-plugin把目标依赖复制到临时目录:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <id>copy-deps-to-obfuscate</id> <phase>prepare-package</phase> <goals> <goal>copy-dependencies</goal> </goals> <configuration> <outputDirectory>${project.build.directory}/obfuscate-libs</outputDirectory> <includeGroupIds>com.yourcompany,org.yourinternal</includeGroupIds> <!-- 替换成你的内部依赖组ID --> <excludeGroupIds>javax.servlet,mysql,org.springframework</excludeGroupIds> <!-- 排除公共库 --> </configuration> </execution> </executions> </plugin>
同时把不需要混淆的公共库复制到另一个目录(比如target/public-libs),后续直接打包进WAR。
步骤3:用ProGuard混淆目标JAR
用proguard-maven-plugin把你的Web代码JAR和筛选后的依赖JAR一起混淆,输出到target/obfuscated-libs:
<plugin> <groupId>com.github.wvengen</groupId> <artifactId>proguard-maven-plugin</artifactId> <version>2.6.0</version> <executions> <execution> <id>obfuscate-jars</id> <phase>prepare-package</phase> <goals> <goal>proguard</goal> </goals> </execution> </executions> <configuration> <injar>${project.build.directory}/app-web-core.jar</injar> <outjar>${project.build.directory}/obfuscated-libs/app-web-core-obf.jar</outjar> <libraryjars> <libraryjar>${project.build.directory}/obfuscate-libs/*.jar</libraryjar> <libraryjar>${java.home}/lib/rt.jar</libraryjar> <libraryjar>${project.build.directory}/public-libs/javax.servlet-api-4.0.1.jar</libraryjar> <!-- 公共库作为ProGuard依赖 --> </libraryjars> <options> <!-- 必须保留对外暴露的类,比如Servlet、Controller --> <option>-keep public class com.yourcompany.web.servlet.** { public *; }</option> <option>-keep public class com.yourcompany.web.controller.** { public *; }</option> <!-- 保留反射、序列化需要的属性 --> <option>-keepattributes Signature,SourceFile,LineNumberTable</option> <!-- 忽略第三方库的警告 --> <option>-dontwarn org.slf4j.**</option> <option>-dontwarn com.fasterxml.jackson.**</option> </options> <obfuscatedDirectory>${project.build.directory}/obfuscated-libs</obfuscatedDirectory> </configuration> </plugin>
重点:Keep规则一定要精准,漏写会导致运行时找不到类或方法,比如Spring的@Component类、MyBatis的Mapper接口都需要保留原名。
步骤4:打包WAR时替换为混淆后的文件
最后用maven-war-plugin,排除原来的classes目录,把混淆后的JAR和公共库一起打包进WAR:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>3.3.2</version> <configuration> <webResources> <!-- 排除原classes目录,改用混淆后的JAR --> <resource> <directory>${project.build.outputDirectory}</directory> <excludes> <exclude>**/*</exclude> </excludes> </resource> <!-- 添加混淆后的JAR到WEB-INF/lib --> <resource> <directory>${project.build.directory}/obfuscated-libs</directory> <targetPath>WEB-INF/lib</targetPath> </resource> <!-- 添加公共库到WEB-INF/lib --> <resource> <directory>${project.build.directory}/public-libs</directory> <targetPath>WEB-INF/lib</targetPath> </resource> </webResources> </configuration> </plugin>
核心注意事项
- 公共库绝对不要混淆:不仅会爆警告,还会导致兼容性问题,比如Spring的注解类混淆后无法被扫描。
- 混淆后必须做全量测试:反射、序列化、动态代理是混淆后最容易出问题的点,测试时要重点覆盖。
- 替代工具:如果ProGuard配置太繁琐,可以试试Allatori或DashO,它们有可视化配置界面,但ProGuard是开源免费的,社区支持更完善。
内容的提问来源于stack exchange,提问作者Johnson
相关产品推荐
相关产品推荐

