cors兼容性解决


很多人以为(包括我之前也是)跨域只需要后端Apach返回的标头中Header set Access-Control-Allow-Origin: *”,就可以放心的使用,今天再跟大家说一次,这个CORS(跨域资源共享)的方案在POST下并不兼容IE7及以下,IE8-IE9则需要使用window.XDomainRequest.来兼容。

比较常用的跨域有jsonp和cors,本文将围绕这两个点来展开。

使用JSONP

虽然jsonp可以支持跨域ajax请求,但是jsonp只支持GET的方式,并不支持post方式,当使用表单发送数据或者数据量较大和安全性较高要求的情况下,你就只能使用post方式了。

$.ajax({
    url : "http://top.caibaojian.com/cross-domain-cors/jsonp.php",
    dataType:"jsonp",
});
 
function mycallback(data)
{
    alert("Here: "+data.name);
}

jsonp.php 的响应:

mycallback({"name":"Ravishanker","age":32,"location":"India"})

如果要自动处理函数,可以使用下面的方法。在这种情况下,你不需要有任何额外的功能。您可以在成功回调中获得服务器响应。

$.ajax({
	url : "http://top.caibaojian.com/cross-domain-cors/jsonp.php",
	dataType:"jsonp",
	jsonp:"mycallback",
	success:function(data)
	{
		alert("Name:"+data.name+"nage:"+data.age+"nlocation:"+data.location);
	}
});
<?php
    $callback ='mycallback';
 
    if(isset($_GET['mycallback']))
    {
        $callback = $_GET['mycallback'];
    }   
    $arr =array();
    $arr['name']="Ravishanker";
    $arr['age']=32; 
    $arr['location']="India";   
 
    echo $callback.'(' . json_encode($arr) . ')';
 
?>

使用CORS

设置标头

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

// Apache (.htaccess)
Header set Access-Control-Allow-Origin "*"

预处理

function createCORSRequest(method, url) {
  var xhr = new XMLHttpRequest();
  if ("withCredentials" in xhr) {

    // "withCredentials"属性是XMLHTTPRequest2中独有的
    xhr.open(method, url, true);

  } else if (typeof XDomainRequest != "undefined") {

    // 检测是否XDomainRequest可用
    xhr = new XDomainRequest();
    xhr.open(method, url);

  } else {

    // 看起来CORS根本不被支持
    xhr = null;

  }
  return xhr;
}

var xhr = createCORSRequest('GET', url);
if (!xhr) {
  throw new Error('CORS not supported');
}

绝大多数情况下,我们只需要和onloadonerror打交道,就像下面这样:

xhr.onload = function() {
 var responseText = xhr.responseText;
 console.log(responseText);
 // 继续其它代码
};

xhr.onerror = function() {
  console.log('There was an error!');
};

简单请求

  1. 不发送自定义header(如x-pingother,等)
  2. 只使用GET、POST或header的方法
//code from http://caibaojian.com/cors-post.html
<script type="text/javascript">
// Using jQuery
$.get("http://www.example.org/ajax.php").done(function (data) {
    console.log(data);
});

// Using XMLHttpRequest
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://www.example.org/ajax.php", true);
xhr.onload = function () {
    console.log(xhr.responseText);
};
xhr.send();
</script>

widthCredentials

默认情况下,非同一来源的请求,浏览器不会发送凭据(如HTTP cookies,HTTP认证和客户端的SSL证书)。如果有需要则需要在设置XMLHttpRequest对象时加一个特定的属性调用。·

<script type="text/javascript">
// Using jQuery
$.ajax({
    xhrFields: {
        withCredentials: true
    },
    type: "GET",
    url: "http://www.example.org/ajax.php"
}).done(function (data) {
    console.log(data);
});

// Using XMLHttpRequest
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://www.example.org/ajax.php", true);
xhr.withCredentials = true;
xhr.onload = function () {
    console.log(xhr.responseText);
};
xhr.send();
</script>

后端响应

<?php
// http://www.example.org/ajax.php
if (!isset($_SERVER['HTTP_ORIGIN'])) {
    // This is not cross-domain request
    exit;
}

$wildcard = FALSE; // Set $wildcard to TRUE if you do not plan to check or limit the domains
$credentials = FALSE; // Set $credentials to TRUE if expects credential requests (Cookies, Authentication, SSL certificates)
$allowedOrigins = array('http://caibaojian.com', 'http://jsfiddle.net');
if (!in_array($_SERVER['HTTP_ORIGIN'], $allowedOrigins) && !$wildcard) {
    // Origin is not allowed
    exit;
}
$origin = $wildcard && !$credentials ? '*' : $_SERVER['HTTP_ORIGIN'];

header("Access-Control-Allow-Origin: " . $origin);
if ($credentials) {
    header("Access-Control-Allow-Credentials: true");
}
header("Access-Control-Allow-Methods: POST, GET, OPTIONS");
header("Access-Control-Allow-Headers: Origin");
header('P3P: CP="CAO PSA OUR"'); // Makes IE to support cookies

// Handling the Preflight
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') { 
    exit;
}

// Response
header("Content-Type: application/json; charset=utf-8");
echo json_encode(array('status' => 'OK'));
?>

一些笔记:

  1. 当 credentials 设为真时,通配符“*”不能用于'Access-Control-Allow-Origin'
  2. 当进行同步请求时,Gecko 11.0 (Firefox 11.0 / Thunderbird 11.0 / SeaMonkey 2.8) 不再支持使用withcredentials属性

浏览器支持:

Chrome 3+, Firefox 3.5+, IE 10+, Opera 12+, Safari 4+

兼容IE8的插件

https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest

  • 1.只能是GET or POST请求,在使用post时,数据总是发送一个 Content-Type 为text/plain的
  • 2.只能是HTTP或者HTTPS,并且双方的协议需要一致
  • 3.总是使用异步请求

引入插件

<script type='text/javascript' src="http://cdnjs.cloudflare.com/ajax/libs/jquery-ajaxtransport-xdomainrequest/1.0.1/jquery.xdomainrequest.min.js"></script>

var contentType ="application/x-www-form-urlencoded; charset=utf-8";
 
if(window.XDomainRequest) //for IE8,IE9
    contentType = "text/plain";
 
$.ajax({
     url:"http://top.caibaojian.com/cross-domain-cors/post.php",
     data:"name=Ravi&age=12",
     type:"POST",
     dataType:"json",   
     contentType:contentType,    
     success:function(data)
     {
        alert("Data from Server"+JSON.stringify(data));
     },
     error:function(jqXHR,textStatus,errorThrown)
     {
        alert("You can not send Cross Domain AJAX requests: "+errorThrown);
     }
 });

post.php代码

<?php
header('Access-Control-Allow-Origin: *'); 
header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');
 
if(isset($HTTP_RAW_POST_DATA)) {
  parse_str($HTTP_RAW_POST_DATA,$arr); 
  $arr['extra']='1.POST Request from caibaojian.com';
  echo json_encode($arr);
}
else
{
    $_POST['extra']='2.POST Request from caibaojian.com';
    echo json_encode($_POST);
}
?>

网上太多的跨域解决方案了,我比较常用的就属JSONP和CORS了,对于IE系列的浏览器兼容,提交数据推荐使用iframe+form的方式

http://friedcell.si/js/jQuery.windowName/jQuery.windowName.plugin.js

以上代码参考:

  1. How to Send Cross Domain AJAX Request with jQuery
  2. Cross Domain AJAX Request
  3. 利用CORS实现跨域请求
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值