⚠️ Alpha内测版本警告:此为早期内部构建版本,尚不完整且可能存在错误,欢迎大家提Issue反馈问题或建议
Skip to content

6.4.4 同源策略:浏览器安全基础

一句话破题

同源策略是浏览器的默认安全机制:只有来自同一个"源"的脚本,才能读取对方的数据。它是 Web 安全的第一道防线。

核心价值

理解同源策略能让你:

  • 明白为什么需要 CORS
  • 理解前后端分离时的跨域问题
  • 知道哪些操作会被浏览器阻止

什么是"同源"?

一个 URL 由协议、域名、端口组成。只有三者完全相同,才算"同源"。

URL AURL B是否同源原因
https://example.comhttps://example.com/page✅ 同源路径不影响
https://example.comhttp://example.com❌ 不同源协议不同
https://example.comhttps://api.example.com❌ 不同源域名不同
https://example.comhttps://example.com:8080❌ 不同源端口不同

同源策略限制什么?

被限制的操作

javascript
// ❌ 不能读取跨域请求的响应
fetch('https://other-site.com/api')
  .then(res => res.json())  // 被阻止

// ❌ 不能读取跨域 iframe 的内容
const iframe = document.querySelector('iframe')
iframe.contentDocument  // 被阻止

// ❌ 不能读取跨域页面的 Cookie/Storage
localStorage.getItem('other-site-data')  // 只能读本站的

不被限制的操作

html
<!-- ✅ 可以加载跨域资源 -->
<img src="https://other-site.com/image.png" />
<script src="https://cdn.example.com/lib.js"></script>
<link href="https://fonts.googleapis.com/css" rel="stylesheet" />

<!-- ✅ 可以发送跨域请求(但不能读响应) -->
<form action="https://other-site.com/submit" method="POST">

绕过同源策略的合法方式

1. CORS(推荐)

服务端返回允许跨域的响应头:

http
Access-Control-Allow-Origin: https://your-site.com

2. 代理

通过同源的服务端转发请求:

typescript
// 前端请求同源 API
fetch('/api/proxy?url=https://other-site.com/data')

// 服务端代理转发
export async function GET(request: Request) {
  const url = new URL(request.url).searchParams.get('url')
  const res = await fetch(url!)
  return Response.json(await res.json())
}

3. JSONP(过时)

利用 <script> 标签不受同源限制的特性,现已不推荐使用。

避坑指南

开发时的常见困惑

问题:本地开发时 localhost:3000 调用 localhost:8000 的 API 被阻止

原因:端口不同 = 不同源

解决

  1. 后端配置 CORS 允许 localhost:3000
  2. 或使用 Next.js 的 API Routes 作为代理