全部文章

CORS 报错总缠身?这个决策树终于管用了

服务器机架前缠绕的电线和一个阻塞连接的数字挂锁,象征 CORS 错误。

朗读全文

凌晨两点。你的前端就绪,API 端点已上线,阻碍你部署的唯一东西是控制台里一个顽固的 CORS 错误。你已经在一个端点上设置了该头部。你从 Stack Overflow 复制了代码。用 curl 测试没问题,但浏览器里就是不行。浏览器在这里是老大,它说了“不行”。

这是独立开发者构建第一个 SaaS 时最常见、最令人头疼的障碍。大多数开发者迟早都会碰上它。这不是你代码里的 bug;这是你正在协商的一个安全协议。

什么是 CORS?为什么浏览器要强制执行它?

CORS(跨源资源共享)是一种浏览器安全机制,它控制哪些 Web 应用程序可以从不同的源(域名、端口或协议)请求资源。它是防范跨站请求伪造(CSRF)攻击的一种保护。是你的浏览器阻止了请求,而不是你的服务器。你需要告诉浏览器,这个请求是安全的。

定义: CORS = 一种由浏览器强制执行的安全策略,用于规定哪些域名可以访问你的 API 资源。

CORS 诊断决策树

别再盲目搜索了。按照这棵树走。从顶部开始。

1. 控制台里的错误是预检请求失败吗? - 是(OPTIONS 请求失败): 你的服务器没有正确响应预检请求。请看步骤 2。 - 否(简单请求失败): 请看步骤 4。

2. 检查你的服务器预检响应 浏览器首先会发送一个 OPTIONS 请求。你的服务器必须用所有这些头部进行响应,实际请求才能继续:

Access-Control-Allow-Origin: https://your-frontend-domain.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization

这是第一个常见故障点。常见的情形是:后端中间件只在 POST 路由上添加了 Allow-Origin,而没有在 OPTIONS 上添加。修复方法: 确保你的服务器或中间件(如 Express.js 的 cors 包)拦截所有路由,包括 OPTIONS 方法。

3. 你的源被允许了吗? Access-Control-Allow-Origin 头部不能是 *,如果用于凭证请求(即发送 cookie、Authorization 头或客户端 TLS 证书的请求)。你必须将请求中精确的 Origin 头部回传。一个常见错误是硬编码 * 或填入错误的域名。

4. 检查是否满足简单请求条件 一个“简单请求”如果满足以下所有条件,就可以绕过预检: - 方法:GET、HEAD 或 POST - 头部:仅包含 Accept、Content-Language、Content-Type(值为 application/x-www-form-urlencoded、multipart/form-data 或 text/plain)等。 - 没有自定义头部,如 Authorization 或 X-Custom-Token。 如果你发送 PUT 请求,或者 JSON 内容类型并附带认证令牌,它就不是简单请求。预检是必须的。

请求类型 发送预检 (OPTIONS) 吗? 常见失败原因
简单请求(GET 且无自定义头部) 否 响应中缺少或错误配置了 Access-Control-Allow-Origin 头。
非简单请求(POST 带 JSON 主体和令牌) 是 服务器未处理 OPTIONS 或无法回传 Origin/methods/headers。

5. 检查凭证与头部 你是否在 fetch 中使用了 credentials: 'include' 或在 XMLHttpRequest 中使用了 withCredentials: true?如果是,你的服务器必须: - 设置 Access-Control-Allow-Credentials: true - 将 Access-Control-Allow-Origin 设置为一个具体的域名(不能是 *) 这是一个严格的安全配对,你无法跳过。

6. 用这些工具调试 - 浏览器网络选项卡: 按“preflight”或“OPTIONS”过滤。响应头才是真相。 - curl -v: 模拟预检请求:curl -X OPTIONS -H "Origin: https://your-domain.com" -v https://your-api.com/endpoint - 安全头部: 在生产环境中,把 CORS 验证与 TLS 1.3 和 AES-256 加密一并检查。一个配置错误的 CORS 策略就像锁了前门但窗户大开。

SaaS 创始人常见的陷阱

  • 开发与生产环境: 开发时用 localhost:3000,生产用 yourapp.com?你的允许来源列表需要包含两者。一个基于环境变量的动态配置是必不可少的。
  • CDN 或代理层: Cloudflare 等服务或自定义 Nginx 代理可能会剥离或覆盖你的 CORS 头。你必须在边缘配置它们,而不仅仅是源服务器。
  • WebSocket 握手: 虽然不是经典的 CORS 问题,WebSocket 连接 (wss://) 在初始 HTTP 升级请求期间也会受到类似 CORS 的检查。

这个修复方案如何扩展?

一个正确的 CORS 配置对每个 API 域名来说是一次性设置。上面的决策树是针对初始设置的诊断。一旦在服务器上正确配置——无论是 Node.js、Python/Django、Go 还是无服务器函数——它应该保持稳定。关键是在你的中间件或 API 网关中集中 CORS 逻辑,而不是分散在各个路由中。这减少了错误,并使你的安全态势可审计。

别再和 CORS 较劲了。开始构建吧。

如果你是一个独立开发者,觉得这像是一个你不想深入的安全兔子窝,你不是一个人。适当的安全保障是任何 SaaS 的基本门槛。在 Trove Deck,每个定制工具从第一天起就把安全(如 CORS 和加密)打进地基。如果你需要一个技术合作伙伴来处理基础设施,好让你专注于用户,我很乐意和你聊聊你的想法。

#CORS · #WebDevelopment · #SaaS · #IndieHackers · #API · #Security · #JavaScript · #TechSupport