jQuery AJAX 跨域

IT技术 javascript jquery ajax json cross-domain
2020-12-10 16:22:04

这里有两个页面,test.php 和 testserver.php。

测试.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>

测试服务器.php

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

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

6个回答

使用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");
     }      
});

PHP:

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

回声可能是错误的,自从我使用 php 以来已经有一段时间了。在任何情况下,您都需要输出callbackName('jsonString')通知引号。jQuery 将传递它自己的回调名称,因此您需要从 GET 参数中获取该名称。

正如 Stefan Kendall 发布的那样,$.getJSON()是一种速记方法,但随后您需要将'callback=?'其作为 GET 参数附加到 url(是的,值是 ?,jQuery 将其替换为自己生成的回调方法)。

我收到以下错误。语法错误:缺少;在语句 {"ResultCode":2} 之前。其中 {"ResultCode":2} 是响应。请指教。
2021-02-19 16:22:04
为什么你需要返回callbackName('/* json */')而不是callbackName(/* json */)
2021-02-22 16:22:04
@eric 回调需要一个 JSON 字符串。理论上,一个对象可能也能工作,但不确定 jQuery 如何对此做出响应,它可能会抛出错误或静默失败。
2021-02-27 16:22:04
现在是 2016 年。 CORS 现在是一个得到广泛支持的标准,与 JSONP 不同,后者只能被描述为 hack。下面@joshuarh 的答案现在应该是首选。
2021-03-03 16:22:04
@user2003356 看起来您返回的是纯 JSON 而不是 JSONP。你需要返回类似的东西:callbackFunction({"ResultCode":2})。jQuery 将 GET 参数“回调”添加到请求中,这是 jquery 使用的回调函数的名称,应该添加到响应中。
2021-03-05 16:22:04

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

在此示例中,该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

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

最好只允许那些您想与之共享数据的域,而不是使用通配符“*”。
2021-02-14 16:22:04
在 PHP header("Access-Control-Allow-Origin: *");
2021-02-22 16:22:04
以这种方式配置服务器的安全隐患是什么?
2021-02-28 16:22:04
Jsonp 不支持 post、put 和 delete。您的解决方案效果很好。
2021-03-02 16:22:04
@Warrior 如果您使用 jQuery 的.post()方法,则必须在 jQuery 中启用跨域支持。它是这样完成的:$.support.cors = true
2021-03-06 16:22:04

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

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

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

不要忘记在 httpd.conf 中启用 mod_headers module。

您需要查看同源政策

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

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

相同的协议和主机

您需要实现JSONP来解决它。

我必须从本地磁盘“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 文档了。其他浏览器我没有测试。
  • 响应文档可以是纯文本、xml、json 或其他任何内容

这是带有一些调试系统输出的示例 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);
    }
});
对于最重要的一点:在 PHP 中,将此行添加到脚本中: header("Access-Control-Allow-Origin: *");
2021-02-14 16:22:04
我在这里为这个问题写了一个答案:Loading cross domain html page with jQuery AJAX最后一个,支持 https
2021-03-04 16:22:04
@whohome 非常感谢您的回答。你帮了我很多。干杯。
2021-03-04 16:22:04