В предишни статии разгледахме основите на изграждането на RESTful API-та с FastAPI и изследвахме ползите от асинхронното програмиране с ASGI. Днес ще се съсредоточим върху един критичен аспект на съвременните уеб API-та – Cross-Origin Resource Sharing (CORS). Ще обясним какво е CORS, защо е важно и как да го конфигурираме правилно във вашите FastAPI приложения, за да осигурите сигурност и гъвкавост. Да започваме!
Какво е CORS?
CORS (Cross-Origin Resource Sharing) е механизъм за сигурност, който позволява на уеб страница от един домейн да прави заявки към API от друг домейн. По подразбиране повечето браузъри прилагат Same-Origin Policy (SOP), което забранява JavaScript код от една страница да прави заявки към различен домейн, порт или протокол. Това е важна мярка за сигурност, която предотвратява злонамерени сценарии като Cross-Site Request Forgery (CSRF) атаки.
Въпреки това, в много модерни уеб приложения API бекендът и фронтендът често се хостват на различни домейни. Например, вашето API може да е на https://api.example.com, докато фронтендът е на https://app.example.com. В такива случаи CORS позволява контролиран и сигурен начин браузърът да разреши заявки между различни източници.
Как работи CORS?
CORS използва допълнителни HTTP заглавия, за да даде на браузъра разрешение да достъпва ресурси от различен домейн. Ето как изглежда основният поток:
Браузърът изпраща OPTIONS заявка (наречена preflight request) към API сървъра, питайки дали е разрешено да направи действителната заявка. API сървърът отговаря с Access-Control-* заглавия, указвайки кои домейни, методи и заглавия са разрешени. Ако preflight заявката е успешна, браузърът изпраща действителната заявка (GET, POST и т.н.) с Origin заглавка, указваща произхода на заявката. API сървърът проверява Origin заглавката и ако съвпада с разрешените домейни, изпраща отговор с Access-Control-Allow-Origin заглавка. Браузърът получава отговора и ако Access-Control-Allow-Origin съответства на текущия домейн, той позволява на JavaScript кода да получи достъп до отговора. Тези стъпки гарантират, че браузърът и сървърът „се договарят“ за достъп между източници и предотвратяват неоторизирани заявки.
CORS във FastAPI
FastAPI предоставя вграден middleware за лесно и гъвкаво управление на CORS конфигурацията. Ето как да го използвате:
1. Инсталирайте fastapi и uvicorn:
pip install fastapi uvicorn
2. Създайте FastAPI приложение и включете CORSMiddleware:
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
origins = [
"http://localhost.tiangolo.com",
"https://localhost.tiangolo.com",
"http://localhost",
"http://localhost:8080",
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/")
async def main():
return {"message": "Hello World"}
Тук дефинираме списък от разрешени origins и го подаваме към CORSMiddleware. Middleware ще обработва входящите заявки и автоматично ще добавя необходимите CORS заглавия към отговорите.
3. Стартирайте сървъра:
uvicorn main:app --reload
Сега вашето API ще отговаря на preflight заявки и ще разрешава заявки от посочените домейни.
Конфигуриране на CORS
FastAPI предоставя няколко параметъра за фино настройване на поведението на CORS:
allow_origins
: Списък от разрешени домейни. Можете да използвате["*"]
, за да разрешите всички домейни (не се препоръчва за продукция).allow_methods
: Списък от разрешени HTTP методи. По подразбиране се разрешават самоGET
.allow_headers
: Списък от разрешени заглавия. По подразбиране са само няколко основни.allow_credentials
: Булев флаг, указващ дали са разрешени кредитирани заявки (т.е. с бисквитки).expose_headers
: Заглавия, които браузърът ще направи достъпни за клиентския код.max_age
: Как дълго да се кешира preflight отговора (по подразбиране 600 секунди).
Обикновено ще искате да настроите тези параметри според нуждите на вашето приложение – разрешете само необходимите домейни, методи и заглавия и избягвайте прекалено разхлабени конфигурации в продукция.
Примери за CORS конфигурация
Ето няколко често срещани сценарии и как да ги реализирате с FastAPI CORS middleware:
1. Разрешаване на всички произходи (подходящо само за разработка/тестване):
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
2. Разрешаване на само специфичен домейн:
origins = ["https://example.com"]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["GET", "POST"],
allow_headers=["*"],
)
3. Разрешаване на множество домейни с поддомейни:
origins = [
"https://*.example.com",
"https://example.org",
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["Content-Type", "Authorization"],
)
4. Селективно разрешаване на CORS за специфични route-ве:
@app.get("/public")
async def public_endpoint():
return {"message": "Publicly accessible"}
@app.get("/private", response_class=PlainTextResponse)
async def private_endpoint():
return "Only accessible from specific origins"
origins = ["https://example.com"]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
expose_headers=["X-Custom-Header"],
max_age=3600,
)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["GET"],
allow_headers=["*"],
expose_headers=["X-Custom-Header"],
max_age=3600,
route_settings=[
{"path": "/public", "allow_origins": ["*"], "allow_methods": ["GET"]},
],
)
Тук дефинираме две отделни CORS конфигурации – една за частните route-ве, ограничена до специфичен домейн, и една за публичните route-ве, достъпна от всички домейни. Използваме параметъра route_settings
, за да зададем специфична конфигурация за /public
route-а.
Тези примери илюстрират само някои от възможните CORS конфигурации. Винаги можете да промените настройките според конкретните изисквания на вашето приложение.
Най-добри практики за CORS
Ето няколко съвета за сигурна и ефективна конфигурация на CORS във вашите FastAPI приложения:
- Разрешавайте само необходимите домейни: Избягвайте използването на
allow_origins=["*"]
в продукция, освен ако API-то ви не е наистина публично. Вместо това изброявайте изрично разрешените домейни. - Ограничете разрешените методи и заглавия: Разрешавайте само HTTP методите и заглавията, които вашето API действително използва. Това минимизира повърхността за атака.
- Преценете дали ви трябват кредитирани заявки: Ако вашето API не разчита на бисквитки или други кредитирани информации, изключете
allow_credentials
за допълнителна сигурност. - Задайте подходящо
max_age
: Задаването на по-висока стойност наmax_age
може да подобри производителността, като намали броя на preflight заявките, но също така може да задържи застарели CORS политики в кеша на браузъра. - Тествайте конфигурацията на CORS: Уверете се, че вашето API правилно обработва preflight заявки и включва правилните CORS заглавия в отговорите. Инструменти като cURL или Postman могат да помогнат за тестването.
- Наблюдавайте и записвайте CORS заявките: Включете CORS заявките в логовете на вашето приложение и наблюдавайте за неуспешни заявки или необичайни модели. Това може да ви помогне да идентифицирате потенциални проблеми със сигурността или грешни конфигурации.
- Имайте предвид CORS при кеширане и CDN: Ако използвате кеширане или CDN, уверете се, че CORS заглавията се обработват правилно и не се кешират неподходящо.
Тези най-добри практики могат да ви помогнат да изградите сигурни и надеждни API, като същевременно позволявате необходимия контролиран достъп между произходи.
Заключение
В тази статия изследвахме критичната роля на CORS в модерните уеб приложения и как да го конфигурираме ефективно във FastAPI. Разбрахме как CORS позволява сигурен достъп между произходи, като същевременно предпазва от неоторизирани заявки между сайтове.
Видяхме как да използваме FastAPI’s CORSMiddleware за лесно добавяне на CORS поддръжка към вашите API маршрути и как да персонализирате конфигурацията според нуждите на вашето приложение. Обсъдихме също някои най-добри практики за сигурни и ефективни CORS политики.
С правилната CORS конфигурация вашите FastAPI приложения могат да обслужват множество клиенти по сигурен и контролиран начин, позволявайки безпроблемна интеграция между фронтенд и бекенд, дори между различни домейни.
Така че следващия път, когато създавате API с FastAPI, не забравяйте да обърнете внимание на CORS. Малко планиране и конфигуриране отиват дълъг път към изграждането на сигурни и гъвкави API-та, които могат да обслужват широк спектър от клиенти.
Допълнителни ресурси:
- Документация на FastAPI за CORSMiddleware: https://fastapi.tiangolo.com/tutorial/cors/
- MDN Web Docs за CORS: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS