2009-10-28 43 views
6

我将尽可能详细和详尽,并包括我使用的一些代码。我已经做了搜索,发现this question,这看起来很相似;然而作者那里使用的是ActionScript 2而不是3,而且我似乎无法有效地应用任何给予我自己情况的答案。如何解决这个跨域ActionScript 3错误?

我想通过Flash/ActionScript 3来模拟(通过有限的方式)JavaScript的XMLHttpRequest对象的行为,以克服相同的域限制。但我发现ActionScript在这方面有其自身的局限性。我承认我可能弄错了,但根据我的理解,只要您获得所有权限,理论上仍然可以使用ActionScript执行这种跨域脚本编写。这就是我遇到麻烦的地方。

首先,我借用了一些名为AjaxRequest的开源代码,我保存为/ajax/AjaxRequest.as。然后我创建了一个名为/jsajax.fla的Flash文件,该文件导出到最终的SWF文件/jsajax.swf。现在,这里是包含Flash文件的第一帧也是唯一帧的ActionScript代码:

import ajax.AjaxRequest; 
Security.allowDomain("domainone.com"); 
Security.allowDomain("domaintwo.com"); 

function jsAjax(stringURL:String, stringMethod:String, stringData:String):void 
{ 
    var xhr:AjaxRequest = new AjaxRequest(stringURL); 
    xhr.contentType = "application/x-www-form-urlencoded"; 
    xhr.dataFormat = URLLoaderDataFormat.TEXT; 

    if (stringMethod.toUpperCase() == "POST") { 
     xhr.method = URLRequestMethod.POST; 
    } else { 
     xhr.method = URLRequestMethod.GET; 
    } 

    xhr.addEventListener("complete", jsAjaxResponse); 
    xhr.send(stringData); 
    return; 
} 

function jsAjaxResponse(evt:Event):void 
{ 
    ExternalInterface.call("jsAjaxResponse", evt.currentTarget.data.toString()); 
    return; 
} 

ExternalInterface.addCallback("jsAjax", jsAjax); 
ExternalInterface.call("jsAjaxReady"); 

到目前为止这样好。我有一种感觉,其中一个或多个Security.allowDomain调用不需要,但他们是我尝试解决此问题的尝试(不成功)。

在我的JavaScript中,我定义了三个函数:jsAjax,jsAjaxResponsejsAjaxReady。最后一个只是一个非常基本的函数,用于指示Flash对象成功加载(在加载它时只调用一次并立即调用),另外两个用于发送和接收数据。如您所见,它们具有相应的ActionScript对应项。

最后,我创建了一个名为/test.html一个简单的HTML页面嵌入该SWF文件(使用swfobject),并具有用于调用jsAjax功能的几个简单的表单控件。我所有的JavaScript定义都嵌入在这个HTML文件中。我还创建了一个名为/test.php的非常简单的PHP脚本,它打印出$_REQUEST数组的内容。这就是我打算用这个ajax方法请求的脚本。

有迹象表明,我测试了三种情形,但我只能得到其中的两个工作:


场景一:所有的一台服务器
。如果我上传所有这些文件到domainone.com,然后请求test.php,它工作正常。然后我的文件/文件夹结构如下:

domainone.com/jsajax.swf 
domainone.com/test.html 
domainone.com/test.php 

再次,这个工程。 jsAjaxResponse函数很好地接收来自test.php的数据。


方案二:在两台服务器上,扶着左
当我上传的HTML和SWF到第一台服务器,然后就使用它调用PHP脚本的第二个服务器上,它没有马上工作。我做了一些挖掘,发现通过在domaintwo.com上创建一个允许访问domainone.com的crossdomain.xml文件,可以解决这个问题。所以,我的文件/文件夹结构是这样的:

domainone.com/jsajax.swf 
domainone.com/test.html 
domaintwo.com/test.php 
domaintwo.com/crossdomain.xml 

当明确允许domainone.com在crossdomain.xml文件,这个工程。再次,jsAjaxResponse函数接收来自test.php的数据就好了。


方案三:在两台服务器上,扶着右
当我上传的所有,但HTML到domaintwo.com,我再也无法得到它的工作。换句话说,domainone.com上的HTML引用了domaintwo.com上托管的SWF文件,并且该SWF文件正试图向domaintwo.com发出请求。以防万一,我从方案2中保留了相同的crossdomain.xml文件。我的文件/文件夹结构是这样的:

domainone.com/test.html 
domaintwo.com/jsajax.swf 
domaintwo.com/test.php 
domaintwo.com/crossdomain.xml 

这是我不能获得工作的唯一案例,这是我需要工作的情况。前两个实际上只是测试场景,以查看脚本是否工作。当我试图在这里经营我jsAjax功能,我在Firebug风与显示了一个错误两次:

uncaught exception: Error calling method on NPObject! [plugin exception: Error in Actionscript. Use a try/catch block to find error.]. 
uncaught exception: Error calling method on NPObject! [plugin exception: Error in Actionscript. Use a try/catch block to find error.]. 

帮助!我如何在场景3中使用它?

回答

4

我只是想通了!它的确与我的Flash文件中的Security.allowDomain命令有关。我实际上是在domainone.com的一个子域上托管test.html,并且正在抛弃它。它必须是完全匹配,子域和全部。事实证明,我并不需要引用domaintwo.com的Security.allowDomain命令,也不需要为场景3提供crossdomain.xml文件!

因为在这个脚本,我最终使用的“真实”的版本,我不一定会知道什么domainone.com实际上是,我改变了代码的Flash文件的顶部,这样的:

import ajax.AjaxRequest; 
try { 
    var domain1:String = LoaderInfo(this.root.loaderInfo).parameters["allow"]; 
    if (domain1.length > 0) { 
     Security.allowDomain(domain1); 
    } 
} catch (error:Error) { } 
try { 
    var domain2:String = LoaderInfo(this.root.loaderInfo).parameters["allowhttps"]; 
    if (domain2.length > 0) { 
     Security.allowInsecureDomain(domain2); 
    } 
} catch (error:Error) { } 
... 

然后,在我用来在其中嵌入SWF的JavaScript中,我基本上从document.location.toString()获取页面的当前域,检查它是使用http还是https,然后将域作为flashvars参数中的allow和/或allowhttps。可能有一种“更好”的方式来做到这一点,它不依赖于在Flash Vars中明确地设置域(Flash中的某种自动检测),但我并不熟悉ActionScript,出。由于这个文件已经在JavaScript和ActionScript之间进行了大量的双向通信,这并不是什么大不了的事情。这个解决方案对我来说已经足够了。