【工具】代码保护

代码保护

1、混淆

代码混淆会污染代码的标识符,降低软件被反编译后源码的可读性,从而提高破解的成本。

1.1、ProGuard

对 Java 代码作混淆处理。

ProGuard Manual: Home | Guardsquare

Java 代码混淆 – 技术研究 – KOCA开发者论坛

不推荐代码混淆来对 Java 代码做保护。

代码混淆会扰乱代码或文件的标识符,这会导致 Spring 工程的包扫描和 Bean 管理失效。

proguard.cfg 配置

支持对单个或多个目录、文件、类、方法、变量的标识保持不变。

# 取消 warming
-dontwarn
# 保持目录结构,解决 @ComponentScan 失效
-keepdirectories
# 默是开启的,这里关闭 shrink,即不删除没有使用的类/成员,否则会把 Controller 啥的给删掉(取消 ProGuard 对代码的收缩)
-dontshrink
# 默认是开启的,这里关闭字节码级别的优化,否则 aop 会报错(取消 ProGuard 的优化)
-dontoptimize
# 混淆类名之后,对使用 Class.forName('className') 之类的地方进行相应替代
-adaptclassstrings
# 不混淆所有特殊的类,否则抛出去的异常会出问题
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod

# 保持 VerifyImpl 类下 verify 和 verifyStatus 两个方法不被混淆
-keep public class com.xxx.yyy.zzz.kkk.VerifyImpl {
    public boolean verify();
    public com.xxx.yyy.zzz.entity.Id verifyStatus();
}

# 保留 Id 实体类,防止 json 序列和反序列化失败
-keep public class com.xxx.yyy.zzz.entity.Id {*;}

# 枚举类不变
-keep public enum com.xxx.yyy.zzz.constants.WayEnum {*;}

# 保留配置变量
-keep public class com.xxx.yyy.zzz.common.properties.MyProperties {*;}

# 保留指定成员变量
-keepclassmembernames public class com.xxx.yyy.zzz.common.properties.SecurityProperties {
    int timeout;
}
# 保留资源文件
-adaptresourcefilecontents META-INF/maven/**

# 保留类名,防止混淆后,bean 名称冲突的问题
-keepnames class com.xxx.yyy.zzz.common.properties.SecurityProperties 
-keepnames class com.xxx.yyy.zzz.core.id.**

使用

可以采用 ProGuard 界面或命令行的方式完成代码混淆,也可以使用 ProGuard 官方推荐的第三方 Maven 插件来完成,效果都是差不多。

wvengen

dingxin

插件的使用

<build>
    <plugins>
        <plugin>
            <groupId>com.github.wvengen</groupId>
            <artifactId>proguard-maven-plugin</artifactId>
            <version>2.5.3</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>proguard</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <!--输入的 jar-->
                <injar>${project.build.finalName}.jar</injar>
                <!--输出的 jar-->
                <outjar>${project.build.finalName}.jar</outjar>
                <!-- 是否混淆 -->
                <obfuscate>true</obfuscate>
                <!-- 混淆配置文件 -->
                <proguardInclude>${project.basedir}/proguard.cfg</proguardInclude>
                <!-- 依赖的 JAVA library -->
                <libs>
                    <lib>${java.home}/lib/rt.jar</lib>
                </libs>
            </configuration>
        </plugin>
        <!--springboot 打包插件-->
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>2.5.14</version>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <!--声明 mainClass-->
                <mainClass>com.xxx.yyy.zzz.Application</mainClass>
            </configuration>
        </plugin>
    </plugins>
</build>

如果工程用 SpringBoot 的插件打包,那么需要在 SpringBoot 插件打包前,先进行代码混淆然后再交给 SpringBoot 的插件打包。

1.2、其他

代码混淆和加密 – 开源软件 – OSCHINA – 中文开源技术交流社区

2、加密

对代码编译后的字节码作加密,在加载时再解密,那加密的内容就无法反编译。

2.1、Classfinal

免费,开源。Classfinal 提供了两种方式,一种是基于命令行完成,另一宗基于 Maven 插件完成。ClassFinal: Java字节码加密工具

配置

<plugin>
    <!-- https://gitee.com/roseboy/classfinal -->
    <groupId>net.roseboy</groupId>
    <artifactId>classfinal-maven-plugin</artifactId>
    <version>1.2.1</version>
    <configuration>
        <!--加密打包之后 pom.xml 会被删除,不用担心在 jar 包里找到此密码-->
        <password>#</password>
        <!--加密的包路径,多个用逗号分隔-->
        <packages>com.xxx.server,com.xxx.security</packages>
        <!--需要加密的配置文件,多个用逗号分隔-->
        <cfgfiles>application.yml</cfgfiles>
        <!--不需要加密的类名,多个用逗号分隔-->
        <excludes>org.spring</excludes>
        <!--jar 包 lib 下需要加密的 jar 包文件名,多个用逗号分隔-->
        <libjars>xxx-yyy-core-1.0.0.jar</libjars>
    </configuration>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>classFinal</goal>
            </goals>
        </execution>
    </executions>
</plugin>

如果项目工程使用 SpringBoot 插件打包,那么 Classfinal 一定要在 SpringBoot 插件打包后再对 Jar 包加密。

加密后的 Jar 包需要通过以下命令参数来启动

java -javaagent: -jar

效果

参考

线上项目源码安全性处理方案_classfinal-maven-plugin-CSDN博客

创作不易,转载请注明出处: 【工具】代码保护
上一篇
下一篇