31

我正在尝试从 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();
}
4

8 回答 8

13

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

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

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

于 2009-02-11T22:35:30.913 回答
9

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

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

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

所以我揭开了真相。(我认为)它比想象的更折磨

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

2/ 所有具有非内容类型的HTTP GET请求application/x-www-form-urlencoded都变成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/ 至关重要。这浪费了我很多时间。

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

希望这可以帮助某人。

于 2009-09-15T03:52:57.410 回答
1

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();
}

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

于 2009-01-29T14:46:53.710 回答
1

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

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

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

    sfWS.httpHeaders = {Authorization:"Basic " + encoder.toString()};   
于 2009-10-13T13:01:57.087 回答
1

我在使用 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));
于 2011-01-14T21:43:44.117 回答
0

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

于 2009-01-29T09:03:56.793 回答
0

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

        import mx.utils.Base64Encoder;

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

于 2009-03-08T01:36:00.833 回答
0

这就是它的完成方式。

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()}; 
于 2010-12-21T20:50:47.317 回答