返回顶部
首页 > 资讯 > 前端开发 > JavaScript >一文详解CORS与预检请求
  • 518
分享到

一文详解CORS与预检请求

JSCORS与预检请求CORS预检请求 2023-05-17 08:05:04 518人浏览 泡泡鱼
摘要

目录CORS预检请求携带了自定义头信息的请求PUT,DELETE方法的请求服务器不允许跨域总结CORS 出于安全性,浏览器限制脚本内发起的跨源 Http 请求。例如,XMLHttpR

CORS

出于安全性,浏览器限制脚本内发起的跨源 Http 请求。例如,XMLHttpRequest 和 Fetch api 遵循。这意味着使用这些 API 的 WEB 应用程序只能从加载应用程序的同一个域请求 HTTP 资源,除非响应报文包含了正确 CORS 响应头。

跨源资源共享CORS,通过允许服务器标示除了它自己以外的其他访问源、协议或端口,使得浏览器允许这些源访问加载自己的资源。简单讲,就是目标资源与当前页面不处于同一个域时,浏览器的同源策略会阻止请求发出者获得响应数据。除非服务器允许跨域访问,也就是支持CORS。

这是一些CORS相关的响应头信息,如果目标资源服务器支持CORS,必须附带一部分这些头信息与浏览器交互

Access-Control-Allow-Origin:该字段必须出现在服务器的响应中,表示允许跨域的源。如果是通配符( * ),表示接受任意域名的请求。
Access-Control-Allow-Methods:该字段表示接受的请求方法列表,多个值用逗号分隔。
Access-Control-Allow-Headers:该字段指定了实际请求可以携带的头部信息,多个值用逗号分隔。
Access-Control-Allow-Credentials:该字段标记是否允许发送 Cookie。如果为 true,则表示允许发送 Cookie。
Access-Control-Max-Age:该字段指定了预检请求的有效期(单位为秒),即在指定时间内不再发送预检请求,直接发送实际请求即可。
Access-Control-Expose-Headers:该字段用于指定哪些头部信息可以作为响应的一部分被获取到。

预检请求

当发送跨域请求时,浏览器会先发送一个OPTioNS方法的预检请求,探测服务器是否允许实际请求(POST、GET等)的跨域访问。服务器在接收到这个请求后,会返回一组响应头信息(详见上文),包含了对CORS的支持情况和允许的请求方法,如果服务器对跨域请求进行了允许,则浏览器才会真正地发送POST请求。如果服务器对预检请求的响应头中拒绝跨域访问或者根本没有任何CORS头信息,浏览器会抛出错误

因此,浏览器需要发送两次请求来确认服务器是否允许跨域请求,并确保安全性。

下面将演示触发预检请求的情况并且演示是处于跨域的环境下。

携带了自定义头信息的请求

在这种情况下,无论任何请求方法都会触发预检请求

我们请求 https://api.GitHub.com/,这个接口支持跨域访问,我们通过添加自定义请求头,来触发预检请求

代码:

var requestOptions = {
  method: 'GET',
  headers: {
    test: 'test'   // 自定义的头信息
  },
  redirect: 'follow'
}

fetch("https://api.github.com/", requestOptions)
  .then(response => response.JSON())
  .then(result => console.log(result))
  .catch(error => console.log('error', error))

运行效果:

可以看到明明在代码里面只有一次请求,可是浏览器却发出了两次请求,其中一个请求就是预检请求

看下预检请求和真实请求的请求头:

不难发现

  • 真实请求中,携带了自定义请求头字段
  • 在预检请求头中,access-control-request-headers字段标识了真实请求头中的自定义字段
  • 在预检请求头中,access-control-request-method字段标识了真实请求所使用的方法,这里是GET方法

总结来说,预检请求会携带上真实请求使用的请求方法和自定义头字段,去探测服务器是否允许这样做。

再来看下预检请求的响应头

这些用蓝色方框圈起来的字段可以在上文中找到对应的解释。这里需要说明一点,可以从第一张图看到真实请求是失败的,原因在于我们添加的自定义请求头字段test并不在服务器允许的请求头字段中,这一点从预检请求的响应头字段access-control-allow-headers很容易看出。

那么如果不携带test头信息,或者换成允许的头字段,请求会成功,这一点留给读者自行测试

PUT,DELETE方法的请求

PUT请求

var raw = jsON.stringify({
  "selected_organization_ids": [
    32,
    91
  ]
})

var requestOptions = {
  method: 'PUT',
  body: raw,
  redirect: 'follow'
}

fetch("https://api.github.com/enterprises//actions/runner-groups//organizations", requestOptions)
  .then(response => response.text())
  .then(result => console.log(result))
  .catch(error => console.log('error', error))

DELETE请求

var requestOptions = {
  method: 'DELETE',
  redirect: 'follow'
}

fetch("https://api.github.com/admin/users//authorizations", requestOptions)
  .then(response => response.text())
  .then(result => console.log(result))
  .catch(error => console.log('error', error))

真实请求失败是因为没有传递正确的参数或者接口需要认证。

服务器不允许跨域

上文的演示都是建立在目标资源允许跨域访问的基础上,下面演示目标资源不允许跨域的情况

fetch("https://buy.vmall.com/getSkuRushbuyInfo.json", {
  method: 'get',
  headers: {
    test: 'test'
  }
}).then(res => {
  return res.json()
}).then(res => {
  console.log(res)
})

观察到预检请求头中没有任何CORS响应头信息,表示服务器不允许跨域访问,这时候浏览器就会报错

在代码层面也是可以捕捉到错误的,但是演示代码中没有捕获。

总结

  • CORS是一套规范,指导浏览器和服务器之间如何进行跨域资源共享
  • 如果请求跨域,对于一些特定类型的请求,浏览器会先发送一次预检请求,去探测服务器是否允许
  • 演示了一部分会触发预检请求的情况

以上就是一文详解CORS与预检请求的详细内容,更多关于CORS与预检请求的资料请关注编程网其它相关文章!

--结束END--

本文标题: 一文详解CORS与预检请求

本文链接: https://lsjlt.com/news/210968.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作