浏览器解决跨域的方法

261 阅读3分钟

这是我参与8月更文挑战的第28天,活动详情查看:8月更文挑战

为什么会跨域

因为浏览器有同源策略,即:协议名、端口号、域名必须是源网站和请求地址保持一致;
当页面在执行一个脚本时,会检查访问的资源是否同源,如果不是,就会报错。
注意: 对于像 img、iframe、script 等标签的 src 属性是特例,它们是可以访问

跨域的解决方案

1、JSONP

这个方案就是利用了js标签的src属性不会跨域的原理。 具体实现如下:

// 第一步创建script标签
var script = document.createElement('script');
//第二补 将src变为要访问的网站
script.src = 'testJS.js'
// 第三步 将script添加入页面
document.body.appendChild(script);
// 定义函数操作获取的数据
function response(data) {
    console.log(data)
}

testJS.js

response(
    {
        a:1
    }
)

注解: script标签会执行所访问文件的内容,比如testJS.js。当把script加入页面后,会执行testJS文件,也即response({a:1})函数

JSONP的缺点
只支持GET请求;因为script标签只支持get请求

2、代理跨域

这个就是利用服务器代替浏览器去请求数据。因服务器之间的请求不会导致跨域的问题。
大概步骤

  1. 浏览器访问目标接口。(此时会可能跨域)
  2. 因为会跨域,所以由一个服务器将接口拦截,转为由服务器代发。(不会跨域)
  3. 请求回来之后,服务器将接口返回

这就是一个大概的服务器代理跨域。具体的代理服务器如何实现,留个坑,以后再详谈。

3、CORS跨域

全称:跨域资源共享 Cross-Origin Resource Sharing

优点: 可以携带cookie。

实现CORS的关键在于服务器,只要服务器实现CORS接口,就可以实现跨域通信。

CORS分为简单请求 和 非简单请求(需预检)两类。

简单请求

只要同时满足以下两大条件,就属于简单请求。

  1. 请求方法是以下三种方法之一:
  • HEAD
  • GET
  • POST
  1. HTTP的头信息不超出以下几种字段:
  • Accept

  • Accept-Language

  • Content-Language

  • Last-Event-ID

  • Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

非简单请求

注意: 非简单请求是那种对服务器有特殊要求的请求\

下面是一个非预检请求的http头部 "预检"请求用的请求方法是OPTIONS,表示这个请求是用来询问的。头信息里面,关键字段是Origin,表示请求来自哪个源。 除了Origin字段,"预检"请求的头信息包括两个特殊字段。

image.png

"预检"请求用的请求方法是OPTIONS,表示这个请求是用来询问的。头信息里面,关键字段是Origin,表示请求来自哪个源。
除了Origin字段,"预检"请求的头信息包括两个特殊字段:

  1. Access-Control-Request-Method
    该字段是必须的,用来列出浏览器的CORS请求会用到哪些HTTP方法,上例是PUT。

  2. Access-Control-Request-Headers
    该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段,上例是X-Custom-Header。

options请求的步骤

当发生符合非简单请求(预检请求)的条件时,浏览器会自动先发送一个options请求,如果发现服务器支持该请求,则会将真正的请求发送到后端,反之,如果浏览器发现服务端并不支持该请求,则会在控制台抛出错误,如下:

image.png

一旦服务器通过了"预检"请求,以后每次浏览器正常的CORS请求,就都跟简单请求一样,会有一个Origin头信息字段。服务器的回应,也都会有一个Access-Control-Allow-Origin头信息字段。

image.png