Question

I am trying to create a java jar Applet that will run in a browser, download an image from a URL, and display it to the user. My implementation is:

try {
     String imageURL = "http://www.google.com/intl/en_ALL/images/logo.gif";
     URL url = new URL(imageURL);
     img = ImageIO.read(url);
   } catch (IOException e) {
     System.out.println(e);
   }  

But it gives me a security exception:

java.security.AccessControlException: access denied (java.net.SocketPermission www.google.com:80 connect,resolve)

Solution:

I have implemented Knife-Action-Jesus's suggestion, and it works in a web browser (but not using the applet viewer).

Only with the applet viewer I still encounter:

java.security.AccessControlException: access denied (java.net.SocketPermission www.google.com:80 connect,resolve)

When loading the web page in a browser, there is a Trust/Deny dialogue box, if I click Trust, then the image shows up.

These are the steps that I'm taking:

ant makejar
jarsigner -keystore keystore-name -storepass password -keypass password web/LoadImageApp.jar alias-name
jarsigner -verify -verbose web/LoadImageApp.jar 
appletviewer web/index.html  ## as mentioned above, this gives a security exception. instead, load the webpage in a browser.

The output from jarsigner -verify is:

Warning: The signer certificate will expire within six months.

         332 Thu Jan 07 20:03:38 EST 2010 META-INF/MANIFEST.MF
         391 Thu Jan 07 20:03:38 EST 2010 META-INF/ALIAS-NA.SF
        1108 Thu Jan 07 20:03:38 EST 2010 META-INF/ALIAS-NA.DSA
sm       837 Thu Jan 07 20:03:38 EST 2010 LoadImageApp$1.class
sm       925 Thu Jan 07 20:03:38 EST 2010 LoadImageApp.class
sm        54 Wed Jan 06 01:28:02 EST 2010 client.policy

  s = signature was verified 
  m = entry is listed in manifest
  k = at least one certificate was found in keystore
  i = at least one certificate was found in identity scope

jar verified.

The following is the complete java source code (to emphasize the concept, I removed all that extra exception handling/null checking) :

import java.awt.*;
import java.awt.image.*;
import javax.imageio.*;
import javax.swing.*;
import java.net.*;
import java.security.*;

public class LoadImageApp extends JApplet
{
  private BufferedImage img;
  private final String imageURL = "http://www.google.com/intl/en_ALL/images/logo.gif";

  public void init()
  {
    loadImage();
  }

  public void paint(Graphics g)
  {
    if (null != img) { g.drawImage(img, 0, 0, null); }
  }

  public void loadImage()
  {
    AccessController.doPrivileged(new PrivilegedAction()
    {
      public Object run()
      {
        try
        {
          URL url = new URL(imageURL);
          if (null == url)
          {
            throw new MalformedURLException();
          }
          img = ImageIO.read(url);
        }
        catch (Exception e) { e.printStackTrace(); }
        return null;
      }
    });
  }

}
Was it helpful?

Solution

Your running into the exception because by default applets load into sandbox security, Sandbox only allows you to make url connections to the domain serving the applet. Meaning you cannot create a url connection to google unless you applet is hosted by google.

You need to do the following in order to properly connect to a remote url.

Create a self signed certificate at least, Ideally you have a verified certificate linking back through verisign or some other certificate authority (CA) of your choosing. Certificate Instructions

Sign your jar using jarsigner. Signing Instructions

Now you can wrap your code in a privileged block as follows

try 
{
    final String imageURL = "http://www.google.com/intl/en_ALL/images/logo.gif";
    URL url = (URL) AccessController.doPrivileged(new PrivilegedAction() 
    {

        public Object run() 
        {
            try
            {
                return new URL(imageURL);
            }
            catch (MalformedURLException e)
            {
                e.printStackTrace();
                return null;
            }

        }  
    });  

    if(url == null)
    {
         // Something is wrong notify the user
    }
    else
    {
         // We know the url is good so continue on
          img = ImageIO.read(url);
    }

} 
catch (IOException e) 
{
    System.out.println(e);
}  

I imported your applet code, I switched some of it around, Pulling the img instantiation out of the privileged block & having the block return a url. This works when I load it into a webbrowser.

import java.applet.Applet;
import java.awt.*;
import java.awt.image.*;
import javax.imageio.*;
import javax.swing.*;

import java.io.IOException;
import java.net.*;
import java.security.AccessController;
import java.security.PrivilegedAction;

public class LoadImageApp extends Applet
{
  private BufferedImage img;
  private final String imageURL = "http://www.google.com/intl/en_ALL/images/logo.gif";

  public void init()
  {
    loadImage();
  }

  public void paint(Graphics g)
  {
    if (null != img) { g.drawImage(img, 0, 0, null); }
  }

  public void loadImage()
  {
    URL url = (URL) AccessController.doPrivileged(new PrivilegedAction()
    {
      public Object run()
      {
        try
        {
            return new URL(imageURL);
        }
        catch (Exception e) { e.printStackTrace(); }
        return null;
      }
    });

    try {
        img = ImageIO.read(url);
    } catch (IOException e) {
    e.printStackTrace();
    }

  }
}

OTHER TIPS

It seems you're running an applet instead of a normal application. An applet is not allowed to retrieve any resources outside the domain it has been loaded from. The idea is to prevent "bad" applications from calling something like

String targetURL = "http://www.foo.bar/spoof?source" + System.getProperty("...);

or transfering other kinds of data to an unknown destination.

If you really need to retrieve external data you have to sign your applet.

  1. Create a file call "policy.all" in the same folder of your jar
  2. copy/paste the following text in it :

    grant { permission java.security.AllPermission;};

  3. Start application like this :

    java -jar yourjar.jar -Djava.security.policy=policy.all

Sounds like you’re not trying to create a jar file which will be run from the command line but an applet which will be executed in the browser. If that is true, you’re pretty much out of luck because applets are only allowed to access the server they have been loaded from. If you really want to access other servers from an applet, you have to sign your applet; Google can help you find more information.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top