Skip to content

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❌ 不支持

参考资料

Released under the MIT License.