jQuery AJAX 跨域

jQuery AJAX cross domain

提问人:Firose Hussain 提问时间:8/18/2010 最后编辑:Stephen OstermillerFirose Hussain 更新时间:12/6/2022 访问量:818671

问:

这里有两个页面,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);
?>

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

javascript jquery ajax json 跨域

评论

38赞 Abdul Munim 8/2/2012
对于停下来的人。阅读本文以了解跨域 javascript 调用的工作原理 stackoverflow.com/a/11736771/228656
1赞 jherax 6/27/2014
我在这里为这个问题写了一个答案:使用 jQuery AJAX 加载跨域 html 页面最后一个,支持 https

答:

20赞 Sarfraz 8/18/2010 #1

您需要看一下同源策略

在计算中,同源策略 是一个重要的安全概念 浏览器端编程数量 语言,例如 JavaScript。这 策略允许在 来自同一网站的网页 访问彼此的方法和 没有特定属性 限制,但会阻止访问 大多数方法和属性 不同网站上的页面。

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

相同的协议和主机

您需要实现 JSONP 才能解决它。

7赞 Jacob Mattison 8/18/2010 #2

浏览器安全性可防止从一个域上托管的页面到另一个域上托管的页面进行 ajax 调用;这称为“同源策略”。

评论

0赞 MeSo2 11/14/2022
是否可以在响应服务器上为一组域名打开和关闭允许跨域访问的例外?(我会以正常的方式问这个问题,但我被禁止提出新问题;并希望版主能取消删除我删除的问题,这样我就可以重新处理它们并最终再次提问。jquery
0赞 Jacob Mattison 11/14/2022
可以允许从服务器端进行跨域共享,而不是从 jQuery 进行跨域共享。查看 CORS:developer.mozilla.org/en-US/docs/Web/HTTP/CORS
419赞 BGerrissen 8/18/2010 #3

使用 JSONP

j查询:

$.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了。在任何情况下,您都需要输出注意引号。jQuery 将传递自己的回调名称,因此您需要从 GET 参数中获取该名称。callbackName('jsonString')

正如 Stefan Kendall 所发布的,$.getJSON() 是一个简写方法,但您需要将 URL 作为 GET 参数附加到 url 中(是的,value 是 ?,jQuery 将其替换为自己生成的回调方法)。'callback=?'

评论

2赞 Eric 10/23/2011
为什么你需要返回而不是?callbackName('/* json */')callbackName(/* json */)
4赞 BGerrissen 10/24/2011
@eric回调需要 JSON 字符串。从理论上讲,一个对象也可以工作,但不确定jQuery如何响应,它可能会抛出错误或静默失败。
0赞 user2003356 1/23/2014
我收到以下错误。SyntaxError: 缺少 ;在语句 {“ResultCode”:2} 之前。其中 {“ResultCode”:2} 是响应。请指教。
3赞 Vicky Chijwani 7/20/2016
现在是 2016 年。CORS 现在是一个广泛支持的标准,而不是 JSONP,后者只能被描述为黑客攻击。@joshuarh下面的答案应该是现在的首选答案。
1赞 Raymond Nijland 3/25/2019
请记住,如果远程 API 具有可攻击性,使用跨域 JSONP 也可能使您的网站受到跨端脚本攻击。
4赞 William Clemens 8/18/2010 #4

来自 Jquery 文档(链接):

  • 由于浏览器安全限制,大多数“Ajax”请求都受同源策略的约束;请求无法成功从其他域、子域或协议中检索数据。

  • 脚本和 JSONP 请求不受同源策略限制。

因此,我认为您需要为请求使用jsonp。但是我自己没有尝试过。

9赞 Paul Schreiber 8/18/2010 #5

这是可能的,但您需要使用 JSONP,而不是 JSON。Stefan 的链接为您指明了正确的方向。jQuery AJAX 页面提供了有关 JSONP 的更多信息。

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

207赞 jrh 3/2/2012 #6

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

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

class HelloController < ApplicationController
  def say_hello
    headers['Access-Control-Allow-Origin'] = "*"
    render text: "hello!"
  end
end

在此示例中,该操作将接受来自任何域的 AJAX 请求,并返回响应“hello!”。say_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

评论

12赞 TonyTakeshi 7/23/2012
Jsonp 不支持 post、put 和 delete。您的解决方案效果很好。
35赞 SparK 9/20/2012
在 PHP header(“Access-Control-Allow-Origin: *”);
9赞 Friederike 4/26/2013
@Warrior 如果您使用的是 jQuery 的方法,则必须在 jQuery 中启用跨域支持。它是这样完成的:..post()$.support.cors = true
21赞 Jon Schneider 1/24/2014
以这种方式配置服务器会带来哪些安全隐患?
21赞 Sebastián Grignoli 12/12/2014
最好只允许那些要与之共享数据的域,而不是使用 wilcard “*”。
9赞 imilbaev 4/2/2012 #7

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

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

然后添加:

ProxyPass /your-proxy-url/ http://service-url:serviceport/

最后,将 proxy-url 传递给脚本。

18赞 Whome 5/16/2012 #8

我必须从本地磁盘“file:///C:/test/htmlpage.html”加载网页,调用“http://localhost/getxml.php”url,并在 IE8+ 和 Firefox12+ 浏览器中执行此操作,使用 jQuery v1.7.2 库来最小化样板代码。看了几十篇文章终于想通了。这是我的总结。

  • 服务器脚本(.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);
    }
});

评论

1赞 jherax 6/27/2014
我在这里为这个问题写了一个答案:使用 jQuery AJAX 加载跨域 html 页面最后一个,支持 https
0赞 T30 1/15/2016
对于最关键的一点:在PHP中,将以下行添加到脚本中:header("Access-Control-Allow-Origin: *");
1赞 Luis Milanese 12/13/2019
@whome非常感谢您的回答。你帮了我很多。干杯。
4赞 BillyTom 5/10/2013 #9

使用 JSONP 的示例很少,其中包括错误处理。

但是,请注意,使用 JSONP 时不会触发 error-event!请参阅:使用 jsonp 错误 http://api.jquery.com/jQuery.ajax/ 或 jQuery ajax 请求

10赞 Jason 8/29/2013 #10

诚然,同源策略阻止了 JavaScript 跨域发出请求,但 CORS 规范只允许您正在寻找的那种 API 访问,并且当前一批主要浏览器都支持它。

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

http://enable-cors.org/

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

32赞 Adorjan Princz 11/29/2014 #11

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

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

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

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

0赞 Josh Schultz 7/24/2017 #12

对于Microsoft Azure,它略有不同。

Azure 有一个特殊的 CORS 设置需要设置。这在幕后本质上是一样的,但简单地设置约书亚提到的标题是行不通的。可在此处找到用于启用跨域的 Azure 文档:

https://learn.microsoft.com/en-us/azure/app-service-api/app-service-api-cors-consume-javascript

我摆弄了几个小时,然后才意识到我的托管平台有这个特殊的设置。

3赞 Ali_Hr 3/3/2018 #13

我知道 3 种方法可以解决您的问题:

  1. 首先,如果您有权访问这两个域,则可以使用以下命令允许访问所有其他域:

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

    或者只是通过向 .htaccess 文件添加以下代码来设置域:

    <FilesMatch "\.(ttf|otf|eot|woff)$"> <IfModule mod_headers.c> SetEnvIf Origin "http(s)?://(www\.)?(google.com|staging.google.com|development.google.com|otherdomain.net|dev02.otherdomain.net)$" AccessControlAllowOrigin=$0 Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin </IfModule> </FilesMatch>

  2. 您可以对服务器中的 PHP 文件进行 AJAX 请求,并使用此 PHP 文件处理对另一个域的请求。

  3. 您可以使用 jsonp ,因为它不需要权限。为此,您可以阅读我们的朋友@BGerrissen答案。
0赞 Paun Narcis Iulian 5/4/2018 #14

它有效,你需要的一切:

PHP格式:

header('Access-Control-Allow-Origin: http://www.example.com');
header("Access-Control-Allow-Credentials: true");
header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');

JS(jQuery ajax):

var getWBody = $.ajax({ cache: false,
        url: URL,
        dataType : 'json',
        type: 'GET',
        xhrFields: { withCredentials: true }
});
1赞 Sergio Abreu 7/14/2022 #15

它在PHP中工作,只需将其添加到所服务的页面中:

header("Access-Control-Allow-Origin: *");
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');

PS:我用方便实用的方法制作了自己的名为sa_ajax的xhr套件。(https://github.com/osergioabreu/sa_ajax/)