🧑💻 面试官:前端请求 API,报跨域。怎么处理?
🙋♂️ 我:服务端允许当前 Origin,并配置需要的方法与请求头。
🧑💻 面试官:Allow-Origin 写星号,再携带登录 Cookie,可以吗?
🙋♂️ 我:不可以,带凭据时需要明确允许的来源。
🧑💻 面试官:跨域报错,是不是请求没到服务器?OPTIONS 成功,为什么正式请求又返回 401?
CORS 管的是「浏览器怎样跨来源访问并读取响应」,不替服务端完成鉴权,也不阻止所有跨来源请求到达。
面试速答(60 秒版)
同源通常要求协议、主机与端口相同。不同来源之间,浏览器按同源策略和 CORS 规则处理。
有些请求可以直接发,但响应需要服务端许可,页面脚本才能读取;另一些先发 OPTIONS 预检,询问来源、方法与请求头是否允许,再发正式请求。
跨来源携带 Cookie,前端通常需要 credentials: “include”,服务端需要明确 Allow-Origin 和 Allow-Credentials。Cookie 还要符合域、路径、SameSite、Secure 及浏览器策略。
CORS 不代替认证。允许某个页面跨域,不代表它的用户有权限;预检通过,也不代表正式请求登录成功。

知识点详解:浏览器究竟拦住了哪一步?
域名一样,不一定同源
app.example.com 与 api.example.com 主机不同;localhost 的 3000 与 8080 端口不同,都跨源。
路径不同不会造成跨源。同源比较协议、主机和端口,不是完整 URL 必须一样。
SameSite 判断的“站”又是另一组概念。同一主域下不同子域可能跨源,却仍同站。排查 Cookie 时不能混为一谈。
请求可能发出,只是脚本读不到响应
部分符合条件的 GET 或表单类型请求,无需预检,可以先发送,再由浏览器检查响应许可。
因此,CORS 报错不代表服务端没有收到。即使脚本无法读取结果,修改数据的操作也可能发生。这也是不能只靠 CORS 防 CSRF 的原因。
不符合这类条件的请求,例如使用 application/json 或某些自定义头,通常会先预检。MDN CORS 指南列出了相应条件。
预检问规则,正式请求做业务
OPTIONS 表达的是:“这个来源想用 POST,并带这些请求头,可以吗?”
服务端用 Allow-Origin、Allow-Methods、Allow-Headers 等响应。它确认浏览器访问规则,不确认用户能不能下单。
标准预检通常不携带用户 Cookie。如果把 OPTIONS 也放进必须登录的拦截逻辑,就可能在正式请求前被 401 拦住。
可以让白名单来源的有效预检通过,但正式请求仍要认证和鉴权。正式错误响应也应在允许范围内带正确 CORS 头,否则页面读不到真正的错误,只看到跨域报错。

include 不是绕过 Cookie 规则的按钮
它允许 fetch 携带凭据,但 Cookie 域、路径不匹配,仍然不会发送。
真正跨站的 Cookie 可能需要 SameSite=None; Secure。第三方 Cookie 策略还可能继续限制它,不能认为配齐两个响应头就一定成功。
带凭据响应不能使用 Allow-Origin: *。应返回经过白名单验证的具体来源并允许凭据。按来源动态响应时,还要考虑 Vary: Origin,防止共享缓存混用响应。
直接回显任意客户端 Origin,也不是白名单,只是换了写法的全放行。

代理改变路径,不取消安全责任
开发代理让浏览器请求同源地址,再由服务端转发。生产也可以采用同源网关。
浏览器不再看到跨源请求,但后端鉴权、权限和数据检查仍然必须保留。
排查可以按顺序检查是否预检、预检响应、正式状态、Cookie 实际发送与响应许可。不要见到报错就不断加星号。
面试官继续追问
curl 成功,浏览器失败,说明接口坏了吗?
不一定。curl 不按浏览器的页面同源策略限制读取。它成功不能证明 CORS 配置正确。
no-cors 能解决吗?
通常不能满足读取 API 的需求。跨源响应会成为脚本无法正常读取的 opaque 响应,它不是关闭安全规则的开关。
OPTIONS 成功,POST 401,该改 CORS 吗?
先确认正式请求有没有带上有效身份、后端为何拒绝。预检许可与登录校验不同,也要确认 401 响应的 CORS 头正确。
面试速记卡
- 同源:协议、主机、端口相同,路径不参与。
- 预检:先询问来源、方法与头,再发正式请求。
- 凭据:include、响应许可和 Cookie 自身规则都要满足。
- 鉴权:CORS 通过不代表用户有权限。
- 排查:分开看预检、正式请求、凭据与响应读取。
