少用但始终都会碰到 - 跨域ajax ¶
作者:KK
发表日期:2017.2.15
方法1:利用HTML5新特性的支持实现 ¶
现在大家大部分都做移动Web,基本上都支持HTML5,甚至做PC端的也越来越无视旧版IE了,所以比较推荐这个
前端的ajax写法就像平时获取本域名数据一样不用改
被跨域请求的接口只要加上这两句话:
header('Access-Control-Allow-Origin: http://test'); //允许指定域名的来源请求 //header('Access-Control-Allow-Origin: *'); //还能这样允许所有来源 header('Access-Control-Allow-Credentials: true');
其实就是响应两个报头,而
Access-Control-Allow-Origin
的值是请求来源的网址,“http://test
”是我的示例网址,实际上要换成你的真实的来源地址在新浏览器环境下(只要不是旧IE),当ajax发起对其它域名的请求时,其实请求是出去了,也到达了目标服务器,并使服务器上的PHP程序(或其它语言的程序)跑起来了
但目标服务器发现来源不是本域,所以没有将PHP的运行结果回送给请求来源,而是直接响应了302状态码
只要添加这两个报头就可以允许别人跨域请求自己,浏览器收到这个响应头后也会配合开放办事
无法便捷地同时允许指定多个来源
我暂时也没找到办法,类似下面这样同时声明多个来源都不行
header('Access-Control-Allow-Origin: http://source1 http://source2');
只能用
*
号允许来自全部的,希望只是我没找到简单的办法,如果大家找到了方法麻烦告诉我一下哦!
我绕了个方法实现允许多个来源:
$来源白名单'http://aa.com', 'https://bb.com', ]; if(isset($_SERVER['HTTP_REFERRER'])){ $urlInfo = parse_url($_SERVER['HTTP_REFERRER']); $来源域名协议域名协议$urlInfo['scheme']; $来源域名$urlInfo['host']; $来源首页'://' . $来源域名'Access-Control-Allow-Origin: ' . $来源首页'Access-Control-Allow-Credentials: true'); } }
方法2:用jsonp
¶
为了解答大部分菜鸟的疑惑,首先这里很直白地描述一个接近jsonp的跨域数据传递实现方案:
A(请求方)先定义一个类似这样的全局JS函数:
var cityName = ''; function setData(data){ cityName = data; }
A发起了一个GET请求去获取B(另一个域)的接口数据,希望所在城市名称
B可以不管三七二十一,直接
echo 'setData("江苏");'
,其实就是返回了一个JS代码,别管这个代码是干嘛的A相当于请求了一个JS文件,于是这个JS代码
setData("江苏");
自动运行了你想想,HTML页面可以引用非本域的JS是不是,比如直接引用 ,这是允许的,并且加载这个JS后浏览器也会自动运行这个JS源里面的代码
A再执行
alert('我的所在城市:' + cityName)
就显示了江苏
这样就实现了A向不同域名的B获取数据了,前提是B要返回JS代码,这个代码能在A那边运行后,将数据赋值给A的储存变量;甚至B还可以返回window.cityName = '江苏';
这样的代码来暴力赋值
好了这下来看看jsonp ¶
其实jsonp的基本原理和上面是一致的,但是做法稍有不同,A向B发请求时,A构造了这么一个地址:http://bb.com/xxx.json?callback=setData
有没有发现,网上很多讲jsonp的例子都有提到callback,接下来callback是这样被B站处理响应回去的:
$callback = $_GET['callback'];
echo $callback . '("江苏")';
//于是最后输出了 setData("江苏");
这样B站就可以毫不关心A站要执行哪个函数来生成设置数据的JS代码了,反正A站将函数名称通过callback传过来,B站再拼接生成代码就是
所以jsonp的特征往往就是请求方A总是附带一个callback参数
在jQuery里实现jsonp ¶
这个很简单,直接将dataType
声明为“jsonp”就行
$.ajax({
url : 'http://bb.com/xxx.php',
dataType : 'jsonp',
success : function(data){
console.log(data);
}
});
当dataType为jsonp时,jQuery会生成一个临时全局函数,函数的命名大概是这么长:jQuery111102055743417706435_1487088707749
然后打开浏览器Network记录一看,请求地址就是
http://bb.com/xxx.php?callback=jQuery111102055743417706435_1487088707749&_=1487088707750
其中地址后面第2个参数_
是一个防缓存参数,值又是一个随机数字,因为它必须走GET请求(所有加载第三方JS代码的都是GET请求),只要URL不变都很可能被浏览器或中间的网络节点直接返回缓存,所以必须通过生成随机数来让URL不与旧的请求重复嘛,就不详解了
这下明白jQuery为什么要生成那个临时全局函数了吧,压根就是为了B方响应时拼成执行这个函数的JS代码吧,所以B方响应的结果大概就是:jQuery111102055743417706435_1487088707749(数据)