Коли веб‑додаток (фронтенд) хоче звернутися до вашого API (бекенд), який знаходиться на іншому домені, це вважається міждоменним запитом. Наприклад, frontend живе на https://app.example.com, а backend — на https://api.example.com. Браузер, ніби параноїдальний охоронець, відмовляється виконувати такі запити, щоб захистити користувача від підступного сценарію «злий сайт вкрав особисті дані».
CORS — це механізм, який дозволяє браузерам дізнатися, що запити між доменами безпечні та дозволені. Це як список гостей на вечірці; браузер спочатку питає: «Можна цьому домену зайти?» І якщо конфігурація CORS каже «так», запит пропускається.
Концепція дозволених міждоменних запитів
Міждоменні запити варто дозволяти тільки для довірених джерел. Наприклад:
- Ваші фронтенд‑додатки, розміщені на конкретних доменах.
- Дозвіл API для третіх сторін з обмеженням по конкретних методах.
Дозвіл усіх джерел (*) — погана практика, якщо ви не розробляєте публічний API без авторизації, який дозволяє доступ усім підряд. Це рівносильно стояти при вході до замку і кричати: «Пускаю всіх!»
Коли забороняти міждоменні запити?
Якщо ваш API:
- Містить конфіденційні дані.
- Не призначений для взаємодії з зовнішніми системами.
- Буде використовуватися тільки внутрішніми сервісами (наприклад, вашим фронтендом).
У таких випадках жорсткі обмеження на джерела (список дозволених доменів) — це must‑have.
Управління джерелами запитів
FastAPI надає простий і зручний спосіб регулювати, які джерела можуть звертатися до вашого API. Для цього ми використовуємо CORSMiddleware, який можна легко підключити до вашого додатка.
Почнемо з базового прикладу, де ми дозволяємо доступ тільки з одного домену — нашого фронтенду:
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
# Дозволені домени
origins = [
"https://app.example.com"
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins, # Вказуємо дозволені джерела
allow_credentials=True, # Дозволити передачу cookies і авторизації
allow_methods=["GET", "POST"], # Вказуємо дозволені методи
allow_headers=["*"], # Дозволяємо будь-які заголовки
)
@app.get("/")
def read_root():
return {"message": "Hello, World!"}
Тут:
allow_origins— список доменів, які можуть звертатися до вашого API.allow_credentials=Trueкаже браузеру, що ми дозволяємо відправляти cookie (наприклад, для сесій).allow_methodsобмежує HTTP‑методи, які можуть використовуватися крос‑доменно.
Тепер тільки запити з адреси https://app.example.com зможуть отримати доступ до нашого API.
Дозвіл кількох джерел
А що, якщо у вас є два фронтенди, які працюють з одним API? Наприклад, звичайний веб‑додаток і мобільна версія. Просто додайте обидва домени в origins:
origins = [
"https://app.example.com",
"https://mobile.example.com"
]
Браузер буде перевіряти запит по цьому списку і дозволяти тільки ті, що співпадають.
Використання wildcard (*)
Ви можете дозволити доступ з будь‑якого джерела, встановивши allow_origins=["*"]. Проте це безпечно лише в випадках, коли:
- Ваш API повністю публічний.
- Дані, що надаються API, не потребують авторизації.
Приклад:
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["GET", "POST"],
allow_headers=["*"],
)
Але пам'ятайте, що дозвіл усіх джерел — це відчиняти двері хакерам. Краще уникати цього на production.
Визначення допустимих HTTP‑методів
CORS дозволяє обмежувати HTTP‑методи, які можуть використовуватися для міждоменних запитів. Наприклад, якщо ви хочете, щоб тільки GET запити були дозволені:
app.add_middleware(
CORSMiddleware,
allow_origins=["https://app.example.com"],
allow_methods=["GET"], # Тільки GET‑запити
allow_headers=["*"],
)
Інші методи, такі як POST, PUT або DELETE, будуть заблоковані.
Управління заголовками запитів
Іноді вашому фронтенду потрібно відправити кастомний заголовок, наприклад, Authorization, щоб передати токен. У таких випадках це потрібно явно вказати в allow_headers:
app.add_middleware(
CORSMiddleware,
allow_origins=["https://app.example.com"],
allow_methods=["GET", "POST"],
allow_headers=["Authorization", "Content-Type"],
)
Якщо дозволити всі заголовки (allow_headers=["*"]), браузер із задоволенням пропускатиме будь‑які заголовки, але це може призвести до несанкціонованого доступу.
Управління терміном дії preflight‑запитів
Браузери використовують попередні запити (preflight) для перевірки політики CORS перед основним запитом. Щоб зменшити кількість таких запитів, можна налаштувати їхній термін дії (в секундах) за допомогою max_age:
app.add_middleware(
CORSMiddleware,
allow_origins=["https://app.example.com"],
allow_methods=["GET", "POST"],
max_age=3600, # 1 година
)
Це буде корисно для підвищення продуктивності, особливо коли фронтенд інтенсивно взаємодіє з вашим API.
Практичні приклади налаштування міждоменних запитів
Приклад 1: Дозвіл тільки для production
Для забезпечення безпеки ви можете дозволити запити тільки з домену production:
origins = [
"https://myproductionapp.com"
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_methods=["GET", "POST", "DELETE"],
allow_headers=["Authorization"],
allow_credentials=True,
)
Приклад 2: Дозвіл для development і production
Під час розробки вам, ймовірно, знадобиться доступ для localhost:
origins = [
"http://localhost:3000", # React dev server
"https://myproductionapp.com"
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_methods=["*"], # Усі методи
allow_headers=["*"],
allow_credentials=True,
)
Підсумкові думки про міждоменні запити
Налаштування дозволених джерел і методів у CORS — це баланс між безпекою і зручністю. Налаштовуючи CORS для вашого FastAPI‑додатка, завжди думайте про те, хто може звертатися до вашого API і навіщо. Надмірні дозволи — це шлях до проблем. Краще трохи ускладнити собі розробку, ніж потім боротися з витоком даних.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ