1. 什么是同源策略?
同源策略 是Netscape
提出的一个安全策略
,它是浏览器最核心也是最基本的安全机制,用于限制不同源的网页脚本(如 JavaScript)之间的交互。目的是防止恶意网站通过脚本窃取用户数据或进行未授权的操作。浏览器在执行脚本的时候,都会检查这个脚本属于哪个页面,即检查是否同源,只有同源的脚本才会被执行;而非同源的脚本在请求数据的时候,浏览器会报一个异常,提示拒绝访问。
2. 如何定义“同源”?
两个 URL 的以下三部分完全一致时,视为同源:
-
协议(Protocol):如
http
vshttps
-
域名(Host):如
example.com
vssub.example.com
-
端口(Port):如
:80
(默认) vs:8080
image.png
URL1 | URL2 | 是否同源 | 原因 |
---|---|---|---|
http://a.com/index.html |
http://a.com/api |
是 | 协议、域名、端口一致 |
https://a.com |
http://a.com |
否 | 协议不同(HTTP vs HTTPS) |
http://a.com:80 |
http://a.com:8080 |
否 | 端口不同 |
http://a.com |
http://b.com |
否 | 域名不同 |
示例2:
http://localhost:8080/index.html
和 http://127.0.0.1:8080/index.html
不同源 。同源策略规定,只有协议、域名、端口三者都相同才属于同源 。虽然 localhost
在大多数系统中通过 hosts
文件映射到 127.0.0.1
,但从浏览器同源策略的判断标准来看:
-
http://localhost:8080/index.html
中,域名是localhost
。 -
http://127.0.0.1:8080/index.html
中,域名是127.0.0.1
。
所以:二者域名不同,不满足同源策略中 “同源” 的要求,所以它们不是同源的。
3. 同源策略的限制范围
同源策略限制的情况:
1、Cookie、LocalStorage 和 IndexDB 无法读取
2、DOM 和 JS对象无法获得
3、AJAX 请求不能发送
注意:对于像 img、iframe、script 等标签的 src 属性是特例,它们是可以访问非同源网站的资源的
同源策略主要限制以下操作:
3.1 DOM 访问限制
-
跨域 iframe 访问:
父页面无法通过 JavaScript 访问不同源子页面的 DOM。// 父页面尝试访问子页面 DOM(不同源时会报错) const iframe = document.getElementById('my-iframe'); const childDoc = iframe.contentDocument; // 报错:Blocked by Same-Origin Policy
3.2 网络请求限制
-
AJAX/Fetch 跨域请求:
默认禁止通过XMLHttpRequest
或Fetch API
发送跨域请求。fetch('https://api.other.com/data') // 不同源 .then(response => response.json()) .catch(error => console.error('被浏览器拦截'));
3.3 数据存储隔离
-
Cookie、LocalStorage、SessionStorage、IndexDB:
不同源的页面无法互相访问本地存储数据。// 在 https://a.com 的页面中 document.cookie = 'name=John'; // 在 https://b.com 的页面中无法读取该 Cookie
4. 同源策略的例外情况
虽然同源策略限制严格,但以下场景允许跨域:
4.1 跨域资源加载
-
部分标签允许跨域加载资源:
<img>
、<video>
、<iframe>
、<script>
、<link>
、 等标签可加载跨域资源,但 JavaScript 无法直接读取内容。<!-- 允许加载跨域图片 --> <img src="https://other.com/image.jpg"> <!-- 允许加载跨域脚本(JSONP 原理) --> <script src="https://api.other.com/data?callback=handleData"></script>
4.2 CORS(跨源资源共享)
-
服务端显式授权:
若服务器返回Access-Control-Allow-Origin
头,浏览器允许跨域请求。Access-Control-Allow-Origin: https://your-site.com # 允许指定源 Access-Control-Allow-Origin: * # 允许所有源(慎用)
4.3 其他豁免场景
-
表单提交:
HTML 表单(<form>
)允许提交到不同源,但无法读取响应结果。 -
WebSocket:
WebSocket 不受同源策略限制,但需服务端支持。
5. 同源策略的实际影响与解决方案
5.1 常见问题场景
-
前端调用第三方 API:
若未配置 CORS,浏览器会拦截响应。 -
微前端架构:
子应用间跨域通信需通过postMessage
或代理解决。
5.2 主流解决方案
方案 | 原理 | 适用场景 |
---|---|---|
CORS | 服务端设置响应头声明允许的源 | 生产环境主流方案 |
JSONP | 利用 <script> 标签跨域加载脚本,通过回调函数接收数据
|
仅支持 GET,旧项目兼容 |
代理服务器 | 前端请求同源代理,由代理转发至目标服务器 | 无法修改服务端配置时 |
postMessage | 跨窗口通信(如 iframe、新标签页)传递数据 | 跨域页面间可控通信 |
WebSocket | 使用 WebSocket 协议绕过同源策略 | 实时双向通信场景 |
6. 绕过同源策略的风险
尽管存在多种跨域方案,但需注意:
-
CORS 配置不当:
滥用Access-Control-Allow-Origin: *
可能导致 CSRF 攻击。 -
JSONP 安全性:
若第三方脚本不可信,可能注入恶意代码。 -
代理服务器性能:
频繁请求可能增加服务器负载。
7. 总结
同源策略是浏览器安全的基石,通过限制跨域交互保护用户隐私。开发者需根据场景选择合法、安全的跨域方案(如 CORS 或代理),避免因配置不当引发安全漏洞。理解其原理与限制,是构建健壮 Web 应用的关键。