6.4.4 同源策略:浏览器安全基础
一句话破题
同源策略是浏览器的默认安全机制:只有来自同一个"源"的脚本,才能读取对方的数据。它是 Web 安全的第一道防线。
核心价值
理解同源策略能让你:
- 明白为什么需要 CORS
- 理解前后端分离时的跨域问题
- 知道哪些操作会被浏览器阻止
什么是"同源"?
一个 URL 由协议、域名、端口组成。只有三者完全相同,才算"同源"。
| URL A | URL B | 是否同源 | 原因 |
|---|---|---|---|
https://example.com | https://example.com/page | ✅ 同源 | 路径不影响 |
https://example.com | http://example.com | ❌ 不同源 | 协议不同 |
https://example.com | https://api.example.com | ❌ 不同源 | 域名不同 |
https://example.com | https://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.com2. 代理
通过同源的服务端转发请求:
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 被阻止
原因:端口不同 = 不同源
解决:
- 后端配置 CORS 允许
localhost:3000 - 或使用 Next.js 的 API Routes 作为代理
