前端面对跨域问题的处理方案

311 阅读4分钟

wallhaven-g7dyqe.jpg

为什么会出现跨域问题?

“跨域”问题是指浏览器为了安全考虑实施的一种同源策略(Same-origin policy)。这个策略限制了来自不同源的“写”操作。当一个网页尝试访问另一个来源的资源时,如果这两个来源不是同一个源,就会遇到跨域问题。

关键词:‘浏览器’ ‘限制’ ‘非同一来源’

我的理解:为了安全,浏览器限制了网页从非同一来源获取资源的行为

补充:浏览器对从非同一来源获取资源不同行为限制程度不同

  • 轻微限制(几乎没有限制):
  1. <img> 标签:
    • 浏览器允许从任何来源加载图片,因此<img>标签可以加载非同一来源的图片资源。
  2. <script> 标签
    • 类似于<img>标签,浏览器也允许从任何来源加载脚本资源,但这种加载有一定的限制。例如,加载的脚本不能包含敏感信息或执行危险的操作。
    • JSONP(JSON with Padding)就是利用了<script>标签的这个特性。
  3. <link> 标签
    • 浏览器允许从任何来源加载样式表(CSS文件)。
  4. <iframe> 标签
    • 浏览器允许从任何来源加载嵌入式页面,但<iframe>中的页面仍然受限于同源策略。
    • 可以通过设置<iframe>sandbox属性或目标页面的X-Frame-Options来增加安全性。
  5. 字体资源 (<font> 或 @font-face)
    • 浏览器允许从任何来源加载字体资源。
  6. 视频和音频资源 (<video><audio>)
    • 浏览器允许从任何来源加载视频和音频文件。

  • 严格限制

除了上述资源之外,其他跨域行为通常受到严格的限制。例如,AJAX请求、Fetch API调用等都需要遵守同源策略,除非服务器明确允许跨域访问。

浏览器并没有完全限制非同一来源的资源访问,而是根据资源类型的不同采取不同程度的限制。对于静态资源(如图片、样式表、字体、视频和音频),浏览器通常允许跨域加载,但对于涉及执行代码或敏感数据的资源,则需要更加严格的同源策略检查。

解决跨域的方法类型

从关键词可以知道,跨域原理是浏览器限制了非同一来源的行为。因此,解决跨域问题可以从两个方向入手:一是绕过浏览器的限制,二是解决非同一来源的问题。

1. 绕过浏览器限制

方法一:JSONP(JSON with Padding)
  • 适用场景:仅支持GET请求。
  • 原理:利用<script>标签不受同源策略限制的特点。
  • 实现
方法二:使用代理服务器
  • 适用场景:适用于开发环境或需要转发请求的场景。

  • 原理:在前端项目中配置一个代理服务器,所有跨域请求都通过代理服务器转发。

  • 实现

    • 配置代理:在前端开发环境中配置代理,例如使用Webpack Dev Server。
    • 请求重定向:前端请求通过代理服务器进行重定向。
    fetch('/proxy?url=https://api.example.com/data')
     .then(response => response.json())
     .then(data => console.log(data));
    

2. 解决非同一来源问题

方法一:CORS(Cross-Origin Resource Sharing)
  • 适用场景:适用于所有HTTP请求类型。

  • 原理:服务器设置响应头Access-Control-Allow-Origin来允许特定源或所有源访问资源。

  • 实现

    • 后端设置:在后端服务器中配置CORS支持。
    // Node.js + Express 示例
    const express = require('express');
    const cors = require('cors');
    const app = express();
    
    app.use(cors());
    
    app.get('/data', (req, res) => {
      res.setHeader('Access-Control-Allow-Origin', '*');
      res.send({ message: 'Hello from server!' });
    });
    
    app.listen(3000, () => {
      console.log('Server running on port 3000');
    });
    
方法二:修改文档域名
  • 适用场景:适用于同一主域名下的不同子域名之间的资源共享。

  • 原理:通过设置document.domain为相同的值,使子域名被视为同源。

  • 实现

    1// 主域名相同的不同子域名
    2document.domain = 'example.com';
    
方法三:WebSocket
  • 适用场景:适用于需要实时双向通信的场景。

  • 原理:WebSocket协议不受同源策略限制。

  • 实现

    const socket = new WebSocket('wss://api.example.com');
    
    socket.onopen = () => {
      socket.send('Hello, server!');
    };
    
    socket.onmessage = event => {
      console.log('Message from server:', event.data);
    };
    
  • 绕过浏览器限制:主要通过前端技术如JSONP或设置代理服务器来实现。

  • 解决非同一来源问题:主要通过后端配置CORS或调整域名设置来实现。

实际开发中如何选择哪种解决方案?

image.png

总结

在实际开发中,配置CORS(跨源资源共享,Cross-Origin Resource Sharing)是解决跨域问题的一种非常主流且推荐的做法。