Scott Tiger Tech Blog

Blog technologiczny firmy Scott Tiger S.A.

Cross-Origin Resource Sharing (CORS)

Autor: Piotr Karpiuk o środa 1. Sierpień 2012

W miarę rozwoju Internetu coraz większego znaczenia nabiera współdzielenie zasobów, a także aplikacje agregujące dane pochodzące z różnych źródeł. Aplikacje webowe typu mashup udostępniają na jednej stronie WWW dane pochodzące z różnych serwerów, np. na jednym pulpicie użytkownik może mieć kursy walut, prognozę pogody, program telewizyjny itp. Jeszcze do niedawna implementacja takich witryn napotykała spore problemy za sprawą polityki bezpieczeństwa JavaScriptu. Chodzi o zasadę same origin policy, która utrudnia skryptom strony WWW komunikację się z innymi serwerami niż ten, z którego pochodzi witryna. Twórcy aplikacji webowych rozwiązywali ten problem albo niewydajnie (gdy serwer witryny służy przeglądarce jako pośrednik w komunikacji z innym serwerem), albo uciekając się do podejrzanych hakerskich technik w rodzaju JSONP.

Rozszerzenie AJAXa obecne już od dłuższego czasu we współczesnych przeglądarkach udostępnia mechanizm Cross-Origin Resource Sharing (CORS), znacznie upraszczający cały proces.

Rozważmy taki scenariusz: serwer api.alice.com udostępnia dane, z których chce skorzystać aplikacja webowa umieszczona na api.bob.com.

Z punktu widzenia programisty JavaScript wywołanie AJAX CORS wygląda tak jak komunikacja z macierzystym serwerem:

          xhr.open('GET', 'http://api.alice.com/cors', true);
          xhr.withCredentials = true;
          xhr.send();

(Opcjonalnie można ustawić własność withCredentials obiektu XHR, aby spowodować żeby w zleceniu do zdalnego serwera poszły również ciasteczka domeny api.alice.com i żeby ta domena mogła ustawiać ciasteczka. Trzeba nadmienić, że w przeciwieństwie do samej przeglądarki kod JavaScriptu aplikacji api.bob.com nie będzie miał dostępu do ciasteczek domeny api.alice.com – ani w postaci nagłówków HTTP, ani w document.cookie).

Różnice w porównaniu ze zwykłym zleceniem AJAX do macierzystego serwera występują w nagłówkach HTTP automatycznie wysyłanych przez przeglądarkę:

        Origin: http://api.bob.com

…oraz nagłówkach HTTP jakimi odpowiada serwer. Przede wszystkim, serwer musi wyrazić zgodę na udostępnienie swoich zasobów. Potwierdza ją, wysyłając pierwszy z poniższych nagłówków (opcjonalnie wartością tego nagłówka może być gwiazdka (*) oznaczająca zasoby publiczne):

        Access-Control-Allow-Origin: http://api.bob.com
        Access-Control-Allow-Credentials: true
        Access-Control-Expose-Headers: FooBar

Drugi nagłówek jest konieczny dla poprawnego zakończenia wywołania, jeśli klient ustawił własność xhr.withCredentials w obiekcie XHR. Ostatni nagłówek wymienia te nadmiarowe nagłówki odpowiedzi serwera, które mają być dostępne klientowi z poziomu JavaScriptu.

Skomplikowane zapytania

Tak wygląda sprawa w przypadku prostych zapytań HTTP POST, GET lub HEAD, z ustawionymi jedynie co najwyżej nagłówkami Accept, Accept-Language, Content-Language, Last-Event-ID i Content-Type, przy czym ten ostatni może być tylko jednym z: application/x-www-form-urlencoded, multipart/form-data, albo text/plain. Gdy chcemy wykonać zapytanie HTTP PUT, wysłać inny nagłówek, albo wysłać do zdalnego serwera coś innego niż tekst lub formularz, sprawy się komplikują.

Powiedzmy że aplikacja api.bob.com wykonuje zapytanie:

      xhr.open('PUT', http://api.alice.com/cors'', true);
      xhr.setRequestHeader('X-Custom-Header', 'value');
      xhr.send();

W pierwszej kolejności przeglądarka po cichu wyśle do serwera wstępne zapytanie HTTP OPTIONS o pozwolenie, i będzie ono zawierało nagłówki CORS:

      Origin: http://api.bob.com
      Access-Control-Request-Method: PUT
      Access-Control-Request-Headers: X-Custom-Header

Ostatni z wymienionych nagłówków zawiera rozdzieloną przecinkami listę nietypowych nagłówków naszego zlecenia.

Serwer może nie wyrazić zgody, nie wysyłając nagłówków CORS (kod odpowiedzi może być 200).

W przypadku zgody serwer odpowiada dodatkowymi nagłówkami CORS:

      Access-Control-Allow-Origin: http://api.bob.com
      Access-Control-Allow-Methods: GET, POST, PUT
      Access-Control-Allow-Headers: X-Custom-Header

Serwer może w odpowiedzi wymienić wiele obsługiwanych metod HTTP i nagłówków HTTP, aby klient mógł sobie tą odpowiedź zbuforować i nie musiał wykonywać dodatkowego zapytania HTTP OPTIONS przy kolejnych zleceniach CORS.

W dalszej kolejności przeglądarka wykona zapytanie HTTP PUT tak jak w przypadku „zwykłego” wywołania CORS.

Share and Enjoy:
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Śledzik
  • Blip
  • Blogger.com
  • Gadu-Gadu Live
  • LinkedIn
  • MySpace
  • Wykop

Zostaw komentarz

XHTML: Możesz użyć następujących tagów: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>