拒绝访问(java.net.SocketPermission 127.0.0.1:8080 连接,解析)

12

我在一个简单的HTML页面上插入了一个Java Applet,该页面位于http://localhost:8080/index.html:

<applet id="applet" code="SomeCode.class" archive="lib.jar" Width="1" Height="1"></applet>

Java Applet有一个类似下面代码的方法:

public void PostStuffToServer() {
  String server = "http://localhost:8080/PostHandler.ashx";
  URL u = new URL(server);
  URLConnection con = u.openConnection();
  con.setDoOutput(true);
  con.getOutputStream().write(stream.toByteArray());
  con.connect();
}

当我像这样从JavaScript执行小程序代码:

obj = document.getElementById('applet');
obj.getClipboardImageURL();

我遇到了以下错误:

access denied (java.net.SocketPermission 127.0.0.1:8080 connect,resolve)

看起来Java代码将域名 localhost 解析为其等效的IP地址,因此会引发跨域安全限制。当我从http://127.0.0.1:8080/index.html执行相同的代码时,它可以正常运行。lib.jar文件已签名。

有没有什么方法可以避免这种情况?


尝试对lib.jar和你使用的所有其他外部jar文件进行签名。 - Enrique
1
不要使用“localhost”!我也会解释为什么:根本没有保证“localhost”就是127.0.0.1。另外在小程序中始终使用getCodeBase(),不要使用硬编码位置。 - bestsss
10个回答

14

安装Java 6 Update 22后,我遇到了同样的问题。我的小程序在几年的在线运行中从未出现错误。当我降级到版本6 Update 21时,一切都正常工作。我的小程序没有签名。

解决方案: 我花了一段时间才找到问题的原因。实际上,在我这种情况下有几个因素导致了安全性错误。跨域策略文件crossdomain.xml解决了这个问题。Java小程序试图下载crossdomain文件,但失败了,而且甚至没有在Java控制台(调试级别为5)中显示任何错误信息。Java尝试从我的域名IP地址(http://ip-address/crossdomain.xml)下载文件,而不是从我的网站根目录(http://domain-name/crossdomain.xml)下载。我想这对安全方面更好?然后我不得不配置Web服务器在IP地址上公开crossdomain文件。在我的情况下,出于安全考虑,我删除了ISS中的默认网站,并创建了一个新的网站。然后我发现Java小程序与我用于Flash的crossdomain文件不兼容:

<?xml version="1.0"?>
<cross-domain-policy>
   <site-control permitted-cross-domain-policies="master-only"/>
   <allow-http-request-headers-from domain="*" headers="*"/>
   <allow-access-from domain="*" />
</cross-domain-policy>

为了让小程序正常工作,我不得不从XML文件中删除site-control和allow-http-request-headers-from节点。


10

我想可能已经晚了,但是无论如何......你们无法相信解决这个问题有多容易。

问题在于,从JavaScript调用的Java小程序代码只具有JavaScript代码和您的小程序代码的交集所拥有的权限 - 而某种程度上,JavaScript的权限被视为较少,这导致了此异常。

这是我所做的:假设您有一个函数innocentFunc(),该函数会抛出java.net.SocketPermission异常,因此您的代码类似于:

String s = innocentFunc();

现在你可以将它更改为类似以下的内容:

String s = AccessController.doPrivileged(
      new PrivilegedAction<String>() {
          public String run() {
              return innocentFunc();
          }
        }
     );

这个 AccessController 调用基本上告诉 Java 虚拟机,它运行的代码不应该遵循调用链中的权限,而只应该遵循其自己调用者的权限。

当然,在确保即使被恶意代码调用这个 innocentFunc 调用也不会造成任何破坏之后,才应该做类似这样的事情。


1
我只是想回复一个类似的解决方案。看到你的,我取而代之地修改了它,并添加了一些解释。 - Paŭlo Ebermann

2
我在更新22中遇到了同样的问题,而在更新21中没有出现。
我使用TinyPlayer applet,并通过JavaScript对其进行控制。
我从与加载applet相同域名(mydomain.example.com,IP 1.2.3.4)的位置加载音频文件 - 所有内容都使用相对URL引用。
当我尝试播放音频时,无法播放并且会出现以下错误: access denied (java.net.SocketPermission 1.2.3.4:80 connect,resolve)
查看访问日志,发现在此之前请求crossdomain.xml。但是问题在于Java并没有从 mydomain.example.com/crossdomain.xml 请求crossdomain.xml,而是从 1.2.3.4/crossdomain.xml 请求crossdomain.xml。
解决方法似乎是设置一个虚拟主机来响应IP地址1.2.3.4,并提供crossdomain.xml,以便Java可以在(错误的)位置找到它正在寻找的crossdomain.xml。
我刚刚测试了一下内容:
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
  <allow-access-from domain="*" />
</cross-domain-policy>

...但可能可以更加限制。

有了这个,音频就可以正常播放了。


2

补充一下,这里有些内容恰好符合我一直遇到的问题 - 它明确提到了使用JavaScript控制applet。

http://www.oracle.com/technetwork/java/javase/6u22releasenotes-176121.html

CVE-2010-3560的修复可能会导致运行在新Java插件中的某些Java applet在嵌入了调用Java以执行需要网络安全权限的操作的JavaScript的网页中停止工作。如果解析原始Web页面URL主机名的名称服务未返回匹配名称作为反向地址查找的结果,则这些applet可能会在某些情况下因网络安全异常而失败。

他们的建议是在DNS中添加一个特殊的仅供Java使用的疯狂A记录,例如:

10.11.12.13    foo.bar.com.auth.13.12.11.10.in-addr.arpa

1

据我所知,JavaScript的同源策略防止访问相同主机/不同端口。插件的LiveConnect仅强制执行本地主机的此策略。


我不确定这是什么意思?这是否意味着,如果我将此代码部署到生产环境(例如www.productiondomain.com),该代码将正常工作而不会解析到IP地址? - PropellerHead
它应该可以。 (当然,除非该主机名解析为localhost。) - Tom Hawtin - tackline
你可以从小程序连接到同一主机的任何端口。 - bestsss

1

1

我曾经遇到过类似的问题,只有在使用“localhost”作为包含小程序页面URL的一部分时才会出现。当我使用实际主机名或IP地址作为URL的一部分时,问题就不会发生。我不确定这是否是Java插件的缺陷...

例如,当我使用像http://localhost:9080/app_id/appletPage这样的URL时,问题就会出现,但是当我使用实际的IP或主机名时,问题就不会出现。


0

0

您应该检查您的虚拟目录权限。


0

来自@Kristian的更新解决了我的问题。

我在Web应用程序中的一个小程序中遇到了access denied (java.net.SocketPermission <server_ip>:<server port> connect,resolve)的错误。

我们的DNS发生了变化,导致应用程序服务器的负载均衡器IP地址无法解析为带有域名的名称。因此,从小程序返回服务器的疑似“跨域连接”被阻止了。 我添加了crossdomain.xml:

<?xml version="1.0"?> <cross-domain-policy> <allow-access-from domain="*" /> </cross-domain-policy>

将其添加到<tomcat-home>/webapps目录下,并检查它是否可以通过http://<server name>:<server port>/crossdomain.xml访问。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接