如何将JavaFX应用程序签名并部署到单个.JAR中?

如何将JavaFX应用程序签名并部署到单个.JAR中?,java,ant,jar,javafx,code-signing,Java,Ant,Jar,Javafx,Code Signing,我仍在学习JavaFX的细节。一个主要的区别是,在dist文件夹中(除了库之外),除了.jar文件之外,我还找到了一个HTML文件和一个JNLP文件,它们对我都没有任何用处(这将是一个桌面应用程序) 我发现了以下内容(由于敏感/无关信息而省略了属性): 我发现它不起作用并不完全感到惊讶,但这有点问题。我做了一些关于可能部署“自包含”应用程序的研究,但这不适合我们的需要。我的雇主花了一些钱购买了一份Comodo证书,我很快就撞到了一堵墙,墙里似乎是因为苹果的恶作剧(除非我在这个假设中弄错了),你

我仍在学习JavaFX的细节。一个主要的区别是,在dist文件夹中(除了库之外),除了.jar文件之外,我还找到了一个HTML文件和一个JNLP文件,它们对我都没有任何用处(这将是一个桌面应用程序)

我发现了以下内容(由于敏感/无关信息而省略了属性):

我发现它不起作用并不完全感到惊讶,但这有点问题。我做了一些关于可能部署“自包含”应用程序的研究,但这不适合我们的需要。我的雇主花了一些钱购买了一份Comodo证书,我很快就撞到了一堵墙,墙里似乎是因为苹果的恶作剧(除非我在这个假设中弄错了),你必须以每年100美元的低成本加入他们的开发者俱乐部(没有发生)。我并不是专门为苹果平台做开发。我做Java开发。无论如何,如果我是正确的,这将不适用于我们,因此一个针对Windows、Linux和Mac的自包含部署已经过时(如果我是正确的,请再说一次)

我希望这是件简单的事

那么,如何将我创建的用于将包含所有依赖lib的JAR编译成代码签名JAR的ANT脚本应用到JavaFX应用程序中呢

编辑1:好吧,我肯定说得太早了。不太接近答案。我试着告诉弗兰肯斯坦我所知道的关于编译和签名常规JAR文件的知识,以便包括所有的LIB,并且该签名成功地进入了我能够从中挑选出来的内容中。我所拥有的是一个大杂烩和一个失败。我得到了一个.JAR文件,除了主.JAR文件之外,它包含了所有内容。无论如何,这是ANT脚本代码:

特性:

<property  name = "name"
          value = "APPNAME"/>

<property  name = "file"
          value = "APPJAR"/>

<property  name = "MC" 
          value = "MAINPACKAGE.MAINCLASS" />

<property  name = "released.dir"
          value = "released"/>

<property  name = "compiled.dir"
          value = "${released.dir}/compiled"/>

<property  name = "stored.dir"
          value = "${released.dir}/stored"/>

<property  name = "signed.dir"
          value = "${released.dir}/signed"/>
<property name = "JFXProject.name"
         value = "PROJECT"/> <!-- Put your own project name here -->
<property name = "JFXMainClass"
         value = "MAINPACKAGE.MAINCLASS"/> <!--Put your own main class here -->
    <!-- don't edit below this line -->
<property name = "JFX.src.dir"
         value = "src"/>
<property name = "JFX.lib.dir"
         value = "dist/lib"/>
<property name = "JFX.build.dir"
         value = "release/JFXBuild"/>
<property name = "JFX.sign.dir"
         value = "release/JFXSign"/>
<property name = "store.dir"
         value = "release/store"/>
<property name = "sign.dir"
         value = "release/sign"/>
<property name = "comodo.key.store"
         value = "PATH-TO-YOUR-CERTIFICATE" /> <!-- You can name this what you like, but you want to make sure the value points to your certificate or JKS file -->

<property name = "comodo.key.storepass"
         value = "PASSWORD"/> <!-- Above applies here. Make sure it's the right password -->

<property name = "comodo.key.alias"
         value = "ALIAS"/> <!-- Make sure it's your right alias. You can find out how to find that information from [here][3] -->

<property name = "comodo.key.pass"
         value = "PASSWORD"/> <!-- In my own experience this was the same as the storepass but it may be different for you -->

<property name = "timestamp.url"
         value = "TIMESTAMPURL"/> <!-- This will vary for you depending on your certificate. -->

其他一切:

<delete dir = "${released.dir}"/>
        <mkdir dir = "${compiled.dir}"/>

        <fx:jar destfile = "dist/compiled.jar">
            <fx:platform javafx = "8.0+" j2se = "8.0"/>
            <fx:application      name = "${name}"
                            mainClass = "${MC}"/>

            <fileset dir = "build/classes"/>

            <fx:resources>
                <fx:fileset dir = "dist" includes = "lib/*.jar"/>
            </fx:resources>
        </fx:jar>

        <fx:signjar keystore = "${comodo.key.store}"
                       alias = "${comodo.key.alias}"
                   storetype = "PKCS12"
                     keypass = "${comodo.key.pass}"
                   storepass = "${comodo.key.storepass}"
                         jar = "dist/compiled.jar"
                     destdir = "${compiled.dir}"/>

        <mkdir dir = "${stored.dir}"/>

        <jar       destFile = "${stored.dir}/temp_final.jar"
            filesetmanifest = "skip" >
            <zipgroupfileset      dir = "${compiled.dir}"
                             includes = "compiled.jar"/>

            <zipgroupfileset      dir = "dist/lib"
                             includes = "*.jar"/>

            <manifest>
                <attribute name = "Main-Class"
                          value = "${main.class}"/>
            </manifest>
        </jar>

        <zip destfile = "${stored.dir}/${file}">
            <zipfileset src = "${stored.dir}/temp_final.jar"
                   excludes = "META-INF/*.SF, META-INF/*.DSA, META-INF/*.RSA"/>
        </zip>

        <delete file="${stored.dir}/temp_final.jar"/>

        <mkdir dir = "${signed.dir}"/>

        <signjar
            keystore = "${comodo.key.store}"
               alias = "${comodo.key.alias}"
           storetype = "PKCS12"
              tsaurl = "${timestamp.url}"
             keypass = "${comodo.key.pass}"
           storepass = "${comodo.key.storepass}"
                 jar = "${stored.dir}/${file}"
             destdir = "${signed.dir}"/>


这就是我在我的时间里要展示的。如果有人能从中收集到一些东西,让我走上正确的道路(如果我离得很近,但我感觉不到我离得很近),那真是太棒了。

在把我的头骨和头骨里的东西捣碎成一种几乎认不出是连贯性思维的泥浆后,我成功地编写了一个脚本,完成了我要完成的任务。其中大部分来自其他人的贡献和咨询。另一个主要贡献是发现了(线程上的最后一条评论,它链接到另一个SO答案,但那个SO答案对我没有多大帮助)。感谢所有我能够从中提取部分解决方案的东西。我希望这对其他需要/想要完成这项任务的人有所帮助

无论如何:第一件事第一:属性:

<property  name = "name"
          value = "APPNAME"/>

<property  name = "file"
          value = "APPJAR"/>

<property  name = "MC" 
          value = "MAINPACKAGE.MAINCLASS" />

<property  name = "released.dir"
          value = "released"/>

<property  name = "compiled.dir"
          value = "${released.dir}/compiled"/>

<property  name = "stored.dir"
          value = "${released.dir}/stored"/>

<property  name = "signed.dir"
          value = "${released.dir}/signed"/>
<property name = "JFXProject.name"
         value = "PROJECT"/> <!-- Put your own project name here -->
<property name = "JFXMainClass"
         value = "MAINPACKAGE.MAINCLASS"/> <!--Put your own main class here -->
    <!-- don't edit below this line -->
<property name = "JFX.src.dir"
         value = "src"/>
<property name = "JFX.lib.dir"
         value = "dist/lib"/>
<property name = "JFX.build.dir"
         value = "release/JFXBuild"/>
<property name = "JFX.sign.dir"
         value = "release/JFXSign"/>
<property name = "store.dir"
         value = "release/store"/>
<property name = "sign.dir"
         value = "release/sign"/>
<property name = "comodo.key.store"
         value = "PATH-TO-YOUR-CERTIFICATE" /> <!-- You can name this what you like, but you want to make sure the value points to your certificate or JKS file -->

<property name = "comodo.key.storepass"
         value = "PASSWORD"/> <!-- Above applies here. Make sure it's the right password -->

<property name = "comodo.key.alias"
         value = "ALIAS"/> <!-- Make sure it's your right alias. You can find out how to find that information from [here][3] -->

<property name = "comodo.key.pass"
         value = "PASSWORD"/> <!-- In my own experience this was the same as the storepass but it may be different for you -->

<property name = "timestamp.url"
         value = "TIMESTAMPURL"/> <!-- This will vary for you depending on your certificate. -->

如果需要,可以将属性名称更改为对您更有意义的名称,但请确保它们在整个脚本中保持一致

接下来,我们要清理最后一个构建:

<target name = "JFXClean">
    <echo>Cleaning ${JFX.build.dir}...</echo>
    <delete dir = "${JFX.build.dir}"/>
    <delete dir = "${JFX.sign.dir}"/>
    <delete dir = "${store.dir}"/>
    <delete dir = "${sign.dir}"/>
</target>

正在清理${JFX.build.dir}。。。
然后我们要为新的干净构建重新创建目录

<target name = "JFXInit" depends = "JFXClean">
    <echo>Creating the build directory...</echo>
    <mkdir dir = "${JFX.build.dir}"/>
    <mkdir dir = "${JFX.sign.dir}"/>
    <mkdir dir = "${store.dir}"/>
    <mkdir dir = "${sign.dir}"/>
</target>

正在创建生成目录。。。
这一部分对于获取正常运行的JavaFXJAR文件至关重要:

<target name = "JFXBuild" depends = "jar, JFXInit">
    <fx:jar destfile = "${JFX.build.dir}/${JFXProject.name}.jar">
        <fx:application name = "${JFXProject.name}"
                   mainClass = "${JFXMainClass}"/>
        <fileset dir = "build/classes"/>
    </fx:jar>
</target>

这将正确地将所有部件存储到JAR中的相应位置(包括您可能拥有的任何CSS和JFXML文件)。如果您没有创建JFXML应用程序,这可能是不必要的。我不知道我还没有对其进行测试

然后我们要签署javafxjar:

<target name = "JFXSign" depends = "JFXBuild">
    <fx:signjar  keystore = "${comodo.key.store}"
                    alias = "${comodo.key.alias}"
                storetype = "PKCS12" <!-- This is necessary for me, but may not be for you if you are not using a PFX file -->
                  keypass = "${comodo.key.pass}"
                storepass = "${comodo.key.storepass}"
                      jar = "${JFX.build.dir}/${JFXProject.name}.jar"
                  destdir = "${JFX.sign.dir}"/>
</target>

神谕说:

需要修改

<manifest>
    <attribute name="Main-Class" value="${main.class}"/>
</manifest>

并将其更改为

<manifest>
    CHANGE application.MainClass to 
    <attribute name="JavaFX-Application-Class" value="application.MainClass" />
    <attribute name="Main-Class" value="com/javafx/main/Main" />
</manifest>

将application.MainClass更改为

但是听了上面的Oracle之后,我得到了一个包含外部jar的JavaFX。我尝试了build.xml示例,但没有成功

然而,我确实找到了一种使用Eclipse的替代方法

  • 在Eclipse中打开JavaFX项目
  • 右键单击项目并将其导出为可运行的JAR文件
  • 将所需库提取到生成的JAR中
  • 使用标准JAR签名器对可运行JAR进行签名
  • 为此,您需要首先创建密钥库:

    keytool -genkey -keyalg RSA -alias Aubrey -keystore keystore.jks -storepass YourPassword
    
    然后像这样签字:

    jarsigner -keystore c:\path\to\your\keystore.jks -storepass YourPassword c:\path\to\your\file.jar Aubrey
    
  • 最后,创建一个javafxjnlp文件,并将签名的jar和jnlp上传到服务器
  • 例如:

    <?xml version="1.0" encoding="utf-8"?>
    <jnlp spec="1.0" xmlns:jfx="http://javafx.com" codebase="http://aubreigo.info/java/" href="FX-People.jnlp">
    <information>
    <title>FX-People</title>
    <vendor>aubrey</vendor>
    <description>Google Contacts Viewer</description>
    <offline-allowed/>
    </information>
    
    <security>
    <all-permissions/>
    </security>
    
    <resources>
    <j2se version="1.6+" href="http://java.sun.com/products/autodl/j2se"/>
    <jar href="FX-People.jar" size="109545" download="eager" />
    </resources>
    
    <applet-desc  width="800" height="600" main-class="com.javafx.main.NoJavaFXFallback"  name="FX-People" >
    <param name="requiredFXVersion" value="8.0+"/>
    </applet-desc>
    <jfx:javafx-desc  width="800" height="600" main-class="fx.contacts.FXContacts"  name="FX-People" />
    <update check="always"/>
    </jnlp>
    
    
    外汇人员
    奥布里
    谷歌联系人查看器
    
    期待你的答案“遗嘱”。考虑在你的答案下面把这个变成一个评论,然后在你找出答案的时候发布你的完整答案。很抱歉,但是好消息是我有一个工作解决方案!可能已经找到了一个咨询文档的答案。
    <?xml version="1.0" encoding="utf-8"?>
    <jnlp spec="1.0" xmlns:jfx="http://javafx.com" codebase="http://aubreigo.info/java/" href="FX-People.jnlp">
    <information>
    <title>FX-People</title>
    <vendor>aubrey</vendor>
    <description>Google Contacts Viewer</description>
    <offline-allowed/>
    </information>
    
    <security>
    <all-permissions/>
    </security>
    
    <resources>
    <j2se version="1.6+" href="http://java.sun.com/products/autodl/j2se"/>
    <jar href="FX-People.jar" size="109545" download="eager" />
    </resources>
    
    <applet-desc  width="800" height="600" main-class="com.javafx.main.NoJavaFXFallback"  name="FX-People" >
    <param name="requiredFXVersion" value="8.0+"/>
    </applet-desc>
    <jfx:javafx-desc  width="800" height="600" main-class="fx.contacts.FXContacts"  name="FX-People" />
    <update check="always"/>
    </jnlp>