Due to tighter security restrictions in 7u51
, due in January, I'm trying to sign my JNLP file.
Our application requires certain custom system properties to be set, and the values of some of those properties are different depending on where the applet is being deployed. I would like to avoid having to re-sign the JAR containing the JNLP template for each deployment.
The naive approach of putting <property name="my-prop" value="*"/>
in the JNLP template does not work.
Even with <property name="my-prop" value="fixed-value"/>
in the template, I sometimes get a dialog saying "This application is going to perform an insecure operation. Do you want to continue?":
What's the right way to pass system properties in to a signed Java RIA?
On both counts, your application will need to add some trivial code to be executed at start-up, in order to work around these two issues.
The JNLP specification says:
It is expected that a JNLP Client will blacklist (or restrict) certain jnlp elements and argument values such as "java-vm-args" or property "name" and "value" to maintain security. The exact list is up to the individual JNLP Client implementations.
In fact, the Oracle implementation (at least in 7u45) does blacklist the value
attribute of the <property/>
element -- it cannot be wildcarded. I've been unable to locate any reasoning behind this decision, but there it is.
The webstart work-around allows arbitrary property names as well as values; the applet work-around requires that the names of the properties be known at code-signing time.
In your JNLP file, include a number of wildcard arguments:
<application-desc main-class="com.example.YourMainClass">
<argument>*</argument>
<argument>*</argument>
</application-desc>
In your application's main
method, parse these arguments and copy them in to system properties using System.setProperty()
, skipping over arguments that still have the literal value "*"
. I recommend simply splitting each argument on the first occurrence of "="
. (If your application already takes regular arguments as well, you'll have to get a bit more creative.)
In your JNLP file, include parameters defining the system properties that need to be set:
<applet-desc main-class="com.example.YourMainClassApplet">
<param name="SYS_PROPERTY_PARAMETERS" value="prop1,prop2"/>
<param name="prop1" value="*"/>
<param name="prop2" value="*"/>
</applet-desc>
In your Applet.init()
method, get the value of the SYS_PROPERTY_PARAMETERS
parameter, and iterate over it to get the value of each parameter. If it is not the literal "*"
, copy it to a system property using System.setProperty()
.
This is a bug in the Oracle plugin that is triggered by the use of LiveConnect (Java <-> JavaScript interaction).
Prefix all system properties set via <property/>
elements in the JNLP with "jnlp."
:
<property name="jnlp.my-prop" value="fixed-value"/>
Then in your application's main()
or Applet.init()
method, iterate over a copy of System.getProperties()
and, if the property name starts with "jnlp."
, copy its value into a property of the same name with that prefix stripped off. (Iterating over the copy is necessary to avoid a ConcurrentModificationException
.)
Finally, if your process of filling in the values for the properties could cause attributes of other elements in the JNLP document to be reordered, this may cause the JNLP template validation to fail. (Parsing the JNLP with a DOM parser, filling in the wildcards, and streaming it back out using StreamResult
is one way this could happen.) For example, I had these two multi-attribute elements, and the order of the elements had to match:
<jnlp codebase="*" spec="1.0+">
<j2se java-vm-args="-Xms256M -Xmx512M -XX:MaxPermSize=256m" version="1.6+"/>