您的位置:

CORS 错误详解

一、什么是CORS?

CORS(Cross-Origin Resource Sharing)是一种机制,它使用额外的HTTP头来告诉浏览器,让运行在一个origin (domain) 的Web应用被准许访问来自不同源服务器上的指定的资源。当一个资源在请求时,它使用一个GET、POST或是HEAD方法,然后这个资源响应一个HTTP头,表示允许特定的源来访问该资源,从而实现在不同域之间(协议、域名、端口号)进行安全地数据传输。

二、CORS的场景

CORS适用于XMLHttpRequest或Fetch API发出的请求,用于跨域访问其它域名下的数据,典型的场景有:

  • Web前端应用程序发出跨域AJAX请求,比如一个设置在a.com域名下的Web应用请求b.com域名下的资源。
  • CORS也适用于Web前端框架客户端应用程序与API客户端服务之间的跨域调用。

三、CORS的请求头和响应头

1、请求头:

Origin: http://a.com

2、响应头:

Access-Control-Allow-Origin: http://a.com
Access-Control-Allow-Headers: *, Authorization
Access-Control-Allow-Methods: *
Access-Control-Allow-Credentials: true

四、CORS的错误码

1、简单请求时,出现以下情况会产生CORS错误码:

  • 请求方式不是GET、HEAD、POST,如PUT、DELETE等。
  • 请求头信息不是以下几种,参考HTTP规范中的“列出的首部字段”:
  •     Accept
        Accept-Language
        Content-Language
        Last-Event-ID
        Content-Type(仅限于部分值)
        
  • 请求使用了HTTP身份验证信息。
  • 请求包含cookie信息。
  • 请求的Content-Type不正确。

2、复杂请求时,出现以下情况会产生CORS错误码:

  • 请求方法并不是GET/POST/HEAD。
  • 发送了POST请求,但不是以下类型之一:
  •     application/x-www-form-urlencoded
        multipart/form-data
        text/plain
        
  • 设置了自定义请求头,服务器没有在响应中添加对应头信息。
  • 请求中包含的Origin值和服务器所在的域不匹配。
  • 服务器没有响应Access-Control-Allow-Origin头。
  • 服务器响应中没有Access-Control-Allow-Methods头、Access-Control-Allow-Headers头或Access-Control-Max-Age头。
  • 可能是因为跨域设置了Credentials属性,但后台没有响应Access-Control-Allow-Credentials: true

五、CORS错误的解决方法

CORS错误解决分两种情况:一种是服务端提供跨域支持,一种是在前端搭配后端提供跨域支持,该解决方法大体分为以下几种:

1、服务端提供跨域支持。

在服务器端添加 Access-Control-Allow-Origin头部,可允许特定的源访问该资源,并可在头部添加允许的 HTTP 方法和响应头域。

if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
    header("Access-Control-Allow-Origin: http://a.com");
    header("Access-Control-Allow-Headers: *, Authorization");
    header("Access-Control-Allow-Methods: *");
    header('Access-Control-Allow-Credentials: true');
    exit;
}
header("Access-Control-Allow-Origin: http://a.com");
header('Access-Control-Allow-Credentials: true');

2、前端搭配后端提供跨域支持。

在前端发起请求时,设置请求头:

const xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.open('GET', 'http://b.com/api', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.setRequestHeader('Cookie', document.cookie)
xhr.setRequestHeader('Authorization', auth);
xhr.send();

在后端返回请求响应时,设置响应头:

header('Access-Control-Allow-Origin: http://a.com');
header('Access-Control-Allow-Headers: *, Authorization');
header('Access-Control-Allow-Methods: *');
header('Access-Control-Allow-Credentials: true');
echo $responseBody;

六、CORS错误码实际案例

1、ERR_TOO_MANY_REDIRECTS:重定向次数过多,通常是请求被拦截。

2、ERR_FAILED:通常是请求超时,或者是服务器内部错误。

3、ERR_TUNNEL_CONNECTION_FAILED:WebSocket服务请求失败。

4、ERR_ABORTED:用户主动中断请求。

5、ERR_CONNECTION_REFUSED:请求被服务器拒绝,通常是跨域问题导致。