技术复盘文档:HTTPS 站点安全下载 HTTP 资源实践总结
1. 业务背景
在 子系统日志中心 业务模块中,用户需要从主站界面下载各子系统的运行日志(如 ETL 日志、DCP 日志)。
- 主站域名:
https://aims.dcsoft.local或https://083.dev.aims.dcsoft.vip(安全 HTTPS 协议) - 下载服务器:
http://192.168.13.220:2800或http://192.168.100.72:2800(非安全 HTTP 协议) - 资源类型:
.log后缀的文本文件 - 核心诉求:点击下载按钮后,触发文件下载,严禁导致主站页面跳转或重定向
2. 核心问题描述
由于现代浏览器(尤其是 Chrome 88+)加强了安全防护,当一个 HTTPS 站点 尝试请求一个 HTTP 资源 进行下载时,会触发 Mixed Content(混合内容) 拦截和 Insecure Download Blocking(不安全下载拦截)。
其表现为:浏览器认为该下载不安全,为了提醒用户,会强行夺取主站窗口的控制权并将其重定向到目标地址,导致主站业务中断。
3. 技术探索历程与失败原因分析
我们针对该问题先后尝试了 6 种前端方案,均由于浏览器底层的安全策略无法完美达成目标:
方案一:动态 <a> 标签 + download 属性
- 操作:创建隐藏
<a>标签,设置target="_blank"和download属性 - 结果:主站重定向跳转,下载未触发
- 原因:
download属性在跨域/跨协议时被浏览器忽略。Chrome 识别到安全降级,强行在当前窗口导航
方案二:隐藏 <iframe> 方案
- 操作:创建不可见 iframe,将其 src 指向下载地址
- 结果:控制台报错:
was loaded over an insecure connection - 原因:Mixed Content 拦截。HTTPS 严禁以 Frame 形式加载 HTTP 资源
方案三:window.open('about:blank') + document.write 中转
- 操作:先开空白页,在新页内注入跳转脚本
- 结果:主站依然闪退/跳转,或者新页面无反应
- 原因:Chrome 会追踪窗口的 opener(血缘关系)。只要新窗口处于主站的安全上下文中,不安全下载依然会触发父窗口的关联重定向
方案四:window.open + noopener noreferrer
- 操作:彻底斩断新旧窗口的联系
- 结果:主站保住了,但新窗口打开后显示日志文本,不触发下载;或弹出"您即将提交的信息不安全"的蓝色警告页
- 原因:
- 蓝色警告是 Chrome 对跨协议提交的硬件级拦截,JS 无法消除
.log被识别为文本,后端缺少Content-Disposition响应头,导致预览而非下载
方案五:Form 表单提交到 target="_blank"
- 操作:创建隐藏表单模拟 POST/GET 提交
- 结果:跳转到新窗口,但必现"您即将提交的信息不安全"提示
- 原因:浏览器判定将加密页面的数据提交到非加密页面存在风险
4. 根源复盘总结
4.1 为什么前端无法完美解决?
浏览器厂商(Google/Microsoft)已经将 "HTTPS 页面静默触发 HTTP 下载" 这条路在代码层面封死了。
- 如果使用 脚本触发,浏览器判定为流氓行为,直接重定向主站
- 如果使用 用户点击,浏览器判定为安全降级,弹出蓝色警告提示
4.2 为什么手动复制链接可以下载?
因为手动复制链接属于 "用户在地址栏直接输入",不属于任何站点的派生行为,浏览器不执行混合内容检查。