Flex 3: cómo admitir la Autenticación HTTP URLRequest?
actionscript base64 (9)
Tengo un script de carga de archivos Flex que usa URLRequest para cargar archivos a un servidor. Quiero agregar soporte para la autenticación http (directorios protegidos por contraseña en el servidor), pero no sé cómo implementar esto, supongo que necesito extender la clase de alguna manera, pero sobre cómo estoy un poco perdido.
Traté de modificar lo siguiente (reemplazando HTTPService con URLRequest), pero eso no funcionó.
private function authAndSend(service:HTTPService):void{
var encoder:Base64Encoder = new Base64Encoder();
encoder.encode("someusername:somepassword");
service.headers = {Authorization:"Basic " + encoder.toString()};
service.send();
}
Debo señalar que no conozco ActionScript / Flex, aunque sí he logrado modificar el script de carga.
[Editar] - aquí hay una actualización de mi progreso, basado en la respuesta a continuación, aunque todavía no puedo hacer que esto funcione:
Gracias por su asistencia. Intenté implementar tu código, pero no tuve suerte.
El comportamiento general que experimento cuando trato con ubicaciones autenticadas HTTP es que con IE7 todo está bien, pero en Firefox cuando intento subir un archivo al servidor, aparece una solicitud de autenticación HTTP, que incluso si se dan los detalles correctos, simplemente se detiene. el proceso de carga
Creo que la razón por la que IE7 está bien es por la información de sesión / autenticación que comparten el navegador y el componente Flash; sin embargo, en Firefox este no es el caso y experimento el comportamiento anterior.
Aquí está mi función de carga actualizada, que incorpora sus cambios:
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);
}
}
Como se indicó anteriormente, parece que estoy experimentando los mismos resultados con o sin las modificaciones a mi función.
¿Puedo preguntar también dónde se debe ubicar crossdomain.xml, ya que actualmente no tengo uno y no estoy seguro de dónde ubicarlo?
" http: // username: [email protected]/yourservice.ext "
Esto no funciona en IE ( http://www.theregister.co.uk/2004/01/30/ms_drop_authentication_technique/ ) y tampoco parece funcionar en Chrome.
probablemente no se pueda usar en Flash
Aquí hay una solución temporal al usar ASP.Net basado en parte en el trabajo aquí .
Creé un componente que escribe dinámicamente objetos Flex en la página para que puedan ser utilizados en UpdatePanels. Envíame un mensaje si quieres que codifiquen. Para resolver el problema anterior en páginas donde las cookies de autenticación necesitarán ser enviadas por URLRequest, agrego los valores en flashVars.
Este código solo funciona en mi objeto, pero obtienes la idea
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);
Luego, en el objeto Flex, verifique los 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;
Finalmente, rellene las cookies en 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) { }
}
Espero que esto ayude a alguien a evitar las 6 horas que acabo de pasar abordando esto. Adobe ha cerrado el problema como irresoluble, por lo que este fue mi último recurso.
Flash es muy limitado en términos de qué tipo de encabezados puede pasar con una solicitud http (y cambia entre los navegadores y los sistemas operativos). Si logras que esto funcione en un navegador / sistema operativo, asegúrate de probarlo en los demás.
Lo mejor que puedes hacer es no meterse con los encabezados HTTP.
Tenemos el mismo problema (cargar en Álbumes web de Picasa desde el flash) y publicar a través de un proxy en nuestro servidor. Pasamos los encabezados adicionales como parámetros de publicación y nuestro proxy hace lo correcto.
La sintaxis es un poco diferente para URLRequest, pero la idea es la misma:
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);
}
Un par de cosas a tener en cuenta:
Lo mejor que puedo decir es que, por alguna razón, esto solo funciona cuando el método de solicitud es POST; los encabezados no se configuran con las solicitudes GET.
Curiosamente, también falla a menos que al menos un par de nombre-valor URLVariables se empaquete con la solicitud, como se indicó anteriormente. Es por eso que muchos de los ejemplos que ves por ahí (incluido el mío) adjuntan "name = John + Doe" - es solo un marcador de posición para algunos datos que parece requerir URLRequest al configurar cualquier encabezado HTTP personalizado. Sin él, incluso una solicitud POST debidamente autenticada también fallará.
Aparentemente, la versión de Flash Player 9.0.115.0 bloquea completamente todos los encabezados de Autorización (más información sobre este aquí ), por lo que probablemente también desee tener eso en cuenta.
Seguramente tendrá que modificar su archivo crossdomain.xml para acomodar el (los) encabezado (s) que va a enviar. En mi caso, estoy usando esto, que es un archivo de política bastante abierto en el sentido de que acepta desde cualquier dominio, por lo que en su caso, es posible que desee limitar las cosas un poco más, dependiendo de qué tan consciente esté de la seguridad. .
crossdomain.xml:
<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="*" />
<allow-http-request-headers-from domain="*" headers="Authorization" />
</cross-domain-policy>
... y eso parece funcionar; más información sobre esto está disponible de Adobe aquí ).
El código anterior se probó con Flash Player 10 (con SWF de depuración y liberación), por lo que debería funcionar para usted, pero quería actualizar mi publicación original para incluir toda esta información adicional en caso de que tenga algún problema, ya que las posibilidades parecen (tristemente) es probable que lo haga.
¡Espero eso ayude! Buena suerte. Voy a estar atento a los comentarios.
Los métodos FileReference.upload () y FileReference.download () no admiten el parámetro URLRequest.requestHeaders.
http://livedocs.adobe.com/flex/2/langref/flash/net/URLRequest.html
No estoy seguro de esto, pero ¿ha intentado agregar el nombre de usuario: contraseña @ al comienzo de su url?
Si desea cargar un archivo, solo tiene que enviar los encabezados correctos y el contenido del archivo usando URLRequest a través de la clase UploadPostHelper. Esto funciona al 100%, estoy usando esta clase para cargar imágenes generadas y archivos CSV, pero puedes subir cualquier tipo de archivo.
Esta clase simplemente prepara la solicitud con los encabezados y el contenido como si estuvieras cargando el archivo desde un formulario 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);
Un problema aparentemente similar fue resuelto aquí . Le insto a que también verifique las publicaciones de Flexcoders vinculadas en la primera publicación.
El problema era que FireFox utiliza una instancia de ventana del navegador por separado para enviar la solicitud de carga del archivo. La solución es adjuntar manualmente el ID de sesión a la url de solicitud. El ID de la sesión no está adjuntado como una variable GET normal, pero con un punto y coma (el motivo de esta sintaxis es desconocido para mí).
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();