关于同源策略和跨域请求
一、什么是同源策略?
同源策略(Same-Origin Policy)是浏览器实施的核心安全机制。它规定了同一来源的资源如何进行交互,同时限制了不同来源的资源之间的交互方式。一个"源"由以下三个要素组成:[协议] + [域名] + [端口]。即同源的判断标准:协议相同(http/https/ftp等),域名相同(包括完全匹配的子域名),端口相同(默认端口可省略),例如:
| 当前页面URL | 目标URL | 是否同源 | 原因说明 |
|---|---|---|---|
| https://shop.com/app | https://shop.com/cart | 是 | 完全相同 |
| https://shop.com | http://shop.com | 否 | 协议不同(HTTPS vs HTTP) |
| https://shop.com | https://api.shop.com | 否 | 子域名不同 |
| https://shop.com:443 | https://shop.com:8080 | 否 | 端口不同 |
二、为什么需要同源策略?
同源策略是现代Web安全的基石,主要解决两个核心安全问题:防止数据窃取和防止未授权操作
-
防止数据窃取例如:
用户浏览器行为:
登录银行网站 bank.com → 获取有效会话Cookie
打开恶意网站 evil.com
恶意网站代码:
// 尝试读取银行账户信息
const bankFrame = document.getElementById('bank-iframe').contentDocument;
const balance = bankFrame.querySelector('.balance').innerText;
alert('您的账户余额:${balance}'); -
防止未授权操作例如:
恶意网站代码:
// 伪造银行转账请求
fetch('https://bank.com/transfer', {
method: 'POST',
body: 'toAccount=hacker&amount=10000'
});
三、同源策略的限制范围
1.严格受限的操作
| 限制类型 | 示例说明 | 安全威胁 |
|---|---|---|
| DOM访问 | 读取/修改其他源的iframe内容 | 账户信息窃取 |
| AJAX/Fetch | 读取跨源API响应内容 | 数据盗窃 |
| Cookie访问 | 读取其他源的Cookie | 身份盗用 |
| Web存储 | 访问其他源的LocalStorage | 持久数据窃取 |
2.允许的跨源操作
为保持Web功能性,部分操作被允许:
- 嵌入资源:
<img>,<script>,<link>,<video>等 - 表单提交:可提交到不同源的URL(但无法读取响应)
- 窗口导航:
window.open()或链接可导航到不同源
四、跨域请求
1.概念
当页面向不同协议/域名/端口的目标发起请求时,即发生了跨域请求。
2.合理跨域场景
开发中,我们想在主页面设置一个天气预报的功能:我们需要向一个第三方开源的网站发送请求来获取接下来的天气数据,比如OpeaWeather提供的免费API,但我们并不希望在重新获取数据(比如换一个城市查询)时整个页面刷新,因此我们可以设置一个切换城市的按钮,触发点击事件时向OpeanWeather发送Ajax请求,仅仅更新整个页面的天气这一个组件,此时发送Ajax请求时就会触发跨域请求的问题。
3.突破限制的解决方案
方案1:CORS(跨域资源共享)- 官方标准
原理:服务器声明允许哪些外部域访问自己
服务端响应头示例
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://your-app.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Credentials: true
方案2:JSONP(历史解决方案)
原理:利用<script>标签不受同源策略限制的特点
点击查看代码
<script>
function handleResponse(data) {
console.log("收到数据:", data);
}
</script>
<script src="https://api.com/data?callback=handleResponse"></script>
局限性:仅支持GET请求,存在XSS风险
方案3:服务器代理
原理:通过同源服务器中转请求(同源策略是浏览器的机制)
浏览器(发送Ajax请求给服务器) → 由服务器去发送跨域请求 → 最后服务器返回请求内容给浏览器

浙公网安备 33010602011771号