Authentification HTTP Basic avec les objets HTTPService dans Adobe Flex / AIR
j'essaie de demander une ressource HTTP qui nécessite des en-têtes d'autorisation de base à partir d'une application Adobe AIR. J'ai essayé d'ajouter manuellement les en-têtes à la requête, ainsi que d'utiliser la méthode setRemoteCredentials() pour les définir, en vain.
voici le code:
<mx:Script>
<![CDATA[
import mx.rpc.events.ResultEvent;
import mx.rpc.events.FaultEvent;
private function authAndSend(service:HTTPService):void
{
service.setRemoteCredentials('someusername', 'somepassword');
service.send();
}
private function resultHandler(event:ResultEvent):void
{
apiResult.text = event.result.toString();
}
private function resultFailed(event:FaultEvent):void
{
apiResult.text = event.fault.toString();
}
]]>
</mx:Script>
<mx:HTTPService id="apiService"
url="https://mywebservice.com/someFileThatRequiresBasicAuth.xml"
resultFormat="text"
result="resultHandler(event)"
fault="resultFailed(event)" />
<mx:Button id="apiButton"
label="Test API Command"
click="authAndSend(apiService)" />
<mx:TextArea id="apiResult" />
cependant, une boîte de dialogue standard de l'auteur apparaît toujours en demandant à l'utilisateur son nom d'utilisateur et son mot de passe. J'ai un sentiment que je ne suis pas le faire jusqu'à ce de la bonne façon, mais toutes les infos que j'ai pu trouver (Flex docs, blogs, Google, etc.) soit n'a pas fonctionné, soit était trop vague pour aider.
de la magie noire, oh gourous de Flex? Grâce.
éditer: changer setRemoteCredentials() en setCredentials () produit l'erreur suivante ActionScript:
[MessagingError message='Authentication not supported on DirectHTTPChannel (no proxy).']
modifier: Problème résolu, après un peu D'attention de la part D'Adobe. Voir les messages ci-dessous pour une explication complète. Ce code fonctionnera pour les en-têtes D'authentification HTTP de longueur arbitraire.
import mx.utils.Base64Encoder;
private function authAndSend(service:HTTPService):void
{
var encoder:Base64Encoder = new Base64Encoder();
encoder.insertNewLines = false; // see below for why you need to do this
encoder.encode("someusername:somepassword");
service.headers = {Authorization:"Basic " + encoder.toString()};
service.send();
}
8 réponses
a finalement reçu une certaine attention de la part D'Adobe et a obtenu une réponse à ce sujet. Le problème avec les en-têtes D'authentification HTTP longue durée est que, par défaut, la classe Base64Encoder injectera des caractères newline tous les 72 caractères. De toute évidence, cela fait qu'une partie de la chaîne encodée base-64 est interprétée comme un nouvel attribut d'en-tête, ce qui provoque l'erreur.
vous pouvez corriger cela en définissant (dans l'exemple ci-dessus) encoder.insertNewLines = false; le paramètre par défaut est true.
j'ai corrigé le code ci-dessus pour qu'il fonctionne avec des chaînes d'authentification de longueur arbitraire.
Ah. La douleur, la souffrance. La misère pure et simple.
alors que vous avez trouvé comment ajouter un en-tête avant de faire votre appel, la méchante vérité est que quelque part au fond de L'Espace D'intégration Flash/browser vos en-têtes sont enlevés à nouveau.
D'après mon billet de blog l'année dernière à verveguy.blogspot.com
ainsi j'ai découvert la vérité. (Je pense) C'est plus torturé que l'on pourrait imaginer
1 / Toutes les requêtes HTTP GET sont dépouillées des en-têtes. Ce n'est pas dans la pile Flex, donc c'est probablement L'exécution Flash player sous-jacente
2 / Toutes les requêtes HTTP GET ayant un type de contenu autre que application/x-www-form-urlencoded
sont transformées en requêtes POST
3 / Toutes les requêtes HTTP POST qui n'ont pas de données postées réelles sont transformées en requêtes GET. Voir 1 / et 2 /
4 / Toutes les requêtes HTTP PUT et HTTP DELETE sont activées dans les requêtes POST. Cela semble être une limitation de navigateur que le lecteur Flash est coincé avec. (?)
ce qui se résume en termes pratiques est que si vous voulez passer des en-têtes dans toutes les demandes, vous devez toujours utiliser le courrier et vous devez trouver une autre façon de communiquer la sémantique de l'opération que vous "avez vraiment voulu". La communauté des Rails a décidé de passer ?_method=PUT/DELETE
comme un travail autour pour les problèmes de navigateur sous-jacents 4 /
depuis Flash ajoute le magnifique en-tête stripping pain sur GET, je suis également en utilisant ?_method=GET
comme une solution de contournement pour cela. Cependant, depuis, les voyages sur 3/,
Je passe un objet factice en tant que données codées. Ce qui veut dire que mon service doit ignorer les données postées factices sur une demande ?_method=GET
.
Crucial à ce point de savoir environ 2/. Qui a perdu un tas de mon temps.
j'ai construit toute cette manipulation dans une nouvelle classe RESTService avec le support de markup MXML il est donc possible de prétendre que cela n'existe pas du côté des clients.
J'espère que ça aidera quelqu'un.
les méthodes setCredentials() & setRemoteCredentials() sont destinées à être utilisées avec les services de données Flex/LiveCycle, de sorte qu'elles ne s'appliquent probablement pas dans votre cas.
ça devrait marcher pour vous. J'ai été capable de reproduire ce comportement sur mon serveur, et ce correctif semble avoir fait l'affaire; il semble encore un peu étrange que ce ne soit pas plus API-facile à utiliser, Compte tenu de la façon dont un cas d'utilisation commune que vous pensez qu'il était, mais néanmoins, j'ai testé et vérifié ces travaux, compte tenu d'un certificat SSL valide:
private function authAndSend(service:HTTPService):void
{
var encoder:Base64Encoder = new Base64Encoder();
encoder.encode("someusername:somepassword");
service.headers = {Authorization:"Basic " + encoder.toString()};
service.send();
}
Espère que cela aide! Et merci d'avoir posté -- je suis sûr que j'aurais rencontré celui-ci tôt ou tard moi-même. ;)
cela m'a vraiment aidé! Merci! J'utilise Flex Builder 3
One note: les en-têtes de propriété de WebService sont en lecture seule. Alors j'ai essayé d'utiliser httpHeaders. Il fonctionne!
var encoder:Base64Encoder = new Base64Encoder();
encoder.insertNewLines = false;
encoder.encode("test:test");
sfWS.httpHeaders = {Authorization:"Basic " + encoder.toString()};
j'ai eu le même problème en utilisant le service Web authentifié HTTP Basic. C'est ma solution; elle fonctionne bien:
private function authAndSend(service:WebService):void
{
var encoder:Base64Encoder = new Base64Encoder();
encoder.insertNewLines = false;
encoder.encode("user:password");
service.httpHeaders = { Authorization:"Basic " + encoder.ToString() };
service.initialize();
}
utilisation
authAndSend(WebService( aWebServiceWrapper.serviceControl));
essayez d'utiliser setCredentials plutôt que setRemoteCredentials et à défaut, utilisez Fiddler/Charles pour savoir quels en-têtes sont envoyés avec la requête.
aussi, juste pour que les autres ne passent pas 10 minutes à comprendre pourquoi le " bon exemple ne fonctionne pas tout à fait asis, vous devez importer le mx.utils.Base64Encoder package par exemple:
import mx.utils.Base64Encoder;
au début ou quelque part dans la zone de CDATA. Je suis nouvelle à flex, donc ce n'était pas évident au début.
C'est comme ça que ça marche.
import mx.utils.Base64Encoder;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.http.HTTPService;
var _oHttp:HTTPService = new HTTPService;
var sUsername:String = "theusername"
var sPassword:String = "thepassword";
var oEncoder:Base64Encoder = new Base64Encoder();
oEncoder.insertNewLines = false;
oEncoder.encode(sUsername + ":" + sPassword);
_oHttp.method = "POST";
_oHttp.headers = {Authorization:"Basic " + oEncoder.toString()};