一篇文章搞定跨域问题!

“跨域”的问题来源于浏览器的同源策略(Same-Origin Policy),这是一个用于保障 Web 安全的机制。它限制了网页中加载的脚本或资源访问其他源的数据。


一.跨域的来源

什么是“源”?

一个网页的“源”由三部分构成:

协议://域名:端口号
  • 协议(Protocol):如 http://https://

  • 域名(Domain):如 example.com

  • 端口号(Port):如 :80:443

只有这三者都相同,两个页面才属于“同源”,如果三者有其一不同,则会产生跨域

二.跨域常见的类型

1. 脚本访问跨域

    通过 JavaScript 脚本(如 fetchXMLHttpRequest主动请求跨域数据(如 JSON、API 接口等),并试图读取资源的内部数据,而产生的跨域。

  • 不同源之间的页面不能直接通过 JS 访问对方的 DOM。

  • 比如,在使用iframe预览图片时。当iframe中的图片来源与包含iframe的页面的域名不同时,就会触发浏览器的同源策略,从而导致跨域问题。

  • <!-- 父页面(a.com)中嵌套了一个 iframe -->
    <iframe src="https://b.com/page.html" id="myFrame"></iframe>
    
    <script>
      const iframe = document.getElementById('myFrame');
      console.log(iframe.contentWindow.document); //  报错:Permission denied
    </script>
    因为 a.com 与 b.com 不同源,浏览器禁止 JS 直接访问 iframe 的内容。

2. 数据请求跨域(AJAX/Fetch)

       通过 JavaScript 主动发起的数据请求(如 AJAX、Fetch),尝试从不同源(协议、域名、端口任一不同)的服务器获取数据资源,而这种行为受到浏览器 同源策略(Same-Origin Policy) 的限制

  • 使用 fetchXMLHttpRequest 请求其他域名的数据时被浏览器拦截。

  • 需要目标服务器设置 CORS 头部允许访问。

  • 解决方案

  • 1.后端设置cors
  • 2.前端使用代理服务器
  • 3.jsonp ,仅支持get请求,已过时

3. 资源加载跨域

        浏览器从不同源(协议、域名、端口任一不同)加载静态资源(如图片、CSS、JS、字体、视频等)。

  • 加载图片、字体、音视频、PDF 等静态资源时,若未配置 CORS,可能无法使用或被限制访问(如无法绘制到 canvas 上)。

  • 解决方案

  • 1. 资源服务器配置 CORS 响应头

    后端服务器需返回以下 HTTP 头:

    Access-Control-Allow-Origin: *

    或者指定源

  • Access-Control-Allow-Origin: https://your-website.com
  • 2. 前端添加 crossorigin 属性(图片、音视频、字体时需)

    <img src="..." crossorigin="anonymous">
     <video src="..." crossorigin="anonymous"></video>
     <link rel="stylesheet" href="..." crossorigin="anonymous">

     注意:

  • 仅前端设置 crossorigin 不够服务器必须响应带有 Access-Control-Allow-Origin,两边要配合。

4.浏览器缓存跨域---最难发现的跨域

        浏览器缓存跨域,是由于浏览器的缓存机制导致的一种跨域情况。这种跨域一般会出现在浏览器通过一些无视跨域的标签和css(如img、background-image)缓存了一些图片资源之后,当再次发起图片请求时,就不会向服务器端请求数据,而是直接向浏览器请求缓存的数据,从而引起了跨域。这个时候即使服务端设置了Access-Control-Allow-Origin,但浏览器请求的是缓存,依旧会导致跨域的发生。

解决

1.设置时间戳,让浏览器以为是不同资源来防止缓存

  // 在UR 后面加上时间戳参数,避免浏览器缓存导致图片不刷新。
    img.src = url + '?t=' + new Date().getTime();

2.发送请求时,设置如下配置,强制刷新

 const res = await fetch(url,{cache:'no-cache'})

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值