特别注意两点:
#1、如果是协议和端口造成的跨域问题“前台”是无能为力的;
#2、在跨域问题上,域仅仅是通过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。
方法一、通过jsonp跨域要解决跨域的问题,我们可以使用以下几种方法:
JSONP包含两部分:回调函数和数据。
回调函数:当响应到来时要放在当前页面被调用的函数。
数据:就是传入回调函数中的json数据,也就是回调函数的参数了。
/*handleResonse({"data": "zhe"})*///原理如下://当我们通过script标签请求时//后台就会根据相应的参数(json,handleResponse)//来生成相应的json数据(handleResponse({"data": "zhe"}))//最后这个返回的json数据(代码)就会被放在当前js文件中被执行//至此跨域通信完成//1、使用JS动态生成script标签,进行跨域操作function handleResponse(response){ console.log('The responsed data is: '+response.data); //处理获得的Json数据}var script = document.createElement('script');script.src = 'http://www.example.com/data/?callback=handleResponse';document.body.insertBefore(script, document.body.firstChild);--------------------------//2、手动生成script标签function handleResponse(response){ console.log('The responsed data is: '+response.data); //处理获得的Json数据}--------------------------//3、使用jQuery进行jsonp操作//jquery会自动生成一个全局函数来替换callback=?中的问号,之后获取到数据后又会自动销毁//$.getJSON方法会自动判断是否跨域,不跨域的话,就调用普通的ajax方法;跨域的话,则会以异步加载js文件的形式来调用jsonp的回调函数。
jsonp虽然很简单,但是有如下缺点:
#1)安全问题(请求代码中可能存在安全隐患)
#2)要确定jsonp请求是否失败并不容易
浏览器同源策略限制:
#(1)不能通过ajax的方法去请求不同源中的文档。
#(2)浏览器中不同域的框架之间是不能进行js的交互操作的。
所以,在不同的框架之间(父子或同辈),是能够获取到彼此的window对象的,但不能使用获取到的window对象的属性和方法(html5中的postMessage方法是一个例外),总之,你可以当做是只能获取到一个几乎无用的window对象。
例如,在一个页面 http:// www.example.com/a.html 中,有一个iframe框架它的src是http:// example.com/b.html, 很显然,这个页面与它里面的iframe框架是不同域的,所以我们是无法通过在页面中书写js代码来获取iframe中的东西的:
// http://www.example.com/a.html 页面中
2) 在http:// script.a.com/dir/b.html也需要显示的设置document.domain
注意,document.domain的设置是有限制的:
我们只能把document.domain设置成自身或更高一级的父域,且主域必须相同。
例如:a.b.c.com 中某个文档的document.domain 可以设成a.b.c.com、b.c.com 、c.com中的任意一个
window的name属性特征:name 值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB),即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面window.name都有读写的权限。
正是由于window的name属性的特征,所以可以使用window.name来进行跨域。
举例:
1)在一个a.html页面中,有如下代码:
2)再在b.html中读取window.name的值:
3)a.html载入3秒后,跳转到b.html页面中,结果为
#注意:
#1.window.name的值只能是字符串的形式,这个字符串的大小最大能允许2M左右甚至更大的一个容量,具体取决于不同的浏览器。
比如:有一个example.com/a.html页面,需要通过a.html页面里的js来获取另一个位于不同域上的页面cnblogs.com/data.html里的数据。接下来使用window.name进行跨域举例
1)创建cnblogs.com/data.html代码:
2)创建example.com/a.html的代码:
想要即使a.html页面不跳转也能得到data.html里的数据。在a.html页面中使用一个隐藏的iframe来充当一个中间人角色,由iframe去获取data.html的数据,然后a.html再去得到iframe获取到的数据。
window.postMessage(message,targetOrigin) 方法是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源(可实现跨域),目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。
message:为要发送的消息,类型只能为字符串;
targetOrigin:用来限定接收消息的那个window对象所在的域,如果不想限定域,可以使用通配符 “*”。
1)创建www.test.com/a.html页面代码:
2)创建www.script.com/b.html页面代码:
优点:使用postMessage来跨域传送数据还是比较直观和方便的;
缺点:IE6、IE7不支持,所以用不用还得根据实际需要来决定。
CORS:一种跨域访问的机制,可以让AJAX实现跨域访问;CORS允许一个域上的网络应用向另一个域提交跨域AJAX请求。
服务器设置Access-Control-Allow-Origin HTTP响应头之后,浏览器将会允许跨域请求.
就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功,还是应该失败。
1) IE中对CORS的实现是通过xdr
var xdr = new XDomainRequest(); xdr.onload = function(){ console.log(xdr.responseText); } xdr.open('get', 'http://www.test.com'); ...... xdr.send(null);
2) 其它浏览器中的实现就在xhr中
var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if(xhr.readyState === 4 && xhr.status === 200){ console.log(xhr.responseText); } } } xhr.open('get', 'http://www.test.com'); ...... xhr.send(null);
3) 实现跨浏览器的CORS
function createCORS(method, url){ var xhr = new XMLHttpRequest(); if('withCredentials' in xhr){ xhr.open(method, url, true); }else if(typeof XDomainRequest != 'undefined'){ var xhr = new XDomainRequest(); xhr.open(method, url); }else{ xhr = null; } return xhr; } var request = createCORS('get', 'http://www.test.com'); if(request){ request.onload = function(){ ...... }; request.send(); }
假设域名test.com下的文件a.html要和csdnblogs.com域名下的b.html传递信息。
1) 创建test.com下的a.html页面, 同时在a.html上加一个定时器,隔一段时间来判断location.hash的值有没有变化,一旦有变化则获取获取hash值,代码如下:
2) b.html响应请求后再将通过修改a.html的hash值来传递数据,代码如下:
3) test.com域下的c.html代码:
web sockets:是一种浏览器的API,它的目标是在一个单独的持久连接上提供全双工、双向通信。(同源策略对web sockets不适用)
web sockets原理:在JS创建了web socket之后,会有一个HTTP请求发送到浏览器以发起连接。取得服务器响应后,建立的连接会使用HTTP升级从HTTP协议交换为web sockt协议。