项目组核心代码模块部署于用户服务器上,直接甩jar包到服务器的方式,极有可能导致数据泄露和代码泄露,为了防止有技术能力的用户反编译我们的程序,采用了proguard和xjar两种方式来混淆和加密jar包,注:加密技术只是提高别人获取你的代码的门槛,没有绝对安全的加密方式,而安全等级越高,程序开发、运维、部署的成本就越高,所以,合适的加密技术就是最好的。
1. ProGuard是一个压缩、优化和混淆Java字节码文件的免费的工具,它可以删除无用的类、字段、方法和属性。可以删除没用的注释,最大限度地优化字节码文件。它还可以使用简短的无意义的名称来重命名已经存在的类、字段、方法和属性。常常用于Android开发用于混淆最终的项目,增加项目被反编译的难度。
2. Xjar
3.ClassFinal是一款Java class文件安全加密工具,支持直接加密jar包或war包,无需修改任何项目代码,兼容spring-framework,可避免源码泄漏或字节码被反编译,
功能特性
classfinal其实也可以起到代码加密的效果,功能也很强大,被classfinal加密过后的jar包,反编译了以后,方法返回值会return null或者0,方法内部会自动去掉。并且用classfinal加密过后的jar包启动方式需要用javaagnet启动。而相比较xjar,反编译以后,反编译后,直接显示Internal Error.
1.module pom文件引入
net.roseboy
classfinal-maven-plugin
1.2.1
#
com.nick.gnss
org.spring
package
classFinal
2.启动方式
1)无密码启动
java -jar gnss-server-1.0.0-encrypted.jar
2)有密码启动
java -javaagent:gnss-server-1.0.0-encrypted.jar="-pwd 123456" -jar gnss-server-1.0.0-encrypted.jar
3.反编译后的效果
所有的方法,return 0 或者 null. 方法体内部是空的。
1.module中增加proguard.cfg文件
#指定Java的版本
-target 1.8
#proguard会对代码进行优化压缩,他会删除从未使用的类或者类成员变量等
-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 * { *; }
# 不混淆所有的set/get方法
-keepclassmembers public class * {void set*(***);*** get*();}
# 不混淆所有包含Component等注解的类
-keep @org.springframework.context.annotation.Bean class * {*;}
-keep @org.springframework.context.beans.factory.annotation.Autowired class * {*;}
-keep @org.springframework.context.beans.factory.annotation.Value class * {*;}
-keep @org.springframework.stereotype.Service class * {*;}
-keep @org.springframework.stereotype.Component class * {*;}
-keep @org.springframework.web.bind.annotation.RestController class * {*;}
-keep @org.springframework.context.annotation.Configuration class * {*;}
#忽略warn消息
-ignorewarnings
#忽略note消息
-dontnote
#打印配置信息
-printconfiguration
#启动类不需要混淆
-keep class com.nick.GnssApplication {
public static void main(java.lang.String[]);
}
2.module pom文件引入
此处需要注意,proguard plugin需要放在repackage plugin之前,否则混淆没有效果。原理就是在打包之前将代码混淆,然后再打包。
com.github.wvengen
proguard-maven-plugin
2.6.0
package
proguard
${project.build.finalName}.jar
${project.build.finalName}.jar
true
${project.basedir}/proguard.cfg
${java.home}/lib/rt.jar
${java.home}/lib/jce.jar
${java.home}/lib/jsse.jar
!META-INF/**,!META-INF/versions/9/**.class
${project.basedir}/target
org.springframework.boot
spring-boot-maven-plugin
2.3.7.RELEASE
com.nick.GnssApplication
repackage
repackage
3.反编译看效果
查看xxx.jar是否有混淆的效果,而不是xxx_proguard_base.jar(此jar是没有混淆的原jar)
效果杠杠滴!!!需要试运行,并且注意配置proguard,否则会导致程序运行异常,这可能就是proguard的唯一缺点了吧,欢迎拍砖。。。
4.运行查看效果
启动成功,没毛病
1.parent pom文件引入
重点在最下面的xjar plugin
4.0.0
com.nick
nick-server
1.0.0
nick-server
Demo project for Spring Boot
1.8
UTF-8
UTF-8
2.3.7.RELEASE
gnss-server
pom
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-test
test
org.junit.vintage
junit-vintage-engine
org.springframework.boot
spring-boot-dependencies
${spring-boot.version}
pom
import
org.apache.maven.plugins
maven-compiler-plugin
3.8.1
1.8
UTF-8
com.github.core-lib
xjar-maven-plugin
v2.0.7
build
package
44889951235894612351265ABD123
1
${project.build.directory}
${project.build.finalName}_x.jar
com/nick/**
2. module pom文件引入
需要放在module pom文件plugin 最后一个,保证xjar是最后一个执行plugin
com.github.core-lib
xjar-maven-plugin
3.编译打包
4.反编译看效果
效果杠杠滴
5.运行查看效果
将第四步和第五步融合即可,但是要注意pom文件中的plugin的先后问题,不然要么混淆失败,要么加密失败。
1.完整版的parent pom文件
4.0.0
com.nick
nick-server
1.0.0
nick-server
Demo project for Spring Boot
1.8
UTF-8
UTF-8
2.3.7.RELEASE
gnss-server
pom
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-test
test
org.junit.vintage
junit-vintage-engine
org.springframework.boot
spring-boot-dependencies
${spring-boot.version}
pom
import
org.apache.maven.plugins
maven-compiler-plugin
3.8.1
1.8
UTF-8
com.github.core-lib
xjar-maven-plugin
v2.0.7
build
package
44889951235894612351265ABD123
1
${project.build.directory}
${project.build.finalName}_x.jar
com/nick/**
2.完整版的poguard.cfg
#指定Java的版本
-target 1.8
#proguard会对代码进行优化压缩,他会删除从未使用的类或者类成员变量等
-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 * { *; }
# 不混淆所有的set/get方法
-keepclassmembers public class * {void set*(***);*** get*();}
# 不混淆所有包含Component等注解的类
-keep @org.springframework.context.annotation.Bean class * {*;}
-keep @org.springframework.context.beans.factory.annotation.Autowired class * {*;}
-keep @org.springframework.context.beans.factory.annotation.Value class * {*;}
-keep @org.springframework.stereotype.Service class * {*;}
-keep @org.springframework.stereotype.Component class * {*;}
-keep @org.springframework.web.bind.annotation.RestController class * {*;}
-keep @org.springframework.context.annotation.Configuration class * {*;}
#忽略warn消息
-ignorewarnings
#忽略note消息
-dontnote
#打印配置信息
-printconfiguration
#启动类不需要混淆
-keep class com.nick.GnssApplication {
public static void main(java.lang.String[]);
}
3.完整版的module pom文件
该pom文件中注意两点 1)引入parent节点 2)需要放在最后一个plugin执行
nick-server
com.nick
1.0.0
4.0.0
com.nick
gnss-server
1.0.0
gnss-server
gnss-server
1.8
UTF-8
UTF-8
2.3.7.RELEASE
${maven.build.timestamp}
yyyy-MM-dd HH:mm:ss
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-test
test
org.junit.vintage
junit-vintage-engine
io.jsonwebtoken
jjwt
0.9.1
org.projectlombok
lombok
1.18.16
commons-io
commons-io
2.6
com.alibaba
fastjson
1.2.83
com.google.guava
guava
30.1.1-jre
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-dependencies
${spring-boot.version}
pom
import
org.apache.maven.plugins
maven-compiler-plugin
3.8.1
1.8
UTF-8
org.apache.maven.plugins
maven-resources-plugin
@
false
com.github.wvengen
proguard-maven-plugin
2.6.0
package
proguard
${project.build.finalName}.jar
${project.build.finalName}.jar
true
${project.basedir}/proguard.cfg
${java.home}/lib/rt.jar
${java.home}/lib/jce.jar
${java.home}/lib/jsse.jar
!META-INF/**,!META-INF/versions/9/**.class
${project.basedir}/target
org.springframework.boot
spring-boot-maven-plugin
2.3.7.RELEASE
com.nick.GnssApplication
repackage
repackage
com.github.core-lib
xjar-maven-plugin
src/main/resources
true
4.打包编译
5.反编译查看效果
OK, 效果杠杠滴,混淆+加密。
至此,混淆+加密搞定。
花了蛮多时间测试验证,兄弟们觉得疗效好,望不吝点赞啊,也欢迎各种拍砖,哈哈~~~~