Jeśli jesteś programistą front-endu i próbowałeś połączyć się z API, które jest na innym serwerze niż Twoja aplikacja, mogłeś natrafić na błąd o nazwie CORS. Ale czym tak naprawdę jest CORS, dlaczego jest ważny i jak można go zrozumieć? W tym wpisie przybliżę te zagadnienia w prosty sposób.
Co to jest CORS?
CORS (ang. Cross-Origin Resource Sharing) to mechanizm zabezpieczeń w przeglądarkach, który pozwala kontrolować, kto może uzyskać dostęp do zasobów na serwerze. W praktyce, oznacza to, że jeżeli strona, na której jesteś, chce pobrać dane z innego serwera, przeglądarka musi sprawdzić, czy serwer, z którego pobierane są dane, pozwala na taki dostęp. Bez CORS przeglądarka blokowałaby takie żądania w celu ochrony użytkownika przed potencjalnymi zagrożeniami.
Dlaczego CORS jest potrzebny?
Załóżmy, że Twoja aplikacja działa na adresie https://moja-aplikacja.com, a potrzebujesz danych z API na serwerze https://inne-api.com. Przeglądarka uzna, że te dwie domeny są różne (różne pochodzenia) i musi mieć pewność, że serwer z https://inne-api.com pozwala na taki dostęp. To właśnie tutaj pojawia się CORS – pozwala on określić, które domeny mogą korzystać z zasobów serwera.
Jak działa CORS?
Mechanizm CORS działa poprzez dodanie specjalnych nagłówków HTTP do odpowiedzi z serwera. Serwer, do którego wysyłasz żądanie, określa, jakie domeny mogą uzyskać dostęp do jego zasobów. Najczęściej używany nagłówek to:
Access-Control-Allow-Origin: https://moja-aplikacja.com
W ten sposób serwer informuje przeglądarkę, że zasoby mogą być dostępne dla konkretnej domeny, czyli https://moja-aplikacja.com. Możesz także zobaczyć nagłówek, który pozwala wszystkim domenom na dostęp:
Access-Control-Allow-Origin: *
W takim przypadku każdy może korzystać z zasobów serwera, co nie zawsze jest bezpieczne, ale bywa używane w przypadku otwartych API.
Przykład działania CORS
Wyobraźmy sobie prostą stronę, która próbuje pobrać dane o pogodzie z publicznego API:
fetch('https://api.pogoda.com/data') .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Błąd:', error));
Jeśli serwer https://api.pogoda.com nie ma odpowiedniego nagłówka Access-Control-Allow-Origin ustawionego na Twoją stronę, przeglądarka zablokuje żądanie, a Ty otrzymasz komunikat o błędzie CORS.
Typowy błąd CORS
Gdy serwer nie zezwala na żądania z Twojej domeny, w konsoli przeglądarki zobaczysz coś podobnego do tego:
Access to fetch at 'https://api.pogoda.com/data' from origin 'https://moja-aplikacja.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Ten komunikat oznacza, że serwer https://api.pogoda.com nie pozwala na uzyskanie zasobów przez Twoją domenę https://moja-aplikacja.com.
Jak rozwiązać problem CORS?
Rozwiązanie problemu CORS wymaga zazwyczaj modyfikacji konfiguracji serwera, który dostarcza API. Administrator musi dodać odpowiednie nagłówki, aby zezwolić Twojej stronie na dostęp. Przykładowo, w przypadku serwera Apache można dodać do .htaccess następujący fragment:
Header set Access-Control-Allow-Origin "https://moja-aplikacja.com"
Dla Node.js i Express, można użyć middleware o nazwie cors, aby zezwolić na odpowiednie połączenia:
const express = require('express'); const cors = require('cors'); const app = express(); app.use(cors({ origin: 'https://moja-aplikacja.com' })); app.get('/data', (req, res) => { res.json({ message: 'Dane o pogodzie' }); });
Jak ustawić CORS w backendzie? – przykład CORS w Symfony
Jeśli pracujesz z backendem w Symfony, konfiguracja CORS może być zarządzana za pomocą specjalnych narzędzi. Najlepszym sposobem na obsługę CORS w Symfony jest skorzystanie z NelmioCorsBundle. To popularny bundle, który umożliwia łatwe zarządzanie politykami CORS.
Instalacja i konfiguracja NelmioCorsBundle
Aby zainstalować NelmioCorsBundle, możesz użyć poniższej komendy:
composer require nelmio/cors-bundle
Po zainstalowaniu musisz dodać odpowiednią konfigurację do pliku config/packages/nelmio_cors.yaml:
nelmio_cors: defaults: allow_credentials: false allow_origin: ['*'] # Możesz określić konkretne domeny, np. ['https://moja-aplikacja.com'] allow_headers: ['Content-Type', 'Authorization'] allow_methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'] max_age: 3600 paths: '^/api/': allow_origin: ['*'] allow_headers: ['Content-Type', 'Authorization'] allow_methods: ['GET', 'POST', 'OPTIONS'] max_age: 3600
W powyższym przykładzie skonfigurowaliśmy NelmioCorsBundle, aby pozwalał na żądania CORS na ścieżkach zaczynających się od /api/. Możesz skonfigurować szczegóły takie jak metody HTTP, nagłówki i maksymalny czas życia odpowiedzi pre-flight.
Bundle NelmioCorsBundle jest jednym z najlepszych rozwiązań w ekosystemie Symfony, gdyż oferuje dużą elastyczność i prostotę konfiguracji, co pozwala łatwo dostosować CORS do wymagań Twojej aplikacji.
Podsumowanie
CORS to mechanizm, który zapewnia bezpieczeństwo w przeglądarkach, ograniczając dostęp do zasobów znajdujących się na innym serwerze. Aby umożliwić żądania między różnymi domenami, serwer musi jasno określić, komu pozwala na dostęp, używając odpowiednich nagłówków. Dzięki temu mechanizmowi możemy bezpiecznie korzystać z API, minimalizując ryzyko ataków takich jak Cross-Site Request Forgery (CSRF).
Nikt jeszcze nie komentował. Bądź pierwszy!