一个通过 HTTP 加载脚本的 HTTPS 页面会发出两个请求,两者的保护级别不同,而锁图标只描述第一个。隧道不会改变这一点,因为它保护的是承载通道,而不是资源自身的协议。只要读控制台而不是地址栏,浏览器其实已经告诉你是哪个请求失败了。三项检查能把你从半好半坏的页面带到真正的修复。

读请求,而不是读地址栏

通过 HTTPS 获取的文档,仍可以用明文 HTTP 引用脚本、样式表、字体或框架。该引用是独立的请求,也正是浏览器抱怨的对象。主文档的保护不会倒流进去,承载两条流的隧道也不改变任何一方的协议。因此页面可以同时是真正安全又真正损坏的。

把资源仅仅称为被包含的文件,并不能让替换它变得无害。

如果不安全的脚本内容能在传输中被改动然后执行,它就能改变页面的行为,这比外观故障严重得多。图片在途中被修改时,风险较小但真实存在。锁图标没有说谎。它回答的是一个比你提问更窄的问题。

弄清哪些资源会被拦截,哪些会被升级

浏览器并不同等对待每一类资源。 关于混合内容的指南 把升级为 HTTPS 的请求与直接拦截的请求区分开来:脚本、样式表和程序化请求属于被拦截的一侧,而图片与媒体则可能被升级或标记。

这一差别解释了那些令人困惑的报告。脚本被拦截的页面会彻底失去某项功能,而图片被升级的页面看上去正常,却已悄悄改变了请求。文档化的分类也有例外,所以不要假定某一类型的每个 URL 都能成功升级。与其从文件扩展名去推断,不如读控制台对具体请求说了什么。

组件被拦截,并不能证明隧道失败。它证明的是浏览器履行了职责。

从源头修复引用

对站点所有者来说,修复应落在写入不安全 URL 的地方:模板、样式表、拼接 URL 的脚本,或第三方组件。只改页面上可见的地址,这些地方一概没动。在源码中搜索主机名,修掉每一处引用,而不只是控制台碰巧点名的那一处。

然后确认该资源确实以有效身份通过 HTTPS 提供,因为换协议并不能凭空变出从未在那里发布过的服务。

grep -rn "http://assets.example" ./templates
curl -sSI https://assets.example/widget.js | head -n 1

也要跟踪重定向,因为以 HTTPS 开头的引用仍可能落到明文投递路径上。当某个依赖确实没有安全投递方式时,应通过正常的变更流程移除或替换它,而不是发布一个绕行方案。对用户而言,让浏览器保护保持开启,并把资源的 URL、类型和控制台消息报告给站点所有者。绝不要散发让员工为某个页面允许不安全内容的说明,因为那条例外会比促成它的事件活得更久。

按用户实际触碰页面的方式重新测试

要演练按需加载资源的操作,而不只是首个文档。页面会在按下按钮后拉取额外的代码、数据和下载,而那些请求往往才是不安全的。在保护仍然开启的情况下确认具体请求与可见行为。从放宽的浏览器配置开始的测试,无法告诉你普通用户看到什么。

隧道仍有自己的工作,那是网络访问,而不是页面完整性。

一旦流量离开隧道端点,任何剩余的 HTTP 抓取都没有从承载通道得到任何好处。修好资源路径,并让浏览器端的强制保持原位。把又一层传输当作不安全依赖的修复,正是团队最终写出一个帮助台脚本、关掉本来工作正常的控制的原因。

相关文章