【问题标题】:HTTP Basic Authentication with HTTPService Objects in Adobe Flex/AIR在 Adob​​e Flex/AIR 中使用 HTTPService 对象进行 HTTP 基本身份验证
【发布时间】: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();
}

【问题讨论】:

    标签: apache-flex air http-authentication httpservice


    【解决方案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 的输出是什么?
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-03-18
            • 1970-01-01
            • 1970-01-01
            • 2021-10-05
            • 2015-09-07
            • 2017-05-25
            • 1970-01-01
            相关资源
            最近更新 更多