Flex 3 - как поддерживать HTTP-аутентификацию URLRequest? - PullRequest
10 голосов
/ 04 февраля 2009

У меня есть скрипт загрузки файлов 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 - поскольку у меня его нет, и я не уверен, где его разместить.

Ответы [ 9 ]

18 голосов
/ 04 февраля 2009

Синтаксис немного отличается для 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-файлами для отладки и выпуска), поэтому он должен работать для вас, но я хотел обновить свой оригинальный пост, чтобы включить всю эту дополнительную информацию на случай, если вы столкнетесь с какими-либо проблемами, как шансы кажутся (к сожалению) вероятными, что вы будете.

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

3 голосов
/ 31 июля 2009

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

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

2 голосов
/ 17 октября 2012

Если вы хотите загрузить файл, вам просто нужно отправить правильные заголовки и содержимое файла, используя 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);
1 голос
/ 28 июля 2009
var service : HTTPService  = new HTTPService ();
var encoder:Base64Encoder = new Base64Encoder();
encoder.insertNewLines = false;
encoder.encode("user:password");

service.headers = {Authorization:"Basic " + encoder.toString()};
service.method = HTTPRequestMessage.POST_METHOD;
service.request = new URLVariables("name=John+Doe");
service.addEventListener(FaultEvent.FAULT,error_handler );
service.addEventListener(ResultEvent.RESULT,result_handler);
service.url = 'http://blah.blah.xml?'+UIDUtil.createUID();
service.send();
1 голос
/ 22 мая 2009

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

"http://username:password@yoursite.com/yourservice.ext"

0 голосов
/ 09 июля 2010

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

Я создал компонент, который динамически записывает объекты Flex на страницу, чтобы их можно было использовать в UpdatePanels. Напишите мне, если вы хотите, чтобы они код. Чтобы решить вышеупомянутую проблему на страницах, где 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;

Наконец, добавьте куки в 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 закрыла вопрос как неразрешимый, так что это было мое последнее средство.

0 голосов
/ 10 марта 2010

"http://username:password@yoursite.com/yourservice.ext"

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

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

0 голосов
/ 27 мая 2009

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

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

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

0 голосов
/ 26 мая 2009

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

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

...