5.3 Doing More With Java Rich Internet Applications

«« Previous
Next »»

Applets launched by using the Java Network Launch Protocol (JNLP) have capabilities similar to those of Java Web Start applications. This lesson contains topics common to the development and deployment of applets and Java Web Start applications (together known as rich Internet applications). If you are unfamiliar with applets or Java Web Start applications, you can learn more in the following lessons of the Java Tutorials:
  • To learn more about applet development and deployment, visit the Java Applets lesson.
  • To learn more about the development and deployment of Java Web Start applications, visit the Java Web Start lesson.

System Properties


This topic lists system properties that can be accessed by rich Internet applications (RIAs) that are restricted to the security sandbox and are launched with or without the Java Network Launch Protocol (JNLP). Some system properties cannot be accessed by sandbox RIAs.

Secure System Properties Accessible by All RIAs

All RIAs can retrieve the following secure system properties:
  • java.class.version
  • java.vendor
  • java.vendor.url
  • java.version
  • os.name
  • os.arch
  • os.version
  • file.separator
  • path.separator
  • line.separator
Secure System Properties Accessible by RIAs Launched by Using JNLP

RIAs launched by using JNLP can set and retrieve the following secure properties:
  • awt.useSystemAAFontSettings
  • http.agent
  • http.keepAlive
  • java.awt.syncLWRequests
  • java.awt.Window.locationByPlatform
  • javaws.cfg.jauthenticator
  • javax.swing.defaultlf
  • sun.awt.noerasebackground
  • sun.awt.erasebackgroundonresize
  • sun.java2d.d3d
  • sun.java2d.dpiaware
  • sun.java2d.noddraw
  • sun.java2d.opengl
  • swing.boldMetal
  • swing.metalTheme
  • swing.noxp
  • swing.useSystemFontSettings
Forbidden System Properties

Sandbox RIAs cannot access the following system properties:
  • java.class.path
  • java.home
  • user.dir
  • user.home
  • user.name

JNLP API


Rich Internet applications (RIAs) can use the Java Network Launch Protocol (JNLP) API to perform extensive operations on the user's environment. When launched by using JNLP, even unsigned RIAs can perform the following operations with the user's permission:
  • They can use the FileOpenService and FileSaveService API to access the user's file system..
  • They can use the ClipboardService API to access the shared system-wide clipboard.
  • They can use the PrintService API to access printing functions.
  • They can use the PersistenceService API to access persistence storage.
  • They can use the DownloadService API to control how the RIA is downloaded and cached.
  • They can use the DownloadServiceListener API to determine progress of the RIA's download.
  • They can use the SingleInstanceService API to decide how to handle arguments when multiple instances of the RIA are launched.
  • They can use the ExtendedService API to request permission to open certain files that have not been opened before.

Cookies


Web applications are typically a series of Hypertext Transfer Protocol (HTTP) requests and responses. As HTTP is a stateless protocol, information is not automatically saved between HTTP requests. Web applications use cookies to store state information on the client. Cookies can be used to store information about the user, the user's shopping cart, and so on.

Types of Cookies

The two types of cookies follow:
  • Session cookies – Session cookies are stored in memory and are accessible as long as the user is using the web application. Session cookies are lost when the user exits the web application. Such cookies are identified by a session ID and are most commonly used to store details of a shopping cart.
  • Permanent cookies – Permanent cookies are used to store long-term information such as user preferences and user identification information. Permanent cookies are stored in persistent storage and are not lost when the user exits the application. Permanent cookies are lost when they expire.

Cookie Support in Rich Internet Applications


Rich Internet applications (applets and Java Web Start applications) support session and permanent cookies. The underlying cookie store depends on the browser and the operating system on the client.

To learn more about cookies, see the following:

  • Working With Cookies lesson in the Java Tutorial
  • API Documentation for CookieManager and related classes

Accessing Cookies


You can set and retrieve cookies in your rich Internet application (RIA). Cookies can enhance the capabilities of your RIA. For example, consider the scenario where you have applets on various web pages. An applet on a web page cannot directly access or share information with an applet on another web page. In this scenario, cookies provide an important connection between applets and help one applet pass information to another applet on a different web page. Java Web Start applications can also use cookies to store information on the client.

The Cookie Applet example has a CookieAccessor class that retrieves and sets cookies.

Retrieving Cookies

The following code snippet shows the getCookieUsingCookieHandler method of the CookieAccessor class:

public void getCookieUsingCookieHandler() {
    try {    
        // Instantiate CookieManager;
        // make sure to set CookiePolicy
        CookieManager manager = new CookieManager();
        manager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
        CookieHandler.setDefault(manager);

        // get content from URLConnection;
        // cookies are set by web site
        URL url = new URL("http://host.example.com");
        URLConnection connection = url.openConnection();
        connection.getContent();

        // get cookies from underlying
        // CookieStore
        CookieStore cookieJar =  manager.getCookieStore();
        List <HttpCookie> cookies =
            cookieJar.getCookies();
        for (HttpCookie cookie: cookies) {
          System.out.println("CookieHandler retrieved cookie: " + cookie);
        }
    } catch(Exception e) {
        System.out.println("Unable to get cookie using CookieHandler");
        e.printStackTrace();
    }
}

The CookieManager class is the main entry point for cookie management. Create an instance of the CookieManager class and set its CookiePolicy. Set this instance of the CookieManager as the default CookieHandler.

Open a URLConnection to the website of your choice.

Next, retrieve cookies from the underlying CookieStore by using the getCookies method.

Setting Cookies

The following code snippet shows the setCookieUsingCookieHandler method of the CookieAccessor class:

public void setCookieUsingCookieHandler() {
    try {
        // instantiate CookieManager
        CookieManager manager = new CookieManager();
        CookieHandler.setDefault(manager);
        CookieStore cookieJar =  manager.getCookieStore();

        // create cookie
        HttpCookie cookie = new HttpCookie("UserName", "John Doe");

        // add cookie to CookieStore for a
        // particular URL
        URL url = new URL("http://host.example.com");
        cookieJar.add(url.toURI(), cookie);
        System.out.println("Added cookie using cookie handler");
    } catch(Exception e) {
        System.out.println("Unable to set cookie using CookieHandler");
        e.printStackTrace();
    }
}

As shown in Retrieving Cookies, the CookieManager class is the main entry point for cookie management. Create an instance of the CookieManager class and set the instance as the default CookieHandler.

Create the desired HttpCookie with the necessary information. In our example, we have created a new HttpCookie that sets the UserName as John Doe.

Next, add the cookie to the underlying cookie store.

Running the Cookie Applet Example

To access cookies, you must sign your RIA JAR file and request permission to run outside of the security sandbox. See the documentation for the jarsigner tool to learn how to sign JAR files.

Customizing the Loading Experience


Rich Internet applications (RIAs) may take a few seconds to load depending on factors such as network speed and resources required by the RIA. Customize the RIA loading experience by providing a splash screen or a customized loading progress indicator to engage the end user during the loading process and to communicate measurable progress information.

While the overall mechanisms to customize the loading experience for applets and Java Web Start applications are similar, there are subtle differences in syntax and implementation. See the following topics for step-by-step instructions and conceptual information about customizing the RIA loading experience:
  • Customizing the Loading Screen
  • Displaying a Customized Loading Progress Indicator for an applet
  • Displaying a Customized Loading Progress Indicator for a Java Web Start application
  • Customizing the Loading Experience (conceptual information, client Java Runtime Environment (JRE) software capabilities)

Security in Rich Internet Applications


The security model behind rich Internet applications (RIAs) works to protect the user from malicious Internet applications. This topic discusses security aspects that are common to applets and Java Web Start applications. See the following topics for more information:
  • What Applets Can and Cannot Do
  • Java Web Start and Security
RIAs can be restricted to the Java security sandbox or request permission to access resources outside the sandbox. The first time an RIA is launched, the user is prompted for permission to run. The dialog shown provides information about the signer's certificate and indicates if the RIA requests permission to run outside the sandbox. The user can then make an informed decision about running the application.

Apply the following guidelines to help secure your RIAs.
  • Sign the JAR file of the RIA with a certificate from a recognized certificate authority. For more information, see the Signing and Verifying JAR Files topic.
  • If the RIA requires access outside of the security sandbox, specify the all-permissions element in the JNLP file for the RIA. Otherwise, let the RIA default to running in the security sandbox. The following code snippet shows the all-permissions element in the RIA's JNLP file.
<security>
   <all-permissions/>
</security>
  • A JNLP file can only include JAR files signed by the same certificate. If you have JAR files that are signed using different certificates, specify them in separate JNLP files. In the RIA's main JNLP file, specify the component-desc element to include the other JNLP files as component extensions.
  • The security model for RIAs does not allow JavaScript code from a web page to invoke security-sensitive code in a signed JAR file unless you explicitly enable this. In the signed JAR file, wrap the section of code that you want JavaScript code to be able to invoke in a AccessController.doPrivileged block. This allows the JavaScript code to run with elevated permissions when executing the code in the doPrivileged code block.
  • Avoid mixing privileged and sandbox components in a RIA, if possible, as they can raise security warnings about mixed code. 
  • Include the Permissions and Codebase attributes in the JAR file manifest to ensure that your RIA requests only the permissions you specify, and that the RIA is accessed from the correct location.
  • JAR file manifest attributes enable you to restrict access to your RIA and help to ensure that your code is not tampered with.

Guidelines for Securing Rich Internet Applications


The following guidelines provide steps you can take to reduce the vulnerability of the Rich Internet Applications (RIAs) that you provide to users.
  • Follow Secure Coding Guidelines
  • Test with the Latest Version of the JRE
  • Include Manifest Attributes
  • Use a Signed JNLP File
  • Sign and Time Stamp JAR Files
  • Use the HTTPS Protocol
  • Avoid Local RIAs
1. Follow Secure Coding Guidelines

Follow the recommendations in the Secure Coding Guidelines for the Java Programming Language. Section 4, "Accessibility and Extensibility" describes how to limit accessibility to classes and packages, which reduces the vulnerability of your code.

JavaScript code is considered insecure and is restricted to the security sandbox by default. Minimize interactions between your RIA and JavaScript code. Use the AccessController.doPrivileged block with care because it allows access from any HTML page or JavaScript code.

2. Test with the Latest Version of the JRE

Make sure that your RIA runs on the latest, secure version of the JRE. The Java platform supports the ability for RIAs to specify the Java version that is needed to run the RIA, however, requiring users to maintain more than one version of the JRE, especially older, insecure versions, is a security risk for the user.

One of the benefits of RIAs is that updated versions of the RIA are automatically download to a user's system. Test your RIA against each update of the JRE and make sure that it works. If changes are needed, update your RIA on the server so that users can install the latest JRE and still run the RIA.

3. Include Manifest Attributes

Add attributes to the JAR file manifest that describe the properties of the RIA. Values in the JNLP file or the applet tag are compared to values in the manifest to verify that the correct code is run.

Request sandbox permissions when your RIA does not require access beyond the security sandbox. The Java sandbox provides additional protections for users, and users might not run a privileged application if they do not understand why it requests unrestricted access to their system.

Manifest attributes can also be used to identify the locations from which your RIA can be accessed. This includes locations from which JavaScript code can call your RIA, and locations of JNLP files or applet tags that can start your RIA. .

4. Use a Signed JNLP File

If your RIA needs to access non-secure system properties or JVM arguments, use a signed JNLP. If some variation between the external and internal JNLP files is required, use JNLP templates.

To access non-secure system properties or JVM arguments, include the property or argument in the JNLP file as described in Setting Trusted Arguments and Secure Properties.

5. Sign and Time Stamp JAR Files

Obtain a code signing certificate from a trusted certificate authority and use it to sign the JAR files for your RIA. Deploy to users only RIAs that are signed with a valid certificate.

When you sign your JAR file, also time stamp the signature. Time stamping verifies that the certificate was valid at the time that the JAR was signed, so the RIA is not automatically blocked when the certificate expires.

Self-signed and unsigned RIAs are considered unsafe and are not allowed to run unless an exception site list or deployment rule set is set up to allow specific applications. However, self-signing can be useful for testing purposes. To test using your self-signed RIA, you can import the self-signed certificate into the trusted keystore.

6. Use the HTTPS Protocol

Use the HTTPS protocol for the web server from which users get your RIA. The HTTPS protocol is encrypted and validated by the server, making it more difficult for anyone to tamper with your RIA.

7. Avoid Local RIAs

Local RIAs are not intended for use in production. To ensure that users run the code that you intend for them to run, host your RIA on an application server.

For testing, the use of a web server is recommended. Another option is to add your application to the exception site list, which is managed in the Security tab of the Java Control Panel.

Answers to Questions and Exercises: Doing More With Rich Internet Applications


Questions

1. Question: True or False: Rich Internet applications (RIAs) can set secure properties by prefixing the property name with "jnlp.".
Answer: True: Rich Internet applications (RIAs) can set secure properties by prefixing the property name with "jnlp." or "javaws.".

2. Question: True or False: Only signed RIAs can use JNLP API to access files on the client.
Answer: False: Unsigned RIAs can also use JNLP API to access files on the client.

Exercises

1. Exercise: To the following JNLP file, add a secure property called jnlp.foo and set its value to true.
<?xml version="1.0" encoding="UTF-8"?>
<jnlp spec="1.0+" codebase="" href="">
    <information>
        <title>Dynamic Tree Demo</title>
        <vendor>Dynamic Team</vendor>

    </information>
    <resources>
        <!-- Application Resources -->
        <j2se version="1.6+"
              href="http://java.sun.com/products/autodl/j2se" />
        <jar href="DynamicTreeDemo.jar" main="true" />
    </resources>
    <applet-desc
         name="Dynamic Tree Demo Applet"
         main-class="components.DynamicTreeApplet"
         width="300"
         height="300">
     </applet-desc>
     <update check="background"/>
</jnlp>                        
Answer:

<?xml version="1.0" encoding="UTF-8"?>
<jnlp spec="1.0+" codebase="" href="">
    <information>
        <title>Dynamic Tree Demo</title>
        <vendor>Dynamic Team</vendor>

    </information>
    <resources>
        <!-- Application Resources -->
        <j2se version="1.6+"
              href="http://java.sun.com/products/autodl/j2se" />
        <jar href="DynamicTreeDemo.jar" main="true" />
        <property name="jnlp.foo" value="true"/>
    </resources>
    <applet-desc
         name="Dynamic Tree Demo Applet"
         main-class="components.DynamicTreeApplet"
         width="300"
         height="300">
     </applet-desc>
     <update check="background"/>
</jnlp> 

«« Previous
Next »»