2020-10-26

跨站资源共享CORS原理深度解析

我相信如果你写过前后端分离的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(域)和端口。例如

  • 三、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: GETmethod进行调用,Content-TypeAccept作为HTTP headers,这个请求是从https://test.com发起的。服务器响应此请求:

    HTTP/1.1 204 No ContentAccess-Control-Allow-Origin: *Access-Control-Allow-Methods: OPTIONS, GET, HEAD, POSTAccess-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: Request Blocked错误。因为服务器端预检结果只允许四、如何处理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配置

    @Configurationpublic 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("*"); //暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)   }  }; }}

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

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

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

    • 《手摸手教你学Spring Boot2.0》
    • 《Spring Security-JWT-OAuth2一本通》
    • 《实战前后端分离RBAC权限管理系统》
    • 《实战SpringCloud微服务从青铜到王者》
    • 《VUE深入浅出系列》

    原文转载:http://www.shaoqun.com/a/483318.html

    马士基集团:https://www.ikjzd.com/w/1296

    mail.ru:https://www.ikjzd.com/w/2232

    square:https://www.ikjzd.com/w/2106


    我相信如果你写过前后端分离的web应用程序,或者写过一些ajax请求调用,你可能会遇到过CORS错误。CORS是什么?它与安全性有关吗?为什么要有CORS?它解决了什么目的?CORS是怎样运行的?如果您有这些问题,那么这篇文章非常适合您。一、什么是CORS?要了解什么是CORS(Cross-OriginResourceSharing:跨站资源共享),首先我们需要了解什么是同源策略SameOrigi
    anker:https://www.ikjzd.com/w/1027
    汇通天下物流:https://www.ikjzd.com/w/2055
    台风未走、地震又来,日本站卖家遭遇订单暴跌和断货危机!:https://www.ikjzd.com/home/6029
    惠州永记生态园怎么样?好玩吗?:http://tour.shaoqun.com/a/2276.html
    干货:Facebook官方商务插件功能及使用方法详解:https://www.ikjzd.com/home/21458

No comments:

Post a Comment