2017-10-04 48 views
1

J'essaie d'accéder à l'API Text to Speech de Watson via une application Flash d'action script 3. Comme vous le savez, Adobe met en œuvre de nouvelles fonctions de sécurité pour restreindre l'accès à travers les domaines en utilisant un mécanisme qui utilise un fichier de configuration xml basé sur des règles (crossdomain.xml). Dans mon cas, l'erreur ci-dessous est déclenché lorsque le script est exécuté:Accès à l'API Watson à partir du script d'action adobe 3

code source:

 

    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); 
     } 
     } 
    } 

Sortie de la console:

 

[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. 

¿Exist une autre option pour accéder à l'API d'Action Script flash App?

+4

** Option 1 **. Certains services ont en tête le modèle de sécurité Flash et fournissent les moyens d'utiliser leurs fonctionnalités. Lisez leur documentation ou contactez leur support. **Option 2**. Si vous n'avez pas besoin d'une application Web, utilisez AIR. Les applications de bureau/mobiles ont moins de restrictions. ** Option 3 **. Vous pouvez toujours recourir à votre application ** <-> ** Votre serveur ** <-> ** Leur modèle de service. – Organis

+0

Affiche du code qui peut être testé pour recréer cette erreur. Peut-être que quelqu'un peut le réparer. –

+0

@Garrapato, PHP est-il une option pour accéder aux données et passer à AS3? Votre erreur de sécurité est due au fait que votre site est 'http: //' mais vous essayez de charger le média depuis un site 'https: //'. Même si vous corrigez cela (en utilisant un serveur sécurisé/HTTPS), vous obtiendrez la vraie erreur en disant: 'L'en-tête d'autorisation n'est pas autorisé dans Actionscript'. Utilisez PHP ou Javascript et passez les données à AS3 via l'interface externe. –

Répondre

0

Votre vraie question devrait être « comment authentifier? » avec l'API Watson à partir de Flash plutôt que la façon de battre cette question sandbox de sécurité de chargement/décodage via URLLoader (qui a contrôle automatique inter-domaines).

Vous devez vous authentifier (se connecter) d'une manière ou d'une autre. Cela semble une chose improbable à réaliser via Actionscript seulement. Vous pouvez voir une erreur Flash Player comme:

"Authorization header cannot be sent using Actionscript" 

en utilisant URLStream à la place URLLoader. Aussi URLStream ne se soucie pas de problèmes de sécurité. Il obtient juste les octets s'ils existent. Selon this document, il est dit que les demandes d'autorisation "Flash" sont autorisées. Je n'ai pas travaillé pour moi. Peut-être que ce n'est pas autorisé dans le débogueur?

Une fois authentifié à partir de votre URL/Domaine, votre application Flash peut également faire des demandes comme d'habitude POST car elle demande via le même domaine (maintenant autorisé). Utilisez URLStream au lieu de URLLoader si vous voulez des octets car il n'a pas de restrictions inter-domaines. PS: par exemple, vous pouvez utiliser un objet Sound pour lire un texte converti en discours.

(si authenticated, à savoir: vous êtes connecté) Essayez:

  • Faire une zone de texte input sur scène, avec par exemple le nom txtbox.
  • Enregistrer sous le code dans la classe de document intitulé: Main.as (compilation comme main.swf)

Test du code ci-dessous: (SWF résultat = le type en zone de texte et appuyez sur Entrée pour entendre parler).

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 

Ceci ne fonctionne que lorsque le fichier SWF est incorporé dans une page HTML. Quelque chose comme ci-dessous:

<!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>