老生常谈的跨域处理
阅读目录
主要从事网页设计、PC网站建设(电脑版网站建设)、wap网站建设(手机版网站建设)、响应式网站设计、程序开发、微网站、小程序开发等,凭借多年来在互联网的打拼,我们在互联网网站建设行业积累了丰富的成都做网站、网站建设、外贸营销网站建设、网络营销经验,集策划、开发、设计、营销、管理等多方位专业化运作于一体,具备承接不同规模与类型的建设项目的能力。
- 什么是跨域
- 常用的几种跨域处理方法:
- 跨域的原理解析及实现方法
- 总结
摘要:跨域问题,无论是面试还是平时的工作中,都会遇到,本文总结处理跨域问题的几种方法以及其原理,也让自己搞懂这方面的知识,走起。
什么是跨域
在JavaScript中,有一个很重要的安全性限制,被称为“Same-Origin Policy”(同源策略)。这一策略对于JavaScript代码能够访问的页面内容做了很重要的限制,即JavaScript只能访问与包含它的文档在同一域下的内容。
JavaScript这个安全策略在进行多iframe或多窗口编程、以及Ajax编程时显得尤为重要。根据这个策略,在baidu.com下的页面中包含的JavaScript代码,不能访问在google.com域名下的页面内容;甚至不同的子域名之间的页面也不能通过JavaScript代码互相访问。对于Ajax的影响在于,通过XMLHttpRequest实现的Ajax请求,不能向不同的域提交请求,例如,在abc.example.com下的页面,不能向def.example.com提交Ajax请求,等等。
为什么浏览器要实现同源限制?我们举例说明:
比如一个黑客,他利用iframe把真正的银行登录页面嵌到他的页面上,当你使用真实的用户名和密码登录时,如果没有同源限制,他的页面就可以通过javascript读取到你的表单中输入的内容,这样用户名和密码就轻松到手了.
又比如你登录了OSC,同时浏览了恶意网站,如果没有同源限制,该恶意 网站就可以构造AJAX请求频繁在OSC发广告帖.
跨域的情况分为以下几种:
特别注意两点:
1、如果是协议和端口造成的跨域问题“前台”是无能为力的
2、在跨域问题上,域仅仅是通过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。比如上面的,http://www.a.com/a.js和http://70.32.92.74/b.js。虽然域名和域名的ip对应,不过还是被认为是跨域。
“URL的首部”指window.location.protocol +window.location.host。其中,
window.location.protocol:指含有URL第一部分的字符串,如http:
window.location.host:指包含有URL中主机名:端口号部分的字符串.如//www.cenpok.net/server/
常用的几种跨域处理方法:
1、JSONP
2、CORS策略
3、document.domain+iframe的设置
4、HTML5的postMessage
5、使用window.name来进行跨域
跨域的原理解析及实现方法
1、JSONP(JSON with padding)
原理 :
我们知道,在页面上有三种资源是可以与页面本身不同源的。它们是:js脚本,css样式文件,图片,像淘宝等大型网站,肯定会将这些静态资源放入cdn中,然后在页面上连接,如下所示,所以它们是可以链接访问到不同源的资源的。
1)
2)
3)
而jsonp就是利用了script标签的src属性是没有跨域的限制的,从而达到跨域访问的目的。因此它的最基本原理就是:动态添加一个
在页面 http://example.com/b.html 中也设置document.domain,而且这也是必须的,虽然这个文档的domain就是example.com,但是还是必须显示的设置document.domain的值:
//http://example.com/b.htmlB页面 B页面
这里有个注意点,就是在A页面中,要等iframe标签完成加载B页面之后,再取iframe对象的contentDocument,否则如果B页面没有被iframe完全加载,在A页面中通过contentDocument属性就取不到B页面中的jQuery对象。
一旦取到B页面中的jQuery对象,就可以直接发ajax请求了,这种类似“代理”方式可以解决主子域的跨域问题。
缺点:
只有在主域相同的时候才能使用该方法
4、HTML5的postMessage
原理:
没啥原理,就是一个html5所提供的一个API.--->HTML5 window.postMessage是一个安全的、基于事件的消息API。
在需要发送消息的源窗口调用postMessage方法即可发送消息。其中.源窗口可以是全局的window对象,也可以是以下类型的窗口:
1、文档窗口中的iframe:
var iframe = document.getElementById('my-iframe'); var win = iframe.documentWindow;
2、JavaScript打开的弹窗:
var win = window.open();
3、当前文档窗口的父窗口:
var win = window.parent;
4、
var win = window.opener();
发送消息:找到源window对象后,即可调用postMessage API向目标窗口发送消息:
win.postMessage(msg, targetOrigin);
说明:postMessage函数接收两个参数:
1、msg, 将要发送的消息,可以使一切javascript参数,如字符串,数字,对象,数组等。
2、targetOrigin,这个参数称作“目标域”,注意,是目标域不是本域!比如,你想在2.com的网页上往1.com网页上传消息,那么这个参数就是“http://1.com/”,而不是2.com.协议,(一个完整的域名包括:主机名,端口号。如:http://g.cn:80/)
接收消息:那目标窗口要怎么接收传过来的数据呢,只要监听window的message事件就可以接收了。
var onmessage = function (event) { var data = event.data; var origin = event.origin; //do someing }; if (typeof window.addEventListener != 'undefined') { window.addEventListener('message', onmessage, false); } else if (typeof window.attachEvent != 'undefined') { //for ie window.attachEvent('onmessage', onmessage); }
message事件监听函数接收一个参数,Event对象实例,该对象有三个属性:
- data : 消息
- origin:消息的来源地址
- source:发送消息窗口的window对象引用
使用方法(案例):
http://test.com/index.html--> 发送消息的页面
http://lslib.com/lslib.html --> 接收消息的页面
优缺点:
优点:方便,安全,有效的解决了跨域问题
缺点:万恶的资本主义,ie8+才支持,而且ie8+ 5、使用window.name来进行跨域(相对比较完美的方法) 原理: 当iframe的页面跳到其他地址时,其window.name值保持不变,并且可以支持非常长的 name 值(2MB)。 浏览器跨域iframe禁止互相调用/传值.但是调用iframe时 window.name 却不变,正是利用这个特性来互相传值,当然跨域下是不容许读取ifram的window.name值. 所以这里我们还要准备一个和主页面http://www.a.com/main.html 相同域下的代理页面http://www.a.com/other.html ,iframe调用子页面 http://www.b.com/data.html 使用方法: 1、准备三个页面: http://www.a.com/main.html //应用页面 http://www.a.com/other.html // 代理页面,要求和应用页面在同一个域。一般是一个空的html http://www.b.com/data.html //应用页面获取数据的页面,简称:数据页面 2、数据页面将数据传到window.name中去。如下: http://www.b.com/data.html中的 data.html http://www.a.com/main.html //应用页面的代码如下: 3、获取数据以后销毁这个iframe,释放内存;这也保证了安全(不被其他域frame js访问)。 优缺点: 浏览器支持情况好,是比较普遍的使用方法 总结 以上总结了js跨域的几种方法,当然还有其他的方法,不过没有。他们各有千秋。其实最主要的区别除了实现方式不一样,主要是浏览器的兼容问题而已。 JSONP: JSONP的优点是:它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持;并且在请求完毕后可以通过调用callback的方式回传结果。 JSONP的缺点则是:它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。 CORS策略 优点:使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理。 缺点:古老的浏览器不支持,不过大部分现代浏览器都支持 document.domain+iframe:只适用于主域相同的跨域问题处理 html5的postMessage: 优点:是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源,目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。如果是现代浏览器,首选。 缺点: ie8以前不支持 window.name: 主要是应用当frame的页面跳到其他地址时,其window.name值保持不变的原理。兼容性好。需要照顾落后的浏览器时,首选。 以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持创新互联!// data.html
window.name="苍老师"; //可以是其他类型的数据,比如数组,对象等等
var iframeData;
var state = 0;//开关变量
var iframe = document.createElement('iframe'); //创建iframe
var loadfn = function() {
if (state === 1) {
iframeData = iframe.contentWindow.name; // 读取数据
alert('获取到了iframe传过来的妹子'+iframeData);
}else if (state === 0) {
state = 1;
iframe.contentWindow.location = 'http://www.a.com/other.html'; //这里是代理页面 other.html
/**
这里说明一下:
由于iframe的location改变了,相当于重新载入页面(这是iframe的性质决定的),于是重新执行loadfn方法。
由于当iframe的页面跳到其他地址时,其window.name值保持不变,并且此时开关变量 state已经变为1,
于是就可以获取到window.name值,也就达到了跨域访问的目的了。
**/
};
}
iframe.src = 'http://www.b.com/data.html'; //这是是数据页面,data.html
if (iframe.attachEvent) {
iframe.attachEvent('onload', loadfn);
} else {
iframe.onload = loadfn;
}
document.body.appendChild(iframe);
iframe.contentWindow.document.write('');
iframe.contentWindow.close();
document.body.removeChild(iframe);
网站栏目:老生常谈的跨域处理
分享URL:http://myzitong.com/article/gccjcc.html