​每次遇到跨域、代理、CORS这几个词都懵懵的,我决定一次把他们都搞明白,以后遇到他们再也不用害怕了。

一、什么是同源策略?

同源策略是在1995年由 Netscape公司引入到浏览器的,目前所有浏览器都支持,它是浏览器最重要的安全保障,目的是严格管理不同网站间相互的资源访问(严格来说是不同“源”之间)。

什么是“源”,“源”是指:协议+域名+端口号,这三个必须都相同,才算是同源。假设我们的网站是:http://www.abc.com,那么:

http://www.abc.com/a 同源(与路径无关)
http://www.abc.com:80 同源(80端口是http默认端口)
http://www.Abc.com 同源(url忽略大小写)
https://www.abc.com 不同源(协议不同)
http://www.abc.com:81 不同源(端口不同)
http://abc.com 不同源(域名不同)
http://api.abc.com 不同源(域名不同)
http://api.www.abc.com 不同源(域名不同)
http://220.188.32.45:80 不同源(自己服务器的IP也不行)

注意,同源策略只存在于浏览器之中,服务端发出的HTTP请求是不受限制的。

二、跨源不止AJAX

提到跨域(跨源),一般都是我们在写AJAX的时候会涉及。其实,web中还有很多别的行为也会跨域,浏览器对这些行为有不同的默认处理方式,常见的有以下这些(注意,浏览器的处理方式未经严格验证,仅供参考):

<script>、<link>、<img>、<video>、<object>、background的url() 根据我们的经验,对这些浏览器是允许跨域访问的,css好像需要设置一下content-type,这个用到时再说
@font-face引入字体 这个部分浏览器是不支持跨域的,需要CORS
cookie 可以通过把cookie写入到一级域名,二级域名就可以访问了,其余情况不允许
localStorge和indexDB 不允许跨域
form提交 允许跨域
AJAX 不允许跨域
<iframe> 过时的东西,不讨论了

三、为什么需要同源策略?

我是这么理解的:网站获取自己的资源当然没问题,可如果想拉取其他网站的资源,这种行为等于“偷”啊!你用我的浏览器去“偷”人家的东西,那万一出了事,我是要承担责任的!那可不行,我得禁止你“偷”人家的东西,于是就有了同源策略。

以下我们只讨论AJAX。并且其实AJAX跨域也有:JSONP、WebSocket、CORS三种方法,由于本人只对CORS感兴趣,所以只讨论CORS。

四、什么是CORS?

很显然,完全禁止跨源也不行啊,现在很多应用前端和服务本来就不在一个服务器上。那怎么办呢?除非,服务器你自己告诉我,这个资源允不允许这个源访问。怎么告诉我呢?在响应头里。这种通过允许服务器自定义不同源对自己资源的访问权限,然后浏览器据此来拦截或放行的方式,就叫CORS。

这儿我们可以得到一个重要的信息,就是浏览器拦截跨域请求,是在响应阶段,也就是响应返回到浏览器之后,再决定是否拦截。自然会产生的疑问是,为什么不在请求阶段就拦截呢?在请求阶段就拦截的话,如何知道服务器那边到底允不允许呢?这样等于彻底禁止了跨域资源请求,显然不行。

四、简单请求和复杂请求

浏览器把跨域的AJAX分为:简单请求和复杂请求。具体定义如下,同时满足以下3项(其实还有其他2项,只是一般用不到)要求的,就是简单请求,其余的都是复杂请求:

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

  • HEAD
  • GET
  • POST

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

  • Accept
  • Accept-Language
  • Accept-Encoding
  • Content-Language
  • Content-Type

(3)Content-Type只限于以下三个值:

  • text/plain
  • multipart/form-data
  • application/x-www-form-urlencoded

是不是有点眼熟?这三种Content-Type正是Form表单的三种数据提交格式。这主要是因为,在没有AJAX的时代,我们通过Form表单的方式来提交数据,做过Form表单提交的同学都知道,这个是允许跨域的。所以为了向前兼容,浏览器就把Form表单可以模拟的AJAX称为简单请求,反之就是复杂请求。

关于这个其实有更深层次的理解,大家可以在知乎搜索“为什么跨域的post请求区分为简单请求和非简单请求和content-type相关?”,看看“贺师俊”大佬的回答。

与简单请求不同的是,复杂请求会在正式请求之前,先发送一个OPTIONS请求到服务器,称为“预检”,在获得服务器的允许后,才会发送正式请求。

五、什么是预检请求?

那么问题来了,既然是响应阶段才拦截,也就是说,不管这个跨域访问服务器允不允许,都不影响它真实的到达服务器,在服务器“兜了一圈”。如果这个请求是GET还好,只不过是来“观光”的,不会产生啥影响,但如果是POST、PUT之类的请求,本身往往是会修改服务器资源的,即便响应结果在到达浏览器后被拦截了,对服务器的影响也已经发生了,无法挽回了。虽然服务器也可以写代码直接拒绝这些请求,但浏览器不能指望服务器自己把这些都做好啊。那怎么办呢?浏览器也有办法,在发出真实请求之前,先发一个“预检请求”,先问服务器这个请求是否被允许?服务器允许之后,才发送正式请求。这种方式,就叫“预检”。

六、预检请求能不能省了?

如果每次复杂请求都要先发送一次预检,也太麻烦了。很自然的会想,有没有办法来避免每次都要预检?有办法,服务器可以在OPTIONS请求的响应里加一个Access-Control-Max-Age响应头,告诉浏览器这个预检的结果可以被缓存多久。比如Access-Control-Max-Age:86400,则在一天之内,对同一个请求,浏览器不用重复发送预检请求了。什么?你想再简单一点,能不能告诉浏览器“这个网站朕准了,发送一次之后都不用发送预检了”?抱歉,做不到。预检能省来源于浏览器对预检请求结果的缓存,而这个缓存的键,是:URL+请求方法+请求头。所以,只能针对单个请求,利用缓存在一定时间内只发送一次预检。

以上是我对跨域和CORS的理解,有错误之处欢迎指出,非常感谢!

重学HTTP:理解同源策略和CORS的更多相关文章

  1. 浏览器的同源策略及CORS跨域解决方案 DRF

    一个源的定义 如果两个页面的协议,端口(如果有指定)和域名都相同,则两个页面具有相同的源. 举个例子: 下表给出了相对http://a.xyz.com/dir/page.html同源检测的示例: UR ...

  2. 同源策略与CORS

    同源策略 同源策略是浏览器保护用户安全上网的重要措施,协议.域名.端口号三者相同即为同源. 不同源下,浏览器不允许js操作Cookie.LocalStorage.DOM等数据或页面元素,也不允许发送a ...

  3. 同源策略、CORS

    一.同源策略 同源策略(Same origin policy) 是一种约定, 它是浏览器最核心也是最基本的安全功能 , 如果缺少了同源策略, 则浏览器的正常功能可能都会受影响 , 可以说web是构建在 ...

  4. 同源策略与CORS跨域请求

    一.同源策略 1.简介 同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响.可以说Web是构建在同源 ...

  5. 同源策略 - JSONP - CORS

    1.  Jquery 对象可以通过 .index() 进行取出自当前元素在父级元素中存放的索引: 2. 浏览器的同源策略 -- Ajax 在访问非本网站的时候,在数据返回的时候,会被浏览器拦截 - 后 ...

  6. JSONP跨域的script标签请求为什么不受同源策略的限制?

    在复习跨域的时候,复习到了JSONP跨域,大家都知道JSONP跨域是通过动态创建script标签,然后通过其src属性进行跨域请求的,前端需要一个数据处理的回调函数,而服务端需要配合执行回调函数,放入 ...

  7. [CORS:跨域资源共享] 同源策略与JSONP

    Web API普遍采用面向资源的REST架构,将浏览器最终执行上下文的JavaScript应用Web API消费者的重要组成部分."同源策略"限制了JavaScript的跨站点调用 ...

  8. Apache2 同源策略解决方案 - 配置 CORS

    什么是同源策略 现在的浏览器大多配有同源策略(Same-Origin Policy),具体表现如下: 浏览某一网站,例如 http://www.decembercafe.org/.这个网页中的 Aja ...

  9. 关于安全性问题:(XSS,csrf,cors,jsonp,同源策略)

    关于安全性问题:(XSS,csrf,cors,jsonp,同源策略) Ajax 是无需刷新页面就能从服务器获取数据的一种方法.它的核心对象是XHR,同源策略是ajax的一种约束,它为通信设置了相同的协 ...

  10. 同源策略 & 高效调试CORS实现

    # 目录 为什么有同源策略? 需要解决的问题 CORS跨域请求方案 preflight withCredentials 附:高效.优雅地调试CORS实现 ----------------------- ...

随机推荐

  1. 2023-02-23:请用go语言调用ffmpeg,解码mp4文件并保存为YUV420P格式文件。

    2023-02-23:请用go语言调用ffmpeg,解码mp4文件并保存为YUV420P格式文件. 答案2023-02-23: 使用 github.com/moonfdd/ffmpeg-go 库. 解 ...

  2. 2021-09-28:合并区间。以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回一个不重叠

    2021-09-28:合并区间.以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] .请你合并所有重叠的区间,并返回一个不重叠 ...

  3. [ABC270F] Transportation

    [ABC270F] Transportation 题意 有 \(n\) 个点,有 \(m\) 条可以加上的边,如果两个点同时建立了一种东西,那么也算连了一条边,每条边都有个代价,每个点建一个东西也有不 ...

  4. 文心一言 VS 讯飞星火 VS chatgpt (26)-- 算法导论5.1 1题

    一.证明:假设在过程 HIRE-ASSISTANT 的第 4 行中,我们总能决定哪一个应聘者最佳.则意味着我们知道应聘者排名的全部次序. 文心一言: 证明: 假设在过程 HIRE-ASSISTANT ...

  5. \n被当成回车处理

    Regex.Escape   C# 字符串变量str 的值为"a\nb"如果直接输出显示的话,就成了:ab需要输出显示为:a\nb string str = "a\nb& ...

  6. Java(instanceof和类型转换)

    1.instanceof和类型转换 instanceof 引用类型比较,判断一个对象是什么类型 public static void main(String[] args) { // Object & ...

  7. Simple Date Format类到底为啥不是线程安全的?

    摘要:我们就一起看下在高并发下Simple Date Format类为何会出现安全问题,以及如何解决Simple Date Format类的安全问题. 本文分享自华为云社区<[高并发]Simpl ...

  8. 喜报 | ShowMeBug获国家高新技术企业认证!

    近日,深圳至简天成科技有限公司(以下简称至简天成)顺利通过国家高新技术企业认证! 国家高新技术企业是由国务院主导.科技部牵头的国家级荣誉资质,是我国科技类企业中的"国"字号招牌,完 ...

  9. malloc/free 与 new/delete

    malloc/free与new/delete表达式的区别?相同点: 都是用来申请堆空间不同点: 1. malloc/free是库函数; new/delete是表达式 2. malloc开空间时,并不会 ...

  10. SpringBoot集成支付宝 - 少走弯路就看这篇

    最近在做一个网站,后端采用了SpringBoot,需要集成支付宝进行线上支付,在这个过程中研究了大量支付宝的集成资料,也走了一些弯路,现在总结出来,相信你读完也能轻松集成支付宝支付. 在开始集成支付宝 ...