同源策略那些事
字数 2163 2025-08-25 22:58:34

同源策略与跨域技术详解

同源策略基础

同源策略(Same Origin Policy)是浏览器最基本也是最核心的安全功能,它限制了来自不同源的"document"或脚本对当前"document"读取或设置某些属性。

判断是否同源

影响源的因素包括:

  • HOST:域名或IP地址
  • 子域名
  • 端口
  • 协议

文件所在域不重要,重要的是文件解析加载所在的域。

同源判断示例

URL 结果 原因
http://blog.twosmi1e.com/dir2/test.html success 同源
https://blog.twosmi1e.com/secure.html failure 不同协议
http://blog.twosmi1e.com:90/dir2/etc.html failure 不同端口
http://code.twosmi1e.com/dir/other.html failure 不同主机

跨域场景

常见的跨域业务场景包括:

  1. 前后端分离开发模式下,前后端域名不一致
  2. 本地开发时不同文件夹间的ajax请求
  3. 电商网站加载第三方快递物流信息
  4. 子站域名调用主站域名的用户资料接口

跨域解决方案

1. HTML标签跨域

<script>, ``, <iframe>, <link>等带src属性的标签都可以跨域加载资源,不受同源策略限制。

常见跨域标签:

<script src="..."></script>

<video src="..."></video>
<audio src="..."></audio>
<embed src="...">
<frame src="...">
<iframe src="..."></iframe>
<link rel="stylesheet" href="...">
<applet code="..."></applet>
<object data="..."></object>

CSS中@font-face也可以跨域:

@font-face {
    src: url("http://example.com/font.ttf");
}

2. document.domain

同一主域不同子域之间可以通过设置document.domain为相同的高级域名来实现同源。

// 父域和子域都设置
document.domain = "example.com";

3. window.name

利用window.name在页面跳转后仍保留的特性实现跨域通信。

实现步骤:

  1. 在a.com/index.html中嵌入iframe,src设为b.com/index.html
  2. b.com/index.html设置window.name后跳转到a.com/empty.html
  3. a.com/index.html通过iframe.contentWindow.name获取数据

4. window.postMessage

HTML5引入的API,安全地实现跨域通信。

// 发送消息
targetWindow.postMessage(message, targetOrigin);

// 接收消息
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) {
    if (event.origin !== "http://example.com") return;
    // 处理消息
}

5. location.hash

利用iframe的location.hash传值,通过中间页实现跨域通信。

6. Flash跨域

通过crossdomain.xml文件声明允许访问的域:

<?xml version="1.0"?>
<cross-domain-policy>
    <allow-access-from domain="*.example.com" />
</cross-domain-policy>

7. JSONP

利用<script>标签无跨域限制的特性,通过回调函数获取数据。

实现流程:

  1. 定义回调函数
function handleResponse(data) {
    console.log(data);
};
  1. 动态创建script标签
var script = document.createElement('script');
script.src = 'http://example.com/json?callback=handleResponse';
document.body.appendChild(script);
  1. 服务器返回
handleResponse({"name": "value"});

8. CORS (跨源资源共享)

现代浏览器支持的跨域解决方案,关键在于服务器配置。

简单请求

满足以下条件:

  • 方法:GET、HEAD、POST
  • 头信息限于:Accept、Accept-Language、Content-Language、Content-Type(值限于application/x-www-form-urlencoded、multipart/form-data、text/plain)

非简单请求

需要先发送OPTIONS预检请求。

HTTP头字段

  • Access-Control-Allow-Origin: 允许的域
  • Access-Control-Allow-Credentials: 是否允许带凭证
  • Access-Control-Expose-Headers: 允许访问的返回头
  • Access-Control-Max-Age: 预检请求缓存时间
  • Access-Control-Allow-Methods: 允许的方法
  • Access-Control-Allow-Headers: 允许的自定义头

安全相关问题

CORS漏洞

漏洞原理
服务器配置不当,Access-Control-Allow-Origin设置为*或直接取自请求头Origin字段,且Access-Control-Allow-Credentials设置为true。

攻击示例

<script>
function cors() {
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            alert(this.responseText);
        }
    };
    xhttp.open("GET", "https://target.com", true);
    xhttp.withCredentials = true;
    xhttp.send();
}
</script>

检测工具
CORScanner

JSONP劫持

原理
当网站使用JSONP方式跨域传递敏感信息且缺乏有效控制(对referer或token的检查)时,攻击者可构造恶意页面获取用户数据。

简单POC

<script> 
function jsonph(json){ 
    alert(JSON.stringify(json)) 
} 
</script>  
<script src="https://target.com?callback=jsonph"></script>

SOME (Same Origin Method Execution)

不同于XSS盗取cookie,SOME直接劫持cookie进行操作,与CSRF类似但执行脚本代码。

防御建议

  1. 严格设置Access-Control-Allow-Origin,避免使用*
  2. 对JSONP接口进行referer检查或添加token验证
  3. 敏感操作使用CSRF Token防护
  4. 避免在客户端存储敏感信息
  5. 对跨域请求进行严格的输入验证和输出编码

总结

同源策略是Web安全的基础,理解其原理和各种跨域技术对于现代Web开发至关重要。在实际应用中,应根据具体场景选择适当的跨域方案,同时注意潜在的安全风险,做好相应的防护措施。

同源策略与跨域技术详解 同源策略基础 同源策略(Same Origin Policy) 是浏览器最基本也是最核心的安全功能,它限制了来自不同源的"document"或脚本对当前"document"读取或设置某些属性。 判断是否同源 影响源的因素包括: HOST :域名或IP地址 子域名 端口 协议 文件所在域不重要,重要的是文件解析加载所在的域。 同源判断示例 : | URL | 结果 | 原因 | |------|------|------| | http://blog.twosmi1e.com/dir2/test.html | success | 同源 | | https://blog.twosmi1e.com/secure.html | failure | 不同协议 | | http://blog.twosmi1e.com:90/dir2/etc.html | failure | 不同端口 | | http://code.twosmi1e.com/dir/other.html | failure | 不同主机 | 跨域场景 常见的跨域业务场景包括: 前后端分离开发模式下,前后端域名不一致 本地开发时不同文件夹间的ajax请求 电商网站加载第三方快递物流信息 子站域名调用主站域名的用户资料接口 跨域解决方案 1. HTML标签跨域 <script> , ``, <iframe> , <link> 等带src属性的标签都可以跨域加载资源,不受同源策略限制。 常见跨域标签: CSS中 @font-face 也可以跨域: 2. document.domain 同一主域不同子域之间可以通过设置 document.domain 为相同的高级域名来实现同源。 3. window.name 利用 window.name 在页面跳转后仍保留的特性实现跨域通信。 实现步骤: 在a.com/index.html中嵌入iframe,src设为b.com/index.html b.com/index.html设置window.name后跳转到a.com/empty.html a.com/index.html通过iframe.contentWindow.name获取数据 4. window.postMessage HTML5引入的API,安全地实现跨域通信。 5. location.hash 利用iframe的location.hash传值,通过中间页实现跨域通信。 6. Flash跨域 通过crossdomain.xml文件声明允许访问的域: 7. JSONP 利用 <script> 标签无跨域限制的特性,通过回调函数获取数据。 实现流程: 定义回调函数 动态创建script标签 服务器返回 8. CORS (跨源资源共享) 现代浏览器支持的跨域解决方案,关键在于服务器配置。 简单请求 满足以下条件: 方法:GET、HEAD、POST 头信息限于:Accept、Accept-Language、Content-Language、Content-Type(值限于application/x-www-form-urlencoded、multipart/form-data、text/plain) 非简单请求 需要先发送OPTIONS预检请求。 HTTP头字段 Access-Control-Allow-Origin : 允许的域 Access-Control-Allow-Credentials : 是否允许带凭证 Access-Control-Expose-Headers : 允许访问的返回头 Access-Control-Max-Age : 预检请求缓存时间 Access-Control-Allow-Methods : 允许的方法 Access-Control-Allow-Headers : 允许的自定义头 安全相关问题 CORS漏洞 漏洞原理 : 服务器配置不当, Access-Control-Allow-Origin 设置为 * 或直接取自请求头Origin字段,且 Access-Control-Allow-Credentials 设置为true。 攻击示例 : 检测工具 : CORScanner JSONP劫持 原理 : 当网站使用JSONP方式跨域传递敏感信息且缺乏有效控制(对referer或token的检查)时,攻击者可构造恶意页面获取用户数据。 简单POC : SOME (Same Origin Method Execution) 不同于XSS盗取cookie,SOME直接劫持cookie进行操作,与CSRF类似但执行脚本代码。 防御建议 严格设置 Access-Control-Allow-Origin ,避免使用 * 对JSONP接口进行referer检查或添加token验证 敏感操作使用CSRF Token防护 避免在客户端存储敏感信息 对跨域请求进行严格的输入验证和输出编码 总结 同源策略是Web安全的基础,理解其原理和各种跨域技术对于现代Web开发至关重要。在实际应用中,应根据具体场景选择适当的跨域方案,同时注意潜在的安全风险,做好相应的防护措施。