Flex 3 - 如何支持HTTP身份验证URLRequest?

时间:2009-02-03 22:32:29

标签: flex actionscript base64 http-authentication urlrequest

我有一个Flex文件上传脚本,它使用URLRequest将文件上传到服务器。我想添加对http身份验证(服务器上受密码保护的目录)的支持,但我不知道如何实现这一点 - 我假设我需要以某种方式扩展类,但是如何让我有点迷失。

我尝试修改以下内容(用URLRequest替换HTTPService),但这不起作用。

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应该位于何处 - 因为我目前没有,并且我不确定在哪里放置它。

9 个答案:

答案 0 :(得分: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(带有调试和发布SWF)测试的,所以它应该适合你,但我想更新我原来的帖子,以包含所有这些额外的信息,以防你遇到任何问题,因为很可能(遗憾地)你很可能会这样做。

希望它有所帮助!祝好运。我会留意你的意见。

答案 1 :(得分:3)

FileReference.upload()和FileReference.download()方法不支持URLRequest.requestHeaders参数。

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

答案 2 :(得分:2)

如果您想上传文件,只需通过UploadPostHelper类使用URLRequest发送正确的标题和文件内容。这是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);

答案 3 :(得分:1)

我对此不太确定,但您是否尝试在网址的开头添加用户名:password @?

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

答案 4 :(得分: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();

答案 5 :(得分:0)

看似类似的问题已经解决here。我还建议您检查第一篇文章中链接的Flexcoders post

问题是FireFox使用单独的浏览器窗口实例来发送文件上传请求。 解决方案是将会话ID手动附加到请求网址。会话ID不作为常规GET变量附加,而是附加分号(我不知道这种语法的原因)。

答案 6 :(得分:0)

Flash在使用http请求传递的标头类型方面非常有限(并且它在浏览器和操作系统之间发生变化)。如果你在一个浏览器/操作系统上运行它,请确保在其他浏览器/操作系统上进行测试。

最好的办法是不要乱用HTTP标头。

我们遇到了同样的问题(从Flash上​​传到Picasa网络相册)并通过我们服务器上的代理发布。我们通过post参数传递额外的标题,我们的代理做了正确的事。

答案 7 :(得分:0)

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

这在IE(http://www.theregister.co.uk/2004/01/30/ms_drop_authentication_technique/)中不起作用,并且似乎也无法在Chrome中使用。

可能无法在Flash中使用

答案 8 :(得分:0)

在使用部分基于工作here的ASP.Net时,这是一个解决方法。

我构建了一个组件,可以动态地将Flex对象写入页面,以便可以在UpdatePanels中使用它们。如果你想要他们代码,请给我留言。要在URLRequest需要发送身份验证cookie的页面中解决上述问题,我将这些值添加为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已将此问题视为无法解决,因此这是我的最后一招。