网络相关 - 跨域解决方式

文章目录

    • 一、什么是"跨域"?
    • 二、为什么浏览器要限制跨域?
      • [1. 核心原因:安全防御](#1. 核心原因:安全防御)
      • [**2. 历史背景**](#2. 历史背景)
    • 三、哪些操作会触发跨域限制?
      • [1. 受同源策略限制的操作](#1. 受同源策略限制的操作)
      • [2. 不受限的跨域资源](#2. 不受限的跨域资源)
    • 四、跨域问题的技术本质
      • [1. 浏览器的双重验证](#1. 浏览器的双重验证)
      • [2. 常见错误场景](#2. 常见错误场景)
    • [五、为什么移动端/Postman 没有跨域问题?](#五、为什么移动端/Postman 没有跨域问题?)
    • 六、解决跨域的四种方式
      • [6.1 JSONP(仅限 GET 请求)](#6.1 JSONP(仅限 GET 请求))
      • [6.2 前端代理(开发环境常用)](#6.2 前端代理(开发环境常用))
      • [6.3 后端配置 CORS(生产环境推荐)](#6.3 后端配置 CORS(生产环境推荐))
      • [6.4 Nginx 反向代理(生产环境高效方案)](#6.4 Nginx 反向代理(生产环境高效方案))
      • [6.5 对比总结](#6.5 对比总结)

一、什么是"跨域"?

当浏览器向 不同源(Origin) 的服务器发起请求时,就会触发跨域限制。判断"同源"需同时满足以下三项:

  1. 协议相同(HTTP/HTTPS)
  2. 域名相同www.example.com
  3. 端口相同(80/443)

以下均为跨域示例

  • http://a.comhttps://a.com(协议不同)
  • https://a.comhttps://api.a.com(子域名不同)
  • https://a.com:80https://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. 浏览器的双重验证

当发起跨域请求时:

  1. 预检请求(Preflight)

    对复杂请求(如带自定义头的 POST),浏览器先发OPTIONS请求询问服务器是否允许跨域。

    bash 复制代码
    OPTIONS /data HTTP/1.1
    Origin: https://your-site.com
    Access-Control-Request-Method: POST
  2. 服务端响应 CORS 头

    服务器必须返回明确的许可头:

    http 复制代码
    Access-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 允许指定域名的跨域请求。
关键响应头

bash 复制代码
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 头。
配置示例

bash 复制代码
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 代理 生产环境 所有 否(运维配置)

👉点击进入 我的网站

相关推荐
liulilittle1 天前
Windows WSL部署Ubuntu子系统到其它磁盘上
linux·运维·服务器·网络·windows·ubuntu·wsl
天蓝色的鱼鱼1 天前
Vue开发必考:defineComponent与defineAsyncComponent,你真的掌握吗?
前端·vue.js
用户81274828151201 天前
aosp14分屏分割线区域部分深入剖析-framework实战干货
前端
三小河1 天前
内网环境下 Web 离线地图的实现方案与合规性探讨
前端
2501_941807261 天前
在迪拜智能机场场景中构建行李实时调度与高并发航班数据分析平台的工程设计实践经验分享
java·前端·数据库
一 乐1 天前
餐厅点餐|基于springboot + vue餐厅点餐系统(源码+数据库+文档)
java·前端·数据库·vue.js·spring boot·后端
易天ETU1 天前
2026年光模块市场分析与预见
大数据·运维·网络·人工智能·光模块·光通信
踢球的打工仔1 天前
typescript-var和let作用域
前端·javascript·typescript
手握风云-1 天前
JavaEE 进阶第八期:Spring MVC - Web开发的“交通枢纽”(二)
前端·spring·java-ee