关于跨域

JSONP

文章链接: https://juejin.im/post/5a274ae9f265da430a5071eb

同源策略只是阻止了通过ajax技术跨域获取资源,而并没有禁止跨域获取资源本身这件事本身

正因如此,我们可以通过<link>标签,<img>标签以及<script>标签中的href属性或src属性获取异域的CSS,JS资源和图片(虽然我们其实并不能读取这些资源的内容,所以与其是是通过src属性获取这些资源,不如说是通过src引用了这些资源

CORS

官方推荐的跨域资源共享方案

CORS是W3C颁布的一个浏览器技术规范,其全称为“跨域资源共享”(Cross-origin resource sharing),它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。它的意义在于,它是由W3C官方推广的允许通过AJAX技术跨域获取资源的规范,因此相较于JSONP而言,功能更加强大,使用起来也没有了hack的味道。

浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request),浏览器对这两种请求的处理,是不一样的。

只要同时满足以下两大条件,就属于简单请求。

  • 请求方法是以下三种之一:head、get、post
  • http的头信息不超出以下几种子段:Accept、 Accept-language、 Content-Language、 Last-Event-ID、Content-Type只限于三个值: application/x-www-form-urlencoded、multipart/form-data、text/plain。

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

简单请求

对于简单请求,浏览器直接发出CORS请求。具体来说,就是在头信息之中,增加一个Origin字段。

GET /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...

上面的头信息中,Origin字段用来说明,本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。
如果Origin指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应。浏览器发现,这个回应的头信息没有包含Access-Control-Allow-Origin字段(详见下文),就知道出错了,从而抛出一个错误,被XMLHttpRequest的onerror回调函数捕获。注意,这种错误无法通过状态码识别,因为HTTP回应的状态码有可能是200。
如果Origin指定的域名在许可范围内,服务器返回的响应,会多出几个头信息字段。

Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8
  • Access-Control-Allow-Origin: 该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。

非简单请求

预检请求

非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json。
非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为”预检”请求(preflight)。

浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。