jQuery AJAX跨域

Fir*_*ain 468 javascript ajax jquery json cross-domain

这是两个页面,test.php和testserver.php.

test.php的

<script src="scripts/jq.js" type="text/javascript"></script>
<script>
    $(function() {
        $.ajax({url:"testserver.php",
            success:function() {
                alert("Success");
            },
            error:function() {
                alert("Error");
            },
            dataType:"json",
            type:"get"
        }
    )})
</script>
Run Code Online (Sandbox Code Playgroud)

testserver.php

<?php
$arr = array("element1",
             "element2",
             array("element31","element32"));
$arr['name'] = "response";
echo json_encode($arr);
?>
Run Code Online (Sandbox Code Playgroud)

现在我的问题是:当这两个文件都在同一台服务器(localhost或web服务器)上时,它可以工作并被alert("Success")调用; 如果它位于不同的服务器上,意味着Web服务器上的testserver.php和localhost上的test.php,它就无法工作,并且alert("Error")正在执行.即使ajax中的URL更改为http://domain.com/path/to/file/testserver.php

BGe*_*sen 409

使用JSONP.

jQuery的:

$.ajax({
     url:"testserver.php",
     dataType: 'jsonp', // Notice! JSONP <-- P (lowercase)
     success:function(json){
         // do stuff with json (in this case an array)
         alert("Success");
     },
     error:function(){
         alert("Error");
     }      
});
Run Code Online (Sandbox Code Playgroud)

PHP:

<?php
$arr = array("element1","element2",array("element31","element32"));
$arr['name'] = "response";
echo $_GET['callback']."(".json_encode($arr).");";
?>
Run Code Online (Sandbox Code Playgroud)

回声可能是错的,自从我使用php以来已经有一段时间了.无论如何,您需要输出callbackName('jsonString')通知报价.jQuery将传递它自己的回调名称,因此你需要从GET参数中获取它.

正如Stefan Kendall 所说,$ .getJSON()是一种速记方法,但是你需要将'callback=?'它作为GET参数附加到url(是的,值是?,jQuery用它自己生成的回调方法替换它).

  • @eric回调需要一个JSON字符串.从理论上讲,一个对象可能也可以正常工作,但不确定jQuery如何响应它,它可能会抛出错误或无声地失败. (3认同)
  • 为什么需要返回`callbackName('/*json*/')`而不是`callbackName(/*json*/)`? (2认同)
  • 现在是2016年。CORS现在是一种广泛支持的标准,与JSONP(只能描述为黑客)相对。现在,@ joshuarh的答案应该是首选。 (2认同)

jos*_*arh 200

JSONP是一个不错的选择,但有一种更简单的方法.您只需Access-Control-Allow-Origin在服务器上设置标头即可.将其设置为*将接受来自任何域的跨域AJAX请求.(https://developer.mozilla.org/en/http_access_control)

当然,执行此操作的方法因语言而异.这是在Rails中:

class HelloController < ApplicationController
  def say_hello
    headers['Access-Control-Allow-Origin'] = "*"
    render text: "hello!"
  end
end
Run Code Online (Sandbox Code Playgroud)

在此示例中,say_hello操作将接受来自任何域的AJAX请求并返回"hello!"的响应.

以下是可能返回的标头示例:

HTTP/1.1 200 OK 
Access-Control-Allow-Origin: *
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Type: text/html; charset=utf-8
X-Ua-Compatible: IE=Edge
Etag: "c4ca4238a0b923820dcc509a6f75849b"
X-Runtime: 0.913606
Content-Length: 6
Server: WEBrick/1.3.1 (Ruby/1.9.2/2011-07-09)
Date: Thu, 01 Mar 2012 20:44:28 GMT
Connection: Keep-Alive
Run Code Online (Sandbox Code Playgroud)

虽然很容易,但它确实有一些浏览器限制.请参阅http://caniuse.com/#feat=cors.

  • 在PHP标题中("Access-Control-Allow-Origin:*"); (35认同)
  • 以这种方式配置服务器有什么安全隐患? (20认同)
  • 最好只允许那些您想要共享数据的域而不是使用wilcard"*". (18认同)
  • Jsonp不支持post,put和delete.您的解决方案很有效. (12认同)
  • @Warrior如果你正在使用jQuery的`.post()`方法,你必须在jQuery中启用跨域支持.它完成了:`$ .support.cors = true`. (9认同)
  • 只是懒得不将特定域列入白名单,而是允许从所有域访问..​​. (6认同)
  • 仅供参考 - 官方名称为'CORS'(跨源资源共享).更多信息:http://en.wikipedia.org/wiki/Cross-origin_resource_sharing (4认同)
  • @JonSchneider这种方法的问题(只允许带*的任何来源)是任何恶意页面都可以捕获该服务器上的用户信息.Gmail曾经遇到过这个问题.它无意中泄露了用户的联系人列表. (4认同)

Ado*_*ncz 31

您可以通过添加Access-Control-Allow-Origin来通过HTTP标头控制此操作.将其设置为*将接受来自任何域的跨域AJAX请求.

使用PHP非常简单,只需将以下行添加到您希望从域外访问的脚本中:

header("Access-Control-Allow-Origin: *");
Run Code Online (Sandbox Code Playgroud)

不要忘记在httpd.conf中启用mod_headers模块.


Sar*_*raz 19

您需要查看同源策略:

在计算中,相同的源策略是许多浏览器端编程语言(如JavaScript)的重要安全概念.该策略允许在源自同一站点的页面上运行的脚本在没有特定限制的情况下访问彼此的方法和属性,但阻止访问不同站点上的页面上的大多数方法和属性.

为了能够获取数据,它必须是:

相同的协议和主机

您需要实现JSONP来解决它.


Who*_*ome 16

我不得不从本地磁盘"file:/// C:/test/htmlpage.html"加载网页,调用"http://localhost/getxml.php"url,并在IE8 +和Firefox12 +浏览器中执行此操作,使用jQuery v1 .7.2 lib最小化样板代码.看了几十篇文章后终于搞清楚了.这是我的总结.

  • 服务器脚本(.php,.jsp,...)必须返回http响应头Access-Control-Allow-Origin:*
  • 在使用jQuery之前,ajax在javascript中设置了这个标志:jQuery.support.cors = true;
  • 你可以在使用jQuery ajax函数之前设置一次或每次标记
  • 现在我可以在IE和Firefox中阅读.xml文档了.其他浏览器我没有测试.
  • 响应文档可以是plain/text,xml,json或其他任何内容

这是一个带有一些调试sysout的jQuery ajax调用示例.

jQuery.support.cors = true;
$.ajax({
    url: "http://localhost/getxml.php",
    data: { "id":"doc1", "rows":"100" },
    type: "GET",
    timeout: 30000,
    dataType: "text", // "xml", "json"
    success: function(data) {
        // show text reply as-is (debug)
        alert(data);

        // show xml field values (debug)
        //alert( $(data).find("title").text() );

        // loop JSON array (debug)
        //var str="";
        //$.each(data.items, function(i,item) {
        //  str += item.title + "\n";
        //});
        //alert(str);
    },
    error: function(jqXHR, textStatus, ex) {
        alert(textStatus + "," + ex + "," + jqXHR.responseText);
    }
});
Run Code Online (Sandbox Code Playgroud)


Jas*_*son 10

确实,同源策略阻止JavaScript跨域发出请求,但CORS规范只允许您正在寻找的那种API访问,并且受当前批量主流浏览器的支持.

了解如何为客户端和服务器启用跨源资源共享:

http://enable-cors.org/

"跨域资源共享(CORS)是一种规范,可以实现跨域边界的真正开放访问.如果您提供公共内容,请考虑使用CORS打开它以进行通用JavaScript /浏览器访问."


Pau*_*ber 9

这是可能的,但您需要使用JSONP,而不是JSON.斯特凡的链接指向了正确的方向.在jQuery的AJAX页面对JSONP的更多信息.

Remy Sharp有一个使用PHP详细示例.


zen*_*nio 9

我使用Apache服务器,所以我使用了mod_proxy模块.启用模块:

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
Run Code Online (Sandbox Code Playgroud)

然后加:

ProxyPass /your-proxy-url/ http://service-url:serviceport/
Run Code Online (Sandbox Code Playgroud)

最后,将proxy-url传递给您的脚本.


Jac*_*son 8

浏览器安全性阻止从托管在一个域上的页面到托管在不同域上的页面进行ajax调用; 这被称为" 同源政策 ".


Bil*_*Tom 5

使用JSONP的例子很少,包括错误处理.

但请注意,使用JSONP时不会触发错误事件!请参阅:http://api.jquery.com/jQuery.ajax/使用jsonp错误的jQuery ajax请求