CORS跨域问题解决方案

跨域问题主要是由于浏览器同源策略限制引起,简单来说,就是只相信自己人,不相信外人,只响应同域名发来的http请求,不相信其他域名发来的http请求。好处是减少上当受骗的几率,缺点是不符合webapi的大趋势,api访问会受限。

浏览器同源策略

同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说 Web 是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。

它的核心就在于它认为自任何站点装载的信赖内容是不安全的。浏览器只被允许访问来自同一站点的资源,而不是那些来自其它站点可能怀有恶意的资源。

同源是指:域名、协议、端口相同。

跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin (domain) 上的Web应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在的服务器不同的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求

CORS(跨域资源共享)

CORS(Cross-origin resource sharing,跨域资源共享)是一个 W3C 标准,定义了在必须访问跨域资源时,浏览器与服务器应该如何沟通。CORS 背后的基本思想,就是使用自定义的 HTTP 头部(origin、method)让浏览器与服务器进行沟通,从而决定请求或响应是应该成功,还是应该失败。

CORS 需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE 浏览器不能低于 IE10。

整个 CORS 通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS 通信与同源的 AJAX 通信没有差别,代码完全一样。浏览器一旦发现 AJAX 请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求(非简单请求),但用户不会有感觉。

因此,实现 CORS 通信的关键是服务器。只要服务器实现了 CORS 接口,就可以跨源通信。

浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。

只要同时满足以下两大条件,就属于简单请求。
1、请求方法是以下三种方法之一:HEADGETPOST
2、HTTP的头信息不超出以下几种字段:AcceptAccept-LanguageContent-LanguageLast-Event-IDContent-Type

Content-Type:只限于三个值application/x-www-form-urlencodedmultipart/form-datatext/plain

凡是不同时满足上面两个条件,就属于非简单请求。

浏览器对这两种请求的处理,是不一样的。

简单请求

在请求中需要附加一个额外的 Origin 头部,其中包含请求页面的源信息(协议、域名和端口),以便服务器根据这个头部信息来决定是否给予响应。例如:Origin: http://www.abc.com
如果服务器认为这个请求可以接受,就在Access-Control-Allow-Origin头部中回发相同的源信息(如果是公共资源,可以回发 * )。例如:Access-Control-Allow-Origin:http://www.abc.com
没有这个头部或者有这个头部但源信息不匹配,浏览器就会驳回请求。正常情况下,浏览器会处理请求。注意,请求和响应都不包含 cookie 信息。
如果需要包含 cookie 信息,ajax 请求需要设置 xhr 的属性 withCredentialstrue,服务器需要设置响应头部Access-Control-Allow-Credentials: true

服务器需要做的工作:
1.设置允许访问本接口的网址
2.设置允许访问本接口的请求类型
3.设置允许访问本接口的头

非简单请求

浏览器在发送真正的请求之前,会先发送一个 Preflight 请求给服务器,这种请求使用 OPTIONS方法,发送下列头部:
Origin:与简单的请求相同。
Access-Control-Request-Method: 请求自身使用的方法。
Access-Control-Request-Headers: (可选)自定义的头部信息,多个头部以逗号分隔。

例如:
1、浏览器先发送一个Option请求到服务器

Origin: http://www.abc.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: token

2、发送这个请求后,服务器可以决定是否允许这种类型的请求。服务器通过在响应中发送如下头部与浏览器进行沟通:

Access-Control-Allow-Origin:与简单的请求相同。
Access-Control-Allow-Methods: 允许的方法,多个方法以逗号分隔。
Access-Control-Allow-Headers: 允许的头部,多个方法以逗号分隔。
Access-Control-Max-Age: 应该将这个 Preflight 请求缓存多长时间(以秒表示)。

例如:

Access-Control-Allow-Origin: http://www.abc.com
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: token
Access-Control-Max-Age: 1728000

一旦服务器通过 Preflight 请求允许该请求之后,以后每次浏览器正常的 CORS 请求,就都跟简单请求一样了。

预请求只在第一次发生,检测通过后,后面请求时不会再发出Option请求

服务器需要做的工作:
1.设置允许访问本接口的网址
2.设置允许访问本接口的请求类型
3.设置允许访问本接口的头

优点
CORS 通信与同源的 AJAX 通信没有差别,代码完全一样,容易维护。
支持所有类型的 HTTP 请求。

缺点
存在兼容性问题,特别是 IE10 以下的浏览器。
第一次发送非简单请求时会多一次请求。

案例一:

这就是个简单请求

$ajax({
url:"http://www.abc.com/api.php?action=getlogo",
data:{siteid:123}
})

案例二:

这是一个非简单请求,因为headers中加入了自定义头
图片发自简书App

参考:
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS
https://www.cnblogs.com/laixiangran/p/9064769.html

推荐阅读更多精彩内容

  • 本文主要参考跨域资源共享 CORS 详解 浏览器的同源策略一直以来都是Web安全的基础,但这同时也制约了Web研发...
    liqingbiubiu阅读 744评论 0 2
  • 1. 什么是跨域 跨域,是指浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对JavaScri...
    极客教程阅读 4,208评论 2 86
  • <转>详解跨域(最全的解决方案) 什么是跨域跨域,是指浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,...
    涅槃快乐是金阅读 2,035评论 0 3
  • 题目1.什么是同源策略? 同源策略(Same origin Policy): 浏览器出于安全方面的考虑,只允许与本...
    FLYSASA阅读 903评论 0 6
  • 前沿: 最近总听到同事聊跨域得问题,于是自己抽空仔细的查阅了一下关于跨域的知识。说到跨域,就得提到同源,跨域是指一...
    戈弋图阅读 699评论 0 4