0

我正在尝试创建一个将在浏览器中运行、从 URL 下载图像并将其显示给用户的 java jar Applet。我的实现是:

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

但这给了我一个安全例外:

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

解决方案:

我已经实现了 Knife-Action-Jesus 的建议,它可以在网络浏览器中运行(但不使用小程序查看器)。

只有小程序查看器我仍然遇到:

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

在浏览器中加载网页时,有一个信任/拒绝对话框,如果我单击信任,则会显示图像。

这些是我正在采取的步骤:

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.

jarsigner -verify 的输出是:

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.

以下是完整的 java 源代码(为了强调这个概念,我删除了所有额外的异常处理/空检查):

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

}
4

4 回答 4

2

您遇到异常是因为默认情况下小程序会加载到沙箱安全性中,沙箱仅允许您与服务小程序的域建立 url 连接。这意味着除非您的小程序由 google 托管,否则您无法创建与 google 的 url 连接。

您需要执行以下操作才能正确连接到远程 URL。

至少创建一个自签名证书,理想情况下,您有一个通过威瑞信或您选择的其他证书颁发机构 (CA) 链接回来的经过验证的证书。证书说明

使用 jarsigner 为你的 jar 签名。签署说明

现在您可以将代码包装在特权块中,如下所示

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

我导入了您的小程序代码,我切换了其中的一些,将 img 实例从特权块中拉出并让块返回一个 url。当我将它加载到网络浏览器中时,这有效。

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

  }
}
于 2010-01-06T16:01:17.963 回答
0

您似乎正在运行一个小程序而不是一个普通的应用程序。不允许小程序检索已加载域之外的任何资源。这个想法是为了防止“坏”应用程序调用类似的东西

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

或将其他类型的数据传输到未知目的地。

如果您确实需要检索外部数据,您必须签署您的小程序。

于 2010-01-06T08:46:31.463 回答
-1
  1. 在 jar 的同一文件夹中创建一个名为“policy.all”的文件
  2. 在其中复制/粘贴以下文本:

    授予 { 权限 java.security.AllPermission;};

  3. 像这样启动应用程序:

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

于 2010-01-06T07:22:28.833 回答
-1

听起来您不是在尝试创建一个jar将从命令行运行的文件,而是一个将在浏览器中执行的小程序。如果这是真的,那么你就很不走运了,因为小程序只被允许访问它们从中加载的服务器。如果你真的想从一个小程序访问其他服务器,你必须签署你的小程序;谷歌可以帮助您找到更多信息。

于 2010-01-06T07:24:11.207 回答