`

CORS简介 跨域

 
阅读更多

现在请跟我做:在您的浏览器的地址栏中输入www.yhd.com并敲击回车。在网站内容全部加载完毕后,按F12打开浏览器的调试窗口。当切换到Sources页时,您会发现您当前所看到的一号店的页面是从多个不同的域中得到的:

  或许有些读者会感到奇怪:在之前自己 写网页的时候就曾经尝试访问非当前域中的资源,却怎么也不成功,一号店是如何做到的?

  当然,这不是一号店的独门绝技,而仅仅是使用了一些跨域访问的技术而已。而在本文中,我们就将对一种跨域访问技术CORS(Cross-Origin Resource Sharing)进行介绍。

 

为什么要用CORS

  在需要做出一个技术决定时,我们常常需要给出适当的理由。就CORS而言,使用它的根本原因就是要完成资源的跨域访问,也就是如何绕过Same-origin Policy。

  那么什么是Same-origin Policy呢?简单地说,在一个浏览器中访问的网站不能访问另一个网站中的数据,除非这两个网站具有相同的Origin,也即是拥有相同的协议、主机地址以及端口。一旦这三项数据中有一项不同,那么该资源就将被认为是从不同的Origin得来的,进而不被允许访问。

  但是这个限制的确过于严格了:一个大型网站常常拥有一系列子域。在这些域之间交换数据就会受到Same-origin Policy的限制。为了绕过该限制,业界提出了一系列解决该问题的方法,例如更改document.domain属性,跨文档消息,JSONP以及CORS等。这些解决方案各有各的长处,因此我们需要根据需求的不同来对这些方案进行选择。

  可以说更改document.domain属性的方法是最为直接快速的的方法,也较为常见。通过将从不同域中得到的脚本的document.domain属性设置为同一个值,就可以使得这些脚本之间可以相互交互。例如从“http://blog.ambergarden.com”得到的网页可以通过执行如下的脚本改变其document.domain属性中记录的所属域:

1 document.domain = ‘ambergarden.com’;

  那么接下来,该脚本就可以访问ambergarden.com中的数据了。

  这种方法也有其自身的劣势,那就是软件开发人员不可以随便设置document.domain属性的值,至少在一些浏览器上是如此的。

  跨文档消息则是通过向Window实例发送消息来完成的。在使用时,软件开发人员需要通过调用一个Window的postMessage()函数来向该Window实例发送消息。此时Window实例内部的onmessage事件将被触发,进而使得该事件的消息处理函数被调用。但是在接收到消息的时候,消息处理函数首先需要判断消息来源的合法性,以避免恶意用户通过发送消息的方式来非法执行代码。

  JSONP则是通过在文档中嵌入一个<script>标记来从另一个域中返回数据。例如在页面中添加一个如下的<script>标记:

1 <script src="http://blog.ambergarden.com/someData?callback=some_func"/>

  该<script>标记会向http://blog.ambergarden.com/someData发送一个GET请求。在数据返回到客户端后,some_func()函数将会被调用。当然,这种方法拥有一个显著的缺点,那就是只支持GET操作。

  就如您刚刚看到的一样,上面所列出的各个方法各自有各自的缺点及局限性。而相较于这些方法,CORS则没有那么多工作需要去做,也没有那么多限制。因此在本文中,我们将主要对CORS进行讲解。

 

CORS运行流程

  现在我们就来看一个通过CORS来进行跨域访问的简单示例。假设ambergarden.com想从一个公有数据平台public-data.com中返回一些数据,那么在页面逻辑中,其可以通过下面的代码向public-data.com发送数据请求:

1 function retrieveData() {
2     var request = new XMLHttpRequest();
3     request.open('GET', 'http://public-data.com/someData', true);
4     request.onreadystatechange = handler;
5     request.send();
6 }

  在运行这段代码的之后,浏览器会向服务发送如下的请求:

1 GET /someData/ HTTP/1.1
2 Host: public-data.com
3 ......
4 Referer: http://ambergarden.com/somePage.html
5 Origin: http://ambergarden.com

  而一个支持CORS协议的服务可能会给出下面的响应:

1 HTTP/1.1 200 OK
2 Access-Control-Allow-Origin: http://ambergarden.com
3 Content-Type: application/xml
4 ......
5 
6 [Payload Here]

  这里有一个值得注意的响应头:Access-Control-Allow-Origin。该响应头用来记录可以访问该资源的域。在接收到服务端响应后,浏览器将会查看响应中是否包含Access-Control-Allow-Origin响应头。如果该响应头存在,那么浏览器会分析该响应头中所标示的内容。如果其包含了当前页面所在的域,那么浏览器就将知道这是一个被允许的跨域访问,从而不再根据Same-origin Policy来限制用户对该数据的访问。

  从整个访问数据的流程来看,用户所使用的跨域访问数据的脚本实际上和普通的访问同一个域中数据的脚本并没有什么不同。而不同的,仅仅是在响应中多了一个Access-Control-Allow-Origin响应头。

  是不是很简单?实际上我们展示的仅仅是最为简单的Simple Request的执行流程。而CORS则将导致跨域访问的请求分为三种:Simple Request,Preflighted Request以及Requests with Credential。

  如果一个请求没有包含任何自定义请求头,而且它所使用HTTP动词是GET,HEAD或POST之一,那么它就是一个Simple Request。但是在使用POST作为请求的动词时,该请求的Content-Type需要是application/x-www-form-urlencoded,multipart/form-data或text/plain之一。

  如果一个请求包含了任何自定义请求头,或者它所使用的HTTP动词是GET,HEAD或POST之外的任何一个动词,那么它就是一个Preflighted Request。如果POST请求的Content-Type并不是application/x-www-form-urlencoded,multipart/form-data或text/plain之一,那么其也是Preflighted Request。

  一般情况下,一个跨域请求不会包含当前页面的用户凭证。一旦一个跨域请求包含了当前页面的用户凭证,那么其就属于Requests with Credential。

  前面我们已经看过浏览器对Simple Request是如何进行处理的。那么接下来我们就来看看Preflight Request是如何执行的。相较于Simple Request,Preflight Request的运行流程则略为复杂一些。

  假设现在我们要向公有数据平台public-data.com写入一些数据,那么我们就需要发送一个POST请求:

复制代码
1 function sendData() {
2     var request = new XMLHttpRequest(),
3         payload = ......;
4     request.open('POST', 'http://public-data.com/someData', true);
5     request.setRequestHeader('X-CUSTOM-HEADER', 'custom_header_value');
6     request.onreadystatechange = handler;
7     request.send(payload);
8 }
复制代码

  在执行了该段代码之后,浏览器首先发出的请求将如下所示:

1 OPTIONS /someData/ HTTP/1.1
2 Host: public-data.com
3 ......
4 Origin: http://ambergarden.com
5 Access-Control-Request-Method: POST
6 Access-Control-Request-Headers: X-CUSTOM-HEADER

  可以看到,我们首先发送的并不是POST请求,而是OPTION请求。该请求还通过Access-Control-Request-Method以及Access-Control-Request-Headers标示了请求类型以及请求中所包含的自定义HTTP Header。实际上,它相当于向服务端询问访问资源的权限:“您好,我想向你这里发送数据,你看可以吗?”。而在真正访问资源前发送一个请求进行探测也是该请求被称为是Preflight Request的原因。

  在服务端看到该OPTIONS请求后,其将分析该请求中的内容并返回一个响应,以通知浏览器是否允许向它发送数据:

1 HTTP/1.1 200 OK
2 Access-Control-Allow-Origin: http://ambergarden.com
3 Access-Control-Allow-Methods: POST, GET, OPTIONS
4 Access-Control-Allow-Headers: X-CUSTOM_HEADER
5 Access-Control-Max-Age: 1728000
6 ......

  浏览器分析该响应并了解到其被允许向服务端发送数据以后,其才会向服务端发送真正的POST请求:

1 POST /someData/ HTTP/1.1
2 Host: public-data.com
3 X-CUSTOM-HEADER: custom_header_value
4 ......
5 
6 [Payload Here]

  而服务端则会接收并处理该请求:

1 HTTP/1.1 200 OK
2 Access-Control-Allow-Origin: http://ambergarden.com
3 Content-Type: application/xml
4 ......
5 
6 [Payload Here]

  最后一种请求Requests with Credential的运行流程则和前两种请求类似。只不过在发送请求的时候,我们需要将用户凭证包含在请求中:

复制代码
1 function retrieveData() {
2     var request = new XMLHttpRequest();
3     request.open('GET', 'http://public-data.com/someData', true);
4     request.withCredentials = true;
5     request.onreadystatechange = handler;
6     request.send();
7 }
复制代码

  而在服务端的响应中,其将拥有一个额外的Access-Control-Allow-Credentials响应头:

1 HTTP/1.1 200 OK
2 Access-Control-Allow-Origin: http://ambergarden.com
3 Content-Type: application/xml
4 ......
5 
6 [Payload Here]

 

集成对CORS的支持

  从上面的示例中已经能够看到,在使用CORS来访问数据的时候,客户端不需要更改任何数据访问逻辑。所有的一切工作都是在服务端及浏览器之间自动完成的。因此如果希望为一个系统集成CORS支持的时候,我们需要做的工作主要集中在服务端。

  当然,集成工作实际上十分简单:在你的web.xml中添加一个Filter(或利用已有的Filter)并根据传入的请求首先判断其是哪一种CORS请求。在得知了请求的类型后,我们就可以决定到底以哪种方式响应用户了。这里的逻辑较为简单,因此我就不再赘述了。

 

转载请注明原文地址并标明转载:http://www.cnblogs.com/loveis715/p/4592246.html

分享到:
评论

相关推荐

    java基于ssm+jsp珠宝购物网站系统源码 带毕业论文

    【资源说明】 1、开发环境:ssm框架;内含Mysql数据库;JSP技术 2、项目代码都经过严格调试,代码没有任何bug!下载可以直接使用! 3、本项目适合作为计算机、数学、电子信息等专业的课程设计、期末大作业和毕设项目,作为参考资料学习借鉴。 4、本资源作为“参考资料”如果需要实现其他功能,需要能看懂代码,并且热爱钻研,自行调试。

    基于SSM的企业工资管理系统.zip(毕设&课设&实训&大作业&竞赛&项目)

    项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。

    基于java的大学生兼职系统设计与实现.docx

    基于java的大学生兼职系统设计与实现.docx

    使用加权最小二乘法进行电力系统状态估计。测量包括电压幅值、功率注入和功率流Matlab代码.rar

    1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

    vue+SpringBoot488基于springboot的医务室管理系统java毕业设计源码含论文.rar

    jdk版本:jdk1.8+ 前端:vue.js+ElementUI 开发工具:IDEA 或者eclipse都支持 编程语言: java 框架支持:springboot 数据库: mysql 版本不限 数据库工具:Navicat/SQLyog都可以 详细技术:java+springboot+vue+MYSQL+MAVEN 前端采用的Vue框架,后端采用java语言,sprinboot框架,mybatis操作数据源,使用软件:idea,eclipse、MySQL。完成了用户登录管理等模块的设计与实现。完成了系统数据库的设计,并基于MySQL数据库管理系统

    P1024 [NOIP2001 提高组] 一元三次方程求解

    题目描述: 给出一个简单的一元三次方程,要求三个解。 思路: 这些大佬们为何都用一些神奇的算法……还把这道题评为普及组难度……其实只要枚举就可以了,注意一下double精度。 这道题的代码可以比一些入门组的还要短……这道题其实应该在普及-难度

    java基于ssm+jsp个体户商城管理系统源码 带毕业论文

    【资源说明】 1、开发环境:ssm框架;内含Mysql数据库;JSP技术 2、项目代码都经过严格调试,代码没有任何bug!下载可以直接使用! 3、本项目适合作为计算机、数学、电子信息等专业的课程设计、期末大作业和毕设项目,作为参考资料学习借鉴。 4、本资源作为“参考资料”如果需要实现其他功能,需要能看懂代码,并且热爱钻研,自行调试。

    基于SSM+JSP的大学生创新创业平台竞赛管理子系统.zip(毕设&课设&实训&大作业&竞赛&项目)

    项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。

    JPEG文件,一个上传开发板,一个解压后拖到Ubuntu的Home中

    JPEG文件,一个上传开发板,一个解压后拖到Ubuntu的Home中

    java基于ssm+vue服装品牌的推广及应用网站系统源码 带毕业论文

    【资源说明】 1、开发环境:ssm框架;内含Mysql数据库;VUE技术 2、项目代码都经过严格调试,代码没有任何bug!下载可以直接使用! 3、本项目适合作为计算机、数学、电子信息等专业的课程设计、期末大作业和毕设项目,作为参考资料学习借鉴。 4、本资源作为“参考资料”如果需要实现其他功能,需要能看懂代码,并且热爱钻研,自行调试。

    HTML5+CSS3网站设计学习。.zip(毕设&课设&实训&大作业&竞赛&项目)

    项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。

    [基于Python]自己写的一个微信跳一跳自动游戏程序(针对安卓手机)。(毕设&课设&实训&大作业&竞赛&项目)

    项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还[基于Python]自己写的一个微信跳一跳自动游戏程序(针对安卓手机)。 全自动运行 自动适应不同分辨率 自动调整各个参数误差.zip行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。

    微信小程序购物商城管理系统.zip(毕设&课设&实训&大作业&竞赛&项目)

    项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。

    基于java的网上图书商城系统设计与实现.docx

    基于java的网上图书商城系统设计与实现.docx

    基于Q-learning算法和ε-greedy策略解决随机生成的方形迷宫问题Matlab代码实现.rar

    1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

    java毕业设计源码ssm953基于Java技术的儿童成长系统的设计与实现+vue程序数据库含论文.rar

    前端采用的Vue框架,后端采用java语言,ssm框架,mybatis操作数据源,使用软件:idea,eclipse、MySQL。完成了用户登录管理等模块的设计与实现。完成了系统数据库的设计,并基于MySQL数据库管理系统 本系统基于SSM(Spring+SpringMVC+MyBatis)框架,适用于毕业设计, 基于B/S模式, mysql数据库,感兴趣的朋友们可以下载研究一下。 jdk版本:jdk1.8+ 前端:vue.js+ElementUI 开发工具:IDEA 或者eclipse都支持 编程语言: java 框架支持:ssm 数据库: mysql 版本不限 数据库工具:Navicat/SQLyog都可以 详细技术:java+ssm+vue+MYSQL+MAVEN

    用 Android Studio(AS) 以 JNI 方式开发 OpenCV 的最小工程.zip(毕设&课设&实训&大作业&竞赛

    项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。

    vue+SpringBoot738药品仓储管理系统java毕业设计源码含论文.zip

    jdk版本:jdk1.8+ 前端:vue.js+ElementUI 开发工具:IDEA 或者eclipse都支持 编程语言: java 框架支持:springboot 数据库: mysql 版本不限 数据库工具:Navicat/SQLyog都可以 详细技术:java+springboot+vue+MYSQL+MAVEN 前端采用的Vue框架,后端采用java语言,sprinboot框架,mybatis操作数据源,使用软件:idea,eclipse、MySQL。完成了用户登录管理等模块的设计与实现。完成了系统数据库的设计,并基于MySQL数据库管理系统

    给Wpf的datagrid动态添加title和数据的方法.zip

    给Wpf的datagrid控件动态添加title和数据的方法

Global site tag (gtag.js) - Google Analytics