同源策略详解
同源是指协议、域名和端口三者完全相同。只要其中任意一项不同,即视为跨源(跨域),浏览器将触发同源策略限制。
源的组成格式为:协议://域名:端口。其中,HTTP默认端口为80,HTTPS默认端口为443,若省略则使用默认端口。
以基准地址 http://a.com:80/index.html 为例,具体判断如下:
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
同源策略的核心目的
同源策略是浏览器的安全机制,而非服务器限制。其核心目的是防止恶意网站读取其他网站的敏感数据,如Cookie、LocalStorage、DOM结构及接口返回数据。
例如,用户登录银行网站后若访问钓鱼网站,若无同源策略保护,钓鱼网站的JavaScript可能读取银行页面的Cookie并冒充用户进行操作。因此,A页面的JavaScript默认无法读取B源的资源。虽然页面可以发起资源加载请求,但浏览器会拦截响应数据,导致JS无法获取。
同源策略限制的行为
1. 禁止JS读取跨源资源的响应
最常见的场景是AJAX或Fetch跨域请求。请求可以正常发送,服务器也能接收并返回结果,但浏览器会拦截响应体,导致JS无法获取数据,控制台通常报CORS policy错误。
2. 不能访问跨源页面的DOM对象
当通过iframe嵌入其他源的页面时,父页面的JavaScript无法读取iframe内部的DOM或window变量。
// 跨源iframe,会报错
document.getElementById('myIframe').contentDocument
3. 不能读写跨源的存储
Cookie、LocalStorage、SessionStorage和IndexedDB均遵循同源隔离原则,JavaScript无法读取其他源的存储数据。
不受同源策略限制的资源加载
以下标签可以加载跨源资源,浏览器不会拦截资源本身的加载,但JavaScript无法直接获取资源内容:
<img src="跨域图片"><link href="跨域css"><script src="跨域js"><video><iframe>(可以展示页面,但JS不能直接通信)
这也是为什么图片、静态CDN资源可以直接跨域加载,而fetch或axios请求接口却受到限制的原因。
跨域解决方案
CORS(跨域资源共享)
CORS是目前主流的跨域解决方案,由后端配置响应头,浏览器进行校验放行,现代浏览器均支持。
服务器需返回以下响应头:
Access-Control-Allow-Origin: https://允许的域名
Access-Control-Allow-Methods: GET,POST
Access-Control-Allow-Headers: Content-Type
CORS本质上是服务端声明允许哪些源访问,由浏览器执行校验逻辑。
代理服务器
由于同源策略仅存在于浏览器端,服务器之间的通信没有此限制。可通过以下方式解决:
前端请求同域的后端代理接口;
代理服务器转发请求到目标接口,获取数据后返回给前端。
postMessage
适用于父页面与跨域iframe之间的通信,不受同源限制。
// 父页面发送
iframe.contentWindow.postMessage('消息','*')
// iframe监听
window.addEventListener('message',(e)=>{})
注意:使用时务必校验消息来源origin,以防恶意网站发送虚假消息。
常见误区澄清
误区一:跨域是浏览器阻止发送请求
真相:请求会正常到达服务器,浏览器只是阻止JavaScript读取响应内容。
误区二:同源策略是服务器的安全策略
真相:这是浏览器的安全策略,服务器本身没有同源限制。
误区三:端口不参与同源判断
真相:协议、域名、端口三者缺一不可,任何一项不同即为跨源。
误区四:CORS可以前端绕过
真相:CORS校验逻辑在浏览器端,前端无法绕过;修改前端Header无效,必须由后端配置。
#浏览器同源策略

