CORS——跨域请求那些事儿

 

【本期嘉宾介绍】睿得,具有多年研发、运维、安全等IT相关从业经历。目前从事CDN、存储、视频直播点播的技术支持。喜爱钻研,喜爱编码,喜爱分享。


699a892b2bcb6e4fe72e215c530339d87f32c2af
在日常的项目开发时会不可避免的需要进行跨域操作,而在实际进行跨域请求时,经常会遇到类似 No 'Access-Control-Allow-Origin' header is present on the requested resource.这样的报错。

这样的错误,一般是由于CORS跨域验证机制设置不正确导致的,本文将详细讲解CORS跨域验证机制的原理,让您轻松掌握CORS跨域设置的使用方法,安全、方便的进行前端开发。

什么是CORS

CORS(Cross-Origin Resource Sharing 跨源资源共享),当一个请求url的协议、域名、端口三者之间任意一与当前页面地址不同即为跨域。

例如最常见的,在一个域名下的网页中,调用另一个域名中的资源。

相对于上面这种静态的调用方式,还可以通过Ajax技术来动态发起跨域请求。例如如下的方式,利用XMLHttpRequest对象发送一个GET请求,获取另一个域名下的图片内容。

<!DOCTYPE html> 
<html><head>CORS Test</head><body><div id="img_Div"></div><script type="text/javascript">  //XmlHttpRequest对象  function createXmlHttpRequest(){  if(window.ActiveXObject){ //如果是IE浏览器  return new ActiveXObject("Microsoft.XMLHTTP");  }else if(window.XMLHttpRequest){ //非IE浏览器  return new XMLHttpRequest();  }  }  function getFile() {var img_Container = document.getElementById("img_Div");var xhr = createXmlHttpRequest();xhr.open('GET', 'http://oss.youkouyang.com/1.jpg', true);xhr.setRequestHeader('Content-Type', 'image/jpeg');xhr.responseType = "blob";xhr.onload = function() {if (this.status == 200) {var blob = this.response;var img = document.createElement("img");img.onload = function(e) {window.URL.revokeObjectURL(img.src); };img.src = window.URL.createObjectURL(blob);img_Container.appendChild(img);    }}xhr.send(null);}</script><div class="row"><input type="button" onclick="getFile()" value="Get" /></div></body>
</html>  

CORS的作用

为了改善网络应用程序,开发人员要求浏览器供应商允许跨域请求。跨域请求主要用于:

  • 调用XMLHttpRequest或fetchAPI通过跨站点方式访问资源
  • 网络字体,例如Bootstrap(通过CSS使用@font-face 跨域调用字体)
  • 通过canvas标签,绘制图表和视频。

CORS的安全隐患

跨域请求和Ajax技术都会极大地提高页面的体验,但同时也会带来安全的隐患,其中最主要的隐患来自于CSRF(Cross-site request forgery)跨站请求伪造。

CSRF攻击的大致原理是:

  1. 用户通过浏览器,访问正常网站A(例如某银行),通过用户的身份认证(比如用户名/密码)成功A网站。
  2. 网站A产生Cookie信息并返回给用户的浏览器; 
  3. 用户保持A网站页面登录状态,在同一浏览器中,打开一个新的TAB页访问恶意网站B;
  4. 网站B接收到用户请求后,返回一些攻击性代码,请求A网站的资源(例如转账请求);
  5. 浏览器执行恶意代码,在用户不知情的情况下携带Cookie信息,向网站A发出请求。
  6. 网站A根据用户的Cookie信息核实用户身份(此时用户在A网站是已登录状态),A网站会处理该请求,导致来自网站B的恶意请求被执行。

CORS验证机制

出于安全原因,浏览器限制从脚本中发起的跨域HTTP请求。默认的安全限制为同源策略, 即JavaScript或Cookie只能访问同域下的内容。
W3C推荐了一种跨域的访问验证的机制,即CORS(Cross-Origin Resource Sharing 跨源资源共享)。
这种机制让Web应用服务器能支持跨站访问控制,使跨站数据传输更加安全,减轻跨域HTTP请求的风险。
CORS验证机制需要客户端和服务端协同处理。

CORS浏览器支持情况

目前主流浏览器都已基本提供对跨域资源共享的支持,移动端浏览器也几乎全部支持。


客户端处理机制

基于上述的CSRF的风险,各主流的浏览器都会对动态的跨域请求进行特殊的验证处理。验证处理分为简单请求验证处理和预先请求验证处理。

简单请求

当请求同时满足下面两个条件时,浏览器会直接发送GET请求,在同一个请求中做跨域权限的验证。

请求方法是下列之一:

  • GET
  • HEAD
  • POST

请求头中的Content-Type请求头的值是下列之一:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

简单请求时,浏览器会直接发送跨域请求,并在请求头中携带Origin 的header,表明这是一个跨域的请求。
服务器端接到请求后,会根据自己的跨域规则,通过Access-Control-Allow-Origin和Access-Control-Allow-Methods响应头,来返回验证结果。
如果验证成功,则会直接返回访问的资源内容。


如果验证失败,则返回403的状态码,不会返回跨域请求的资源内容。


可以通过浏览器的Console查看具体的验证失败原因

预先请求

当请求满足下面任意一个条件时,浏览器会先发送一个OPTION请求,用来与目标域名服务器协商决定是否可以发送实际的跨域请求。

请求方法不是下列之一:

  • GET
  • HEAD
  • POST

请求头中的Content-Type请求头的值不是下列之一:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

 

浏览器在发现页面中有上述条件的动态跨域请求的时候,并不会立即执行对应的请求代码,而是会先发送Preflighted requests(预先验证请求),Preflighted requests是一个OPTION请求,用于询问要被跨域访问的服务器,是否允许当前域名下的页面发送跨域的请求。 

 

OPTIONS请求头部中会包含以下头部:Origin、Access-Control-Request-Method、Access-Control-Request-Headers。
服务器收到OPTIONS请求后,设置Access-Control-Allow-Origin、Access-Control-Allow-Method、Access-Control-Allow-Headers头部与浏览器沟通来判断是否允许这个请求。
如果Preflighted requests验证通过,浏览器才会发送真正的跨域请求。
  

如果Preflighted requests验证失败,则会返回403状态,浏览器不会发送真正的跨域请求。
 

 可以通过浏览器的Console查看具体的验证失败原因

 

带认证的请求

默认情况下,跨源请求不提供凭据(cookie、HTTP认证及客户端SSL证明等)。通过将withCredentials属性设置为true,可以指定某个请求应该发送凭据。
xhr.withCredentials = true;
如果服务器接收带凭据的请求,会用下面的HTTP头部来响应。
Access-Control-Allow-Credentials: true
服务器还可以在Preflight响应中发送这个HTTP头部,表示允许源发送带凭据的请求。


如果发送的是带凭据的请求,但服务器的响应中没有包含这个头,那么浏览器就不会把响应交给JavaScript(responseText中将是空字符串,size为0)。

注意,当withCredentials属性设置为true,需要response header中的'Access-Control-Allow-Origin'为一个确定的域名,而不能使用'*'这样的通配符。

服务端处理机制

服务器端对于跨域请求的处理流程如下:

  1. 首先查看http头部有无origin字段;
  2. 如果没有,或者不允许,直接当成普通请求处理,结束;
  3. 如果有并且是允许的,那么再看是否是preflight(method=OPTIONS);
  4. 如果不是preflight(简单请求),就返回Allow-Origin、Allow-Credentials等,并返回正常内容。
  5. 如果是preflight(预先请求),就返回Allow-Headers、Allow-Methods等,内容为空;

HTTP Header

Request header

Origin

Origin头在跨域请求或预先请求中,标明发起跨域请求的源域名。

Access-Control-Request-Method

Access-Control-Request-Method头用于表明跨域请求使用的实际HTTP方法

Access-Control-Request-Headers

Access-Control-Request-Headers用于在预先请求时,告知服务器要发起的跨域请求中会携带的请求头信息

Response header

Access-Control-Allow-Origin

Access-Control-Allow-Origin头中携带了服务器端验证后的允许的跨域请求域名,可以是一个具体的域名或是一个*(表示任意域名)。简单请求时,浏览器会根据此响应头的内容决定是否给脚本返回相应内容,预先验证请求时,浏览器会根据此响应头决定是否发送实际的跨域请求。

Access-Control-Expose-Headers

Access-Control-Expose-Headers头用于允许返回给跨域请求的响应头列表,在列表中的响应头的内容,才可以被浏览器访问。

Access-Control-Max-Age

Access-Control-Max-Age用于告知浏览器可以将预先检查请求返回结果缓存的时间,在缓存有效期内,浏览器会使用缓存的预先检查结果判断是否发送跨域请求。

Access-Control-Allow-Credentials

Access-Control-Allow-Credentials用于告知浏览器当withCredentials属性设置为true时,是否可以显示跨域请求返回的内容。简单请求时,浏览器会根据此响应头决定是否显示响应的内容。预先验证请求时,浏览器会根据此响应头决定在发送实际跨域请求时,是否携带认证信息。

Access-Control-Allow-Methods

Access-Control-Allow-Methods用于告知浏览器可以在实际发送跨域请求时,可以支持的请求方法,可以是一个具体的方法列表或是一个*(表示任意方法)。简单请求时,浏览器会根据此响应头的内容决定是否给脚本返回相应内容,预先验证请求时,浏览器会根据此响应头决定是否发送实际的跨域请求。

Access-Control-Allow-Headers

Access-Control-Allow-Headers用于告知浏览器可以在实际发送跨域请求时,可以支持的请求头,可以是一个具体的请求头列表或是一个*(表示任意请求头)。简单请求时,浏览器会根据此响应头的内容决定是否给脚本返回相应内容,预先验证请求时,浏览器会根据此响应头决定是否发送实际的跨域请求。 

配置CORS规则

nginx上的CORS配置

OSS上的CORS配置 

CDN上的CORS配置

注意:由于CDN的缓存特性,CDN配合OSS时,需要在CDN中设置CORS配置。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/282896.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

oracle 数据执行计划,Oracle里常见的执行计划

本文介绍了Oracle数据库里常见的执行计划&#xff0c;使用的Oracle数据库版本为11.2.0.1。1、与表访问相关的执行计划Oracle数据库里与表访问有关的两种方法&#xff1a;全表扫描和ROWID扫描。反映在执行计划上&#xff0c;与全表扫描对应的执行计划中的关键字是“TABLE ACCESS…

.NET MAUI实战 Dispatcher

详细内容这一期分享的内容非常简单&#xff0c;在之前使用过WPF的开发者对MVVM开发模式下ViewModel中后台线程转UI线程并不陌生使用Appplication.Current.Dispatcher。那么在.NET MAUI中也有同样的机制&#xff0c;存在于.NET MAUI Shell对象中。那么什么是Shell&#xff1f;官…

GDB 配置

GDB 配置 使用 GDB 扩展来配置 GDB 事实上我还是觉得原生的 GDB 就挺好&#xff0c;速度快&#xff0c;需要查看什么执行命令就可以。 GDB DashBoard https://github.com/cyrus-and/gdb-dashboard $sudo mkdir -m 777 ~/gdbinit; cd ~/gdbinit $git clone https://github.com/c…

Oracle区分中文和英文,oracle中中英文段落划分实现

oracle中关于中文占用字节数&#xff0c;不同的数据库有不同的情况&#xff0c;有的占用两个字节、有的占用三个字节&#xff0c;现在测试环境的数据库中文占用三个字节&#xff0c;要实现由中英文组成的段落字符串&#xff0c;按照每行占用多少字节重新分段&#xff0c;具体应…

虚拟机网络配置详解(NAT、桥接、Hostonly)

VirtualBox中有四种网络连接方式: NATBridged AdapterInternalHost-only AdapterVMWare中有三种&#xff0c;其实它跟VMWare的网络连接方式都是一样的概念&#xff0c;只是比VMWare多了Internal方式 在介绍四种工作模式之前&#xff0c;先说下虚拟网卡&#xff0c;虚拟机安装好…

微软宣布正式开源 Azure IoT Edge 边缘计算服务

开发四年只会写业务代码&#xff0c;分布式高并发都不会还做程序员&#xff1f; 微软宣布&#xff0c;去年年底公开预览的 Azure IoT Edge 边缘计算服务已进入官方版&#xff0c;并通过 GitHub 将其开源。Azure IoT Edge 主要将基于云的分析和定制的业务逻辑转移到边缘设备&a…

Windows下安装BeautifulSoup

电脑首先要安装好了python&#xff0c;我安装的是2.7。 下面就是bs4的安装过程了: 1.去官网下载BeautifulSoup4 2017.02.10目前最新版本&#xff1a;Beautiful Soup 4.3.2 2.解压文件 将下载得到的压缩包解压到任意文件夹&#xff0c;路径不含中文 3.打开cmd命令提示符 winr&am…

BZOJ1578: [Usaco2009 Feb]Stock Market 股票市场

S<50只股票D<10天的价格给出&#xff0c;求第一天开始用n<200000元最后能得到的最大钱数&#xff0c;保证答案<500000。 做D次完全背包即可&#xff0c;每次做完把dp数组清空。 1 #include<cstdio>2 #include<cstring>3 #include<algorithm>4 #i…

OC如何跳到系统设置里的各种设置界面

当 iOS系统版本 < iOS7时 , 只能跳转到 系统设置页面 &#xff0c;楼主试了下&#xff0c;非真机是没有任何效果的 当iOS系统版本 < iOS 10.0 时 NSURL *url [NSURL URLWithString:"prefs:rootLOCATION_SERVICES"]; if( [[UIApplication sharedApplication]can…

虚拟DOM Diff算法解析

React中最神奇的部分莫过于虚拟DOM&#xff0c;以及其高效的Diff算法。这让我们可以无需担心性能问题而”毫无顾忌”的随时“刷新”整个页面&#xff0c;由虚拟DOM来确保只对界面上真正变化的部分进行实际的DOM操作。React在这一部分已经做到足够透明&#xff0c;在实际开发中我…

Azure 跨订阅迁移资源踩坑记

突然收到微软的邮件&#xff0c;提示我的一个 Azure 订阅已经到期&#xff0c;所以转为“禁用”状态&#xff0c;只能进行数据的导出和处理。在这个订阅里有不少较重要的资源在跑&#xff0c;直接关了可不行…于是开启了一个支持事件&#xff0c;台湾美眉的态度和声线真的没话说…

《ASP.NET Core 6框架揭秘》实例演示[25]:配置与承载环境的应用

与服务注册一样&#xff0c;针对配置的设置同样可以采用三种不同的编程模式。第一种是利用WebApplicationBuilder的Host属性返回的IHostBuilder对象&#xff0c;它可以帮助我们设置面向宿主和应用的配置。IWebHostBuilder接口上面同样提供了一系列用来对配置进行设置的方法&…

Linux日志出现大量kernel: NET: Registered protocol family 36

一台Linux服务器的系统错误日志出现大量的“ kernel: NET: Registered protocol family 36”错误信息&#xff0c;如下所示&#xff1a; Jul 2 05:27:45 xxxxxx kernel: NET: Registered protocol family 36Jul 2 05:27:45 xxxxxx kernel: NET: Unregistered protocol family…

node的模块机制

Node.js模块的实现 之前在网上查阅了许多介绍Node.js的文章&#xff0c;可惜对于Node.js的模块机制大都着墨不多。在后续介绍模块的使用之前&#xff0c;我认为有必要深入一下Node.js的模块机制。 CommonJS规范 早在Netscape诞生不久后&#xff0c;JavaScript就一直在探索本地编…

httpstat:一个检查网站性能的 curl 统计分析工具

httpstat&#xff1a;一个检查网站性能的 curl 统计分析工具httpstat 是一个 Python 脚本&#xff0c;它以美妙妥善的方式反映了 curl 统计分析&#xff0c;它是一个单一脚本&#xff0c;兼容 Python 3 &#xff0c;在用户的系统上不需要安装额外的软件(依赖)。作者&#xff1a…

关于面试中看到一些问题

最近公司在招聘.NET开发人员&#xff0c;面试了一些人&#xff0c;有一些感悟&#xff0c;分享出来&#xff0c;以供参考。面试的人员中&#xff0c;有一些是三五年的开发人员&#xff1b;也有几个是10年左右的技术负责人&#xff0c;不但自己架构过项目&#xff0c;还有带领导…

一个countDown在多线程调度下使用不当的分享

2019独角兽企业重金招聘Python工程师标准>>> 一个countDown在多线程调度下使用不当的分享 1. 诡异的数据抖动 在一个需求开发过程中&#xff0c;由于有多角色需要获取每个角色下的菜单&#xff1b;结果出现了单角色下拉去菜单没问题&#xff0c;多角色情况下只有一个…

linux脚本打印循环次数,shell脚本编程基础(3)——循环用法

本节索引&#xff1a;一、if、case条件判断二、for、while及until循环三、循环控制语句continue、break、shift及select菜单四、信号捕捉trap在前面的基础编程内容中&#xff0c;我们已经学习了shell脚本的顺序执行及选择执行&#xff0c;通过这两种方式&#xff0c;可以帮我们…

EF CORE 7 中的新功能:使用 ExecuteDelete 和 ExecuteUpdate 进行批量操作

原文链接&#xff1a;https://timdeschryver.dev/blog/new-in-entity-framework-7-bulk-operations-with-executedelete-and-executeupdate原文作者&#xff1a;tim_deschryver翻译&#xff1a;沙漠尽头的狼(谷歌翻译加持)Entity Framework 7 包括一些已被要求的流行功能&#…

java 简单json和对象相互转换

2019独角兽企业重金招聘Python工程师标准>>> package Fasterxml; import com.fasterxml.jackson.databind.ObjectMapper; import mode.User; import java.io.StringWriter; import java.util.ArrayList; import java.util.List;/*** maven...**<dependency>* …