mixed content 怎么修:浏览器升级了哪些、挡了哪些,还有一条能跑的排查命令

mixed content 是 HTTPS 页面发出的 http:// 请求。浏览器会自己把图片、视频、音频升级成 HTTPS,其余的一律挡掉,所以一条 http:// 地址就能让一个脚本或一次下载悄悄失效。这里有一条审计命令、一张修复表,和一条兜底的 CSP 指令。

抓取与收录6 分钟读完1257 次阅读
mixed content 怎么修:浏览器升级了哪些、挡了哪些,还有一条能跑的排查命令

mixed content 是浏览器给一种请求起的名字:页面本身是用 HTTPS 打开的,它却去请求一个 http:// 地址。浏览器对这件事分两种处理——图片、视频、音频会被自动升级成 HTTPS,其余的不安全请求(脚本、样式表、iframe、fetch、下载)一律直接挡掉。修法是让每一个子资源都走 HTTPS;来不及全改时,最快的兜底是一条 Content-Security-Policy 指令。

读这篇前

你只要能改一个页面、能看到它的源码就够了,不需要构建流程。有两章挨着这篇。安全响应头会不会挡住 Google 渲染器,是另一篇——content-security-policy 会不会挡住 Google 渲染器讲的是那个头本身,这篇只从里面借一条指令。如果页面真正的问题是爬虫拿到的是空壳,AI 爬虫会执行 JavaScript 吗是这一步之前。量出来的那一半——面板里到底有多少 http:// 地址——在27 个首页上的 mixed content 实测。

mixed content 是什么,浏览器为什么把不安全请求分成两类

安全上下文(secure context)指用 HTTPS 打开的页面。MDN 给的定义是:"When a web page is loaded from a secure origin, over a secure channel such as HTTPS, the connection with the web server is encrypted, and is therefore protected from eavesdropping and modification by manipulator in the middle (MITM) attacks"(MDN,2026-09-27 访问)。页面里只要有一条 http:// 请求,这条请求就不再有这层保证,网络路径上的任何人都能在它传输时改掉它。

多数人是先撞见那句报错才来搜这个词的。Chrome 在控制台里会把整句话打出来,形如 Mixed Content: The page at '…' was loaded over HTTPS, but requested an insecure …——后半句写的是被挡下的是哪一种资源。这条消息本身就是排查的入口:它同时告诉你是哪个地址、属于哪一类。中文侧的下拉里,跳过按钮直接整句复制去搜的人不在少数,这也是中文读者到达 mixed content 这个词最常见的一条路。

现代浏览器在这里只画一条线。按 MDN 的说法,"a web page is divided into two categories: 'upgradable content' and 'blockable content'",可升级的那类会被自动从 HTTP 改写成 HTTPS,可拦截的那类直接挡下。落到具体资源上,图片、视频、音频属于 auto-upgrading,脚本、样式表、iframe、fetch/XHR、字体属于 block all other resource types。

一条不安全请求就够了。页面的安全程度,取决于它加载的东西里最不安全的那一个。

还有一类容易漏:不安全下载(mixed downloads)。MDN 说这类资源是 "initiated from a secure context, but fetched over an insecure connection",浏览器 "should also block mixed downloads by default"。你页面提供的一个文件,会和脚本一样被挡住,理由完全相同。

读者看到的现象取决于失败落在哪一边。可拦截的请求会在开发者工具里报一句拒绝,资源根本不出现;可升级的请求在 HTTPS 版本不存在时会安静地失败。光看 HTML 分不出访客遇到的是哪一种——那是控制台的事实,不是标记的事实。这篇剩下的部分只讲标记。

按这个顺序做

四步,每一步都有一个可以先检查、再往下走的完成标志。

  1. 先把页面加载的子资源列出来。图片、脚本、样式表、字体、iframe、视频。完成标志:这份清单和硬刷新时 Network 面板里的一致。
  2. 把 http:// 的那几条标出来。跑下面的审计命令。完成标志:它返回零行,或者你能逐条说明剩下那几行为什么还留着。
  3. 先修可拦截的资源。脚本和样式表没法被自动升级,必须给它一个真的 https:// 地址。完成标志:控制台里那条拒绝消失了。
  4. 补上兜底。今天改不完所有地址,就先加 upgrade-insecure-requests。完成标志:响应头里有它,且可拦截的资源能加载出来。

交付物:一条审计命令 + 一张修复表

这条命令读的是服务端返回的 HTML,把每一条仍然以 http:// 开头的地址打出来。它不执行 JavaScript,所以看到的是爬虫第一次抓取时看到的东西。

curl -sL https://example.com \
  | grep -oE 'http://[^" ]+' \
  | sort | uniq -c | sort -rn

再配一条命令,看兜底是不是已经在了:

curl -sIL https://example.com | grep -i content-security-policy

拿它去跑 Google 自己的 SEO Starter Guide——那页教你怎么写好 HTML——第一条命令在 2026-09-27 返回空:交付的 HTML 里没有 http:// 地址。有意思的是第二条。那一页确实发了 Content-Security-Policy,但不是会升级的那一种;它的 script-src 甚至放行了 http: 这个协议。同样两条命令去跑 querywin.com 和 byerisk.com:两边都是零个 http:// 地址,两边也都没有 Content-Security-Policy 响应头。这是一次干净的审计,同时也是一句提醒——我们自己的两个页面都没有这张网。

那一页还有一个数字值得一提,因为它最容易让人误判。它有十一个子资源引用是协议相对地址,也就是用 // 开头而不是写协议。在 HTTPS 页面上它们就是走 HTTPS,不算 mixed content;只有页面哪天被用 HTTP 打开时这行才有意义。我们因此把它们分开数。

现象原因修法
图片或视频裂了http:// 的媒体地址改成 https://;HTTPS 版本存在时浏览器也会自动升级
脚本或样式被拒http:// 的可拦截资源必须给真的 https:// 地址,自动升级不覆盖脚本
历史地址太多老 CMS 或模板边改写边发 upgrade-insecure-requests
下载被挡不安全下载把文件改成 HTTPS 提供

兜底就是一条响应头,具体加在哪里取决于你的托管方式。

Content-Security-Policy: upgrade-insecure-requests

MDN 对这行指令的说明是,它 "instructs the user agent to treat a site's insecure URLs (those served over HTTP) as though they have been replaced with secure URLs";它会在请求发出前改写地址,"first-party as well as third-party requests",而且是给 "websites with large numbers of insecure legacy URLs that need to be rewritten" 用的。有两条边界写在里面,两条都要知道。第一,如果某个资源根本没有 HTTPS 版本,"the request will fail without any fallback to HTTP"——它会失败,不会退回 HTTP。第二,它管不到顶级跳转:MDN 明说它 "will not ensure that users visiting your site via links on third-party sites will be upgraded to HTTPS for the top-level navigation",所以它替代不了 HSTS。

做错了会怎样

三种错误占了绝大多数。

  1. HTTPS 版本还没就绪就先开了升级。每条被改写的请求都没有退路,于是原本能打开的文件变成了打不开的文件。先把地址改对,或者接受这张网会弄坏它升不了级的东西。
  2. 太信这条 grep。审计读的是交付的 HTML。页面加载完再注入一个 http:// 图片或统计脚本的组件,它看不见;那要等控制台告诉你。这条命令是下限,不是合格证。
  3. 把协议相对地址当成不安全。//cdn.example.com/x.js 在 HTTPS 页面上就是 HTTPS。手动改写它没坏处,但把它算成 mixed content,会让你去追一个根本不存在的问题。

常见问题

mixed content 是什么?

HTTPS 页面发出的、却走 HTTP 的请求。页面是安全的,那条请求不是。浏览器会挡掉危险的那类、升级安全的那类。

mixed content 会影响收录或排名吗?

不是排名因素,我们也不会说它能让排名涨。它影响的是「加载了什么」:一条被挡的脚本或样式表,会同时改变渲染型爬虫和访客看到的页面。Google 自己的文档只把 HTTPS 当作一个很轻的信号,所以修它的理由是页面能正常跑,不是排名。

upgrade-insecure-requests 能全修好吗?

不能。它只覆盖子资源、不覆盖跳转,而且只有 HTTPS 版本存在时才生效。把它当兜底,别当修复。

怎么确认某个资源有没有 HTTPS 版本?

动手改之前先试一下:curl -sI https://example.com/logo.png,看第一行的状态码。返回 200,说明 HTTPS 版本在,可以直接把页面里的地址改过去;返回 404 或连不上,说明版本还没准备好,这时候开 upgrade-insecure-requests 只会让原本能加载的图片变成加载不出来。先备好 HTTPS 版本,再切换,这个顺序不能反。

你们是怎么测的?

2026-09-27,我们用交付物里的审计命令对三个页面各跑了一次:Google 的 SEO Starter Guide,和我们自己的 querywin.com、byerisk.com。只读服务端返回的 HTML,没在浏览器里复现被挡的情况;我们报告的只有标记和响应头,更大范围的样本在 27 个首页那篇实测里。

mixed content 是一个很小、很好查的交付层 bug,通常要等到某个第三方组件或模板在你看不见的地方换了东西才会冒出来。同一个问题的更大一半——爬虫到底拿不拿得到你改完的页面——是 QueryWin 在做的那部分。

本文属于 QueryWin 实操手册 · 第 2 阶

mixed content 怎么修:浏览器升级了哪些、挡了哪些,还有一条能跑的排查命令