如何避免使用Youtube AS3 Player API时的安全错误

问题描述:

我正在使用Youtube AS3 Player API在Flash项目中加载视频。 我加载播放器SWF的时候得到这个真的很烦人的错误:如何避免使用Youtube AS3 Player API时的安全错误

SecurityError: Error #2047: Security sandbox violation: parent: http://www.degoudenglimlach.be/main.swf cannot access http://www.youtube.com/[[IMPORT]]/s.ytimg.com/yt/swf/watch_as3-vflbgr4dW.swf. 

我试图加载SWF之前添加以下到我的代码,但它并没有任何区别:

Security.allowDomain("*"); 
Security.allowDomain("www.youtube.com"); 
Security.allowDomain("youtube.com"); 
Security.allowDomain("s.ytimg.com"); 
Security.allowDomain("i.ytimg.com"); 

任何帮助会很好。

这里是我的全部包装类:

package be.zap.media 
{ 
    import flash.display.Loader; 
    import flash.display.Sprite; 
    import flash.events.Event; 
    import flash.net.URLRequest; 
    import flash.system.Security; 
    import flash.system.System; 

    /** 
    * ... 
    * @author Yens Resmann 
    */ 
    public class ZapYoutubeVideo extends Sprite 
    { 
     private var ytPlayer : Object; 
     private var ldr : Loader 
     private static const YOUTUBE_EMBEDDED_PLAYER_URL : String = "http://www.youtube.com/v/VIDEO_ID?version=3"; 

     public static const PLAYER_READY : String = "playerReady"; 

     public static const QUALITY_SMALL : String = "small"; 
     public static const QUALITY_MEDIUM : String = "medium"; 
     public static const QUALITY_LARGE : String = "large"; 
     public static const QUALITY_HD720 : String = "hd720"; 
     public static const QUALITY_HD1080 : String = "hd1080"; 
     public static const QUALITY_HIGHRES : String = "highres"; 
     public static const QUALITY_DEFAULT : String = "default"; 

     public function ZapYoutubeVideo() 
     { 
      Security.allowDomain("*"); 
      Security.allowDomain("www.youtube.com"); 
      Security.allowDomain("youtube.com"); 
      Security.allowDomain("s.ytimg.com"); 
      Security.allowDomain("i.ytimg.com"); 

      ldr = new Loader(); 
      ldr.contentLoaderInfo.addEventListener(Event.INIT, handleInitPlayer); 
      addEventListener(Event.REMOVED_FROM_STAGE, handleRemovedFromStage); 
     } 

     public function initPlayer(vidId : String) 
     { 
      var url : String = YOUTUBE_EMBEDDED_PLAYER_URL.split("VIDEO_ID").join(vidId); 
      ldr.load(new URLRequest(url)); 
     } 

     private function handleInitPlayer(e:Event):void 
     { 
      addChild(ldr); 
      ldr.contentLoaderInfo.removeEventListener(Event.INIT, handleInitPlayer); 

      ldr.content.addEventListener("onReady", handlePlayerReady); 
      ldr.content.addEventListener("onError", handlePlayerError); 
      ldr.content.addEventListener("onStateChange", handlePlayerStageChange); 
      ldr.content.addEventListener("onPlaybackQualityChange", handlePlayerQualityChange); 
     } 

     private function handlePlayerReady(e:Event):void 
     { 
      ytPlayer = ldr.content; 
      dispatchEvent(new Event(PLAYER_READY)); 
     } 

     public function queueVideoById(videoID : String, quality : String = QUALITY_DEFAULT):void 
     { 
      ytPlayer.cueVideoById(videoID, 0, quality); 
     } 

     public function loadVideoById(videoID : String, quality : String = QUALITY_DEFAULT):void 
     { 
      ytPlayer.loadVideoById(videoID, 0, quality); 
     } 

     public function queueVideoByUrl(url : String, quality : String = QUALITY_DEFAULT):void 
     { 
      ytPlayer.cueVideoByUrl(url, 0, quality); 
     } 

     public function loadVideoByUrl(url : String, quality : String = QUALITY_DEFAULT):void 
     { 
      ytPlayer.loadVideoByUrl(url, 0, quality); 
     } 

     public function setSize(w:int, h:int):void 
     { 
      ytPlayer.setSize(w, h); 
     } 

     private function handlePlayerError(e:Event):void 
     { 

     } 

     private function handlePlayerStageChange(e:Event):void 
     { 

     } 

     private function handlePlayerQualityChange(e:Event):void 
     { 

     } 

     private function handleRemovedFromStage(e:Event):void 
     { 
      removeEventListener(Event.REMOVED_FROM_STAGE, handleRemovedFromStage); 
      dispose(); 
     } 

     public function dispose():void 
     { 
      ytPlayer.destroy(); 
      if (ldr) { 
       if (contains(ldr)) { 
        removeChild(ldr); 
       } 
       ldr = null; 
      } 
     } 

     /** 
     * parse out the Youtube Video ID from the video URL 
     * @param url 
     * @return String 
     */ 
     public static function getIdFromURL(url:String):String 
     { 
      var parts : Array = []; 
      if (url.indexOf("watch?v=") != -1) { 
       parts = url.split("watch?v="); 
      } else if (url.indexOf("watch/v/") != -1) { 
       parts = url.split("watch/v/"); 
      } else if (url.indexOf("youtu.be/") != -1) { 
       parts = url.split("youtu.be/"); 
      } 
      return String(parts[1]).split("/").join(""); 
     } 

     /** 
     * get the thumbnail of the video 
     * @param String youtube Video ID 
     * @return URLRequest 
     */ 
     public static function getThumbnail(videoId : String):URLRequest 
     { 
      return new URLRequest("http://img.youtube.com/vi/" + videoId + "/0.jpg"); 
     } 

    } 

} 

我不认为这是可能的,看的错误信息,你应该看到,他们主要是不得不面对的事实,YouTube已经没有更新他们的跨域策略文件并且不指定元策略。这里是他们的政策文件:

<!-- http://www.youtube.com/crossdomain.xml --> 
<!DOCTYPE cross-domain-policy 
    SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd"> 
<cross-domain-policy> 
    <allow-access-from domain="*.youtube.com" /> 
    <allow-access-from domain="s.ytimg.com" /> 
</cross-domain-policy> 

他们需要添加一行:

<site-control permitted-cross-domain-policies="all"/> 
+0

所以API非常漂亮,除非他们更新这个策略文件? – Yens 2010-09-24 10:13:45

+0

好吧,它实际上是在工作,这些错误大多是警告说应该更新策略文件。这很烦人,但没有多少人可以做到这一点 – PatrickS 2010-09-24 16:43:44

+0

这些错误的大部分确实是警告。如果是这样的话,我不会介意那么多,但是我所说的错误会导致Firefox + FP10.1崩溃。 – Yens 2010-09-25 08:13:03

我使用这个功能

private function test():void 
{ 
    var ytLoader:SWFLoader = new SWFLoader(); 
    ytLoader.addEventListener(Event.INIT, playerLoaderInitHandler); 
    ytLoader.loaderContext = new LoaderContext(true); 
    ytLoader.load("http://www.youtube.com/v/TXrc6BwGCXE?version=3"); 
} 
private function playerLoaderInitHandler(event:Event):void 
{ 
    var loader:SWFLoader = event.currentTarget as SWFLoader; 
    addChild(loader); 
} 

我使用的SWFLoader代替装载机。

+0

谢谢,greensock的SWFLoader类没有问题。在YouTube的变化之后,原生Flash的Loader类似乎不再适用。它以前工作正常。即使在脚本文件中添加了所有类型的system.security()函数后,它不仅需要“https”,而且还会一直发出“安全错误”。 – 2016-10-05 13:23:53

我得到同样的问题,并花费大量的时间试图修复而不隐藏错误。 所以我做了一个非常疯狂的举动。 根据我的错误,进一步跟踪堆栈看起来像这样:

error before .... 
cannot access https://s.ytimg.com/yts/swfbin/player-vflzYgZmb/watch_as3.swf. 
at flash.display::DisplayObject/get parent() 
at fl.managers::FocusManager/isTabVisible() 
at fl.managers::FocusManager/tabEnabledChangeHandler() 
at flash.events::EventDispatcher/dispatchEventFunction() 
at flash.events::EventDispatcher/dispatchEvent() 
at com.google.youtube.ui::UIElement/onAddedToStage() 

那么我注意到,如果标签儿童被允许YouTube播放器API被检查,所以我只是删除它在容器MC增加,其中玩家放置:

this.tabChildren = false; 

并猜测什么 - 没有更多的错误!而且我需要在将tabChildren设置为false并且玩家准备好之后添加到舞台玩家。