前端面试常问的跨域问题
为什么要跨域?跨域问题是浏览器同源策略限制,当前域名的js只能读取同域下的窗口属性。 一个网站的网址组成包括协议名,子域名,主域名,端口号。比如https://www.github.com/80其中https是协议名,www.github.com是子域名,github.com是主域名,端口号是80,当在在页面中从一个url请求数据时,如果这个url的协议名、子域名、主域名、端口号任意一个
为什么要跨域?
跨域问题是浏览器同源策略限制,当前域名的js只能读取同域下的窗口属性。
一个网站的网址组成包括协议名,子域名,主域名,端口号。比如https://www.github.com/80
其中https是协议名,www.github.com是子域名,github.com是主域名,端口号是80,当在在页面中从一个url请求数据时,如果这个url的协议名、子域名、主域名、端口号任意一个有一个不同,就会产生跨域问题。
即使是在 http://localhost:80/ 页面请求 http://127.0.0.1:80/ 也会有跨域问题(因为域名不一样嘛~)
PS:下浏览器中的 file://域拥有的权限很高,WebKit可以读取磁盘上的文件,IE可以执行CMD,这里大家可以尽情发挥想象,能做的事情太多了!
跨域解决方法小结
- 最简单也最常见:使用jsonp ,即json with padding(内填充),顾名思义,就是把JSON填充到一个盒子里
- 一劳永逸:直接在服务器端设置跨域资源访问 CORS(Cross-Origin Resource Sharing),设置Request Header头中Access-Control-Allow-Origin为指定可获取数据的域名
- 简单有效:直接请求一张图片
- 找”爸爸”:通过修改document.domain来跨子域
- 哥俩好:通过window.name来跨域接收数据
- 新石器时代:使用HTML5的window.postMessage方法跨域
jsonp
核心思想:浏览器的script、img、iframe标签是不受同源策略限制的 ,所以通过script标签引入一个js文件,这个js文件载入成功后会执行我们在url参数中指定的callback函数,并把把我们需要的json数据作为参数传入。在服务器端,当req.params参数中带有callback属性时,则把数据作为callback的参数执行,并拼接成一个字符串后返回。
- 优点:兼容性好,在很古老的浏览器中也可以用,简单易用,支持浏览器与服务器双向通信。
- 缺点:只支持GET请求,且只支持跨域HTTP请求这种情况(不支持HTTPS)
网页端的代码如下
创建一个函数tryJSONPadding,并在script标签的源地址中加入这个函数名,服务器端(Node.js写的后端)的处理如下
CORS
核心思想:在服务器端通过检查请求头部的origin,从而决定请求应该成功还是失败。具体的方法是在服务端设置Response Header响应头中的Access-Control-Allow-Origin为对应的域名,实现了CORS(跨域资源共享),这里出于在安全性方面的考虑就是尽量不要用 *,但对于一些不重要的数据则随意,例如图片。下图是某公司阿里云服务器上的CORS设置
Node.js实现CORS的方法也很简单,如图。
图片ping
因为在浏览器中,JS脚本和图片是可以跨域的,所以我们可以直接新建一个图片对象,然后在地址中存放一些简单,这种方法只支持get秦秋,且只能单向地向服务器发送请求,在统计广告曝光次数中比较常见。
寻找相同主域document.domain
对于以下的这两个域名,可以看到他们的主域名都是 example.com,相同于有一个共同的爸爸,且此方法只适用于两个iframe之间的跨域。
http://www.example.com/a.html 和http://bbs.example.com/b.html)
- 1
- 2
下面是另外一篇文章中的例子。
window.name
window对象中其实包含了黑魔法的,window.name属性就是其中之一,不同域的框架把想要共享的信息放在window.name里面,且此方法只适用于两个iframe之间的跨域。
a.com/getDomainData.htmla.com/getDomainData.htmlb.com/data.htmlb.com/data.htmla.com/null.htmla.com/null.html获得数据将iframe的src改为a.com/null.html,跳回原来的域执行回调函数,并销毁iframe,关闭null.html
- 在a.com网站添加一个空HTML页。名称为:http://a.com/null.html (用于实现二次跳转)
- 在a.com网站需要获取数据页面(如:http://a.com/getDomainData.html)
- 在b.com中添加获取数据页面 如:http://b.com/data.html 内容需包含:
接下来访问 http://a.com/getDomainData.html 就可返回 http://b.com/data.html 中的window.name中的数据了。
HTML5 中的window.postMessage方法
window.postMessage(message,targetOrigin) 方法是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源,目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。这种方法不能和服务端交换数据,只能在两个窗口(iframe)之间交换数据
www.example.com中主动发起连接
处于安全考虑,另一个域下的脚本中需要验证消息orgin来源后为http://www.example.com后再发送消息
event对象,这里的origin为http://localhost:81,仅作为演示
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)