HTTP跨域原理

posts/http%E8%B7%A8%E5%9F%9F%E5%8E%9F%E7%90%86

简单请求

请求方式为 GETPOSTHEAD,且仅包含以下 Request Headers:

  • Accept
  • Accept-Language
  • Content-Type(只限于 application/x-www-form-urlencoded、multipart/form-data、text/plain)
  • Content-Language
  • Last-Event-ID

当发生跨域时,浏览器会携带一个 Origin 头,其包含了协议、域名、端口。

服务器依据该头检查请求是否被允许,若允许向浏览器返回一个正确的 Access-Control-Allow-Origin,浏览器根据它的值决定是否完成请求(或报错)。

复杂请求

不符合“简单请求”要求的,被称为“复杂请求”。如采用 PUTDELETE 请求方式,或 Content-Type 的类型为 application/json

复杂请求会在“本次请求”前,先发起一个预检(Preflight)请求,以检查“本次请求”是否被允许。允许则发送,否则直接报错。预检的请求方式为 OPTIONS,请求头除 Origin 外,还包括:

  • Access-Control-Request-Method:指明“本次请求”方式;
  • Access-Control-Request-Headers:指明“本次请求”携带的头,逗号分隔;

与“简单请求”一致,同样需要服务器返回正确的 Access-Control-Allow-Origin 头,否则将终止“本次请求”并报错。

CORS Response Headers

共用

  • Access-Control-Allow-Origin 必选,表示本次请求是否允许跨域。它的值可以与 Origin 一致(多个使用逗号隔开),或为 *

  • Access-Control-Allow-Credentials 可选,表示是否允许携带 Cookie 等授权信息。可选值 truefalse,默认 false。 若设置为 true,需要配合 withCredentials 属性一并使用。

  • Access-Control-Expose-Headers 可选,除“安全响应头”外,浏览器可读取的其它响应头列表。如 Content-Encoding(多个使用逗号隔开),或为 *。 安全响应头包括:Cache-Control、Content-Language、Content-Length、Content-Type、Expires、Last-Modified、Pragma。

复杂请求

  • Access-Control-Allow-Methods 可选,表示所有被允许的请求方式(逗号分隔)。

  • Access-Control-Allow-Headers 可选,表示所有被允许的请求头(逗号分隔)。

  • Access-Control-Max-Age 可选,预检查询的有效期(单位秒),在此期间,不再发起新的预检请求。

三种请求方式

  • same-origin:仅允许同源请求
  • cors:按照 CORS 策略请求。若非同源,且未响应有效的 CORS Response Headers,则报错
  • no-cors:不按照 CORS 策略请求,仅支持“简单请求”。若非同源,返回的 Response 对象 type 为 opaque,且读不到任何值(status、body、url 等字段均为 zero value)。像是 <link><script><img><iframe> 在未指定 crossorigin 时都为 no-cors