Javascript AJAX 跨域调用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2558977/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 00:55:03  来源:igfitidea点击:

AJAX cross domain call

javascriptjqueryajaxjsonjsonp

提问by jAndy

I know about AJAX cross-domain policy. So I can't just call "http://www.google.com" over a ajax HTTP request and display the results somewhere on my site.

我了解 AJAX 跨域策略。所以我不能只是通过 ajax HTTP 请求调用“ http://www.google.com”并在我网站的某处显示结果。

I tried it with dataType "jsonp", that actually would work, but I get a syntax error (obviously because the received data is not JSON formated)

我用 dataType "jsonp" 尝试过,这实际上可以工作,但出现语法错误(显然是因为接收到的数据不是 JSON 格式的)

Is there any other possiblity to receive/display data from a foreign domain? iFrames follow the same policy?

是否还有其他可能从外部域接收/显示数据?iFrame 遵循相同的政策?

回答by Tatu Ulmanen

The only (easy) way to get cross-domain data using AJAX is to use a server side language as the proxy as Andy Enoted. Here's a small sample how to implement that using jQuery:

正如Andy E指出的那样,使用 AJAX 获取跨域数据的唯一(简单)方法是使用服务器端语言作为代理。这是一个如何使用 jQuery 实现的小示例:

The jQuery part:

jQuery 部分:

$.ajax({
    url: 'proxy.php',
    type: 'POST',
    data: {
        address: 'http://www.google.com'
    },
    success: function(response) {
        // response now contains full HTML of google.com
    }
});

And the PHP (proxy.php):

和 PHP (proxy.php):

echo file_get_contents($_POST['address']);

Simple as that. Just be aware of what you can or cannot do with the scraped data.

就那么简单。请注意您可以或不能对抓取的数据做什么。

回答by alunny

You will need to dynamically insert a script tag into the page that references the data. Using JSONP, you can execute some callback function when the script has loaded.

您需要将脚本标记动态插入到引用数据的页面中。使用 JSONP,您可以在脚本加载后执行一些回调函数。

The wikipedia page on JSONPhas a concise example; the script tag:

JSONP上的维基百科页面有一个简洁的例子;脚本标签:

<script type="text/javascript" src="http://domain1.com/getjson?jsonp=parseResponse">
</script>

would return the JSON data wrapped in a call to parseResponse:

将返回包含在调用中的 JSON 数据parseResponse

parseResponse({"Name": "Cheeso", "Rank": 7})

(depending on the configuration of the getjsonscript on domain1.com)

(取决于getjsondomain1.com上脚本的配置)

The code to insert the tag dynamically would be something like:

动态插入标签的代码类似于:

var s = document.createElement("script");
s.src = "http://domain1.com/getjson?jsonp=parseResponse";
s.type = "text/javascript";
document.appendChild(s);

回答by Alexandre Vicente

You can use YQLto do the request without needing to host your own proxy. I have made a simple function to make it easier to run commands:

您可以使用YQL来执行请求,而无需托管您自己的代理。我做了一个简单的函数来更容易地运行命令:

function RunYQL(command, callback){
     callback_name = "__YQL_callback_"+(new Date()).getTime();
     window[callback_name] = callback;
     a = document.createElement('script');
     a.src = "http://query.yahooapis.com/v1/public/yql?q="
             +escape(command)+"&format=json&callback="+callback_name;
     a.type = "text/javascript";
     document.getElementsByTagName("head")[0].appendChild(a);
}

If you have jQuery, you may use $.getJSON instead.

如果你有 jQuery,你可以使用 $.getJSON 代替。

A sample may be this:

一个样本可能是这样的:

RunYQL('select * from html where url="http://www.google.com/"',
       function(data){/* actions */}
);

回答by Andy E

Unfortunately (or fortunately) not. The cross-domain policy is there for a reason, if it were easy to get around it then it wouldn't be very effective as a security measure. Other than JSONP, the only option is to proxy the pages using your own server.

不幸(或幸运)不是。跨域策略的存在是有原因的,如果它很容易绕过它,那么它作为一种安全措施就不会非常有效。除了 JSONP,唯一的选择是使用您自己的服务器代理页面

With an iframe, they are subject to the same policy. Of course you can display the data from an external domain, you just can't manipulate it.

对于 iframe,它们受相同的策略约束。当然,您可以显示来自外部域的数据,只是无法对其进行操作。

回答by R Francky

I use this code for cross domain ajax call, I hope it will help more than one here. I'm using Prototype library and you can do the same with JQuery or Dojo or anything else:

我使用这段代码进行跨域ajax调用,我希望它在这里可以帮助不止一个。我正在使用 Prototype 库,你可以用 JQuery 或 Dojo 或其他任何东西做同样的事情:

Step 1: create a new js file and put this class inside, I called it xss_ajax.js

第一步:新建一个js文件,把这个类放在里面,我叫它xss_ajax.js

var WSAjax = Class.create ({
    initialize: function (_url, _callback){
        this.url = _url ;
        this.callback = _callback ;
        this.connect () ;
    },
    connect: function (){
        var script_id = null;
        var script = document.createElement('script');
        script.setAttribute('type', 'text/javascript');
        script.setAttribute('src', this.url);
        script.setAttribute('id', 'xss_ajax_script');

        script_id = document.getElementById('xss_ajax_script');
        if(script_id){
            document.getElementsByTagName('head')[0].removeChild(script_id);
        }

        // Insert <script> into DOM
        document.getElementsByTagName('head')[0].appendChild(script);
    },
    process: function (data){
        this.callback(data) ;
    }

}) ;

This class creates a dynamic script element which src attributes targets your JSON data provider (JSON-P in fact as your distant server must provide the data in this format :: call_back_function(//json_data_here) :: so when the script tag is created your JSON will be directly evaled as a function (we'll talk about passing the callback method name to server on step 2), the main concept behind this is that script like img elements are not concerned by the SOP constraints.

此类创建一个动态脚本元素,其 src 属性针对您的 JSON 数据提供者(实际上 JSON-P,因为您的远程服务器必须以这种格式提供数据 :: call_back_function(//json_data_here) :: 因此,当创建脚本标记时,您的JSON 将直接作为函数进行评估(我们将在步骤 2 中讨论将回调方法名称传递给服务器),这背后的主要概念是像 img 元素这样的脚本不受 SOP 约束。

Step2: in any html page where you wanna pull the JSON asynchronously (we call this AJAJ ~ Asynchronous JAvascript + JSON :-) instead of AJAX which use the XHTTPRequest object) do like below

步骤 2:在任何想要异步拉取 JSON 的 html 页面中(我们称之为 AJAJ ~ Asynchronous JAvascript + JSON :-) 而不是使用 XHTTPRequest 对象的 AJAX),请执行以下操作

//load Prototype first
//load the file you've created in step1


var xss_crawler = new WSAjax (
     "http://your_json_data_provider_url?callback=xss_crawler.process"
 ,   function (_data){
            // your json data is _data and do whatever you like with it 
        }) ;

D'you remenber the callback on step 1? so we pass it to the server and it will returns the JSON embeded in that method so in our case the server will return an evalable javascript code xss_crawler.process(//the_json_data), remember that xss_crawler is an instance of WSAjax class. The server code depends on you (if it's yours), but most of Ajax data providers let you specify the callback method in parameters like we did. In Ruby on rails I just did

你记得第 1 步的回调吗?所以我们将它传递给服务器,它会返回嵌入在该方法中的 JSON,所以在我们的例子中,服务器将返回一个可评估的 javascript 代码 xss_crawler.process(//the_json_data),记住 xss_crawler 是 WSAjax 类的一个实例。服务器代码取决于您(如果它是您的),但大多数 Ajax 数据提供程序允许您像我们一样在参数中指定回调方法。在 Ruby on rails 中,我刚刚做了

render :json=>MyModel.all(:limit=>10), :callback => params[:callback],:content_type => "application/json"

and that's all, you can now pull data from another domain from your apps (widgets, maps etc), in JSON format only, don't forget.

就是这样,您现在可以从您的应用程序(小部件、地图等)的另一个域中提取数据,仅采用 JSON 格式,不要忘记。

I hope it was helpfull, thanks for your patience :-), peace and sorry for code formatting, it doesn't work well

我希望它会有所帮助,感谢您的耐心等待 :-),对代码格式感到抱歉,它不能正常工作

回答by jAndy

after doing some research, the only "solution" to this problem is to call:

在做了一些研究之后,这个问题的唯一“解决方案”是调用:

if($.browser.mozilla)
   netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');

this will ask an user if he allows a website to continue. After he confirmed that, all ajax calls regardless of it's datatype will get executed.

这将询问用户是否允许网站继续。在他确认之后,所有 ajax 调用,无论其数据类型如何,都将被执行。

This works for mozilla browsers, in IE < 8, an user has to allow a cross domain call in a similar way, some version need to get configured within browser options.

这适用于 mozilla 浏览器,在 IE < 8 中,用户必须以类似的方式允许跨域调用,某些版本需要在浏览器选项中进行配置。

chrome/safari: I didn't find a config flag for those browsers so far.

chrome/safari:到目前为止,我没有找到这些浏览器的配置标志。

using JSONP as datatype would be nice, but in my case I don't know if a domain I need to access supports data in that format.

使用 JSONP 作为数据类型会很好,但就我而言,我不知道我需要访问的域是否支持该格式的数据。

Another shot is to use HTML5 postMessage which works cross-domain aswell, but I can't afford to doom my users to HTML5 browsers.

另一个镜头是使用 HTML5 postMessage,它也可以跨域工作,但我不能让我的用户注定要使用 HTML5 浏览器。

回答by Nir

JSONP is the best option, in my opinion. Try to figure out why you get the syntax error - are you sure the received data is not JSON? Then maybe you're using the API wrong somehow.

在我看来,JSONP 是最好的选择。尝试弄清楚为什么会出现语法错误 - 您确定收到的数据不是 JSON?那么也许您以某种方式错误地使用了 API。

Another way you could use, but I don't think that it applies in your case, is have an iFrame in the page which src is in the domain you want to call. Have it do the calls for you, and then use JS to communicate between the iFrame and the page. This will bypass the cross domain, but only if you can have the iFrame's src in the domain you want to call.

您可以使用的另一种方法,但我认为它不适用于您的情况,是在页面中有一个 iFrame,其中 src 位于您要调用的域中。让它为你做调用,然后使用 JS 在 iF​​rame 和页面之间进行通信。这将绕过跨域,但前提是您可以在要调用的域中拥有 iFrame 的 src。

回答by akadi81

If you are using a php script to get the answer from the remote server, add this line at the begining:

如果您使用 php 脚本从远程服务器获取答案,请在开头添加以下行:

header("Access-Control-Allow-Origin: *");

回答by AlexTR

Here is an easy way of how you can do it, without having to use anything fancy, or even JSON.

这是一个简单的方法,您可以这样做,而无需使用任何花哨的东西,甚至 JSON。

First, create a server side script to handle your requests. Something like http://www.example.com/path/handler.php

首先,创建一个服务器端脚本来处理您的请求。类似于http://www.example.com/path/handler.php

You will call it with parameters, like this: .../handler.php?param1=12345&param2=67890

您将使用参数调用它,如下所示: .../handler.php?param1=12345¶m2=67890

Inside it, after processing the recieved data, output:

在里面,处理收到的数据后,输出

document.serverResponse('..all the data, in any format that suits you..');
// Any code could be used instead, because you dont have to encode this data
// All your output will simply be executed as normal javascript

Now, in the client side script, use the following:

现在,在客户端脚本中,使用以下内容:

document.serverResponse = function(param){ console.log(param) }

var script = document.createElement('script');
script.src='http://www.example.com/path/handler.php?param1=12345&param2=67890';
document.head.appendChild(script);

The only limit of this approach, is the max length of parameters that you can send to the server. But, you can always send multiple requests.

这种方法的唯一限制是您可以发送到服务器的参数的最大长度。但是,您始终可以发送多个请求。

回答by morhook

You can use the technology CORS to configure both servers (the server where the Javascript is running and the external API server)

您可以使用 CORS 技术来配置两个服务器(运行 Javascript 的服务器和外部 API 服务器)

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

p.s.: the answer https://stackoverflow.com/a/37384641/6505594is also suggesting this approach, and it's opening the external API server to everyone else to call it.

ps:答案https://stackoverflow.com/a/37384641/6505594也提出了这种方法,它向其他人开放了外部 API 服务器来调用它。