2009-02-03 4 views
10

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

Я попытался изменить следующее (заменив 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, хотя мне удалось успешно изменить сценарий загрузки несколько.

[Редактировать] - вот это обновление моего прогресса, на основе ниже ответ, хотя я до сих пор не могу получить эту работу:

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

Общее поведение, которое я испытываю при работе с проверенными 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 - поскольку в настоящее время у меня его нет, и я не уверен, где его разместить.

+0

crossdomain.xml должны быть помещены в корневой каталог вашего веб-приложения. Поэтому, если файлы, содержащие www.yoursite.com, расположены в D: \ websites \ yoursite.com, путь файла должен быть d: \ websites \ yoursite.com \ crossdomain.xml. –

+0

В дополнение к размещению файла corssdomain.xml (что вам нужно сделать), знаете ли вы, какая версия проигрывателя Flash вы установили? Вы уверены, что используете Flash Player 10? (Похоже, мои выводы были в том, что Flash Player 9 не играет хорошо с пользовательскими заголовками авторизации.) –

+0

Благодарим за помощь. Кристиан - к сожалению, у меня не было возможности пройти дополнительные испытания (были завалены другим проектом) но я попробую один, я получаю эту возможность. – BrynJ

ответ

18

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

  • Вам почти наверняка придется изменить свой 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 here).

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

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

+0

Тоны советов для одного и того же, но единственный реальный рабочий ответ, который работает для простого приложения flex с помощью sdk 4.6. Большое спасибо. – serkan

+0

это хорошо работает с as3 ide. – sputn1k

1

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

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

+0

Использование этого, кажется, единственный способ отправить информацию авторизации с использованием запроса GET – Arpit

+0

Очевидно, что это старый поток, но просто выбрасывает его, чтобы этот метод добавления 'username: password @ ...' работал для меня, тогда как добавление заголовков Basic Auth не работало без отображения диалоговых окон проверки подлинности в моем приложении AIR. – dierdre

0

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

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

+0

Я также столкнулся с этой проблемой сеанса и придумал аналогичное решение, но здесь не проблема, а именно HTTP-аутентификация (не связанная с сеансом как таковая). – BrynJ

0

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

Лучшее, что нужно сделать, это не испортить HTTP-заголовки.

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

1
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(); 
+0

эй, ребята, спасибо за ваши идеи, мне удается взломать для использования HTTPService вместо URLRequest. Все, что я сделал, это добавить переменную через service.request и установить service.method = 'POST' Надеюсь, что поможет !!! :) – 2009-07-28 14:22:43

0

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

Я построил компонент, который динамически записывает объекты 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, проверьте наличие Params

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

2

Если вы хотите загрузить файл, вам просто нужно отправить правильные заголовки и содержимое файла с помощью 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);