代码之家  ›  专栏  ›  技术社区  ›  BrynJ

flex 3-如何支持HTTP身份验证urlrequest?

  •  10
  • BrynJ  · 技术社区  · 16 年前

    我有一个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方面,我不太了解,尽管我已经成功地修改了上传脚本。

    [编辑] -以下是我的进度更新,基于下面的答案,尽管我仍然无法使其生效:

    谢谢你的帮助。我试过实现你的代码,但我运气不好。

    我在处理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 回复  |  直到 16 年前
        1
  •  18
  •   Stu Thompson Helter Scelter    13 年前

    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”--它只是一个占位符,用于设置任何自定义HTTP头时,urlrequest似乎需要的某些数据。如果没有它,即使一个经过适当身份验证的POST请求也会失败。

    • 显然,Flash播放器版本 0.0.11.5 完全阻止所有授权头(有关此头的详细信息 here ,所以你可能也要记住这一点。

    • 几乎可以肯定的是,您必须修改crossdomain.xml文件以适应要发送的头文件。在我的例子中,我正在使用这个,它是一个相当广泛的开放策略文件,因为它接受来自任何域的信息,所以在您的例子中,您可能希望根据您的安全意识来限制更多的内容。

    交叉域.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 swfs)测试的,所以它应该对您有用,但是我想更新我的原始帖子,以包含所有这些额外的信息,以防您遇到任何问题,因为您很可能(很遗憾)会遇到这种情况。

    希望有帮助!祝你好运。我会留意评论的。

        2
  •  3
  •   Steven Mo    15 年前

    filereference.upload()和filereference.download()方法不支持urlrequest.requestheaders参数。

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

        3
  •  2
  •   Caius Miron    12 年前

    如果您想要上传一个文件,只需要通过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);
    
        4
  •  1
  •   Leo Jweda    15 年前

    我不确定,但您是否尝试将username:password@添加到URL开头?

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

        5
  •  1
  •   Stu Thompson Helter Scelter    13 年前
    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();
    
        6
  •  0
  •   Niko Nyman David Karlsson    15 年前

    似乎相似的问题解决了 here . 我劝你也检查一下 Flexcoders post 在第一篇文章中链接到。

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

        7
  •  0
  •   Brian    15 年前

    Flash在通过HTTP请求(在浏览器和OSE之间也会发生变化)传递什么样的头文件方面非常有限。如果您让它在一个浏览器/OS上工作,请确保在另一个浏览器/OS上测试它。

    最好不要弄乱HTTP头。

    我们有同样的问题(从flash上传到picasa网络相册)并通过我们服务器上的代理发布。我们将额外的头作为post参数传递,我们的代理做了正确的事情。

        8
  •  0
  •   Anentropic    15 年前

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

    这在IE中不起作用( http://www.theregister.co.uk/2004/01/30/ms_drop_authentication_technique/ )而且似乎也不适用于铬合金。

    可能在闪存中不可用

        9
  •  0
  •   Laramie    14 年前

    下面是在部分基于工作使用ASP.NET时的解决方法 here .

    我构建了一个组件,它动态地将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;
    

    最后把饼干塞进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已经解决了这个问题,这是我最后的选择。

    推荐文章