什么是 HTTP 请求中的 preflight 类型请求

news/2024/10/8 10:00:44/
http://www.w3.org/2000/svg" style="display: none;">

在浏览器的 HTTP 请求中,当我们使用 fetch API 或者 XMLHttpRequest 来进行跨域请求时,浏览器有时会发送一种称为 Preflight 的请求。这种请求是浏览器在实际发送跨域请求前,先与目标服务器进行的一次 “探测” 请求,以确认服务器是否允许这样的请求方式。Preflight 请求的存在是为了保障浏览器的安全性,确保跨域请求不会在没有服务器允许的情况下进行。

跨域资源共享(CORS)机制规定了当浏览器发起跨域请求时,某些条件下需要发送 Preflight 请求。这种探测性的请求使用 OPTIONS 方法发出,目标是向服务器询问,客户端接下来想要发送的实际请求是否被允许。
下面是一个例子:
https://img-blog.csdnimg.cn/img_convert/b8cf65b98823c1f40318c2a9fe0b6225.webp?x-oss-process=image/format,png" alt="" />

Preflight 请求的触发条件

不是所有的跨域请求都会触发 Preflight 请求,浏览器会根据请求的类型和头部信息来决定是否需要预检。Preflight 请求通常在以下几种情况下触发:

  1. 当请求方法不是 GETPOSTHEAD,例如 PUTDELETE
  2. 当请求包含非标准的 HTTP 头部字段,比如自定义的 Authorization 头部,或者 Content-Type 不是 application/x-www-form-urlencodedmultipart/form-datatext/plain

下面是自定义头部字段触发 preflight 请求的一个例子:

https://img-blog.csdnimg.cn/img_convert/8a5ed71c04ea99348ed1024c64bb51c6.webp?x-oss-process=image/format,png" alt="" />

  1. 请求中涉及跨域资源时,尤其是涉及到敏感的操作时,浏览器会通过 Preflight 请求来确保服务器允许这些操作。

这种设计的初衷是为了防止跨域请求滥用,尤其是在涉及敏感数据的场景下,确保浏览器与服务器之间的交互安全。

Preflight 请求的流程

当浏览器决定某个跨域请求需要进行 Preflight,它会先向目标服务器发出一个 OPTIONS 请求,携带一些必要的头部信息,如 Access-Control-Request-MethodAccess-Control-Request-Headers,用于告知服务器,客户端即将发送的请求的具体方法和头部信息。服务器通过响应来告知浏览器,是否允许这样的请求。

请求示例:

假设我们要向 https://api.example.com/data 发送一个跨域的 PUT 请求,并且需要携带自定义头部 X-Custom-Header。在实际发出 PUT 请求之前,浏览器会自动生成如下的 Preflight 请求:

http">OPTIONS /data HTTP/1.1
Host: api.example.com
Origin: https://client.example.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header

其中,Access-Control-Request-Method 头部用来告诉服务器接下来会使用 PUT 方法,而 Access-Control-Request-Headers 则表明请求中会携带 X-Custom-Header 这个自定义头部。

服务器响应:

服务器接收到 Preflight 请求后,必须返回一个响应来告诉浏览器是否允许此类请求:

http">HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://client.example.com
Access-Control-Allow-Methods: GET, PUT, POST, DELETE
Access-Control-Allow-Headers: X-Custom-Header

服务器通过 Access-Control-Allow-Origin 来指定哪些源是允许访问的(这里是 https://client.example.com),通过 Access-Control-Allow-Methods 来列出允许的 HTTP 方法,并通过 Access-Control-Allow-Headers 来列出允许的头部字段。
下面是 Preflight 请求来自服务器端的响应的一个例子:

https://img-blog.csdnimg.cn/img_convert/13bb979dbe4bf47f8ea9c90a3b761139.webp?x-oss-process=image/format,png" alt="" />

Preflight 请求的使用场合

Preflight 请求主要用于跨域场景下,特别是那些涉及到更复杂请求的场合,比如非 GETPOST 方法,或者请求中包含了额外的自定义头部。

常见的使用场景包括:

  1. RESTful API 请求:当前端应用需要与其他域名下的 REST API 进行交互时,尤其是对资源进行 PUTDELETE 操作时,往往会触发 Preflight 请求。这些操作可能会修改服务器上的数据,因此需要确保安全。

    例如,一个前端应用需要向远程服务器发送数据更新请求,使用 PUT 方法更新用户信息。在这种场景下,Preflight 请求就会确保目标服务器允许跨域的 PUT 请求。

  2. 上传文件的操作:在表单上传文件时,如果使用 fetch API 或 XMLHttpRequest 并携带了非标准的头部,比如自定义的认证信息,通常会触发 Preflight 请求。浏览器需要确保服务器允许上传操作以及这些自定义的头部字段。

  3. 自定义认证头部的请求:很多应用在发起跨域请求时,需要在头部中携带如 AuthorizationToken 的自定义认证信息。由于这些头部字段并非标准字段,浏览器会先发送 Preflight 请求来探测服务器是否允许使用这些自定义头部。

Preflight 请求的实际案例

在实际开发中,有一个典型的例子是前端应用需要向第三方服务发送请求并带有认证信息。这种场景下的跨域请求常常会触发 Preflight 请求。

假设我们开发了一个电子商务应用,这个应用的后端服务托管在 https://api.shop.com,而前端页面托管在 https://shop.com。用户在购物时,前端需要向后端发送带有用户身份认证的请求,如以下场景:

  1. 用户在购物车页面点击结账,前端应用需要向后端 API 发送包含用户认证信息的请求,以确认用户是否已登录,且是否有购买权限。
  2. 请求方法为 POST,同时头部中带有 Authorization: Bearer token123 来验证用户身份。

此时,由于 Authorization 头部是非标准字段,且前端和后端的域名不同,这个请求会触发 Preflight 检查。

请求步骤:
  1. Preflight 请求
    浏览器会自动先发送一个 OPTIONS 请求,探测服务器是否允许发送带有 Authorization 头部的跨域请求:

    http">OPTIONS /checkout HTTP/1.1
    Host: api.shop.com
    Origin: https://shop.com
    Access-Control-Request-Method: POST
    Access-Control-Request-Headers: Authorization
    
  2. 服务器响应
    后端服务器接收到该请求后,会检查是否允许该跨域请求,并返回允许的结果:

    http">HTTP/1.1 204 No Content
    Access-Control-Allow-Origin: https://shop.com
    Access-Control-Allow-Methods: POST
    Access-Control-Allow-Headers: Authorization
    

    响应中,服务器明确告知浏览器允许该域名 https://shop.com 发起 POST 请求,并且允许使用 Authorization 头部。

  3. 实际请求
    在确认服务器允许跨域请求后,浏览器会继续发送实际的 POST 请求,包括认证信息:

    http">POST /checkout HTTP/1.1
    Host: api.shop.com
    Origin: https://shop.com
    Authorization: Bearer token123
    
使用 Preflight 请求的优化

尽管 Preflight 请求保障了安全性,但在一些频繁的跨域请求场景下,这会带来额外的网络开销。为此,可以采用一些优化策略:

  1. 服务器缓存 Preflight 响应:通过在响应中设置 Access-Control-Max-Age 头部,服务器可以告知浏览器在一定时间内不需要重复进行 Preflight 请求。这能显著减少不必要的 OPTIONS 请求,提升应用的性能。

    例如,服务器可以返回这样的响应,告知浏览器在未来 10 分钟内不需要重新发起 Preflight 请求:

    http">HTTP/1.1 204 No Content
    Access-Control-Allow-Origin: https://shop.com
    Access-Control-Allow-Methods: POST
    Access-Control-Allow-Headers: Authorization
    Access-Control-Max-Age: 600
    
  2. 减少复杂的请求:避免不必要的自定义头部字段,或者尽量使用简单的 GETPOST 请求,能够有效减少 Preflight 请求的触发。对于一些轻量级的操作,使用标准的请求方法和头部可以避免 Preflight 请求,从而提升效率。

结语

Preflight 请求作为 CORS 机制的一部分,主要作用是确保跨域请求的安全性,尤其是在涉及非标准请求时。通过 Preflight 请求,浏览器与服务器能够就请求的合法性达成共识,保护用户的数据安全。在实际应用中,理解 Preflight 请求的工作原理,并在合适的场景下进行优化,能够大大提升 Web 应用的性能和用户体验。


http://www.ppmy.cn/news/1536065.html

相关文章

机器学习框架

机器学习框架是用于构建、训练和评估机器学习模型的工具集。以下是一些常用的机器学习框架: TensorFlow:由Google开发的开源框架,支持深度学习和传统机器学习模型。 PyTorch:由Facebook开发的开源框架,重点支持动态计…

医院管理新趋势:Spring Boot技术引领

4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式,是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示: 图4-1系统工作原理…

CoppeliaSim和Matlab建立远程连接教程

CoppeliaSim和Matlab建立远程连接教程 Matlab通过调用CoppeliaSim的远程API和库函数实现远程连接,为实现Matlab和CoppeliaSim的联合仿真做准备。 一、获取并查看版本信息 点击 Help 查看版本信息 使用的CoppeliaSim Edu版本为:4.4.0 位数:64bit 二、拷贝API函数和库文件…

Spring Boot驱动的现代医院管理系统

1系统概述 1.1 研究背景 如今互联网高速发展,网络遍布全球,通过互联网发布的消息能快而方便的传播到世界每个角落,并且互联网上能传播的信息也很广,比如文字、图片、声音、视频等。从而,这种种好处使得互联网成了信息传…

微信小程序的面试题

简述下 wx.navigateTo(), wx.redirectTo(), wx.switchTab(), wx.navigateBack(), wx.reLaunch() 区别 ? wx.navigateTo() : 保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面 wx.redirectTo() : 关闭当前页面,跳转到应用内的…

《自然语言处理NLP》—— 词嵌入(Embedding)及 Word2Vec 词嵌入方法

在了解词嵌入之前需要了解什么是独热编码(One-Hot Encoding),下面链接的文章中对其有简单的介绍 https://blog.csdn.net/weixin_73504499/article/details/142748311?spm1001.2014.3001.5501 一、词嵌入介绍 词嵌入(Embedding…

计算机网络:计算机网络概述 —— 描述计算机网络的参数

文章目录 数据量性能指标速率带宽数据传输速率 吞吐量时延分析时延问题 时延带宽积往返时间利用率丢包率丢包的情况 抖动可用性可靠性安全性 计算机网络是现代信息社会的基础设施,其性能和可靠性对各类应用至关重要。为了理解和优化计算机网络,我们需要深…

智能涌现|迎接智能时代,算力产业重构未来

前言 OpenAI首席执行官山姆奥特曼在《智能时代》中描绘了一个令人振奋的未来图景,其中算力产业将扮演至关重要的角色。奥特曼预测,我们可能在“几千天内”迎来超级智能,这一进程将极大加速社会结构的智能化转型。 这一预测与算力产业的未来…