在 jar 中加载 Web 图像时出现安全异常
Posted
技术标签:
【中文标题】在 jar 中加载 Web 图像时出现安全异常【英文标题】:security exception when loading web image in jar 【发布时间】:2010-01-06 07:03:48 【问题描述】:我正在尝试创建一个将在浏览器中运行、从 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;
);
【问题讨论】:
上下文是什么?是小程序吗? (我建议不要绕过安全策略,除非你真的知道自己在做什么。) 是的,我应该指定我正在尝试在网站上制作小程序。当前的解决方法是在 jar 中包含我可能在最坏情况下使用的所有图像,这会导致 jar 膨胀。 【参考方案1】:您遇到异常是因为默认情况下小程序会加载到沙箱安全性中,沙箱仅允许您与为小程序服务的域建立 url 连接。这意味着除非您的小程序由 google 托管,否则您无法创建与 google 的 url 连接。
您需要执行以下操作才能正确连接到远程 URL。
至少创建一个自签名证书,理想情况下,您有一个通过威瑞信或您选择的其他证书颁发机构 (CA) 链接回来的经过验证的证书。 Certificate Instructions
使用 jarsigner 为您的 jar 签名。 Signing Instructions
现在您可以将代码包装在特权块中,如下所示
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();
【讨论】:
您的证书指令链接是 TLTR,所以我遵循较短的:cs.princeton.edu/introcs/85application/jar/sign.html 在首先修改代码,然后签署 jar,然后尝试通过 appletviewer 执行它之后,我仍然遇到同样的异常。 代码中可能还有另一个地方需要包装在特权块中。一旦你签署你的 jar 确保你验证它。使用 jarsigner 工具。如果它被验证,那么唯一的另一个问题就是您在代码中所做的事情也需要许可。诸如复制到剪贴板之类的事情 在客户端计算机上编写文件需要许可,如果您不确定如何包装其他代码块,请发布它,我可以尝试提供更多帮助。 感谢您的承诺,KAJ!我已经在上面包含了我的源代码。 试试我添加的代码,我能够在没有问题的情况下运行签名的 jar,并且可以毫无问题地显示谷歌徽标。可能仍然会遇到这种情况,因为您使用的是小程序查看器而不是网页。如果需要,我可以包含我在简单页面上使用的 【参考方案2】:您似乎正在运行小程序而不是普通应用程序。不允许小程序检索已加载域之外的任何资源。这个想法是为了防止“坏”的应用程序调用类似的东西
字符串 targetURL = "http://www.foo.bar/spoof?source" + System.getProperty("...);或将其他类型的数据传输到未知目的地。
如果您确实需要检索外部数据,您必须签署您的小程序。
【讨论】:
其实AppletContext.showDocument
并不局限于同源策略,比如javascript(可以通过调用JavaScript等价物来实现)。 javax.jnlp
也有类似的方法。【参考方案3】:
-
在 jar 的同一文件夹中创建一个名为“policy.all”的文件
复制/粘贴以下文本:
授予 权限 java.security.AllPermission;;
像这样启动应用程序:
java -jar yourjar.jar -Djava.security.policy=policy.all
【讨论】:
您不应该在您自己的测试之外使用该策略文件,授予所有权限现在对恶意站点的任何访问都是危险的,您刚刚授予他们在您选择的计算机上执行任何操作的权限。即使使用自签名证书进行签名也很容易。【参考方案4】:听起来您不是在尝试创建一个将从命令行运行的jar
文件,而是一个将在浏览器中执行的小程序。如果这是真的,那么你就很不走运了,因为小程序只被允许访问它们被加载的服务器。如果你真的想从一个小程序访问其他服务器,你必须签署你的小程序; Google 可以帮助您找到更多信息。
【讨论】:
当然会。如果他真的想在一个小程序中这样做,他现在知道他必须签署他的小程序才能将其标记为有效。 我确实在尝试制作一个将在浏览器中执行的小程序。 那么,正如您现在所知道的,当您真的想要访问其他服务器而不是加载您的小程序的服务器时,签署小程序是您的唯一选择。跨度>以上是关于在 jar 中加载 Web 图像时出现安全异常的主要内容,如果未能解决你的问题,请参考以下文章
在 java 中加载 freemarker 模板时出现 FileNotFoundException
在 Android Studio 中加载 Facebook 登录按钮时出现异常