混合内容是指 HTTPS 页面通过明文 HTTP 加载子资源(图片、脚本、样式表、字体)。浏览器会阻止或警告这种行为,因为安全页面上的不安全资源会破坏整个页面的安全性。
两种类型的混合内容
| 类型 | 示例 | 浏览器行为 |
|---|---|---|
| 主动(危险) | 脚本、iframe、XHR、CSS | 所有浏览器阻止 |
| 被动(显示) | 图片、音频、视频 | 显示警告 / 降级锁头图标 |
主动混合内容可以修改页面(中间人攻击者可以注入恶意 JavaScript),因此浏览器完全阻止它。被动混合内容危险性较低,但仍会降级安全指示器。
如何查找混合内容
浏览器 DevTools
- 在 Chrome/Firefox 中打开你的网站
- 打开 DevTools(F12)→ Console 标签
- 查找如下错误:
Mixed Content: The page at 'https://example.com' was loaded over HTTPS, but requested an insecure resource 'http://example.com/image.jpg'.
命令行扫描
curl -s https://yourdomain.com | grep -oP 'http://[^"'"'"'> ]+' | sort -u
常见原因和修复方法
HTML 中硬编码的 http:// URL
<!-- Problem -->
<img src="http://example.com/logo.png">
<!-- Fix: use protocol-relative or HTTPS -->
<img src="https://example.com/logo.png">
<img src="//example.com/logo.png">
<img src="/logo.png">
最佳实践:尽可能使用相对路径(/images/logo.png)。
第三方资源仍在用 HTTP
<!-- Problem -->
<script src="http://cdn.example.com/library.js"></script>
<!-- Fix -->
<script src="https://cdn.example.com/library.js"></script>
如果第三方不支持 HTTPS,找一个替代提供商或自托管该资源。
数据库内容含有硬编码 URL
WordPress 和其他 CMS 在数据库中存储绝对 URL。迁移到 HTTPS 后:
-- WordPress: update URLs in posts
UPDATE wp_posts SET post_content = REPLACE(post_content, 'http://example.com', 'https://example.com');
UPDATE wp_options SET option_value = REPLACE(option_value, 'http://example.com', 'https://example.com');
或者使用 Better Search Replace 插件。
CSS 中的 HTTP 引用
/* Problem */
background-image: url('http://example.com/bg.jpg');
/* Fix */
background-image: url('https://example.com/bg.jpg');
background-image: url('/images/bg.jpg');
Content Security Policy (CSP) — 防止未来的混合内容
添加 CSP 头来阻止 HTTP 资源:
Nginx:
add_header Content-Security-Policy "upgrade-insecure-requests" always;
Apache:
Header always set Content-Security-Policy "upgrade-insecure-requests"
upgrade-insecure-requests 告诉浏览器自动将 http:// 请求升级为 https://——在你修复源 URL 期间作为安全网。
系统性修复:全站审计
对于彻底的清理,审计你的整个网站:
1. 扫描 HTTP 引用
# Scan all HTML files for http:// URLs
find /var/www/html -name '*.html' -o -name '*.php' | xargs grep -l 'http://' 2>/dev/null
# Scan CSS files
find /var/www/html -name '*.css' | xargs grep -l 'http://' 2>/dev/null
# Scan JavaScript files
find /var/www/html -name '*.js' | xargs grep -l 'http://' 2>/dev/null
2. 按类别修复 URL
| 来源 | 修复方法 |
|---|---|
| 你自己的资源 | 改为相对路径(/images/logo.png) |
| CDN 资源 | 更新为 https://cdn.example.com/... |
| 第三方脚本 | 更新 URL 或寻找 HTTPS 替代 |
| 内联 CSS | 搜索替换 http:// → https:// |
| 数据库内容 (WordPress) | wp search-replace 'http://yourdomain.com' 'https://yourdomain.com' |
| 模板/主题文件 | 直接编辑源文件 |
3. 用浏览器 DevTools 验证
修复后,打开每个页面 → DevTools(F12)→ Console 标签。干净的页面不会显示混合内容警告。锁头图标应该是实心的(没有破损或警告三角形)。
4. 防止未来的混合内容
在 HTML <head> 中添加此 meta 标签作为永久安全网:
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
或通过 Nginx/Apache 配置在服务器级别设置(如上所示)。
常见引起混合内容的内容类型
| 内容类型 | 检查位置 | 示例 |
|---|---|---|
| 图片 | <img src="http://..."> | 上传的图片、头像、Logo |
| 脚本 | <script src="http://..."> | 分析工具、聊天组件、广告脚本 |
| 样式表 | <link href="http://..."> | 外部字体、CSS 框架 |
| 字体 | @font-face { src: url("http://...") } | Google Fonts(通常没问题)、自定义字体 |
| iframe | <iframe src="http://..."> | 嵌入视频、地图、组件 |
| XHR/Fetch | fetch("http://...") | JavaScript 中的 API 调用 |
| 背景图片 | background-image: url("http://...") | CSS 背景 |
常见问题
混合内容会影响 SEO 吗?
不直接影响。Google 基于页面 URL 协议抓取,而非子资源。但是,如果混合内容触发浏览器警告或阻止可见内容,用户体验下降——这可能通过更高的跳出率间接影响排名。
可以只用 upgrade-insecure-requests 而不修复 URL 吗?
它可以作为权宜之计,但修复源 URL 更好。CSP 头依赖于浏览器支持(所有现代浏览器都支持,但一些旧客户端不支持),并为每个响应增加了一个额外的头。
我的网站有数百个硬编码的 HTTP URL,最快的修复方法是什么?
立即添加 upgrade-insecure-requests CSP 头(一行服务器配置)。然后在代码库和数据库中做全局搜索替换。使用 grep -r 'http://' src/ 查找代码中的硬编码 URL。