跨域访问问题(Cross-Origin Resource Sharing, CORS)是由浏览器的同源策略(Same-Origin Policy)引发的一种安全限制。当网页尝试从一个与自身"源"(协议、域名、端口号)不同的地址请求资源(如API数据、图片、脚本等)时,浏览器会阻止该请求,除非目标服务器明确允许这种跨域访问。
核心概念解析
-
同源策略(Same-Origin Policy)
- 定义:浏览器要求网页只能访问与自身"源"相同的资源。
- 同源判定 :协议(
http/https
)、域名(example.com
)、端口(:80
)三者完全一致。
例如:
https://a.com/index.html
→https://a.com/api
✅ 同源
https://a.com/index.html
→http://a.com/api
❌ 协议不同(HTTPS vs HTTP)
https://a.com/index.html
→https://b.com/api
❌ 域名不同
https://a.com:80/index.html
→https://a.com:8080/api
❌ 端口不同
-
跨域场景举例
- 前端部署在
https://web.com
,调用APIhttps://api.com/data
。 - 本地开发时
http://localhost:3000
访问本地APIhttp://localhost:8000
(端口不同)。 - 子域名不同:
https://shop.example.com
访问https://api.example.com
。
- 前端部署在
为什么需要跨域限制?
- 安全防护
防止恶意网站通过脚本窃取用户敏感数据(如Cookie、私有数据)。例如:- 用户登录了
bank.com
,若恶意网站evil.com
能随意读取bank.com
的数据,将导致账户被盗。
- 用户登录了
- 隔离攻击面
限制CSRF(跨站请求伪造)、XSS(跨站脚本攻击)等漏洞的影响范围。
如何解决跨域问题?
方案1:服务端配置CORS(主流方案)
服务端在响应头中添加允许跨域的声明:
http
Access-Control-Allow-Origin: https://web.com // 允许特定域名
Access-Control-Allow-Origin: * // 允许所有域名(慎用)
Access-Control-Allow-Methods: GET, POST, PUT // 允许的请求方法
Access-Control-Allow-Headers: Content-Type // 允许的请求头
流程:
- 浏览器发送预检请求(OPTIONS)询问服务器是否允许跨域。
- 服务器响应允许的规则。
- 浏览器确认后发送真实请求。
方案2:代理服务器(Proxy)
前端通过同源代理中转请求:
浏览器 → https://web.com/proxy?target_api=xxx → 代理请求 → https://api.com/data
常用于开发环境(如Webpack DevServer代理)或后端服务中转。
方案3:JSONP(过时方案,仅限GET请求)
利用 <script>
标签不受同源策略限制的特性:
html
<script src="https://api.com/data?callback=handleData"></script>
服务端返回:handleData({...})
,前端需提前定义 handleData
函数。
常见误区
- "Postman能请求成功,但浏览器报CORS错误"
→ 因为Postman不受同源策略限制,浏览器才会拦截。 - "前端代码修改请求头可以绕过CORS"
→ 浏览器会阻止前端修改敏感请求头(如Origin
),必须服务端授权。
总结
关键点 | 说明 |
---|---|
触发原因 | 浏览器同源策略的安全限制 |
本质 | 浏览器与服务端的协作机制(通过HTTP头协商) |
解决方案 | 服务端配置CORS、代理服务器、JSONP(历史方案) |
核心目标 | 在安全前提下实现合法跨域通信 |
⚠️ 注意:CORS是浏览器行为,服务端即使未配置CORS,接口本身仍可被非浏览器工具(如curl、Postman)正常调用。