​每次遇到跨域、代理、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. 百度飞桨(PaddlePaddle)- 张量(Tensor)

    飞桨 使用张量(Tensor) 来表示神经网络中传递的数据,Tensor 可以理解为多维数组,类似于 Numpy 数组(ndarray) 的概念.与 Numpy 数组相比,Tensor 除了支持运行在 ...

  2. Keepalived 高可用

    Keepalived 高可用 什么是高可用 一般是指2台机器启动着完全相同的业务系统,当有一台机器down机了,另外一台服务器就能快速的接管,对于访问的用户是无感知的. 高可用通常使用的软件 keep ...

  3. 2021-08-06:天际线问题。城市的天际线是从远处观看该城市中所有建筑物形成的轮廓的外部轮廓。给你所有建筑物的位置和高度,请返回由这些建筑物形成的 天际线 。每个建筑物的几何信息由数组 build

    2021-08-06:天际线问题.城市的天际线是从远处观看该城市中所有建筑物形成的轮廓的外部轮廓.给你所有建筑物的位置和高度,请返回由这些建筑物形成的 天际线 .每个建筑物的几何信息由数组 build ...

  4. 【Python】爬虫下载视频

    Python爬虫下载视频 前言 这两天我一时兴起想学习 PS ,于是去我的软件宝库中翻出陈年已久的 PhotoshopCS6 安装,结果发现很真流畅诶! 然后去搜索学习视频,网上的视频大多浮躁,收费, ...

  5. dotnet平台Http消息处理者工厂

    1 前言 Microsoft.Extensions.Http是一个设计非常优异的客户端工厂库,其提供了IHttpClientFactory用于创建HttpClient和IHttpMessageHand ...

  6. javascript中的错误类型

    javascript 中的错误类型: SyntaxError TypeError ReferenceError RangeError URLError Error SyntaxError 语法错误 / ...

  7. Charles一文全明白

    自从用上了Mac本,抓包工具也从Fiddler换成了Charles,用了这么长时间,也是该对Charles做一个总结了,避免自己下次配置的时候又忘记怎么操作 1.Charles是什么? Charles ...

  8. 【lwip】14-TCP协议分析之TCP协议之可靠传输的实现(TCP干货)

    lwip_14_TCP协议之可靠传输的实现 前言 ‍ 前面章节太长了,不得不分开. 这里已源码为主,默认读者已知晓概念或原理,概念或原理可以参考前面章节,有分析. 参考:李柱明博客:https://w ...

  9. 一步步教你如何搭建K8S集群

    一.环境配置 三台CentOS7虚拟机,默认配置,内存2GB.处理器2核心. 先更新下系统 1 sudo yum update 2 sudo yum upgrade 二.安装并启动 docker 1 ...

  10. Python socket记录

    目录 网络编程 1.基本概念 Python中的网络编程 网络编程 1.基本概念 1.什么是客户端/服务器架构? 服务器就是一系列硬件或软件,为一个或多个客户端(服务的用户)提供所需的"服务& ...