web-dev-qa-db-ja.com

Adobe Flex / AIRのHTTPServiceオブジェクトを使用したHTTP基本認証

Adobe AIRアプリケーション内から基本的な認証ヘッダーを必要とするHTTPリソースをリクエストしようとしています。リクエストにヘッダーを手動で追加したり、setRemoteCredentials()メソッドを使用してヘッダーを設定したりして、役に立たないようにしました。

これがコードです:

<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" />

ただし、標準の基本認証ダイアログボックスがポップアップし、ユーザー名とパスワードの入力をユーザーに求めます。私はこれを正しい方法で行っていないと感じていますが、見つけることができたすべての情報(Flexドキュメント、ブログ、Googleなど)が機能しなかったか、あいまいすぎて助けになりませんでした。

ブラックマジック、フレックスグルありがとう。


EDIT: setRemoteCredentials()をsetCredentials()に変更すると、次のActionScriptエラーが発生します。

[MessagingError message='Authentication not supported on DirectHTTPChannel (no proxy).']

編集:アドビの注意を払って問題を解決しました。完全な説明については、以下の投稿を参照してください。このコードは、任意の長さのHTTP認証ヘッダーで機能します。

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();
}
31
Bob Somers

ついにアドビから注目を集め、これについて回答を得ました。長いHTTP認証ヘッダーの問題は、デフォルトでは、Base64Encoderクラスが72文字ごとに改行文字を挿入することです。これにより、base-64でエンコードされた文字列のチャンクが新しいヘッダー属性として解釈され、エラーが発生することは明らかです。

これを修正するには、(上記の例で)encoder.insertNewLines = falseを設定します。デフォルト設定はtrueです。

上記のコードを任意の長い認証文字列で機能するように修正しました。

13
Bob Somers

ああ。痛み、苦しみ。純粋な悲惨さ。

呼び出しを行う前にヘッダーを追加する方法を理解しましたが、厄介な真実は、Flash /ブラウザー統合スペースのどこかでヘッダーが再び削除されていることです。

昨年のブログ投稿 verveguy.blogspot.com から

だから私は真実を解明しました。 (思う)想像以上に拷問される

1 /すべてのHTTP GETリクエストからヘッダーが取り除かれます。 Flexスタックにはないので、おそらく基礎となるFlashプレーヤーランタイムです。

2/application/x-www-form-urlencoded以外のコンテンツタイプを持つすべてのHTTP GETリクエストは、POSTリクエストに変換されます

3 /すべてのHTTP POST実際にポストされたデータがないリクエストは、GETリクエストに変換されます。1/および2 /を参照してください。

4 /すべてのHTTP PUTおよびHTTP DELETE要求はPOST要求に変換されます。これは、Flashプレーヤーが動かなくなっているブラウザの制限のようです。(?)

これが具体的に言えば、すべてのリクエストでヘッダーを渡したい場合は、常にPOSTを使用する必要があります。また、実際に行う操作のセマンティクスを伝える別の方法を見つける必要があります。 Railsコミュニティは、?_method=PUT/DELETEを渡すことで、ブラウザの問題の回避策として4 /

FlashはGETに素晴らしいヘッダーストリッピングの痛みを追加するので、その回避策として?_method=GETも使用しています。ただし、これは3 /で作動するため、エンコードされたPOST dataとしてダミーオブジェクトを渡します。つまり、私のサービスは?_method=GETリクエストでダミーの投稿データを無視する必要があります。

この時点で重要なのは2 /について知ることです。それは私の時間の多くを無駄にしました。

このすべての処理をMXMLマークアップをサポートする新しいRESTServiceクラスに組み込んだので、これがクライアント側に存在しないふりをすることができます。

これが誰かを助けることを願っています。

9
verveguy

これは本当に私を助けました!ありがとう! Flex Builder 3を使用しています

注:WebServiceのプロパティヘッダーは読み取り専用です。そこで、httpHeadersを使用しようとしました。できます!

    var encoder:Base64Encoder = new Base64Encoder();
    encoder.insertNewLines = false;
    encoder.encode("test:test");

    sfWS.httpHeaders = {Authorization:"Basic " + encoder.toString()};   
1
user189100

SetCredentials()およびsetRemoteCredentials()メソッドは、Flex/LiveCycle Data Servicesでの使用を目的としているため、これらのメソッドはおそらく適用されません。

これはあなたのために働くべきです。サーバーでこの動作を再現できましたが、この修正で問題が解決したようです。ユースケースがどれほど一般的であると考えるかを考えると、これはまだAPIユーザーフレンドリーではないようですが、有効なSSL証明書が与えられているため、これが機能することをテストおよび検証しました。

private function authAndSend(service:HTTPService):void
{
        var encoder:Base64Encoder = new Base64Encoder();
        encoder.encode("someusername:somepassword");

        service.headers = {Authorization:"Basic " + encoder.toString()};                            
        service.send();
}

それが役に立てば幸い!そして投稿してくれてありがとう-遅かれ早かれ自分でこれに遭遇したと私は確信している。 ;)

1

HTTP Basic Authenticated Webserviceを使用しているときにも同じ問題が発生しました。これが私の解決策です。それはうまくいきます:

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

使用法

authAndSend(WebService( aWebServiceWrapper.serviceControl));
1
user576241

また、他の人が 正しい例 がまったく機能しない理由を解決するために10分間費やさないようにするには、mx.utils.Base64Encoderパッケージをインポートする必要があります。例:

        import mx.utils.Base64Encoder;

最初またはCDATA領域内のどこかに。私はflexを初めて使用するので、これは最初はそれほど明白ではありませんでした。

0
Bradley Falzon

SetRemoteCredentialsではなくsetCredentialsを使用して失敗します。Fiddler/ Charlesを使用して、リクエストで送信されているヘッダーを確認します。

0
Richard Szalay

これがその方法です。

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()}; 
0
Blake