AJAX 跨域调用

IT技术 javascript jquery ajax json jsonp
2021-01-12 19:03:43

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

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

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

6个回答

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

jQuery 部分:

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

和 PHP (proxy.php):

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

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

并且要非常清楚这样的代理是一个严重的安全漏洞...至少列出可接受的地址列表,不要盲目接受任何通过的地址。在这里查看一个不错的代理脚本:benalman.com/projects/php-simple-proxy
2021-03-15 19:03:43
但是当目标页面有非绝对 URL 和相对链接时,它不会破坏布局吗?
2021-04-03 19:03:43
@ChristianStuder 为什么这有问题?
2021-04-03 19:03:43

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

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

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

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

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

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

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

var s = document.createElement("script");
s.src = "http://domain1.com/getjson?jsonp=parseResponse";
s.type = "text/javascript";
document.appendChild(s);
仅适用于 GET 请求。没有 PUT、DELETE 或 POST。所以没有RESTful接口。
2021-03-11 19:03:43
这仅在您收到 JSON 数据或纯文本或 HTML 时才有效吗?
2021-03-17 19:03:43
@jAndy:这仅适用于 JSONP(包括回调函数)数据。
2021-03-23 19:03:43

您可以使用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);
}

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

一个样本可能是这样的:

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

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

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

@jAndy:不,在跨不同域访问文档时,对 99% 的 DOM 的访问被阻止。跨文档消息传递是可能的(使用 HTML5/现代浏览器),但必须由双方实施。
2021-03-10 19:03:43
你是什​​么意思,“你就是不能操纵它”?例如,您不能将一些数据加载到 iFrame 并通过 jQuery 选择器读取该数据?
2021-03-22 19:03:43

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

第一步:新建一个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) ;
    }

}) ;

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

步骤 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 
        }) ;

你记得第 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"

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

我希望它有帮助,感谢您的耐心 :-),对于代码格式的和平和抱歉,它不能正常工作