1.由于项目需要私有化部署,为了保证代码的安全性,需要对springboot项目进项代码混淆,代码混淆顾名思义就是把代码变得让人看不懂,那么看不懂了又怎么运行呢,其实混淆主要混淆一些关键性的业务性代码,把关于业务逻辑的一部分代码变量名称变成a,b,c,d,e,f,g…就让人读起来很难理解。但是话又说回来,由于代码的特殊性,像mybatis一样,如果把变量名都改了,xml文件能映射到对象吗?答案是否定的。所以在代码混淆时需要排除掉一些可能会有问题的方法和类。下面就让我们一起来从零混淆一个springboot的项目吧。
[官网](http://www.allatori.com/)
可以先看一下官网的案例,解压官网给的demo:
在这里可以执行官网给的demo,并查看混淆后的代码。
<build>
<plugins>
<plugin>
<!-- springboot打包插件 -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<!-- resouces拷贝文件插件 -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<executions>
<!-- 执行这个插件的时候执行申明的所有phase -->
<execution>
<id>copy-and-filter-allatori-config</id>
<phase>package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<!-- 这个地方需要注意拷贝的文件位置需要是target目录,target目录是最终打jar包存放的位置 -->
<outputDirectory>${basedir}/target</outputDirectory>
<resources>
<resource>
<!-- 这个地方的文件目录需要注意,网上很多目录都是${basedir}/allatori这个,所以才会需要手动拷贝allatori.xml文件到target目录下,有了这个mvn会自动帮我们拷贝了 -->
<directory>src/main/resources</directory>
<includes>
<!-- 配置文件文件名 -->
<include>allatori.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<!-- 代码混淆打包插件 -->
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<id>run-allatori</id>
<phase>package</phase>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>java</executable>
<arguments>
<argument>-Xms128m</argument>
<argument>-Xmx512m</argument>
<argument>-jar</argument>
<!-- 指定引用的allatori的jar包位置,这里把jar包放在了根目录下的lib目录里 -->
<argument>../lib/allatori.jar</argument>
<!-- 指定代码混淆时的配置文件,因为是混淆指定的是jar包,jar包位置在target下,所以我们的allatori.xml也需要拷贝到该目录下 -->
<argument>${basedir}/target/allatori.xml</argument>
</arguments>
</configuration>
</plugin>
</plugins>
</build>
<config>
<input>
<!-- in中是待混淆的jar包,out是混淆后的jar包,路径是相对本配置文件所在位置 -->
<!-- 这个示例中,A.jar是工程jar包,B.jar是子模块jar包 -->
<jar in="demo_service-0.0.1-SNAPSHOT.jar" out="demo_service-0.0.1-SNAPSHOT-obfuscated.jar"/>
<!-- <jar in="../../B/target/B.jar" out="B.jar"/>-->
</input>
<!-- ignore-classes中配置不被混淆的类 -->
<ignore-classes>
<!-- 配置了启动相关类不被混淆,保证springboot可以正常启动 -->
<class template="class *Application*"/>
<class template="class *springframework*"/>
<class template="class *alibaba*"/>
<class template="class *persistence*"/>
<class template="class *apache*"/>
<class template="class *model*"/>
<class template="class *enums*"/>
<class template="class *repository*"/>
</ignore-classes>
<keep-names>
<!-- 防止部分类、方法、变量找不到名称而报错 -->
<!-- 所有方法名称不变,parameters="keep"表示方法参数名也不变 -->
<method template="*(**)" parameters="keep"/>
<!-- com.a.b.c中的类以及其子包中的类的名称不变 -->
<!-- <class template="class com.a.b.c.*"/>-->
</keep-names>
<property name="log-file" value="log.xml"/>
</config>
还有很多配置可以参考官方文档:
配置好之后就可以打包了,如下图所示
当你看到下图时,说明多半你的代码已经混淆成功了,至于能不能用还有待验证
jar包拿出来就可以运行了,如果不能运行,就需要看一下错误信息,可能是某个类或方法不能做混淆,就需要在配置文件中配置相关类不被混淆
实际工作中,我们的项目大部分情况下是在自己服务器上部署的,只有个别需要私有化部署的项目,所以我们希望在需要的时候打开混淆的开关,生成混淆后的jar包,不需要的时候就还按照原有的jar包生成。我相信有很多公司也是一样的情况,那下面我们继续探索吧。
方案一:
设置两个pom.xml通过maven打包配置 mvn package -f allatori-pom.xml,其中原pom.xml保持不变,在allatori-pom.xml中指定代码混淆的插件,在jenkins打包中可以通过配置,设置打包时指定pom文件
并把pom.xml参数化,可以在需要的时候打出混淆的包,不需要的时候指定默认的pom.xml即可
优点:清晰明了,在大部分不需要打代码混淆包的情况下比较实用,原pom不受影响,代码修改最小化
缺点:pom.xml无法继承或复用,新建的allatori-pom.xml需要维护,添加依赖时需要多次复制,否则可能在生成混淆包时打包错误
方案二:
pom文件还按照上面例子中修改,打包时指定-Dskip=true,指跳过代码混淆执行器,注意:插件exec-maven-plugin在1.5.0以前是有别名的,别名叫skip,可以通过-Dskip=true跳过执行器,1.5.0之后去掉了别名,需要通过-Dexec.skip=true跳过执行器,默认配置false
打包时通过jenkins配置,如下图:
优点:不需要考虑pom.xml维护问题,一次修改,终身受益
选择方案二,因为刚开始不知道有这个配置项的,所以暂时采用了方案一,后边翻看maven官网,并看了exec-maven-plugin源码后,发现了这个配置项,所以就改用第二种方案了。真香!
1 如果代码里请求静态资源的方法,注意请求路径的写法。因为如果是第三步将混淆后的jar包导入项目,获取文件的相对路径可能会不一样
2 如果方法中有重定向等写法,主要不要将此内容进行混淆;