文章目录
字节码加密
方案1:使用工具ClassFinal
使用工具ClassFinal
说明:ClassFinal是一款java class文件安全加密工具,支持直接加密jar包或war包,无需修改任何项目代码,兼容spring-framework;可避免源码泄漏或字节码被反编译。
目前项目处于暂停状态
使用方式
1. 命令行方式
java -jar classfinal-fatjar.jar -file yourpaoject.jar -libjars a.jar,b.jar -packages com.yourpackage,com.yourpackage2 -exclude com.yourpackage.Main -pwd 123456 -Y
参数说明
-file 加密的jar/war完整路径
-packages 加密的包名(可为空,多个用","分割)
-libjars jar/war包lib下要加密jar文件名(可为空,多个用","分割)
-cfgfiles 需要加密的配置文件,一般是classes目录下的yml或properties文件(可为空,多个用","分割)
-exclude 排除的类名(可为空,多个用","分割)
-classpath 外部依赖的jar目录,例如/tomcat/lib(可为空,多个用","分割)
-pwd 加密密码,如果是#号,则使用无密码模式加密
-code 机器码,在绑定的机器生成,加密后只可在此机器上运行
-Y 无需确认,不加此参数会提示确认以上信息
2. maven插件方式
在要加密的项目pom.xml中加入以下插件配置,目前最新版本是:1.2.1。
<plugin>
<!-- https://gitee.com/roseboy/classfinal -->
<groupId>net.roseboy</groupId>
<artifactId>classfinal-maven-plugin</artifactId>
<version>${classfinal.version}</version>
<configuration>
<password>000000</password><!--加密打包之后pom.xml会被删除,不用担心在jar包里找到此密码-->
<packages>com.yourpackage,com.yourpackage2</packages>
<cfgfiles>application.yml</cfgfiles>
<excludes>org.spring</excludes>
<libjars>a.jar,b.jar</libjars>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>classFinal</goal>
</goals>
</execution>
</executions>
</plugin>
运行mvn package时会在target下自动加密生成yourpaoject-encrypted.jar。
maven插件的参数名称与直接运行的参数相同,请参考上节的参数说明。
示例:
比如源码:
@RestController
@RequestMapping("user")
public class UserController {
@GetMapping("get")
public String get(){
System.out.println("hello world");
return "user";
}
}
加密之后的源码:
@RestController
@RequestMapping({"user"})
public class UserController {
public UserController() {
}
@GetMapping({"get"})
public String get() {
return null;
}
}
注意: 原始的class文件并不会完全被加密,只是方法体被清空,保留方法参数、注解等信息,这是为了兼容spring,swagger等扫描注解的框架; 方法体被清空后,反编译者只能看到方法名和注解,看不到方法的具体内容;当class被classloader加载时,真正的方法体会被解密注入。
方案2:使用Protector4J
官网地址:Protector4J
说明:收费java字节码加密工具
-
支持 windows、Linux、macOS
-
费用:
项目 | 599/Y | 1099/Y | 3099/Y |
---|---|---|---|
For Individual Use | ✅ | ✅ | ✅ |
JavaSE Apps Protection | ✅ | ✅ | ✅ |
Tomcat Apps Protection | ✅ | ✅ | ✅ |
Spring Boot Apps Protection | ✅ | ✅ | ✅ |
Email Support | ✅ | ✅ | ✅ |
Live Chat Support (Slack) | ✅ | ✅ | |
Windows/Linux Service Creator | ✅ | ✅ | |
Docker Image Creator | ✅ | ✅ | |
Apple Silicon Support | ✅ | ✅ | |
Local Deployment (Encrypt without Internet) | ✅ |
- 参考文档:https://protector4j.com/docs
- 加密之后运行项目 jar:
# 默认加密之后的jar存放在vlxlib目录中
vlxjre/bin/java -jar vlxlib/xxx.jar
# 或者:
vlxjre/bin/java -cp vlxlib/xxx.jar MainClass
字节码混淆
方式1:ProGuard
介绍:
ProGuard 是一个开源的 Java 类文件压缩器、优化器、混淆器和预验证器。因此,ProGuard 处理的应用程序和库更小、更快,并且在一定程度上增强了逆向工程的能力。
文档:https://www.guardsquare.com/manual/
github:https://github.com/Guardsquare/proguard/
maven使用方式:
<plugin>
<groupId>com.github.wvengen</groupId>
<artifactId>proguard-maven-plugin</artifactId>
<version>2.0.14</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>proguard</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- 将混淆后的pg包自动部署到maven上-->
<attach>true</attach>
<attachArtifactClassifier>pg</attachArtifactClassifier>
<!-- attach 的作用是在 install 与 deploy 时将生成的 pg 文件也安装与部署 -->
<options>
<!-- JDK目标版本1.6-->
<option>-target 1.6</option>
<!-- 不做收缩(删除注释、未被引用代码)-->
<option>-dontshrink</option>
<!-- 不做优化(变更代码实现逻辑)-->
<option>-dontoptimize</option>
<!-- 不路过非公用类文件及成员-->
<option>-dontskipnonpubliclibraryclasses</option>
<option>-dontskipnonpubliclibraryclassmembers</option>
<!-- 优化时允许访问并修改有修饰符的类和类的成员 -->
<option>-allowaccessmodification</option>
<!-- 确定统一的混淆类的成员名称来增加混淆-->
<option>-useuniqueclassmembernames</option>
<!--保证spring注解能力-->
<!--<option>-keepdirectories</option>-->
<!-- 不混淆所有包名,本人测试混淆后WEB项目问题实在太多,毕竟Spring配置中有大量固定写法的包名-->
<option>-keeppackagenames</option>
<!-- 不混淆所有特殊的类-->
<option>-keepattributes
Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,LocalVariable*Table,*Annotation*,Synthetic,EnclosingMethod
</option>
<!-- 不混淆所有的set/get方法,毕竟项目中使用的部分第三方框架(例如Shiro)会用到大量的set/get映射-->
<option>-keepclassmembers public class * {void set*(***);*** get*();}</option>
<!-- 不混淆commonmodel,model包中的所有类以及类的属性及方法,实体包,混淆了会导致前端无法识别-->
<!--<option>-keep class com.xxx.web.commonmodel.** {*;}</option>-->
<!--<option>-keep class com.xxx.web.model.** {*;}</option>-->
<!--不混淆JNI相关接口-->
<!--<option>-keep class com.xxx.dasheng_cluster.service.** {*;}</option>-->
<!--<option>-keep class com.xxx.dasheng_selfsampling.service.** {*;}</option>-->
<!-- 非核心业务类,不作混淆 -->
<!--<option>-keep class com.xxx.web.util.** {*;}</option>-->
<!--<option>-keep class com.xxx.web.Swagger2 {*;}</option>-->
<!-- 以下三个包因为大部分是Spring管理的Bean,不对包类的类名进行混淆,但对类中的属性和方法混淆-->
<!--<option>-keep class com.xxx.web.controller.**</option>-->
<!--<option>-keep class com.xxx.web.service.**</option>-->
<!--<option>-keep class com.xxx.web.singleton.**</option>-->
<!-- 不混淆凭证包下的所有类名,但对类中的属性、方法进行混淆-->
<option>-keep class com.jd.ssa.client.interceptor.** {*;}</option>
<option>-keep class com.jd.ssa.client.service.** {*;}</option>
<option>-keep class com.jd.ssa.client.LoginContext {*;}</option>
<option>-keep class com.lopSdk.** {*;}</option>
<!-- 不混淆启动类,否则spring-boot不能正常启动 -->
<!--<option>-keep class com.xxx.web.Application</option>-->
<!-- 忽略打包时的告警信息 -->
<option>-ignorewarnings</option>
</options>
<!-- 输出目录-->
<outjar>${project.build.finalName}-pg.jar</outjar>
<!-- 添加依赖,这里你可以按你的需要修改,这里测试只需要一个JRE的Runtime包就行了 -->
<libs>
<lib>${java.home}/lib/rt.jar</lib>
<lib>${java.home}/lib/jce.jar</lib>
</libs>
<!-- 加载文件的过滤器,就是你的工程目录了-->
<!--<inFilter>com/xxx/dasheng/**</inFilter>-->
<!-- 对什么东西进行加载,这里仅有classes成功,毕竟你也不可能对配置文件及JSP混淆吧-->
<!--<injar>classes</injar>-->
<!-- 输出pom文件 -->
<addMavenDescriptor>true</addMavenDescriptor>
<!-- 输出目录-->
<outputDirectory>${project.build.directory}</outputDirectory>
</configuration>
</plugin>