Spring boot使用ProGuard实现代码混淆

目录

  • 参考
  • 一、 ProGuard简介
  • 二、混淆配置要点
  • 三、快速开始
    • 方案一 配置文件
      • 新增proguard.cfg
      • 配置插件
        • 打包
    • 方案二 pom中定义配置

参考

Spring boot使用ProGuard实现代码混淆
SpringBoot 玩一玩代码混淆,防止反编译代码泄露

代码混淆常见于安卓的apk安装文件, 服务端的代码因为不易被普通用户接触到, 所以混淆不多。但是某些场景下, 比如:项目需要部署到客户机器上, 就会有泄露代码逻辑的风险。
不过需要知道的是:使用proguard混淆代码只能增加阅读和理解的难度, 并不能百分百保证代码安全。也即是达到让开发人员看到这头痛的代码有99.99999%的冲动放弃阅读,拍桌子说还不如我重写一遍逻辑。

一、 ProGuard简介

附:proGuard官网

因为Java代码是非常容易反编译,况且Springboot和Android开发的应用程序都是用Java代码写的,为了很好的保护Java源代码,我们需要对编译好后的class文件进行混淆。

ProGuard是一个混淆代码的开源项目,它的主要作用是混淆代码,殊不知ProGuard还包括以下4个功能:

压缩(Shrink):检测并移除代码中无用的类、字段、方法和特性(Attribute)。
优化(Optimize):对字节码进行优化,移除无用的指令。
混淆(Obfuscate):使用a,b,c,d这样简短而无意义的名称,对类、字段和方法进行重命名。
预检(Preveirfy):在Java平台上对处理后的代码进行预检,确保加载的class文件是可执行的。

二、混淆配置要点

建议逐个java包定义混淆规则,这样思路更清晰 ;

  • repository(dao)层需要保存包名和类名,因为Mybatis的xml文件中引用了dao层的接口 ;
  • controller层注意在使用@PathVariable、@RequestParam时需要显式声明参数名 ;
  • dao层用于映射数据库表的类和controller层映射前台参数的类,都需要保留类成员 ;
  • 修改spring的bean命名策略,改成按类的全限定名来命名。
  • -entity和dto中的字段要保留命名,否则无法执行拷贝动作
  • -service最好用@Service(“xxxService”)指定名字,否则会模糊成a,导致依赖问题
    • 多模块依赖的模块最好不要模糊,否则无法依赖正常

混淆的大概效果图
Spring boot使用ProGuard实现代码混淆_第1张图片

三、快速开始

本文基于springboot2.x + maven + proguard进行代码混淆。

proguard是最为广为使用的工具之一,可是用他的客户端方式来混淆springboot项目的时候最后总得不到可执行的jar。后来发现了proguard-maven-plugin这个插件,所有proguard的指令都可以在pom中定义实现,本文采用proguard-maven-plugin方案。

方案一 配置文件

新增proguard.cfg

#指定Java的版本
-target 1.8
#proguard会对代码进行优化压缩,他会删除从未使用的类或者类成员变量等,shrink这个功能一般最好别用,所以这里添加了,我就遇到过启动jar的时候不支持压缩jar的问题
-dontshrink
#是否关闭字节码级别的优化,如果不开启则设置如下配置
-dontoptimize
#混淆时不生成大小写混合的类名,默认是可以大小写混合
-dontusemixedcaseclassnames
# 对于类成员的命名的混淆采取唯一策略
-useuniqueclassmembernames
#混淆时不生成大小写混合的类名,默认是可以大小写混合
-dontusemixedcaseclassnames
#混淆类名之后,对使用Class.forName('className')之类的地方进行相应替代
-adaptclassstrings

#对异常、注解信息予以保留
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
# 此选项将保存接口中的所有原始名称(不混淆)-->
-keepnames interface ** { *; }
# 此选项将保存所有软件包中的所有原始接口文件(不进行混淆)
#-keep interface * extends * { *; }
#保留参数名,因为控制器,或者Mybatis等接口的参数如果混淆会导致无法接受参数,xml文件找不到参数
-keepparameternames
# 保留枚举成员及方法
-keepclassmembers enum * { *; }
# 不混淆所有类,保存原始定义的注释-
-keepclassmembers class * {
                        @com.baomidou.mybatisplus.annotation *;
                        @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 *;
                        }

#忽略warn消息
-ignorewarnings
#忽略note消息
-dontnote
#打印配置信息
-printconfiguration
# 不混淆controller入口类
-keep class com.edevp.modules.store.dto.*
-keep class com.edevp.modules.**.*Impl
-keep class com.edevp.modules.store.web.* {*;}
-keep class com.edevp.modules.store.entity.* {*;}
-keep public class com.edevp.modules.store.StoreApplication {
        public static void main(java.lang.String[]);
    }

下面这些代码是用来指定哪些包不被混淆,注意将包路径改为你自己的



<option>-keep class com.demo.data.jpa.JpaApplicationoption>
<option>-keep class com.demo.data.jpa.base.* {*;}option>
<option>-keep class com.demo.data.jpa.entity.* {*;}option>
<option>-keep class com.demo.data.jpa.model.* {*;}option>
<option>-keep class com.demo.data.jpa.controller.* {*;}option>
 

对应配置文件方式:

# 不混淆controller入口类
-keep class com.edevp.modules.store.dto.*
-keep class com.edevp.modules.**.*Impl
-keep class com.edevp.modules.store.web.* {*;}
-keep class com.edevp.modules.store.entity.* {*;}
-keep public class com.edevp.modules.store.StoreApplication {
        public static void main(java.lang.String[]);
    }

说明:
-keep class 类/包.** 表示保留类名;
-keepclassmembers class 类/包.**{ *;} 表示保留类下边的所有变量,均不混淆。

配置插件

在pom.xml中配置插件

<plugins>
            <plugin>
                <groupId>com.github.wvengengroupId>
                <artifactId>proguard-maven-pluginartifactId>
                <version>2.6.0version>
                <executions>
                    
                    <execution>
                        <phase>packagephase>
                        <goals>
                            <goal>proguardgoal>
                        goals>
                    execution>
                executions>
                <configuration>
                    
                    <injar>${project.build.finalName}.jarinjar>
                    
                    <outjar>${project.build.finalName}.jaroutjar>
                    
                    <obfuscate>trueobfuscate>
                    
                    <proguardInclude>${project.basedir}/proguard.cfgproguardInclude>
                    
                    <libs>
                        <lib>${java.home}/lib/rt.jarlib>
                        <lib>${java.home}/lib/jce.jarlib>
                        <lib>${java.home}/lib/jsse.jarlib>
                    libs>
                    
                    <inLibsFilter>!META-INF/**,!META-INF/versions/9/**.classinLibsFilter>
                    
                    <outputDirectory>${project.basedir}/targetoutputDirectory>
                    
                    <options>
                        
                    options>
                configuration>
            plugin>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
                <version>2.6.8version>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackagegoal>
                        goals>
                        <configuration>
                            <mainClass>com.edevp.modules.store.StoreApplicationmainClass>
                        configuration>
                    execution>
                executions>
            plugin>
            
        plugins>

    build>

Spring boot使用ProGuard实现代码混淆_第2张图片

打包

然后点击package,正常执行编译打包流程就可以 :
Spring boot使用ProGuard实现代码混淆_第3张图片
打包之后
Spring boot使用ProGuard实现代码混淆_第4张图片

在target目录下会生成5个文件:

jpa-0.0.1-SNAPSHOT.jar混淆后的Spring boot
jar,里面包含完整的项目结构,可以运行,这个就是我们本文的产出物; proguard_map.txt 混淆内容的映射;
proguard_seed.txt 参与混淆的类; 还有2个未混淆的原始jar包。

反编译
Spring boot使用ProGuard实现代码混淆_第5张图片

方案二 pom中定义配置


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>
    <groupId>com.erbadagang.data.jpagroupId>
    <artifactId>jpaartifactId>
    <version>0.0.1-SNAPSHOTversion>
    <name>jpaname>
    <description>JPA project for Spring Bootdescription>

    <properties>
        <java.version>1.8java.version>
        <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
        <spring-boot.version>2.3.0.RELEASEspring-boot.version>
    properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-data-jdbcartifactId>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-data-jpaartifactId>
        dependency>
        
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <scope>runtimescope>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintagegroupId>
                    <artifactId>junit-vintage-engineartifactId>
                exclusion>
            exclusions>
        dependency>
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <version>1.18.12version>
        dependency>
    dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-dependenciesartifactId>
                <version>${spring-boot.version}version>
                <type>pomtype>
                <scope>importscope>
            dependency>
        dependencies>
    dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.pluginsgroupId>
                <artifactId>maven-compiler-pluginartifactId>
                <configuration>
                    <source>1.8source>
                    <target>1.8target>
                    <encoding>UTF-8encoding>
                configuration>
            plugin>

            
            <plugin>
                <groupId>com.github.wvengengroupId>
                <artifactId>proguard-maven-pluginartifactId>
                <version>2.2.0version>
                <executions>
                    <execution>
                        
                        <phase>packagephase>
                        <goals>
                            <goal>proguardgoal>
                        goals>
                    execution>
                executions>
                <configuration>
                    <injar>${project.build.finalName}.jarinjar>
                    
                    <outjar>${project.build.finalName}.jaroutjar>
                    
                    <obfuscate>trueobfuscate>
                    <options>
                        <option>-target 1.8option> 
                        <option>-dontshrinkoption> 
                        <option>-dontoptimizeoption>
                        <option>-adaptclassstringsoption>
                        <option>-ignorewarnings
                        option>
                        <option>-keep class org.apache.logging.log4j.util.* { *; }option>
                        <option>-dontwarn org.apache.logging.log4j.util.**option>
                        <option>-keepattributes
                            Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
                        option>
                        
                        
                        <option>-keepclassmembers enum * { *; }option>
                        <option>-keepparameternamesoption>
                        <option>-keepclasseswithmembers public class * {
                            public static void main(java.lang.String[]);}
                        option> 
                        
                        <option>-dontnote javax.annotation.**option>
                        <option>-dontnote sun.applet.**option>
                        <option>-dontnote sun.tools.jar.**option>
                        <option>-dontnote org.apache.commons.logging.**option>
                        <option>-dontnote javax.inject.**option>
                        <option>-dontnote org.aopalliance.intercept.**option>
                        <option>-dontnote org.aopalliance.aop.**option>
                        <option>-dontnote org.apache.logging.log4j.**option>

                        
                        
                        <option>-keep class com.erbadagang.data.jpa.JpaApplicationoption>
                        <option>-keep class com.erbadagang.data.jpa.base.* {*;}option>
                        <option>-keep class com.erbadagang.data.jpa.entity.* {*;}option>
                        <option>-keep class com.erbadagang.data.jpa.model.* {*;}option>
                        <option>-keep class com.erbadagang.data.jpa.controller.* {*;}option>
                        

                        <option>-keep interface * extends * { *; }option>
                        
                        <option>-keepclassmembers class * {
                            @org.springframework.beans.factory.annotation.Autowired *;
                            @org.springframework.beans.factory.annotation.Value *;
                            }
                        option>
                    options>
                    <libs>
                        
                        <lib>${java.home}/lib/rt.jarlib>
                        <lib>${java.home}/lib/jce.jarlib>
                    libs>
                configuration>
                <dependencies>
                    
                    <dependency>
                        <groupId>net.sf.proguardgroupId>
                        <artifactId>proguard-baseartifactId>
                        <version>6.1.1version>
                    dependency>
                dependencies>
            plugin>

            
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
                <executions>
                    <execution>
                        
                        <goals>
                            <goal>repackagegoal>
                        goals>
                        <configuration>
                            <mainClass>com.erbadagang.data.jpa.JpaApplicationmainClass>
                        configuration>
                    execution>
                executions>
            plugin>
        plugins>
    build>

project>

你可能感兴趣的:(开发工具,spring,boot,java,mybatis)