理解浏览器跨域问题

44 阅读3分钟

跨域

[跨域阅读]  link.juejin.cn/?target=htt… 

CORS背后是死路:使用自定义的HTTP头部允许浏览器和服务器之间互相了解,以确实请求和响应应该成功或失败

简单请求

不会触发CORS预检的请求称为简单请求,满足以下所有条件的才会被视为简单请求,基本上我们日常开发只会关注前面两点

  1. 使用GET、POST、HEAD其中一种方法

  2. 只使用了如下的安全首部字段,不得人为设置其他首部字段

    • Accept

    • Accept-Language

    • Content-Language

    • Content-Type
      

      仅限以下三种

      • text/plain
      • multipart/form-data
      • application/x-www-form-urlencoded
    • HTML头部header field字段:DPR、Download、Save-Data、Viewport-Width、WIdth

  3. 请求中的任意XMLHttpRequestUpload 对象均没有注册任何事件监听器;XMLHttpRequestUpload 对象可以使用 XMLHttpRequest.upload 属性访问

  4. 请求中没有使用 ReadableStream 对象

对于的简单请求,没有自定义头部,而且请求体是text/pain类型,这样的请求在发送时会有一个额外的头部叫Origin

Origin头部:包含发送请求的页面的源(协议,域名,端口)

服务器若决定响应:发送Access-Control-Allow-Origin头部,包含相同的源或是“ * ”

预检请求

需预检的请求要求必须首先使用 OPTIONS 方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。"预检请求“的使用,可以避免跨域请求对服务器的用户数据产生未预期的影响

下面的请求会触发预检请求,其实非简单请求之外的就会触发预检,就不用记那么多了

  1. 使用了PUT、DELETE、CONNECT、OPTIONS、TRACE、PATCH方法
  2. 人为设置了非规定内的其他首部字段,参考上面简单请求的安全字段集合,还要特别注意Content-Type的类型
  3. XMLHttpRequestUpload 对象注册了任何事件监听器
  4. 请求中使用了ReadableStream对象

预检请求使用OPTIONS方法发送并包含以下头部

  • Origin:与简单请求相同
  • Access-Control-Request-Method:请求的方法
  • Access-Control-Request-Headers:(可选)要使用的逗号分隔的自定义头部列表

服务器通过在响应中发送如下头部信息与浏览器沟通这些信息

  • Access-Control-Allow-Origin:与简单请求相同
  • Access-Control-Allow-Method:允许的方法
  • Access-Control-Allow-Headers:服务器允许的头部
  • Access-Control-Allow-Max-Age:缓存预检请求的秒数

请求附带身份凭证 -> cookies

如果发起请求时设置withCredentials 标志设置为 true,从而向服务器发送cookie, 但是如果服务器端的响应中未携带Access-Control-Allow-Credentials: true,浏览器将不会把响应内容返回给请求的发送者

对于附带身份凭证的请求,服务器不得设置 Access-Control-Allow-Origin 的值为*, 必须是某个具体的域名

注意,简单 GET 请求不会被预检;如果对此类带有身份凭证请求的响应中不包含该字段,这个响应将被忽略掉,并且浏览器也不会将相应内容返回给网页

img