Adobe Flex/AIR中使用HTTPService对象的HTTP基本身份验证

tez616oj  于 2022-09-21  发布在  Apache
关注(0)|答案(8)|浏览(197)

我正在尝试从Adobe 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文档、博客、谷歌等)要么没有奏效,要么含糊其辞,不愿提供帮助。

有黑魔法吗,哦,Flex Gurus?谢谢。

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

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

**编辑:**问题解决,Adobe关注后。有关完整的解释,请参阅下面的帖子。此代码将适用于任意长度的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();
}
k5ifujac

k5ifujac1#

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

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

我已经修复了上面的代码,使其可以处理任意长度的身份验证字符串。

zaqlnxep

zaqlnxep2#

阿。痛苦,痛苦。彻头彻尾的痛苦。

虽然您已经了解了如何在调用之前添加标题,但令人不快的事实是,在Flash/浏览器集成空间的深处,您的标题再次被删除。

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

所以我揭开了真相。(我认为)这比人们想象的更痛苦

1/所有的HTTP GET请求都会去掉头部。它不在Flex堆栈中,因此很可能是底层的Flash Player运行时

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/至关重要。这浪费了我很多时间。

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

希望这能帮到什么人。

vm0i2vca

vm0i2vca3#

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

希望它能帮上忙!感谢你的帖子--我相信我自己迟早也会遇到这一点。;)

ddarikpa

ddarikpa4#

这对我真的很有帮助!谢谢!我使用Flex Builder 3

注意:WebService的属性标头是只读的。因此,我尝试使用HTTPHeaders。它起作用了!

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

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

m0rkklqb5#

在使用经过HTTP基本身份验证的Web服务时,我也遇到了同样的问题。这是我的解决方案;它工作得很好:

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));
wlsrxk51

wlsrxk516#

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

nr9pn0ug

nr9pn0ug7#

另外,为了不让其他人花10分钟弄清楚为什么正确的示例不能很好地用于ASIS,您需要导入mx.utils.Base64Encode包,例如:

import mx.utils.Base64Encoder;

在CDATA区域的开头或某个位置。我刚接触FLEX,所以这一点一开始并不是很明显。

bn31dyow

bn31dyow8#

这就是它是怎么做的。

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

相关问题