java、springboot使用proguard混淆代码

1.情景展示

  我的需求是:为了将项目部署到机器上时,既不影响项目的正常运行,又可以做到降低项目源码(class文件)的可读性,其主要目的是为了防盗。

  一般情况下是用不到混淆器的,但是实际生活中往往存在这样的问题或需求,比方说:由于时间紧迫,两家企业被迫联合共同上线一个产品,现在是虽是合作关系,他们又可以相互取缔,同样的市场,蛋糕就这么大,时间长了难免互生嫌隙,所以为了保护各自产品被窃取,就需要防盗神器proguard了。

2.proguard简介

ProGuard 是一个免费的 Java类文件的压缩,优化,混肴器。它删除没有用的类,字段,方法与属性。使字节码最大程度地优化,使用简短且无意义的名字来重命名类、字段和方法 。eclipse已经把Proguard集成在一起了。

  吐槽:但说句实在话,proguard虽然降低了代码的可读性,但是,仍是能够读懂的,只是费点劲罢了。正所谓:防君子不防小人。

3.proguard教程

  第一步:maven配置(pom.xml)

<!--构建工具-->
<build>
    <!--自定义打包后的项目名称
    可以无视默认的打包名称规则:${artifactId}-${version}-->
    <finalName>bill</finalName>
    <plugins>
        <!--maven编译插件-->
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <!--二选一-->
            <version>${spring.version}</version>
            <!--<version>2.3.1.RELEASE</version>-->
        </plugin>
        <!--java混淆器插件-->
        <plugin>
            <groupId>com.github.wvengen</groupId>
            <artifactId>proguard-maven-plugin</artifactId>
            <version>2.3.1</version>
            <executions>
                <execution>
                    <!-- 混淆时刻:这里是打包的时候混淆 -->
                    <phase>package</phase>
                    <goals>
                        <!-- 使用插件的什么功能: 混淆-->
                        <goal>proguard</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <proguardVersion>${proguard.version}</proguardVersion>
                <!--<proguardVersion>6.2.2</proguardVersion>-->
                <!-- 是否混淆-->
                <obfuscate>true</obfuscate>
                <!--关键:引入配置文件,这里换成你的配置文件所在路径,一般情况下就是把proguard.cfg放到这个目录-->
                <proguardInclude>${project.basedir}/src/main/resources/proguard.cfg</proguardInclude>
                <!-- 混淆时需要引用的java库,这些库的类不会做混淆 -->
                <libs>
                    <lib>${java.home}/lib/rt.jar</lib>
                    <lib>${java.home}/lib/jce.jar</lib>
                </libs>

                <!--当<injar></injar>的值为:classes时,可以结合该标签使用,作用:相关混淆配置只为指定目录下的class文件起效-->
                <!--<inFilter>com/marydon/**</inFilter>-->
                <!-- 需要做混淆的jar或class目录,也就是:选择对什么东西进行加载-->
                <injar>classes</injar>
                <!--<injar>${project.build.finalName}.jar</injar>-->

                <!--class 混淆后输出的jar包,说明:这个输出格式可有可无,下面会讲 -->
                <outjar>${project.build.finalName}-pd.jar</outjar>
                <!-- 输出目录 -->
                <outputDirectory>${project.build.directory}</outputDirectory>
            </configuration>
            <dependencies>
                <dependency>
                    <groupId>net.sf.proguard</groupId>
                    <artifactId>proguard-base</artifactId>
                    <version>${proguard.version}</version>
                    <!--<version>6.2.2</version>-->
                    <scope>runtime</scope>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
 </build>

  这里需要注意的一点是:build标签需要在dependencies下方

  第二步:插件下载

  先不要管proguard.cfg文件怎么写,搞定这个插件才能继续往下走,不然就是浪费时间,即使你将配置文件写好,离开了这个插件,要配置文件有啥用?

  为了搞定最新版的插件,浪费了我不少时间,下面科普一下,如果你引入以上配置文件后,proguard插件下载成功,就可以跳过这一步了。

  上面这个插件,明确的告诉你:阿里云maven中央仓库有!!!

  如果下载失败,说明:该项目使用的maven中央仓库不是阿里云的,怎么办?

  很简单,不用去该maven下面的settings.xml,直接在项目中引入即可。

 <!--配置项目的jar包仓库-->
<repositories>
    <!--阿里云仓库,id=central,会覆盖掉setting.xml中配置的中央仓库-->
    <repository>
        <id>central</id>
        <name>central maven</name>
        <url>https://maven.aliyun.com/repository/central</url>
        <!--<url>http://maven.aliyun.com/nexus/content/groups/public/</url>-->
    </repository>
    <!--maven官网-->
    <repository>
        <id>public</id>
        <name>public maven</name>
        <url>https://mvnrepository.com</url>
    </repository>
</repositories>

  这样,仓库配置仅对本项目生效,也不会影响到其它项目对于settings.xml的依赖。

  这里需要注意的一点是:repositories标签需要在dependencies上方

  点击右侧maven视图里的这个按钮,网络较好的情况下,很快就下载完成了。

  如果插件不再报错,基本上就成了 

  如果该插件下载不成功,就没有继续进行下去的必要了,等搞定再往下看。

  第三步:proguard.cfg配置文件

  新建proguard.cfg文件,并将其放到src/main/resources目录下

  第四步:打包

  使用maven插件打包,打开maven视图,找到package,进行打包即可。

  打包成功日志 

  成功后,target目录下会多出三个文件 

  bill-pd.jar,就是项目混淆后的jar包(

  也就是说:混淆后的代码会被proguard插件单独打成一个jar包,与bill.jar的主要区别就是:前者是带有混淆的class文件,后者是正常的class文件

 

  这里,讲一下前面在pom.xml中配置的<outjar>${project.build.finalName}-pd.jar</outjar>标签,这个标签可有可无。

  如果去掉指定混淆文件的输出格式,打包后会是什么样的呢?

  区别在于:原来的bill-pd.jar变成了classes_proguard_base目录

  里面的内容没有区别。

  第五步:injar与outjar

  这两个标签如果不配合好,效率将会大打折扣,而且还容易出错。由上面我们知道,

  injar:是在插件混淆的源目录,也就是,混淆前的代码来源,它有两种表现形式:第一种是class目录,第二种是${project.build.finalName}.jar;

  outjar:插件执行混淆完毕后,将要输出的文件打包成什么样的格式,这里仅支持jar包,不支持war包,injar标签也一样;如果不声明该标签的话,将会默认生成classes_proguard_base目录。

  第六步:部署项目

  方式一:部署jar包

  编译源目录格式使用:<injar>${project.build.finalName}.jar</injar>

  输出目录格式使用:<outjar>${project.build.finalName}-pd.jar</outjar>

  这样,即使没有前后端分离,我们也可以确保bill-pd.jar包含的是项目的完整代码,可以拿出直接使用

  测试结果如下:

  可能会报这个错:Unable to open nested entry ********.jar

  分析:因为javaUtils.jar是我自己封装的一个jar包,混淆插件会将它单独抽出来再次压缩,导致java解析失败,所以我就想将输入输出名字保持一致。 

  测试结果如下:

  使用将输出的jar包名称和输入jar包名称保持一致

  即:<outjar>${project.build.finalName}.jar</outjar>,其执行结果是:生成的默认值(项目名称_proguard_base.jar)

  项目启动成功,但仍无法访问项目,这个问题是idea maven插件自身package命令的bug

  解决方案,就是使用原始的maven命令,手动将其打成jar包,不懂的可以见文末推荐

  项目访问成功(<outjar>${project.build.finalName}.jar</outjar>,必须是这个)

  方式二:部署war包

  编译源目录格式使用:<injar>classes</injar>

  输出目录格式使用:删除<outjar></outjar>标签

  打包标签设置成war:<packaging>war</packaging>

  将项目打成war包后,用压缩软件打开,依次打开WEB-INF/classes目录,删掉,再将生成的混淆文件里的class文件复制进去即可。

   

写在最后

  哪位大佬如若发现文章存在纰漏之处或需要补充更多内容,欢迎留言!!!

 相关推荐:

原文地址:https://www.cnblogs.com/Marydon20170307/p/13847588.html