在 Adob​​e Flex/AIR 中使用 HTTPService 对象进行 HTTP 基本身份验证

Posted

技术标签:

【中文标题】在 Adob​​e Flex/AIR 中使用 HTTPService 对象进行 HTTP 基本身份验证【英文标题】:HTTP Basic Authentication with HTTPService Objects in Adobe Flex/AIR 【发布时间】:2010-10-04 04:45:18 【问题描述】:

我正在尝试从 Adob​​e AIR 应用程序中请求需要基本授权标头的 HTTP 资源。我尝试手动将标头添加到请求中,以及使用 setRemoteCredentials() 方法设置它们,但无济于事。

代码如下:

<mx:Script>
    <![CDATA[
        import mx.rpc.events.ResultEvent;
        import mx.rpc.events.FaultEvent;

        private function authAndSend(service:HTTPService):void
        
            service.setRemoteCredentials('someusername', 'somepassword');
            service.send();
        

        private function resultHandler(event:ResultEvent):void
        
            apiResult.text = event.result.toString();
        

        private function resultFailed(event:FaultEvent):void
        
            apiResult.text = event.fault.toString();
        
    ]]>
</mx:Script>

<mx:HTTPService id="apiService"
    url="https://mywebservice.com/someFileThatRequiresBasicAuth.xml"
    resultFormat="text"
    result="resultHandler(event)"
    fault="resultFailed(event)" />

<mx:Button id="apiButton"
    label="Test API Command"
    click="authAndSend(apiService)" />

<mx:TextArea id="apiResult" />

但是,仍然会弹出一个标准的基本身份验证对话框,提示用户输入用户名和密码。我感觉我的做法不对,但我能找到的所有信息(Flex 文档、博客、Google 等)要么没有用,要么太模糊,无法提供帮助。

任何黑魔法,哦,Flex 大师?谢谢。


编辑:将 setRemoteCredentials() 更改为 setCredentials() 会产生以下 ActionScript 错误:

[MessagingError message='Authentication not supported on DirectHTTPChannel (no proxy).']

编辑:经过 Adob​​e 的关注,问题解决了。有关完整说明,请参阅下面的帖子。此代码适用于任意长度的 HTTP 身份验证标头。

import mx.utils.Base64Encoder;
private function authAndSend(service:HTTPService):void

        var encoder:Base64Encoder = new Base64Encoder();
        encoder.insertNewLines = false; // see below for why you need to do this
        encoder.encode("someusername:somepassword");

        service.headers = Authorization:"Basic " + encoder.toString();                                                
        service.send();

【问题讨论】:

【参考方案1】:

终于得到了Adobe的关注并得到了答复。长 HTTP 身份验证标头的问题在于,默认情况下,Base64Encoder 类将每 72 个字符注入换行符。显然,这会导致一段 base-64 编码字符串被解释为新的标头属性,从而导致错误。

您可以通过设置(在上面的示例中)encoder.insertNewLines = false; 来解决此问题,默认设置为 true。

我已将上述代码修复为适用于任意长度的身份验证字符串。

【讨论】:

哇,谈论一个非常可怕的默认值。这垃圾是谁写的!?【参考方案2】:

我在使用 HTTP Basic Authenticated Webservice 时遇到了同样的问题。这是我的解决方案;它工作正常:

private function authAndSend(service:WebService):void

    var encoder:Base64Encoder = new Base64Encoder();
        encoder.insertNewLines = false; 
        encoder.encode("user:password");
    service.httpHeaders =  Authorization:"Basic " + encoder.ToString() ;
    service.initialize();

用法

authAndSend(WebService( aWebServiceWrapper.serviceControl));

【讨论】:

【参考方案3】:

这就是它的完成方式。

import mx.utils.Base64Encoder;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.http.HTTPService;

var _oHttp:HTTPService = new HTTPService;
var sUsername:String = "theusername"
var sPassword:String = "thepassword";

var oEncoder:Base64Encoder = new Base64Encoder(); 
oEncoder.insertNewLines = false; 
oEncoder.encode(sUsername + ":" + sPassword); 

_oHttp.method = "POST";
_oHttp.headers = Authorization:"Basic " + oEncoder.toString(); 

【讨论】:

【参考方案4】:

这真的帮助了我!谢谢! 我使用 Flex Builder 3

注意:WebService 的属性标头是只读的。 所以我尝试使用httpHeaders。有效!

    var encoder:Base64Encoder = new Base64Encoder();
    encoder.insertNewLines = false;
    encoder.encode("test:test");

    sfWS.httpHeaders = Authorization:"Basic " + encoder.toString();   

【讨论】:

【参考方案5】:

啊。痛苦,苦难。纯粹的苦难。

虽然您已经知道如何在拨打电话之前添加标头,但令人讨厌的事实是,在 Flash/浏览器集成空间的深处,您的标头再次被删除。

来自我去年verveguy.blogspot.com的博文

所以我揭开了真相。 (我想) 比想象中还要折磨

1/ 所有 HTTP GET 请求都被剥离了标头。它不在 Flex 堆栈中,因此它可能是底层 Flash 播放器运行时

2/所有内容类型不是application/x-www-form-urlencoded的HTTP GET请求都变成POST请求

3/ 所有没有实际发布数据的 HTTP POST 请求都将转换为 GET 请求。见 1/ 和 2/

4/ 所有 HTTP PUT 和 HTTP DELETE 请求都转换为 POST 请求。这似乎是 Flash 播放器所坚持的浏览器限制。 (?)

这实际上归结为,如果您想在所有请求中传递标头,您应该始终使用 POST,并且您应该找到另一种方式来传达您“真正想要”的操作的语义。 Rails 社区已决定通过 ?_method=PUT/DELETE 作为解决 4/ 底层浏览器问题的解决方法

由于 Flash 在 GET 上添加了美妙的标题剥离痛苦,我也使用?_method=GET 作为解决方法。然而,由于这在 3/ 时触发, 我将一个虚拟对象作为编码的 POST 数据传递。这意味着我的服务需要忽略 ?_method=GET 请求中的虚拟发布数据。

此时了解 2/ 至关重要。这浪费了我很多时间。

我已将所有这些处理构建到一个新的 RESTService 类中,并支持 MXML 标记,因此可以假装它在客户端不存在。

希望这对某人有所帮助。

【讨论】:

【参考方案6】:

另外,为了让其他人不用花 10 分钟时间弄清楚为什么 correct example 不能正常工作,您需要导入 mx.utils.Base64Encoder 包,例如:

        import mx.utils.Base64Encoder;

在 CDATA 区域的开头或某处。我是 flex 新手,所以一开始这并不是很明显。

【讨论】:

好收获。我已经更新了问题中的代码以反映缺少的导入,谢谢!【参考方案7】:

setCredentials() 和 setRemoteCredentials() 方法旨在用于 Flex/LiveCycle 数据服务,因此它们可能不适用于您的情况。

这应该对你有用。我能够在我的服务器上重现这种行为,而且这个修复似乎成功了;考虑到您认为它是多么常见的用例,这似乎仍然有点奇怪,这不是对 API 用户更友好,但尽管如此,在给定有效的 SSL 证书的情况下,我已经测试并验证了它的工作原理:

private function authAndSend(service:HTTPService):void

        var encoder:Base64Encoder = new Base64Encoder();
        encoder.encode("someusername:somepassword");

        service.headers = Authorization:"Basic " + encoder.toString();                            
        service.send();

希望对您有所帮助!感谢您的发帖——我相信我自己迟早会遇到这个。 ;)

【讨论】:

啊,谢谢,这更有意义。我仍然有问题,因为这段代码给了我一个“错误 #2096:HTTP 请求标头基本 无法通过 ActionScript 设置”。这与 Adob​​e 将 Authorization 标头列入黑名单有关吗?这应该不会影响 AIR 应用程序,对吧? 换句话说,我是否需要促使 Web 服务提供商创建一个 crossdomain.xml 文件? 我不知道,不——您使用的是 AIR 1.5,对吗?我使用 AIR 1.5 + Flex 3.2 和您的相同源测试了上述内容,只是使用我自己的 uid/pwd、XML 和 SSL 证书的路径。没有任何问题。您是什么意思“Adobe blacklinting Auth 标头”? 是的,AIR 1.5/Flex 3.2。我像您一样设置了自己的测试环境,并且运行良好。我切换到实时 API 并且它中断了。看来我需要与网络服务提供商交谈并了解发生了什么。不过,您的代码效果很好。谢谢! 嗨,我遇到了类似的问题,我试过了,仍然得到“401 - 此请求需要 HTTP 身份验证()”还有什么可能丢失?【参考方案8】:

尝试使用 setCredentials 而不是 setRemoteCredentials,如果失败,请使用 Fiddler/Charles 找出随请求发送的标头。

【讨论】:

fiddler/charles 的输出是什么?

以上是关于在 Adob​​e Flex/AIR 中使用 HTTPService 对象进行 HTTP 基本身份验证的主要内容,如果未能解决你的问题,请参考以下文章

Adobe Flex/AIR Maven 集成

Flex AIR 编译错误访问未定义属性

iOS UITableView 类似 Flex Air 的 Sticky Header Index 列表

Flex AIR编译未定义属性的错误访问

Flex / Air混淆[关闭]

从 flex (air) 将文档与 OpenOffice 合并