CORS 跨域详解

1、为何会有跨域问题

  • 浏览器同源策略
  • (跨域是浏览器的限制,抓包工具等能够拿到数据)
  • 浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感受
  • 如下状况会致使跨域


    2、如何解决跨域

  • CORS(跨域资源共享),支持全部类型的 http 请求,本文主要介绍这种方式

3、简单请求和非简单请求

Ajax 按照条件能够分为两种请求方式,简单请求和非简单请求。nginx

同时知足如下两个条件,就属于简单请求
ajax

  1. 使用下列方法之一
    • head
    • get
    • post
  2. 请求的header是
    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type 只限于三个值
      • application/x-www-form-urlencodes
      • multipart/form-data
      • text/plain

对于简单请求,浏览器直接发出CORS请求。在头部字段中,增长一个Origin字段。(chrome有时会隐藏这个字段)
chrome

下面是一个项目中的ajax封装,使用的就是简单请求:json


4、CORS请求相关的字段,都以 Access-Control- 开头

  • Access-Control-Allow-Origin :必选
    • (一个或者多个容许跨越的)请求头Origin字段的值
    • *:接受任何域名
  • Access-Control-Allow-Credentials: 可选
    • true:表示容许发送cookie,此时 Access-Control-Allow-Origin 不能设置为*,必须指定明确的,与请求网页一致的域名;
    • 不设置该字段,不须要浏览器发送cookie
  • Access-Control-Expose-Headers:可选
    • 列出了哪些首部能够做为响应的一部分暴露给外部
    • 默认,只有六种暴露给外部
      • Cache-Control
      • Content-Language
      • Content-Type
      • Expires
      • Last-Modified
      • Pragma
    • 若是想让客户端能够访问到其余的首部信息,能够将他们在Access-Control-Expose-Headers里面列出来

5、withCredentials 属性

  • CORS默认不发送Cookie和HTTP认证信息,若是要把Cookie 发送到服务器,一方面须要服务器赞成,设置响应头 Access-Control-Allow-Credentials:true另外一方面,客户端发送请求时,也要进行一些设置,例如 xhr.withCredentials = true;

6、非简单请求

非简单请求就是那种对服务器有特殊要求的请求,好比请求方法为PUT 或者 DELETE,或者 Content-Type 为 application/json;跨域

预检请求和回应

非简单请求的CORS请求,会在正式通讯以前,增长一次HTTP查询请求,称为“预检”。浏览器会询问服务器,当前网页所在的域名是否在服务器的许可名单以内,以及可使用哪些 HTTP 动词和头部信息段,只有获得确定答复,才会发出正式的接口请求。不然,报错。浏览器

一、预检请求服务器

  • 用 OPTIONS 方法,询问。预检请求包括三个字段
    • Origin,表示请求来自哪一个域;
    • Access-Control-Request-Method:必须,浏览器会使用的请求方法;
    • Access-Control-Request-Headers: 浏览器发送 CORS 请求会额外发送的头部信息段;

二、预检回应cookie

  • 服务器收到预检请求后,检查了Origin,Access-Control-Request-Method,Access-Control-Request-Headers字段后,确认容许跨域,就能够作出回应
  • 若是浏览器否定了“预检”请求,会返回一个正常的HTTP回应,可是没有任何CORS相关的头部信息字段,浏览器会认为不一样意,触发一个错误
  • 服务器回应的其余CORS字段
    • Access-Control-Allow-Methods: 必需,逗号分隔的字符串,表示服务器支持的全部跨域请求方法;
    • Access-Control-Allow-Headers:浏览器支持的全部头部字段;
    • Access-Control-Allow-Credentials:Cookie
    • Access-Control-Allow-Max-Age: 指定本次请求的有效期;

正常请求和回应

一旦经过预检请求,之后就跟简单请求同样。app

另外一个项目使用了这种方式,如下是其截图:工具




7、服务端如何设置CORS

  • 若是设置请求头 Content-Type:application/x-www-form-urlencoded,则为简单请求
    • 直接设置响应头 Access-Control-Allow-Origin 为 *,或者具体的域名;
    • 若是响应头Access-Control-Allow-Credentials 为 true,则此时Access-Control-Allow-Origin 不能设置为*,必须指定明确的域名;
  • 若是设置请求头 Content-Type:application/json,则为非简单请求
    • 处理 OPTIONS 请求,服务端能够单独写一个路由
    • 能够把这部分抽离处理,做为一个中间件,例如Koa;
相关文章
相关标签/搜索