2017-10-04 106 views
1

我想通過動作腳本3 Flash應用程序訪問Watson文本到語音API。正如您所知,Adobe實施了一項新的安全功能,以使用基於規則的xml配置文件(crossdomain.xml)的機制來限制跨域的訪問。在我的情況下,執行腳本時提出了以下錯誤:從Adobe動作腳本沃森API訪問3

的源代碼:

 

    package 
    { 
     import flash.net.URLRequest; 
     import flash.net.URLRequestHeader; 
     import flash.net.URLLoaderDataFormat; 
     import flash.net.URLLoader; 
     import flash.net.URLVariables; 
     import flash.net.URLRequestMethod; 
     import flash.events.Event; 
     import flash.events.HTTPStatusEvent; 
     import flash.events.SecurityErrorEvent; 
     import flash.events.IOErrorEvent; 

     public class Greeter 
     { 
     public function sayHello():String 
     { 

      var params:Object = {user:"John",password:"secret"}; 

      var request:URLRequest = new URLRequest(); 
      request.url = "https://watson-api-explorer.mybluemix.net/text-to-speech/api/v1/voices"; 
      request.contentType = "application/json"; 
      request.method = URLRequestMethod.POST; 

      request.data = JSON.stringify(params); 

      var contentTypeHeader:URLRequestHeader = new URLRequestHeader("Content-Type","application/json"); 
      var acceptHeader:URLRequestHeader = new URLRequestHeader("Accept","application/json"); 
      var formDataHeader:URLRequestHeader = new URLRequestHeader("Content-Type","application/json"); 
      var authorizationHeader:URLRequestHeader = new URLRequestHeader("Authorization","Basic YjcxYWUwNTMtZTJmYi00ZmQzLWFiMTctOTRjYTc2MzYzYWE3OlZ5dU9VZ0w3ak1zVw=="); 

      request.requestHeaders = [acceptHeader,formDataHeader,authorizationHeader,contentTypeHeader]; 

      var postLoader:URLLoader = new URLLoader(); 
      postLoader.dataFormat = URLLoaderDataFormat.BINARY; 
      postLoader.addEventListener(Event.COMPLETE, loaderCompleteHandler); 
      postLoader.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler); 
      postLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler); 
      postLoader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler); 

      try 
      { 
      postLoader.load(request); 
      } 
      catch (error:Error) 
      { 
      trace("Unable to load post URL"); 
      } 

      var greeting:String; 
      greeting = "Prueba de conexión a Watson!"; 
      return JSON.stringify(request.data); 
     } 

     private function loaderCompleteHandler(event:Event):void 
     { 
      trace("loaderCompleteHandler: "); 
     } 

     private function httpStatusHandler(event:HTTPStatusEvent):void 
     { 
      trace("httpStatusHandler: "); 
     } 

     private function securityErrorHandler(event:SecurityErrorEvent):void 
     { 
      trace("securityErrorHandler: " + event); 
     } 

     private function ioErrorHandler(event:IOErrorEvent):void 
     { 
      trace("ioErrorHandler: " + event); 
     } 
     } 
    } 

控制檯輸出:

 

[trace] Advertencia: Error al cargar el archivo de política desde https://watson-api-explorer.mybluemix.net/crossdomain.xml 
[trace] *** Violación de la seguridad Sandbox *** 
[trace] Se ha detenido la conexión con https://watson-api-explorer.mybluemix.net/text-to-speech/api/v1/voices - no se permite desde http://garragames.com/garra-x/Tick.swf 
[trace] 05:45:44 PM | err | [SecurityErrorEvent type="securityError" bubbles=false cancelable=false eventPhase=2 text="Error #2170: Security sandbox violation: http://garragames.com/garra-x/Tick.swf cannot send HTTP headers to https://watson-api-explorer.mybluemix.net/text-to-speech/api/v1/voices."] 
[trace] Error #2044: Unhandled securityError:. text=Error #2170: Security sandbox violation: http://garragames.com/garra-x/Tick.swf cannot send HTTP headers to https://watson-api-explorer.mybluemix.net/text-to-speech/api/v1/voices. 

¿存在另一種選擇,從動作腳本的Flash訪問API應用程序?

+4

**選項1 **。一些服務考慮了Flash安全模型,並提供了使用其功能的方法。閱讀他們的文檔或聯繫他們的支持。 **選項2 **。如果您不需要它是基於Web的應用程序,請使用AIR。桌面/移動應用程序的限制較少。 **選項3 **。你可以隨時訴諸你的應用** <-> **你的服務器** <-> **他們的服務模式。 – Organis

+0

顯示一些可以測試的代碼以重新創建此錯誤。也許有人可以修復它。 –

+0

@Garrapato,PHP是一個訪問數據並傳遞給AS3的選項嗎?您的安全性錯誤是因爲您的網站是'http://',但您嘗試從'https://'網站加載媒體。即使你解決了這個問題(通過使用安全/ HTTPS服務器),你也會得到真正的錯誤:「Actionscript中不允許授權頭」。使用PHP或Javascript並通過外部接口將數據傳遞給AS3 .. –

回答

0

你真正的問題應該是如何認證?從閃存沃森API,而不是如何擊敗裝載的是一個安全沙箱問題/通過URLLoader解碼(有自動跨域檢查)。

您必須以某種方式進行身份驗證(登錄)。這似乎不太可能通過Actionscript實現。通過使用URLStream代替URLLoader

"Authorization header cannot be sent using Actionscript" 

:你可以看到像Flash Player的錯誤。另外URLStream不關心安全問題。它只是獲得字節,如果它們存在。根據this document它說Flash「授權」請求是允許的。雖然沒有爲我工作。也許在調試器中不允許?

一旦從您的URL /域進行身份驗證,您的Flash應用程序也可以按照正常的POST網址發送任何請求,因爲它通過同一個(現在允許的)域詢問。如果您想要字節,請使用URLStream而不是URLLoader,因爲它沒有跨域限制。例如,您可以使用Sound對象來播放轉換爲語音的文本。

(如果authenticated,即:您登錄)嘗試:

  • 讓舞臺上的input文本框中,用實例名txtbox
  • 保存在以下文檔類代碼名爲:Main.as(編譯爲main.swf中)

測試代碼如下:(SWF結果=類型爲文本框,然後按回車聽到口語)。

package 
    { 
     import flash.display.MovieClip; 
     import flash.utils.*; 
     import flash.media.*; 
     import flash.net.*; 
     import flash.events.*; 

     public class Main extends MovieClip 
     { 
      public var snd_Obj: Sound = new Sound; 
      public var snd_Chann: SoundChannel = new SoundChannel; 
      public var snd_req: URLRequest = new URLRequest(); 

      public var str_Token: String = ""; 
      public var url_sendto_Watson: String = ""; 

      public var str: String = ""; 
      public var str_Voice: String = ""; 
      public var str_mySpeech: String = ""; 

      public var load_Token: URLLoader; 

      public function Main() 
      { 
       load_Token = new URLLoader(); 
       load_Token.addEventListener(Event.COMPLETE, onTokenLoaded); 
       load_Token.load(new URLRequest("https://stream.watsonplatform.net/authorization/api/v1/token?url=https://stream.watsonplatform.net/text-to-speech/api")); 

       //# Your token as requested from :: https://stream.watsonplatform.net/authorization/api/v1/token?url=https://stream.watsonplatform.net/text-to-speech/api 
       //trace("Token : " + str_Token); //# To confirm it has token code 

       //txtbox.type = "INPUT"; 
       txtbox.background = true; 
       txtbox.text = ""; //starting text 
       txtbox.addEventListener(TextEvent.TEXT_INPUT, text_inputCapture); 
       txtbox.addEventListener(KeyboardEvent.KEY_DOWN, key_handler); 
       addChild(txtbox); 
      } 

      function key_handler(evt:KeyboardEvent) 
      { 
       if(evt.charCode == 13) //# if ENTER key is pressed (will send text to convert to speech) 
       { 
        str_mySpeech = txtbox.text; 
        str_mySpeech = str_mySpeech.replace(" ", "%20"); 

        str_Voice = "en-US_AllisonVoice"; //or your preferred voice (see: 

        //# Update requested URL to include your typed text 
        url_sendto_Watson = ""; //# reset 
        url_sendto_Watson = "https://stream.watsonplatform.net/text-to-speech/api/v1/synthesize?"; 
        url_sendto_Watson += "accept=audio/mp3"; //# get as MP3 result 
        url_sendto_Watson += "&text=" + str_mySpeech; 
        url_sendto_Watson += "&voice=" + str_Voice; //# ie: "en-US_AllisonVoice" 
        url_sendto_Watson += "&token=" + str_Token; 

        //# Attempt loading 
        snd_req.url = url_sendto_Watson; 
        snd_Obj = new Sound(); 
        snd_Obj.addEventListener(Event.COMPLETE, onSoundLoaded); 
        snd_Obj.load(snd_req); 

        txtbox.removeEventListener(KeyboardEvent.KEY_DOWN, key_handler); 
       } 
      } 

      public function text_inputCapture(event:TextEvent):void 
      { 
       str = txtbox.text; //# Update text to send 
       txtbox.addEventListener(KeyboardEvent.KEY_DOWN, key_handler); 
      } 

      function onSoundLoaded(event:Event):void 
      { 
       snd_Chann = snd_Obj.play(); //# Play returned Speech convert result 
       snd_Obj.removeEventListener(Event.COMPLETE, onSoundLoaded); 
      } 

      function onTokenLoaded(evt:Event):void 
      { str_Token = evt.target.data; /*# get Token result */ } 


     } //end Class 

    } //end Package 

這隻有在SWF文件嵌入HTML頁面內時纔有效。如下所示:

<!DOCTYPE html> 
    <html> 
    <body> 

    <audio id="audio_watson"> 
    <source src="http://stream.watsonplatform.net/text-to-speech/api/v1/synthesize?accept=audio/mp3&text=welcome&voice=en-US_AllisonVoice" type="audio/mpeg"> 
    </audio> 

    <embed src="Main.swf" width="800" height="600"> 

    <script> 
    var a = document.getElementById("audio_watson"); 
    a.play(); //playback to trigger authentication 
    </script> 

    </body> 
    </html>