IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

Flash在某些多标签浏览器中的“伪沙箱”问题

阿里巴巴(中文站)用户体验设计部博客 2010-10-31 22:24:01 累计浏览 2,999 次
本机暂存

    Javascript-Selectors

    在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运行时发生了异常。

    sandbox

    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的源码:

package
{
 import flash.display.Sprite;
 import flash.external.ExternalInterface;
 import flash.system.Security;
 import flash.text.TextField;
 
 /**
  * Flash缓存造成的伪沙箱问题演示
  * @author qhwa
  */
 public class Main extends Sprite
 {
 
  public function Main():void
  {
   var tf:TextField = new TextField();
   tf.text = 'flash ready';
   tf.autoSize = 'left';
   addChild(tf);
 
   //允许被所有其他沙箱中的js或flash调用
   Security.allowDomain("*");
 
   start();
  }
 
  private function start():void
  {
   //在基于IE的多标签浏览器中,这里运行时可能出错
   ExternalInterface.call("alert", "Hi, flash is ready!");
   ExternalInterface.addCallback('drawCircle', drawCircle);
  }
 
  private function drawCircle():void
  {
   TextField(getChildAt(0)).appendText('\\nDraw a circle');
 
   graphics.beginFill(Math.random() * 0xFFFFFF, .5);
   graphics.drawCircle(
    Math.random() * stage.stageWidth,
    Math.random() * stage.stageHeight,
    50);
   graphics.endFill();
  }
 
 }
 
}

    似乎一旦swf是从缓存中读取的,allowScriptAccess这个配置就不起作用?为了验证是不是缓存引起的,我们每次为swf文件地址后面加上随机的数字,发现就不存在上面的问题了。可见这个问题确实是浏览器缓存造成的。

    为swf文件动态加时间戳或随机数,通过防止缓存可以回避掉这个问题。不过这不是一个很好的方案,因为这会极大增加服务器的压力,并且导致页面加载速度一直都很慢。

    不过好消息是,目前有个比这个更好的方案:延迟Flash的初始化功能。通过将Flash的ExternalInterface.addCallback时机延后一些,就可以解决这个问题。

    修改一下Flash的代码,加一个setTimeout:

…(略)
 public class Main extends Sprite
 {
 
  public function Main():void
  {
   …(|>略)
   //start();
   setTimeout(start, 500);
  }
 
  …(|>略)
 
 }
 
}

    测试修改后的效果

    那么,延迟多少比较合适呢?如果太多,用户会感觉到明显的延迟;太少,一些性能较差的电脑上问题依然存在。根据我一年多总结的经验,500ms是比较合理的数字。目前阿里巴巴中国网站上使用的Flash应用程序,如果有需要和js通信,都是延迟500ms初始化。

    顺便说一下,延迟500ms还有另外的一个作用。IE6中,Flash初始化的时候无法得到 stage.stageWidth正确的数字,返回是0(stageHeight也一样)。延迟一点初始化就可以得到正确的数值了。

    目前我还没有发现比延迟初始化更好的解决方案,如果你有更好的办法,欢迎交流!

同分类推荐文章

  1. 绿盟科技《APT组织研究年鉴》(2026 版)正式发布 (2026-06-16 20:21:10)
  2. 【已复现】Linux内核Fragnesia权限提升漏洞(CVE-2026-46300) (2026-06-15 10:53:58)
  3. 企业文档安全最佳实践(二):给文档上“身份证”——手动标密与智能自动标密 (2026-06-12 17:18:33)

查看更多 安全 文章 →

建议继续学习

  1. 视觉设计前瞻实用性研究(PNVD) 第三期 (累计阅读 6,042)
  2. 为flash建立socket安全策略文件服务器 (累计阅读 4,789)
  3. SAE云服务安全沙箱绕过5(强制修改class私有权限) (累计阅读 4,528)
  4. 如何将AIR应用打包成exe (累计阅读 4,145)
  5. 清除Firefox下Flash(swf文件)缓存 (累计阅读 3,950)
  6. FlashCookie (累计阅读 3,943)
  7. 使用html5 postMessage和window.name实现多浏览器跨域 (累计阅读 3,680)
  8. 网页设计三剑客 (累计阅读 3,219)
  9. 有故事的网页设计――Flash网站奇妙之旅 (累计阅读 3,188)
  10. SAE云服务安全沙盒绕过 (累计阅读 3,037)