​每次遇到跨域、代理、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. 2021-11-12:前 K 个高频元素。给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。提示:1 <= nums.length <=

    2021-11-12:前 K 个高频元素.给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素.你可以按 任意顺序 返回答案.提示:1 <= nums.length ...

  2. React-hooks 父组件通过ref获取子组件数据和方法

    我们知道,对于子组件或者节点,如果是class类,存在实例,可以通过 React.createRef() 挂载到节点或者组件上,然后通过 this 获取到该节点或组件. class RefTest e ...

  3. Python这样读写Excel数据,这样简直不要太粗暴!

    什么是xlrd&xlwt? xlrd和xlwt是Python语言中,读取和写入Excel数据的扩展工具.xlrd为xls文件read库,xlwt为xls文件write库.具体请看xlrd百度百 ...

  4. 手动封装XMLHttpRequest

    自己动手封装一个XMLHttpRequest, 兼容低版本浏览器,自动检测post与get 类型请求,自动参数拼接,参数类型辨别 <!DOCTYPE html> <html> ...

  5. nginx 反向代理proxy_pass 后加斜杠和不加斜杆的区别

    今日准备使用nginx 将上次使用docker 部署的一个vue项目进行地址代理,让他看起来高达尚一点,原本docker打包的镜像只是向外暴露了一个8191的端口,访问的时候就只能是 http://w ...

  6. 生物信息培训之WGCNA-权重基因共表达网络分析

    本文分享自微信公众号 - 生信科技爱好者(bioitee).如有侵权,请联系 support@oschina.cn 删除.本文参与"OSC源创计划",欢迎正在阅读的你也加入,一起分 ...

  7. 案例分享-被*队友的mybatis蠢哭的一天

    昨晚加班的时候被队友拉着看一个mybatis的问题,耗费了我一个小时时间,最后差点没被我打死,实在是觉得滑稽,今天回家写下来跟大伙分享一下. 问题现象 Invalid bound statement ...

  8. JavaWeb编程面试题——Spring Web MVC

    引言 面试题==知识点,这里所记录的面试题并不针对于面试者,而是将这些面试题作为技能知识点来看待.不以刷题进大厂为目的,而是以学习为目的.这里的知识点会持续更新,目录也会随时进行调整. 关注公众号:编 ...

  9. ChatGPT在工业领域的研究与应用探索-AI助手实验应用

    为什么我的工作效率和质量要比其他人要高,因为我的电脑里有代码库.产品库.方案库.自己工作经验资料库等,根据一个应用场景或需求能够很快关联到想要的资料,并且整合成新的方案.我的核心竞争力是什么?各种资料 ...

  10. DevOps|中式土味OKR与绩效考核落地与实践

    昨天一个小伙伴和我讨论了一下OKR和绩效管理,所以这次想简单明了地说下在中国怎么做比较合适,很多高大上的理论无法落地也是空中楼阁. 首先说一些,我个人的理解 道德品质和能力素质决定了一个人的职位行为 ...