Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/image/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Html 在看似有效的URL上违反内容安全策略_Html_Image_Service Worker_Content Security Policy - Fatal编程技术网

Html 在看似有效的URL上违反内容安全策略

Html 在看似有效的URL上违反内容安全策略,html,image,service-worker,content-security-policy,Html,Image,Service Worker,Content Security Policy,我有一个网站正在从openstreetmap加载图像块。 这些图像来自openstreetmap.org的多个子域,例如: a.tile.openstreetmap.org b.tile.openstreetmap.org c.tile.openstreetmap.org 为了允许这样做,我在我的内容安全策略*.openstreetmap.org中添加了一个img src,这样所有子域都应该是有效的 完整的img src现在显示: img-src https: data: *.openstr

我有一个网站正在从openstreetmap加载图像块。 这些图像来自openstreetmap.org的多个子域,例如:

  • a.tile.openstreetmap.org
  • b.tile.openstreetmap.org
  • c.tile.openstreetmap.org
为了允许这样做,我在我的内容安全策略
*.openstreetmap.org
中添加了一个
img src
,这样所有子域都应该是有效的

完整的
img src
现在显示:

img-src https: data: *.openstreetmap.org;
为了完整性起见,完整内容安全策略为:

default-src 'self'; script-src https: 'unsafe-inline' 'unsafe-eval'; style-src https: 'unsafe-inline'; img-src https: data: *.openstreetmap.org;
当站点第一次加载,并且包含地图的页面被导航到时,这似乎可以按预期工作。实际上有多个包含地图的页面,这两个页面都可以使用

但是,当用户点击“刷新”时,会出现以下错误:

Refused to connect to 'https://a.tile.openstreetmap.org/12/2011/1356.png' because it violates the document's Content Security Policy.
GET https://a.tile.openstreetmap.org/12/2010/1355.png net::ERR_FAILED
如果我打开Chrome开发工具并使用“右键单击刷新”->“空缓存和硬重新加载”选项重新加载页面,那么图像块将再次加载,但只有一次后续的“正常”刷新会产生相同的错误

此站点使用的是“serviceworker.js”,本地服务器页面被缓存,但是
openstreetmap.org
中的平铺没有缓存。然而,我已经手动清空了这个缓存,并验证了缓存版本具有正确的内容安全策略,因此可能存在
serviceworker.js
是一个误称

编辑1

发布这个问题让我进一步调查了
serviceworner.js
。我把它移走了,问题就不存在了。恢复服务人员的工作使问题再次出现。这就是原因

应用程序缓存中没有来自openstreetmap.org的任何内容

编辑2

进一步的调查已经找到了原因,但我还没有找到解决办法。第一次加载是因为我的“serviceworker.js”首先在缓存上运行,然后在网络上运行。因此,第一次加载没有缓存。后续加载有一个缓存,但openstreetmap.org中的图像不在其中

有关章节如下:

self.addEventListener('fetch', function (event) {
    event.respondWith(
        // cache first then network
        // but not for different origin calls, this includes API
        caches.open("my-cache-" + self.sw_version)
            .catch((msg) => { console.log("caches.open(): ", msg); })
            .then(cache => {

                return cache.match(event.request)
                    .catch((msg) => { console.log("cache.match(): ", msg); })
                    .then(response => {

                        return response || fetch(event.request)
                            .catch((msg) => { console.log("fetch(event.request): ", msg); })
                            .then(response => {

                            // if it was from a differnt origin - simply return it
                            if (!event.request.url.match(event.request.referrer))
                                return response;

                            console.log("ServiceWorker.caching: ", event.request.url);
                            cache.put(event.request, response.clone());
                            return response;
                    });
                });
        })
    );
});
服务人员在缓存中找不到
fetch()
请求时发现了问题

fetch(event.request):  TypeError: Failed to fetch
这意味着serviceworker.js中的
fetch()
没有使用正确的内容安全策略,而是使用了请求违反的策略

dev工具的network选项卡为请求/响应显示了这一点

请求

Request URL: https://b.tile.openstreetmap.org/12/2011/1355.png
Referrer Policy: no-referrer-when-downgrade
回应

Origin: https://localhost:9443
Referer: https://localhost:9443/my-app/?
Sec-Fetch-Mode: cors
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36
编辑3

通过显式设置强制
fetch()
使用相同的内容安全策略,允许请求工作。但这是一个黑客补丁,正如它现在在两个地方(整个网站和serviceworker.js中)声明的那样,因此如果有一个“合适的”补丁,甚至只是解释为什么需要这样做,我仍然会感兴趣

编辑4

我今天回到这里是想再尝试一次。 我意识到在检查远程URL时出现了一个问题——我正在将referer URL传递给match函数unscaped,因此它的行为不符合预期。我现在已经纠正了这一点,并移动了一些代码以使它(对我自己)更清晰

现在我遇到了一个奇怪的情况,它报告了相同的错误,但也从openstreetmap加载了瓷砖


任何关于为什么会发生这种情况的建议都将被感激地接受。

强制在每个请求上显式声明标题似乎会导致其他fetch()出现各种问题,因此我不得不将其删除。仍然在寻找解决方案/解释有一点:我有类似的东西,尽管我对软件线程使用相同的内容安全策略。该链接指出,当sw使用fetch()时,它使用connect src,这可能值得一试,尽管对我来说,更改错误的人并没有修复它。
self.addEventListener('fetch', function (event) {

    // https://stackoverflow.com/a/6969486 - escape a string to use in regex
    if (!event.request.url.match(event.request.referrer.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&'))) {
        fetch(event.request)
            .catch((msg) => { console.log("fetch(event.request).remoteorigin: ", { event: event, error: msg }); })
            .then(response => {
                return response;
            });
    }
    else {
        event.respondWith(
            // cache first then network
            // but not for different origin calls, this includes API
            caches.open("crt-scada-" + self.sw_version)
                .catch((msg) => { console.log("caches.open(): ", msg); })
                .then(cache => {
                    return cache.match(event.request)
                        .catch((msg) => { console.log("cache.match(): ", msg); })
                        .then(response => {
                            return response || fetch(event.request)
                                .catch((msg) => { console.log("fetch(event.request).sameorigin: ", { event: event, error: msg }); })
                                .then(response => {
                                    cache.put(event.request, response.clone());
                                    return response;
                                });

                        });
                })
        );
    }
});