使用 Service Worker 缓存非 SSL 请求
Cache non-SSL request with Service Worker
因为 Service Worker registration requires website to be served over HTTPS, Google Chrome throws an error when I try to add HTTP resource to Cache:
Mixed Content: The page at 'https://example.com/sw.js' was loaded over HTTPS, but requested an insecure resource 'http://example.com/'. This request has been blocked; the content must be served over HTTPS.
我想缓存主 HTTP 页面(或至少 301 重定向到 HTTPS),因为用户很难输入 https://
部分,尤其是在移动设备上,以访问我网站的缓存版本,离线时。
是否有任何解决方法可以实现此目的?
我已经考虑了一下,但我认为没有直接解决您遇到的问题的方法。跨源策略将阻止您在本地缓存它,这是有充分理由的。如果这没有到位,您可以拦截对其他来源的任何请求。
https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API 说
“出于安全原因,服务工作者仅 运行 通过 HTTPS。修改网络请求对中间人攻击开放将非常糟糕。
作为一种解决方案,我将在 http 上托管一个应用程序缓存清单,并重定向到 https。如果用户第一次通过 https 访问,这不会自动缓存,但如果是这种情况,用户很可能总是通过 https 访问该页面。如果用户确实使用 http,它将缓存重定向,并且这将可离线使用。虽然该技术已被弃用,但仍被广泛使用,参考:https://developer.mozilla.org/en-US/docs/Web/HTML/Using_the_application_cache .
如果还使用 301 永久重定向,则浏览器不太可能缓存重定向并默认加载 https,请参阅:https://en.wikipedia.org/wiki/HTTP_301。
希望这足以满足您的需求,如果不能,我想讨论一下您在使用此解决方案时遇到的问题。
我不认为这个问题可以通过 service worker 来解决,因为没有办法拦截对 http 方案的请求。但是,看起来 Strict-Transport-Security
header 可以工作。
如果在 https
响应中提供,它会强制浏览器始终使用 https
方案来加载页面——如果已正确安装,这应该会影响服务工作者。这适用于用户未键入方案(例如 example.com
)或键入 http
方案(例如 http://example.com
)的情况。
如果 server-side 解决方案,例如返回 HTTP 301 响应或包含 Strict-Transport-Security
header 由于您的服务设置而无法实现,则另一种选择是使用 client-side JavaScript 更新 window.location.href
,这将触发页面重新加载。
您可以遵循 <platinum-https-redirect>
Polymer element 中使用的技术,改编如下:
function _isLocalhost(hostname) {
// !! coerces the logical expression to evaluate to the values true or false.
return !!(hostname === 'localhost' ||
// [::1] is the IPv6 localhost address.
hostname === '[::1]' ||
// 127.0.0.1/8 is considered localhost for IPv4.
hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/));
}
if (window.location.protocol === 'http:' && !_isLocalhost(window.location.hostname)) {
// Redirect to https: if we're currently using http: and we're not on localhost.
window.location.href = 'https:' + window.location.href.substring(window.location.protocol.length);
}
因为 Service Worker registration requires website to be served over HTTPS, Google Chrome throws an error when I try to add HTTP resource to Cache:
Mixed Content: The page at 'https://example.com/sw.js' was loaded over HTTPS, but requested an insecure resource 'http://example.com/'. This request has been blocked; the content must be served over HTTPS.
我想缓存主 HTTP 页面(或至少 301 重定向到 HTTPS),因为用户很难输入 https://
部分,尤其是在移动设备上,以访问我网站的缓存版本,离线时。
是否有任何解决方法可以实现此目的?
我已经考虑了一下,但我认为没有直接解决您遇到的问题的方法。跨源策略将阻止您在本地缓存它,这是有充分理由的。如果这没有到位,您可以拦截对其他来源的任何请求。
https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API 说 “出于安全原因,服务工作者仅 运行 通过 HTTPS。修改网络请求对中间人攻击开放将非常糟糕。
作为一种解决方案,我将在 http 上托管一个应用程序缓存清单,并重定向到 https。如果用户第一次通过 https 访问,这不会自动缓存,但如果是这种情况,用户很可能总是通过 https 访问该页面。如果用户确实使用 http,它将缓存重定向,并且这将可离线使用。虽然该技术已被弃用,但仍被广泛使用,参考:https://developer.mozilla.org/en-US/docs/Web/HTML/Using_the_application_cache .
如果还使用 301 永久重定向,则浏览器不太可能缓存重定向并默认加载 https,请参阅:https://en.wikipedia.org/wiki/HTTP_301。
希望这足以满足您的需求,如果不能,我想讨论一下您在使用此解决方案时遇到的问题。
我不认为这个问题可以通过 service worker 来解决,因为没有办法拦截对 http 方案的请求。但是,看起来 Strict-Transport-Security
header 可以工作。
如果在 https
响应中提供,它会强制浏览器始终使用 https
方案来加载页面——如果已正确安装,这应该会影响服务工作者。这适用于用户未键入方案(例如 example.com
)或键入 http
方案(例如 http://example.com
)的情况。
如果 server-side 解决方案,例如返回 HTTP 301 响应或包含 Strict-Transport-Security
header 由于您的服务设置而无法实现,则另一种选择是使用 client-side JavaScript 更新 window.location.href
,这将触发页面重新加载。
您可以遵循 <platinum-https-redirect>
Polymer element 中使用的技术,改编如下:
function _isLocalhost(hostname) {
// !! coerces the logical expression to evaluate to the values true or false.
return !!(hostname === 'localhost' ||
// [::1] is the IPv6 localhost address.
hostname === '[::1]' ||
// 127.0.0.1/8 is considered localhost for IPv4.
hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/));
}
if (window.location.protocol === 'http:' && !_isLocalhost(window.location.hostname)) {
// Redirect to https: if we're currently using http: and we're not on localhost.
window.location.href = 'https:' + window.location.href.substring(window.location.protocol.length);
}