Włączanie żądań między źródłami w interfejsie ASP.NET Web API 2
Autor: Mike Wasson
Ta zawartość dotyczy poprzedniej wersji platformy .NET. Nowe programowanie powinno używać ASP.NET Core. Aby uzyskać więcej informacji na temat korzystania z internetowego interfejsu API i żądań między źródłami (CORS) w ASP.NET Core, zobacz:
- Samouczek: tworzenie internetowego interfejsu API przy użyciu platformy ASP.NET Core
- Włączanie żądań między źródłami (CORS) w usłudze ASP.NET Core
Zabezpieczenia przeglądarki uniemożliwiają stronie internetowej wysyłanie żądań AJAX do innej domeny. To ograniczenie jest nazywane zasadami tego samego źródła i uniemożliwia złośliwej witrynie odczytywanie poufnych danych z innej witryny. Czasami jednak warto zezwolić innym witrynom na wywoływanie internetowego interfejsu API.
Współużytkowanie zasobów między źródłami (CORS) to standard W3C, który umożliwia serwerowi złagodzenie zasad tego samego źródła. Przy użyciu mechanizmu CORS serwer może jawnie zezwalać na niektóre żądania między źródłami podczas odrzucania innych. MECHANIZM CORS jest bezpieczniejszy i bardziej elastyczny niż wcześniejsze techniki, takie jak JSONP. W tym samouczku pokazano, jak włączyć mechanizm CORS w aplikacji internetowego interfejsu API.
Oprogramowanie używane w samouczku
- Program Visual Studio
- Internetowy interfejs API 2.2
Wprowadzenie
W tym samouczku przedstawiono obsługę mechanizmu CORS w internetowym interfejsie API ASP.NET. Zaczniemy od utworzenia dwóch projektów ASP.NET — jednego o nazwie "WebService", który hostuje kontroler internetowego interfejsu API, a drugi o nazwie "WebClient", który wywołuje usługę WebService. Ponieważ dwie aplikacje są hostowane w różnych domenach, żądanie AJAX z elementu WebClient do usługi webservice jest żądaniem między źródłami.
Co to jest "to samo źródło"?
Dwa adresy URL mają to samo źródło, jeśli mają identyczne schematy, hosty i porty. (RFC 6454)
Te dwa adresy URL mają to samo źródło:
http://example.com/foo.html
http://example.com/bar.html
Te adresy URL mają inne źródła niż poprzednie dwa:
http://example.net
- Inna domenahttp://example.com:9000/foo.html
- Inny porthttps://example.com/foo.html
- Inny schemathttp://www.example.com/foo.html
- Inna poddomena
Uwaga
Program Internet Explorer nie uwzględnia portu podczas porównywania źródeł.
Tworzenie projektu WebService
Uwaga
W tej sekcji założono, że wiesz już, jak tworzyć projekty internetowego interfejsu API. Jeśli nie, zobacz Wprowadzenie do internetowego interfejsu API ASP.NET.
Uruchom program Visual Studio i utwórz nowy projekt aplikacji internetowej ASP.NET (.NET Framework).
W oknie dialogowym Nowa aplikacja internetowa ASP.NET wybierz szablon Pusty projekt. W obszarze Dodaj foldery i odwołania podstawowe dla wybierz pole wyboru Internetowy interfejs API .
Dodaj kontroler internetowego interfejsu API o nazwie z
TestController
następującym kodem:using System.Net.Http; using System.Web.Http; namespace WebService.Controllers { public class TestController : ApiController { public HttpResponseMessage Get() { return new HttpResponseMessage() { Content = new StringContent("GET: Test message") }; } public HttpResponseMessage Post() { return new HttpResponseMessage() { Content = new StringContent("POST: Test message") }; } public HttpResponseMessage Put() { return new HttpResponseMessage() { Content = new StringContent("PUT: Test message") }; } } }
Aplikację można uruchomić lokalnie lub wdrożyć na platformie Azure. (Zrzuty ekranu z tego samouczka są wdrażane w usłudze aplikacja systemu Azure Service Web Apps). Aby sprawdzić, czy internetowy interfejs API działa, przejdź do
http://hostname/api/test/
adresu , gdzie nazwa hosta to domena, w której wdrożono aplikację. Powinien zostać wyświetlony tekst odpowiedzi "GET: Test Message".
Tworzenie projektu WebClient
Utwórz inny projekt ASP.NET Web Application (.NET Framework) i wybierz szablon projektu MVC . Opcjonalnie wybierz pozycję Zmień uwierzytelnianie bez uwierzytelniania>. W tym samouczku nie potrzebujesz uwierzytelniania.
W Eksplorator rozwiązań otwórz plik Views/Home/Index.cshtml. Zastąp kod w tym pliku następującym kodem:
<div> <select id="method"> <option value="get">GET</option> <option value="post">POST</option> <option value="put">PUT</option> </select> <input type="button" value="Try it" onclick="sendRequest()" /> <span id='value1'>(Result)</span> </div> @section scripts { <script> // TODO: Replace with the URL of your WebService app var serviceUrl = 'http://mywebservice/api/test'; function sendRequest() { var method = $('#method').val(); $.ajax({ type: method, url: serviceUrl }).done(function (data) { $('#value1').text(data); }).fail(function (jqXHR, textStatus, errorThrown) { $('#value1').text(jqXHR.responseText || textStatus); }); } </script> }
W przypadku zmiennej serviceUrl użyj identyfikatora URI aplikacji WebService.
Uruchom aplikację WebClient lokalnie lub opublikuj ją w innej witrynie internetowej.
Po kliknięciu przycisku "Wypróbuj" żądanie AJAX zostanie przesłane do aplikacji WebService przy użyciu metody HTTP wymienionej w polu listy rozwijanej (GET, POST lub PUT). Umożliwia to badanie różnych żądań między źródłami. Obecnie aplikacja WebService nie obsługuje mechanizmu CORS, więc po kliknięciu przycisku zostanie wyświetlony błąd.
Uwaga
Jeśli obserwujesz ruch HTTP w narzędziu takim jak Fiddler, zobaczysz, że przeglądarka wysyła żądanie GET, a żądanie zakończy się powodzeniem, ale wywołanie AJAX zwróci błąd. Ważne jest, aby zrozumieć, że zasady tego samego źródła nie uniemożliwiają wysyłania żądania przez przeglądarkę. Zamiast tego uniemożliwia aplikacji wyświetlanie odpowiedzi.
Włączanie mechanizmu CORS
Teraz włączymy mechanizm CORS w aplikacji WebService. Najpierw dodaj pakiet NuGet CORS. W programie Visual Studio z menu Narzędzia wybierz pozycję NuGet Menedżer pakietów, a następnie wybierz pozycję Menedżer pakietów Konsola. W oknie Menedżer pakietów Console (Konsola Menedżer pakietów) wpisz następujące polecenie:
Install-Package Microsoft.AspNet.WebApi.Cors
To polecenie instaluje najnowszy pakiet i aktualizuje wszystkie zależności, w tym podstawowe biblioteki internetowego interfejsu API. Użyj flagi -Version
, aby oznaczyć określoną wersję. Pakiet CORS wymaga internetowego interfejsu API 2.0 lub nowszego.
Otwórz plik App_Start/WebApiConfig.cs. Dodaj następujący kod do metody WebApiConfig.Register :
using System.Web.Http;
namespace WebService
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// New code
config.EnableCors();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
}
Następnie dodaj atrybut [EnableCors] do TestController
klasy:
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Cors;
namespace WebService.Controllers
{
[EnableCors(origins: "http://mywebclient.azurewebsites.net", headers: "*", methods: "*")]
public class TestController : ApiController
{
// Controller methods not shown...
}
}
W przypadku parametru origins użyj identyfikatora URI, w którym wdrożono aplikację WebClient. Dzięki temu żądania między źródłami z elementu WebClient nadal nie zezwalają na wszystkie inne żądania między domenami. Później opiszę parametry [ EnableCors] bardziej szczegółowo.
Nie dołączaj ukośnika do przodu na końcu adresu URL źródła .
Ponownie wdróż zaktualizowaną aplikację WebService. Nie musisz aktualizować elementu WebClient. Teraz żądanie AJAX z elementu WebClient powinno zakończyć się powodzeniem. Metody GET, PUT i POST są dozwolone.
Jak działa mechanizm CORS
W tej sekcji opisano, co dzieje się w żądaniu CORS na poziomie komunikatów HTTP. Ważne jest, aby zrozumieć, jak działa mechanizm CORS, aby można było poprawnie skonfigurować atrybut [EnableCors] i rozwiązywać problemy, jeśli wszystko nie działa zgodnie z oczekiwaniami.
Specyfikacja MECHANIZMU CORS wprowadza kilka nowych nagłówków HTTP, które umożliwiają żądania między źródłami. Jeśli przeglądarka obsługuje mechanizm CORS, automatycznie ustawia te nagłówki dla żądań między źródłami; Nie musisz wykonywać żadnych specjalnych czynności w kodzie JavaScript.
Oto przykład żądania między źródłami. Nagłówek "Origin" udostępnia domenę witryny wysyłającej żądanie.
GET http://myservice.azurewebsites.net/api/test HTTP/1.1
Referer: http://myclient.azurewebsites.net/
Accept: */*
Accept-Language: en-US
Origin: http://myclient.azurewebsites.net
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)
Host: myservice.azurewebsites.net
Jeśli serwer zezwala na żądanie, ustawia nagłówek Access-Control-Allow-Origin. Wartość tego nagłówka jest zgodna z nagłówka Origin lub jest wartością wieloznacznymi "*", co oznacza, że dowolne źródło jest dozwolone.
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: text/plain; charset=utf-8
Access-Control-Allow-Origin: http://myclient.azurewebsites.net
Date: Wed, 05 Jun 2013 06:27:30 GMT
Content-Length: 17
GET: Test message
Jeśli odpowiedź nie zawiera nagłówka Access-Control-Allow-Origin, żądanie AJAX zakończy się niepowodzeniem. W szczególności przeglądarka nie zezwala na żądanie. Nawet jeśli serwer zwróci pomyślną odpowiedź, przeglądarka nie udostępni odpowiedzi aplikacji klienckiej.
Żądania wstępne
W przypadku niektórych żądań CORS przeglądarka wysyła dodatkowe żądanie nazywane "żądaniem wstępnym", zanim wyśle rzeczywiste żądanie dla zasobu.
Jeśli spełnione są następujące warunki, przeglądarka może pominąć żądanie wstępne:
Metoda żądania to GET, HEAD lub POST i
Aplikacja nie ustawia żadnych nagłówków żądań innych niż Accept, Accept-Language, Content-Language, Content-Type lub Last-Event-ID i
Nagłówek Content-Type (jeśli ustawiono) jest jednym z następujących elementów:
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
Reguła dotycząca nagłówków żądań dotyczy nagłówków ustawianych przez aplikację przez wywołanie polecenia setRequestHeader w obiekcie XMLHttpRequest . (Specyfikacja MECHANIZMU CORS wywołuje te "nagłówki żądań autora"). Reguła nie ma zastosowania do nagłówków , które można ustawić w przeglądarce , takich jak User-Agent, Host lub Content-Length.
Oto przykład żądania wstępnego:
OPTIONS http://myservice.azurewebsites.net/api/test HTTP/1.1
Accept: */*
Origin: http://myclient.azurewebsites.net
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: accept, x-my-custom-header
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)
Host: myservice.azurewebsites.net
Content-Length: 0
Żądanie przed lotem używa metody HTTP OPTIONS. Zawiera dwa specjalne nagłówki:
- Access-Control-Request-Method: metoda HTTP, która będzie używana dla rzeczywistego żądania.
- Access-Control-Request-Headers: lista nagłówków żądań ustawionych przez aplikację w rzeczywistym żądaniu. (Ponownie nie zawiera to nagłówków zestawów przeglądarki).
Oto przykładowa odpowiedź, zakładając, że serwer zezwala na żądanie:
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 0
Access-Control-Allow-Origin: http://myclient.azurewebsites.net
Access-Control-Allow-Headers: x-my-custom-header
Access-Control-Allow-Methods: PUT
Date: Wed, 05 Jun 2013 06:33:22 GMT
Odpowiedź zawiera nagłówek Access-Control-Allow-Methods, który zawiera listę dozwolonych metod i opcjonalnie nagłówek Access-Control-Allow-Headers, który zawiera listę dozwolonych nagłówków. Jeśli żądanie wstępne zakończy się pomyślnie, przeglądarka wyśle rzeczywiste żądanie zgodnie z wcześniejszym opisem.
Narzędzia często używane do testowania punktów końcowych przy użyciu żądań OPCJI wstępnych nie wysyłają domyślnie wymaganych nagłówków OPTIONS. Upewnij się, że Access-Control-Request-Method
nagłówki i Access-Control-Request-Headers
są wysyłane z żądaniem i że nagłówki OPTIONS docierają do aplikacji za pośrednictwem usług IIS.
Aby skonfigurować usługi IIS tak, aby umożliwić aplikacji ASP.NET odbieranie i obsługę żądań OPTION, dodaj następującą konfigurację do pliku web.config aplikacji w <system.webServer><handlers>
sekcji:
<system.webServer>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
Usunięcie programu OPTIONSVerbHandler
uniemożliwia usługom IIS obsługę żądań OPTIONS. Zamiana polecenia umożliwia żądaniom OPTIONS dotarcie do aplikacji, ponieważ domyślna rejestracja modułu ExtensionlessUrlHandler-Integrated-4.0
zezwala tylko na żądania GET, HEAD, POST i DEBUG z adresami URL bez rozszerzenia.
Reguły zakresu dla [EnableCors]
Mechanizm CORS na akcję, kontroler lub globalny można włączyć dla wszystkich kontrolerów interfejsu API sieci Web w aplikacji.
Na akcję
Aby włączyć mechanizm CORS dla pojedynczej akcji, ustaw atrybut [EnableCors] w metodzie akcji. Poniższy przykład włącza mechanizm CORS tylko dla GetItem
metody .
public class ItemsController : ApiController
{
public HttpResponseMessage GetAll() { ... }
[EnableCors(origins: "http://www.example.com", headers: "*", methods: "*")]
public HttpResponseMessage GetItem(int id) { ... }
public HttpResponseMessage Post() { ... }
public HttpResponseMessage PutItem(int id) { ... }
}
Na kontroler
Jeśli ustawisz wartość [EnableCors] w klasie kontrolera, będzie ona stosowana do wszystkich akcji na kontrolerze. Aby wyłączyć mechanizm CORS dla akcji, dodaj do akcji atrybut [DisableCors ]. Poniższy przykład umożliwia mechanizm CORS dla każdej metody z wyjątkiem PutItem
.
[EnableCors(origins: "http://www.example.com", headers: "*", methods: "*")]
public class ItemsController : ApiController
{
public HttpResponseMessage GetAll() { ... }
public HttpResponseMessage GetItem(int id) { ... }
public HttpResponseMessage Post() { ... }
[DisableCors]
public HttpResponseMessage PutItem(int id) { ... }
}
Globalnie
Aby włączyć mechanizm CORS dla wszystkich kontrolerów internetowego interfejsu API w aplikacji, przekaż wystąpienie EnableCorsAttribute do metody EnableCors :
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
var cors = new EnableCorsAttribute("www.example.com", "*", "*");
config.EnableCors(cors);
// ...
}
}
Jeśli atrybut zostanie ustawiony w więcej niż jednym zakresie, kolejność pierwszeństwa to:
- Akcja
- Kontroler
- Globalnie
Ustawianie dozwolonych źródeł
Parametr origins atrybutu [EnableCors] określa, które źródła mogą uzyskiwać dostęp do zasobu. Wartość jest rozdzielaną przecinkami listą dozwolonych źródeł.
[EnableCors(origins: "http://www.contoso.com,http://www.example.com",
headers: "*", methods: "*")]
Możesz również użyć wartości wieloznacznych "*", aby zezwolić na żądania z dowolnych źródeł.
Przed zezwoleniem na żądania z dowolnego źródła należy dokładnie rozważyć. Oznacza to, że dosłownie każda witryna internetowa może wykonywać wywołania AJAX do internetowego interfejsu API.
// Allow CORS for all origins. (Caution!)
[EnableCors(origins: "*", headers: "*", methods: "*")]
Ustawianie dozwolonych metod HTTP
Parametr metod atrybutu [EnableCors] określa, które metody HTTP mogą uzyskiwać dostęp do zasobu. Aby zezwolić na wszystkie metody, użyj wartości wieloznacznych "*". Poniższy przykład umożliwia tylko żądania GET i POST.
[EnableCors(origins: "http://www.example.com", headers: "*", methods: "get,post")]
public class TestController : ApiController
{
public HttpResponseMessage Get() { ... }
public HttpResponseMessage Post() { ... }
public HttpResponseMessage Put() { ... }
}
Ustawianie dozwolonych nagłówków żądań
W tym artykule opisano wcześniej, w jaki sposób żądanie wstępne może zawierać nagłówek Access-Control-Request-Headers z listą nagłówków HTTP ustawionych przez aplikację (tzw. "nagłówki żądania autora"). Parametr nagłówków atrybutu [EnableCors] określa, które nagłówki żądań autora są dozwolone. Aby zezwolić na wszystkie nagłówki, ustaw nagłówki na "*". Aby zezwolić na określone nagłówki, ustaw nagłówki na rozdzielaną przecinkami listę dozwolonych nagłówków:
[EnableCors(origins: "http://example.com",
headers: "accept,content-type,origin,x-my-header", methods: "*")]
Jednak przeglądarki nie są całkowicie spójne w sposobie ustawiania nagłówków Access-Control-Request-Headers. Na przykład przeglądarka Chrome obecnie zawiera "origin". Aplikacja FireFox nie zawiera standardowych nagłówków, takich jak "Akceptuj", nawet jeśli aplikacja ustawia je w skry skrycie.
Jeśli ustawisz nagłówki na inne niż "*", należy uwzględnić co najmniej "accept", "content-type" i "origin" oraz wszelkie nagłówki niestandardowe, które mają być obsługiwane.
Ustawianie dozwolonych nagłówków odpowiedzi
Domyślnie przeglądarka nie uwidacznia wszystkich nagłówków odpowiedzi aplikacji. Nagłówki odpowiedzi, które są dostępne domyślnie, to:
- Cache-Control
- Content-Language
- Typ zawartości
- Wygasa
- Ostatnia modyfikacja
- Pragma
Specyfikacja CORS wywołuje te proste nagłówki odpowiedzi. Aby udostępnić inne nagłówki aplikacji, ustaw parametr exposedHeaders [EnableCors].
W poniższym przykładzie metoda kontrolera Get
ustawia niestandardowy nagłówek o nazwie "X-Custom-Header". Domyślnie przeglądarka nie uwidacznia tego nagłówka w żądaniu między źródłami. Aby udostępnić nagłówek, dołącz "X-Custom-Header" w elementach exposedHeaders.
[EnableCors(origins: "*", headers: "*", methods: "*", exposedHeaders: "X-Custom-Header")]
public class TestController : ApiController
{
public HttpResponseMessage Get()
{
var resp = new HttpResponseMessage()
{
Content = new StringContent("GET: Test message")
};
resp.Headers.Add("X-Custom-Header", "hello");
return resp;
}
}
Przekazywanie poświadczeń w żądaniach między źródłami
Poświadczenia wymagają specjalnej obsługi w żądaniu CORS. Domyślnie przeglądarka nie wysyła żadnych poświadczeń z żądaniem między źródłami. Poświadczenia obejmują pliki cookie, a także schematy uwierzytelniania HTTP. Aby wysyłać poświadczenia z żądaniem między źródłami, klient musi ustawić wartość XMLHttpRequest.withCredentials na true.
Bezpośrednie używanie elementu XMLHttpRequest :
var xhr = new XMLHttpRequest();
xhr.open('get', 'http://www.example.com/api/test');
xhr.withCredentials = true;
W zapytaniu jQuery:
$.ajax({
type: 'get',
url: 'http://www.example.com/api/test',
xhrFields: {
withCredentials: true
}
Ponadto serwer musi zezwalać na poświadczenia. Aby zezwolić na poświadczenia między źródłami w internetowym interfejsie API, ustaw właściwość SupportsCredentials na wartość true dla atrybutu [EnableCors] :
[EnableCors(origins: "http://myclient.azurewebsites.net", headers: "*",
methods: "*", SupportsCredentials = true)]
Jeśli ta właściwość ma wartość true, odpowiedź HTTP będzie zawierać nagłówek Access-Control-Allow-Credentials. Ten nagłówek informuje przeglądarkę, że serwer zezwala na poświadczenia dla żądania między źródłami.
Jeśli przeglądarka wysyła poświadczenia, ale odpowiedź nie zawiera prawidłowego nagłówka Access-Control-Allow-Credentials, przeglądarka nie ujawni odpowiedzi na aplikację, a żądanie AJAX zakończy się niepowodzeniem.
Należy zachować ostrożność przy ustawianiu wartości "SupportsCredentials " na wartość true, ponieważ oznacza to, że witryna internetowa w innej domenie może wysyłać poświadczenia zalogowanego użytkownika do internetowego interfejsu API w imieniu użytkownika, bez świadomości użytkownika. Specyfikacja MECHANIZMU CORS stwierdza również, że ustawienie wartości origins na "*" jest nieprawidłowe, jeśli parametr SupportsCredentials ma wartość true.
Niestandardowi dostawcy zasad CORS
Atrybut [EnableCors] implementuje interfejs ICorsPolicyProvider . Możesz zapewnić własną implementację, tworząc klasę, która pochodzi z atrybutu i implementuje element ICorsPolicyProvider.
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)]
public class MyCorsPolicyAttribute : Attribute, ICorsPolicyProvider
{
private CorsPolicy _policy;
public MyCorsPolicyAttribute()
{
// Create a CORS policy.
_policy = new CorsPolicy
{
AllowAnyMethod = true,
AllowAnyHeader = true
};
// Add allowed origins.
_policy.Origins.Add("http://myclient.azurewebsites.net");
_policy.Origins.Add("http://www.contoso.com");
}
public Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request)
{
return Task.FromResult(_policy);
}
}
Teraz możesz zastosować atrybut w dowolnym miejscu, które należy umieścić [EnableCors].
[MyCorsPolicy]
public class TestController : ApiController
{
.. //
Na przykład niestandardowy dostawca zasad CORS może odczytać ustawienia z pliku konfiguracji.
Alternatywą dla używania atrybutów jest zarejestrowanie obiektu ICorsPolicyProviderFactory , który tworzy obiekty ICorsPolicyProvider .
public class CorsPolicyFactory : ICorsPolicyProviderFactory
{
ICorsPolicyProvider _provider = new MyCorsPolicyProvider();
public ICorsPolicyProvider GetCorsPolicyProvider(HttpRequestMessage request)
{
return _provider;
}
}
Aby ustawić metodę rozszerzenia ICorsPolicyProviderFactory, wywołaj metodę rozszerzenia SetCorsPolicyProviderFactory podczas uruchamiania w następujący sposób:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.SetCorsPolicyProviderFactory(new CorsPolicyFactory());
config.EnableCors();
// ...
}
}
Obsługa przeglądarek
Pakiet CORS internetowego interfejsu API jest technologią po stronie serwera. Przeglądarka użytkownika musi również obsługiwać mechanizm CORS. Na szczęście bieżące wersje wszystkich głównych przeglądarek obejmują obsługę mechanizmu CORS.