Loading... ### 一、HTTP Get 请求详解 HTTP Get 请求是客户端向服务器请求获取特定资源的方式。在 Web 环境中,浏览器向服务器请求网页、图像或其他数据时通常使用 Get 请求。其特性如下: 1. **请求方式**:GET 请求通过 URL 发送请求数据,适用于请求不需要修改服务器上数据的场景。 2. **参数传递**:GET 请求参数通常以键值对形式附加在 URL 的查询字符串部分,例如:`http://example.com/api?param1=value1¶m2=value2`。 3. **安全性与幂等性**: - GET 请求是**幂等**的,即多次调用相同请求不会对服务器状态产生不同影响。 - 不建议将敏感信息通过 GET 请求传递,因为 URL 会被记录到日志或浏览器历史中。 ### 二、什么是 CORS 预检请求(Preflight Request) **跨域资源共享(Cross-Origin Resource Sharing, CORS)** 是一种机制,允许受限资源(如网页、API)被其他不同域的网页安全访问。在跨域请求中,浏览器会在正式请求前先发起一份 **预检请求**,以确定服务器是否允许目标请求。 #### 1. 为什么需要预检请求? 跨域请求(例如通过 JavaScript 的 XMLHttpRequest 或 Fetch API 发起的请求)可能存在安全隐患。浏览器出于安全考虑,会先向目标服务器发起一份**预检请求**,以确保实际请求的安全性,尤其是在请求类型或自定义 HTTP 头字段不属于简单请求的情况下。 - **简单请求**:GET、POST(只限 `application/x-www-form-urlencoded`,`multipart/form-data`,`text/plain`)等常用请求类型,不包含自定义头信息,通常无需预检。 - **复杂请求**:PUT、DELETE 等请求方法或包含自定义头信息时,浏览器会先进行**预检**,询问服务器是否允许该请求。 预检请求的类型为 **OPTIONS**,其目的为向服务器询问实际请求是否被允许。 #### 2. 预检请求的工作流程 预检请求的主要流程如下: 1. 浏览器首先发送一个 **OPTIONS** 请求到目标服务器。 2. 服务器根据请求的内容,判断是否允许该实际请求(通过特定的 HTTP 响应头来指示)。 3. 如果服务器允许,浏览器才会继续发送后续的实际请求。 下面是一个**预检请求工作流程图**,帮助理解: ```mermaid graph TD; A[浏览器发起跨域请求] --> B{请求是否简单请求?}; B -- 是 --> C[直接发送 GET/POST 请求]; B -- 否 --> D[发送 OPTIONS 预检请求]; D --> E{服务器允许该请求?}; E -- 是 --> F[继续发送实际请求]; E -- 否 --> G[终止请求,报错]; ``` ### 三、HTTP Get + Preflight 请求的示例 假设前端页面需要从跨域的 API 获取数据,数据请求方式为 **GET**,但包含了一些自定义的 HTTP 头,例如 `Authorization`,此时浏览器会发起预检请求。 #### 1. 预检请求(OPTIONS) 预检请求的格式如下: ```http OPTIONS /api/data HTTP/1.1 Host: api.example.com Origin: http://frontend.example.com Access-Control-Request-Method: GET Access-Control-Request-Headers: Authorization ``` - **Access-Control-Request-Method**:告知服务器接下来的实际请求使用的 HTTP 方法(如 GET)。 - **Access-Control-Request-Headers**:告知服务器即将使用的自定义头字段。 #### 2. 服务器的响应 服务器收到预检请求后,若允许该请求,将返回如下响应: ```http HTTP/1.1 200 OK Access-Control-Allow-Origin: http://frontend.example.com Access-Control-Allow-Methods: GET, POST, OPTIONS Access-Control-Allow-Headers: Authorization ``` - **Access-Control-Allow-Origin**:表示允许请求的来源。 - **Access-Control-Allow-Methods**:允许使用的请求方法。 - **Access-Control-Allow-Headers**:允许的自定义头字段。 #### 3. 实际 GET 请求 一旦服务器允许,浏览器便会继续发送实际的 GET 请求,如下所示: ```http GET /api/data HTTP/1.1 Host: api.example.com Authorization: Bearer <token> Origin: http://frontend.example.com ``` 服务器返回数据后,浏览器即可在页面中进行渲染。 ### 四、HTTP Get 与 Preflight 请求的联系 在特定场景下,虽然使用了 **GET** 请求,但由于存在自定义头字段或请求的其他特征超出了简单请求的范畴,浏览器会自动发起 **OPTIONS** 预检请求,以确保跨域访问的安全性。 - **安全性考量**:预检请求为跨域通信增加了额外的安全保障,避免恶意网站对用户敏感数据进行未经授权的访问。 - **性能考量**:预检请求会产生额外的网络开销,尤其是对延迟敏感的请求。开发者在设计系统时应权衡其带来的性能影响,合理地使用简单请求,或者优化跨域策略以减少预检请求的频率。 ### 五、CORS 和预检请求的配置要点 #### 1. 服务端配置 为了允许跨域请求,服务器需要正确配置 **CORS** 响应头: - **Access-Control-Allow-Origin**:允许特定的来源(或设置为 `*` 允许所有来源)。 - **Access-Control-Allow-Methods**:指定允许的 HTTP 方法,例如 `GET, POST, PUT, DELETE`。 - **Access-Control-Allow-Headers**:列出允许的自定义头字段,如 `Authorization`、`Content-Type`。 #### 2. 示例配置(Node.js + Express) 以下是使用 **Express** 框架在 **Node.js** 中配置 CORS 的示例代码: ```javascript const express = require('express'); const app = express(); app.use((req, res, next) => { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization'); next(); }); app.get('/api/data', (req, res) => { res.json({ message: '数据获取成功!' }); }); app.listen(3000, () => { console.log('Server is running on port 3000'); }); ``` - **Access-Control-Allow-Origin** 设置为 `*`,表示允许所有来源,视情况可替换为特定的域名。 - **Access-Control-Allow-Headers** 包含了自定义的 `Authorization` 头,以便前端请求时能够通过预检。 ### 六、总结 HTTP Get 请求与预检请求在跨域场景中相辅相成。**预检请求**确保了跨域通信的安全性,防止未经授权的跨域数据获取,同时需要开发者在设计 API 时仔细考虑性能开销。 1. **GET 请求**用于获取服务器资源,适合幂等操作; 2. **预检请求**主要用于浏览器在跨域请求前确认安全性,由于其额外的请求次数,可能带来性能问题; 3. 开发者可以通过合理的**CORS** 配置来减少预检请求的频率或范围。 在开发过程中,正确理解和配置 CORS 以及预检请求对于确保 Web 应用的安全性与性能至关重要。 --- 以上为对 HTTP Get + Preflight 请求的深入解析,包含了每个部分的详细说明与实际操作示例,希望对您理解 HTTP 请求中的跨域安全机制有所帮助。🚀 最后修改:2024 年 10 月 18 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏