关注公众号“执鸢者”,回复“红宝书”获取“javaScript高级程序第四版(pdf)”及大量前端学习材料。

跨域问题始终是面试中的经典问题,不论是前端老鸟还是新鸟都碰到过。其中针对跨源Ajax申请中有一个终极解决办法——CORS(跨源资源共享)大家必定也不生疏,一说这个名词,咱们就会哗啦哗啦说进去一套又一套的理论知识,然而这些理论知识很多咱们做的仅仅是去背诵,很少去验证每一个实践点,本节咱们将通过试验的形式去验证这些实践点,通过实践与实际相结合的形式彻底了解CORS。

一、理论知识

既然是CORS,背背这些实践点必定不为过吧,我就用三幅图对这个实践进行一些简略的总结

1.1 申请类型

1.1.1 简略申请

1.1.2 非简略申请

1.2 申请如何带上Cookie信息

二、试验

为试验做好后期筹备工作,蕴含一个html页面和一个服务器程序,其中html拜访网址为http://127.0.0.1:8009; 服务器监听端口为:8010.
  1. html页面初始代码
<!DOCTYPE html><html>    <head>        <meta charset="UTF-8">        <title>test CORS</title>    </head>    <body>        CORS        <script src="https://code.bdstatic.com/npm/axios@0.20.0/dist/axios.min.js"></script>        <script>            axios('http://127.0.0.1:8010', {                method: 'get'            }).then(console.log)        </script>    </body></html>
  1. 服务器端代码(用express框架)
const express = require('express');const app = express();app.get('/', (req, res) => {    console.log('get申请收到了!!!');    res.send('get申请曾经被解决');})app.listen(8010, () => {    console.log('8010 is listening')});

2.1 试验一

试验目标:

  1. 非同源会产生跨域问题
  2. 跨域是浏览器对响应拦挡造成的
  1. 首先来看看浏览器控制台内容

控制台内容显示报错,报错内容是跨域,这是因为端口不同(一个8009一个8010),两者不同源,所以导致跨域,验证了试验目标1.
  1. 紧接着来瞅瞅服务器控制台打印了啥内容

控制台内容打印了接管到了get申请,则证实浏览器的申请收回了并被服务器端失常接管,从侧面证实了跨域是浏览器对响应进行了拦挡,从而验证了试验目标2.

2.2 试验二

试验目标

  1. 服务器配置Access-Control-Allow-Origin会解决跨域问题
  2. 浏览器通过响应头中是否蕴含Access-Control-Allow-Origin这个响应头的值与申请头中Origin是否相等来确定是否可能进行跨域拜访
  1. 首先来搂一眼申请头

  1. 紧接着再来搂一眼响应头

依照实践来说,申请头中的Origin字段示意本次申请来自哪个源(协定+域名+端口),服务器依据这个值来决定是否批准这次申请。如果Origin指定的源不在许可范畴内,服务器会返回一个失常的HTTP回应。目前并没有批改,还处于报错状态,该响应的确是一个失常响应,不蕴含Access-Control-Allow-Origin字段,然而这也不足以压服我浏览器是通过验证该字段来的确是否容许跨域申请。所以紧接着须要做一个比照试验,通过批改服务端的代码后察看响应头内容。
  1. 从最简略的批改开始,间接将响应头中退出Access-Control-Allow-Origin=“http://127.0.0.1:8009” 字段,实践上来说此时会容许所有的跨域申请。
服务端代码批改后内容
app.get('/', (req, res) => {    console.log('get申请收到了!!!');    res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:8009');    res.send('get申请曾经被解决');})
响应头内容

察看到响应头中多了一行内容:Access-Control-Allow-Origin:http://127.0.0.1:8009 字段,在看看响应内容,的确有音讯返回了,内容如下:

  1. 只验证了Origin和Access-Control-Allow-Origin中内容响应,若内容不同又会有什么景象呢?
服务端代码进一步批改
app.get('/', (req, res) => {    console.log('get申请收到了!!!');    res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:8008');    res.send('get申请曾经被解决');})
响应头内容

此时浏览器控制台报错了,呈现了跨域问题

通过该试验能够验证通过配置Access-Control-Allow-Origin字段能够解决跨域问题;此外,浏览器是通过查看响应头中Access-Control-Allow-Origin字段的值与Origin的值是否相等来确定是否容许跨域拜访的。通过该试验达到了咱们试验的目标。

2.3 试验三

试验目标
验证CORS申请默认不发送Cookie信息,如果要把Cookie发送到服务器,一方面要服务器批准(通过指定Access-Control-Allow-Origin字段且Access-Control-Allow-Origin须要指定具体域名);另一方面浏览器申请中必须带上withCredentials字段。
  1. 通过观察申请头(看试验一中申请头),并不蕴含Cookie信息
  2. 代码批改
index.html页面进行批改
axios('http://127.0.0.1:8010', {    method: 'get',    withCredentials: true}).then(console.log)
服务器端代码批改
app.get('/', (req, res) => {    console.log('get申请收到了!!!');    console.log('cookie 内容为', req.headers.cookie);    res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:8009');    res.setHeader('Access-Control-Allow-Credentials', true);    res.cookie('test', 'test', {expires: new Date(Date.now() + 900000)});    res.send('get申请曾经被解决');})
  1. 再次察看申请头内容,带上了cookie

  1. 看看服务器端有没有接管到cookie信息,控制台信息如下,的确收到了cookie信息

依照上述进行配置发送申请过程中将会带着cookie信息,上一个配置将会报错(能够自行验证)

2.4 试验四

试验目标

  1. 验证非简略申请会减少一次预检申请
  2. 预检申请是Options申请
  3. 申请头中会携带非简略申请的申请办法(Access-Control-Request-Methods)和头信息(Access-Control-Request-Headers),预检申请的响应头信息中Access-Control-Allow-Methods和Access-Control-Allow-Headers与上述申请头中的信息匹配才能够发送失常的CORS申请。
  1. 第一步必定是要批改代码了
index.html代码
axios('http://127.0.0.1:8010', {    method: 'post',    headers: {        'Content-Type': 'application/json'    },    data: {        name: 'dog'    }}).then(console.log)
服务器代码批改如下
app.options('/', (req, res) => {    console.log('options申请收到了!!!');    res.setHeader('Access-Control-Allow-Origin', '*');    res.setHeader('Access-Control-Allow-Headers', 'Content-Type');    res.setHeader('Access-Control-Max-Age', 10000);    res.send('options申请曾经被解决');});app.post('/', (req, res) => {    console.log('post申请收到了!!!');    res.setHeader('Access-Control-Allow-Origin', '*');    res.send('post申请曾经被解决');});
  1. 批改完了代码是不是要瞅瞅后果呢?
先看看浏览器是不是输入了内容,的确有内容输入了

再瞅瞅服务器输入了些什么内容

能够看到原本打算发一次申请,但实际上发了两条,第一条是Options申请,第二条申请才是post申请,上述打印内容验证了试验目标中的一和二。

  1. 上面持续深刻思考,来看看预检申请的申请头和响应头
申请头内容

响应头内容

上述Access-Control-Request-Headers与Access-Control-Allow-Headers一样,而且内容也失常返回了(步骤二中曾经进行了展现),然而这不足以证实试验目标三,上面咱们认为减少一条头信息再来看后果。

  1. 人为减少一条申请头信息
index.html页面批改后如下
axios('http://127.0.0.1:8010', {    method: 'post',    headers: {        'Content-Type': 'application/json',        'Test': 'test'    },    data: {        name: 'dog'    }}).then(console.log)
此时浏览器控制台报错了

服务端只接管到了options申请

申请头信息为

响应头信息为

通过该试验证实只有Access-Control-Request-Headers与Access-Control-Allow-Headers相等的时候,预检申请才会通过,后续申请才会收回,从而达到了该试验的试验目标三。

1.如果感觉这篇文章还不错,来个分享、点赞吧,让更多的人也看到

2.关注公众号执鸢者,支付学习材料,定期为你推送原创深度好文