前端面试必看:浏览器同源策略详解+跨域方案
本文专为前端面试打造,吃透同源策略定义、核心规则、安全意义、高频跨域方案,搭配代码示例+面试话术,发文、自用复盘两用,搞定90%同源策略面试题。
前言:同源策略到底有多重要?
同源策略是浏览器最核心的安全基石,也是前端面试必考题。不管是校招还是社招,面试官都会追问:什么是同源?为什么要有同源策略?常用跨域方式有哪些?原理是什么?
前端日常开发中,接口跨域、资源加载失败、本地调试报错,几乎都和同源策略相关。
一、什么是同源策略?
1. 同源的定义(面试必背)
同源:指两个URL的协议(protocol)、域名(host)、端口(port) 完全一致,只要有一项不同,就是不同源。
三要素判断:协议 + 域名 + 端口 → 三者全同=同源,缺一不同=跨域
2. 同源判断示例(一看就懂)
以 https://www.baidu.com:8080/index.html 为基准:
| 对比URL | 是否同源 | 原因 |
|---|---|---|
| www.baidu.com:8080/home.html | ✅ 同源 | 三要素完全一致 |
| www.baidu.com:8080/index.html | ❌ 跨域 | 协议不同(https vs http) |
| map.baidu.com:8080/index.html | ❌ 跨域 | 域名不同(www vs map) |
| www.baidu.com:9090/index.html | ❌ 跨域 | 端口不同(8080 vs 9090) |
⚠️ 小贴士:默认端口(http=80、https=443)不写时,端口判定为默认值,不一致仍跨域;IP和域名、主域和子域,均属于跨域。
3. 同源策略的核心作用
同源策略是浏览器自带的安全限制,禁止不同源的JS脚本读取、修改对方的资源,主要防范3大风险:
- CSRF攻击:防止恶意网站盗用用户Cookie、身份信息发起请求
- XSS窃取数据:阻止恶意脚本获取敏感页面数据
- 资源篡改:避免非法修改DOM、Cookie、LocalStorage等存储数据
二、同源策略限制的行为(面试高频)
浏览器并非限制所有跨域行为,而是针对敏感操作做限制,这些也是面试常考点:
❌ 受限制的跨域操作
- AJAX/Fetch 跨域请求(无法获取响应数据)
- 读取/修改跨域页面的Cookie、LocalStorage、SessionStorage
- 操作跨域页面的DOM节点、获取页面数据
- 获取跨域Canvas的像素数据
✅ 不受限制的跨域操作
这些资源加载不受同源策略约束,也是前端常用的兼容方式:
- 标签加载资源:<img>、<script>、<link>、<iframe>、<video>
- 表单提交(form表单action跨域可提交,但无法获取返回结果)
- 重定向跳转(window.location.href)
三、前端高频跨域解决方案(面试+实战双用)
开发中跨域是常态,面试官重点考察方案原理、适用场景、优缺点,以下是最常用的8种方案,按面试热度排序。
方案1:CORS(跨域资源共享,生产首选)
核心原理:服务端设置响应头,允许指定源访问资源,浏览器自动放行,是最规范的跨域方案。
服务端配置示例(Node/Express)
// 后端设置CORS响应头
app.all('*', (req, res, next) => {
// 允许所有源访问(生产建议指定具体域名)
res.header('Access-Control-Allow-Origin', '*');
// 允许请求头
res.header('Access-Control-Allow-Headers', 'Content-Type,Authorization');
// 允许请求方式
res.header('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE,OPTIONS');
// 允许携带Cookie
res.header('Access-Control-Allow-Credentials', true);
next();
});
前端适配(携带Cookie)
// Fetch请求
fetch('https://api.xxx.com/data', {
method: 'GET',
credentials: 'include' // 允许携带Cookie
});
// Axios请求
axios.get('https://api.xxx.com/data', {
withCredentials: true
});
优缺点
- ✅ 支持所有请求方式、携带Cookie、安全性高
- ✅ 生产环境标准方案,无需前端改代码
- ❌ 依赖后端配置,简单请求无感知,复杂请求会发预检OPTIONS
方案2:JSONP(仅支持GET,老式方案)
核心原理:利用<script>标签跨域加载资源不受限,后端返回函数调用,前端执行回调获取数据。
前端代码示例
// 定义回调函数
function getData(res) {
console.log('跨域数据:', res);
}
// 动态创建script标签发起请求
const script = document.createElement('script');
script.src = 'https://api.xxx.com/data?callback=getData';
document.body.appendChild(script);
优缺点
- ✅ 兼容低版本浏览器(IE)
- ❌ 仅支持GET请求,无法携带Cookie、安全性低
- ❌ 无错误捕获机制,现在极少使用
方案3:代理服务器(开发环境首选)
核心原理:前端请求本地代理服务器,由代理转发请求到目标接口,浏览器仅同源请求,无跨域问题。
Vue/React代理配置(vue.config.js)
module.exports = {
devServer: {
proxy: {
'/api': {
target: 'https://api.xxx.com', // 目标接口域名
changeOrigin: true, // 开启代理
pathRewrite: {
'^/api': ''
}
}
}
}
};
优缺点
- ✅ 开发环境零成本、支持所有请求方式、无感知跨域
- ❌ 仅适用于开发环境,生产需Nginx代理
方案4:Nginx反向代理(生产环境)
核心原理:Nginx统一接收前端请求,根据路径转发到不同服务,浏览器始终访问同源地址。
server {
listen 80;
server_name localhost;
# 接口代理
location /api {
proxy_pass https://api.xxx.com; # 转发到目标服务
proxy_set_header Host $host;
}
# 前端静态资源
location / {
root /dist;
index index.html;
}
}
其他常用方案(面试补充)
- postMessage:iframe跨页面通信,适用于父子iframe交互
- window.name:利用window.name存储跨域数据,兼容性好
- document.domain:主域相同、子域不同场景,设置主域即可同源
- WebSocket:WebSocket通信不受同源策略限制
四、跨域方案对比(面试快速选择)
| 方案 | 支持请求 | 适用场景 | 推荐度 |
|---|---|---|---|
| CORS | 所有请求 | 生产环境、正规项目 | ⭐⭐⭐⭐⭐ |
| 代理服务器 | 所有请求 | 本地开发调试 | ⭐⭐⭐⭐⭐ |
| Nginx代理 | 所有请求 | 生产环境部署 | ⭐⭐⭐⭐ |
| JSONP | 仅GET | 兼容老旧浏览器 | ⭐⭐ |
五、面试高频问答(直接背诵)
1. 什么是同源策略?为什么需要它?
同源策略是浏览器的安全限制,要求协议、域名、端口完全一致才允许交互;目的是防范CSRF、XSS攻击,保护用户Cookie和数据安全。
2. 常见的跨域解决方案有哪些?
主流方案:CORS、代理服务器、Nginx反向代理;老式方案:JSONP;iframe场景:postMessage、document.domain。
3. CORS的简单请求和复杂请求区别?
简单请求:GET/HEAD/POST,请求头仅简单字段,直接发起请求;复杂请求:非简单请求方式/请求头,会先发送OPTIONS预检请求,通过后才发正式请求。
4. 为什么JSONP能跨域?
因为<script>标签加载资源不受同源策略限制,通过回调函数获取后端返回的数据,仅支持GET请求。
5. 前端请求跨域携带Cookie需要注意什么?
后端开启Access-Control-Allow-Credentials:true,且Origin不能为*;前端设置withCredentials/credentials:include。
面试加分话术:生产环境优先用CORS,开发用代理服务器,跨域核心是绕开浏览器同源限制,同时保证接口安全。
文末小结:同源策略是浏览器安全底线,跨域本质是突破限制的合规方案。面试重点掌握同源三要素、CORS原理、代理配置,遇到同源策略相关问题稳拿高分。
💬 跨域踩过坑的同学欢迎评论区吐槽~觉得有用记得点赞+收藏+关注,持续更新前端面试硬核干货!