如何在构建“maven-plugin”包时使用Proguard混淆?

时间:2016-01-10 14:21:07

标签: java maven plugins proguard

“maven-plugin”项目的生成输出JAR(使用maven-plugin-plugin)被Proguard工具执行的模糊处理打破。尝试将混淆的JAR用作Maven插件会生成异常,例如MojoExecutionException,它会以错误终止构建。什么是适当的Proguard配置选项,以允许生成包含自动生成的插件描述符的工作“maven-plugin”JAR?

1 个答案:

答案 0 :(得分:23)

Maven插件和Proguard工具的基础知识

为了生成Maven插件(maven包装类型"maven-plugin",它生成包含特定于插件的配置资源的JAR),我们必须指示maven-plugin-plugin关于Mojos的位置和名称。假设正确配置了maven-plugin-plugin执行,using annotations或其他配置选项,生成的JAR将在JAR根目录的META-INF目录中包含plugin.xml文件。此plugin.xml文件使用对Java类和包名称的静态引用来描述插件的目标和可配置参数(您可以在此文件中找到更多信息here)。

必须特别注意将混淆纳入一个" maven-plugin"罐;这里我们解释使用Proguard obfuscation library所采取的步骤。使用default Proguard configuration for library obfuscation时,生成的JAR将无法正常工作,因为Proguard重命名,收缩,重定位和混淆Maven插件的重要文件。尝试使用您的插件可能会导致异常终止构建,并出现与Maven运行时无法定位和处理插件的配置和类文件相关的错误。

然而,通过一些重新配置,我们可以指示Proguard正确维护您生成的插件文件和您的" maven-plugin"罐。 Proguard选项的必要更改如下(请参阅以下链接的说明):

自定义Proguard配置

目录结构

-keepdirectories

这指示Proguard维护输入JAR目录结构,而不是将所有文件移动到根目录。 Maven希望plugin.xml文件位于/ META-INF / maven /目录中,并通过此选项与所有其他目录一起保存。您可以通过指定目录过滤器来更具体地过滤保留的目录,但是我选择不加选择地维护所有输入目录结构。

静态包参考

-keeppackagenames org.apache.maven.plugin.my.MyMojo

您应该使用包含Mojo定义的包替换占位符包。如果您的Mojo定义不共享公共包,则应根据需要使用多个选项指定每个唯一包。如果您不确定需要保留哪些包,请在文本编辑器中打开生成的plugin.xml文件,并检查"实现"每个" mojo"中的元素定义。 "实施" element通过完全限定名称指定类。这些完全限定类名的每个包组件都是您应该指定的包。例如,我的basedir-plugin包含一个Mojo实现元素值" com.github.emabrey.maven.plugins.basedir.RootDirectoryGoal",所以我将该选项写为-keeppackagenames com.github.emabrey.maven.plugins.basedir

静态类引用

-keepnames class * implements org.apache.maven.plugin.AbstractMojo

此选项可防止Proguard重命名包含Maven插件Mojo实现的类。如果这些类重命名为上述"实现"元素将不再正确识别包含Mojo实现的类。

私有类字段和方法

-keepclassmembers class * implements org.apache.maven.plugin.AbstractMojo { private <fields>; private <methods>; }

此选项可防止Proguard重命名插件Mojo实现中的类级别方法和字段。 Maven使用这些类字段/方法的名称来生成插件的配置元素。如果Proguard重命名字段,则Maven执行环境将无法使用用户配置正确填充Mojo实现。

完成Proguard配置

版本2.0.13的完整配置(more versions here;请参阅有关插件版本的说明),包括默认库配置以及上述修改,为方便起见,此处提供(请记住使用latest version of the proguard-base artifact指定${tool.proguard.version}属性并使用适当的值替换占位符包&#34; org.apache.maven.plugin.my.MyMojo&#34;:

<!-- Configures Proguard obfuscation tool to generate an
     obfuscated version of the JAR file that replaces the
     default unobfuscated JAR.
-->
<plugin>
    <groupId>com.github.wvengen</groupId>
    <artifactId>proguard-maven-plugin</artifactId>
    <version>2.0.13</version>
    <executions>
        <execution>
            <id>obfuscation-packaging</id>
            <phase>package</phase>
            <goals>
                <goal>proguard</goal>
            </goals>
            <configuration>
                <proguardVersion>${tool.proguard.version}</proguardVersion>
                <obfuscate>true</obfuscate>
                <attach>true</attach>
                <appendClassifier>false</appendClassifier>
                <addMavenDescriptor>true</addMavenDescriptor>
                <injar>${project.build.finalName}.jar</injar>
                <injarNotExistsSkip>true</injarNotExistsSkip>
                <libs>
                    <lib>${java.home}/lib/rt.jar</lib>
                </libs>

                <options>
                    <option>-keepdirectories</option>
                    <option>-keeppackagenames org.apache.maven.plugin.my.MyMojo</option>
                    <option>-keepnames class * implements org.apache.maven.plugin.AbstractMojo</option>
                    <option>-keepclassmembers class * implements org.apache.maven.plugin.AbstractMojo {
                        private <![CDATA[<fields>]]>;
                        private <![CDATA[<methods>]]>;
                    }
                    </option>
                    <option>-keepparameternames</option>
                    <option>-renamesourcefileattribute SourceFile</option>
                    <option>-keepattributes Exceptions,InnerClasses,Signature,Deprecated,
                        SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
                    </option>
                    <option>-target 1.8</option>
                    <option>-keep public class * {
                        public protected *;
                        }
                    </option>
                    <option>-keepclassmembernames class * {
                        java.lang.Class class$(java.lang.String);
                        java.lang.Class class$(java.lang.String, boolean);
                        }
                    </option>
                    <option>-keepclasseswithmembernames,includedescriptorclasses class * {
                        native <![CDATA[<methods>]]>;
                        }
                    </option>
                    <option>-keepclassmembers,allowoptimization enum * {
                        public static **[] values();
                        public static ** valueOf(java.lang.String);
                        }
                    </option>
                    <option>-keepclassmembers class * implements java.io.Serializable {
                        static final long serialVersionUID;
                        private static final java.io.ObjectStreamField[] serialPersistentFields;
                        private void writeObject(java.io.ObjectOutputStream);
                        private void readObject(java.io.ObjectInputStream);
                        java.lang.Object writeReplace();
                        java.lang.Object readResolve();
                        }
                    </option>
                </options>
            </configuration>
        </execution>
    </executions>
    <dependencies>
        <dependency>
            <groupId>net.sf.proguard</groupId>
            <artifactId>proguard-base</artifactId>
            <version>${tool.proguard.version}</version>
        </dependency>
    </dependencies>
</plugin>  

备注

链接问题(9-04-2019)

Proguard网站存在某种问题,这意味着我对程序选项的链接并不总是以锚点链接的方式进入锚点的位置。如果您没有看到您点击的选项最初显示在他们的网页上,只需稍微向上滚动即可。

proguard-maven-plugin的版本问题(9-04-2019)

截至2017年3月,com.github.wvengen:proguard-maven-plugin的当前版本为2.0.14,直到进行此修改为止。我将完整保留原始配置版本号2.0.13,因为版本2.0.14包含可能发生的重大更改。它现在包含种子和映射文件,作为最终Proguard混淆工件的输出工件的一部分。大多数用例实际上不太可能在工件中消耗额外的文件,但不是忍者编辑配置指向2.0.14,而是留下这个注释,让你评估哪个版本适合于你的项目。也就是说,只需将版本更改为<version>2.0.14</version>即可,因为版本2.0.14的提交历史记录中未记录任何插件配置更改。