学会这几点,CORS Error 轻松解决

11,026 阅读3分钟

一、什么是 CORS

先从名称出发,Cross-Origin Resource Sharing (CORS) 翻译过来就是「跨域资源共享」,它是一个系统,它由一系列传输的 HTTP 头组成,这些 HTTP 头决定浏览器是否阻止前端 JavaScript 代码获取跨域请求的响应。 举一个跨域的例子: www.baidu.com/fetchData 使用 XHR 请求 www.qiandu.com/featchData

名词解释

  • HTTP 头,它是服务端与客户端之间传递消息的附加信息,包括请求标头、响应标头、通用标头,实体标头,并且通常存在于 HTTP 请求的首部,格式是 header-name: header-value
  • Origin,Web 内容的源由用于访问它的的方案 (协议),主机 (域名) 和端口定义。只有当协议,域名和端口都匹配时,这时就称为同源。

二、造成 CORS errors 的原因以及解决

原因有多种,比如:

  • CORS 被禁用
  • 服务端响应请求为重定向
  • 协议不同,使用 http 去请求 https 的资源
  • 服务端没有设置 'Access-Control-Allow-Origin' 标头的值或者不匹配
  • Credential 不接受 http 响应标头中的 ‘Access-Control-Allow-Origin’ 设置为 ‘*’
  • http 请求的方法与服务端设置的 'Access-Control-Allow-Method' 标头的值不匹配
  • CORS 请求要求服务端设置 'Access-Control-Allow-Credential' 设置为 true,但是服务端并没有设置或者设置为 false
  • CORS 预检请求失败
  • 服务端设置了多个 'Access-Control-Allow-Origin' 标头的值,该标头只接受一个值

详情参考:CORS errors 汇总

三、为什么有 CORS errors

出于安全的考虑,浏览器限制从脚本中发出的跨域请求。例如 XHR 和 Fetch 都遵守同源策略。

四、什么是 CORS 预检请求

CORS 预检请求用于检查服务器是否支持 CORS 即跨域资源共享。 它一般是用了以下几个 HTTP 请求头的 OPTIONS 请求:Access-Control-Request-Method 和 Access-Control-Request-Headers,以及一个 Origin 标头。 当有必要的时候,浏览器会自动发出一个预检请求;所以在正常情况下,前端开发者不需要自己去发这样的请求。

五、为什么要有预检请求

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

六、什么情况下触发预检请求

先说说什么情况不会触发预检请求吧,也就是简单请求。

简单请求

⚠️注意:需要满足以下所有条件

  • 使用下列方法之一
    • GET
    • POST
    • HEAD
  • 除了被用户代理自动设置的首部字段(例如 Connection、User-Agent)其他允许设置的标头集合:
    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type(需要注意额外的限制)
  • **Content-Type **的值仅限于下列三者之一:
    • text/plain
    • multipart/form-data
    • application/x-www-form-urlencoded
  • 请求中的任意 XMLHttpRequest 对象均没有注册任何事件监听器;XMLHttpRequest 对象可以使用 XMLHttpRequest.upload 属性访问。
  • 请求中没有使用 ReadableStream 对象。

如果不满足以上条件,那么 CORS 请求将自动变为预检请求