项目包混淆

394 阅读1分钟

混淆包:通过代码混淆工具(对 Java 字节码进行 重命名、结构优化、删除无用代码、加密等操作后生成的jar包文件,防止代码泄露

一、配置

1、由于该项目时多模块项目,所以在使用proguard-maven-plugin时,需要在每个需要混淆的模块下pom配置

pom文件配置

<build>
        <plugins>
            <plugin>
                <groupId>com.github.wvengen</groupId>
                <artifactId>proguard-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>proguard</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <!-- 指定外部ProGuard配置文件路径 -->
                    <proguardInclude>${project.basedir}/../proguard.cfg</proguardInclude>
                    <!-- 输入和输出JAR设置 -->
<!--                    <injar>${project.build.finalName}.jar</injar>-->
                    <outjar>${project.build.finalName}.jar</outjar>

                    <!-- 包括依赖 -->
                    <includeDependency>true</includeDependency>
                    <addMavenDescriptor>true</addMavenDescriptor>

                    <!-- 库路径,通常需要包含JDK的rt.jar -->
                    <libs>
                        <lib>${java.home}/lib/rt.jar</lib>
                        <lib>${java.home}/lib/jce.jar</lib>
                    </libs>

                    <obfuscate>true</obfuscate>
                    <!-- 添加以下配置避免重复 -->
                    <skip>false</skip>
                    <attach>true</attach>
                    <attachArtifactClassifier>obf</attachArtifactClassifier>
                </configuration>
                <dependencies>
                    <!--<dependency>
                        <groupId>net.sf.proguard</groupId>
                        <artifactId>proguard-base</artifactId>
                        <version>6.2.2</version>
                    </dependency>-->
                    <dependency>
                        <groupId>com.guardsquare</groupId>
                        <artifactId>proguard-base</artifactId>
                        <version>7.2.2</version>
                        <scope>runtime</scope>
                    </dependency>
                </dependencies>
            </plugin>

        </plugins>
    </build>

2、混淆包规则配置文件,放在项目根目录下即可

混淆规则需要一点点调试,一般混淆的是模块中私有方法/变量,对于包名,类名,方法名,序列化字段,枚举名,注解等一般需要保持原样

# ========== 基础配置 ==========
-dontoptimize
-dontshrink
-keepattributes *Annotation*,EnclosingMethod,Signature,InnerClasses,Exceptions,LocalVariableTable,LocalVariableTypeTable,SourceFile,LineNumberTable,Deprecated,Synthetic,RuntimeVisibleAnnotations,RuntimeInvisibleAnnotations


# ========== Spring框架保留 ==========
-keep class org.springframework.** { *; }
-keep class org.springframework.boot.** { *; }
-keep class com.fasterxml.jackson.** { *; }
-keep class com.alibaba.fastjson.** { *; }
-keep class com.fasterxml.jackson.** { *; }
-keep class com.alibaba.druid.** { *; }
-keep class com.aliyun.oss.** { *; }
-keep interface com.aliyun.oss.** { *; }
-keep class org.apache.ibatis.** { *; }
-keep class org.apache.http.** { *; }
-keep @org.springframework.stereotype.* abstract class *
-keep @org.springframework.stereotype.** class *
-keep @org.springframework.context.annotation.** class *
-keep @org.springframework.web.bind.annotation.** class * { *; }
-keep @org.springframework.beans.factory.annotation.* class *
-keep @com.alibaba.nacos.api.annotation.** class *
-keep @org.aspectj.lang.annotation.** class *
-keep class com.baomidou.mybatisplus.** { *; }
-keep interface com.baomidou.mybatisplus.** { *; }
-keep class com.baomidou.mybatisplus.extension.plugins.pagination.** { *; }
-keep interface com.baomidou.mybatisplus.core.mapper.** { *; }
-keep class com.baomidou.mybatisplus.core.mapper.** { *; }
-keep @javax.annotation.** class *
-keep class lombok.** { *; }
-keep interface lombok.** { *; }

# ========== 本地包保留 ==========
-keep class com.bangdao.**.dto.** { *; }
-keep class com.bangdao.**.vo.** { *; }
-keep class com.bangdao.**.request.** { *; }
-keep class com.bangdao.**.response.** { *; }
-keep class com.bangdao.**.model.** { *; }
-keep class com.bangdao.**.pojo.** { *; }
-keep class com.bangdao.**.entity.** { *; }
-keep class com.bangdao.**.properties.** { *; }
-keep enum com.bangdao.** { *; }



-keepclassmembers class * {
    @org.springframework.beans.factory.annotation.* *;
    @org.springframework.context.annotation.Bean.* *;
    @org.springframework.web.bind.annotation.* *;
    @java.lang.annotation.* *;
    @java.lang.Override *;
    @javax.annotation.* *;
    @org.aspectj.lang.annotation.* *;
    @com.fasterxml.jackson.annotation.* *;
    @org.springframework.beans.factory.annotation.* *;
    @javax.persistence.* *;
    @com.alibaba.nacos.api.annotation.* *;
    @org.apache.ibatis.annotations.* *;
}

# 保留反射相关
-keep class com.bangdao.**.config.** { *; }
-keep class com.bangdao.**.service.** { *; }
-keep class com.bangdao.**.controller.** { *; }

# 保留 META-INF 下所有文件(包括 spring.components)
-keepdirectories META-INF
-keepdirectories

# 保留所有类名(包括内部类)
-keepnames class **
-keepnames class **$*

# 保留所有内部类不被混淆
-keepclassmembers class **$* {
    *;
}

# 保留所有公共类和公共方法
-keep public class * {
    public *;
    protected *;
}

# 保留所有公共类和公共方法
-keep abstract class * {
    public *;
    protected *;
}

# 保留公共API
-keep public interface *

# 保留接口的所有方法(包括 defaultstatic)
-keepclassmembers interface * {
    *;
}

# 保留项目包下所有自定义注解
-keep @interface com.bangdao.tiny.boot.** { *; }

# 保留所有的枚举类
-keep public enum *

# 枚举不混淆
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

# 类名混淆,但保持包名
-keeppackagenames com.bangdao.tiny.boot.**

# 按包名保留抽象类
-keep abstract class com.bangdao.tiny.boot.** { *; }

# 保留抽象类的公开/受保护方法
-keepclassmembers abstract class com.bangdao.tiny.boot.** {
    public *;
    protected *;
}

# 处理JSON/XML序列化
-keepclassmembers class * {
    public void set*(***);
    public *** get*();
    public boolean is*();
}

# 保留序列化相关的类
-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}


# ========== 忽略警告 ==========
-dontwarn org.**
-dontwarn ch.**
-dontwarn com.auth0.**
-dontwarn com.zaxxer.**
-dontwarn com.xxl.**
-dontwarn com.github.**
-dontwarn com.fasterxml.**
-dontwarn com.jcraft.**
-dontwarn com.alibaba.**
-dontwarn com.google.**
-dontwarn com.mongodb.**
-dontwarn com.netflix.**
-dontwarn retrofit2.**
-dontwarn feign.**
-dontwarn com.squareup.**
-dontwarn okio.**
-dontwarn okhttp3.**
-dontwarn javax.**
-dontwarn io.**
-dontwarn groovy.**
-dontwarn java.lang.**
-dontwarn com.fasterxml.jackson.**
-dontwarn com.alibaba.fastjson.**
-dontwarn javax.annotation.**

3、配置混淆规则后,重新打包,将打包后的混淆包替换原来的jar包,重新运行项目,保证项目业务正常运行

二、出现的问题

问题1

Parameter 0 of method authFilter in com.bangdao.common.admin.starter.background.CommonBackgroundFilterAutoConfiguration required a bean of type 'com.bangdao.common.admin.audit.service.ICommonSysAccessLogService' that could not be found.

e89d6d504b452c57d56dd3a45021e4fc.png 出现原因: 混淆插件打出来的包不能正常注入

解决办法:对于混淆打出来的jar包解压缩后,重新打包替换,打包命令如下

jar -cfM0 common-admin-core-2.6.0-duchang-xunjia.jar ./*

问题2

Null key returned for cache operation (maybe you are using named params on classes without debug info?) Builder[public java.util.List com.bangdao.common.admin.core.service.impl.CommonAuthorityServiceImpl.getUserRolesWithCache(java.lang.String)] caches=[COMMON_USER_ROLE] | key='#userId' | keyGenerator='' | cacheManager='' | cacheResolver='' | condition='' | unless='' | sync='false'

4f386002d16e826f1cfe1551a9b318db.png 出现原因: 框架中引用了@Cacheable(value = MessageConstant.MESSAGE_DT_CONFIG,key = "#merchantId")注解,混淆后不能识别

解决办法: 更改混淆包规则配置文件,加上LocalVariableTable,LocalVariableTypeTable

-keepattributes *Annotation*,EnclosingMethod,Signature,InnerClasses,Exceptions,LocalVariableTable,LocalVariableTypeTable,SourceFile,LineNumberTable,Deprecated,Synthetic,RuntimeVisibleAnnotations,RuntimeInvisibleAnnotations

问题3

[ERROR] Failed to execute goal com.github.wvengen:proguard-maven-plugin:2.6.0:proguard (default) on project common-admin-background: Execution default of goal com.github.wvengen:proguard-maven-plugin:2.6.0:proguard failed: java.io.IOException: Cannot run program "E:\e\software\jdk 8\jre\bin\java.exe" (in directory "E:\e\code\duchang\common-admin\common-admin-background"): CreateProcess error=206, 文件名或扩展名太长。 -> [Help 1]

69302053ecfed3a8fc3a169d4a7a028b.png 出现原因: 模块依赖包太多,导致在打包时,打包命令超过windows系统运行命令的最大长度

解决办法: 相应模块下的pom配置,增加配置

<!--避免命令行参数超出-->
<generateTemporaryConfigurationFile>true</generateTemporaryConfigurationFile>

问题4

[proguard] java.io.IOException: You have to specify '-keep' options if you want to write out kept elements with '-printseeds'.

e906b732b41fc0cb0d3dace5911a9288.png 出现原因: 配置的混淆规则不能识别

解决办法: 多模块应用,检查规则配置文件地址

  <!-- 指定外部ProGuard配置文件路径 -->
  <proguardInclude>${project.basedir}/../../proguard.cfg</proguardInclude>

问题5

[proguard] Warning: com.bangdao.common.admin.audit.service.impl.CommonSysAccessLogServiceImpl: can't find referenced class com.bangdao.common.admin.basic.pojo.SysUser

[proguard] Warning: com.bangdao.common.admin.audit.service.impl.CommonSysAccessLogServiceImpl: can't find referenced class com.bangdao.common.admin.basic.pojo.SysMerchant

[proguard] Warning: com.bangdao.common.admin.audit.service.impl.CommonSysAccessLogServiceImpl: can't find referenced class com.baomidou.mybatisplus.extension.service.impl.ServiceImpl

ed195f726c47a775d49c4b69a00577dc.png 出现原因: 混淆规则配置错误

解决办法: 1、首先检查配置规则,是否正确,检查包是否存在,如果不需要此类,可以选择忽略告警

2、若检查没有问题,检查pom配置文件,由于依赖的其他模块的代码,需要配置,不配置的话,会导致keep规则无效

<!-- 包括依赖 -->
<includeDependency>true</includeDependency>