HTTPS 网站访问 HTTP 资源
问题背景
当 HTTPS 页面需要加载 HTTP 资源时,浏览器会报错或给出安全提示。这是浏览器为了保护用户安全、促进协议升级所采取的默认行为。
为了避免网站开发者手动将所有 HTTP 资源逐一替换为 HTTPS,Chrome 引入了 Upgrade-Insecure-Requests 请求头机制。
工作原理
浏览器发送请求时携带:
Upgrade-Insecure-Requests: 1告知服务器当前浏览器支持 HTTPS 协议。服务器随后在响应头中返回:
Content-Security-Policy: upgrade-insecure-requests浏览器收到该响应头后,会自动将页面中所有 HTTP 资源请求升级为 HTTPS。
示例
页面中有如下图片资源:
http://localhost/1.jpg浏览器会自动将请求升级为:
https://localhost/1.jpg注意
服务器端需要在对应的 HTTPS 端口上部署相应资源,否则升级后的请求仍会失败。
例外情况
<a> 标签指向的外站资源不会被自动升级。
例如,A 网站包含一个指向 B 网站的链接,该链接对应的 URL 不会被升级为 HTTPS。
解决方案
方案一:静态 Meta 标签
在 HTML 的 <head> 标签中添加以下 meta 标签:
html
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">方案二:动态 JS 注入(推荐)
将逻辑封装到 JavaScript 中,仅在 HTTPS 环境下动态注入 meta 标签,避免在 HTTP 环境中造成不必要的影响:
js
// 动态添加 meta 资源 https
if (window.location.protocol.split(":")[0] == 'https') {
var meta = document.createElement('meta');
meta.content = "upgrade-insecure-requests";
meta.setAttribute('http-equiv', "Content-Security-Policy");
document.getElementsByTagName('head')[0].appendChild(meta);
}推荐理由
动态注入方式更灵活,同一套代码可以同时兼容 HTTP 和 HTTPS 环境,无需为不同环境维护两份 HTML 模板。
方案对比
| 方案 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 静态 Meta 标签 | 纯 HTTPS 站点 | 简单直观 | 在 HTTP 环境下可能造成干扰 |
| 动态 JS 注入 | HTTP / HTTPS 混合环境 | 灵活兼容 | 依赖 JS 执行 |
浏览器兼容性
| 浏览器 | 支持版本 |
|---|---|
| Chrome | ✅ 43+ |
| Firefox | ✅ 42+ |
| Edge | ✅ 17+ |
| Safari | ✅ 10.1+ |
| IE | ❌ 不支持 |
