Flex 3 - как поддерживать HTTP-аутентификацию URLRequest?

У меня есть сценарий загрузки файла Flex, который использует URLRequest для загрузки файлов на сервер. Я хочу добавить поддержку HTTP-аутентификации (защищенные паролем каталоги на сервере), но я не знаю, как это реализовать - я предполагаю, что мне нужно как-то расширить класс, но как это сделать, я немного потерялся.

Я попытался изменить следующее (заменив HTTPService на URLRequest), но это не сработало.

private function authAndSend(service:HTTPService):void{        
   var encoder:Base64Encoder = new Base64Encoder();        
   encoder.encode("someusername:somepassword");        
   service.headers = {Authorization:"Basic " + encoder.toString()};
   service.send();
}

Я должен отметить, что я не разбираюсь в ActionScript / Flex, хотя мне удалось несколько успешно изменить сценарий загрузки.

[Edit] - это обновленная информация о моем прогрессе, основанная на приведенном ниже ответе, хотя я все еще не могу заставить это работать:

Спасибо за помощь. Я пытался реализовать ваш код, но мне не повезло.

Общее поведение, с которым я сталкиваюсь при работе с местоположениями с аутентификацией HTTP, заключается в том, что с IE7 все в порядке, но в Firefox, когда я пытаюсь загрузить файл на сервер, он отображает запрос аутентификации HTTP, который даже при наличии правильных данных просто останавливается процесс загрузки.

Я считаю, что причина, по которой IE7 в порядке, заключается в том, что информация о сеансе / аутентификации совместно используется браузером и компонентом Flash - однако в Firefox это не так, и я испытываю вышеуказанное поведение.

Вот моя обновленная функция загрузки, включающая ваши изменения:

private function pergress():void 
{
if (fileCollection.length == 0) 
  {
  var urlString:String = "upload_process.php?folder="+folderId+"&type="+uploadType+"&feid="+formElementId+"&filetotal="+fileTotal;
  if (ExternalInterface.available) 
    {
    ExternalInterface.call("uploadComplete", urlString);
    }
  }
if (fileCollection.length > 0) 
  {
  fileTotal++;
  var urlRequest:URLRequest = new URLRequest("upload_file.php?folder="+folderId+"&type="+uploadType+"&feid="+formElementId+"&obfuscate="+obfuscateHash+"&sessidpass="+sessionPass);
  urlRequest.method = URLRequestMethod.POST;
  urlRequest.data = new URLVariables("name=Bryn+Jones");
  var encoder:Base64Encoder = new Base64Encoder();
  encoder.encode("testuser:testpass");
  var credsHeader:URLRequestHeader = new URLRequestHeader("Authorization", "Basic " + encoder.toString());
  urlRequest.requestHeaders.push(credsHeader);

  file = FileReference(fileCollection.getItemAt(0));
  file.addEventListener(Event.COMPLETE, completeHandler);
  file.addEventListener(HTTPStatusEvent.HTTP_STATUS, onHTTPStatus);
  file.addEventListener(ProgressEvent.PROGRESS, onUploadProgress);
  file.upload(urlRequest);
  }
}

Как указано выше, я, кажется, испытываю те же результаты с поправками к моей функции или без них.

Могу ли я также спросить, где должен находиться crossdomain.xml - поскольку у меня его в настоящее время нет, и я не уверен, где его разместить.


person BrynJ    schedule 03.02.2009    source источник
comment
crossdomain.xml следует поместить в корневой каталог вашего веб-приложения. Поэтому, если файлы, составляющие www.yoursite.com, расположены в D: \ sites \ yoursite.com, путь к файлу должен быть d: \ sites \ yoursite.com \ crossdomain.xml.   -  person Christian Nunciato    schedule 22.05.2009
comment
Знаете ли вы, какую версию Flash-плеера вы установили, помимо размещения файла corssdomain.xml (что вам следует сделать)? Вы уверены, что используете Flash Player 10? (Похоже, я пришел к выводу, что Flash Player 9 плохо работает с настраиваемыми заголовками авторизации.)   -  person Christian Nunciato    schedule 22.05.2009
comment
Спасибо за помощь, Кристиан - к сожалению, у меня не было возможности продолжить тестирование (я был завален другим проектом), но я попробую тот, который у меня есть.   -  person BrynJ    schedule 27.05.2009
comment
В любой момент! Надеюсь, что это работает для вас.   -  person Christian Nunciato    schedule 28.05.2009


Ответы (9)


Синтаксис URLRequest немного отличается, но идея та же:

private function doWork():void
{
    var req:URLRequest = new URLRequest("http://yoursite.com/yourservice.ext");
    req.method = URLRequestMethod.POST;
    req.data = new URLVariables("name=John+Doe");

    var encoder:Base64Encoder = new Base64Encoder();        
    encoder.encode("yourusername:yourpassword");

    var credsHeader:URLRequestHeader = new URLRequestHeader("Authorization", "Basic " + encoder.toString());
    req.requestHeaders.push(credsHeader);

    var loader:URLLoader = new URLLoader();
    loader.load(req);
}

Следует помнить о нескольких вещах:

  • Лучшее, что я могу сказать, по какой-то причине это работает только там, где метод запроса - POST; заголовки не устанавливаются с запросами GET.

  • Интересно, что он также терпит неудачу, если хотя бы одна пара имя-значение URLVariables не будет упакована с запросом, как указано выше. Вот почему многие из примеров, которые вы видите (включая мой), прикрепляют «name = John + Doe» - это просто заполнитель для некоторых данных, которые, похоже, требуются URLRequest при установке любых пользовательских заголовков HTTP. Без него даже правильно аутентифицированный запрос POST также не сработает.

  • Очевидно, Flash Player версии 9.0.115.0 полностью блокирует все заголовки авторизации (подробнее об этом здесь), так что вы, вероятно, тоже захотите иметь это в виду.

  • Вам почти наверняка придется изменить файл crossdomain.xml, чтобы он соответствовал заголовкам, которые вы собираетесь отправлять. В моем случае я использую это, который является довольно широко открытым файлом политики, поскольку он принимает из любого домена, поэтому в вашем случае вы можете немного ограничить вещи, в зависимости от того, насколько вы заботитесь о безопасности. .

crossdomain.xml:

<?xml version="1.0"?>
<cross-domain-policy>
    <allow-access-from domain="*" />
    <allow-http-request-headers-from domain="*" headers="Authorization" />
</cross-domain-policy> 

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

Приведенный выше код был протестирован с помощью Flash Player 10 (с SWF-файлами для отладки и выпуска), поэтому он должен работать для вас, но я хотел обновить свое исходное сообщение, чтобы включить всю эту дополнительную информацию на случай, если у вас возникнут какие-либо проблемы, поскольку есть вероятность (к сожалению) вероятно, что вы это сделаете.

Надеюсь, поможет! Удачи. Я буду следить за комментариями.

person Christian Nunciato    schedule 03.02.2009
comment
Тонны советов для одного и того же, но единственный реальный рабочий ответ, работающий для простого гибкого приложения с sdk 4.6. Большое Вам спасибо. - person serkan; 24.01.2014

Методы FileReference.upload () и FileReference.download () не поддерживают параметр URLRequest.requestHeaders.

http://livedocs.adobe.com/flex/2/langref/flash/net/URLRequest.html

person Steven Mo    schedule 31.07.2009

Если вы хотите загрузить файл, вам просто нужно отправить правильные заголовки и содержимое файла с помощью URLRequest через класс UploadPostHelper. Это работает на 100%, я использую этот класс для загрузки сгенерированных изображений и файлов CSV, но вы можете загрузить любой файл.

Этот класс просто подготавливает запрос с заголовками и содержимым, как если бы вы загружали файл из HTML-формы.

http://code.google.com/p/as3asclublib/source/browse/trunk/net/UploadPostHelper.as?r=118

_urlRequest = new URLRequest(url);
        _urlRequest.data = "LoG";
        _urlRequest.method = URLRequestMethod.POST; 

        _urlRequest.requestHeaders.push(new URLRequestHeader("X-HTTP-Code-Override", "true"));
        _urlRequest.requestHeaders.push(new URLRequestHeader("pragma", "no-cache"));

        initCredentials();
_loader.dataFormat = URLLoaderDataFormat.BINARY;
            //this creates a security problem, putting the content type in the headers bypasses this problem
            //_urlRequest.contentType = 'multipart/form-data; boundary=' + UploadPostHelper.getBoundary();
            _urlRequest.requestHeaders.push( new URLRequestHeader( 'Cache-Control', 'no-cache' ) );
            _urlRequest.requestHeaders.push(new URLRequestHeader('Content-Type', 'multipart/form-data; boundary=' + UploadPostHelper.getBoundary()));
            _urlRequest.data = UploadPostHelper.getPostData("file.csv", param[1]);

        _loader.load(_urlRequest);
person Caius Miron    schedule 17.10.2012

Я не уверен в этом, но пробовали ли вы добавить имя пользователя: пароль @ в начало URL-адреса?

"http://username:[email protected]/yourservice.ext"

person Leo Jweda    schedule 22.05.2009
comment
Использование этого кажется единственным способом отправить информацию об авторизации с помощью запроса GET. - person Arpit; 26.03.2010
comment
Ясно, что это старый поток, но я просто сказал, что этот метод добавления username:password@... работал у меня, тогда как добавление заголовков Basic Auth не работало без отображения диалоговых окон аутентификации в моем приложении AIR. - person dierdre; 29.12.2014

Похоже на то, что проблема была решена здесь. Я настоятельно рекомендую вам также проверить сообщение о Flexcoders, ссылка на которое есть в первый пост.

Проблема заключалась в том, что FireFox использует отдельный экземпляр окна браузера для отправки запроса на загрузку файла. Решение - вручную прикрепить идентификатор сеанса к URL-адресу запроса. Идентификатор сеанса прикрепляется не как обычная переменная GET, а через точку с запятой (причина такого синтаксиса мне неизвестна).

person Niko Nyman    schedule 26.05.2009
comment
Я тоже столкнулся с этой проблемой сеанса и придумал аналогичное решение, но это не проблема, с которой здесь столкнулся, а именно HTTP-аутентификация (не связанная с сеансом как таковая). - person BrynJ; 27.05.2009

Flash очень ограничен с точки зрения того, какие заголовки вы можете передавать с HTTP-запросом (и он меняется между браузерами и ОС). Если вы заставили это работать в одном браузере / ОС, обязательно протестируйте его на других.

Лучше всего не связываться с заголовками HTTP.

У нас та же проблема (загрузка в Веб-альбомы Picasa с флэш-памяти) и публикация через прокси-сервер на нашем сервере. Мы передаем лишние заголовки как параметры публикации, и наш прокси-сервер делает все правильно.

person Brian    schedule 27.05.2009

"http://username:[email protected]/yourservice.ext"

Это не работает в IE (http://www.theregister.co.uk/2004/01/30/ms_drop_authentication_technique/) и, похоже, не работает в Chrome.

вероятно, не может использоваться во Flash

person Anentropic    schedule 10.03.2010

Вот обходной путь при использовании ASP.Net, частично основанный на работе, которую здесь.

Я создал компонент, который динамически записывает объекты Flex на страницу, чтобы их можно было использовать в UpdatePanels. Напишите мне, если хотите, чтобы они кодировали. Чтобы решить указанную выше проблему на страницах, где файлы cookie проверки подлинности должны быть отправлены с помощью URLRequest, я добавляю значения в виде flashVars.

Этот код работает только в моем объекте, но вы поняли идею

Dictionary<string, string> flashVars = new Dictionary<string, string>();     
flashVars.Add("auth", Request.Cookies["LOOKINGGLASSFORMSAUTH"].Value);
flashVars.Add("sess", Request.Cookies["ASP.NET_SessionId"].Value);
myFlexObject.SetFlashVars(flashVars);

Затем в объекте Flex проверьте параметры

if (Application.application.parameters.sess != null)
    sendVars.sess= Application.application.parameters.sess;
if (Application.application.parameters.auth != null)
    sendVars.au= Application.application.parameters.auth;

request.data = sendVars;
request.url = url;
request.method = URLRequestMethod.POST;

Наконец, поместите файлы cookie в global.asax BeginRequest

if (Request.RequestType=="POST" && Request.Path.EndsWith("upload.aspx"))
{
    try
    {
        string session_param_name = "sess";
        string session_cookie_name = "ASP.NET_SESSIONID";
        string session_value = Request.Form[session_param_name]; // ?? Request.QueryString[session_param_name];
        if (session_value != null) { UpdateCookie(session_cookie_name, session_value); }
    }
    catch (Exception) { }

    try
    {
        string auth_param_name = "au";
        string auth_cookie_name = FormsAuthentication.FormsCookieName;
        string auth_value = Request.Form[auth_param_name];// ?? Request.QueryString[auth_param_name];

        if (auth_value != null) { UpdateCookie(auth_cookie_name, auth_value); }
    }
    catch (Exception) { }   

}

Надеюсь, это поможет кому-то избежать 6 часов, которые я только что потратил на решение этой проблемы. Adobe закрыла проблему как неразрешимую, так что это было моим последним средством.

person Laramie    schedule 08.07.2010

person    schedule
comment
Привет, ребята, спасибо за ваши идеи, мне удалось придумать хак для использования HTTPService вместо URLRequest. Все, что я сделал, это добавил переменную через service.request и установил service.method = 'POST' Надеюсь, что это поможет !!! :) - person ; 28.07.2009