浏览器的跨域是什么?

浏览器的跨域是什么?解决方案是什么?

面试题

  • 什么是跨域,跨域是谁引起的?为什么服务端没有同源限制?
  • 什么是同源策略,为什么有同源策略?
  • CORS的相关请求头
  • 手写JSONP
  • 简单请求和非简单请求
  • options请求是什么?有什么作用?

同源策略

同源策略是浏览器的一种安全策略

同源策略:两个 URL 的协议域名端口都相同。
注意: 两个不同的域名指向同一个ip地址,也非同源。

浏览器默认两个相同的源之间是可以相互访问资源操作 DOM 的。

同源政策主要限制了三个方面

  • 当前域下的 js 脚本不能访问其他域下的 cookie、localStorage
  • 当前域下的 js 脚本不能操作访问操作其他域下的 DOM
  • 当前域下 ajax(XMLHttpRequest)等方式 无法发送跨域请求。

但是有三个标签是允许跨域加载资源:

  • <img src=XXX>
  • <link href=XXX>
  • <script src=XXX>

跨域问题

跨域问题的描述
违背了同源策略就是跨域
同源策略是浏览器的行为。当客户端向服务器请求数据,服务器返回数据给浏览器后,浏览器发现跨域(不是同源),不将数据给客户端

在这里插入图片描述

跨域问题的解决

  • Cross-Origin Resource Sharing CORS跨域资源共享
  • 代理服务器,代理服务器和客户端同源。服务器之间没有同源策略
  • JSONP 就是利用 <script> 标签没有跨域限制的漏洞
  • 跨文档消息机制,可以通过 window.postMessage 的 JavaScript 接口和不同源的 DOM 进行通信。

JSONP

JSONP (JSON with Padding)的原理很简单: 就是利用 <script> 标签没有跨域限制的漏洞。

主要实现
动态插入script标签,通过script标签引入一个js文件。
前端先定义一个回调函数,其参数是需要接受的数据。将该回调函数作为url的参数传给后端。告诉后端回调函数的名字。
后端将数据作为回调函数的参数传给浏览器。
浏览器执行后端返回的立即执行函数(前端定义的回调函数),获取到数据。

1.前端设置一个函数,动态创建一个 script 标签,通过callback参数告诉后端回调函数名叫handle

//1.动态创建 script
var script = document.createElement('script');

//2.处理数据的回调函数
function handle(data){
	//获取result元素
	console.log(data);
}

//3.设置 script 的 src 属性,告诉服务器回调函数是handle
script.src = 'http://localhost:3000/?callback=handle';

// 让 script 生效
document.body.appendChild(script);

2.需要后端配合,后端能够识别这样的 URL 格式并处理该请求,然后返回handle({"name": "ranan"}) 给浏览器。

const data = {
	name:'ranan'
}
handle(data)

3.浏览器在接收到 handle({"name": "ranan"}) 之后立即执行 handle方法(前端定义的),获得后端返回的数据,这样就完成一次跨域请求了。

JSONP 特点

  • 使用简单且兼容性不错,但是只限于 get 请求
  • JSONP 需要后端配合返回指定格式的数据。
  • 由于是从其它域中加载代码执行,因此如果其他域不安全,很可能会在响应中夹带一些恶意代码。

CORS 跨域资源共享

是什么?
浏览器提供了CORS 跨域资源共享机制,使用该机制可以进行跨域访问控制。 —> 浏览器会自动进行 CORS 通信,实现 CORS 通信的关键是后端。

浏览器一旦发现 AJAX 请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉

优点与缺点

优点

  • CORS 通信与同源的 AJAX 通信没有差别,代码完全一样,容易维护。
  • 支持所有类型的 HTTP 请求。

缺点

  • 第一次发送非简单请求时会多一次请求。
简单请求与非简单请求

简单请求

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

  • HEAD
  • GET
  • POST

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

  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-Type:只限于三个值 application/x-www-form-urlencodedmultipart/form-datatext/plain

同时满足以上两个条件就是简单请求。

简单请求的流程
1.在请求中需要附加一个额外的 Origin 头部,包含请求页面的源信息(协议、域名和端口),以便服务器根据这个头部信息来决定是否给予响应。例如:Origin: http://www.xxx.cn
2.如果服务器认为这个请求可以接受,就在 Access-Control-Allow-Origin 中回发相同的源信息(如果是公共资源,可以回发 * )。
3.没有这个头部或者有这个头部但源信息不匹配,浏览器就会驳回请求。

非简单请求

1.浏览器会在正式通信之前,增加一次HTTP查询请求。使用 OPTIONS 方法发起一个预检(preflight)请求到服务器。

目的是为了知道服务器是否允许该请求。
服务器成功响应预检请求后,浏览器才会发送真正的请求,并携带真实数据

  • Origin:与简单的请求相同。
  • Access-Control-Request-Method: 请求自身使用的方法。
  • Access-Control-Request-Headers: (可选)自定义的头部信息,多个头部以逗号分隔

2.服务器可以决定是否允许这种类型的请求。服务器通过在响应中发送如下头部与浏览器进行沟通:

  • Access-Control-Allow-Origin:与简单的请求相同。
  • Access-Control-Allow-Methods: 允许的方法,多个方法以逗号分隔。
  • Access-Control-Allow-Headers: 允许的头部,多个方法以逗号分隔。
  • Access-Control-Max-Age: 将这个 Preflifght 请求缓存多长时间(以秒表示)。

一旦服务器通过 Preflight 请求允许该请求之后,以后每次浏览器正常的 CORS 请求,就都跟简单请求一样了。

在这里插入图片描述

代理服务器 利用脚手架配置

代理服务器和客户端同源,两个相同的源之间是可以相互访问资源操作 DOM 的。
服务器和服务器之间没有同源策略。

修改vue.config.js

module.exports = {
	devServer:{
		proxy:{//遇见xxx前缀的请求,走代理去服务器端获取
			'/xxx':{
				target:'http:localhost:5000', //需要将请求转发到服务器的地址
			}
	}
}

H5新特性 postMessage

跨文档消息机制:通过使用window.postMessage(message,targetOrigin)和不同源的 DOM 进行通信。
发送方通过 postMessage API 来发送消息,而接收方可以通过监听 message 事件,来添加消息处理回调函数

iframe+postMessage

1.父窗口给子窗口发送消息的方式:
document.getElementById('myframe').contentWindow.postMessage('MessageFromIndex1','*');
其实就是在父窗口中操作子窗口发消息,然后让子窗口接收自己刚才发的消息。
2.子窗口给父窗口发送消息的方式:
window.parent.postMessage( {msg: 'MessageFromIframePage'}, '*');
注意:此处parent === window.parent,即子窗口的父窗口
其实就是在子窗口中操作父窗口发消息,然后让父窗口接收自己刚才发的消息。
总结:所谓的跨窗口发送消息,就是通过在别的窗口操作本窗口发送消息,然后本窗口再自己接收的方式实现。

iframe+postMessage跨域的具体实现
1.父窗口创建跨域iframe子窗口,子窗口的src就是目标通信的地址
2.父窗口给子窗口发送消息

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值