前端跨域原理和常见解决方式
来源:互联网 发布:网络采购的方式主要有 编辑:程序博客网 时间:2024/05/23 15:45
理解跨域必须先了解同源策略,所以——
何谓同源策略(same origin policy)?
浏览器的同源策略,出于防范跨站脚本的攻击,禁止客户端脚本对不同域的服务进行跨站调用。简单来讲就是,从一个域上加载的脚本不允许访问另外一个域的文档属性。
何谓同源?
URL由协议、域名、端口和路径组成,当三同——同协议(protocol)、同域名/IP(domain)、同端口(port)的时候,则表示同源。
http://www.baidu.com/b.js 同一域名 允许 http://www.baidu.com/aaa/a.js
http://www.baidu.com/bbb/b.js 同一域名不同文件 允许 http://www.baidu.com:8000/a.js
http://www.baidu.com:3000/b.js 同一域名不同端口 不允许 http://www.baidu.com
https://www.baidu.com 同一域名不同协议 不允许 http://www.baidu.com
https://www.google.com 主域相同,子域不同 不允许 http://www.baidu.com
https://aaa.bbb.ccc 不同域名 不允许 http://www.aaa.com
https://aaa.com 同一域名,不同二级域名 不允许
上表中的3、4、5、6、7种情况都会造成跨域请求,也就是违背了同源策略。而这些跨域请求并非是浏览器限制了发起跨站请求,而是请求可以正常发起,到达服务器端,但是服务器端返回的结果会被浏览器拦截。
跨域调用的解决方式:
1. jsonp
那就又有必要先提一下json的概念了,json是一种轻量级的数据传输格式,因为json格式数据的编码和解析基本在所有主流语言中都被实现,所以大部分前后端分离的架构都以json格式进行数据传输。
那jsonp又是什么呢?
jsonp(json padding),json数据的包装,形如:callback({“name”:”zhangyangyang”,”major”:”network”}),或者我们也可以简单理解为带有callback(回调函数)的json即为jsonp。也就是说,jsonp里传输的就是json的数据格式。只是在发送请求时多加一个参数,值为callback(回调函数)。后台程序在获得该回调函数后,把准备好的json数据拼接到callback里面。
原理很简单,就是利用script标签没有跨域限制的“漏洞”,来达到与第三方通讯的目的。在需要通讯时,本站脚本创建一个script标签,地址指向第三方的API网址,形如: <script src = "http://www.baidu.com/api?param1=aaa¶m2=bbb"></script>
, 并提供一个回调函数来接收数据(函数名可约定,或通过地址参数传递)。这样浏览器就会调用callback函数,并传递解析后json对象作为参数。本站脚本可在callback函数里处理传入的数据。
下面就可以撕一波jsonp代码了~
function jsonp(options){ // 整理参数 options = options || {}; options.data = options.data || {}; options.timeout = options.timeout || 0; // 随机回调函数的名字 var callbackName = ' jsonp ' + Math.random(); callbackName = callbackName.replace('.', ' '); //函数名不可含有. options.data[options.callback] = callbackName; // 拼接url var arr = []; for(var key in options.data){ arr.push(key + ' = ' + encodeURIComponent(options.data[key])); } options.url = options.url + ' ? ' + arr.join('&); // 添加script标签 var script = document.createElement("script"); script.type = "text/javascript"; script.src = options.url; document.body.appendChild(script); // 设定超时 if(options.timeout){ var timer = setTimeout(function(){ document.body.removeChild(scipt); window[options.data[options.callback]] = function(){ options.err && options.error(); } },options.timeout); } // 定义回调函数 window[options.data[options.callback]] = function(json){ clearTimeout(timer); options.success && options.success(json); document.body.removeChild(script); //清除用过的script标签 window[options.data[options.callback]] = null; //释放window头上用过的属性 }}
2.Ajax
jQuery已经有集成的近乎完美的$.ajax也可以实现jsonp的跨域调用,我在前面博客也有用原生js去实现jQuery的ajax,详情请戳原生js封装Ajax.
[注]:两者的实现大同小异,但是实现原理并不相同,jsonp跨域调用不是通过XMLHttpReaquest对象,而是通过动态创建script标签,所以再实现原理上,jsonp和Ajax已经没有一点关系。看上去形式相似,只是由于jQuery对jsonp做了封装和转换。
jsonp和Ajax的区别:
1. jsonp只能使用GET方法发起请求,这是由于script标签自身的限制决定的。
2.jsonp由于不是通过XMLHttpRequest进行传输,所以不能注册success和error等事件监听函数。
3.CORS
什么是CORS?
Cross-Origin Resource Sharing(CORS)跨域资源共享是一份浏览器技术的规范,提供了 Web 服务从不同域传来沙盒脚本的方法,以避开浏览器的同源策略,是 jsonp 模式的现代版。与 jsonp 不同,CORS 除了 GET 要求方法以外也支持其他的 HTTP 要求。用 CORS 可以让网页设计师用一般的 XMLHttpRequest,这种方式的错误处理比jsonp 要来的好。另一方面,jsonp 可以在不支持 CORS 的老旧浏览器上运作。现代的浏览器都支持 CORS。
CORS实现——
app.post('/cors', function(req, res) { res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "X-Requested-With"); res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS"); res.header("X-Powered-By", ' 3.2.1') res.header("Content-Type", "application/json;charset=utf-8"); var data = { name: req.body.name + ' - server 3001 cors process', id: req.body.id + ' - server 3001 cors process' } console.log(data) res.send(data) res.end()})
在服务器中对返回信息的请求头进行设置:
1.Access-Control-Allow-Origin
2.Access-Control-Allow-Methods
3.Access-Control-Allow-Headers
jsonp与CORS的区别:
1.CORS 除了 GET 方法外,也支持其它的 HTTP 请求方法如 POST、 PUT 等
2.CORS 可以使用 XMLHttpRequest 进行传输,所以它的错误处理方式比 jsonp 好
3.jsonp 可以在不支持 CORS 的老旧浏览器上运作
4.document.domain
比如,有一个页面,它的src是http://www.example.com/a.html , 在这个页面里面有一个iframe,它的src是http://script.com/b.html, 很显然,这个页面与它里面的iframe框架是不同域的,所以我们是无法通过在页面中书写js代码来获取iframe中的东西的。但是我们只要把http://www.example.com/a.html 和 http://script.com/b.html这两个页面的document.domain都设成相同的域名就可以了。但要注意的是,document.domain的设置是有限制的,我们只能把document.domain设置成自身或更高一级的父域,且主域必须相同。:
// http://www.example.com/a.html document.domain = 'example.com'; var ifr = document.createElement('iframe'); ifr.src = ' http://script.com/b.html '; ifr.style.display = 'none'; document.boody.appendChild(ifr); ifr.onload = function(){ var doc = ifr.contentDocument || ifr.contentWindow.document; console.log(doc); //获取到的页面数据 }
http://script.com/b.html document.domain = 'example.com';
5.window.postMessage()
这个方法是 HTML5 的一个新特性,可以用来向其他所有的 window 对象发送消息。需要注意的是我们必须要保证所有的脚本执行完才发送 MessageEvent,如果在函数执行的过程中调用了他,就会让后面的函数超时无法执行。
postMessage()允许来自不同源的脚本采用异步方式进行通信,可以实现跨域消息传递。
postMessage(data,origin)
data:要传递的数据
origin:指明目标窗口的源。协议主机端口号
接收消息:监听window的message事件,包括
1.data——传递过来的message
2.source——发送消息的窗口对象
3.origin——发送消息窗口的源
6.window.name
window对象有个name属性,该属性有个特征:即在一个窗口 (window) 的生命周期内,窗口载入的所有的页面都是共享一个 window.name 的,每个页面对 window.name 都有读写的权限,window.name 是持久存在一个窗口载入过的所有页面中的,并不会因新页面的载入而进行重置。
end···
阅读全文
0 0
- 前端跨域原理和常见解决方式
- 前端跨域问题遇到的坑及解决方式
- 浅谈前端跨域的几种解决方式
- js 跨域问题常见的五种解决方式
- vue-cli+webpack前端使用后台接口跨域问题的多种解决及其原理和产生原因
- 前端常见跨域解决方案
- 前端常见跨域解决方案
- 前端常见跨域解决方案
- 前端常见跨域解决方案
- 前端跨域解决
- 常见错误解决方式
- P2P的原理和常见的实现方式
- P2P的原理和常见的实现方式
- P2P的原理和常见的实现方式
- P2P的原理和常见的实现方式
- P2P的原理和常见的实现方式
- P2P的原理和常见的实现方式
- P2P的原理和常见的实现方式
- 社交网络成反恐战场,看人工智能如何阻止暴恐信息扩散
- 每日产品辣评:史上最贵联发科,美图手机V4 3499元起
- 央视:从手机管家大数据看支付病毒乱象
- 360行车记录仪双十一狂销20万 月出货已占行业四分之一
- C++ 指针/数组指针操作
- 前端跨域原理和常见解决方式
- angular学习总结十一——动态创建组件并实现交互二
- Haskell语言学习笔记(31)ListT
- 流程控制—静态代码块、构造器、常量以及Spring的@AutoWired注释
- 腾讯糖大夫2.0版开创“互联网+医疗金融”新模式
- 雷锋网2015年十佳评选——锋神榜
- 蓝牙音箱的终极?——超引力磁悬浮蓝牙音箱简评
- 腾讯手机管家6.0发布 iPhone清理空间更简单
- 数据分析之Scipy-输入输出和图片处理