主题
跨域解决方式
更新: 11/20/2025字数: 0 字 时长: 0 分钟
一、什么是"跨域"?
当浏览器向 不同源(Origin) 的服务器发起请求时,就会触发跨域限制。判断"同源"需同时满足以下三项:
- 协议相同(HTTP/HTTPS)
- 域名相同(www.example.com)
- 端口相同(80/443)
❌ 以下均为跨域示例:
http://a.com→https://a.com(协议不同)https://a.com→https://api.a.com(子域名不同)https://a.com:80→https://a.com:8080(端口不同)
二、为什么浏览器要限制跨域?
1. 核心原因:安全防御
同源策略是为了防止恶意网站:
- 窃取用户数据
例:攻击者在页面嵌入脚本,偷偷访问用户的银行网站(假设用户已登录)。 - CSRF 攻击
利用用户 Cookie 伪造请求(如转账操作)。
2. 历史背景
- 早期 Web 没有同源策略,导致 XSS/CSRF 攻击泛滥
- 1995 年由 Netscape 浏览器首次引入,现成所有浏览器的标准
三、哪些操作会触发跨域限制?
1. 受同源策略限制的操作
| 操作类型 | 示例 | 是否跨域限制 |
|---|---|---|
| AJAX 请求/Fetch 请求 | fetch('https://api.com/data') | ✅ 受限 |
| Web 字体 | @font-face加载外部字体 | ✅ 受限 |
| Cookie/LocalStorage | 读取其他域的存储 | ✅ 受限 |
| drawImage() | 绘制其他域的图片 | ✅ 受限 |
| WebGL 贴图 | 加载其他域的 3D 模型 | ✅ 受限 |
2. 不受限的跨域资源
| 资源类型 | 原因 |
|---|---|
<img>/<script>/<link> | 历史遗留,但要求服务端不返回敏感数据 |
| 跨域 CSS | 需确保Content-Type: text/css |
四、跨域问题的技术本质
1. 浏览器的双重验证
当发起跨域请求时:
预检请求(Preflight)
对复杂请求(如带自定义头的 POST),浏览器先发OPTIONS请求询问服务器是否允许跨域。httpOPTIONS /data HTTP/1.1 Origin: https://your-site.com Access-Control-Request-Method: POST服务端响应 CORS 头
服务器必须返回明确的许可头:httpAccess-Control-Allow-Origin: https://your-site.com Access-Control-Allow-Methods: POST, GET
2. 常见错误场景
- 后端未配置 CORS 头:返回数据但被浏览器拦截
- 证书不匹配:HTTPS 页面请求 HTTP 接口
- 复杂请求未处理预检:如带
Authorization头的 API
五、为什么移动端/Postman 没有跨域问题?
- 浏览器是唯一执行者
同源策略是浏览器行为,Postman/cURL/手机 App 直接发送 HTTP 请求,不受限制。 - Native App 无同源策略
安卓/iOS 应用可自由请求任意 API(但需自行处理安全问题)。
六、解决跨域的四种方式
6.1 JSONP(仅限 GET 请求)
原理:利用 <script> 标签不受同源策略限制的特性,通过动态创建脚本实现跨域请求。
特点:
- 仅支持 GET 请求。
- 需要服务端配合返回回调函数包裹的数据(如
callback(data))。
示例代码:
javascript
function jsonp(url, callbackName) {
const script = document.createElement("script");
script.src = `${url}?callback=${callbackName}`;
document.body.appendChild(script);
window[callbackName] = (data) => {
console.log(data);
document.body.removeChild(script);
};
}
jsonp("http://api.example.com/data", "handleData");适用场景:老旧浏览器兼容、简单数据获取。
6.2 前端代理(开发环境常用)
原理:在开发环境中,前端服务器(如 Vite/Webpack)代理请求到后端,绕过浏览器同源限制。
特点:
- 仅用于开发环境。
- 无需后端配合,前端配置即可。
配置示例(Vite):
js
// vite.config.js
export default {
server: {
proxy: {
"/api": {
target: "http://api.example.com",
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, "")
}
}
}
};适用场景:本地开发调试。
6.3 后端配置 CORS(生产环境推荐)
原理:服务端通过设置响应头 Access-Control-Allow-Origin 允许指定域名的跨域请求。
关键响应头:
http
Access-Control-Allow-Origin: * // 允许所有域名(或指定域名)
Access-Control-Allow-Methods: GET,POST,PUT // 允许的请求方法
Access-Control-Allow-Headers: Content-Type // 允许的请求头
Access-Control-Allow-Credentials: true // 允许携带Cookie(需前端配合)后端示例(Node.js):
js
res.setHeader("Access-Control-Allow-Origin", "https://your-frontend.com");
res.setHeader("Access-Control-Allow-Methods", "GET,POST");适用场景:生产环境跨域请求。
6.4 Nginx 反向代理(生产环境高效方案)
原理:通过 Nginx 配置反向代理,将跨域请求转发到目标服务器,并添加 CORS 头。
配置示例:
nginx
server {
listen 80;
server_name your-frontend.com;
location /api {
proxy_pass http://api.example.com;
add_header 'Access-Control-Allow-Origin' 'https://your-frontend.com';
add_header 'Access-Control-Allow-Methods' 'GET,POST';
add_header 'Access-Control-Allow-Headers' 'Content-Type';
}
}优势:
- 高性能,无需修改后端代码。
- 可统一管理跨域策略。
适用场景:生产环境多服务跨域。
6.5 对比总结
| 方案 | 适用场景 | 请求类型 | 是否需要后端配合 | 安全性 |
|---|---|---|---|---|
| JSONP | 老旧项目兼容 | GET | 是 | 低 |
| 前端代理 | 开发环境 | 所有 | 否 | 中 |
| 后端 CORS | 生产环境 | 所有 | 是 | 高 |
| Nginx 代理 | 生产环境 | 所有 | 否(运维配置) | 高 |