2009-02-03 47 views
10

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

我试着修改下面的代码(用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应该放在哪里 - 因为我目前没有,我不确定放置它的位置。

+0

crossdomain.xml必须放置在你的web应用程序的根目录。因此,如果包含www.yoursite.com的文件位于D:\ websites \ yoursite.com,则文件路径应该是d:\ websites \ yoursite.com \ crossdomain.xml。 – 2009-05-22 13:23:55

+0

除了放置您的corssdomain.xml文件(您应该这样做),您是否知道已安装了哪个Flash Player版本?你确定你在使用Flash Player 10吗? (看起来我的发现是,Flash Player 9与自定义授权标头不兼容。) – 2009-05-22 13:33:28

+0

感谢您的帮助Christian - 不幸的是,我没有机会进一步测试(已经被另一个项目所淹没)但我会尝试一个我得到的机会。 – BrynJ 2009-05-27 13:18:16

回答

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),所以它应该适合您,但我想更新我的原始文章以包含所有这些额外信息,以防您遇到任何问题,因为你可能会(似乎很可能)有机会。

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

+0

对于同样的事情,建议的声调,但唯一真正的工作答案工作简单的Flex应用与SDK 4.6。非常感谢你。 – serkan 2014-01-24 15:38:26

0

看似类似的问题得到解决here。我敦促你也检查第一篇文章中链接的Flexcoders post

问题是FireFox使用单独的浏览器窗口实例发送文件上传请求。 解决方案是手动将会话ID附加到请求url。会话标识不作为常规GET变量附加,但以分号(此语法的原因未知)。

0

对于可以通过http请求传递什么类型的头文件(并在浏览器和操作系统之间进行更改),Flash非常有限。如果你在一个浏览器/操作系统上运行它,请确保在其他浏览器上进行测试。

最好的事情不是搞乱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

可用在这里是一个变通的基础上工作here部分使用ASP.Net时。

我构建了一个组件,将Flex对象动态写入页面,以便它们可以在UpdatePanel中使用。如果你想要他们的代码,给我留言。为了解决上述问题,需要通过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对象,请检查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

如果您想上传文件,只需通过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);