CORS v kontextu webu: proč existuje a co řeší
CORS (Cross-Origin Resource Sharing) je mechanismus HTTP, který umožňuje bezpečné sdílení zdrojů mezi různými původy (origins). Opírá se o hlavičky v požadavcích a odpovědích, které prohlížeč respektuje při čtení dat z jiné domény, subdomény, portu nebo protokolu. CORS rozšiřuje tzv. Same-Origin Policy (SOP) tak, aby webové aplikace mohly přistupovat k API a statickým zdrojům napříč doménami, aniž by tím byla ohrožena bezpečnost.
Origin a Same-Origin Policy: základní pojmy
- Origin = kombinace
scheme://host:port(např.https://app.example.com:443). - Same-Origin Policy brání skriptům načteným z jednoho původu číst citlivé odpovědi z jiného původu.
- CORS umožňuje kontrolované prolomení této bariéry prostřednictvím deklarativních hlaviček na straně serveru.
Aktéři a odpovědnosti
- Prohlížeč vynucuje pravidla CORS a v případě jejich porušení zablokuje přístup k odpovědi (JS nedostane tělo, konzole vypíše chybu).
- Server cílového zdroje rozhoduje, komu (kterému původu) a za jakých podmínek poskytne přístup, a to pomocí hlaviček CORS.
- CDN/Proxy může měnit hlavičky, ukládat odpovědi na preflight do mezipaměti a ovlivnit chování (pozor na
Vary).
Typy požadavků: jednoduché, preflight a credentialed
- Jednoduché požadavky (bez preflightu): metody
GET,HEAD,POSTs bezpečnými hlavičkami typu simple (např.Accept,Content-Types hodnotami typuapplication/x-www-form-urlencoded,multipart/form-datanebotext/plain), bez vlastních nestandardních hlaviček. - Preflight: prohlížeč nejprve odešle
OPTIONSs hlavičkamiOrigin,Access-Control-Request-Methoda případněAccess-Control-Request-Headers. Server musí požadavek povolit, jinak se hlavní požadavek neprovede. - Credentialed (s přihlašovacími údaji): pokud klient odesílá cookies/HTTP auth/klientské certifikáty (
fetchscredentials: "include"), server musí odpovědět hlavičkouAccess-Control-Allow-Credentials: truea nesmí použítAccess-Control-Allow-Origin: *; musí uvést konkrétní původ.
Klíčové hlavičky CORS a jejich význam
Origin: automaticky přidávaná klientem; identifikuje původ volajícího.Access-Control-Allow-Origin: odpověď serveru s povoleným původem (konkrétníhttps://example.comnebo*u požadavků bez přihlašovacích údajů).Access-Control-Allow-Methods: metody povolené při preflightu (GET, POST, PUT, DELETE, OPTIONS…).Access-Control-Allow-Headers: hlavičky, které nejsou simple a jsou povolené v hlavním požadavku (např.Authorization, X-Requested-With).Access-Control-Expose-Headers: seznam hlaviček, které lze číst z JS (bez něj jsou viditelné pouze hlavičky z safe list).Access-Control-Allow-Credentials:true, pokud jsou povoleny cookies/přihlašovací údaje.Access-Control-Max-Age: doba, po kterou může prohlížeč ukládat výsledek preflightu do mezipaměti (snížení latence; prohlížeče mají vlastní horní limity).Vary: Origin: mimořádně důležité při použití CDN – odpověď se má lišit podleOrigin. Bez toho riskujete otrávení mezipaměti nebo únik hlaviček.
Životní cyklus preflightu krok za krokem
- JS (např.
fetch) chce odeslatPUTs hlavičkouAuthorization. - Prohlížeč odešle
OPTIONSna stejnou URL s hlavičkouOrigina hlavičkamiAccess-Control-Request-*. - Server odpoví např.
Access-Control-Allow-Origin: https://app.example.com,Access-Control-Allow-Methods: PUT,Access-Control-Allow-Headers: Authorization,Access-Control-Max-Age: 600. - Prohlížeč si výsledek preflightu dočasně zapamatuje a provede hlavní požadavek.
Obvyklé topologie: SPA, API a CDN
- SPA na doméně A volá API na doméně B: na B nastavte, aby podle seznamu povolených původů vracela
Access-Control-Allow-Originpouze pro známé původy a přidalaVary: Origin. - CDN před API: zajistěte, aby CDN respektovala a předávala
Originpůvodnímu serveru; bezpečně ukládejte odpovědi do mezipaměti podleVarya zvažte ukládání preflightů do mezipaměti. - Statické assety (fonty, obrázky, video): pokud se používají napříč doménami (např. fonty), přidejte
Access-Control-Allow-Origina správnýContent-Type.
Konfigurace: návrhové vzory bez bezpečnostních děr
- Reflexe původu pomocí seznamu povolených původů: server zkontroluje
Origin; pokud je na seznamu, vrátíAccess-Control-Allow-Origins danou hodnotou a doplníVary: Origin. Nikdy bez kontroly nereflektujte libovolnýOrigin. - Credentialed API: použijte konkrétní
Access-Control-Allow-Origin(nikoli*) aAccess-Control-Allow-Credentials: true. OmezteAllow-MethodsaAllow-Headersna minimum. - Minimalizace preflightů: upřednostňujte metody a hlavičky typu simple; JSON posílejte jako
text/plainpouze tehdy, pokud to bezpečnostní politika dovoluje a víte, co děláte. Častěji je lepší preflight přijmout a správně jej ukládat do mezipaměti.
Příklady hlaviček pro odpovědi API
Bez přihlašovacích údajů, více domén přes CDN: Access-Control-Allow-Origin: *, Access-Control-Expose-Headers: ETag, Link, Vary: Origin (pokud později přejdete na politiku podle jednotlivých původů).
S přihlašovacími údaji pouze pro app: Access-Control-Allow-Origin: https://app.example.com, Access-Control-Allow-Credentials: true, Access-Control-Expose-Headers: X-RateLimit-Remaining, Vary: Origin.
Odpověď na preflight: Access-Control-Allow-Origin: https://app.example.com, Access-Control-Allow-Methods: GET, POST, Access-Control-Allow-Headers: Authorization, Content-Type, Access-Control-Max-Age: 600, Vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers.
Přesměrování, mezipaměť a CORS
- Přesměrování mohou způsobit selhání CORS, pokud mezilehlý článek odstraní hlavičky nebo změní protokol/hostitele/port. Ideální je odpovídat přímo, bez 302/301, zejména u preflightu.
- Mezipaměť CDN: vždy zvažte použití
VaryproOrigina případně také proAccess-Control-Request-*u preflightu. - ETag a podmíněné požadavky (
If-None-Match) fungují s CORS, ale pouze pokud jsou hlavičky CORS zachovány i při odpovědi 304.
Bezpečnostní souvislosti: CORS ≠ autentizace
- CORS je mechanismus prohlížeče; nenahrazuje autentizaci ani autorizaci. Server musí i nadále ověřovat tokeny, relace a ACL.
- Nikdy nepovolujte
*společně sAllow-Credentials: true. Prohlížeče takovou kombinaci blokují; jde také o bezpečnostní zásadu. - Odlišujte CORS od politik CSP, COOP/COEP/CORP – tyto související mechanismy řeší jiné oblasti (izolaci, možnost načítání, vkládání obsahu z jiného původu).
Vliv na SEO, AIO/AEO a optimalizaci pro LLM
- Indexace a vykreslování: Googlebot se službou Web Rendering Service sice spouští JS, volání API přes CORS však mohou selhat a způsobit neúplný obsah. Důležitá data pro SEO (např. texty produktů, FAQ) raději vykreslujte pomocí SSR/SSG a nezávisle na běhovém volání přes CORS.
- Strukturovaná data: nenačítejte JSON-LD pomocí běhového cross-origin fetch; vložte ho přímo do HTML.
- AIO/AEO (odpovědi asistentů): pokud widgety (HowTo, FAQ, Product) závisejí na médiích z jiného původu (obrázky, video), povolte CORS na doméně s assety, jinak mohou vložené komponenty v SPA zobrazovat stav „broken“.
- Výkon: preflight přidává RTT; při vysokém podílu volání CORS roste TTI a zhoršují se Core Web Vitals. Zvažte slučování volání API, HTTP/2/3, ukládání preflightů do mezipaměti a proxy same-origin.
Diagnostika a testování
- DevTools → Network: filtrujte
OPTIONSa zkontrolujte přítomnost správných hlaviček CORS při preflightu i v hlavní odpovědi. - curl: simulujte preflight např. pomocí
curl -i -X OPTIONS https://api.example.com/resource -H "Origin: https://app.example.com" -H "Access-Control-Request-Method: PUT" -H "Access-Control-Request-Headers: Authorization". - Logy serveru/CDN: zapněte protokolování požadavků
OPTIONS, sledujte zásahy do mezipaměti a její minutí i chování hlavičkyVary. - Monitorování: měřte podíl chyb CORS v JS (obslužná funkce
errorobjektu window) a porovnávejte ho s konverzemi.
Nejčastější chyby a jejich řešení
- „No ‚Access-Control-Allow-Origin‘ header is present“ – server nevrací povolení pro daný původ; přidejte správnou hlavičku
Access-Control-Allow-OriginaVary: Origin. - „The value of the ‚Access-Control-Allow-Origin‘ header contains ‚*‘ when credentials flag is true“ – místo
*použijte konkrétní původ a ponechteAllow-Credentials: true. - Preflight blokovaný odpovědí 301/302 – odpovídejte přímo nebo přesměrujte pouze hlavní požadavek; preflight by měl dostat konečnou odpověď s hlavičkami CORS.
- Chybějící hlavičky při 304 – i odpověď 304 musí obsahovat relevantní hlavičky CORS.
- CDN odstraňuje hlavičky – povolte a předávejte
Origina zachovávejte hlavičky CORS na edge. - Příliš široké Allow-Headers/Methods – zužte seznam na nezbytné hodnoty; tím snížíte útočnou plochu.
Optimalizace výkonu: jak snížit latenci CORS
- Slučujte volání a upřednostňujte
GETpro čitelné zdroje s agresivním nastavením cache-control. - Pro preflight použijte rozumnou hodnotu
Access-Control-Max-Agea zvažte ukládání do mezipaměti CDN. - Přesuňte API pod stejný původ (reverzní proxy,
/apina stejné doméně), pokud je to možné. - Omezte vlastní hlavičky;
Authorizationčasto spouští preflight – zvažte alternativní modely (např. cookie sSameSitepodle potřeby a ochranou proti CSRF), ale vždy s ohledem na bezpečnost.
Specifika cookies a SameSite
- U cookies pro cross-site požadavky bývá nutné nastavení
SameSite=None; Secure. Jinak prohlížeč cookie neodešle, i když CORS povoluje přihlašovací údaje. - Nezapomeňte sladit doménu cookie (
Domain) se způsobem, jakým ji chcete používat napříč subdoménami.
Fonty, obrázky a média napříč doménami
- Webové fonty vyžadují správné hlavičky CORS na doméně s assety (
Access-Control-Allow-Origin), jinak mohou být zablokovány. - U
<img>se obrázek sice načte, ale čtení pixelových dat z canvasu bez CORS vede k jeho znečištění (ochrana soukromí). - Video a audio streamy mohou vyžadovat kompatibilní CORS také pro požadavky
Rangea správné typy MIME.
Integrace do vývojového procesu
- Infrastruktura jako kód: definujte zásady CORS v konfiguraci Nginx/Apache/CloudFront/S3 jako součást repozitáře.
- Testy: přidejte integrační testy, které ověřují přítomnost správných hlaviček v běžných scénářích i při preflightu.
- Observabilita: metriky provozu
OPTIONS, chybovosti a podílu zásahů do mezipaměti preflightů na CDN.
Kontrolní seznam pro bezpečné nasazení CORS
- Máte výslovný seznam povolených původů (včetně zástupných znaků pro subdomény, pokud je skutečně potřebujete).
- Všechny odpovědi (200/4xx/5xx/304) obsahují konzistentní hlavičky CORS.
- Preflight se obejde bez přesměrování a uvádí přesně ty metody a hlavičky, které potřebujete.
- Ve scénářích s přihlašovacími údaji nepoužíváte
*a vracíteVary: Origin. - CDN předává
Origina respektujeVary; preflight se ukládá do mezipaměti v rozumné míře. - DevTools a automatizované testy nehlásí chyby CORS v kritických uživatelských scénářích.
Shrnutí
CORS je nezbytnou součástí moderního webu, která umožňuje bezpečné propojení SPA, API a assetů napříč doménami. Správně nastavené hlavičky, rozumné ukládání preflightů do mezipaměti, důsledná bezpečnostní politika a začlenění kontrol do CI/CD snižují latenci, chrání data a stabilizují vykreslování – což v konečném důsledku prospívá SEO, AIO/AEO i celkové použitelnosti webu.
