🥇 为什么会出现跨域问题

出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)

🥇 什么是跨域

当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域
image.png

🥇 非同源限制

无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB
无法接触非同源网页的 DOM
无法向非同源地址发送 AJAX 请求

🥇 跨域行为发生在哪里

即使跨域了( 协议,域名,端口号有一个不一样的 ),请求也是可以发出的
服务器端也是可以接收的
服务器端也是可以正常处理的
服务端也是可以正常返回数据的
浏览器也能接收到这些数据
接收到之后,发现当前页面的域和请求的域不同,所有判断为跨域

🥇 解决跨域

🥈 需要后端支持方法

JSONP( 正常的情况,返回的数据都是 JSON 格式,JSONP 是一种特殊的格式)
response 设置响应头,解决跨域请求问题,No ‘Access-Control-Allow-Origin’ header is present on the requested resource

🥈 CORS 解决方法

Cross-origin resource sharing 跨域资源共享

🥉 特点

后端返回的响应头会自动携带 Access-Control-Allow-Origin字段

🥉 实现流程

整个 CORS 通信过程,都是浏览器自动完成, 对于开发者来说,CORS通信与同源的AJAX通信没有差别,浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉, 只是在被请求的服务端响应的时候添加一个 AccessControl-Allow-Origin 的响应头,表示这个资源是否允许指定域请求.

🥉 cors的两种请求方式:

🏅 简单请求

只要同时满足以下两大条件,就属于简单请求
请求方法是以下三种方法之一:

  1. - HEAD
  2. - GET
  3. - POST

HTTP 的头信息不超出以下几种字段:

  1. - Accept
  2. - Accept-Language
  3. - Content-Language
  4. - Last-Event-ID
  5. - Content-Type:只限于三个值`application/x-www-form-urlencoded`、`multipart/form-data`、`text/plain`

🏅 非简单请求

非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUTDELETE,或者Content-Type字段的类型是application/json
非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为”预检”请求(preflight)。
浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,返回状态码204, 否则就报错,返回状态码405

🥈 JSONP 解决方法

JSONP是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,老式浏览器全部支持,服务器改造非常小

🥉 实现原理

网页通过添加一个<script>元素,向服务器请求JSON数据,利用src属性不受同源策略影响的特点;服务器收到请求后,将数据放在一个指定名字的回调函数里作为形参传回来,前端拿到这个形参,就是本次请求的结果.

🥉 特点

只接受GET请求的形式;
需要与后端进行请求参数的约定
有参数数据大小的限制
不是一个真正的ajax请求

  1. var scriptNode = document.createElement('script')
  2. scriptNode.src = 'http://localhost:3000/?callback=responseFn';
  3. document.body.append(scriptNode)
  4. function responseFn(res) {
  5. console.log(res)
  6. }

🥈 proxy 代理解决办法

🥉 实现方法

本地开启代理服务器,前端代码在代理环境下进行开发,请求由代理服务器进行转发,服务器与服务器之间不涉及到跨域问题

🥉 常见的代理方式

liveServer => IDE的三方插件
webpack devServer => 前端工程化构建工具
nginx => nginx服务器代理

🥉 liveServer 代理服务配置方法

visual studio code 安装 live-server 插件
在设置中进行找到 liveServer 的配置项
添加proxy代理设置
选项信息: enable => 是否可使用代理,选择 true ; baseUri => 当前项目中的需要代理地址的基础路径 => proxyUri => 需要代理到哪一个服务器
选择完成之后,重新启动liveServer 实现代理成功
image.png

🥈 iframe跨域解决办法 -( 只能显示不能控制 )

🥉 postMessage

该方法为html5扩展的API,允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递;

🥉 实现流程

🏅 父页面像子页面进行数据的传递

父页面找到iframe标签,为ifrme的window(iframe.contentWindow获取)定义绑定postMessage事件(必须保证页面全部加载完成之后使用该事件)

  1. iframe.onload = function() {
  2. iframe.contentWindow.postMessage('父页面传递给子页面的用户信息', 'http://127.0.0.1:5501/iframe.html')
  3. }

子页面window进行message事件的监听,通过回调函数获取父页面传递的信息

  1. window.addEventListener('message', function(res) {
  2. parentTxt.innerHTML = res.data
  3. })

🏅 子页面像父页面进行数据的传递

子页面获取父页面的window(window.parent获取父级window),进行postMessage事件注册

子页面
  1. // 子页面的点击事件触发像父页面进行发送数据的事件
  2. closeBtn.onclick = function() {
  3. //window.parent 获取父级的window
  4. window.parent.postMessage("关闭ifrmae页面", 'http://127.0.0.1:5500/home.html')
  5. }

父页面
  1. // 进行message事件的监听处理
  2. window.addEventListener('message', function(res) {
  3. frameContainer.style.display = 'none'
  4. })

🥈 WebSocket

Websocket是HTML5的一个持久化的协议,它实现了浏览器与服务器的全双工通信,同时也是跨域的一种解决方案。WebSocket和HTTP都是应用层协议,都基于 TCP 协议。但是 WebSocket 是一种双向通信协议,在建立连接之后,WebSocket 的 server 与 client 都能主动向对方发送或接收数据。同时,WebSocket 在建立连接时需要借助 HTTP 协议,连接建立好了之后 client 与 server 之间的双向通信就与 HTTP 无关了。
原生 WebSocket API 使用起来不太方便,我们使用 Socket.io,它很好地封装了webSocket接口,提供了更简单、灵活的接口,也对不支持webSocket的浏览器提供了向下兼容。
image.png