Базовая аутентификация HTTP с объектами HTTPService в Adobe Flex / AIR - PullRequest
31 голосов
/ 29 января 2009

Я пытаюсь запросить ресурс 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();
}

Ответы [ 8 ]

13 голосов
/ 12 февраля 2009

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

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

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

9 голосов
/ 15 сентября 2009

Ах. Боль, страдание. Явное страдание.

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

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

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

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

2 / Все запросы HTTP GET с типом содержимого, отличным от application/x-www-form-urlencoded, преобразуются в запросы 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. Это означает, что мой сервис должен игнорировать фиктивные данные по запросу ?_method=GET.

Крайне важно знать о 2 /. Это потратило кучу моего времени.

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

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

1 голос
/ 15 января 2011

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

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

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

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

    sfWS.httpHeaders = {Authorization:"Basic " + encoder.toString()};   
1 голос
/ 29 января 2009

Методы 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();
}

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

0 голосов
/ 21 декабря 2010

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

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 голосов
/ 08 марта 2009

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

        import mx.utils.Base64Encoder;

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

0 голосов
/ 29 января 2009

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

...