前端跨域全解析:从 CORS 到 postMessage,再到 WebSocket

小白友好版,跨域不再迷路


1️⃣ 什么是跨域?

跨域,简单理解就是:

"浏览器:哎呀,这请求要跑到别人家去拿数据,我敢不敢让它去呢?"

严格说法:当浏览器从一个源(Origin)请求另一个源(Origin)的资源时,如果两者不一样,就触发同源策略(Same-Origin Policy),这就是跨域。

源(Origin)组成:

复制代码
源 = 协议(Protocol) + 域名(Host) + 端口(Port)

三者任意一项不同,就算跨域。

为什么有同源策略?

  • 防止 CSRF(跨站请求伪造)
  • 防止 XSS(跨站脚本攻击)
  • 防止隐私泄露(Cookie、账户信息)

举个例子:

bash 复制代码
http://example.com:80/page1.html  →  http://api.example.com:80/data

域名不同 → 跨域


2️⃣ CORS(跨域资源共享)

CORS 就像浏览器和服务器的"通行证",谁允许你进,谁说了算。

复制代码
浏览器:我想拿数据!
服务器:你是安全的,我允许你。
浏览器:好,我拿走数据!

2.1 两种 CORS 请求

🔹 简单请求(Simple Request)

条件(全部满足):

  1. 方法:GET / POST / HEAD
  2. 请求头:只能是浏览器安全集合
  3. 请求体:安全格式(纯文本/表单)
javascript 复制代码
// 简单请求示例
fetch('https://api.example.com/data', {
  method: 'GET',
})
  .then(res => res.json())
  .then(data => console.log(data));

服务器只需允许跨域即可:

makefile 复制代码
Access-Control-Allow-Origin: *

🔹 预检请求(Preflight Request)

触发条件:

  • 方法不是 GET/POST/HEAD
  • 自定义请求头(如 X-Token
  • Content-Type 非简单类型

流程示意:

复制代码
浏览器:我想PUT数据,可以吗?(OPTIONS预检)
服务器:可以,你的来源、方法、头都允许
浏览器:好,发真正请求

代码示例:

javascript 复制代码
fetch('https://api.example.com/data', {
  method: 'PUT',
  headers: {
    'Content-Type': 'application/json',
    'X-Token': '123456'
  },
  body: JSON.stringify({ name: '跨域小白' })
})
.then(res => res.json())
.then(data => console.log(data));

面试小技巧:能区分"简单请求 vs 预检请求",CORS 面试题轻松过。


3️⃣ JSONP

JSONP 是老派跨域方式,利用 <script> 标签天生跨域的特性。

xml 复制代码
<script>
  function handleData(data) {
    console.log('拿到跨域数据啦!', data);
  }
</script>
<script src="https://api.example.com/data?callback=handleData"></script>

优点 :兼容老浏览器、实现简单
缺点:只能 GET、XSS 风险、错误处理麻烦

现代项目基本不用 JSONP,直接 CORS + Fetch 就好。


4️⃣ postMessage

当你和不同源的 iframe/窗口要聊聊时,postMessage 就像安全的对讲机。

xml 复制代码
<!-- 父页面 -->
<iframe id="child" src="https://other.com"></iframe>
<script>
  const iframe = document.getElementById('child');
  iframe.contentWindow.postMessage({ msg: 'Hi小伙伴' }, 'https://other.com');

  window.addEventListener('message', (event) => {
    if(event.origin !== 'https://other.com') return; // 安全检查
    console.log('收到子页面消息:', event.data);
  });
</script>

记住:安全第一,一定要检查 event.origin


5️⃣ WebSocket

WebSocket 就是"前端的即时聊天神器",浏览器和服务器可以随时互发消息。

ini 复制代码
const ws = new WebSocket('wss://example.com/socket');

ws.onopen = () => ws.send('hello server!');

ws.onmessage = (msg) => console.log('收到服务器消息:', msg.data);

ws.onclose = () => console.log('连接关闭');

特点:

  • 全双工
  • 单连接
  • 跨域天然支持

6️⃣ 跨域常见应用场景

场景 示例 解决方案 代码示例
前端调用后端 API 开发 localhost → 远端 API CORS / 反向代理 fetch('https://api.example.com')
第三方接口 高德地图、支付 CORS / JSONP fetch('https://maps.com/api')
跨域 iframe 通信 支付 iframe postMessage iframe.contentWindow.postMessage(...)
多窗口/标签页 登录状态同步 postMessage + window.open window.opener.postMessage(...)
Web Worker 跨域 Worker 加载脚本 postMessage + CORS worker.postMessage(...)
静态资源跨域 CDN JS/CSS/图片 允许跨域 <script src="https://cdn.com/lib.js"></script>

7️⃣ 面试问答专栏:跨域篇

1️⃣ 面试官问:什么是跨域?

回答示例

"跨域就是浏览器发现你要去访问别人家的资源,它会先问一句:我敢不敢让它去?

严格来说,就是源(协议 + 域名 + 端口)不同,就触发同源策略。"


2️⃣ 面试官问:什么是 CORS?

回答示例

"CORS 就是浏览器和服务器的通行证,服务器在响应头声明允许的源、方法、头,浏览器通过才交数据给前端。

简单请求直接发,复杂请求会先发 OPTIONS 预检。"

代码示例:

ini 复制代码
fetch('https://api.example.com/data')
  .then(res => res.json())
  .then(data => console.log(data));

3️⃣ 面试官问:JSONP 和 CORS 有什么区别?

回答示例

"JSONP 是老派方案,靠 <script> 标签跨域,只能 GET,有 XSS 风险。

CORS 是现代方案,更安全灵活,支持 POST/PUT/DELETE。"


4️⃣ 面试官问:postMessage 是什么?

回答示例

"父页面和 iframe 或者窗口与 Worker 需要互相通信时,用 postMessage 传消息。安全重点是检查 event.origin。"

代码示例:

css 复制代码
iframe.contentWindow.postMessage({ msg: 'hello' }, 'https://other.com');

5️⃣ 面试官问:WebSocket 跨域吗?

回答示例

"WebSocket 建立的是 TCP 长连接,一旦连接建立就天然跨域,可以双向通信。"


8️⃣ 总结

跨域知识点其实就像"安检关卡",理解它,你就能安全访问资源,而且面试题轻松拿分。

技术 适用场景 优点 注意点
CORS 前后端接口跨域 简单灵活 后端需支持
JSONP 老 GET 请求 兼容老浏览器 只能 GET、有 XSS 风险
postMessage iframe/窗口/Worker 通信 安全灵活 检查 origin
WebSocket 实时通信 高效全双工 服务端支持

小结:

  • CORS → 现代前端首选
  • JSONP → 老项目遗留
  • postMessage → 窗口/iframe/Worker 通信
  • WebSocket → 实时双向通信

跨域学会了,你就是前端安全小能手!


相关推荐
irving同学4623811 分钟前
TypeORM 列装饰器完整总结
前端·后端·nestjs
彭于晏爱编程14 分钟前
你真的了解 Map、Set 嘛
前端
崔璨18 分钟前
详解Vue3的响应式系统
前端·vue.js
摸鱼的鱼lv18 分钟前
🔥 Vue.js组件通信全攻略:从父子传值到全局状态管理,一篇搞定所有场景!🚀
前端·vue.js
IT_陈寒29 分钟前
Java性能优化:10个让你的Spring Boot应用提速300%的隐藏技巧
前端·人工智能·后端
whysqwhw1 小时前
Hippy 跨平台框架扩展原生自定义组件的完整实现方案对比
前端
dasseinzumtode1 小时前
nestJS 使用ExcelJS 实现数据的excel导出功能
前端·后端·node.js
子兮曰1 小时前
🔥C盘告急!WSL磁盘暴增?三招秒清20GB+空间
前端·windows·docker
Jinuss1 小时前
Vue3源码reactivity响应式篇之EffectScope
前端·vue3
stoneship1 小时前
网页截图API-Npm工具包分享
前端