请选择 进入手机版 | 继续访问电脑版
记得收藏【国际动画教程网】,赶快注册吧!
注册

合作站点账号登陆

QQ登录

只需一步,快速开始

扫一扫,访问微社区

快捷导航
查看: 17832|回复: 0
收起左侧

Flash在某些多标签浏览器中的“伪沙箱”问题[含2P]

[复制链接]
发表于 2017-6-8 07:16:18 | 显示全部楼层 |阅读模式

在Flash播放器运行时,将不同来源的资源划分到独立的沙箱(sandbox)内,不同沙箱之间不能彼此操作数据(除非目标沙箱做过一些设置,授 权其他沙箱可访问),这就是Flash的跨沙箱问题。当Flash文件(.swf)  和页面(.html)不在同一个域名下时,如果不经过Flash内部声明System.allowDomain,html无法访问flash定义的接口; 不经过html设置allowScriptAccess为’always’,Flash也无法调用页面上的js函数。
那么如果html和flash都设置了互相可以访问,是否Flash和html之间就可以互相访问了呢?理论上是的,然而实际上却不是。

在Chrome、Firefox等非IE浏览器上,是没有问题的。在“纯正”的IE6、IE7、IE8上也是正常的。但是在傲游、360浏览器、腾讯浏览器等基于IE的多标签浏览器中,刷新页面的时候,Flash播放器还是会抛安全沙箱错误。
点击访问测试页面。
使用上面说的“基于IE的多标签浏览器”访问,你会看到,第一次是正常的,刷新之后就不正常。如果你安装的是debug版本的播放器,可以看到Flash运行时发生了异常。

SecurityError: Error #2060: 安全沙箱冲突:ExternalInterface 调用者 http://pnq.cc/temp/test-dmm-crssdmn.swf 不能访问 http://q.pnq.cc/works/test/test-dmm-crssmn.html。
at flash.external::ExternalInterface$/_initJS()
at flash.external::ExternalInterface$/call()
at Main/start()
at Main/init()
at Main()
Flash的源码:

  1. package
  2. {
  3.         import flash.display.Sprite;
  4.         import flash.external.ExternalInterface;
  5.         import flash.system.Security;
  6.         import flash.text.TextField;

  7.         /**
  8.          * Flash缓存造成的伪沙箱问题演示
  9.          * @author qhwa
  10.          */
  11.         public class Main extends Sprite
  12.         {

  13.                 public function Main():void
  14.                 {
  15.                         var tf:TextField = new TextField();
  16.                         tf.text = 'flash ready';
  17.                         tf.autoSize = 'left';
  18.                         addChild(tf);

  19.                         //允许被所有其他沙箱中的js或flash调用
  20.                         Security.allowDomain("*");

  21.                         start();
  22.                 }

  23.                 private function start():void
  24.                 {
  25.                         //在基于IE的多标签浏览器中,这里运行时可能出错
  26.                         ExternalInterface.call("alert", "Hi, flash is ready!");
  27.                         ExternalInterface.addCallback('drawCircle', drawCircle);
  28.                 }

  29.                 private function drawCircle():void
  30.                 {
  31.                         TextField(getChildAt(0)).appendText('nDraw a circle');

  32.                         graphics.beginFill(Math.random() * 0xFFFFFF, .5);
  33.                         graphics.drawCircle(
  34.                                 Math.random() * stage.stageWidth,
  35.                                 Math.random() * stage.stageHeight,
  36.                                 50);
  37.                         graphics.endFill();
  38.                 }

  39.         }

  40. }
复制代码
似乎一旦swf是从缓存中读取的,allowScriptAccess这个配置就不起作用?为了验证是不是缓存引起的,我们每次为swf文件地址后面加上随机的数字,发现就不存在上面的问题了。可见这个问题确实是浏览器缓存造成的。
为swf文件动态加时间戳或随机数,通过防止缓存可以回避掉这个问题。不过这不是一个很好的方案,因为这会极大增加服务器的压力,并且导致页面加载速度一直都很慢。
不过好消息是,目前有个比这个更好的方案:延迟Flash的初始化功能。通过将Flash的ExternalInterface.addCallback时机延后一些,就可以解决这个问题。
修改一下Flash的代码,加一个setTimeout:

  1.         ...(略)
  2.         public class Main extends Sprite
  3.         {

  4.                 public function Main():void
  5.                 {
  6.                         ...(略)
  7.                         //start();
  8.                         setTimeout(start, 500);
  9.                 }

  10.                 ...(略)

  11.         }

  12. }
复制代码
测试修改后的效果
那么,延迟多少比较合适呢?如果太多,用户会感觉到明显的延迟;太少,一些性能较差的电脑上问题依然存在。根据我一年多总结的经验,500ms是比较合理的数字。目前阿里巴巴中国网站上使用的Flash应用程序,如果有需要和js通信,都是延迟500ms初始化。
顺便说一下,延迟500ms还有另外的一个作用。IE6中,Flash初始化的时候无法得到 stage.stageWidth正确的数字,返回是0(stageHeight也一样)。延迟一点初始化就可以得到正确的数值了。
目前我还没有发现比延迟初始化更好的解决方案,如果你有更好的办法,欢迎交流!



上一篇:Flash AS3.0教你射击类游戏的制作
下一篇:Flash制作钢笔字的简单
一起共享资源,共建精品资源平台。记得一定要收藏我们网站。www.gjdhjc.com ||||| 还有我们的网址导航:www.58q8.com【链接失效可以留言看到第一时间补帖,如果懒的回复我也是没办法了】
快速回复 返回顶部 返回列表