Базовая аутентификация HTTP с использованием объектов HTTPService в Adobe Flex / AIR

StackOverflow https://stackoverflow.com/questions/490806

Вопрос

Я пытаюсь запросить HTTP-ресурс, для которого требуются базовые заголовки авторизации из приложения Adobe AIR.Я пытался вручную добавить заголовки к запросу, а также использовать метод 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 docs, блоги, Google и т.д.), Либо не сработала, либо была слишком расплывчатой, чтобы помочь.

Какая-нибудь черная магия, о, гибкие гуру?Спасибо.


Редактировать: Изменение setRemoteCredentials() на setCredentials() приводит к следующей ошибке ActionScript:

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

Редактировать: Проблема решена после некоторого внимания со стороны Adobe.Смотрите сообщения ниже для получения полного объяснения.Этот код будет работать для заголовков 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();
}
Это было полезно?

Решение

Наконец-то получил некоторое внимание от Adobe и получил ответ на этот вопрос.Проблема с длинными заголовками HTTP-аутентификации заключается в том, что по умолчанию класс Base64Encoder вводит символы новой строки каждые 72 символа.Очевидно, что это приводит к тому, что фрагмент строки в кодировке base-64 интерпретируется как новый атрибут заголовка, что вызывает ошибку.

Вы можете исправить это, установив (в приведенном выше примере) encoder.insertNewLines = false;Значение по умолчанию равно true.

Я исправил приведенный выше код для работы с произвольно длинными строками аутентификации.

Другие советы

А.Боль, страдание.Сплошное страдание.

Хотя вы выяснили, как добавить заголовок перед выполнением вызова, неприятная правда заключается в том, что где-то глубоко в пространстве интеграции Flash / браузера ваши заголовки снова удаляются.

Из моего поста в блоге в прошлом году на вервегай.blogspot.com

Итак, я разгадал Правду.(Я думаю) Это более мучительно, чем можно себе представить

1/ Все HTTP GET-запросы лишены заголовков.Его нет в стеке Flex, так что, вероятно, это базовая среда выполнения Flash Player

2/ Все HTTP-запросы GET, которые имеют тип контента, отличный от application/x-www-form-urlencoded превращаются в запросы POST

3/ Все HTTP-POST-запросы, которые не содержат фактических опубликованных данных, превращаются в GET-запросы.Смотрите 1/ и 2/

4/ Все HTTP-запросы PUT и HTTP DELETE преобразуются в POST-запросы.Похоже, это ограничение браузера, с которым застрял Flash Player.(?)

На практике это сводится к тому, что если вы хотите передавать заголовки во всех запросах, вы всегда должны использовать POST и вам следует найти другой способ передать семантику операции, которую вы "действительно хотели".Сообщество Rails остановилось на прохождении ?_method=PUT/DELETE в качестве решения проблем браузера, лежащих в основе 4/

Поскольку Flash добавляет замечательную проблему удаления заголовка в GET, я также использую ?_method=GET в качестве обходного пути для этого.Однако, поскольку это срабатывает на 3/, Я передаю фиктивный объект в качестве закодированных данных POST.Это означает, что мой сервис должен игнорировать фиктивные размещенные данные на ?_method=GET просьба.

На данный момент крайне важно знать о 2/.Это отняло уйму моего времени.

Я встроил всю эту обработку в новый класс RestService с поддержкой разметки MXML, так что можно притвориться, что этого не существует на стороне клиента.

Надеюсь, это кому-то поможет.

Методы setCredentials() и setRemoteCredentials() предназначены для использования со службами передачи данных Flex / LiveCycle, поэтому они, вероятно, неприменимы в вашем случае.

Это должно сработать у вас.Я смог воспроизвести это поведение на своем сервере, и это исправление, похоже, сделало свое дело;все еще кажется немного странным, что это не более удобно для 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();
}

Надеюсь, это поможет!И спасибо за публикацию - я уверен, что сам рано или поздно столкнулся бы с этим.;)

Это действительно помогло мне!Спасибо!Я использую Flex Builder 3

Одна нота:Заголовки свойств веб-сервиса доступны только для чтения.Поэтому я попытался использовать HttpHeaders .Это работает!

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

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

У меня была такая же проблема при использовании 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));

Попробуйте использовать setCredentials вместо setRemoteCredentials и, если это не удастся, используйте Fiddler / Charles, чтобы узнать, какие заголовки отправляются с запросом.

Кроме того, просто для того, чтобы другие люди не тратили 10 минут на выяснение, почему правильный пример не совсем работает asis, вам нужно импортировать mx.utils.Пакет Base64Encoder, например:

        import mx.utils.Base64Encoder;

В начале или где-то в пределах области CDATA.Я новичок в flex, так что поначалу это было не совсем очевидно.

Вот как это делается.

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()}; 
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top