English 中文(简体)
security exception when loading web image in jar
原标题:

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

}
最佳回答

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

  }
}
问题回答

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.





相关问题
Spring Properties File

Hi have this j2ee web application developed using spring framework. I have a problem with rendering mnessages in nihongo characters from the properties file. I tried converting the file to ascii using ...

Logging a global ID in multiple components

I have a system which contains multiple applications connected together using JMS and Spring Integration. Messages get sent along a chain of applications. [App A] -> [App B] -> [App C] We set a ...

Java Library Size

If I m given two Java Libraries in Jar format, 1 having no bells and whistles, and the other having lots of them that will mostly go unused.... my question is: How will the larger, mostly unused ...

How to get the Array Class for a given Class in Java?

I have a Class variable that holds a certain type and I need to get a variable that holds the corresponding array class. The best I could come up with is this: Class arrayOfFooClass = java.lang....

SQLite , Derby vs file system

I m working on a Java desktop application that reads and writes from/to different files. I think a better solution would be to replace the file system by a SQLite database. How hard is it to migrate ...

热门标签