4
> 几个问题:
1. 什么是跨域?
2. 为什么会有跨域?
3. 如何处理跨域

我们在日常的开发中,经常会遇到跨域资源共享,或者进行跨域接口访问的情况。跨域资源共享( CORS)机制允许 Web 应用服务器进行跨域访问控制。

跨域资源共享标准新增了一组 HTTP 首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源。另外,规范要求,对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是GET以外的 HTTP 请求,或者搭配某些 MIME 类型的POST请求),浏览器必须首先使用OPTIONS方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括Cookies和 HTTP 认证相关数据)。

在涉及到CORS的请求中,我们会把请求分为简单请求和复杂请求。

简单请求

满足以下条件的请求即为简单请求:

  • 请求方法:GET、POST、HEAD
  • 除了以下的请求头字段之外,没有自定义的请求头

  • Content-Type的值只有以下三种(Content-Type一般是指在post请求中,get请求中设置没有实际意义)

    • text/plain
    • multipart/form-data
    • application/x-www-form-urlencoded
  • 请求中的任意XMLHttpRequestUpload 对象均没有注册任何事件监听器 (未验证)

    • XMLHttpRequestUpload 对象可以使用 XMLHttpRequest.upload 属性访问
  • 请求中没有使用 ReadableStream 对象 (未验证)

复杂请求

非简单请求即为复杂请求。复杂请求我们也可以称之为在实际进行请求之前,需要发起预检请求的请求。

简单请求复杂请求的跨域设置

针对简单请求,在进行CORS设置的时候,我们只需要设置

Access-Control-Allow-Origin:*
// 如果只是针对某一个请求源进行设置的话,可以设置为具体的值
Access-Control-Allow-Origin: 'http://www.yourwebsite.com'

针对复杂请求,我们需要设置不同的响应头。因为在预检请求的时候会携带相应的请求头信息

Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-CUSTOMER-HEADER, Content-Type

相应的响应头信息为:

Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
// 设置max age,浏览器端会进行缓存。没有过期之前真对同一个请求只会发送一次预检请求
Access-Control-Max-Age: 86400

如果发送的预检请求被进行了重定向,那大多数的浏览器都不支持对预检请求的重定向。我们可以通过先发送一个简单请求的方式,获取到重定向的url XHR.responseURL,然后再去请求这个url。

附带身份凭证的请求

一般而言,对于跨域 XMLHttpRequest或 Fetch 请求,浏览器不会发送身份凭证信息。如果要发送凭证信息,需要设置 XMLHttpRequest 的某个特殊标志位。
如果在发送请求的时候,给xhr 设置了withCredentials为true,从而向服务器发送 Cookies,如果服务端需要想客户端也发送cookie的情况,需要服务器端也返回Access-Control-Allow-Credentials: true响应头信息。

对于附带身份凭证的请求,服务器不得设置 Access-Control-Allow-Origin的值为“*”。

这是因为请求的首部中携带了Cookie信息,如果 Access-Control-Allow-Origin的值为“*”,请求将会失败。而将 Access-Control-Allow-Origin的值设置为 http://foo.example(请求源),则请求将成功执行。


饭等米
114 声望13 粉丝

前端新人