SPT术语库

跨域资源共享 CORS

本地页面请求 API 的房间数据,服务器明确允许后,浏览器才把响应交给页面脚本。

后端与接口约 10 分钟 · 从真实需求理解

1为什么 API 能收到请求,页面却读不到响应?

READ PERMISSIONCORS 读取边界
01
PAGE ORIGINhttps://app.example.test

页面发起跨域请求

02
OPTIONS PREFLIGHTGET /api/rooms/today

Origin 请求头 · https://app.example.test

03
RESPONSE HEADERS服务器响应头Access-Control-Allow-Origin: https://app.example.test

服务器声明谁可以读取

04
BROWSER READ浏览器允许脚本读取rooms[]

脚本可以读取响应

Origin 已明确,浏览器准备发送预检。

当页面和 API 的协议、域名或端口不同,浏览器会把它们视为跨源。请求可能已经到达服务器,但页面脚本能不能读取响应,还要看服务器返回的 CORS 响应头。

  • 页面先声明来源:浏览器在请求中带上 Origin。
  • 服务器再声明许可:Access-Control-Allow-Origin 等响应头必须匹配实际规则。
  • CORS 不是身份验证:它控制浏览器是否暴露跨源响应,不代替登录、权限或数据库授权。

2CORS、API 和登录权限有什么不同?

CORS 管浏览器能不能读,API 管怎样请求和返回,认证授权管谁能做什么。

  • CORS 不等于 接口 API:API 规定请求和响应的业务契约,CORS 处理浏览器对跨源响应的读取许可。
  • CORS 不等于登录:用户即使已经登录,也可能因为服务器没有允许当前 Origin 而看到 CORS 错误。
  • CORS 不等于 JSON:JSON 是数据格式;CORS 决定这份响应能否交给页面脚本。

3检查 CORS 时要看哪些部分?

01 · ORIGINhttps://app.example.test

页面来源必须被明确识别。

02 · PREFLIGHTGET /api/rooms/todayOrigin 请求头: https://app.example.test
03 · PERMISSION服务器响应头Access-Control-Allow-Origin: https://app.example.test

响应头声明许可范围。

04 · BROWSER浏览器允许脚本读取rooms[]

脚本是否可读由浏览器决定。

下面的编号都对应真实 DOM 部件,不用看图片坐标猜位置。

  • 页面 Origin 是浏览器带给服务器的实际来源。
  • 跨域请求说明方法、路径和目标 API;响应头许可说明服务器允许谁读取。
  • 浏览器读取结果区分响应到达服务器和页面脚本拿到响应这两件事。

4Origin 允许与预检失败时,页面看到什么?

Origin 在白名单内,脚本读到 rooms[]
CORS 请求
请求 OriginGET
/api/rooms/today

https://app.example.test

许可响应200 OK
rooms[]
页面处理

浏览器把响应交给页面脚本,显示今日房间。

点击“检查许可”查看这份响应。

预检未放行 Authorization,PATCH 没有发出
CORS 请求
预检请求OPTIONS → PATCH
/api/rooms/today

Access-Control-Request-Method: PATCH · Access-Control-Request-Headers: Authorization, Content-Type

浏览器结果204 NO CONTENT
CORS error
页面处理

服务器返回了预检响应,但缺少允许的请求头;浏览器在预检阶段停止,不发送 PATCH。

点击“检查许可”查看这份响应。

简单 GET 要匹配 Origin;带 Authorization 的 PATCH 还要先通过 OPTIONS 预检。

  • 简单 GET 的响应头匹配当前 Origin 时,页面可以读取 rooms[]。
  • 预检没有放行 PATCH 或 Authorization 时,浏览器会在预检阶段停止,实际请求可能根本不会发送。

5CORS 配置要同时放行 Origin 和预检

明确 Origin,并正确处理预检
go允许真实页面
allowedOrigin := "https://app.example.test"
origin := r.Header.Get("Origin")
if origin == allowedOrigin {
  w.Header().Set("Access-Control-Allow-Origin", origin)
  w.Header().Set("Vary", "Origin")
}
if r.Method == http.MethodOptions {
  w.Header().Set("Access-Control-Allow-Methods", "GET, PATCH, OPTIONS")
  w.Header().Set("Access-Control-Allow-Headers", "Authorization, Content-Type")
  w.WriteHeader(http.StatusNoContent)
  return
}

预检和实际响应都要覆盖页面真正使用的方法与请求头。

不建议这样用不要用 * 代替白名单并打开凭据
go不要这样放开
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Credentials", "true")

启用凭据时必须返回明确 Origin,不能把 * 当作白名单。

配置 CORS 时先把真实页面 Origin 写成白名单,再把页面确实会用到的方法和请求头覆盖到预检响应。

  • 正确配置:只允许 https://app.example.test,返回 Vary: Origin,并处理 GET、PATCH、OPTIONS 以及 Authorization、Content-Type。
  • 错误配置:用 Access-Control-Allow-Origin: * 配合凭据,既没有表达真实许可范围,也会被浏览器拒绝。

6怎样把 CORS 问题交给 Agent?

请处理页面 https://app.example.test 调用 https://api.example.test/api/rooms/today 的 CORS:允许的实际 Origin 只有 https://app.example.test,方法为 GET,按需允许请求头并正确处理预检;如果启用凭据,不要返回 Access-Control-Allow-Origin: *。请保持认证授权逻辑独立,不要用 no-cors 掩盖问题,也不要允许请求头中的任意 Origin。完成后用浏览器 Network 和 Console 验证预检、实际响应头及页面是否能读取 rooms[]。

7不用背,看看你能不能判断

1 / 3

CORS 主要控制什么?

请选择一个最符合题意的答案

选择答案后自动进入下一题

社区延伸

看别人真实遇到过什么

社区帖子还没有关联到这个词条。