cors跨域探讨

前端跨域

前端跨域方案很多,jsonpiframe等等,但是个人觉得,最正宗,最无损的跨域方式还是CORSCORS(Cross-origin resource sharing)是一个W3C标准,翻译过来是跨域资源共享。 它允许浏览器向跨域(协议、域名、端口任一不相同)服务器发送XMLHttpRequest请求。 目前支持所有现代浏览器(>IE10) 借阅了阮一峰大神的《跨域资源共享 CORS 详解》,结合自己的理解,说一说自己的CORS的领会。

简介

CORS协议本身,可以说,完全是由浏览器执行的。 对前端开发者而言,CORS是在浏览器检查到跨域请求的时候,自动发起的。 对后台开发者而言,只要在headers中返回特定的信息(相当于白名单)–具体的CORS步骤,浏览器会根据headers中返回的信息做出具体的行为。

请求

浏览器会自动将请求分为两类:简单请求、非简单请求。 只要同时满足以下条件,就属于简单请求。

 (1) 请求方法是以下三种方法之一:
· HEAD
· GET
· POST
(2)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返回,并且里面的值包含origin,浏览器才会允许xhr获取返回的内容。 一条简单的跨域请求就完成了: 前端不需要写任何东西。 后台也可以不做任何逻辑处理,一律返回Access-Control-Allow-Origin。 全部的CORS把关工作都在浏览器端正式执行。

同时,发起跨域请求的时候,默认是不带cookie的,需要手动开启,后台也需要权限允许。

一个简单的跨域样例如下:

非简单请求

当浏览器判定是非简单请求的时候,会在发正式请求前,想同一地址发起一个options的预请求。 预请求携带了正式请求的方法(method)和特殊头(headers)。

Access-Control-Request-Method: POST,
Access-Control-Request-Headers: CARVEN

然后服务器返回自己允许的方法(method)和特殊头(headers),当然还有允许域

Access-Control-Allow-Method: POST, PUT
Access-Control-Allow-Headers: CARVEN, ZJY
Access-Control-Allow-Origin: http://localhost:63342

然后浏览器会比较,如果请求发起内容–origin,method,headers,都在服务器响应的名单里,正式请求就可以发起了,流程再次回归到简单请求.


为什么会有非简单请求?

对于非简单(偏激理解为 危险)的请求,做到询问与逻辑代码的隔离。

比如:PUT、DELETE等method,从规范来说,会使目标地址发生增、删等行为,使目标服务器资源发生改变。

所以,浏览器会发起正式请求前,先向发起一次预请求,等到允许后再发正式请求。


控制CORS

在ES6的fetch中,已经可以控制cors开关了。

fetch(url,{ mode: mode})

  • mode=same-origin,不支持跨域,直接在浏览器端拦截跨域请求
  • mode=no-cors,不执行跨域协议,即不存在跨域问题,即使有特殊header,也不发options。 但是只支持HEAD、GET、POST,且代码不能接收到响应信息。
  • mode=cors,默认,执行cors协议。

结尾

前面举的实行例子,只是最简单的cors规则演示,但其实,前后台手动通过获取headers上携带的各种信息,可以很灵活的做其他的逻辑处理。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Python中文社区

Linux进程监控工具Supervisor简易使用教程

專 欄 ❈ gw1770df,Python中文社区专栏作者,从事Python开发工作,全栈工程师。 博客: https://word.gw1770df.cc ...

3796
来自专栏vue学习

npm

本来打算暑假将自己每天学到的东西写下来,每天做成一篇文章的,结果现在每周能产出一篇文章就不错了。。。【掩面】。。今天学了点npm命令行操作,就写一下

1061
来自专栏進无尽的文章

代码管理| 本地Git仓库和远程仓库的创建及关联

顺便说一下:Github账号创建私人项目的话需要付费,可以在码云上面创建个人私有仓库,是免费的。

2.5K2
来自专栏编程

ansible2.4 源码分析-自定义inventory解析插件实现

微信公众号:进击的大杂烩 通过上一篇文章,初步的分析了ansible2.4的一个运行流程,没有对 ansible 解析 source 的过程进行详细分析。本文通...

33810
来自专栏Java架构师历程

Git—具体实例讲解Git用法以及提交PR

Git作为目前比较流行的版本控制系统,被各个互联网公司广泛使用着,使用git可以很方便地进行多人协作和版本控制,大多数时候我们也需要把别人的代码进行整合和修改,...

1492
来自专栏DeveWork

设置你的Gravatar头像的方法

Gravatar是Globally Recognized Avatar的缩写,是gravatar推出的一项服务,意为“全球公用的头像”。如果在Gravatar的...

2817
来自专栏开发之途

Git的使用教程(1)

3085
来自专栏云计算教程系列

如何在CentOS 7上编写自定义系统审计规则

Linux审计系统创建审计跟踪,这是一种跟踪系统上各种信息的方法。它可以记录大量数据,如事件类型,日期和时间,用户ID,系统调用,进程,使用的文件,SELinu...

6482
来自专栏程序小工

【Linux】系统学习Crontab定时任务

crontab 是一个用于设置周期性执行任务的工具。目前服务器端的运行环境大多数为 Linux,在日常的运营和维护中会有很多需要定期执行的操作,其中有些操作是可...

1792
来自专栏散尽浮华

Gitlab上采用rpm方式快速安装的操作记录

之前梳理了一篇Gitlab的安装CI持续集成系统环境---部署Gitlab环境完整记录,但是这是bitnami一键安装的,版本比较老。下面介绍使用rpm包安装G...

2575

扫码关注云+社区

领取腾讯云代金券