• Spring boot使用ProGuard实现代码混淆


    参考

    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,导致依赖问题
      • 多模块依赖的模块最好不要模糊,否则无法依赖正常

    混淆的大概效果图
    在这里插入图片描述

    三、快速开始

    本文基于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[]);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

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

    
    
    <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>
     
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    对应配置文件方式:

    # 不混淆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[]);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    说明:
    -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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    在这里插入图片描述

    打包

    然后点击package,正常执行编译打包流程就可以 :
    在这里插入图片描述
    打包之后
    在这里插入图片描述

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

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

    反编译
    在这里插入图片描述

    方案二 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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
  • 相关阅读:
    FastAdmin表格顶部增加toolbar按钮
    JavaScript 62 JavaScript 版本 62.6 ECMAScript 2018
    Java责任链模式之总有你想不到的知识
    网工自述:在誉天学习的一年里,我的工资从3800涨到15k,而且收获了爱情。
    (c语言)五子棋<可修改棋数>
    如何使用Photino创建Blazor项目进行跨平台
    JUC-进程和线程
    SpringCloud微服务治理技术入门(SCN)
    Linux~常用命令的使用
    【python自动化应用】借助ChatGPT与Python轻松实现办公自动化 —— AIC松鼠活动第九期
  • 原文地址:https://blog.csdn.net/Blueeyedboy521/article/details/127935255