理论与实践相结合彻底理解CORS

简介: 理论与实践相结合彻底理解CORS

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


一、理论知识



既然是CORS,背背这些理论点肯定不为过吧,我就用三幅图对这个理论进行一些简单的总结

1.1 请求类型


1.1.1 简单请求

640.jpg

1.1.2 非简单请求


640.jpg


1.2 请求如何带上Cookie信息

640.jpg

二、实验



为实验做好前期准备工作,包含一个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. 首先来看看浏览器控制台内容

640.png

控制台内容显示报错,报错内容是跨域,这是因为端口不同(一个8009一个8010),两者不同源,所以导致跨域,验证了实验目的1.


  1. 紧接着来瞅瞅服务器控制台打印了啥内容

640.png

控制台内容打印了接收到了get请求,则证明浏览器的请求发出了并被服务器端正常接收,从侧面证明了跨域是浏览器对响应进行了拦截,从而验证了实验目的2.


2.2 实验二


实验目的

  1. 服务器配置Access-Control-Allow-Origin会解决跨域问题
  2. 浏览器通过响应头中是否包含Access-Control-Allow-Origin这个响应头的值与请求头中Origin是否相等来确定是否能够进行跨域访问


  1. 首先来搂一眼请求头

640.png


紧接着再来搂一眼响应头

640.png


按照理论来说,请求头中的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请求已经被处理');
})

响应头内容

640.png

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


640.png


  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请求已经被处理');
})

响应头内容


640.png

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

640.png


通过该实验可以验证通过配置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信息


  1. 代码修改


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

640.png

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

640.png


按照上述进行配置发送请求过程中将会带着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. 修改完了代码是不是要瞅瞅结果呢?


先看看浏览器是不是输出了内容,确实有内容输出了

640.png


可以看到本来打算发一次请求,但实际上发了两条,第一条是Options请求,第二条请求才是post请求,上述打印内容验证了实验目的中的一和二。


  1. 下面继续深入思考,来看看预检请求的请求头和响应头


请求头内容

640.png


响应头内容


640.png


上述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)

此时浏览器控制台报错了

640.png

服务端只接收到了options请求

640.png

请求头信息为


640.png

响应头信息为


640.png


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

相关文章
|
8月前
|
人工智能 前端开发 测试技术
AI:探究下前端组件化设计的实现方法及其重要性(一)
AI:探究下前端组件化设计的实现方法及其重要性
|
8月前
|
人工智能 缓存 前端开发
AI:探究下前端组件化设计的实现方法及其重要性(二)
AI:探究下前端组件化设计的实现方法及其重要性
|
8月前
|
JSON 前端开发 安全
前端开发中的跨域解决方案探究
跨域是前端开发中常见的问题之一,本文将探讨跨域的概念、产生的原因,以及常见的解决方案,包括JSONP、CORS、代理等。通过本文的学习,读者可以深入了解跨域问题及解决方案,为自己的前端开发工作提供参考。
|
2月前
|
监控 安全 持续交付
深入探讨 Webhook 的本质、工作原理以及其在不同领域的应用,帮助你更好地理解和运用这一技术
Webhook是一种在特定事件发生时,由服务器主动向客户端发送通知的机制,实现数据的实时、高效传递。本文介绍Webhook的基本概念、工作原理、应用场景及设置使用方法,探讨其优势与挑战,帮助读者更好地理解和应用这一技术。
130 7
|
3月前
|
存储 缓存 算法
前端算法:优化与实战技巧的深度探索
【10月更文挑战第21天】前端算法:优化与实战技巧的深度探索
34 1
|
3月前
|
机器学习/深度学习 人工智能 算法
揭开深度学习与传统机器学习的神秘面纱:从理论差异到实战代码详解两者间的选择与应用策略全面解析
【10月更文挑战第10天】本文探讨了深度学习与传统机器学习的区别,通过图像识别和语音处理等领域的应用案例,展示了深度学习在自动特征学习和处理大规模数据方面的优势。文中还提供了一个Python代码示例,使用TensorFlow构建多层感知器(MLP)并与Scikit-learn中的逻辑回归模型进行对比,进一步说明了两者的不同特点。
115 2
|
7月前
|
算法 量子技术 数据库
量子计算:从理论到实践的深度解析
在当前科技迅猛发展的时代,量子计算作为一项颠覆性的技术正在不断引起广泛关注。本文旨在深入探讨量子计算的理论基础、关键技术和实际应用,并分析其未来发展前景及面临的挑战。通过对量子比特、纠缠态和量子门操作等核心概念的详细阐述,读者将能够全面理解量子计算的基本原理和潜在影响。
114 0
|
8月前
|
资源调度 前端开发 JavaScript
第十章(应用场景篇) Single-SPA微前端架构深度解析与实践教程
第十章(应用场景篇) Single-SPA微前端架构深度解析与实践教程
266 0
|
5月前
|
缓存 前端开发 JavaScript
深入探讨前端性能优化:从理论到实践
在现代Web开发中,前端性能优化已成为提升用户体验的关键因素。本文将探讨前端性能优化的基本理论,并结合实际案例,深入分析如何通过优化代码、资源管理和用户交互,显著提升网站和应用的响应速度。我们将介绍从理论到实践的多种方法,包括资源压缩、异步加载、缓存机制及工具的使用,帮助开发者构建更加高效和用户友好的前端应用。
|
8月前
|
存储 缓存 算法
后端技术优化与应用研究
后端技术优化与应用研究
65 1