赞
踩
项目组核心代码模块部署于用户服务器上,直接甩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文件引入
- <plugin>
- <groupId>net.roseboy</groupId>
- <artifactId>classfinal-maven-plugin</artifactId>
- <version>1.2.1</version>
- <configuration>
- <password>#</password><!-- #表示启动时不需要密码,事实上对于代码混淆来说,这个密码没什么用,它只是一个启动密码 -->
- <packages>com.nick.gnss</packages><!-- 加密的包名,多个包用逗号分开-->
- <excludes>org.spring</excludes>
- </configuration>
- <executions>
- <execution>
- <phase>package</phase>
- <goals>
- <goal>classFinal</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
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之前,否则混淆没有效果。原理就是在打包之前将代码混淆,然后再打包。
- <!--代码混淆proguard-->
- <plugin>
- <groupId>com.github.wvengen</groupId>
- <artifactId>proguard-maven-plugin</artifactId>
- <version>2.6.0</version>
- <executions>
- <!-- 以下配置说明执行mvn的package命令时候,会执行proguard-->
- <execution>
- <phase>package</phase>
- <goals>
- <goal>proguard</goal>
- </goals>
- </execution>
- </executions>
- <configuration>
- <!-- 就是输入Jar的名称,我们要知道,代码混淆其实是将一个原始的jar,生成一个混淆后的jar,那么就会有输入输出。 -->
- <injar>${project.build.finalName}.jar</injar>
- <!-- 输出jar名称,输入输出jar同名的时候就是覆盖,也是比较常用的配置。 -->
- <outjar>${project.build.finalName}.jar</outjar>
- <!-- 是否混淆 默认是true -->
- <obfuscate>true</obfuscate>
- <!-- 配置一个文件,通常叫做proguard.cfg,该文件主要是配置options选项,也就是说使用proguard.cfg那么options下的所有内容都可以移到proguard.cfg中 -->
- <proguardInclude>${project.basedir}/proguard.cfg</proguardInclude>
- <!-- 额外的jar包,通常是项目编译所需要的jar -->
- <libs>
- <lib>${java.home}/lib/rt.jar</lib>
- <lib>${java.home}/lib/jce.jar</lib>
- <lib>${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中配置 -->
- </options>
- </configuration>
- </plugin>
-
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- <version>2.3.7.RELEASE</version>
- <configuration>
- <mainClass>com.nick.GnssApplication</mainClass>
- </configuration>
- <executions>
- <execution>
- <id>repackage</id>
- <goals>
- <goal>repackage</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
3.反编译看效果
查看xxx.jar是否有混淆的效果,而不是xxx_proguard_base.jar(此jar是没有混淆的原jar)
效果杠杠滴!!!需要试运行,并且注意配置proguard,否则会导致程序运行异常,这可能就是proguard的唯一缺点了吧,欢迎拍砖。。。
4.运行查看效果
启动成功,没毛病
1.parent pom文件引入
重点在最下面的xjar plugin
- <?xml version="1.0" encoding="UTF-8"?>
- <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.0</modelVersion>
- <groupId>com.nick</groupId>
- <artifactId>nick-server</artifactId>
- <version>1.0.0</version>
- <name>nick-server</name>
- <description>Demo project for Spring Boot</description>
-
- <properties>
- <java.version>1.8</java.version>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
- <spring-boot.version>2.3.7.RELEASE</spring-boot.version>
- </properties>
-
- <modules>
- <module>gnss-server</module>
- </modules>
-
- <packaging>pom</packaging>
-
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <scope>test</scope>
- <exclusions>
- <exclusion>
- <groupId>org.junit.vintage</groupId>
- <artifactId>junit-vintage-engine</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- </dependencies>
-
- <dependencyManagement>
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-dependencies</artifactId>
- <version>${spring-boot.version}</version>
- <type>pom</type>
- <scope>import</scope>
- </dependency>
- </dependencies>
- </dependencyManagement>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <version>3.8.1</version>
- <configuration>
- <source>1.8</source>
- <target>1.8</target>
- <encoding>UTF-8</encoding>
- </configuration>
- </plugin>
-
- <!--代码加密-->
- <plugin>
- <groupId>com.github.core-lib</groupId>
- <artifactId>xjar-maven-plugin</artifactId>
- <version>v2.0.7</version>
- <executions>
- <execution>
- <goals>
- <goal>build</goal>
- </goals>
- <phase>package</phase>
- <configuration>
- <password>44889951235894612351265ABD123</password>
- <mode>1</mode>
- <sourceDir>${project.build.directory}</sourceDir>
- <targetJar>${project.build.finalName}_x.jar</targetJar>
- <includes>
- <include>com/nick/**</include>
- </includes>
- </configuration>
- </execution>
- </executions>
- </plugin>
-
- </plugins>
- </build>
-
- </project>
2. module pom文件引入
需要放在module pom文件plugin 最后一个,保证xjar是最后一个执行plugin
- <!--代码加密xjar-->
- <plugin>
- <groupId>com.github.core-lib</groupId>
- <artifactId>xjar-maven-plugin</artifactId>
- </plugin>
3.编译打包
4.反编译看效果
效果杠杠滴
5.运行查看效果
将第四步和第五步融合即可,但是要注意pom文件中的plugin的先后问题,不然要么混淆失败,要么加密失败。
1.完整版的parent pom文件
- <?xml version="1.0" encoding="UTF-8"?>
- <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.0</modelVersion>
- <groupId>com.nick</groupId>
- <artifactId>nick-server</artifactId>
- <version>1.0.0</version>
- <name>nick-server</name>
- <description>Demo project for Spring Boot</description>
-
- <properties>
- <java.version>1.8</java.version>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
- <spring-boot.version>2.3.7.RELEASE</spring-boot.version>
- </properties>
-
- <modules>
- <module>gnss-server</module>
- </modules>
-
- <packaging>pom</packaging>
-
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <scope>test</scope>
- <exclusions>
- <exclusion>
- <groupId>org.junit.vintage</groupId>
- <artifactId>junit-vintage-engine</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- </dependencies>
-
- <dependencyManagement>
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-dependencies</artifactId>
- <version>${spring-boot.version}</version>
- <type>pom</type>
- <scope>import</scope>
- </dependency>
- </dependencies>
- </dependencyManagement>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <version>3.8.1</version>
- <configuration>
- <source>1.8</source>
- <target>1.8</target>
- <encoding>UTF-8</encoding>
- </configuration>
- </plugin>
-
- <!--代码加密-->
- <plugin>
- <groupId>com.github.core-lib</groupId>
- <artifactId>xjar-maven-plugin</artifactId>
- <version>v2.0.7</version>
- <executions>
- <execution>
- <goals>
- <goal>build</goal>
- </goals>
- <phase>package</phase>
- <configuration>
- <password>44889951235894612351265ABD123</password>
- <mode>1</mode>
- <sourceDir>${project.build.directory}</sourceDir>
- <targetJar>${project.build.finalName}_x.jar</targetJar>
- <includes>
- <include>com/nick/**</include>
- </includes>
- </configuration>
- </execution>
- </executions>
- </plugin>
-
- </plugins>
- </build>
-
- </project>
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执行
- <?xml version="1.0" encoding="UTF-8"?>
- <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">
-
- <parent>
- <artifactId>nick-server</artifactId>
- <groupId>com.nick</groupId>
- <version>1.0.0</version>
- </parent>
-
- <modelVersion>4.0.0</modelVersion>
- <groupId>com.nick</groupId>
- <artifactId>gnss-server</artifactId>
- <version>1.0.0</version>
- <name>gnss-server</name>
- <description>gnss-server</description>
-
-
- <properties>
- <java.version>1.8</java.version>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
- <spring-boot.version>2.3.7.RELEASE</spring-boot.version>
- <!--maven.build.timestamp保存了maven编译时间戳-->
- <!--在Maven 3.2.2+中, maven.build.timestamp已被重新定义,显示UTC中的时间,比中国时间慢8个小时-->
- <timestamp>${maven.build.timestamp}</timestamp>
- <!--指定时间格式-->
- <maven.build.timestamp.format>yyyy-MM-dd HH:mm:ss</maven.build.timestamp.format>
- </properties>
-
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <scope>test</scope>
- <exclusions>
- <exclusion>
- <groupId>org.junit.vintage</groupId>
- <artifactId>junit-vintage-engine</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
-
- <dependency>
- <groupId>io.jsonwebtoken</groupId>
- <artifactId>jjwt</artifactId>
- <version>0.9.1</version>
- </dependency>
-
- <!-- lombok -->
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- <version>1.18.16</version>
- </dependency>
-
- <dependency>
- <groupId>commons-io</groupId>
- <artifactId>commons-io</artifactId>
- <version>2.6</version>
- </dependency>
-
- <dependency>
- <groupId>com.alibaba</groupId>
- <artifactId>fastjson</artifactId>
- <!--1.2.80以下存在安全漏洞-->
- <!--<version>1.2.78</version>-->
- <version>1.2.83</version>
- </dependency>
-
- <dependency>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- <version>30.1.1-jre</version>
- </dependency>
-
- <!--nacos-web-->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
- </dependencies>
-
- <dependencyManagement>
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-dependencies</artifactId>
- <version>${spring-boot.version}</version>
- <type>pom</type>
- <scope>import</scope>
- </dependency>
- </dependencies>
- </dependencyManagement>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <version>3.8.1</version>
- <configuration>
- <source>1.8</source>
- <target>1.8</target>
- <encoding>UTF-8</encoding>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-resources-plugin</artifactId>
- <configuration>
- <delimiters>
- <delimiter>@</delimiter>
- </delimiters>
- <useDefaultDelimiters>false</useDefaultDelimiters>
- </configuration>
- </plugin>
-
- <!--代码混淆proguard-->
- <plugin>
- <groupId>com.github.wvengen</groupId>
- <artifactId>proguard-maven-plugin</artifactId>
- <version>2.6.0</version>
- <executions>
- <!-- 以下配置说明执行mvn的package命令时候,会执行proguard-->
- <execution>
- <phase>package</phase>
- <goals>
- <goal>proguard</goal>
- </goals>
- </execution>
- </executions>
- <configuration>
- <!-- 就是输入Jar的名称,我们要知道,代码混淆其实是将一个原始的jar,生成一个混淆后的jar,那么就会有输入输出。 -->
- <injar>${project.build.finalName}.jar</injar>
- <!-- 输出jar名称,输入输出jar同名的时候就是覆盖,也是比较常用的配置。 -->
- <outjar>${project.build.finalName}.jar</outjar>
- <!-- 是否混淆 默认是true -->
- <obfuscate>true</obfuscate>
- <!-- 配置一个文件,通常叫做proguard.cfg,该文件主要是配置options选项,也就是说使用proguard.cfg那么options下的所有内容都可以移到proguard.cfg中 -->
- <proguardInclude>${project.basedir}/proguard.cfg</proguardInclude>
- <!-- 额外的jar包,通常是项目编译所需要的jar -->
- <libs>
- <lib>${java.home}/lib/rt.jar</lib>
- <lib>${java.home}/lib/jce.jar</lib>
- <lib>${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中配置 -->
- </options>
- </configuration>
- </plugin>
-
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- <version>2.3.7.RELEASE</version>
- <configuration>
- <mainClass>com.nick.GnssApplication</mainClass>
- </configuration>
- <executions>
- <execution>
- <id>repackage</id>
- <goals>
- <goal>repackage</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
-
- <!--代码加密xjar-->
- <plugin>
- <groupId>com.github.core-lib</groupId>
- <artifactId>xjar-maven-plugin</artifactId>
- </plugin>
-
- <!--classfinal加密程序-->
- <!--<plugin>-->
- <!--<groupId>net.roseboy</groupId>-->
- <!--<artifactId>classfinal-maven-plugin</artifactId>-->
- <!--<version>1.2.1</version>-->
- <!--<configuration>-->
- <!--<password>#</password><!– #表示启动时不需要密码,事实上对于代码混淆来说,这个密码没什么用,它只是一个启动密码 –>-->
- <!--<packages>com.nick.gnss</packages><!– 加密的包名,多个包用逗号分开–>-->
- <!--<excludes>org.spring</excludes>-->
- <!--</configuration>-->
- <!--<executions>-->
- <!--<execution>-->
- <!--<phase>package</phase>-->
- <!--<goals>-->
- <!--<goal>classFinal</goal>-->
- <!--</goals>-->
- <!--</execution>-->
- <!--</executions>-->
- <!--</plugin>-->
- </plugins>
-
- <resources>
- <resource>
- <directory>src/main/resources</directory>
- <filtering>true</filtering>
- </resource>
- </resources>
- </build>
-
- </project>
4.打包编译
5.反编译查看效果
OK, 效果杠杠滴,混淆+加密。
至此,混淆+加密搞定。
花了蛮多时间测试验证,兄弟们觉得疗效好,望不吝点赞啊,也欢迎各种拍砖,哈哈~~~~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。