美文网首页
跨域通信

跨域通信

作者: 209bd3bc6844 | 来源:发表于2018-02-05 11:27 被阅读0次

阮一峰同源策略
浏览器处于安全考虑实行了同源策略机制。
同源指的是

  • 协议相同
  • 域名相同
  • 端口相同

举例来说,http://www.example.com/dir/page.html这个网址,协议是http://,域名是www.example.com,端口是80(默认端口可以省略)。
域名分为 顶级域名,一级域名,二级域名等。顶级域名就是一级域名,比如 .com .org .cn,N级域名就是在N-1级域名前追加一级。
非同源的话限制如下

  • Cookie、LocalStorage 和 IndexDB 无法读取。
  • DOM 无法获得。
  • AJAX 请求不能发送。

我们首先来看跨域如何请求

1. 跨域如何请求

1.1 JSONP

jsonp的实现是通过<script>标签,因为<script>标签是没有同源限制的。前端通过<script>标签发送请求带上例如callback=foo的参数。服务器收到这个请求以后,会将数据放在回调函数的参数位置返回。

//  前端
<script type="text/javascript" src="'http://example.com/ip?callback=foo"></script>
// 后端返回数据
foo({
  "ip": "8.8.8.8"
});

具有src属性的如img,iframe,srcipt都不受同源策略的影响,这样代码就可以正常请求数据并执行回调函数了。

1.2 CORS

CORS简介
CORS需要前后端同时支持,目前,所有浏览器都支持该功能,浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
主要就是后端设置以下几个响应头

Access-Control-Allow-Origin: http://api.bob.com  // 允许请求的来源
Access-Control-Allow-Credentials: true   // 表示是否允许发送Cookie
Access-Control-Expose-Headers: FooBar

跨域携带cookie设置withCredentials is true时候不能设置 Access-Control-Allow-Credentials 为* 参考

在使用CROS的时候我们的请求分为简单请求和非简单请求
只要同时满足以下两大条件,就属于简单请求。

(1) 请求方法是以下三种方法之一:

HEAD
GET
POST
(2)HTTP的头信息不超出以下几种字段:

Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

非简单请求会发预请求OPTIONS。预请求通过后才能发送真正的请求,预请求OPTINS失败的几个原因

如果'Content-Type': 'application/json'等非简单请求的内容跨域的时候回发options请求。并且


请求头会加上Access-Control-Request-Headers:content-type。这时候options在控制台看是200,但是不会发送真正的请求。所以服务器端还必须设置一个名为Access-Control-Allow-HeadersHeader,将它的值设置为 Content-Type,表明服务器能够接收到前端发送的请求中ContentType属性并使用它的值。
还有几种OPTIONS出错的场景参考链接
1.3 代理

之前写过一篇代理的文章

1.4 WebSocket

WebSocket是一种通信协议,使用ws://(非加密)和wss://(加密)作为协议前缀。该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。

2. cookie

document.domain 。
两个网页一级域名相同,只是二级域名不同,浏览器允许通过设置document.domain共享 Cookie。
A网页是http://w1.example.com/a.html,B网页是http://w2.example.com/b.html,那么只要设置相同的document.domain= 'example.com';,两个网页就可以共享Cookie。
这种方法只适用于 Cookie 和 iframe 窗口,LocalStorage 和 IndexDB 无法通过这种方法

3. iframe

如果两个网页不同源,就无法拿到对方的DOM。典型的例子是iframe窗口和window.open方法打开的窗口,它们与父窗口无法通信。

比如,父窗口运行下面的命令,如果iframe窗口不是同源,就会报错。
如果两个窗口一级域名相同,只是二级域名不同,那么设置上一节介绍的document.domain属性,就可以规避同源政策,拿到DOM。

对于完全不同源的网站,目前有三种方法,可以解决跨域窗口的通信问题。

片段识别符(fragment identifier)
window.name
跨文档通信API(Cross-document messaging)
3.1 片段识别符

就是Hash,URL的#号后面的部分,通过监听hashchange事件得到通知

3.2 window.name

浏览器窗口有window.name属性。这个属性的最大特点是,无论是否同源,只要在同一个窗口里,前一个网页设置了这个属性,后一个网页可以读取它。

3.3 H5的window.postMessage

postMessage:跨文档通信
postMessage作用简介
举例来说,父窗口http://aaa.com向子窗口http://bbb.com发消息,调用postMessage方法就可以了。

var popup = window.open('http://bbb.com', 'title');
popup.postMessage('Hello World!', 'http://bbb.com');

postMessage方法的第一个参数是具体的信息内容,第二个参数是接收消息的窗口的源(origin),即"协议 + 域名 + 端口"。也可以设为*,表示不限制域名,向所有窗口发送。

子窗口向父窗口发送消息的写法类似。

window.opener.postMessage('Nice to see you', 'http://aaa.com');

父窗口和子窗口都可以通过message事件,监听对方的消息。

window.addEventListener('message', function(e) {
  console.log(e.data);
},false);

跨域解决方案

相关文章

  • FE-interview-Q&A

    浏览器标签页通信 WebSocket (可跨域) postMessage(可跨域)iframe 父子通信np = ...

  • localStorage 如何跨域通信?

    cookie 跨域主要记住一个单词,如下: 看看 localStorage 如何跨域通信? 因为要跨域所以我们需要...

  • postMessage 相关漏洞分析与分享

    前言 postMessage API 是在 HTML5 中引入的通信方法,可以在标签中实现跨域通信。 跨域嘛,大家...

  • 跨域通信

    一、跨域and同源政策 1.跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对ja...

  • 跨域通信

    阮一峰同源策略浏览器处于安全考虑实行了同源策略机制。同源指的是 协议相同 域名相同 端口相同 举例来说,http:...

  • 跨域通信

    跨域通信常用的几种方式 1、JSONP 2、WebSocket 3、CORS 4、Hash 5、postMessa...

  • layui下,iframe父子窗口的通信

    iframe通信/跨域通信。http://fly.layui.com/jie/19251/ 待整理

  • 前端基础面试题

    1. 跨域问题 同源:两个文档需满足:协议相同,域名相同,端口相同。跨域通信 :js进行DOM操作、通信时如果目标...

  • 使用postMessage进行跨域通信

    跨域通信是前端开发中经常会遇到的情景,跨域通信有多种多样的方式,今天就详细说一下使用postMessage这样方式...

  • 2021-01-28面试题

    浏览器内多个标签页之间的通信方式有哪些 ? websocket 可跨域 postMessage 可跨域 work...

网友评论

      本文标题:跨域通信

      本文链接:https://www.haomeiwen.com/subject/eaatgxtx.html