← 返回题目列表

什么是同源策略?跨域问题怎么解决?

高频 中等 第 5 / 32 题 更新于 2026/07/28
HTTP同源策略跨域CORS

简化版

同源策略是浏览器的安全机制:只有协议、域名、端口都相同才算「同源」,非同源的脚本不能随意读取对方的资源(防止恶意网站盗取你在别的网站的数据)。跨域就是被同源策略拦下的请求。主流解决方案是 CORS——服务端返回 Access-Control-Allow-Origin 等响应头,明确「允许哪些源访问我」。

详细版

同源的定义:三者全部相同才同源——

  • 协议(http / https)
  • 域名(a.com / b.com)
  • 端口(80 / 8080)
以 https://www.a.com:443 为基准:
https://www.a.com/api      ✅ 同源
http://www.a.com           ❌ 协议不同
https://api.a.com          ❌ 域名不同(子域名也算跨域)
https://www.a.com:8080     ❌ 端口不同

同源策略限制什么:主要限制 JS 发起的跨域读取——不能读跨域的 Cookie/localStorage、不能读跨域 AJAX 的响应、不能操作跨域 iframe 的 DOM。(注意:<img><script><link> 这类标签加载跨域资源是允许的。)

常见解决方案

  • CORS(主流):服务端设响应头 Access-Control-Allow-Origin 声明允许的源;
  • JSONP(旧):利用 <script> 标签能跨域加载的特性,只支持 GET
  • 代理:让同源的后端/Nginx 去转发请求(浏览器只和同源的服务器打交道,服务器之间没有同源限制);
  • postMessage:跨窗口/iframe 通信。

完整版教学

一、为什么要有同源策略

设想没有同源策略:你登录了银行 bank.com(浏览器存了你的 Cookie),然后不小心打开了恶意网站 evil.comevil.com 的脚本就能偷偷向 bank.com 发请求(浏览器会自动带上你的 Cookie)并读取响应——你的账户信息、余额就被它拿走了。

同源策略就是浏览器给不同网站之间砌的一道墙evil.com 的脚本不能读取 bank.com 的响应数据。这是浏览器最基础的安全防线,保护用户在一个网站的登录态不被别的网站盗用。

二、注意:请求「发出去了」和「能不能读响应」是两回事

一个高频的理解误区:跨域请求其实发出去了、服务器也可能处理了,只是浏览器拦截了响应、不让 JS 读取

所以跨域限制是浏览器行为——它保护的是「不让恶意脚本读到跨域响应」,而不是「不让请求到达服务器」。这也解释了两件事:

  • 为什么用 curl、Postman、或服务器之间调用没有跨域问题(它们不是浏览器,没有同源策略);
  • 为什么 CORS 是服务端配置的——由被访问的服务器说「我允许这个源读我的响应」,浏览器才放行。

三、CORS:简单请求与预检请求

CORS 是 W3C 标准的跨域方案,分两种情况:

简单请求(满足特定条件:方法是 GET/POST/HEAD、Content-Type 是几种简单类型等):浏览器直接发,请求带上 Origin 头,服务器响应带 Access-Control-Allow-Origin,匹配就放行。

预检请求(Preflight):如果是 PUT/DELETE、或自定义头、或 application/json 等「复杂请求」,浏览器会先自动发一个 OPTIONS 请求问服务器「我接下来要发的这个请求,你允许吗」:

OPTIONS /api  (预检)
  Origin: https://www.a.com
  Access-Control-Request-Method: PUT
服务器响应:
  Access-Control-Allow-Origin: https://www.a.com
  Access-Control-Allow-Methods: PUT, POST, GET
  Access-Control-Allow-Headers: Content-Type

预检通过后,浏览器才发真正的请求。所以调试跨域时看到一个多出来的 OPTIONS 请求,就是预检。

四、几种方案的取舍

  • CORS:最标准、最推荐,支持所有方法,需服务端配合设响应头。
  • JSONP:老技术,利用 <script> 不受同源限制的特性,但只能 GET、有安全风险(等于执行对方返回的脚本),基本被 CORS 取代。
  • Nginx/后端代理:前端请求同源的代理,由代理转发到目标服务器。因为「同源限制只在浏览器」,服务器转发不受限。开发环境(webpack devServer proxy)和生产 Nginx 反代都常用。
  • postMessage:用于页面和 iframe / 新窗口之间安全地跨源通信。

五、常见误区

  • ❌ 以为跨域请求根本没发出去——请求通常发到了服务器,是浏览器拦了响应不给 JS 读。
  • ❌ 以为跨域是服务器拦的——是浏览器的同源策略;curl/后端互调没有跨域。
  • ❌ 以为 CORS 是前端配置——是服务端设响应头声明允许的源。
  • ❌ 忘了子域名/端口/协议不同也算跨域——三者必须全同才同源。

六、常见误区与追问

考点正确口径
同源协议、域名、端口都相同
同源策略浏览器限制脚本读取跨源响应
CORS服务器通过响应头授权指定跨源访问
预检复杂请求先发 OPTIONS 确认权限
Access-Control-Allow-Origin: https://a.com
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Credentials: true

跨域常见误会是“请求没发出去”:很多时候请求发了,只是浏览器不让 JS 读响应。

  • 误区:跨域是服务器拒绝请求。 同源策略主要由浏览器执行,服务器可能已返回响应,但浏览器拦截读取。
  • 误区:CORS 只要前端配置就能解决。 CORS 授权头必须由被请求的服务器返回,前端不能单方面放开。
  • 误区:Access-Control-Allow-Origin: * 可以和凭证一起用。 带 Cookie 等凭证时不能使用通配符,必须指定明确 Origin。
  • 追问:简单请求和预检请求区别是什么? 复杂方法、自定义头或特殊 Content-Type 会触发 OPTIONS 预检。
  • 追问:JSONP 为什么能跨域? 它利用 script 标签不受同源限制,但只支持 GET,安全和能力都有限。
  • 追问:反向代理为什么能解决跨域? 浏览器访问同源代理,再由代理向目标服务请求,浏览器视角不跨源。

七、加强记忆

同源 = 协议 + 域名 + 端口全相同,同源策略是浏览器安全机制,防止恶意网站读取你在其他网站的数据。跨域请求其实发到了服务器,只是浏览器拦了响应。解决靠 CORS(服务端设 Access-Control-Allow-Origin,复杂请求先发 OPTIONS 预检)为主,另有 JSONP(仅 GET)、代理(服务器转发不受同源限制)、postMessage。