JavaScript 中的 CORS:为什么 Postman 能工作,而浏览器不行?

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:当浏览器说“不”,而 Postman 说“是”



想象一下这个场景:你正在用 JavaScript 编写前端代码,向 API 发送一个 fetch 请求。结果控制台里出现了一个红色错误:



Access to fetch at 'https://api.example.com/data' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.


你抓耳挠腮,打开 Postman,输入相同的 URL,点击发送——然后 奇迹发生了,数据竟然返回了!服务器在工作吗?是的。那为什么浏览器会阻止这个请求呢?



这种情况是 Web 开发中的经典问题。在 Stack Overflow 上,这个问题已经积累了成千上万的浏览量。今天,我们将深入底层,弄清楚为什么会发生这种情况,CORS 是如何工作的,以及如何修复它。开始吧!



什么是 CORS,为什么需要它?



CORS(跨域资源共享) 是一种浏览器安全机制。它禁止来自一个网站(例如 http://localhost:3000)的 JavaScript 向另一个网站(例如 https://api.example.com)发送请求,除非服务器明确允许。



为什么需要它?为了防止攻击者通过你的浏览器从其他网站窃取数据。如果没有 CORS,任何脚本都可以读取你的邮件、银行账户——这太可怕了。



但这里有一个细微差别:CORS 仅在浏览器中生效。Postman、curl、服务器端请求(Node.js、Python)——它们不会检查 CORS。这是 Postman 能工作而 JavaScript 不能的首要原因。



CORS 底层工作原理:简单解释



当你的 JavaScript(例如 fetch)发出跨域请求时,浏览器会做两件事:



  1. 检查请求类型。
  2. 如果需要,发送一个预检请求(OPTIONS)。


简单请求 vs 预检请求



有两种类型的跨域请求:



  • 简单请求——如果你使用 GET、POST 或 HEAD,并且只使用基本标头(Content-Type: text/plain, application/x-www-form-urlencoded, multipart/form-data)。浏览器会直接发送请求,然后检查响应头中的 Access-Control-Allow-Origin。
  • 预检请求——如果你使用非标准标头(例如 Authorization)、PUT/DELETE 方法,或 Content-Type: application/json。浏览器会先发送一个 OPTIONS 请求来询问:“我可以发送这样的请求吗?”


以下是代码中的预检请求示例:



fetch('https://api.example.com/data', {  method: 'POST',  headers: {    'Content-Type': 'application/json', // 这会触发预检请求    'Authorization': 'Bearer my-token'  },  body: JSON.stringify({ key: 'value' })}).then(response => response.json()).then(data => console.log(data)).catch(err => console.error('CORS error:', err));


如果服务器没有在 OPTIONS 响应中返回正确的 Access-Control-Allow-Origin 标头——浏览器就会阻止主请求。



为什么 Postman 会忽略 CORS?



Postman 不是浏览器。它不使用同源策略。它只是发送一个 HTTP 请求并接收响应。它不关心请求来自哪里——它不会检查 CORS 标头。服务器可以返回任何内容,Postman 都会显示响应。



因此,当你通过 Postman 测试 API 时,你看到的是服务器在工作。但浏览器要求服务器明确允许从你的域名进行访问。



如何修复 CORS 错误:3 种实用方法



1. 配置服务器(正确的方法)



如果你有服务器的访问权限,请添加 Access-Control-Allow-Origin 标头。例如,在 Node.js 中使用 Express:



const express = require('express');const app = ex                

博客

书籍推荐