我相信如果你写过前后端分离的web应用程序,或者写过一些ajax请求调用,你可能会遇到过CORS错误。

  • CORS是什么?
  • 它与安全性有关吗?
  • 为什么要有CORS?它解决了什么目的?
  • CORS是怎样运行的?

如果您有这些问题,那么这篇文章非常适合您。

一、什么是CORS?

要了解什么是CORS(Cross-Origin Resource Sharing:跨站资源共享),首先我们需要了解什么是同源策略Same Origin Policy(SOP)。SOP是所有的现代浏览器都具备的安全措施,它不允许从一个加载的js脚本和资源的Origin域与另一个Origin域进行交互。换句话说,如果您的网站是www.example.com,则您无法向www.test.com发出XHR请求。

那么SOP有什么用?如果没有同源策略的限制,你想想会发生什么? 比如:您已经登录到微博,并且不小心打开了一个恶意网站。该网站可以向微博发出请求,并从您微博登录的会话中提取个人信息。这显然是巨大的安全问题,为了防止这种情况,在浏览器中实施同源策略的限制。实际上,服务器并没有意识到在浏览器端发生的这一切,您仍然可以使用curl或postman发出相同的请求,并且一切响应正常,因为这些工具上没有SOP。

如果说SOP是限制跨源访问的一种方式,那么CORS是一种绕过SOP限制并允许您的前端向服务器提出合法请求的方法。 如果您的服务端的确是存在跨域的情况(实际上对于现代分布式应用,这很常见),由于SOP限制您的客户端将无法向多节点跨域服务器发出xhr请求。救星就出现了,CORS使我们能够以安全且可管理的方式做到跨域请求,突破同源策略的限制。

二、同源策略的源(Same Origin Policy的Origin)

源由三部分组成:协议,hostip(域)和端口。例如

  • http://example.com/xxx/index.htmlhttp://example.com/yyy/index.html是同源,
  • http://example.com:80http://example.com(对于http默认端口为80)是同源。
  • 由于协议不同,http://example.com/app1https://example.com/app2是不同的源。
  • http://example.comhttp://www.example.com由于域名不同,也是不同的源
  • 非常要注意的是http://localhosthttp://127.0.0.1是不同的源

同源策略就是:不允许不同的ip、端口、协议的应用在浏览器内进行互相资源共享、请求调用。

三、CORS如何运作?

CORS规范允许服务器向浏览器返回一些HTTP Headers,浏览器可以基于这些HTTP Headers来决定是否突破SOP的限制。最主要的一个HTTP Headers是Access-Control-Allow-Origin。

//目标服务允许所有的网站对其进行跨域访问
Access-Control-Allow-Origin: *
//目标服务允许特定的网站对其进行跨域访问
Access-Control-Allow-Origin: https://example.com

CORS有两种类型的请求:“simple”简单请求和“preflight”预检请求,根据请求方法的不同由浏览器确定使用哪种请求。

simple简单请求:

如果符合以下所有条件,则API请求被视为简单请求:

  • API方法是以下方法之一:GET,POST或HEAD。
  • Content-Type请求头包含:application/x-www-form-urlencodedmultipart/form-datatext/plain

这两个条件将构成大多数简单请求的用例,但是可以在此处找到更详细的简单请求条件列表。

如果您的API请求被视为simple简单请求,这个请求就可以直接被发送给服务器。服务器使用CORS HTTP Headers进行响应,浏览器将检查Access-Control-Allow-Origin后决定这个请求是否可以突破同源策略的限制,进行下一步的处理。

preflight预检请求:

如果您的API请求不满足成为简单请求的标准(最常见不满足简单请求标准的Content-Type值为application/json),则浏览器将在发送实际请求之前发出预检请求。

举一个例子,我们尝试使用GET请求https://example.com/statusContent-Typeapplication/json,所以浏览器认为它不符合一个简单请求的标准,因此浏览器会在发出实际请求之前发出预检请求,这个预检请求是使用HTTP的 OPTIONS方法发出的:

curl --location --request OPTIONS 'http://example.com/status' \
--header 'Access-Control-Request-Method: GET' \
--header 'Access-Control-Request-Headers: Content-Type, Accept' \
--header 'Origin: http://test.com'

上面的curl就是模拟预检请求,实际作用是:浏览器希望告诉服务器,我的实际请求将使用HTTP GETmethod进行调用,Content-TypeAccept作为HTTP headers,这个请求是从https://test.com发起的。服务器响应此请求:

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: OPTIONS, GET, HEAD, POST
Access-Control-Allow-Headers: Content-Type, Accept
  • Access-Control-Allow-Origin:允许发出请求的源,或者*可以从任何来源发出请求。(即允许跨域的源)
  • Access-Control-Allow-Methods:允许的以逗号分隔的HTTP方法列表。(即允许跨域的HTTP方法)
  • Access-Control-Allow-Headers:允许发送的HTTP headers列表。

浏览器收到服务端的预检请求响应之后,在我们的示例中服务器响应*可以从任何来源发出请求,因此现在浏览器将再次访问https://example.com/status,使用GET方法(不再是OPTIONS方法),浏览器将不再限制该请求的发出与响应数据的接收。

如果预检请求响应的Origin是特定的Access-Control-Allow-Origin: http://domain.com,浏览器将出现Cross-Origin Request Blocked错误。因为服务器端预检结果只允许http://domain.com发出跨域请求,不允许其他应用向我发出跨域请求。

四、如何处理CORS错误

我们现在知道什么是CORS及其工作原理,后面的事情其实就简单了。从上面的内容我们需要注意的是,对CORS的完全控制权在服务器,即服务器可以允许或禁止源的跨域访问。所以说跨域问题的处理一般都在服务端进行,不同的服务端的处理HTTP 请求头的代码是不一样的,当然也可以不用写代码,比如:nginx、haproxy设置。但是万变不离其宗:最终都是对HTTP Headers进行重写

我就简单的举几个例子:

比如Servlet处理跨域

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) resp;
response.setHeader("Access-Control-Allow-Origin", "*"); //解决跨域访问报错
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
chain.doFilter(req, resp);
}

比如Spring MVC配置

@Configuration
public class GlobalCorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") //添加映射路径,“/**”表示对所有的路径实行全局跨域访问权限的设置
.allowedOrigins("*") //开放哪些ip、端口、域名的访问权限
.allowCredentials(true) //是否允许发送Cookie信息
.allowedMethods("GET","POST", "PUT", "DELETE") //开放哪些Http方法,允许跨域访问
.allowedHeaders("*") //允许HTTP请求中的携带哪些Header信息
.exposedHeaders("*"); //暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
}
};
}
}

欢迎关注我的博客,里面有很多精品合集

  • 本文转载注明出处(必须带连接,不能只转文字):字母哥博客

觉得对您有帮助的话,帮我点赞、分享!您的支持是我不竭的创作动力! 。另外,笔者最近一段时间输出了如下的精品内容,期待您的关注。

跨站资源共享CORS原理深度解析的更多相关文章

  1. CORS(跨站资源共享)介绍

    起因 有同学在nginx站点配置中加了一行Access-Control-Allow-Origin *,导致微信中业务数据异常,抓包看http头有两个Access-Control-Allow-Origi ...

  2. SpringSecurity环境下配置CORS跨站资源共享规则

    一.CORS简述 要说明CORS(Cross Origin Resourse-Sharing) 跨站资源共享,就必须先说同源策略.长话短说,同源策略就是向服务端发起请求的时候,以下三项必须与当前浏览器 ...

  3. 跨域资源共享CORS与JSONP

    同源策略限制: 同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果没有同源策略,攻击者可以通过JavaScript获取你的邮件以及其他敏感信息,比如说 ...

  4. 跨域解决方案 - 跨域资源共享cors

    目录 1. cors 介绍 2. 原理 3. cors 解决跨域 4. 自定义HTTP 头部字段解决跨域 5. 代码演示 5. 参考链接 1. cors 介绍 cors 说的是一个机制,其实相当于一个 ...

  5. VUE SpringCloud 跨域资源共享 CORS 详解

    VUE  SpringCloud 跨域资源共享 CORS 详解 作者:  张艳涛 日期: 2020年7月28日 本篇文章主要参考:阮一峰的网络日志 » 首页 » 档案 --跨域资源共享 CORS 详解 ...

  6. 网络编程-跨域资源共享 CORS

    目录 1.什么是同源策略? 2.跨域资源共享 CORS 3.预检请求 4.CORS相关字段 5.Golang实现跨域 6.参考资料 1.什么是同源策略? 如果两个 URL 的 protocol.por ...

  7. 跨域资源共享(CORS)问题解决方案

    CORS:Cross-Origin Resource Sharing(跨域资源共享) CORS被浏览器支持的版本情况如下:Chrome 3+.IE 8+.Firefox 3.5+.Opera 12+. ...

  8. java8Stream原理深度解析

    Java8 Stream原理深度解析 Author:Dorae Date:2017年11月2日19:10:39 转载请注明出处 上一篇文章中简要介绍了Java8的函数式编程,而在Java8中另外一个比 ...

  9. mysql索引原理深度解析

    mysql索引原理深度解析 一.总结 一句话总结: mysql索引是b+树,因为b+树在范围查找.节点查找等方面优化 hash索引,完全平衡二叉树,b树等 1.数据库中最常见的慢查询优化方式是什么? ...

随机推荐

  1. spring mvc(3) DispatcherServlet

    通过前面的例子,我们实现了spring mvc模式,那么在spring mvc模式下请求是如何被执行最终返回页面的呢? 从服务器收到请求开始,执行流程如下: 1.服务器接收请求,根据web.xml的配 ...

  2. 部署项目到服务器 & 搭建博客网站

    搭建博客网站 作为名程序员,或者是网络编程爱好者,拥有一个自己的博客网站再好不过,本篇文章手把手教你部署自己的网站

  3. 生成器generator和迭代器Iterator

    一.列表生成式       在学习生成器迭代器之前先了解一下什么是列表生成式,列表生成式是Python内置的非常简单却强大的可以用来创建list的生成式.什么意思?举个例子,如果想生成列表[0,1,2 ...

  4. 题解【QTree3】

    题目描述 给出N个点的一棵树(N-1条边),节点有白有黑,初始全为白 有两种操作: 0 i : 改变某点的颜色(原来是黑的变白,原来是白的变黑) 1 v : 询问1到v的路径上的第一个黑点,若无,输出 ...

  5. Ubuntu通过iptables防止ssh暴力破解

    步骤 安装iptables-persistent用于保存iptables规则 配置iptables规则 实时更新iptables规则以拦截IP访问 安装iptables-persistent sudo ...

  6. Tensorflow学习笔记No.6

    数据的批标准化 本篇主要讲述什么是标准化,为什么要标准化,以及如何进行标准化(添加BN层). 1.什么是标准化 传统机器学习中标准化也叫做归一化. 一般是将数据映射到指定的范围,用于去除不同维度数据的 ...

  7. MySQL数据备份脚本

    #!/bin/bash ############################# # time:20191210 # fage trainning ######################### ...

  8. 更简易的机器学习-pycaret的安装和环境初始化

    1.安装 pip install pycaret 在谷歌colab中还要运行: from pycaret.utils import enable_colab enable_colab() 2.获取数据 ...

  9. mongoose 查询数据属性为数组,且包含某个值的方法

    mongoose在创建schema的时候有些属性需要设置为数组类型,比如商品图片.商品标签.不同尺寸.价格等. 那么怎么查询具有某个标签的商品了,下面记录一下两种情况: 查询具有'vue'标签的文章 ...

  10. 最新最最最简单的Snagit傻瓜式破解教程(带下载地址)

    最新最最最简单的Snagit傻瓜式破解教程(带下载地址) 下载地址 直接滑至文章底部下载 软件介绍 一个非常著名的优秀屏幕.文本和视频捕获.编辑与转换软件.可以捕获Windows屏幕.DOS屏幕:RM ...