关于CORS跨域问题的理解
起因
因为这段时间一个项目前后端分别部署在不同服务器的需要,抽空学习了一下CORS问题,不足之处,欢迎指教.
什么是CORS
CORS是一个w3c标准,全称是"跨域资源共享"(Cross-origin resource sharing),但一个请求url的协议,域名,端口三者之间任意与当前页面地址不同即为跨域.它允许阅览器向跨源服务器发送XMLHttpRequest请求,从而客服AJAX只能同源使用的限制.
CORS简介
浏览器默认的安全限制为同源策略,即JavaScript或Cookie只能访问同源(相同协议,相同域名,相同端口)下的内容。但由于跨域访问资源需要,出现了CORS机制,这种机制让web服务器能跨站访问控制,使跨站数据传输更安全。CORS需要阅览器和服务器同时支持,目前,主流的阅览器都支持cors。
CORS的两种请求方式
浏览器将CORS请求分为两类:简单请求和非简单请求
一 简单请求
1.1 区分条件:
只要满足一下两大条件,属于简单请求:
(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
不同时满足上面两个条件,就是非简单请求
1.2 简单请求的基本流程
浏览器直接发送CORS跨域请求,并在header信息中增加一个Origin字段,表明这是一个跨域的请求。
<script>
var url = 'http://www.lishanlei.cn/CorsTest/CorsTest.php';
var xhr = new XMLHttpRequest();
xhr.open('get', url, true);
// xhr.setRequestHeader('X-Custom-Header', 'value');
xhr.send();
</script>
在上面的代码中以get形式向www.lishanlei.cn进行跨域访问。
上面的头信息Origin字段用来说明本次请求来自哪个源(协议+域名+端口)。服务器根据这个值,决定是否同意这次请求。如果Origin指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应,浏览器收到这个回应发现这个回应的头信息没有包含Access-Control-Allow-Origin字段,就知道错了,从而会抛出一个错误,被XMLHttpRequest的onerror回调函数捕获。注意这种错误无法通过状态码识别,此时HTTP回应的状态码可能是200
如果Origin指定的域名在许可范围内,服务器返回的响应会多出几个头信息字段
Access-Control-Allow-Origin:该字段是必须的,其值可能是请求时Origin字段的值,也可能是一个*,表示接受任意域名请求。
Access-Control-Allow-Credentials:该字段可选,其值类型是布尔型,表示是否允许发送Cookie。默认情况下Cookie不包括在CORS请求中。当设为true时表示服务器明确许可,Cookie可以包含在请求中一起发送给服务器。
Access-Control-Allow-Headers:该字段必须,它是一个都好分割的字符串,表明服务器支持的所有头信息字段
1.3 withCredentials属性
默认情况下,CORS请求默认不发送Cookie和Http认证信息,如果要把Cookie发送到服务器,首先要指定Access-Control-Alloe-Credentials字段,另一方面,需要在AJAX请求中打开withCredentials属性
var xml = new XMLHttpRequest();
xml.withCredentials = true;
如果没有设置该属性为true,即使服务器统一发送Cookie,浏览器也不会发送。
当该属性设置为true时,即需要发送Cookie那么在服务器中Access-Control-Allow-Origin就不能设置成*,必须指定吗明确的与请求一致的域名,同时,Cookie依然遵循同源政策。
二 非简单请求
当不同时满足区分条件的,就是非简单请求。
2.1 预检请求
非简单请求的CORS请求,会在正式通信前进行一次Http查询请求,又称预检请求。
浏览器先请求服务器,当前网页所在域名是否在服务器许可名单中以及可以使用那些HTTP动词和头信息字段,当客户端得到肯定答复时,浏览器才会正式发出XMLHttpRequest请求。
var url = 'http://www.lishanlei.cn/CorsTest/CorsTest.php';
var xhr = new XMLHttpRequest();
xhr.open('PUT', url, true);
xhr.setRequestHeader('X-Custom-Header', 'value');
xhr.send();
上面代码中,请求方式是PUT,并发送一个自定义头信息X-custom-Header,但在服务器的头信息中没有包含X-custom-Header,故浏览器报错,只进行了一次预检请求。
设置header中的Access-Control-Allow-Headers字段:
header('Access-Control-Allow-Headers:x-requested-with,content-type,X-Custom-Header');
再次访问
浏览器发现这是一个非简单请求,自动发出一个预检请求,要求服务其确认这样的请求,下面是这个预检请求的HTTP头信息:
预检请求用的请求方法是OPTIONS,表示这个请求是用来询问的。
Access-Control-Request-Method:该字段是必须的,用来列出浏览器的CORS请求会用到哪些HTTP方法。
Access-Control-Request-Headers:该字段是一个逗号分割的字符串,指定浏览器CORS请求会额外发送的头信息字段。
2.2预检请求的回应
当服务其收到预检请求后,检查了Origin,Access-Control-Request-Method等信息字段后,如果没有问题,则确认允许跨源请求,就可以做出了回应。
Access-Control-Allow-Methods:该字段必须,其值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。这是为了避免多次预检请求。
Access-Control-Max-Age:该字段是可选的,用来指定本次预检请求的有效期,单位是秒。Access-Control-Max-Age:20,即允许缓存该条回应20秒,再此期间不用发出另一条预检请求
如果浏览器否定了预检请求,会返回一个正常的HTTP回应,但是没有任何CORS相关的头信息字段。浏览器此时会认定服务器不同意预检请求,触发一个错误,被XMLHttpRequest的onerror回调函数捕获。
服务器端处理机制
服务器对于跨域请求的处理流程如下:
- 首先查看http头部有无origin字段;
- 如果没有,或者不允许,当成普通请求;
- 如果有且是允许的,再看是否是preflight(method=OPTIONS);
- 如果不是preflight(简单请求),返回Allow-Origin,Allow-Credential等字段,并返回正常内容;
- 如果是preflight(非简单请求),返回Allow-Headers,Allow-Methods等;
配置CORS规则
一 apache上配置CORS规则
Apache需要使用mod_headers模块来激活HTTP头设置,默认是激活的,只需要修改Apache配置文件中的/etc/apache2/sites-available/000-default.conf
1 开启模块
sudo a2enmod headers
2 编辑配置文件
sudo vi /etc/apache2/sites-available/000-default.conf
3 在虚拟主机Directory设置下添加
Header set Access-Control-Allow-Origin *
与JSONP的比较
CORS和JSONP都是为了使web浏览器能够跨源请求,使用目的相同,但是比JSONP更强大。JSONP只支持GET请求,而CORS支持所有类型的HTTP请求,不过JSONP的优势在于支持老式浏览器以及可以向不支持CORS的网站跨源请求。
参考博文:http://www.ruanyifeng.com/blog/2016/04/cors.html
https://blog.csdn.net/u014344668/article/details/54948546
关于CORS跨域问题的理解的更多相关文章
- jsonp与cors跨域的一些理解
浏览器的同源策略,即是浏览器之间要隔离不同域的内容,禁止互相操作. 比如,当你打开了多个网站,如果允许多个网站之间互相操作,那么其中一个木马网站就可以通过这种互相操作进行一系列的非法行为,获取你在各个 ...
- jsonp与cors跨域的一些理解(转)
CORS其实出现时间不短了,它在维基百科上的定义是:跨域资源共享(CORS )是一种网络浏览器的技术规范,它为Web服务器定义了一种方式,允许网页从不同的域访问其资源.而这种访问是被同源策略所禁止的. ...
- CORS跨域模型浅析及常见理解误区分析
CORS跨域资源共享是前后端跨域十分常用的一种方案,主要依赖Access-Control-Allow(ACA)系列header来实现一种协商性的跨域交互. 基本模型 其中的具体流程大致可以分为以下几步 ...
- 彻底理解CORS跨域原理
背景 现在的前端开发中都是前后端分离的开发模式,数据的获取并非同源,所以跨域的问题在我们日常开发中特别常见.其实这种资料网上也是一搜一大堆,但是都不够全面,理解起来也不够透彻.这篇文章就结合具体的示例 ...
- CORS跨域资源共享你该知道的事儿
"唠嗑之前,一些客套话" CORS跨域资源共享,这个话题大家一定不陌生了,吃久了大转转公众号的深度技术好文,也该吃点儿小米粥溜溜胃里的缝儿了,今天咱们就再好好屡屡CORS跨域资源共 ...
- JSONP跨域和CORS跨域
什么是跨域? 跨域:指的是浏览器不能执行其它网站的脚本,它是由浏览器的同源策略造成的,是浏览器的安全限制! 同源策略 同源策略:域名.协议.端口均相同. 浏览器执行JavaScript脚本时,会检查这 ...
- Flask配置Cors跨域
1 跨域的理解 跨域是指:浏览器A从服务器B获取的静态资源,包括Html.Css.Js,然后在Js中通过Ajax访问C服务器的静态资源或请求.即:浏览器A从B服务器拿的资源,资源中想访问服务器C的资源 ...
- 浅谈跨域问题,CORS跨域资源共享
1,何为跨域? 在理解跨域问题之前,你先要了解同源策略和URL,简单叙述: 1)同源策略 三同:协议相同,域名相同,端口相同: 目的:保证用户信息安全,防止恶意网站窃取数据.同源策略是必须的,否则co ...
- 如何在ASP.NET Core中实现CORS跨域
注:下载本文的完整代码示例请访问 > How to enable CORS(Cross-origin resource sharing) in ASP.NET Core 如何在ASP.NET C ...
随机推荐
- 笔记:Struts2 Action 非泛型集合元素类型转换
局部类型转换文件 局部类型转换文件的文件名应为 ActionName-conversion.properties,其中 ActionName 是需要替换为 Action 的类名称,后面的 conver ...
- new Image的API
- 选择排序—堆排序(Heap Sort) 没看明白,不解释
堆排序是一种树形选择排序,是对直接选择排序的有效改进. 基本思想: 堆的定义如下:具有n个元素的序列(k1,k2,...,kn),当且仅当满足 时称之为堆.由堆的定义可以看出,堆顶元素(即第一个元素) ...
- linux-2.6.18源码分析笔记---信号
一.相关数据结构及其位置(大致浏览即可,介绍流程时再来仔细看) 1.1 进程描述符struct task_struct所在目录:include\linux\sched.h 关注task_struct中 ...
- selenium + robotframework的运行原理
1.点击ride界面启动用例执行时,首先会调用脚本 2.打开pybot脚本查看内容. 3.打开robot包下面的run文件,我们可以看到信息 run文件内容 程序启动的入口, sys.agv所表达的含 ...
- java之静态属性和静态方法
前言 静态属性和方法必须用static修饰符 静态属性和非静态属性的区别: 1.在内存中存放位置不同 所有带static修饰符的属性或者方法都存放在内存中的方法区 而非静态属性存放在内存中的堆区 ...
- [福大软工] W班 软件产品案例分析
作业要求 https://edu.cnblogs.com/campus/fzu/FZUSoftwareEngineering1715W/homework/1300 评分细则 第一部分 调研,评测 (3 ...
- C语言博客作业-结构体
一.PTA实验作业 6-2 按等级统计学生成绩 1. 本题PTA提交列表 2. 设计思路 定义i,count存放不及格人数 for i=0 to n-1{ 判断 score的值的范围 if 100&g ...
- alpha-咸鱼冲刺day2-紫仪
总汇链接 一,合照 emmmmm.自然是没有的. 二,项目燃尽图 三,项目进展 今天并没有什么进展,弄了好久好像也只研究出怎么把JS的功能块插入进去.html的信息提交这些还不知道要怎么弄. 四,问题 ...
- Alpha冲刺第十一天
Alpha冲刺第十一天 站立式会议 项目进展 项目进入尾声,主要测设工作完成过半,项目总结也开始进行. 问题困难 项目的困难现阶段主要是测试过程中存在一些"盲点"很难发现或者发现后 ...