【学习记录】浏览器的同源策略

192 阅读4分钟

同源策略

同源策略是浏览器的一种安全机制,用于限制不同源(Origin)之间的交互。它是浏览器安全模型的核心部分,旨在防止恶意网站窃取用户数据或执行未经授权的操作。

1. 什么是同源?

同源是指两个 URL 的协议(Protocol)、域名(Domain)和端口(Port)完全相同。如果其中任何一个不同,则被认为是不同源。

  • 同源示例

    • https://example.comhttps://example.com/api 是同源。
  • 不同源示例

    • https://example.comhttps://api.example.com 是不同源(域名不同)。
    • http://example.comhttps://example.com 是不同源(协议不同)。
    • https://example.comhttps://example.com:8080 是不同源(端口不同)。

2. 同源策略的作用

同源策略的主要目的是保护用户数据安全,防止恶意网站通过脚本访问其他网站的资源。具体来说,同源策略限制了以下行为:

  1. 访问 DOM
    • 不同源的脚本无法访问彼此的 DOM。
    • 例如,https://example.com 的脚本无法访问 https://another.com 的 DOM。
  2. 发送 AJAX 请求
    • 不同源的脚本无法直接发送 AJAX 请求到其他源。
    • 例如,https://example.com 的脚本无法直接请求 https://api.example.com 的数据。
  3. 读取 Cookie 或 LocalStorage
    • 不同源的脚本无法读取彼此的 Cookie 或 LocalStorage。
    • 例如,https://example.com 的脚本无法读取 https://another.com 的 Cookie。
  4. 访问 iframe 内容
    • 不同源的 iframe 无法访问彼此的内容。
    • 例如,https://example.com 的页面无法访问嵌入的 https://another.com iframe 的内容。

3. 同源策略的例外

虽然同源策略限制了跨域访问,但有一些例外情况允许跨域交互:

  1. 跨域资源嵌入
    • 浏览器允许跨域嵌入某些资源,如 <img><script><link><iframe>
    • 例如,https://example.com 的页面可以嵌入 https://another.com 的图片或脚本。
  2. 跨域表单提交
    • 浏览器允许跨域提交表单(如 <form>action 属性指向不同源)。
    • 例如,https://example.com 的表单可以提交到 https://another.com
  3. 跨域资源共享(CORS)
    • 通过 CORS,服务器可以明确允许某些跨域请求。
    • 例如,https://example.com 的脚本可以请求 https://api.example.com 的数据,前提是服务器配置了 CORS。
  4. JSONP(JSON with Padding)
    • 通过动态创建 <script> 标签,可以绕过同源策略获取跨域数据。
    • 例如,https://example.com 的页面可以通过 JSONP 获取 https://api.example.com 的数据。
  5. postMessage API
    • 通过 postMessage API,不同源的页面可以通过消息传递进行通信。
    • 例如,https://example.com 的页面可以向嵌入的 https://another.com iframe 发送消息。

4. 同源策略的实际应用

4.1 防止跨站脚本攻击(XSS)

同源策略限制了脚本访问其他源的资源,从而防止恶意脚本窃取用户数据或执行未经授权的操作。

4.2 防止跨站请求伪造(CSRF)

同源策略限制了跨域请求的发送,从而防止恶意网站伪造用户请求。

4.3 保护用户隐私

同源策略限制了不同源之间的 Cookie 和 LocalStorage 访问,从而保护用户隐私。

5. 同源策略的示例

5.1 访问 DOM

  • 同源:

    // 假设当前页面是 https://example.com
    document.getElementById("element"); // 可以访问
    
  • 不同源:

    // 假设当前页面是 https://example.com
    const iframe = document.getElementById("iframe");
    iframe.contentWindow.document.getElementById("element"); // 报错
    

5.2 发送 AJAX 请求

  • 同源:

    // 假设当前页面是 https://example.com
    fetch("/api/data") // 可以请求
      .then((response) => response.json())
      .then((data) => console.log(data));
    
  • 不同源:

    // 假设当前页面是 https://example.com
    fetch("https://api.example.com/data") // 报错
      .then((response) => response.json())
      .then((data) => console.log(data));
    

5.3 读取 Cookie

  • 同源:

    // 假设当前页面是 https://example.com
    document.cookie; // 可以读取
    
  • 不同源:

    // 假设当前页面是 https://example.com
    // 无法读取 https://another.com 的 Cookie
    

6. 如何绕过同源策略

虽然同源策略是浏览器的重要安全机制,但在某些情况下需要绕过它。以下是常见的绕过方法:

  1. CORS
    • 服务器配置 Access-Control-Allow-Origin 头部字段,允许特定源的跨域请求。
  2. JSONP
    • 通过动态创建 <script> 标签,获取跨域数据。
  3. 代理服务器
    • 使用同源服务器作为代理,转发跨域请求。
  4. postMessage API
    • 通过消息传递实现跨域通信。
  5. document.domain
    • 如果两个页面属于同一主域(如 example.comsub.example.com),可以通过设置 document.domain 实现跨域访问。

7. 总结

  • 同源策略是浏览器的核心安全机制,限制不同源之间的交互。
  • 同源是指协议、域名和端口完全相同。
  • 同源策略保护用户数据安全,防止恶意网站窃取信息或执行未经授权的操作。
  • 通过 CORS、JSONP、代理服务器等方法可以绕过同源策略,实现跨域交互。