Przejdź do głównej zawartości

CORS - mechanizm i znaczenie

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.

Origin składa się z trzech elementow:

  • Protokół (scheme): http:// lub https://
  • 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/page1 i https://example.com/page2 (ta sama)
  • https://example.com i https://example.com:443 (ta sama - domyslny port)

Różne origin:

  • http://example.com vs https://example.com (różny protokół)
  • https://example.com vs https://api.example.com (różny host)
  • https://example.com vs https://example.com:3000 (różny port)

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 pozwala serwerowi explicite zezwolic na dostep z innych origin poprzez specjalne nagłówki HTTP. To serwer decyduje, kto może się z nim komunikowac.

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: [...]} │
│ <─────────────────────────────────────│

Wymagany dla “złożonych” żądań:

  • Metody inne niz GET/HEAD/POST
  • Niestandardowe nagłówki
  • Content-Type: application/json
  1. Przegladarka wysyła OPTIONS - pyta serwer o pozwolenie
  2. Serwer odpowiada nagłówkami CORS - mowi, co jest dozwolone
  3. Przegladarka analizuje odpowiedz - czy zadanie jest dozwolone?
  4. 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łówekOpisPrzykład
Access-Control-Allow-OriginDozwolone originhttps://example.com lub *
Access-Control-Allow-MethodsDozwolone metody HTTPGET, POST, PUT, DELETE
Access-Control-Allow-HeadersDozwolone nagłówki zadaniaContent-Type, Authorization
Access-Control-Allow-CredentialsCzy cookies sa dozwolonetrue
Access-Control-Max-AgeCache preflight (sekundy)86400
Access-Control-Expose-HeadersNagłówki widoczne dla JSX-Total-Count
NagłówekOpis
OriginOrigin strony wysyłającej zadanie
Access-Control-Request-MethodMetoda planowanego zadania
Access-Control-Request-HeadersNiestandardowe nagłówki
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.
import express from 'express';
import cors from 'cors';
const app = express();
// Prosta konfiguracja - zezwol wszystkim
app.use(cors());
// Lub szczegółowa konfiguracja
app.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'));
}
}
}));
main.ts
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();
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 86400
Content-Type: application/json
{"users": [...]}
  1. JavaScript wykonuje fetch/XMLHttpRequest do innego origin
  2. Przegladarka dodaje nagłówek Origin automatycznie
  3. Przegladarka wysyła zadanie (lub preflight)
  4. Serwer odpowiada (z nagłówkami CORS lub bez)
  5. Przegladarka sprawdza nagłówki - czy origin jest dozwolony?
  6. Jeśli nie - blokuje dostep do odpowiedzi dla JavaScript

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)
  • 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