记一次下载文件block问题(mixed content)

9,705 阅读3分钟

背景

前几天QA同学在进行测试走查,突然给到我一个提了一个issue,反馈说在测试环境中打开页面点击下载文件但是没有下载下来,当时脑袋里第一反应,不可能吧,本地测试的时候是没有问题....等等,难道是那个问题?

问题定位

打开chrome浏览器,打开控制台尝试复现这个问题,果然是没有反应,仔细看了一下控制台的信息,从控制台中找到了提示

具体信息:

Mixed Content: The site at 'xxxx.net/​' was loaded over a secure connection, but the file at 'xx.xx.xx.org/obj/xx-xx/a…' was loaded over an insecure connection. This file should be served over HTTPS. This download has been blocked. See blog.chromium.org/2020/02/pro… for more details.

走读一下这段信息,这个的意思是当前的网站(也就是QA同学测试的这个环境)是以一个Https开头的网站,这个会建立起安全的连接,但是我们下载的这个文件是以http开头的,这个是一个不安全的连接,在https网站下加载这个http开头的链接会有Mixed Content的问题

Mixed Content 走读

看一下MDN上面关于这个Mixed content的相关介绍

当用户访问一个通过https serverd出来的页面的时候,这时候和网页之间的连接是基于TLS加密的,所以可以防止大部分的sniffers还有中间人攻击。一个https页面中包含着通过明文http获取内容的话,这个页面就被我们称为「混合内容页面」。像这样只有部分加密的页面只有部分加密,使得sniffers和中间人攻击者可以访问未加密的内容。酱紫页面就不安全了。

Mixed Content分类

  • Mixed passive/display content
  • Mixed active content

这两种的区别在于,如果内容作为中间人攻击的一部分被重写,最坏情况场景的威胁级别会不一样。在Mixed active content的情况下,威胁较低(页面可能包含误导性内容,或者用户的cookie可能被盗)。在主动内容的情况下,威胁可能导致网络钓鱼、敏感数据泄露、重定向到恶意网站等。Mixed passive/display content 这种不能更改网页的一些内容,一般是通过一些适当的图像之类的,Mixed active content 可以访问HTTPS页面的全部或者部分Document Object Model,除了改变行为还可能窃取敏感数据等,还可以重写响应以包含恶意JavaScript代码,或者让用户重定向到其他HTTP页面并窃取cookie等行文。

Passive content 的类型
  • <img> src属性
  • <audio> src属性
  • <video> src属性
Active content 的例子
  • <script> src属性
  • <link> href
  • <iframe> src属性
  • xhr、fetch 请求
  • css 使用url()加载的情况
  • <object> data属性
  • Navigator.sendBeacon url属性

解决方案

按照MDN上面提供的建议,最佳实践是将所有内容都转为https,这里我们就处理一下http的下载资源

原先的代码

const downloadURL = (url: string, filename?: string) => {
  const anchor = document.createElement('a');
  anchor.href = url;
  filename && (anchor.download = filename);
  anchor.click();
};

function downloadResource(url: string) {
    downloadURL(url);
}

改造之后

const downloadURL = (url: string, filename?: string) => {
  const anchor = document.createElement('a');
  anchor.href = url;
  filename && (anchor.download = filename);
  anchor.click();
};
function downloadResource(url: string) {
    // 有一些下载url是http开头的,在https的域名下面下载的话会有mix content问题,这里转成https
    if (url.startsWith('http:')) {
      const replaceUrl = url.replace('http:', 'https:');
      downloadURL(replaceUrl);
    } else {
      downloadURL(url);
    }
}

验证结果

测试了一下,没有出现之前那种下载没有反应的情况,改造完成