如何签署 JavaFX 应用程序并将其部署到单个 .JAR 中? [英] How can I sign and deploy a JavaFX application into a single .JAR?

查看:25
本文介绍了如何签署 JavaFX 应用程序并将其部署到单个 .JAR 中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我仍在学习 JavaFX 的来龙去脉.一个主要区别是,在 dist 文件夹中(除了库之外),除了 .jar 文件之外,我还发现了一个 HTML 文件和一个 JNLP 文件,这两个文件对我来说都没有任何用处(这将是一个桌面应用程序).

I'm still learning the ins and outs of JavaFX. One major difference is that in the dist folder (in addition to the library) I find besides the .jar file, an HTML file and a JNLP file, neither nor of which is any use to me (this will be a desktop application).

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

I found the following (Properties omitted because of sensitive/irrelevant information):

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

<jar destfile="${store.dir}/temp_final.jar" filesetmanifest="skip">
    <zipgroupfileset dir="dist" includes="*.jar"/>
    <zipgroupfileset dir="dist/lib" includes="*.jar"/>

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

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

    <delete     dir = "${build.output.dir}"/>
    <mkdir      dir = "${build.output.dir}"/>

    <signjar
                jar = "${store.jar}"
          signedjar = "${build.output.dir}/${FileName}"
              alias = "${comodo.key.alias}"
          storepass = "${comodo.key.storepass}"
           keystore = "${comodo.key.store}"
          storetype = "PKCS12"
            keypass = "${comodo.key.pass}"
             tsaurl = "${timestamp.url}"/> 

这旨在将可执行"主 JAR 和所有依赖库构建到一个可以从任何位置运行的单个 .JAR 中,然后获取并签署该 JAR,并将其移动到已签名"目录中.

This was intended to build both the "executable" MAIN JAR and all dependent libraries into a single .JAR that could be run from any location, and then take and sign that JAR and move it into a "signed" directory.

这适用于任何 JAR 库或 Swing GUI 应用程序 JAR,但是当我用 JavaFX 应用程序尝试同样的事情时,它就崩溃了:

This works fine for any JAR library or Swing GUI application JAR, but when I tried the same thing with a JavaFX application it borked:

Error: Could not find or load main class com.javafx.main.Main

发现它不起作用我并不完全惊讶,但这有点问题.我做了一些关于可能部署自包含"应用程序的研究,但这不适合我们的需求.我的雇主花费了一些费用获得了 Comodo 证书,我很快就撞到了一堵墙,里面似乎是因为 Apple 的恶作剧(除非我在这个假设上有误),你必须以 100 美元的低成本加入他们的开发者俱乐部年(未发生).我并没有专门为苹果平台做开发.我做Java开发.无论如何,如果我是对的,那对我们来说是行不通的,因此 Windows、Linux 和 Mac 的独立部署已经过时了(如果我是对的,同样如此).

I'm not entirely surprised to find it NOT work, but it is a bit of a problem. I did some research on possibly deploying a "self-contained" application but that will not suit our needs. My employer procured at some expense a Comodo certificate, and I quickly ran into a wall in which it appears that because of Apple shenanigans (unless I am mistaken in this presumption) you have to join their developer club for the low low cost of $100 a year (not happening). I don't really do development for the apple platform SPECIFICALLY. I do Java development. Anyway, if I am correct that will not work for us so a self-contained deployment for Windows, Linux and Mac is out (again, if I am correct).

我希望这很简单.

那么如何将我创建的用于将包含所有依赖 LIB 的 JAR 编译为代码签名的 JAR 的 ANT 脚本应用于 JavaFX 应用程序?

So how do I apply the ANT script I created for compiling a JAR containing all dependent LIBs into a code-signed JAR to a JavaFX application?

编辑 1:好的,所以肯定说得太早了.不是很接近答案.我试图让弗兰肯斯坦知道我对编译和签署常规 JAR 文件的了解,以便包含所有库,并且该标志成功地成为我能够从 手册.我所拥有的是大杂烩和失败.我得到一个 .JAR 文件,其中包含除主 .JAR 文件之外的所有内容.无论如何,这是 ANT 脚本代码:

EDIT 1: Okay so definitely spoke too soon. Not very close to an answer. I've tried to frankenstein what I know about compiling and signing regular JAR files so that all libs are included and that the sign is successful into what I've been able to pick out of the manual. What I have is a hodgepodge and a failure. I get a .JAR file with everything in it except for the main .JAR file. Anyway this is the ANT script code:

属性:

<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"/>

其他一切:

<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}"/>

这就是我必须展示的东西.如果有人能从中收集到一些可能让我走上正轨的东西(如果我什至接近,我觉得我不喜欢),那就太棒了.

And that's what I have to show for my time. If anyone can glean something from this that may put me on the right track (if I am even close, which I don't feel like I am), that would be super awesome.

推荐答案

在将我的头骨和其中的内容砸成一团难以辨认的连贯思想后,我设法编写了一个脚本来完成我设定的任务去完成.其中大部分内容来自其他人的贡献以及查阅 文档.另一个主要贡献是这里(该线程上的最后一条评论,它链接到另一个 SO 答案,但该 SO 答案对我没有太大帮助).感谢我能够从中提取解决方案部分的所有内容.我希望这对需要/想要完成此任务的其他人有所帮助.

After bashing my skull and the contents therein into a slurry of something hardly recognizable as coherent thought I have managed to compose a script that accomplishes the task I have set out to accomplish. Most of this is taken from other peoples contributions and from consulting the docs. The other major contribution is found here (The last comment on the thread, it links to another SO answer, but that SO answer wasn't much help to me). Thanks go to everything from which I was able to extract the parts of the solution. I hope this is helpful for everyone else who needs/wants to accomplish this task.

无论如何:首先:属性:

Anyway: First things first: Properties:

<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. -->

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

You can change the property names to something more meaningful to you if you want but make sure that they are consistent throughout the script.

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

Next, we want to clean out the last build:

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

然后我们要为新的干净构建重新创建目录...

Then we want to re-create the directories for a new clean build...

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

这部分对于获得正常运行的 JavaFX JAR 文件至关重要:

This part is critical to get a functioning JavaFX JAR file:

<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 应用程序,这可能没有必要.我不知道我没有测试了一下.

This will store all parts correctly into their locations in the JAR (including any CSS and JFXML file you may have. If you aren't creating a JFXML application this may not be necessary. I don't know I haven't tested it out.

然后我们要对 JavaFX JAR 进行签名:

Then we want to sign the JavaFX JAR:

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

之后还有另外 2 个目标负责处理 zip 的来源,然后设置该 zip,还有一个目标用于唱最后一个 jar:

After that there are 2 more targets that handle sourcing a zip and then setting up that zip, and one final for singing the last jar:

<target name = "build" depends = "JFXSign">
    <jar destfile = "${store.dir}/temp_final.jar"
  filesetmanifest = "skip">
        <zipgroupfileset dir = "${JFX.build.dir}"
                     includes = "*.jar"/>
        <zipgroupfileset dir = "${JFX.lib.dir}"
                    includes = "*.jar"/>
        <manifest>
            <attribute name = "Main-Class"
                      value = "${JFXMainClass}"/>
        </manifest>
    </jar>
</target>

<target name = "store" depends = "build">
    <zip destfile = "${store.dir}/${JFXProject.name}.jar">
        <zipfileset src = "${store.dir}/temp_final.jar"
               excludes = "META-INF/*sf, META-INF/*.DSA, META-INF/*RSA"/>
    </zip>
    <delete file = "${store.dir}/temp_final.jar"/>
</target>

<target name = "BuildStoreAndSign" depends = "store">
    <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 -->
           tsaurl = "${timestamp.url}"
          keypass = "${comodo.key.pass}"
        storepass = "${comodo.key.storepass}"
              jar = "${store.dir}/${JFXProject.name}.jar"
          destdir = "${sign.dir}"/>
    <delete dir = "${JFX.compile.dir}"/>
    <delete dir = "${JFX.build.dir}"/>
    <delete dir = "${JFX.sign.dir}"/>
    <delete dir = "${store.dir}"/>
</target>

我真的无法解释很多,因为我远不是这方面的专家.我基本上能够从示例代码和我找到的来源中提取出我所看到的内容,并将它们放在一起得到这个:半有用的最后一点信息是 this,但请注意这不使用单罐(我用单罐试过,但没有用.它没有引入 CSS 或应用它).

I can't really explain a whole lot of this because I'm nowhere near an expert on this subject. I was able to basically extract the sense of what I was looking at from the example code and the sources I found and put it together to get this: One final bit of information that was semi-helpful was this, but please note this does NOT use one-jar (I tried it with one-jar but it didn't work. It wasn't bringing in the CSS or applying it).

还有一点警告:这对我有用.我不能保证它会适合你,但我想修改它会产生与我类似的结果(一个单独的 .JAR JavaFX 应用程序,可以在你放置的任何地方运行).

Also, a bit of warning: This worked for me. I can't guarantee it will for you, but I imagine tinkering around with it would produce results similar to mine (a single .JAR JavaFX application that runs where ever you put it).

这篇关于如何签署 JavaFX 应用程序并将其部署到单个 .JAR 中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆