Flex 3 - 如何支持 HTTP Authentication URLRequest?

Posted

技术标签:

【中文标题】Flex 3 - 如何支持 HTTP Authentication URLRequest?【英文标题】:Flex 3 - how to support HTTP Authentication URLRequest? 【发布时间】:2010-10-05 06:50:25 【问题描述】:

我有一个 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 应该放在哪里 - 因为我目前没有,也不确定放在哪里。

【问题讨论】:

crossdomain.xml 应该放在您的 Web 应用程序的根目录中。因此,如果构成 www.yoursite.com 的文件位于 D:\websites\yoursite.com,则文件的路径应为 d:\websites\yoursite.com\crossdomain.xml。 除了放置您的 corssdomain.xml 文件(您应该这样做)之外,您是否知道您安装了哪个 Flash 播放器版本?您确定您使用的是 Flash Player 10 吗? (看起来我的发现是 Flash Player 9 不能很好地使用自定义授权标头。) 感谢您的帮助 Christian - 不幸的是,我没有机会进一步测试(已经被另一个项目淹没了)但我会尝试一个我有机会的。 随时!希望它对你有用。 【参考方案1】:

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 完全阻止了所有 Authorization 标头(有关此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)测试的,所以它应该适合你,但我想更新我的原始帖子以包含所有这些额外的信息,以防你遇到任何问题,因为您似乎(可悲地)很有可能会这样做。

希望对您有所帮助!祝你好运。我会留意 cmets。

【讨论】:

对同一件事的建议音调,但唯一真正有效的答案适用于使用 sdk 4.6 的简单 flex 应用程序。非常感谢。【参考方案2】:

我不确定这一点,但您是否尝试将 username:password@ 添加到您的网址的开头?

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

【讨论】:

使用这似乎是使用 GET 请求发送授权信息的唯一方法 显然这是一个旧线程,但只是把它扔在那里,这种添加 username:password@... 的方法对我有用,而添加 Basic Auth 标头在我的 AIR 应用程序中不显示身份验证对话框的情况下不起作用.【参考方案3】:

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

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

【讨论】:

我也确实遇到了这个会话问题,并提出了类似的解决方案,但这不是这里面临的问题 - 具体来说是 HTTP 身份验证(与会话无关)。【参考方案4】:

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

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

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

【讨论】:

【参考方案5】:
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();

【讨论】:

大家好,感谢您的想法,我设法想出了使用 HTTPService 而不是 URLRequest 的技巧。我所做的只是通过 service.request 添加变量,并设置 service.method = 'POST' 希望有帮助!!! :)【参考方案6】:

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

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

【讨论】:

【参考方案7】:

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

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

可能无法在 Flash 中使用

【讨论】:

【参考方案8】:

这是使用 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;

最后将 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 已将该问题视为无法解决,因此这是我最后的手段。

【讨论】:

【参考方案9】:

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

【讨论】:

以上是关于Flex 3 - 如何支持 HTTP Authentication URLRequest?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不支持 flex 的浏览器中居中按钮?

Flex布局详解

如何通过扩展 mx.containers.Panel 在 flex 3 中创建具有多行标题的面板?

flex 3 http catcher

检测css“flex-box”和“flex-wrap”支持的正确方法是啥?

如何将值从 javascript 传递到嵌入式 flex 对象?