背景

早期为了避免 CSRF(跨站请求伪造) 攻击,浏览器引入了 “同源策略” 机制。如果两个 URL 的协议,主机名(域名/IP),端口号一致,则视为这两个 URL “同源”,属于同一个 “域”,否则视为 “非同源”,即 “跨域”。浏览器会主动拦截跨域的 AJAX 请求,以规避安全风险。

“同源策略” 固然提升了请求的安全性,但有时我们需要跨域请求其他域名下的资源,例如在业务域名下请求 COS 的 API 接口,或者读取 COS 存储桶中文件的内容,进行一些逻辑处理。

浏览器支持一种跨域的访问验证的机制,即 CORS(Cross-Origin Resource Sharing 跨源资源共享)。该机制允许服务端通过返回特定的 HTTP 头部来告知浏览器是否拦截跨域请求。

COS 支持用户在存储桶中配置 “跨域访问 CORS” 规则,以此放行一些合法的跨域请求。

业务场景

下面我们以 博客网站开发 为例,带您了解如何在 COS 配置 CORS 规则。

用户正在开发一个博客网站,为此他将一批 markdown 文件上传到 COS,对每个 markdown 文件设置了自定义头部 x-cos-meta-keywords 表示该文章的关键词,并将文件权限设置为公有读私有写。

网站的前端 JS 脚本通过浏览器向 COS 发起 AJAX 请求,读取响应的内容以及头部信息,将内容转换为 HTML 文本,解析 x-cos-meta-keywords 中包含的关键词,分别挂载到页面对应的 DOM 节点下,其请求过程如下图所示:

用户网站的地址是 http://example.com,Markdown 文件的地址是 https://bucketname-1250000000.cos.ap-guangzhou.myqcloud.com/test.md

很显然,这是在 http://example.com 下对 https://bucketname-1250000000.cos.ap-guangzhou.myqcloud.com 发起请求,涉及跨域。

不出意外地,浏览器拦截了该请求,打开浏览器的 Console 栏可以看到如下报错:

Access to XMLHttpRequest at 'https://bucketname-1250000000.cos.ap-guangzhou.myqcloud.com/test.md'
from origin 'http://example.com' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested resource. GET https://bucketname-1250000000.cos.ap-guangzhou.myqcloud.com/test.md net::ERR_FAILED

CORS 跨域访问机制

为了解决该问题,我们需要理解浏览器的 CORS 跨域访问机制。浏览器将 CORS 请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request),只要同时满足以下两大条件,就属于 “简单请求”,否则就属于 “非简单请求”。

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

  • HEAD
  • GET
  • POST

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

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

对于简单请求,浏览器会在请求时携带 Origin 头部,声明该请求来自哪个 “域”,服务端通过 Access-Control-Allow-Origin 和Access-Control-Allow-Methods 响应头来告知浏览器允许的 “域” 和 “HTTP 动词”。

对于非简单请求,浏览器会在实际请求前发起一次 “预检请求(preflight request)”,用于询问服务端是否允许跨域,如果不允许,则不发起实际请求。

预检请求使用 OPTIONS 动词,并携带 Origin、Access-Control-Request-Method、Access-Control-Request-Headers 请求头部,来声明 “当前的域”、“实际请求使用的 HTTP 动词” 和 “实际请求将携带的头部” 等信息。

服务端通过 Access-Control-Allow-Origin、 Access-Control-Allow-Methods 、Access-Control-Allow-Headers、Access-Control-Allow-Credentials 响应头来告知浏览器 “允许的域”、“允许的所有 HTTP 动词”、“允许携带的所有 HTTP 头部” 以及 “是否允许携带鉴权信息(Cookie,Authorization 头部等)”。

同时,为了避免频繁发起跨域检测,服务端会返回 Access-Control-Max-Age 来声明本次跨域检测的有效期,浏览器会缓存检测结果,并在有效期内使用浏览器缓存。

服务端还可以通过返回 Access-Control-Expose-Headers 头部来告知浏览器,哪些特定响应头允许暴露给 AJAX 请求。通常只有 Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma 允许暴露,其他头部需要服务端特定声明。

浏览器会根据预检请求响应的 CORS 相关头部进行判断,只有实际请求的 Origin,Methods,Headers 等均符合要求,才会发起实际请求。

在 COS 配置 CORS 跨域规则

了解了 CORS 跨域访问机制后,我们看看用户需要配置的哪些 CORS 响应头部。

  • 需配置Access-Control-Allow-Origin,必须包含 http://example.com,表示允许 http://example.com 对 COS 的跨域访问。
  • 需配置Access-Control-Allow-Methods,必须包含GET方法。
  • 需配置Access-Control-Expose-Headers,必须包含自定义头部 x-cos-meta-keywords,表示允许暴露该响应头部。

于是用户进入 COS 控制台,点击进入存储桶,在左侧的 “安全设置” 中选择 “跨域访问 CORS 设置”,点击添加规则,按如下规则填写:

  • 来源 Origin:填入 http://example.com(也可以填写 *,代表允许所有域)
  • 操作 Methods:勾选 GET
  • Allow-Headers:设置为 *,代表请求允许携带任何头部
  • Expose-Headers:添加 x-cos-meta-keywords

实际填写如下图所示,点击确定。

再次尝试刚刚的跨域请求,可以看到,跨域请求成功,并返回了文件内容以及自定义头部信息。

更进一步,用户还希望在网站上添加 “保存文章”,“删除文章” 等功能,为了降低开发成本,我们推荐其使用 cos-js-sdk-v5。为避免后续其他请求的跨域问题,我们推荐进行如下设置:

  • 来源 Origin:填入 http://example.com(填写您的域名,须包含协议)
  • 操作 Methods:勾选 PUT、GET、POST、DELETE、HEAD
  • Allow-Headers:设置为 *,代表请求允许携带任何头部
  • Expose-Headers:添加 ETag,x-cos-request-id 头部,确保 SDK 可以读取到需要的头部
  • 超时 Max-Age:设置为 600,让浏览器缓存跨域检测结果,过期时间为 600 秒

CDN 上配置 CORS 规则

如果开通了 CDN 服务,并且设置 COS 为 CDN 的源站,由于 CDN 会缓存 COS 的响应结果,包括跨域响应头部。通过 CDN 域名访问 COS 上的文件时,如果希望响应的跨域头部为最新配置,可以在 CDN 控制台的 “Response Header 配置” 中设置 CORS 相关跨域头部,如下图所示:

可以看到,跨域请求 CDN 加速域名下的资源成功,响应的跨域头部和 CDN 控制台配置的一致。

结语

全文通过博客网站开发,浏览器主动拦截跨域的 AJAX 请求的场景,详细介绍了 CORS 跨域访问机制,以及如何在 COS 和 CDN 上配置 CORS 跨域规则。

此外,对象存储 COS 的 CORS 跨域机制基于存储桶可以配置多条跨域访问规则,允许 Web 应用服务器进行跨域访问控制,使得跨域数据传输得以安全进行,简单易用,无需额外的第三方工具操作。满足客户 Web 应用需要跨域访问存储桶资源的需求,帮助您构建内容丰富的 Web 应用。

COS 一直在不断地丰富产品特性,帮助用户更加轻松的使用对象存储 COS,让用户聚焦于数据内容,为业务赋能,释放数据价值。

对象存储 COS 帮您轻松搞定跨域访问需求的更多相关文章

  1. 跨域 - jsonp轻松搞定跨域请求

    1.jsonp轻松搞定跨域请求 vue中使用axios,遇到跨域我就蒙逼了.第一次真正意义上的尝试使用jsonp js中用 var myscript = document.createElement( ...

  2. 当文件目录变得杂乱不堪怎么办,python帮你轻松搞定

    这几天和几个小伙伴,在一起合做一个ppt. 做ppt之前有原版的ppt,和一个word大纲,在制作过程中,又不断添加图片.视频等素材,最终,整个目录变得杂乱不堪(见下图-处理之前) 那我想,可不可以做 ...

  3. 轻松搞定javascript变量(闭包,预解析机制,变量在内存的分配 )

    变量:  存储数据的容器     1.声明        var   2.作用域       全局变量. 局部变量. 闭包(相对的全局变量):   3.类型         a.基本类型(undefi ...

  4. Python高级特性: 12步轻松搞定Python装饰器

    12步轻松搞定Python装饰器 通过 Python 装饰器实现DRY(不重复代码)原则:  http://python.jobbole.com/84151/   基本上一开始很难搞定python的装 ...

  5. 【微服务】之三:从零开始,轻松搞定SpringCloud微服务-配置中心

    在整个微服务体系中,除了注册中心具有非常重要的意义之外,还有一个注册中心.注册中心作为管理在整个项目群的配置文件及动态参数的重要载体服务.Spring Cloud体系的子项目中,Spring Clou ...

  6. 【微服务】之四:轻松搞定SpringCloud微服务-负载均衡Ribbon

    对于任何一个高可用高负载的系统来说,负载均衡是一个必不可少的名称.在大型分布式计算体系中,某个服务在单例的情况下,很难应对各种突发情况.因此,负载均衡是为了让系统在性能出现瓶颈或者其中一些出现状态下可 ...

  7. 春节过后就是金三银四求职季,分享几个Java面试妙招,轻松搞定HR!

    春节过后就是金三银四,分享几个Java面试妙招,轻松搞定HR! 2020年了,先祝大家新年快乐! 今年IT职位依然相当热门,特别是Java开发岗位.软件开发人才在今年将有大量的就业机会.春节过后,金三 ...

  8. 【转】轻松搞定FTP之FlashFxp全攻略

    转载网址:http://www.newhua.com/2008/0603/39163.shtml 轻松搞定FTP之FlashFxp全攻略 导读: FlashFXP是一款功能强大的FXP/FTP软件,融 ...

  9. Webcast / 技术小视频制作方法——自己动手录制video轻松搞定

    Webcast / 技术小视频制作方法——自己动手录制video轻松搞定 http://blog.sina.com.cn/s/blog_67d387490100wdnh.html 最近申请加入MSP的 ...

随机推荐

  1. Codis集群相关

    在大数据高并发场景下,单个 Redis 实例往往会显得捉襟见肘.首先体现在内存上,单个 Redis 的内存不宜过大,内存太大会导致 rdb 文件过大,进一步导致主从同步时全量同步时间过长,在实例重启恢 ...

  2. openstack高可用集群19-linuxbridge结合vxlan

    生产环境,假设我们的openstack是公有云,我们一般的linuxbridge结合vlan的模式相对于大量的用户来说是vlan是不够用的,于是我们引进vxlan技术解决云主机内网网络通讯的问题. 我 ...

  3. python之代码重构

    在撸码过程中,总有很多代码需要重构,码一个问候用户的小例子,加深对代码重构的印象. 原始代码: 1 import json 2 3 filename = 'username.json' #定义文件名 ...

  4. C#中无法找到microsoft.web文件

    原因 上午更新了vs2015后,找不到该文件. 解决方法 1.工具->Nuget包管理器->程序包管理器控制台-> 输入 Install-Package Microsoft.Web. ...

  5. 7.自定义ViewGroup-下滑抽屉

    1.效果 2.思路 分析效果: 1.布局分为两部分,后面部分,前面部分,默认状态后面被挡住: 2.后面不可以滑动,前面可以滑动: 3.如果前面的布局本身是可以滑动的,那么当前面布局滑动到第一个时,后面 ...

  6. 基础才是重中之重~BouncyCastle实现的DES3加密~java通用

    对于BouncyCastle类库(包)来说,他提供了很多加密算法,在与.net和java进行相互加解密过程中,得到了不错的应用,本文以DES3为例,来说一下DES3加解密的过程. 加密过程 明文字符转 ...

  7. (java)五大常用算法

    算法一:分治法 基本概念 1.把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题--直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并. 2.分治策略是对于一个 ...

  8. [LeetCode]Path Sum系列

    1.二叉树路径求指定和,需要注意的是由于有负数,所以即使发现大于目标值也不能返回false,而且返回true的条件有两个,到叶节点且等于sum,缺一不可 public boolean hasPathS ...

  9. [leetcode]TwoSum系列问题

    1.普通数组找两个数,哈希表建立数值和下标的映射,遍历时一边判断一边添加 /* 哇,LeetCode的第一题...啧啧 */ public int [] twoSum(int[] nums, int ...

  10. IDEA关联mysql失败Server returns invalid timezone. Go to 'Advanced' tab and set 'serverTimezon'

    时区错误,MySQL默认的时区是UTC时区 要修改mysql的时长 在mysql的命令模式下,输入: set global time_zone='+8:00'; 再次连接成功