我正在尝试从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大师?感谢。
编辑:将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();
}
答案 0 :(得分:13)
最后得到了Adobe的一些关注并得到了答案。长HTTP身份验证标头的问题是,默认情况下,Base64Encoder类将每72个字符注入换行符。显然,这会导致base-64编码字符串的一大块被解释为新的标头属性,从而导致错误。
您可以通过设置(在上面的示例中)encoder.insertNewLines = false来解决此问题。默认设置为true。
我已修复上述代码以适用于任意长的身份验证字符串。
答案 1 :(得分:9)
阿。痛苦,痛苦。纯粹的苦难。
虽然您已经想出如何在拨打电话之前添加标头,但令人讨厌的事实是,在Flash /浏览器集成空间的某个地方,您的标题会被重新删除。
的博文中所以我揭开了真相。 (我认为) 它比人们想象的更痛苦
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 /。这浪费了我一大堆时间。
我已经将所有这些处理构建到一个支持MXML标记的新RESTService类中,因此可以假装它在客户端不存在。
希望这有助于某人。
答案 2 :(得分:1)
setCredentials()&amp; setRemoteCredentials()方法适用于Flex / LiveCycle Data Services,因此它们可能不适用于您的情况。
这应该对你有用。我能够在我的服务器上重现这种行为,而这个修复似乎已经成功了;看起来有点奇怪这不是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();
}
希望它有所帮助!感谢发帖 - 我相信我迟早会遇到这个问题。 ;)
答案 3 :(得分:1)
这对我有帮助!谢谢! 我使用Flex Builder 3
一个注意事项:WebService的属性头是只读的。 所以我尝试使用httpHeaders。它有效!
var encoder:Base64Encoder = new Base64Encoder();
encoder.insertNewLines = false;
encoder.encode("test:test");
sfWS.httpHeaders = {Authorization:"Basic " + encoder.toString()};
答案 4 :(得分:1)
我在使用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));
答案 5 :(得分:0)
尝试使用setCredentials而不是setRemoteCredentials并使其失败,使用Fiddler / Charles查找与请求一起发送的标头。
答案 6 :(得分:0)
另外,为了让其他人花费10分钟来解决为什么correct example不能正常工作,你需要导入mx.utils.Base64Encoder包,例如:
import mx.utils.Base64Encoder;
CDATA区域的开头或某处。我刚开始弯曲,所以一开始并不是很明显。
答案 7 :(得分: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()};