一、什么是跨域?
协议、域名、端口 三者有任意一个不一样 ,就是跨域。
浏览器出于安全考虑,会限制跨域请求,这就是同源策略(Same-Origin Policy)。
举例:
https://www.baidu.com
- 协议:
https - 域名:
www.baidu.com - 端口:443(默认省略)
只要一个不同,就是跨域:
http://baidu.com→ 协议不同https://map.baidu.com→ 子域名不同https://baidu.com:8080→ 端口不同
二、为什么要有跨域限制?
核心目的:防止 CSRF 攻击、窃取 Cookie、窃取用户信息 。
如果没有同源限制,恶意网站可以随便请求你的银行接口、拿你的登录态。
三、前端常见跨域解决方案
1. CORS(最常用、最标准)
Cross-Origin Resource Sharing,跨域资源共享。由后端在响应头里声明 "允许哪些域名跨域",浏览器遵守规则放行。
- 核心原理
跨域请求能发到后端,但浏览器会检查响应头:
- 有 CORS 头 → 给前端数据
- 没有 → 拦截,前端拿不到结果
后端在响应头里加允许跨域的字段,浏览器识别后放行。
关键响应头:
Access-Control-Allow-Origin: *或指定域名Access-Control-Allow-Methods: GET,POST,PUT...Access-Control-Allow-Headers: Content-Type...Access-Control-Allow-Credentials: true允许带 Cookie
特点:
- 简单请求直接跨域
- 复杂请求先发 OPTIONS 预检请求
2. JSONP(老方案,只支持 GET)
利用 <script> 标签不受跨域限制的特点。
流程:
- 前端定义一个全局函数
fn - 动态创建
<script src="http://xxx?callback=fn"> - 后端返回
fn(数据) - 浏览器执行 fn,拿到数据
缺点:只 GET、不安全、不支持 POST。
3. 代理服务器(开发最常用)
前端请求自己的服务器 → 服务器转发请求到目标跨域接口
服务器之间没有跨域限制。
常见:
- webpack devServer proxy
- vite proxy
- Nginx 反向代理
4. Nginx 反向代理(生产常用)
配置 Nginx,把接口路径转发到目标服务器,浏览器看起来是同域。
5. postMessage(iframe 跨域)
页面与内嵌 iframe 之间跨域通信。
6. WebSocket
不受同源策略限制。
7. document.domain(仅限同一主域名不同子域)
比如 a.xxx.com 和 b.xxx.com
设置 document.domain = 'xxx.com' 即可跨域。
四、面试高频问答
1. 什么是简单请求、复杂请求?
简单请求:
- 方法:GET/HEAD/POST
- 请求头只有:Accept、Accept-Language、Content-Language、Content-Type(仅 form-data、urlencoded、text/plain)
复杂请求:
- PUT/DELETE
- 自定义头
- Content-Type: application/json
会先发一次 OPTIONS 预检请求,确认允许跨域才发真实请求。
2. 跨域时为什么能发出去但浏览器拦截?
请求确实发到后端了,后端也返回了。
但浏览器检查响应头没有 CORS 字段,浏览器自己拦截,不给前端数据。
3. Cookie 跨域要注意什么?
- 前端:
withCredentials: true - 后端:
Access-Control-Allow-Credentials: true Allow-Origin不能为*,必须写具体域名
4. 最优跨域方案是什么?
- 开发环境:代理(proxy)
- 生产环境:CORS / Nginx 反向代理
五、一句话总结
跨域是浏览器同源策略 导致的限制;
解决核心是后端允许(CORS) 或 绕开浏览器(代理/JSONP) ;
现代项目首选 CORS + 代理。