为什么在这种情况下Flash Player会抛出沙盒错误?

19

在连接到一个运行在Java(1.5)服务器上的Socket后,我收到了Flex 3沙箱错误#2048。该服务器代码完全属于我自己,即不在Apache下运行。Flash Player版本为10.0 r32。

具体顺序如下...

1 Java服务器启动,监听端口843以获得策略文件请求,并监听端口45455以处理我的其他请求。

2 由Apache提供服务的Flex客户端(即使从文件系统中运行,我仍然会得到相同的结果),在主机地址:45455上进行套接字连接。

3 Flash Player从端口843请求策略文件。这是新安全设置的标准行为,寻找主文件。无论是否指定了不同的策略文件,它都会发生。

4 我通过端口843从Java中提供以下XML:

<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<site-control permitted-cross-domain-policies="all"/>
<allow-access-from domain="*" to-ports="*" secure="false"/>
</cross-domain-policy>

5 玩家将以下内容写入调试策略日志...

OK: Root-level SWF loaded: http://localhost/bst/BasicSocketTest.swf
OK: Searching for <allow-access-from> in policy files to authorize data loading from resource at xmlsocket://192.168.2.3:45455 by requestor from http://localhost/bst/BasicSocketTest.swf
OK: Policy file accepted: xmlsocket://192.168.2.3:843
OK: Request for resource at xmlsocket://192.168.2.3:45455 by requestor from http://localhost/bst/BasicSocketTest.swf is permitted due to policy file at xmlsocket://192.168.2.3:843

我使用writeUTFBytes()flush()在端口45455上从客户端向服务器发送文本消息(这是我自己开发的消息协议,并且在每个端点都正确处理)。

REG/REGISTER;simon;Si

监听端口45455的7个Java服务器线程回复:

REG:0/REGISTER:SUCCESS;simon;Si
Flex客户端收到ProgressEvent事件并调用绑定到套接字的事件侦听器。我处理消息(将其写入屏幕上的文本框)。
Flash播放器抛出2048沙箱错误并断开套接字连接!这是在成功接收和处理消息后发生的。事实上,它大约是12秒后。没有其他的套接字操作能够执行。
我尝试了在Flex客户端中显式加载策略文件,使用Security.loadPolicyFile()进行调用,但新的播放器安全性实际上被忽略了。步骤是,直到发生套接字I / O操作,策略请求才会发送。此时,播放器总是首先访问843端口,以寻找主策略文件。如果找到一个策略文件,并且它是允许的,它就不再继续执行。
我尝试过各种替代方案来终止策略文件和策略文件内容,包括故意制造错误,只是为了看看Flash Player是否清醒。
我看不出为什么会抛出2048。我在指定的主安全端口上准确地提供了套接字策略文件,播放器本身将其记录为正确。然后,套接字成功地从服务器发送和接收一条消息,其内容对我的代码可用。
有人知道为什么会发生这种情况吗?Flash Player的错误?
P.S. 请不要告诉我使用BlazeDS或LCDS或Granite,或者其他服务器,我正在寻找解决这个问题的方法,而不是重新设计。请不要要求我改用XMLSocket - 我尝试过,并获得完全相同的结果。我认真而有意地选择了我的架构,我想要一个二进制套接字。
编辑 响应James Ward在他的评论中的请求,这是整个错误消息:
Error #2048: Security sandbox violation: http://localhost/bst/BasicSocketTest.swf cannot load data from 192.168.2.3:45455.

我有一个简化的测试客户端,为每个套接字事件设置了处理程序,并在屏幕上输出消息。以下是它显示的内容:

RequestPolicy: 192.168.2.3:843
Create Socket: 192.168.2.3:45455
Connect: [Event type="connect" bubbles=false cancelable=false eventPhase=2]
Sending: REG/REGISTER;simon.palmer@gmail.com;Si
Receiving: REG:0/REGISTER:SUCCESS;simon.palmer@gmail.com;Si/
Close: [Event type="close" bubbles=false cancelable=false eventPhase=2]
Error #2048: Security sandbox violation: http://localhost/bst/BasicSocketTest.swf cannot load data from 192.168.2.3:45455.

成功从服务器接收到响应后,立即触发close事件,但是错误#2048要等大约20秒才会出现。如果在关闭之后但在错误之前尝试发送进一步的消息,则Flash Player会抛出无效套接字异常。

我已经在Adobe上记录了一个错误

如果有人感兴趣,我可以提供客户端和服务器的完整源代码。


是否有任何进一步的细节写入到flashlog或policyfiles日志中?如果有,能否添加确切的消息? - Michael Brewer-Davis
flashlog 中有一条消息说正在加载 swf,但是策略日志只有这些了,我已经逐字逐句地展示了整个内容。 - Simon
你能贴出完整的错误信息吗? - James Ward
你能把你的测试源代码上传到FP-3302 bug吗? - James Ward
@James,完成了。我已经将我的服务器代码和我能制作的最简单的客户端放在一个压缩文件中,并附加到问题上。 - Simon
9个回答

3

我一直在本地测试,一切似乎都很正常,直到套接字关闭。套接字不应该关闭吗?在消息发送到Flex客户端后,Java代码执行以下操作:

_in.close();
_out.close();
_socket.close();

然后 Flex 客户端在下一次尝试与套接字通信时会收到沙箱冲突的错误。如果我再次创建一个新的套接字连接,那么发送和接收就可以正常工作,然后关闭。但是大约一分钟后,我又收到了另一个沙箱冲突的错误。我想知道是否 Flash 尝试 ping 套接字,因为它已经关闭,所以会抛出沙箱冲突的错误?


_in和_out只是打印流,应该关闭,但_socket是SocketServer在端口843上侦听时返回的TCP套接字。我将注释掉所有的“close”并查看发生了什么。非常感谢您的关注。 - Simon
进展了!我不再收到沙盒错误的提示了,但套接字也不再起作用了,因此通过它发送的第二个及后续消息都无法到达服务器。我正在进一步调查,但这感觉像是向前迈出的一步。谢谢James。 - Simon
由于某种原因,即使我注释掉了_socket.close()这一行,我仍然收到了一个关闭事件。不确定为什么会关闭。奇怪。 - James Ward

2

你尝试过添加allow-http-request-headers-from元素吗?

<allow-http-request-headers-from domain="*" headers="*" />

或者指定实际端口,而不是使用 * 作为 allow-access-from 元素的参数?

<allow-access-from domain="*" to-ports="843,45455" />

我尝试指定端口,但没有成功。第一个端口不适用,因为套接字策略文件规范不需要该标记。请记住,我不是在进行HTTP请求,而是直接使用二进制套接字连接到端口。 http://www.adobe.com/devnet/flashplayer/articles/socket_policy_files.html - Simon
这是 policyfiles.txt 的样子:OK:在策略文件中搜索 <allow-access-from>,以授权从 xmlsocket://192.168.2.3:45455 资源加载数据,请求者为 http://localhost/bst/BasicSocketTest.swf警告:忽略位于 xmlsocket://192.168.2.3:843 策略文件中的 '*' 域的无效 <allow-http-request-headers-from> 标记OK:策略文件已接受:xmlsocket://192.168.2.3:843OK:由于 xmlsocket://192.168.2.3:843 策略文件,允许来自 http://localhost/bst/BasicSocketTest.swf 请求者的 xmlsocket://192.168.2.3:45455 资源请求然后 2048 - Simon
关于allow-http-request-headers-from的问题有些奇怪,因为它遵循dtd和示例-http://kb2.adobe.com/cps/403/kb403185.html;在以前的项目中,那一行代码并指定实际端口有所帮助。这可能微不足道,但您是否已将本地文件夹添加到全局安全设置http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html中? - dan_nl
你有没有机会再次检查全局安全设置? http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html - dan_nl

1

除了你的crossdomain.xml之外,你可以尝试在代码中进一步使用Security类。

尝试:

Security.allowDomain("*")
Security.allowInsecureDomain("*")

或者,如果您正在从经批准的允许主机之外的外部服务器加载:

Security.allowDomain(loader.contentLoaderInfo.url)

然后慢慢地重新打开它,直到出现错误为止。

确保您可以直接访问策略文件,并且该端口上没有阻止或其他应用程序正在运行。通常情况下,当我运行套接字时,我会选择高于5000的端口,以确保没有任何东西占用该端口。或者尝试几个不同的端口。

另外,只需简单检查一下,确保您将其命名为crossdomain.xml,并且全部小写。我曾经有过程序员抓狂的经历,结果发现这是原因。


感谢您提供的代码建议,我尝试将两者添加到我的代码中,但我得到了同样的沙盒错误。我的服务器成功打开了843和45455端口,所以我没有任何端口阻塞问题。正如我在问题中所说,第一条消息已经传递了,这不会发生除非套接字正在工作。另外,我没有使用HTTP,因此crossdomain.xml与播放器在843端口上查找套接字主策略文件无关。这部分正常,并且我提供了一个开放的策略文件。但我仍然遇到了沙盒错误。http://www.adobe.com/devnet/flashplayer/articles/fplayer9_security_04.html - Simon

1

类似的问题在这里表明localhost没有被解析为127.0.0.1。

您可以尝试切换到IP地址,看看是否有帮助。


感谢您的建议,但是我只在绑定套接字时使用IP地址,所以在另一个线程中的本地主机解析不适用。 - Simon
1
正确但输出日志显示为http://localhost/bst/BasicSocketTest.swf。另一种测试方法是将其放在公共服务器上,然后测试该URL,而不是从本地主机测试。 - Ryan Christensen

1
尝试在XML结束标签“/>”之前加一个空格,就像dan_nl的建议一样,例如:

<allow-access-from domain="*" />

不要嘲笑它,我刚刚用这种方法解决了一个非常类似于你的问题(而且在我看来确实像是解析错误)。


1

不知道是否发生在Windows Vista上?IP地址是否指定为主机名?如果是,请参见this

或者可能是在分析器处于活动状态时发生的?如果是,请参见this


谢谢,但不行,XP。你的第一个链接也是由@Phil Hayward发布的。我不能确定这个问题是否会在公共互联网上消失,我正准备租用一个公共服务器来尝试解决它 - 这是一项昂贵的错误调查。没有使用分析器。 - Simon

1

在发送策略文件时,服务器应该在策略 XML 后始终发送一个零字节。从上面的描述中不清楚是否发送了零字节,这可能会最终混淆 Flash 播放器。


我知道空终止字节并尝试过,但没有任何效果。不过,我是在进行其他更改的同时尝试的,所以也许我会再试一次。谢谢你的回答。 - Simon

1
这可能对你有所帮助,但我们也遇到了类似的问题。我们一直收到安全错误,但不是每次都出现。我负责前端开发,与一个处理用PHP编写的Socket的开发人员合作。问题似乎在于确实存在竞争条件,即Flash在接收策略文件之前尝试连接套接字。因此,在前端中,我在安全错误处理程序中创建了一个重试机制,在放弃之前运行一定次数,并将超时时间从默认的20秒降至6或8秒。通常第二次就能成功连接,这确实有所帮助,但有时需要8-10秒才能连接,这不是最佳解决方案。
在我的搜索中找到了几个链接,其中一个链接提到在服务器上设置延迟,第7篇帖子: http://projectdarkstar.com/forum/?action=printpage;topic=1134.0 最终,我们从Adobe文章中下载并使用了Python策略文件服务器,它一直运行得非常顺畅。我无法解释为什么,因为我不是服务器专家,但这可能值得一试。

好的,我只能发布一个超链接,因为我是新用户,很奇怪。搜索“设置套接字策略文件服务器”,它应该会立即出现,在Adobe网站上的那篇文章中有示例文件。


这是一个非常有用的线索,非常感谢。我会稍微调整一下我的服务器代码来尝试一些东西。你怎么改变超时时间? - Simon
希望您需要Flash 10,因为这是它被引入的版本: http://help.adobe.com/en_US/AS3LCR/Flash_10.0/flash/net/Socket.html#timeout - Duncan
我尝试了与该帖子上的OP相同的事情,即添加延迟并确保套接字在服务器端关闭,并且我得到了略微不同的时间,但是结果相同。我应该在原始问题中放置Flash播放器版本-感谢您指出,我会进行编辑。 - Simon

0

我认为James Ward是正确的 - 我现在正在使用Sockets,前几天遇到了这个问题。我找到了一篇帖子,建议如果Flash客户端在分派COMPLETE事件时没有关闭Socket,则可能会导致您看到的错误。我已经添加了代码来在COMPLETE时关闭客户端Socket,到目前为止一切都正常。


这很有趣,但也有点令人困惑。那么,您是为每个请求创建一个新的客户端套接字吗?我正在捕获从客户端套接字发出的所有事件,但我根本没有收到COMPLETE事件 - 实际上,我无法确定可能是哪个事件,请给出精确的事件细节。我在套接字触发的ProgressEvent.SOCKET_DATA事件上处理数据。 - Simon

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