当 HTTPS 页面加载 HTTP 资源时,就会产生混合内容(Mixed Content)。浏览器会阻止不安全的请求,导致页面功能异常。本文介绍混合内容的类型、排查方法和解决方案。
什么是混合内容#
HTTPS 页面中通过 HTTP 加载的资源称为混合内容:
1
2
3
4
|
<!-- HTTPS 页面中的混合内容 -->
<script src="http://example.com/script.js"></script>
<img src="http://example.com/image.jpg">
<link rel="stylesheet" href="http://example.com/style.css">
|
混合内容类型#
混合被动内容(Mixed Passive Content)#
低风险资源,浏览器通常只显示警告:
<img> 图片
<audio> / <video> 媒体
<object> 子资源
混合主动内容(Mixed Active Content)#
高风险资源,浏览器会直接阻止:
<script> 脚本
<link> 样式表
<iframe> 内嵌页面
- XMLHttpRequest / Fetch 请求
<frame> / <object> 加载的页面
排查方法#
浏览器控制台#
打开开发者工具(F12),查看 Console 和 Security 面板:
1
2
3
|
Mixed Content: The page at 'https://example.com/' was loaded over HTTPS,
but requested an insecure script 'http://cdn.example.com/script.js'.
This request has been blocked.
|
curl 检查#
1
|
curl -I https://example.com 2>&1 | grep -i "location\|http"
|
解决方案#
1. 协议相对 URL#
使用 // 代替 http:// 或 https://:
1
2
3
4
5
|
<!-- 修改前 -->
<script src="http://cdn.example.com/script.js"></script>
<!-- 修改后 -->
<script src="//cdn.example.com/script.js"></script>
|
浏览器会自动使用当前页面的协议。
2. 强制 HTTPS#
直接使用 HTTPS URL:
1
|
<script src="https://cdn.example.com/script.js"></script>
|
3. 服务器端重定向#
配置服务器将 HTTP 重定向到 HTTPS:
Nginx:
1
2
3
4
5
|
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}
|
4. Content-Security-Policy#
使用 CSP 强制升级不安全请求:
1
|
add_header Content-Security-Policy "upgrade-insecure-requests";
|
这会自动将页面中所有 HTTP 请求升级为 HTTPS。
5. HSTS#
启用 HSTS 告诉浏览器始终使用 HTTPS:
1
|
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
常见场景#
第三方资源#
许多第三方服务同时支持 HTTP 和 HTTPS:
1
2
3
4
5
|
<!-- Google Analytics -->
<script src="https://www.googletagmanager.com/gtag/js"></script>
<!-- 字体 -->
<link href="https://fonts.googleapis.com/css2" rel="stylesheet">
|
本地开发#
开发环境使用自签名证书时,浏览器可能阻止混合内容。可以:
- 使用
mkcert 生成本地信任证书
- Chrome 访问
chrome://flags/#allow-insecure-localhost
API 请求#
前端调用后端 API 时确保使用 HTTPS:
1
2
3
4
5
6
7
|
// 错误
fetch('http://api.example.com/data')
// 正确
fetch('https://api.example.com/data')
// 或使用相对路径
fetch('/api/data')
|
检查清单#
| 检查项 |
方法 |
| 页面资源 |
浏览器控制台 |
| API 请求 |
Network 面板 |
| 第三方服务 |
确认支持 HTTPS |
| 重定向配置 |
curl -I 测试 |
| CSP 策略 |
响应头检查 |
混合内容会破坏 HTTPS 的安全性,浏览器会阻止主动混合内容。解决方案包括:
- 使用协议相对 URL 或直接 HTTPS
- 配置 CSP 的
upgrade-insecure-requests
- 启用 HSTS
- 确保所有第三方资源支持 HTTPS