跨域问题(前端面试最常问)

https://blog.csdn.net/as645788/article/details/51285688

为何要跨域?

跨域问题是浏览器同源策略限制,当前域名的js只能读取同域下的窗口属性。 
一个网站的网址组成包括协议名,子域名,主域名,端口号。好比https://www.github.com/80html

其中https是协议名,www.github.com是子域名,github.com是主域名,端口号是80,当在在页面中从一个url请求数据时,若是这个url的协议名、子域名、主域名、端口号任意一个有一个不一样,就会产生跨域问题。html5

即便是在 http://localhost:80/ 页面请求 http://127.0.0.1:80/ 也会有跨域问题(由于域名不同嘛~)git

PS:下浏览器中的 file://域拥有的权限很高,WebKit能够读取磁盘上的文件,IE能够执行CMD,这里你们能够尽情发挥想象,能作的事情太多了!github

跨域解决方法小结

  1. 最简单也最多见:使用jsonp ,即json with padding(内填充),顾名思义,就是把JSON填充到一个盒子里
  2. 一劳永逸:直接在服务器端设置跨域资源访问 CORS(Cross-Origin Resource Sharing),设置Request Header头中Access-Control-Allow-Origin为指定可获取数据的域名
  3. 简单有效:直接请求一张图片
  4. 找”爸爸”:经过修改document.domain来跨子域
  5. 哥俩好:经过window.name来跨域接收数据
  6. 新石器时代:使用HTML5的window.postMessage方法跨域

jsonp

核心思想:浏览器的script、img、iframe标签是不受同源策略限制的 ,因此经过script标签引入一个js文件,这个js文件载入成功后会执行咱们在url参数中指定的callback函数,并把把咱们须要的json数据做为参数传入。在服务器端,当req.params参数中带有callback属性时,则把数据做为callback的参数执行,并拼接成一个字符串后返回。 
- 优势:兼容性好,在很古老的浏览器中也能够用,简单易用,支持浏览器与服务器双向通讯。 
- 缺点:只支持GET请求,且只支持跨域HTTP请求这种状况(不支持HTTPSjson

网页端的代码以下 
jsonp 
建立一个函数tryJSONPadding,并在script标签的源地址中加入这个函数名,服务器端(Node.js写的后端)的处理以下 
服务器端的处理后端

CORS

核心思想:在服务器端经过检查请求头部的origin,从而决定请求应该成功仍是失败。具体的方法是在服务端设置Response Header响应头中的Access-Control-Allow-Origin为对应的域名,实现了CORS(跨域资源共享),这里出于在安全性方面的考虑就是尽可能不要用 *,但对于一些不重要的数据则随意,例如图片。下图是某公司阿里云服务器上的CORS设置 
CROS跨域

Node.js实现CORS的方法也很简单,如图。 
NodeJS浏览器

图片ping

由于在浏览器中,JS脚本和图片是能够跨域的,因此咱们能够直接新建一个图片对象,而后在地址中存放一些简单,这种方法只支持get秦秋,且只能单向地向服务器发送请求,在统计广告曝光次数中比较常见。 
图片ping安全

寻找相同主域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

  1. 在a.com网站添加一个空HTML页。名称为:http://a.com/null.html (用于实现二次跳转) 
    这里写图片描述
  2. 在a.com网站须要获取数据页面(如:http://a.com/getDomainData.html)获取数据]![获取数据
  3. 在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,仅做为演示 
origin示意图