Współdzielenie zasobów pomiędzy serwerami z różnych domen (CORS)

Bezpieczne udostępnianie zasobów między domenami

Mariko Kosaka

Zasada dotycząca tego samego pochodzenia w przeglądarce blokuje odczyt zasobu z innego pochodzenia. Ten mechanizm uniemożliwia złośliwym witrynom odczytywanie danych z innych witryn, ale uniemożliwia też ich legalne wykorzystywanie.

Współczesne aplikacje internetowe często chcą pobierać zasoby z innego źródła, np. aby pobierać dane JSON z innej domeny lub wczytywać obrazy z innej witryny do elementu <canvas>. Mogą to być zasoby publiczne, które powinny być dostępne dla wszystkich, ale są blokowane przez zasady dotyczące tego samego źródła. Deweloperzy korzystali z różnych obejść komunikatu o błędzie, np. z JSONP.

Mechanizm CORS rozwiązuje ten problem w sposób ustandaryzowany. Włączenie CORS pozwala serwerowi poinformować przeglądarkę, że może ona używać dodatkowego źródła.

Jak działa żądanie zasobu w przeglądarce?

żądanie i odpowiedź
Ilustracja żądania klienta i odpowiedzi serwera.

Przeglądarka i serwer mogą wymieniać się danymi w sieci za pomocą protokołu HyperText Transfer Protocol (HTTP). HTTP określa reguły komunikacji między osobą wysyłającą żądanie a osobą odpowiadającą na nie, w tym informacje potrzebne do uzyskania zasobu.

Nagłówek HTTP negocjuje wymianę wiadomości między klientem a serwerem i jest używany do określania dostępu. Zarówno żądanie przeglądarki, jak i odpowiedź serwera są podzielone na nagłówektreść.

Informacje o wiadomości, takie jak typ lub kodowanie wiadomości. Nagłówek może zawierać różne informacje wyrażone jako pary klucz-wartość. Nagłówek żądania i nagłówek odpowiedzi zawierają różne informacje.

Przykładowy nagłówek żądania

Accept: text/html
Cookie: Version=1

Ten nagłówek jest odpowiednikiem stwierdzenia „Chcę otrzymywać w odpowiedzi kod HTML. Oto mój plik cookie.

Przykładowy nagłówek odpowiedzi

Content-Encoding: gzip
Cache-Control: no-store

Ten nagłówek jest odpowiednikiem stwierdzenia „Dane w tej odpowiedzi są kodowane za pomocą programu gzip. Nie przechowuj tego w pamięci podręcznej”.

Treść

Treść wiadomości. Może to być zwykły tekst, plik binarny obrazu, JSON, HTML lub wiele innych.

Jak działa CORS?

Zasada dotycząca tego samego pochodzenia mówi przeglądarce, aby blokowała żądania z wielu źródeł. Gdy potrzebujesz zasobu publicznego z innego źródła, serwer dostarczający zasób informuje przeglądarkę, że źródło wysyłające żądanie może uzyskać dostęp do tego zasobu. Przeglądarka to pamięta i pozwala je na udostępnianie zasobów między domenami.

Krok 1. Żądanie klienta (przeglądarki)

Gdy przeglądarka wysyła żądanie z innej domeny, dodaje nagłówek Origin z bieżącym źródłem (schemat, host i port).

Krok 2. Odpowiedź serwera

Gdy serwer zobaczy ten nagłówek i zechce zezwolić na dostęp, doda do odpowiedzi nagłówek Access-Control-Allow-Origin, podając w nim źródło żądania (lub *, aby zezwolić na dowolne źródło).

Krok 3. Przeglądarka otrzymuje odpowiedź

Gdy przeglądarka zobaczy tę odpowiedź z odpowiednim nagłówkiem Access-Control-Allow-Origin, udostępni dane odpowiedzi stronie klienta.

Udostępnianie danych logowania za pomocą CORS

Ze względu na ochronę prywatności współdzielenie zasobów pomiędzy serwerami z różnych domen jest zwykle używane w przypadku anonimowych żądań, w których nie jest identyfikowany podmiot przesyłający żądanie. Jeśli chcesz wysyłać pliki cookie podczas korzystania z CORS, które mogą identyfikować nadawcę, musisz dodać do żądania i odpowiedzi dodatkowe nagłówki.

Żądanie

Dodaj credentials: 'include' do opcji pobierania, tak jak w przykładzie poniżej. Obejmuje to plik cookie z żądaniem w takiej postaci:

fetch('https://example.com', {
  mode: 'cors',
  credentials: 'include'
})

Odpowiedź

Access-Control-Allow-Origin musi mieć konkretną wartość pochodzenia (bez symbolu wieloznacznego *), a Access-Control-Allow-Credentials musi mieć wartość true.

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true

żądania wstępne w przypadku złożonych wywołań HTTP;

Gdy aplikacja internetowa wysyła złożone żądanie HTTP, przeglądarka dodaje żądanie wstępne na początku łańcucha żądań.

Specyfikacja CORS definiuje złożone żądanie w ten sposób:

  • żądanie, które używa metod innych niż GET, POST lub HEAD;
  • żądanie zawierające nagłówki inne niż Accept, Accept-Language lub Content-Language;
  • Żądanie, które ma nagłówek Content-Type inny niż application/x-www-form-urlencoded, multipart/form-data lub text/plain.

Przeglądarki automatycznie tworzą wszystkie niezbędne żądania wstępne i wysyłają je przed rzeczywistą wiadomością żądania. Żądanie procesu wstępnego to żądanie OPTIONS, takie jak w tym przykładzie:

OPTIONS /data HTTP/1.1
Origin: https://example.com
Access-Control-Request-Method: DELETE

Po stronie serwera aplikacja odbierająca żądanie odpowiada na żądanie wstępne, podając informacje o akceptowanych przez aplikację metodach z tego źródła:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, DELETE, HEAD, OPTIONS

Odpowiedź serwera może też zawierać nagłówek Access-Control-Max-Age określający czas (w sekundach) buforowania wyników kontroli wstępnych. Dzięki temu klient może wysyłać wiele złożonych żądań bez konieczności powtarzania żądania procesu wstępnego.