上海建设网站费用,新冠三阳意味着什么,与做机器人有关的网站,wordpress替换链接背景
当我们需要将 JAR 包交付给第三方时#xff0c;常常担心代码可能会被反编译。因此#xff0c;对 JAR 包进行混淆处理显得尤为重要。
市面上有许多 JAR 包源码混淆工具#xff0c;但真正能稳定投入使用的并不多。例如#xff0c;ClassFinal (ClassFinal: Java字节码加…背景
当我们需要将 JAR 包交付给第三方时常常担心代码可能会被反编译。因此对 JAR 包进行混淆处理显得尤为重要。
市面上有许多 JAR 包源码混淆工具但真正能稳定投入使用的并不多。例如ClassFinal (ClassFinal: Java字节码加密工具)是国内开发者开发的一款 JAR 包加密工具它采用的是字节码加密的方案。然而ClassFinal (ClassFinal: Java字节码加密工具)已经停止维护多年并且它的使用需要额外提供一个加密包来解密这种方式虽然注重安全性但增加了使用的复杂性。由于 JVM 的跨平台特性理想的工具应该是简洁、易于使用的而不是增加额外的“挂件”来进行保护。
另一款常用的工具是 ProGuard(GitHub - Guardsquare/proguard: ProGuard, Java optimizer and obfuscator)它是一款开源的 Java 代码混淆工具。准确来说是一个插件不需要对他进行编码只需要进行配置即可。代码混淆并不是把所有代码进行混淆这样反而会出错比如枚举类型如果也进行混淆那么在使用反射创建实例并给实例赋值的时候枚举类型会反序列化失败。ProGuard 的主要功能是在不影响程序功能的前提下混淆 JAR 包内的源码通过增加代码的混乱程度使得反编译后的代码可读性大大降低从而有效地提高了代码的安全性。对于第三方来说反编译后的代码难以理解与其花费大量时间研究可能更倾向于重新开发实现。因此从这个角度来看ProGuard 确实可以满足一定的代码安全性需求。proguard提供了可以对哪些包类方法等不进行混淆的配置我们可以将枚举配置在这里。
然而需要注意的是ProGuard 是一款通用的 Java 代码混淆工具并非针对 Spring 框架的专用工具。因此它对 Spring 相关的注解并没有特殊的处理。这意味着在使用 ProGuard 混淆 Spring Boot 应用时开发者可能需要进行额外的配置和定制这对不熟悉该工具的开发者来说增加了使用难度和成本。
实现流程
springboot提供了打包插件spring-boot-maven-plugin所以我们的混淆需要在springboot打包的插件之前就是我们要对混淆之后的代码通过spring-boot-maven-plugin进行打包。 Proguard核心内容是两个配置文件一个pom.xml、一个proguard.cfg这里提供最关键的两个能够直接使用的配置文件内容其余的配置相关描述可以通过文末的参考文献获取。
proguard.cfg配置示例
# 指定不警告尚未解决的引用和其他问题
-dontwarn
#指定Java的版本
-target 1.8
#proguard会对代码进行优化压缩他会删除从未使用的类或者类成员变量等删除注释、未被引用代码
-dontshrink
#是否关闭字节码级别的优化如果不开启则设置如下配置 不做优化变更代码实现逻辑
-dontoptimize
#混淆时不生成大小写混合的类名默认是可以大小写混合
-dontusemixedcaseclassnames
# 不去忽略非公共的库类
-dontskipnonpubliclibraryclasses
# 指定不跳过包可见的库类成员字段和方法。
# 默认情况下proguard在解析库类时会跳过包可见的库类成员。当我们确实引用了包可见的类成员时需要设置此项
-dontskipnonpubliclibraryclassmembers
# 对于类成员的命名的混淆采取唯一策略
-useuniqueclassmembernames
# 优化时允许访问并修改有修饰符的类和类的成员
-allowaccessmodificatio
# 不混淆所有包名
#-keeppackagename
#混淆类名之后对使用Class.forName(className)之类的地方进行相应替代
-adaptclassstrings
#保持目录结构
-keepdirectories
#对异常、注解信息予以保留
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod,Qualifier
# 此选项将保存接口中的所有原始名称不混淆--
#-keepnames interface ** { *; }#混淆时是否记录日志
#-verbose# 此选项将保存所有软件包中的所有原始接口文件不进行混淆
#-keep interface * extends * { *; }#保留参数名因为控制器或者Mybatis等接口的参数如果混淆会导致无法接受参数xml文件找不到参数
-keepparameternames
# 保留枚举成员及方法
#-keepclassmembers enum * { *; }
# 不混淆所有类,保存原始定义的注释-
-keepclassmembers class * {org.springframework.context.annotation.Bean *;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 *;org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration *;org.springframework.boot.context.properties.ConfigurationProperties *;org.springframework.web.bind.annotation.RestController *;org.springframework.beans.factory.annotation.Qualifier *;io.swagger.annotations.ApiParam *;org.springframework.validation.annotation.Validated *;io.swagger.annotations.ApiModelProperty *;javax.validation.constraints.NotNull *;javax.validation.constraints.Size *;javax.validation.constraints.NotBlank *;javax.validation.constraints.Pattern *;}
-keep class org.springframework.** {*;}
-keep public class ch.qos.logback.**{*;}
-keep class com.fasterxml.jackson.** { *; }#忽略warn消息
-ignorewarnings
#打印配置信息
-printconfiguration#入口程序类不能混淆混淆会导致springboot启动不了
-keep public class com.zhubayi.proguarddemo.ProguardDemoApplication { *;}#mybatis的mapper/实体类不混淆否则会导致xml配置的mapper找不到 ( 保持该目录下所有类及其成员不被混淆)
#-keep class com.zhubayi.proguarddemo.mapper.** {*;}# 实体类枚举方法不能混淆
#-keep class com.zhubayi.proguarddemo.enums.** {*;}
-keep class com.zhubayi.proguarddemo.entity.** {*;}
#controller不进行混淆
-keep class com.zhubayi.proguarddemo.controller.** {*;}# 保留特定框架或库的类,注解类
#-keep class com.zhubayi.proguarddemo.elasticsearch.** { *; }
#-keep class com.zhubayi.proguarddemo.annotation.** {*;}#还有一些配置类和Bean不能混淆 比如logPointCut prefix 这些 Pointcut ConfigurationProperties(prefix redisson)
#-keep class com.zhubayi.proguarddemo.aspectj.** {*;}# 全放开
#-keep class com.ugdsec.** {*;}
#保留Serializable序列化的类不被混淆
# controller 层映射前台参数的类、后端返回的 bean 属性类等不能混淆类的成员属性如变成 string a;
-keepclassmembers class * implements java.io.Serializable {*;}# 不混淆所有的set/get方法
#-keepclassmembers public class * {void set*(***);*** get*();}
pom.xml配置示例 (注意它必须要放到spring-boot-maven-plugin上面)
buildpluginsplugingroupIdcom.github.wvengen/groupIdartifactIdproguard-maven-plugin/artifactIdversion2.6.0/versionexecutions!-- 以下配置说明执行mvn的package命令时候会执行proguard--executionphasepackage/phasegoalsgoalproguard/goal/goals/execution/executionsconfiguration!-- 是否混淆 默认是true --obfuscatetrue/obfuscate!-- 防止本地编译的时候路径太长编译失败--putLibraryJarsInTempDirtrue/putLibraryJarsInTempDir!-- 就是输入Jar的名称我们要知道代码混淆其实是将一个原始的jar生成一个混淆后的jar那么就会有输入输出。 --injar${project.build.finalName}.jar/injar!-- 输出jar名称输入输出jar同名的时候就是覆盖也是比较常用的配置。 --outjar${project.build.finalName}.jar/outjar!-- 配置一个文件通常叫做proguard.cfg,该文件主要是配置options选项也就是说使用proguard.cfg那么options下的所有内容都可以移到proguard.cfg中 --proguardInclude${project.basedir}/proguard.cfg/proguardInclude!-- 额外的jar包通常是项目编译所需要的jar --libslib${java.home}/lib/rt.jar/liblib${java.home}/lib/jce.jar/liblib${java.home}/lib/jsse.jar/lib/libs!-- 对输入jar进行过滤比如如下配置就是对META-INFO文件不处理。 --!-- inLibsFilter!META-INF/**,!META-INF/versions/9/**.class/inLibsFilter--!-- 这是输出路径配置但是要注意这个路径必须要包括injar标签填写的jar --outputDirectory${project.basedir}/target/outputDirectory!--这里特别重要此处主要是配置混淆的一些细节选项比如哪些类不需要混淆哪些需要混淆--options!-- 可以在这里写option标签配置不过我上面使用了proguardInclude所以可以在proguard.cfg中配置 --!--JDK8--!--option-target 1.8/option--!-- 不做收缩删除注释、未被引用代码--!--option-dontshrink/option--!-- 不做优化变更代码实现逻辑--!--option-dontoptimize/option--!-- 不路过非公用类文件及成员--!--option-dontskipnonpubliclibraryclasses/option--!--option-dontskipnonpubliclibraryclassmembers/option--!--不用大小写混合类名机制--!--option-dontusemixedcaseclassnames/option--/options!--子模块--assemblyinclusions!--inclusion--!-- groupIdcom.zhubayi/groupId--!-- artifactIdchen-system/artifactId--!--/inclusion--/inclusions/assembly/configurationdependenciesdependencygroupIdcom.guardsquare/groupIdartifactIdproguard-base/artifactIdversion7.1.1/versionscoperuntime/scope/dependency!--dependency--!-- groupIdcom.guardsquare/groupId--!-- artifactIdproguard-core/artifactId--!-- version7.1.1/version--!-- scoperuntime/scope--!--/dependency--/dependencies/plugin!-- proguard 代码混淆配置 结束--plugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactIdconfiguration!-- 如果没有该配置devtools不会生效 --forktrue/forkmainClasscom.zhubayi.proguarddemo.ProguardDemoApplication/mainClass!--excludeGroupIdscom.zhubayi/excludeGroupIds--/configurationexecutionsexecutiongoalsgoalrepackage/goal/goals/execution/executions/plugin/plugins/build注意
proguardInclude${project.basedir}/proguard.cfg/proguardInclude${project.basedir}/proguard.cfg表示当前项目的根目录所以需要把proguard.cfg放在当前项目的根目录
然后进行打包
打包之后会多出三个文件
!-- 就是输入Jar的名称我们要知道代码混淆其实是将一个原始的jar生成一个混淆后的jar那么就会有输入输出。 --
injar${project.build.finalName}.jar/injar!-- 输出jar名称输入输出jar同名的时候就是覆盖也是比较常用的配置。 --
outjar${project.build.finalName}.jar/outjar从pom打包配置可以得到proguard-demo-0.0.1-SNAPSHOT.jar就是项目混淆后的jar包。 而proguard-demo-0.0.1-SNAPSHOT_proguard_base.jar就是正常的包没有进行混淆。
反编译查看
下载反编译工具 jd-gui 打开然后选择刚刚的混淆jar包
这里面对springboot相关的都进行过过滤所以剩下的都是和springboot无关的类 entity包、主启动类和controller包配置没有进行混淆所以还是原来的名字其他都进行了混淆类名称都直接缩写成了小写字母a,b,c…
启动测试
D:\IdeaProjects\mytools\proguard-demo\targetjava -jar proguard-demo-0.0.1-SNAPSHOT.jar. ____ _ __ _ _/\\ / ____ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | _ | _| | _ \/ _ | \ \ \ \\\/ ___)| |_)| | | | | || (_| | ) ) ) ) |____| .__|_| |_|_| |_\__, | / / / /|_||___//_/_/_/:: Spring Boot :: (v2.3.12.RELEASE)2024-08-09 10:45:52.197 INFO 18600 --- [ main] c.z.p.ProguardDemoApplication : Starting ProguardDemoApplication v0.0.1-SNAPSHOT on zhubayi-computer with PID 18600 (D:\IdeaProjects\mytools\proguard-demo\target\proguard-demo-0.0.1-SNAPSHOT.jar started by zhubayi in D:\IdeaProjects\mytools\proguard-demo\target)
2024-08-09 10:45:52.199 INFO 18600 --- [ main] c.z.p.ProguardDemoApplication : No active profile set, falling back to default profiles: default
2024-08-09 10:45:53.664 INFO 18600 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2024-08-09 10:45:53.674 INFO 18600 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2024-08-09 10:45:53.675 INFO 18600 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.46]
2024-08-09 10:45:53.730 INFO 18600 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2024-08-09 10:45:53.730 INFO 18600 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1488 ms
2024-08-09 10:45:53.887 INFO 18600 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService applicationTaskExecutor
2024-08-09 10:45:54.028 INFO 18600 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path
2024-08-09 10:45:54.035 INFO 18600 --- [ main] c.z.p.ProguardDemoApplication : Started ProguardDemoApplication in 2.143 seconds (JVM running for 2.561) 成功获取到了数据。