首页 文章

jQuery AJAX跨域

提问于
浏览
449

这是两个页面,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("Success") ;如果它位于不同的服务器上,意味着Web服务器上的testserver.php和localhost上的test.php,它不起作用,并且 alert("Error") 正在执行 . 即使ajax中的URL更改为http://domain.com/path/to/file/testserver.php

14 回答

  • 19

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

    雷米夏普有一个detailed example using PHP .

  • 16

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

  • 0

    浏览器安全性阻止从托管在一个域上的页面到托管在不同域上的页面进行ajax调用;这被称为“same-origin policy” .

  • 1

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

    但请注意,使用JSONP时不会触发错误事件!见:http://api.jquery.com/jQuery.ajax/jQuery ajax request using jsonp error

  • 4

    来自Jquery文档(link):

    • 由于浏览器安全限制,大多数“Ajax”请求都遵循相同的原始策略;请求无法从其他域,子域或协议成功检索数据 .

    • 脚本和JSONP请求不受相同的源策略限制 .

    所以我认为你需要使用jsonp来处理请求 . 但是我自己没试过 .

  • 5

    使用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用它自己生成的回调方法替换它) .

  • 28

    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 .

  • 9

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

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

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

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

  • 8

    你需要看看Same Origin Policy

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

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

    Same protocol and host

    您需要实现JSONP来解决它 .

  • 397

    我不得不从本地磁盘“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);
        }
    });
    
  • 9

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

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

    http://enable-cors.org/

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

  • 195

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

    • 首先,如果您有权访问这两个域,则可以使用以下权限访问所有其他域:

    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>

    • 你可以对服务器中的php文件发出ajax请求,并使用这个php文件处理对另一个域的请求 .

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

  • 0

    For Microsoft Azure, it's slightly different.

    Azure具有需要设置的特殊CORS设置 . 它在幕后基本上是一样的,但只是设置 Headers joshuarh提及将无法正常工作 . 可以在此处找到用于启用跨域的Azure文档:

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

    在实现我的主机平台有这个特殊设置之前,我花了几个小时摆弄这个 .

  • 10

    它的工作原理,你需要的一切:

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

相关问题