views:

259

answers:

4

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;
      }
    });
  }

}
A: 
  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

Julien Grenier
You should not use the policy file beyond your own testing, Granting all permission is dangerous now any visit to a malicious site you just gave them permission to do anything on your machine they choose. Signing even with a self signed certificate is easy.
Knife-Action-Jesus
A: 

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.

Bombe
it won't help him if he's trying to do an applet...
Valentin Rocher
Of course it will. If he’s really trying to do that in an applet he now knows that he has to sign his applet to mark it work.
Bombe
I am indeed trying to make an applet which will be executed in the browser.
dsg
Then, as you know by now, signing the applet is your only option when you *really* want to access other servers than the one your applet is being loaded from.
Bombe
A: 

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.

perdian
Actually `AppletContext.showDocument` is not restricted to the same-origin policy, like JavaScript (may be implemented by calling the JavaScript equivalent). There is also a similar method in `javax.jnlp`.
Tom Hawtin - tackline
+1  A: 

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();
    }

  }
}
Knife-Action-Jesus
Your certificate instruction link was TLTR, so I followed the shorter: http://www.cs.princeton.edu/introcs/85application/jar/sign.htmlAfter first modifing the code, then signing the jar, then trying to execute it via appletviewer, I still encounter the same exception.
dsg
There could be another spot in the code you need to wrap in a privileged block. Once you sign your jar make sure your verifying it. With the jarsigner tool. If its being verified then the only other issue would be something your doing in the code that also needs permission. Things like copying to clipboardWriting a file ont he client machineNeed permission, If your not sure how to wrap the other code blocks post it and I can try and help some more.
Knife-Action-Jesus
Thanks for your commitment, KAJ! I have included my source code above.
dsg
Try my code that I added I was able to run a signed jar without a prob and have the google logo display without any problems. Might still be running into this because your using applet viewer and not a web page. I can include the <OBJECT> code I used on my simple page if you want.
Knife-Action-Jesus