jQuery AJAX 跨域

发布于 2024-09-14 22:26:52 字数 984 浏览 7 评论 0 原文

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

testserver.php

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

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

Here are two pages, test.php and 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>

testserver.php

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

Now my problem: when both of these files are on the same server (either localhost or web server), it works and alert("Success") is called; If it is on different servers, meaning testserver.php on web server and test.php on localhost, its not working, and alert("Error") is executing. Even if the URL inside AJAX is changed to http://domain.example/path/to/file/testserver.php

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(15

一瞬间的火花 2024-09-21 22:26:52

使用 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=?' 附加到 url 作为 GET 参数(是的,值为 ?,jQuery 用它自己生成的回调方法替换它)。

Use 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).");";
?>

The echo might be wrong, it's been a while since I've used php. In any case you need to output callbackName('jsonString') notice the quotes. jQuery will pass its own callback name, so you need to get that from the GET params.

And as Stefan Kendall posted, $.getJSON() is a shorthand method, but then you need to append 'callback=?' to the url as GET parameter (yes, value is ?, jQuery replaces this with its own generated callback method).

甜是你 2024-09-21 22:26:52

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

JSONP is a good option, but there is an easier way. You can simply set the Access-Control-Allow-Origin header on your server. Setting it to * will accept cross-domain AJAX requests from any domain. (https://developer.mozilla.org/en/http_access_control)

The method to do this will vary from language to language, of course. Here it is in Rails:

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

In this example, the say_hello action will accept AJAX requests from any domain and return a response of "hello!".

Here is an example of the headers it might return:

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

Easy as it is, it does have some browser limitations. See http://caniuse.com/#feat=cors.

圈圈圆圆圈圈 2024-09-21 22:26:52

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

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

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

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

You can control this via HTTP header by adding Access-Control-Allow-Origin. Setting it to * will accept cross-domain AJAX requests from any domain.

Using PHP it's really simple, just add the following line into the script that you want to have access outside from your domain:

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

Don't forget to enable mod_headers module in httpd.conf.

泪是无色的血 2024-09-21 22:26:52

您需要查看同源政策

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

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

相同的协议和主机

您需要实现JSONP 来解决它。

You need to have a look at Same Origin Policy:

In computing, the same origin policy
is an important security concept for a
number of browser-side programming
languages, such as JavaScript. The
policy permits scripts running on
pages originating from the same site
to access each other's methods and
properties with no specific
restrictions, but prevents access to
most methods and properties across
pages on different sites.

For you to be able to get data, it has to be:

Same protocol and host

You need to implement JSONP to workaround it.

我还不会笑 2024-09-21 22:26:52

我必须从本地磁盘“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);
    }
});

I had to load webpage from local disk "file:///C:/test/htmlpage.html", call "http://localhost/getxml.php" url, and do this in IE8+ and Firefox12+ browsers, use jQuery v1.7.2 lib to minimize boilerplate code. After reading dozens of articles finally figured it out. Here is my summary.

  • server script (.php, .jsp, ...) must return http response header Access-Control-Allow-Origin: *
  • before using jQuery ajax set this flag in javascript: jQuery.support.cors = true;
  • you may set flag once or everytime before using jQuery ajax function
  • now I can read .xml document in IE and Firefox. Other browsers I did not test.
  • response document can be plain/text, xml, json or anything else

Here is an example jQuery ajax call with some debug sysouts.

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);
    }
});
猥︴琐丶欲为 2024-09-21 22:26:52

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

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

http://enable-cors.org/

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

It is true that the same-origin policy prevents JavaScript from making requests across domains, but the CORS specification allows just the sort of API access you are looking for, and is supported by the current batch of major browsers.

See how to enable cross-origin resource sharing for client and server:

http://enable-cors.org/

"Cross-Origin Resource Sharing (CORS) is a specification that enables truly open access across domain-boundaries. If you serve public content, please consider using CORS to open it up for universal JavaScript/browser access."

烟织青萝梦 2024-09-21 22:26:52

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

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

This is possible, but you need to use JSONP, not JSON. Stefan's link pointed you in the right direction. The jQuery AJAX page has more information on JSONP.

Remy Sharp has a detailed example using PHP.

听,心雨的声音 2024-09-21 22:26:52

我使用 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 传递给您的脚本。

I use Apache server, so I've used mod_proxy module. Enable modules:

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

Then add:

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

Finally, pass proxy-url to your script.

太阳哥哥 2024-09-21 22:26:52

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

Browser security prevents making an ajax call from a page hosted on one domain to a page hosted on a different domain; this is called the "same-origin policy".

绅刃 2024-09-21 22:26:52

来自 Jquery 文档(链接):

  • 由于浏览器安全限制,大多数“ Ajax”请求遵循同源策略;该请求无法成功检索来自不同域、子域或协议的数据。

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

所以我认为您需要使用 jsonp 来请求。但我自己还没有尝试过这个。

From the Jquery docs (link):

  • Due to browser security restrictions, most "Ajax" requests are subject to the same origin policy; the request can not successfully retrieve data from a different domain, subdomain, or protocol.

  • Script and JSONP requests are not subject to the same origin policy restrictions.

So I would take it that you need to use jsonp for the request. But haven't tried this myself.

与之呼应 2024-09-21 22:26:52

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

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

There are few examples for using JSONP which include error handling.

However, please note that the error-event is not triggered when using JSONP! See: http://api.jquery.com/jQuery.ajax/ or jQuery ajax request using jsonp error

心碎无痕… 2024-09-21 22:26:52

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

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

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

    或者只是通过将以下代码添加到 .htaccess 文件中来创建一个域:



    SetEnvIf Origin "http(s)?://(www\.)?(google.com|staging.google.com|development.google.com|otherdomain.net|dev02.otherdomain.net)$" AccessControlAllowOrigin=$0
    标头添加 Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin

  2. 您可以向服务器中的 php 文件发出 ajax 请求,并使用此 php 文件处理对另一个域的请求。

  3. 您可以使用 jsonp ,因为它不需要权限。为此,您可以阅读我们的朋友@BGerrissen 的回答。

I know 3 way to resolve your problem:

  1. First if you have access to both domains you can allow access for all other domain using :

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

    or just a domain by adding code bellow to .htaccess file:

    <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. you can have ajax request to a php file in your server and handle request to another domain using this php file.

  3. you can use jsonp , because it doesn't need permission. for this you can read our friend @BGerrissen answer.
风月客 2024-09-21 22:26:52

只需将其添加到所提供的页面中,它就可以在 PHP 中工作:

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

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

It got to work in PHP just adding this to the page served:

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

PS: I have made my own xhr suite called sa_ajax with handy and useful methods. (https://github.com/osergioabreu/sa_ajax/)

任性一次 2024-09-21 22:26:52

对于 Microsoft Azure,情况略有不同。

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

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

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

For Microsoft Azure, it's slightly different.

Azure has a special CORS setting that needs to be set. It's essentially the same thing behind the scenes, but simply setting the header joshuarh mentions will not work. The Azure documentation for enabling cross domain can be found here:

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

I fiddled around with this for a few hours before realizing my hosting platform had this special setting.

高速公鹿 2024-09-21 22:26:52

它可以工作,您需要的一切:

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

it works, all you need:

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 }
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文