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

问题描述 投票:9回答:1

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

java maven plugins proguard
1个回答
24
投票

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”JAR的构建中;这里我们解释使用Proguard obfuscation library所采取的步骤。使用default Proguard configuration for library obfuscation时,生成的JAR将无法正常工作,因为Proguard重命名,收缩,重定位和混淆Maven插件的重要文件。尝试使用您的插件可能会导致异常,该异常终止构建时出现与Maven运行时无法定位和处理插件的配置和类文件相关的错误。

但是,通过一些重新配置,我们可以指示Proguard正确维护生成的插件文件和“maven-plugin”JAR的目录结构。 Proguard选项的必要更改如下(请参阅以下链接的说明):


自定义Proguard配置

Directory Structure

-keepdirectories

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

Static Package References

-keeppackagenamesorg.apache.maven.plugin.my.MyMojo

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

Static Class References

-keepnamesclass * implements org.apache.maven.plugin.AbstractMojo

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

Private Class Fields and Methods

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

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


完成了Proguard配置

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

<!-- 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)

com.github.wvengen:proguard-maven-plugin的当前版本是2017年3月的2.0.14,直到编辑完成。我将完整保留原始配置版本号2.0.13,因为版本2.0.14包含一个潜在的破坏性更改。它现在包含种子和映射文件,作为最终Proguard混淆工件的输出工件的一部分。大多数用例实际上不太可能在工件中消耗额外的文件,但是不是忍者编辑配置指向2.0.14,而是留下这个注释,让你评估哪个版本适合你的项目。也就是说,简单地将版本更改为<version>2.0.14</version>应该没问题,因为版本2.0.14的提交历史记录中没有注明插件配置更改。

© www.soinside.com 2019 - 2024. All rights reserved.