首先什么是跨域?
跨域是指从一个域名的网站下请求另一个域名网站的资源,比如从a.com下去访问b.com的资源,这就是跨域请求。JavaScript处于安全考虑,不允许跨域调用其他页面的对象。
什么是同源策略?
同源策略是浏览器最核心的安全功能,如果缺少了同源策略,浏览器的正常功能可能会受到影响。
同源策略指的是域名、端口、协议相同,其中有一个不同,就属于跨域。
如:http://www.a.com:8000/a.js
http://www.a.com/b.js 同一域名,不同端口 不允许
http://www.a.com/a.js
https://www.a.com/b.js 同一域名,不同协议 不允许
http://www.cnblogs.com/a.js
http://www.a.com/b.js 不同域名 不允许
如何解决ajax跨域问题?
方法一 jsonp(Json with padding)
JSONP是通过动态<script>元素使用的,使用时可以为src属性指定一个跨域URL。例如:
function handleResponse(response){
alert("You are at IP address" + response.ip + ",which is in" + response.city + "," + response.region_name);
}
var script = document.createElement("script");
script.src = "http://freegeoip.net/json/?callback=handleResponse";
document.body.insertBefore(script,document.body.firstChild);
JSONP由两部分组成:回调函数和数据,是被包含在函数调用中的JSON,像callback({“name”,"TOM"});
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head> <title>JSONP 实例</title> </head> <body> <div id="divCustomers"></div> <script type="text/javascript"> function callbackFunction(result, methodName) { var html = '<ul>'; for(var i = 0; i < result.length; i++) { html += '<li>' + result[i] + '</li>'; } html += '</ul>'; document.getElementById('divCustomers').innerHTML = html; } </script> <script type="text/javascript" src="http://www.runoob.com/try/ajax/jsonp.php?jsoncallback=callbackFunction"></script> </body> </html>
JSONP优点:不受同源策略的限制,兼容性更好,在古老的浏览器中运行的很好,不需要XMLHttpRequest支持,请求完毕后可以通过callback返回结果。
缺点:1.不支持post请求方式,只支持get方法。
2.安全性。JOSNP是从其他域中加载代码执行,如果别的域存在安全性问题,则此时很可能收到恶意代码的攻击。此时只能放弃JSONP调用
3.要确定请求是否失败并不容易,必须使用计时器检测指定事件内是否收到响应。
方法二 CORS(跨源资源共享)
基本思想:使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应式应该成功还是应该失败。
如:
Origin:http://www.a.com(在发送请求时,附加一个额外Origin头部,其中包含请求页面的源信息:协议、域名、端口)
如果服务器觉得这个请求可以接受,就在Access-Control-Allow-Origin头部中发回相同的的源信息。如果是公共资源可以发回“*”
Access-Control-Allow-Origin:http://www.a.com
IE是通过IE8引入XDR类型来实现的
其他WebKit都是通过XMLHttpRequest对象实现对CORS的原生支持
方法三:通过修改document.domain来跨子域:
比如,有一个页面,它的地址是http://www.example.com/a.html , 在这个页面里面有一个iframe,它的src是
http://example.com/b.html, 很显然,这个页面与它里面的iframe框架是不同域的,所以我们是无法通过在页面中书写js代码来获
取iframe中的东西的:这个时候,document.domain就可以派上用场了,我们只要把
http://www.example.com/a.html 和 http://example.com/b.html这两个页面的document.domain都设成相同的域名就可以了。但要
注意的是,document.domain的设置是有限制的,我们只能把document.domain设置成自身或更高一级的父域,且主域必须相同。注
意:修改document.domain的方法只适用于不同子域的框架间的交互。
方法四:图像Ping
图像Ping是与服务器进行简单、单向的跨域通信的一种方式。请求的数据是通过查询字符串形式发送的,而响应可以是任意内容,
但通常是图像或204响应。
var img = new Image();
img.onload = img.onerror = function(){
alert("Done");
}
img.src = "http://www.example.com/test?name=Tom";
图像ping长用于跟踪用户点击页面或动态广告曝光次数。
缺点:1.只能发送GET请求
2.无法访问服务器的响应文本
方法五:代理服务器
这种方式首先将请求发送给后台服务器,通过服务器来发送请求,然后将请求的结果传递给前端。
方法六:使用HTML5的window.postMessage方法跨域:
window.postMessage(message,targetOrigin) 方法是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个
window对象是属于同源或不同源,目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。