摘要

谈到跨域,不论前端还是后端,多少有点谈虎色变,面试中也常会问到这些问题,浏览器和服务器端到底怎么做才能跨域,他们都做了什么?

同源 vs 跨域

同源,字面意义是相同的源头,即同一个web服务器(比如tomcat启动的一个实例),好比一个家庭;跨域就是从一个web服务器向另一个服务器发送或获取数据,好比去邻居家拿东西。之所以要做跨域限制,是为了安全,你不能从邻居家直接拿吧,总得问过人家。

那么怎么来判断同源?就看一个web服务器的根本三要素:协议、web服务器域名、端口号。

比如:当前页面的地址是http://myhost.com:8080/index,源就是http://myhost.com:8080,当新请求的协议、域名、端口号与之完全一致即是同源,否则是跨域。

对于下面发送的请求,浏览器的判决如下:

  • http://www.myhost.com:8080/users 跨域 -> 域名必须完全一致
  • https://myhost.com:8080/users 跨域 -> 协议必须一致
  • https://myhost.com:9000/users 跨域 -> 端口必须一致
  • https://myhost.com/users 跨域 -> 端口必须一致(没有端口也是不一致)
  • https://myhost.com:8080/profile/users 同源

跨域时的动作

浏览器端

假设我们点击一个按钮去获取数据,获取数据的请求准备从浏览器发出,这时浏览器先会检测这条请求是同源还是跨域,也就是与按钮所在页面的地址是同源还是跨域,如果是同源,好说,直接发送出去;如果是跨域的请求,那就得hold住先,浏览器会在请求的http header中加上一个Origin字段,标明这个请求是从哪里发出来的,例如: Origin:http://neighbour.com:9000,这样服务器端好辨识是自己家人来取东西,还是隔壁老王来借东西了。

那些做检测、加header字段等事情全是浏览器做,对于前端开发者来说,什么事都不用干,ajax请求平时怎么发送,跨域时还怎么发送。可见,跨域对于前端没影响,关键在于服务器端。

服务器端

每个web服务器就像一个家庭。好邻居要吃螃蟹来借点醋,这没问题;坏邻居家有醋要来借点螃蟹,这不干。

服务器收到请求会给与响应,响应的header里写明跨域的配置信息,告诉浏览器,它允许哪些域名发来的请求访问,哪些method可以执行。浏览器收到响应后自动判断能不能真正执行请求。

假设服务器域名是http://rich.com:8080,它收到了一个从http://neighbour.com:9000发来的请求http://rich.com:9000/borrow-vinegar,服务器响应它,在响应中写明本服务器支持哪些域名可以访问,哪些method可以执行,浏览器收到后做匹配,再判定。

那么,服务器有哪些判定的规则呢?

是否允许跨域的判定

一个支持CORS的web服务器,有如下的判定字段,他们会在响应的header中写明

  • Access-Control-Allow-Origin:允许跨域的Origin列表
  • Access-Control-Allow-Methods:允许跨域的方法列表
  • Access-Control-Allow-Headers:允许跨域的Header列表
  • Access-Control-Expose-Headers:允许暴露给JavaScript代码的Header列表
  • Access-Control-Max-Age:最大的浏览器缓存时间,单位为s

其中Access-Control-Allow-Origin(访问控制之允许的源),在响应的http header中必须有的,表示允许访问本服务器的源头Origin(域名),可以是特定的域名列表,用逗号分隔,也可以是通配符 *,表示支持任意域名的访问。

除了限定源头Origin,还会限制请求的方法MethodHeader

如,如果服务器设定Access-Control-Allow-Methods:GET,那么跨域的POST请求无法在这个服务器执行。

总流程

  • 页面发送请求
  • 浏览器根据同源策略做出判定,如果是同源请求,直接发送出去;如果是跨域请求,在HTTP HEADER加上Origin字段,或是先发送一次预检请求(preflight)。
  • 服务器接收请求,根据自身跨域的配置(如允许哪些域名,什么样的Method访问),返回文件头。若未配置过任何允许跨域,则文件头里不包含Access-Control-Allow-origin字段,若配置过域名,则返回Access-Control-Allow-origin+ 对应配置规则里的域名的方式。
  • 浏览器接收到响应,根据响应头里的`Access-Control-Allow-origin字段做匹配,如果没有这个字段,说明不匹配;如果有,将字段内容和当前域名做比对。如匹配,则可以发送请求。

跨域的请求形式

跨域的请求分两种,一种是简单请求,一种是非简单请求(废话)。

  • 简单请求,方法仅限于 HEAD,GET或POST,且Header的字段不超过以下字段:

    • HeadeAccept
    • Accept-Language
    • Content-Language
    • Last-Event-ID
    • Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain (没有application/json, 说明如果发送JSON格式的body请求数据是一个非简单请求)
  • 非简单请求就是其他请求

简单请求浏览器会直接在请求的Header加上Origin字段再发送;非简单请求浏览器则会先发送一次预检请求,根据预检请求的结果,决定是否正式发送请求。

详情可以访问阮一峰的日志:跨域资源共享 CORS 详解

来源:https://segmentfault.com/a/1190000017481505

CORS 理解(不要那么多术语)的更多相关文章

  1. spring6——AOP的编程术语

    面向切面编程作为一种编程思想,允许我们对程序的执行流程及执行结果动态的做出改变,以达到业务逻辑之间的分层管理或者是目标对象方法的增强,spring框架很好的实现了这种编程思想,让我们可以对主业务逻辑和 ...

  2. 三分钟理解Java中字符串(String)的存储和赋值原理

    可能很多Java的初学者对String的存储和赋值有迷惑,以下是一个很简单的测试用例,你只需要花几分钟时间便可理解. 1.在看例子之前,确保你理解以下几个术语: 栈:由JVM分配区域,用于保存线程执行 ...

  3. Shiro术语

    请花2分钟阅读和理解Shiro中的术语 - 这是非常重要的.这里的术语和概念在文档中的任何地方都被引用,并且将大大简化您对Shiro和一般的安全性的理解. 因为使用了一些您可能不太明白的术语,所以安全 ...

  4. 行为驱动开发(BDD)实践示例

    引言 BDD是对TDD理念的扩展.BDD强调有利害关系的技术团体和非技术团队都要参与到软件开发过程中.可以把它看成一种强调团体间合作的敏捷方法.大多数采用某种敏捷方法的团队最终都会遵循BDD的许多原则 ...

  5. 分布式一致性算法--Paxos

    Paxos算法是莱斯利·兰伯特(Leslie Lamport)1990年提出的一种基于消息传递的一致性算法.Paxos算法解决的问题是一个分布式系统如何就某个值(决议)达成一致.在工程实践意义上来说, ...

  6. Objective-C Runtime 运行时之四:Method Swizzling

    理解Method Swizzling是学习runtime机制的一个很好的机会.在此不多做整理,仅翻译由Mattt Thompson发表于nshipster的Method Swizzling一文. Me ...

  7. Scala 的确棒

    我的确认为计算机学院应该开一门 Scala 的语言课程. 在这篇文章中,我会讲述为什么我会有这样的想法,在此之前,有几点我想要先声明一下: 本文无意对编程语言进行评比,我要讲述的主体是为什么你应该学习 ...

  8. Hadoop入门学习笔记---part1

    随着毕业设计的进行,大学四年正式进入尾声.任你玩四年的大学的最后一次作业最后在激烈的选题中尘埃落定.无论选择了怎样的选题,无论最后的结果是怎样的,对于大学里面的这最后一份作业,也希望自己能够尽心尽力, ...

  9. C#再识委托

    从C#1到C#3逐步认识委托,由于C#4与C#5对委托改动并不大,故不作说明. 好久没看.NET了,一直在搞HybridAPP,都忘得差不多了,这也是自己从书中摘下笔迹,供日后翻阅. C# 1 1.什 ...

随机推荐

  1. CSS3-文本渐变色

    在活动中,文字的颜色经常采用渐变的效果,在此,做一下笔记 <span>你好呀!</span> span{ background-image: linear-gradient(t ...

  2. js库-AngularJS

    我是一个不思进取的前端. 我想按部就班的工作. 我想得过且过. 老天呀!你咋又逼迫我学习对于我来说的新知识呢!!!!!!!我想哭呀!!!!! 在某个代码项目中我看到了{{??}}这么个标记!我的神呀! ...

  3. Python递归函数和二分查找算法

    递归函数:在一个函数里在调用这个函数本身. 递归的最大深度:998 正如你们刚刚看到的,递归函数如果不受到外力的阻止会一直执行下去.但是我们之前已经说过关于函数调用的问题,每一次函数调用都会产生一个属 ...

  4. 小程序 之使用HMACSHA1算法加密报文

    首先说说我们前端常用的加密技术, 我们常用的加密技术有:如MD5加密,base64加密 今天要说的是HMACSHA1加密技术 先介绍下什么是SHA1算法, 安全哈希算法(Secure Hash Alg ...

  5. logging模块配置共享以及使用文件配置

    1.配置共享 如果每个文件都配置logging,那就太繁琐了,logging提供了父子模块共享配置的机制, 会根据Logger的名称来自动加载父模块的配置.首先定义一个 main.py 文件: imp ...

  6. bzoj 1835/luogu P2605 : [ZJOI2010]base 基站选址

    题目描述 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci.如果在距离第i个村庄不超过Si的范 ...

  7. js中call、apply、bind那些事2

    前言 回想起之前的一些面试,几乎每次都会问到一个js中关于call.apply.bind的问题,比如… 怎么利用call.apply来求一个数组中最大或者最小值 如何利用call.apply来做继承 ...

  8. python--文件处理1

    1.     读取文件 方法: all_the_text = open('thefile.txt').read() 但是为了安全起见还是给打开的文件对象指定一个名字,这样在完成之后可以迅速关掉,防止无 ...

  9. dubbo常见问题解答FAQ

    常见问题解答 1. 如果服务注册不上怎么办? 2. 出现RpcException: No provider available for remote service异常怎么办? 3. 出现调用超时co ...

  10. android客户端向服务器端验证登陆方法的实现2

    一.在上一篇文章中,我只是提到了其中一种方法来实现登陆 大家可以参见: http://www.apkbus.com/android-45004-1-1.html      android获取web服务 ...