В настоящее время у меня есть:
<script rel = "preload" as = "script" src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js" integrity = "sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8 = " crossorigin = "anonymous"></script>
И у меня настроено правило CSP:
add_header Content-Security-Policy: "default-src 'self' https:; script-src 'self' 'sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=';";
Но я получаю следующую ошибку в консоли Chrome:
Refused to load the script 'https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js' because it violates the following Content Security Policy directive: "script-src 'self' 'sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8='". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.
Как я могу это исправить? Нужно ли явно включать underscore-min.js (и любые дополнительные «подключенные» зависимости) в мой html-документ? Могу ли я внести в белый список все скрипты с cdnjs.cloudflare.com вместо этого?
Спасибо!
Редактировать: Вот скриншот ошибки консоли, которая, похоже, происходит в файле jquery.min.js.
Кроме того, не уверен, что это актуально, но я получаю Unrecognized Content-Security-Policy directive ':' с https: частью правила, которое я нашел в какой-то статье Google devtools или где-то еще. Но я предполагаю, что двоеточие недопустимо для правил CSP в nginx?
Редактировать 2: Итак, после дополнительных исследований и экспериментов я узнал больше о CSP, и из того, что я прочитал, я могу столкнуться только с проблемой FireFox. Теперь я получаю следующую ошибку, даже если правило CSP не определено:
Content Security Policy: Ignoring “'unsafe-inline'” within script-src: ‘strict-dynamic’ specified
Самое близкое к рабочему решению, которое я нашел, - это внести в белый список все домены, с которых мне нужно загрузиться:
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com https://stackpath.bootstrapcdn.com https://ssl.google-analytics.com https://www.google.com https://www.gstatic.com; img-src 'self' data: https://ssl.google-analytics.com; style-src 'self' 'unsafe-inline' https://stackpath.bootstrapcdn.com https://fonts.googleapis.com; font-src 'self' https://themes.googleusercontent.com; frame-src https://www.google.com; object-src 'none';";
Да, я знаю, что у меня есть 'unsafe-inline' как в моих правилах script-src, так и в style-src, в попытке заставить сайт работать в FireFox. Если веб-сайт больше не отображается или не работает должным образом в FireFox из-за ошибки в реализации CSP FF (требующей подтверждения), то цель CSP является вторичной и, следовательно, неактуальной (пока эта ошибка, ожидающая подтверждения, не будет исправлена).
Поскольку на момент написания статьи информация о CSP кажется относительно ограниченной, может ли кто-нибудь пролить свет на то, почему FireFox, по-видимому, принудительно включает 'strict-dynamic' в правила CSP, несмотря на то, что его нет нигде в определении правила? Подразумевается ли это или иным образом дополняется интерпретацией FireFox (части) моего текущего правила CSP?
Спасибо за помощь.
А для всех, кто читает CSP, загляните в https://cspvalidator.org/, который может помочь вам отладить свои собственные правила CSP. Я знаю, что это помогло мне!
Пробовали ли вы другой CDN jQuery? Может быть, попробовать прямо из jQuery? code.jquery.com
Неа. В противном случае покажите мне в источнике. Это может быть часть подключаемого модуля или что-то еще, что вы загружаете, но загружается не jQuery.
@RandyCasburn Я добавил скриншот ошибки консоли к своему вопросу.
Итак, перейдите к источник в новой вкладке/окне, нажмите CTRL-F и найдите https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js. Это не там. Если вы мне не верите, зайдите сами на сайт jQuery, посмотрите неминифицированный исходный код. Единственная зависимость — это движок Sizzle (который представляет собой полностью автономную библиотеку). Просто что-то не сходится.
Я могу подтвердить то, что вы говорите, но это не объясняет, почему jquery.min.js является исходным файлом ошибки консоли. Есть ли у вас какое-либо представление о том, почему это так на скриншоте, который я загрузил?
Вероятно, это Rocket Loader — отключите его на CloudFlare и посмотрите, решится ли проблема сама собой.
Не знал, что это так, но отрицательный, я проверил, что он отключен для домена, над которым я работаю.
@Chad - все ответы закончились. без полного понимания серверной среды, какие плагины или расширения браузера используются и т. д. и т. д. У меня нет догадок.
Я решил эту проблему, и это потому, что FireFox плохо работает со ссылками rel = "preload" и элементами скрипта. Я опубликую более подробный ответ на этот вопрос в ближайшее время.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Для тех, кто не может найти решение, я выделил проблему, связанную с тем, как FireFox в настоящее время обрабатывает атрибут rel = "preload". Мягко говоря, это не очень хорошо, и я полагаю, что то же самое с Edge.
TL;DR: Не используйте rel = "preload" до тех пор, пока он не будет унифицирован во всех основных браузерах. Кроме того, мой вопрос касался использования jQuery из CDN CloudFlare, а цель CDN состоит в том, чтобы посетители не могли (бессмысленно) загружать один и тот же контент снова и снова. Другими словами, rel = "preload" не только ведет себя по-разному между флагманскими браузерами, но и является излишним, поскольку суть CDN заключается в том, что посетитель будет иметь уже скачал данный файл(ы) при посещении предыдущих веб-сайтов, которые также используют тот же файл из той же CDN.
кликните сюда, чтобы просмотреть обзор текущей поддержки браузерами rel = "preload".
Результаты
Chrome и, возможно, другие браузеры обрабатывают ресурсы для предварительной загрузки (более) правильно, хотя в целом нам не хватает инструментов и документации о том, как приступить к работе с CSP правильно, и, надеюсь, этот ответ даст некоторое представление другим, которые относительно новичок в CSP, как и я.
При устранении неполадок в правилах CSP я обнаружил ряд проблем. Одним из них является то, что соединение атрибута as с подсказкой типа может работать против вас с текущими реализациями браузера CSP. Например, я пытался загрузить шрифт Google с as = "font", который, если я правильно помню, вызывал дополнительные головные боли, пока вместо него не был установлен as = "style". Что я понял (пожалуйста, отредактируйте этот ответ, если вы можете подтвердить обратное), так это то, что связанный ресурс действительно является таблицей стилей, а не файлом шрифта.
Еще один странный момент, с которым я столкнулся, заключается в том, что когда вы предварительно загружаете ресурс, вы должны фактически «инициализировать» данный ресурс после его загрузки. Таким образом, вы можете либо клонировать элемент <link> с желаемым rel = "stylesheet/script/etc" (что прямо противоречит принципу DRY), либо прикрепить событие загрузки к элементу <link> (что не противоречит DRY, но делает кажется довольно архаичным). .На дворе 2019 год! Почему наш браузер не может сделать это за нас? Или, возможно, мы могли бы добавить в браузер поддержку чего-то вроде атрибута append = "true", который бы автоматически и изящно обрабатывал это за нас).
Я уберу следующий абзац и фрагмент кода из следующий проект GitHub, чтобы лучше объяснить «решение» onload (которое нет работает в FireFox из-за ошибок CSP, которые я задокументировал в этом вопросе):
In browsers that support it, the
rel=preloadattribute will cause the browser to fetch the stylesheet, but it will not apply the CSS once it is loaded (it merely fetches it). To address this, we recommend using an onload attribute on the link that will apply the CSS when it finishes loading.
<link rel = "preload" href = "path/to/mystylesheet.css" as = "style" onload = "this.rel='stylesheet'">
Как уже говорилось, это кажется очень архаичным. Нам не нужно выбирать между избыточным и архаичным кодом.
Я упомянул, что Chrome, похоже, имеет лучшую производственную реализацию CSP, но есть еще над чем поработать. Кроме того, причина, по которой я оказался в этой дикой охоте на ведьм, заключалась (естественно) в том, что я работал над улучшением скорости и производительности веб-сайта, поэтому я использовал инструмент Lightouse / Audit Chrome Inspector. Что ж, из всех проведенных мной тестов выяснилось, что ресурсы, которые, как мы должны ожидать, уже кэшированы на клиентском компьютере (Bootstrap, jQuery, Google Fonts и т. д.), очищаются перед выполнением аудита и повторно загружаются для учета. в сформированном отчете. Это нормально (я понимаю, что это желаемое поведение); однако, если бы у нас в качестве разработчиков был радиобокс для отменить очистки общих ресурсов через CDN при выполнении наших аудитов, я полагаю, что разработчик получил бы дополнительный уровень понимания производительности своего веб-сайта. Или хотя бы дифференцировать в отчете, чтобы точно показать, сколько времени было потрачено на загрузку и инициализацию связанных ресурсов.
Эти зависимости не ограничиваются rel = "preload". При устранении неполадок я в некоторых случаях пробовал использовать альтернативные значения, такие как rel = "connect", для первого ресурса, на который я ссылался через CDN CloudFlare. При проведении исследований по теме я нашел следующая статья с такой информацией:
The final resource hint we want to talk about is preconnect. Preconnect allows the browser to setup early connections before an HTTP request is actually sent to the server. This includes DNS lookups, TLS negotiations, TCP handshakes. This in turn eliminates roundtrip latency and saves time for users.
“Preconnect is an important tool in your optimization toolbox… it can eliminate many costly roundtrips from your request path - in some cases reducing the request latency by hundreds and even thousands of milliseconds. - Ilya Grigorik”
Но, что неудивительно, preconnect работает так же в браузерах, которые не поддерживают preload. И легко все это перепутать, если вы думаете, что проблема связана с вашими правилами CSP, а не с вашей разметкой.
Я надеюсь, что это дает некоторый контекст и помогает смягчить некоторое разочарование в отношении CSP и текущей (отсутствие) его надлежащей реализации в основных браузерах на сегодняшний день. Пожалуйста, не стесняйтесь редактировать этот ответ, чтобы улучшить его или добавить больше контекста и информации в интересах наших коллег-разработчиков.
Что вы подразумеваете под "суб-включением"? Как вы запрашиваете файл, отличный от jQuery?