一针见血!前端新手也能秒懂浏览器的同源策略
				
									
					
					
						|  | 
							freeflydom 2025年8月7日 17:28
								本文热度 1278 | 
					
				 
				想象一下:你写了一个网页 https://www.yoursite.com,想用 JavaScript 获取 https://api.othersite.com 的数据。代码看着没问题,但浏览器无情地抛出一个错误:跨域请求被阻止!这就是同源策略(Same-Origin Policy) 在守护安全大门。
一、什么是“源”?—— 你的网络身份证
浏览器的“源”由三块拼图组成:
- 协议 (Protocol): http://,https://,ftp://等
- 域名 (Host): www.example.com,api.service.org等
- 端口 (Port): :80(HTTP默认),:443(HTTPS默认),:8080等
只有这三者完全相同,才属于“同源”!
✅ 同源示例:
- https://shop.com/page1与- https://shop.com/page2(协议、域名、端口相同)
- http://localhost:8080/app与- http://localhost:8080/api(协议、域名、端口相同)
❌ 不同源示例:
- https://shop.comvs- http://shop.com(协议不同:HTTPS vs HTTP)
- https://shop.comvs- https://api.shop.com(域名不同:shop.com vs api.shop.com)
- https://shop.comvs- https://shop.com:8443(端口不同:443 vs 8443)
二、同源策略管什么?—— 浏览器的安全围栏
同源策略的核心目标是:防止恶意网站窃取你的数据或冒充你的身份! 它主要限制以下行为:
- 读取非同源 DOM: - 你的脚本 (https://your-site.com) 无法直接读取或修改https://bank.com登录页面的 DOM 结构(比如获取密码输入框的值)。想象一下,如果允许,恶意网站就能偷看你在银行网站的输入!
 
- 发送非同源 AJAX/Fetch 请求 (默认): - 你的脚本默认不能向 https://api.other-site.com发送XMLHttpRequest或fetch请求并读取响应内容。这是最常见引发跨域错误的地方。
 
- 读写非同源的 Cookie、LocalStorage 等: - 你网站 https://site-a.com设置的 Cookie,https://site-b.com的脚本无法读取或修改。防止恶意网站盗用你的登录状态。
 
三、安全围栏的“门缝”—— 允许的跨域加载
同源策略不是铁板一块!以下资源默认允许跨域加载(仅加载,JS 通常无法直接操作内容):
- <img src="...">图片
- <link rel="stylesheet" href="...">CSS 样式表
- <script src="...">脚本 (注意:加载的脚本运行在加载它的页面源下)
- <iframe src="...">内嵌框架 (内容可加载,但父页面 JS 访问其内容受同源限制)
为什么允许这些?因为它们是构建网页的基础资源(图片、样式、公共库),且默认情况下,加载这些资源不会直接暴露敏感数据给加载它们的页面脚本。
四、实战跨域问题:AJAX 请求场景
假设你的页面在 http://localhost:3000,想请求 http://localhost:4000/api/data:
fetch('http://localhost:4000/api/data')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('出错了:', error));
错误信息:
Access to fetch at 'http://localhost:4000/api/data' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
原因:
端口不同 (3000 vs 4000) → 不同源 → 浏览器阻止了响应数据的读取。
五、合法跨域方案:CORS 机制(核心解决方案)
CORS (Cross-Origin Resource Sharing) 是 W3C 标准,是解决跨域问题的官方方案。原理是服务器声明允许哪些源访问资源。
关键步骤:
- 浏览器发送请求: 你的脚本发起跨域请求(如 fetch)。
- 浏览器添加 Origin头: 自动带上当前页面的源 (e.g.,Origin: http://localhost:3000)。
- 服务器响应: 服务器检查 Origin。如果允许该源访问,则在响应中包含特定 HTTP 头:- Access-Control-Allow-Origin: http://localhost:3000(或- *表示允许任何源)
- 对于复杂请求(如带自定义头或非简单方法),还需 Access-Control-Allow-Methods,Access-Control-Allow-Headers等。
 
- 浏览器放行: 浏览器检查响应头。如果 Access-Control-Allow-Origin包含当前源,则允许脚本访问响应数据。
图解:

六、其他跨域方案(了解即可)
- JSONP (JSON with Padding): 利用 <script>标签不受同源策略限制的特性。只支持 GET 请求,逐渐被 CORS 取代。
- WebSocket: 协议本身支持跨域通信。
- 代理 (Proxy): 让你的服务器(同源)转发请求到目标服务器,再将结果返回给你的前端。常用在开发环境解决跨域。
- document.domain(降域): 仅适用于主域相同、子域不同的场景(如- a.example.com和- b.example.com),且需要双方页面都设置- document.domain = 'example.com'。限制多,不推荐。
转自https://juejin.cn/post/7533457149332176934
该文章在 2025/8/7 17:28:52 编辑过