我在本地局域网(machineA)上有一台机器,它有两个web服务器。第一个是XBMC中的内置程序(在端口8080上),它显示我们的库。第二个服务器是一个CherryPy python脚本(端口8081),我用它按需触发文件转换。文件转换由XBMC服务器提供的页面的AJAX POST请求触发。

转到http://machineA:8080,显示库 显示Library。 用户单击“转换”链接,发出以下命令-

jQuery Ajax请求

$.post('http://machineA:8081', {file_url: 'asfd'}, function(d){console.log(d)})

浏览器发出一个带有以下报头的HTTP OPTIONS请求;

请求头- OPTIONS

Host: machineA:8081
User-Agent: ... Firefox/4.01
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Origin: http://machineA:8080
Access-Control-Request-Method: POST
Access-Control-Request-Headers: x-requested-with

服务器响应如下;

响应头- OPTIONS (STATUS = 200 OK)

Content-Length: 0
Access-Control-Allow-Headers: *
Access-Control-Max-Age: 1728000
Server: CherryPy/3.2.0
Date: Thu, 21 Apr 2011 22:40:29 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Content-Type: text/html;charset=ISO-8859-1

然后谈话就停止了。理论上,浏览器应该在服务器响应正确的(?)时发出POST请求。CORS报头(Access-Control-Allow-Origin: *)

为了排除故障,我还发布了相同的$。从http://jquery.com发布命令。这就是我难住的地方,从jquery.com, post请求工作,OPTIONS请求被post发送。来自该事务的标题如下;

请求头- OPTIONS

Host: machineA:8081
User-Agent: ... Firefox/4.01
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Origin: http://jquery.com
Access-Control-Request-Method: POST

响应头- OPTIONS (STATUS = 200 OK)

Content-Length: 0
Access-Control-Allow-Headers: *
Access-Control-Max-Age: 1728000
Server: CherryPy/3.2.0
Date: Thu, 21 Apr 2011 22:37:59 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Content-Type: text/html;charset=ISO-8859-1

请求头- POST

Host: machineA:8081
User-Agent: ... Firefox/4.01
Accept: */*
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://jquery.com/
Content-Length: 12
Origin: http://jquery.com
Pragma: no-cache
Cache-Control: no-cache

响应头- POST (STATUS = 200 OK)

Content-Length: 32
Access-Control-Allow-Headers: *
Access-Control-Max-Age: 1728000
Server: CherryPy/3.2.0
Date: Thu, 21 Apr 2011 22:37:59 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Content-Type: application/json

我不明白为什么同样的请求在一个站点上可以工作,而在另一个站点上就不行。我希望有人能指出我错过了什么。谢谢你的帮助!


当前回答

这有点晚了,但我已经为此挣扎了好几天了。这是有可能的,我在这里找到的答案都不奏效。这看似简单。 下面是.ajax调用:

<!DOCTYPE HTML> <html> <head> <body> <title>Javascript Test</title> <script src="http://code.jquery.com/jquery-latest.min.js"></script> <script type="text/javascript"> $(document).domain = 'XXX.com'; $(document).ready(function () { $.ajax({ xhrFields: {cors: false}, type: "GET", url: "http://XXXX.com/test.php?email='steve@XXX.com'", success: function (data) { alert(data); }, error: function (x, y, z) { alert(x.responseText + " :EEE: " + x.status); } }); }); </script> </body> </html>

下面是服务器端的php:

<html> <head> <title>PHP Test</title> </head> <body> <?php header('Origin: xxx.com'); header('Access-Control-Allow-Origin:*'); $servername = "sqlxxx"; $username = "xxxx"; $password = "sss"; $conn = new mysqli($servername, $username, $password); if ($conn->connect_error) { die( "Connection failed: " . $conn->connect_error); } $sql = "SELECT email, status, userdata FROM msi.usersLive"; $result = $conn->query($sql); if ($result->num_rows > 0) { while($row = $result->fetch_assoc()) { echo $row["email"] . ":" . $row["status"] . ":" . $row["userdata"] . "<br>"; } } else { echo "{ }"; } $conn->close(); ?> </body>

其他回答

以下是对我有用的方法的总结:

定义一个新函数(包装为$。简化Ajax):

jQuery.postCORS = function(url, data, func) {
  if(func == undefined) func = function(){};
  return $.ajax({
    type: 'POST', 
    url: url, 
    data: data, 
    dataType: 'json', 
    contentType: 'application/x-www-form-urlencoded', 
    xhrFields: { withCredentials: true }, 
    success: function(res) { func(res) }, 
    error: function() { 
            func({}) 
    }
  });
}

用法:

$.postCORS("https://example.com/service.json",{ x : 1 },function(obj){
      if(obj.ok) {
           ...
      }
});

也可以和.done,.fail等一起使用:

$.postCORS("https://example.com/service.json",{ x : 1 }).done(function(obj){
      if(obj.ok) {
           ...
      }
}).fail(function(){
    alert("Error!");
});

服务器端(在这个例子中,example.com是托管的),设置这些头(添加了一些PHP示例代码):

header('Access-Control-Allow-Origin: https://not-example.com');
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Max-Age: 604800');
header("Content-type: application/json");
$array = array("ok" => $_POST["x"]);
echo json_encode($array);

这是我所知道的从JS真正POST跨域的唯一方法。

JSONP将POST转换为GET,后者可能在服务器日志中显示敏感信息。

这有点晚了,但我已经为此挣扎了好几天了。这是有可能的,我在这里找到的答案都不奏效。这看似简单。 下面是.ajax调用:

<!DOCTYPE HTML> <html> <head> <body> <title>Javascript Test</title> <script src="http://code.jquery.com/jquery-latest.min.js"></script> <script type="text/javascript"> $(document).domain = 'XXX.com'; $(document).ready(function () { $.ajax({ xhrFields: {cors: false}, type: "GET", url: "http://XXXX.com/test.php?email='steve@XXX.com'", success: function (data) { alert(data); }, error: function (x, y, z) { alert(x.responseText + " :EEE: " + x.status); } }); }); </script> </body> </html>

下面是服务器端的php:

<html> <head> <title>PHP Test</title> </head> <body> <?php header('Origin: xxx.com'); header('Access-Control-Allow-Origin:*'); $servername = "sqlxxx"; $username = "xxxx"; $password = "sss"; $conn = new mysqli($servername, $username, $password); if ($conn->connect_error) { die( "Connection failed: " . $conn->connect_error); } $sql = "SELECT email, status, userdata FROM msi.usersLive"; $result = $conn->query($sql); if ($result->num_rows > 0) { while($row = $result->fetch_assoc()) { echo $row["email"] . ":" . $row["status"] . ":" . $row["userdata"] . "<br>"; } } else { echo "{ }"; } $conn->close(); ?> </body>

我为这个问题纠结了几个星期。

要做到这一点,最简单、最兼容和最不受黑客攻击的方法可能是使用提供者JavaScript API,它不进行基于浏览器的调用,可以处理跨源请求。

例如Facebook JavaScript API和谷歌JS API。

如果你的API提供者不是当前的,在它的响应中不支持Cross Origin Resource Origin '*'头,并且没有JS API(是的,我是在说你雅虎),你有三个选择之一-

Using jsonp in your requests which adds a callback function to your URL where you can handle your response. Caveat this will change the request URL so your API server must be equipped to handle the ?callback= at the end of the URL. Send the request to your API server which is controller by you and is either in the same domain as the client or has Cross Origin Resource Sharing enabled from where you can proxy the request to the 3rd party API server. Probably most useful in cases where you are making OAuth requests and need to handle user interaction Haha! window.open('url',"newwindowname",'_blank', 'toolbar=0,location=0,menubar=0')

我解决了自己的问题时使用谷歌距离矩阵API通过设置我的请求头与Jquery ajax。看看下面的内容。

var settings = {
          'cache': false,
          'dataType': "jsonp",
          "async": true,
          "crossDomain": true,
          "url": "https://maps.googleapis.com/maps/api/distancematrix/json?units=metric&origins=place_id:"+me.originPlaceId+"&destinations=place_id:"+me.destinationPlaceId+"&region=ng&units=metric&key=mykey",
          "method": "GET",
          "headers": {
              "accept": "application/json",
              "Access-Control-Allow-Origin":"*"
          }
      }

      $.ajax(settings).done(function (response) {
          console.log(response);

      });

注意我在设置中添加了什么 **

"headers": {
          "accept": "application/json",
          "Access-Control-Allow-Origin":"*"
      }

** 我希望这能有所帮助。

如果由于某些原因,在尝试添加报头或设置控制策略时,你仍然没有得到任何地方,你可以考虑使用apache ProxyPass…

例如,在一个使用SSL的<VirtualHost>中添加以下两个指令:

SSLProxyEngine On
ProxyPass /oauth https://remote.tld/oauth

确保加载了以下apache模块(使用a2enmod加载它们):

代理 proxy_connect proxy_http

显然,为了使用apache代理,你必须改变你的AJAX请求url…