跨域请求
我在前端开发过程中,在请求服务器端后台资源的时候,由于前端资源的域名和服务器端域名不同,导致无法获取资源。
比如,我在本地发起了一个http的ajax请求,请求地址为http://www.baidu.com ,浏览器显示结果如下:
什么是跨域?
出现错误表示,不能跨域请求资源;那什么是跨域呢?
首先回顾一下域名的组成:
http://www.abc.com:8080/server/jquery.js
-协议: http
-子域名: www
-主域名: abc.com
-端口号: 8080
-请求资源: script/jQuery.js
跨域:当协议、子域名、主域名、端口号、请求资源都不同时,这样去请求资源都叫做跨域。
同源策略
同源策略,它是由Netscape提出的一个著名的安全策略。
现在所有支持JavaScript 的浏览器都会使用这个策略。
所谓同源是指,域名,协议,端口相同。
当一个浏览器的两个tab页中分别打开来 百度和谷歌的页面
当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。
如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。
跨域请求方案一: 代理(属于后台技术)
通过在同域名web服务器端创建一个代理, 比如:
在北京的服务器(域名:http://www.beijing.com)
上海的服务器(域名:http://www.shanghai.com)
然后在北京的服务器后台,通过http://www.beijing.com/proxy.shanghai.com/server.php来调用上海的服务器端资源。然后再把相应结果返回給前端。
跨域请求方案二: jsonp(用于解决主流浏览器get请求,跨域问题)
原理:
利用了在html文档中,< script scr=”http://www.baidu.com” >标签可以通过src属性跨域请求资源。
比如在http://www.a.com 文档中有jsonp.js文件:声明jsonp函数
function(){
alert(json['name'])
}
http://www.b.com html 文档中有代码段: 调用www.a.com中的js文件
<sript src='http://www.a.com/jsonp.js'>
jsonp({'name':'jinghong','age': 21})
</script>
jQuery的ajax方法本身就支持jsonp的特性;
如果获取的数据文件存放在远程服务器上(域名不同,也就是跨域获取数据),则需要使用jsonp类型。使用这种类型的话,会创建一个查询字符串参数 callback=? ,这个参数会加在请求的URL后面。服务器端应当在JSON数据前加上回调函数名,以便完成一个有效的JSONP请求。如果要指定回调函数的参数名来取代默认的callback,可以通过设置$.ajax()的jsonp参数。
注意,JSONP是JSON格式的扩展。他要求一些服务器端的代码来检测并处理查询字符串参数。更多信息可以参阅 最初的文章。
如果指定了script或者jsonp类型,那么当从服务器接收到数据时,实际上是用了<script>标签而不是XMLHttpRequest对象。这种情况下,$.ajax()不再返回一个XMLHttpRequest对象,并且也不会传递事件处理函数,比如beforeSend。
//前端jQuery代码:
$.ajax({type:'get',
url:'http://www.baidu.com/server.php',
jsonp: 'callback',
success: function(){
if (data.success){
...todo...
}
}
//后端php代码:
$jsonp = $_GET['callback'];
$result = $jsonp.({'success':false,
'msg': '没有找到数据'})
跨域请求方案三:XMLHttpRequest Level 2
HTML5提供的XMLHttpRequest Level 2已经实现了跨域访问以及其他的一些新功能 ,这需要在远程服务器端添加如下代码,IE10以下版本不兼容。
header('Access-control-Allow-Origin: *')
header('Access-control-Allow-Methods:POST,GET')
总结:
代理最麻烦,需要后端修改,但是运用广泛,只要支持Ajax就行;
jsonp简单,但是只支持get请求,不支持post请求;XMLHttpReauestLevel2也挺简单,但是不支持IE10以下版本;