Як застосувати кеш попередньої перевірки CORS до цілого домену


78

Я створюю додаток REST, який використовує CORS. Кожен виклик REST відрізняється, і я виявляю, що є значні накладні витрати на отримання передвилітного виклику OPTIONS. Чи є спосіб кешувати та застосувати результат ОПЦІЙ до перевірки, щоб будь-які наступні виклики до того самого домену використовували кешовану відповідь?


1
Додаток до запитання: Якщо кешування попереднього друку перед меншим обсягом неможливе, який найкращий спосіб обмежити кількість запитів перед друком у програмі RESTful?
Роб W

1
Зворотний проксі-сервер, перевіривши nginx, дозволить вам уникнути покарання перед польотом CORS. Просто карта / api -> api.site.com
Дуглас Фергюсон

У статті Вікіпедії про CORS є приємна блок-схема, яка допомогла мені зрозуміти, за яких умов буде здійснено передпольотний дзвінок (і, отже, як їх уникнути).
Трентон,

Відповіді:


104

Попередню перевірку можна застосувати лише до запиту, а не до всього домену. Я поставив те саме питання у списку розсилки, і там були проблеми безпеки. Ось вся нитка: http://lists.w3.org/Archives/Public/public-webapps/2012AprJun/0228.html

Існує кілька речей, які слід врахувати, якщо ви хочете обмежити кількість попередніх перевірок. Перше зауважимо, що браузери на основі WebKit / Blink встановили максимальний кеш перед вильотом 10 хвилин:

https://github.com/WebKit/webkit/blob/master/Source/WebCore/loader/CrossOriginPreflightResultCache.cpp https://chromium.googlesource.com/chromium/blink/+/master/Source/core/loader/CrossOriginultRef .cpp

(Я не впевнений, що це справедливо для інших браузерів). Тож, хоча ви завжди повинні встановлювати заголовок Access-Control-Max-Age, максимальне значення становить 10 хвилин.

Далі зауважте, що неможливо уникнути попередньої перевірки запитів PUT / DELETE. Отже, оновлення / видалення вашого API вимагатиме принаймні одного попереднього вильоту кожні 10 хвилин.

У GET / POST уникайте користувацьких заголовків, якщо це можливо, оскільки вони все ще запускають попередні перевірки. Якщо ваш API повертає JSON, зверніть увагу, що Content-Type 'application / json' також ініціює попередню перевірку.

Якщо ви готові відхилитись від того, наскільки "API для вашого відпочинку", є ще кілька речей, які ви можете спробувати. Одним з них є використання типу вмісту, який не потребує попередньої перевірки, наприклад, "text / plain" Спеціальні заголовки завжди запускають попередні перельоти, тому, якщо у вас є будь-які спеціальні заголовки, ви можете перемістити їх у параметри запиту. На крайньому кінці ви можете використовувати протокол, такий як JSON-RPC, де всі запити робляться до однієї кінцевої точки.

Чесно кажучи, через обмеження кеш-пам’яті браузера на 10 хвилин та URL-адреси ресурсів REST, кеш попереднього друку досить марний. Дуже мало ви можете зробити, щоб обмежити попередні вильоти протягом тривалого запуску програми. Я сподіваюся, що автори специфікації CORS спробують вирішити цю проблему в майбутньому.


3
@uglymunky Я уточню цей розділ. Ключ кешу попередньої перевірки базується на парі джерело / URL, де url - це повна URL-адреса запиту. Я мав на увазі, що якщо у вас є спеціальний заголовок, він завжди викликатиме попередній політ, навіть на запит GET. Однак, якщо ви перемістите цей користувальницький заголовок у параметр запиту, не буде попередньої перевірки для запитів GET / POST.
monsur

2
@monsur Привіт трохи запізнився на вечірку, але мені було цікаво, чи можете ви порадити .. Зараз я передаю заголовок авторизації (наприклад, "Basic [base64 закодований рядок]") з усіма запитами до мого API. Попередні запити в основному заважають роботі програми. Якби я перейшов до системи авторизації на основі маркера (з маркером як параметром QS в URL-адресі) і повністю позбувся користувацьких заголовків, чи був би це спосіб уникнути страшних запитів OPTIONS для GET та POST (I ' m добре з тим, що є дещо для PUT та DELETE)?
адаам

5
@adaam, що має зробити трюк. Я щойно закінчив тестування у Firefox та Chrome, щоб краще зрозуміти поведінку, і можу поділитися цим: якщо ваш спеціальний заголовок присутній, браузер ініціює запит OPTIONS, якщо той Access-Control-Max-Ageне присутній і точно таку ж URL-адресу не бачив браузер раніше, і це протягом періоду, визначеного, Access-Control-Max-Ageі браузер, про який йде мова, не скорочує значення (Webkit, Firefox). Якщо ви позбудетеся користувацьких заголовків і перемістите їх у URL-адресу, браузер не надішле запит OPTIONS. Перемоги!
mikegradek

2
Мені подобається, як вони просто перестали відповідати на ваші електронні листи. Все це зайве виклик, для одного краю справи.
Ребс

3
У вашій відповіді обмеження типу вмісту стосується лише надсилання даних, а не їх отримання, тому немає проблем із поверненням серверами довільних заголовків типу вмісту.
letmaik

6

Спробуйте використовувати xDomain

Мені було досить просто налаштувати використання angular або jQuery. На своєму сервері додатків додайте proxy.html, як зазначено в довідці за посиланням нижче. Додайте кілька тегів, що посилаються на файли js на вашому "клієнті" та альта, більше немає попередніх польотів. Це обертається в iframe, щоб уникнути необхідності перевірки корсів.

https://github.com/jpillora/xdomain


1

Один із способів полягає в тому, що ви можете направити всі свої виклики API на той самий домен, що і ваш інтерфейс. Налаштуйте nginx на зовнішньому сервері для переадресації лише викликів API на сервер API. Це призведе до видалення всіх передпольотних дзвінків.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.