CORS - mechanizm i znaczenie
This content is not available in your language yet.
Wprowadzenie
Dział zatytułowany „Wprowadzenie”CORS (Cross-Origin Resource Sharing) to mechanizm bezpieczeństwa implementowany przez przegladarki, który kontroluje, jakie zasoby z jednej domeny (origin) mogą być używane przez strony z innej domeny. Jest to rozszerzenie restrykcyjnej polityki Same-Origin Policy, umozliwiajace kontrolowane współdzielenie zasobow miedzy domenami.
Zrozumienie CORS jest niezbedne dla każdego programisty webowego, ponieważ błędy CORS sa jednym z najczestszych problemow przy integracji frontend-backend.
Kluczowe pojecia
Dział zatytułowany „Kluczowe pojecia”Origin (Źródło)
Dział zatytułowany „Origin (Źródło)”Origin składa się z trzech elementow:
- Protokół (scheme):
http://lubhttps:// - Host (domena):
example.com - Port:
:3000(domyslnie 80 dla HTTP, 443 dla HTTPS)
https://example.com:443 │ │ │ │ │ └── Port │ └─────────── Host └───────────────────── ProtokółTe same origin:
https://example.com/page1ihttps://example.com/page2(ta sama)https://example.comihttps://example.com:443(ta sama - domyslny port)
Różne origin:
http://example.comvshttps://example.com(różny protokół)https://example.comvshttps://api.example.com(różny host)https://example.comvshttps://example.com:3000(różny port)
Same-Origin Policy (SOP)
Dział zatytułowany „Same-Origin Policy (SOP)”Same-Origin Policy to fundamentalna zasada bezpieczeństwa przegladarek, która blokuje skryptom dostep do zasobow z innego origin. Chroni przed atakami typu:
- CSRF (Cross-Site Request Forgery)
- Kradziez danych z innych stron
- Session hijacking
Bez SOP złośliwa strona mogłaby wysyłać zadania do banku użytkownika i kraść dane.
CORS jako rozszerzenie SOP
Dział zatytułowany „CORS jako rozszerzenie SOP”CORS pozwala serwerowi explicite zezwolic na dostep z innych origin poprzez specjalne nagłówki HTTP. To serwer decyduje, kto może się z nim komunikowac.
Jak to działa?
Dział zatytułowany „Jak to działa?”Proste zadania (Simple Requests)
Dział zatytułowany „Proste zadania (Simple Requests)”Nie wymagaja preflight, jeśli spełniają warunki:
- Metoda:
GET,HEAD,POST - Nagłówki: tylko standardowe (Accept, Content-Type z ograniczeniami)
- Content-Type:
text/plain,multipart/form-data,application/x-www-form-urlencoded
┌────────────────┐ ┌────────────────┐│ Frontend │ │ Backend ││ example.com │ │ api.example.com│└───────┬────────┘ └───────┬────────┘ │ │ │ GET /users │ │ Origin: https://example.com │ │ ─────────────────────────────────────>│ │ │ │ 200 OK │ │ Access-Control-Allow-Origin: * │ │ {users: [...]} │ │ <─────────────────────────────────────│Preflight Request (OPTIONS)
Dział zatytułowany „Preflight Request (OPTIONS)”Wymagany dla “złożonych” żądań:
- Metody inne niz GET/HEAD/POST
- Niestandardowe nagłówki
- Content-Type:
application/json
- Przegladarka wysyła OPTIONS - pyta serwer o pozwolenie
- Serwer odpowiada nagłówkami CORS - mowi, co jest dozwolone
- Przegladarka analizuje odpowiedz - czy zadanie jest dozwolone?
- Jeśli tak - wysyła właściwe zadanie - POST/PUT/DELETE itd.
┌────────────────┐ ┌────────────────┐│ Frontend │ │ Backend │└───────┬────────┘ └───────┬────────┘ │ │ │ OPTIONS /users (preflight) │ │ Origin: https://example.com │ │ Access-Control-Request-Method: POST │ │ Access-Control-Request-Headers: Content-Type │ ─────────────────────────────────────>│ │ │ │ 204 No Content │ │ Access-Control-Allow-Origin: https://example.com │ Access-Control-Allow-Methods: POST, GET │ Access-Control-Allow-Headers: Content-Type │ <─────────────────────────────────────│ │ │ │ POST /users (właściwe zadanie) │ │ Origin: https://example.com │ │ Content-Type: application/json │ │ ─────────────────────────────────────>│ │ │ │ 201 Created │ │ Access-Control-Allow-Origin: https://example.com │ <─────────────────────────────────────│Nagłówki CORS
Dział zatytułowany „Nagłówki CORS”Nagłówki odpowiedzi serwera
Dział zatytułowany „Nagłówki odpowiedzi serwera”| Nagłówek | Opis | Przykład |
|---|---|---|
Access-Control-Allow-Origin | Dozwolone origin | https://example.com lub * |
Access-Control-Allow-Methods | Dozwolone metody HTTP | GET, POST, PUT, DELETE |
Access-Control-Allow-Headers | Dozwolone nagłówki zadania | Content-Type, Authorization |
Access-Control-Allow-Credentials | Czy cookies sa dozwolone | true |
Access-Control-Max-Age | Cache preflight (sekundy) | 86400 |
Access-Control-Expose-Headers | Nagłówki widoczne dla JS | X-Total-Count |
Nagłówki zadania (preflight)
Dział zatytułowany „Nagłówki zadania (preflight)”| Nagłówek | Opis |
|---|---|
Origin | Origin strony wysyłającej zadanie |
Access-Control-Request-Method | Metoda planowanego zadania |
Access-Control-Request-Headers | Niestandardowe nagłówki |
Przykłady w kodzie
Dział zatytułowany „Przykłady w kodzie”Błąd CORS w konsoli przegladarki
Dział zatytułowany „Błąd CORS w konsoli przegladarki”Access to XMLHttpRequest at 'https://api.example.com/users'from origin 'https://example.com' has been blocked by CORS policy:No 'Access-Control-Allow-Origin' header is present on the requested resource.Konfiguracja CORS w Express.js
Dział zatytułowany „Konfiguracja CORS w Express.js”import express from 'express';import cors from 'cors';
const app = express();
// Prosta konfiguracja - zezwol wszystkimapp.use(cors());
// Lub szczegółowa konfiguracjaapp.use(cors({ origin: ['https://example.com', 'https://app.example.com'], methods: ['GET', 'POST', 'PUT', 'DELETE'], allowedHeaders: ['Content-Type', 'Authorization'], credentials: true, // Zezwol na cookies maxAge: 86400 // Cache preflight na 24h}));
// Dynamiczne origin (np. z bazy danych)app.use(cors({ origin: (origin, callback) => { const allowedOrigins = ['https://example.com', 'https://app.example.com']; if (!origin || allowedOrigins.includes(origin)) { callback(null, true); } else { callback(new Error('Niedozwolone przez CORS')); } }}));Konfiguracja CORS w NestJS
Dział zatytułowany „Konfiguracja CORS w NestJS”import { NestFactory } from '@nestjs/core';import { AppModule } from './app.module';
async function bootstrap() { const app = await NestFactory.create(AppModule);
app.enableCors({ origin: process.env.ALLOWED_ORIGINS?.split(',') || '*', methods: 'GET,HEAD,PUT,PATCH,POST,DELETE', credentials: true, });
await app.listen(3000);}bootstrap();Przykład odpowiedzi z nagłówkami CORS
Dział zatytułowany „Przykład odpowiedzi z nagłówkami CORS”HTTP/1.1 200 OKAccess-Control-Allow-Origin: https://example.comAccess-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONSAccess-Control-Allow-Headers: Content-Type, AuthorizationAccess-Control-Allow-Credentials: trueAccess-Control-Max-Age: 86400Content-Type: application/json
{"users": [...]}Najczestsze błędy
Dział zatytułowany „Najczestsze błędy”Dlaczego przegladarka blokuje zadanie?
Dział zatytułowany „Dlaczego przegladarka blokuje zadanie?”- JavaScript wykonuje fetch/XMLHttpRequest do innego origin
- Przegladarka dodaje nagłówek Origin automatycznie
- Przegladarka wysyła zadanie (lub preflight)
- Serwer odpowiada (z nagłówkami CORS lub bez)
- Przegladarka sprawdza nagłówki - czy origin jest dozwolony?
- Jeśli nie - blokuje dostep do odpowiedzi dla JavaScript
CORS a bezpieczeństwo
Dział zatytułowany „CORS a bezpieczeństwo”CORS chroni użytkownika przegladarki, nie serwer:
- Uniemozliwia złośliwym stronom odczyt danych z innych domen
- Nie zastepuje autoryzacji - API musi weryfikowac tokeny/sesje
- Może być obejscie przez proxy serwer (brak przegladarki = brak CORS)
Podsumowanie
Dział zatytułowany „Podsumowanie”- CORS rozszerza Same-Origin Policy o kontrolowane współdzielenie zasobow
- Origin = protokół + host + port - różnica w dowolnym elemencie = cross-origin
- Preflight (OPTIONS) jest wymagany dla złożonych żądań
- Nagłówki CORS ustawia serwer - to on decyduje, kto ma dostep
- Przegladarka egzekwuje CORS - serwer tylko deklaruje polityke
- CORS nie zastepuje autoryzacji - to mechanizm przegladarki, nie API