Odpowiedź na żądanie inspekcji wstępnej nie przechodzi kontroli kontroli dostępu

456

Otrzymuję ten błąd, używając ngResource do wywołania interfejsu API REST w Amazon Web Services:

XMLHttpRequest nie może załadować http://server.apiurl.com:8000/s/login?login=facebook . Odpowiedź na żądanie inspekcji wstępnej nie przechodzi kontroli kontroli dostępu: Żądany zasób nie zawiera nagłówka „Kontrola dostępu - Zezwalaj na pochodzenie”. Dlatego źródło „ http: // localhost ” nie ma dostępu. Błąd 405

Usługa:

socialMarkt.factory('loginService', ['$resource', function($resource){    
    var apiAddress = "http://server.apiurl.com:8000/s/login/";
    return $resource(apiAddress, { login:"facebook", access_token: "@access_token" ,facebook_id: "@facebook_id" }, {
                getUser: {method:'POST'}
            });
}]);

Kontroler:

[...]
loginService.getUser(JSON.stringify(fbObj)),
                function(data){
                    console.log(data);
                },
                function(result) {
                    console.error('Error', result.status);
                }
[...]

Używam Chrome i nie wiem, co jeszcze zrobić, aby rozwiązać ten problem. Skonfigurowałem nawet serwer, aby akceptował nagłówki z miejsca pochodzenia localhost.

Andre Mendes
źródło
zdezorientowany: czy „skonfigurowałeś serwer”, czy jest to „interfejs API w serwisie amazon”?
dandavis
3
Najwyraźniej nie zrobiłeś wystarczająco dużo, aby włączyć CORS po stronie serwera. Opublikuj próbkę nagłówków odpowiedzi
charlietfl
4
Tak czy inaczej, twoje głosy w dół są błędne. Hostuje swoje pliki na swoim komputerze lokalnym. Nie będzie miało znaczenia, jakiego rodzaju konfetti będzie on robił na zapleczu. Angular nie zezwoli na ten lot przed lotem.
E. Maggini,
3
Dzięki za komentarze, zadziałało, kiedy ustawiłem przeglądarkę na wyłączenie bezpieczeństwa
Andre Mendes
1
@Andre Ale wyłączenie bezpieczeństwa to tylko brzydkie obejście, w którym
narażasz się

Odpowiedzi:

240

Występują problemy z CORS.

Istnieje kilka sposobów rozwiązania tego problemu.

  1. Wyłącz CORS. Na przykład: jak wyłączyć corsy w chromie
  2. Użyj wtyczki do przeglądarki
  3. Użyj proxy, takiego jak nginx. przykład konfiguracji
  4. Przejdź przez niezbędną konfigurację swojego serwera. Jest to raczej czynnik serwera sieciowego załadowanego do instancji EC2 (zakładając, że to właśnie rozumiesz przez „serwis internetowy Amazon”). W przypadku konkretnego serwera możesz odwołać się do strony internetowej umożliwiającej włączenie CORS.

Mówiąc dokładniej, próbujesz uzyskać dostęp do api.serverurl.com z localhost. To jest dokładna definicja żądania między domenami.

Wyłączając go tylko po to, aby wykonać swoją pracę (OK, zapewnij słabe bezpieczeństwo, jeśli odwiedzasz inne witryny i po prostu rzucisz puszkę w dół drogi), możesz użyć serwera proxy, który sprawia, że ​​przeglądarka myśli, że wszystkie żądania pochodzą od lokalnego hosta, gdy naprawdę masz serwer lokalny, który następnie wywołuje serwer zdalny.

więc api.serverurl.com może stać się localhost: 8000 / api, a lokalny nginx lub inny serwer proxy wyśle ​​do właściwego miejsca docelowego.


Teraz popularne zapotrzebowanie, 100% więcej informacji o CORS .... ten sam wspaniały smak!


A dla downvoters ... omijanie CORS jest dokładnie tym, co pokazano dla tych, którzy po prostu uczą się interfejsu. https://codecraft.tv/courses/angular/http/http-with-promises/

E. Maggini
źródło
774
pominięto oczywistą prawidłowość implementacji CORS
charlietfl
40
Głosowanie jest łatwe. Mniej łatwo samemu zaryzykować, przyjacielu. Wszystkie działają dokładnie w środowisku programistycznym.
E. Maggini,
3
To faktycznie działało. Dodałem flagę, aby wyłączyć zabezpieczenia sieci. Bo rozwój jest w porządku.
Andre Mendes
15
@charlietfl How?
GreenAsJade,
3
Dziękuję, że uratowałeś mi dzień. Używana tylko pierwsza opcja: C: \ Program Files (x86) \ Google \ Chrome \ Application> chrome.exe --user-data-dir = "C: \ Chrome dev session" --disable-web-security. Od: stackoverflow.com/questions/3102819/…
Harsimer
169

Mój „Serwer API” to aplikacja PHP, więc aby rozwiązać ten problem, znalazłem poniższe rozwiązanie do pracy:

Umieść linie w index.php

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token');
Slipstream
źródło
3
Zgadzam się, to jest lepsze niż zaakceptowana odpowiedź, chociaż zachowaj ostrożność podczas kopiowania tych wierszy, pamiętaj o zmodyfikowaniu metod i pochodzenia.
Amir Savand
11
Gdzie umieścić go w projekcie Angular 6?
whatthefish
@CodyBugstein i whatthefish postawili przed jakimkolwiek wyjściem
Garet Claborn
Moja aplikacja kliencka przestała działać, gdy dodałem nagłówek wymagany tylko przez niektóre serwery. Jeśli żądanie zawiera niestandardowe nagłówki, należy je wymienić na Access-Control-Allow-Headers.
z0r
46

W interfejsie internetowym AspNetCore ten problem został rozwiązany przez dodanie „Microsoft.AspNetCore.Cors” (wer. 1.1.1) i dodanie poniższych zmian w Startup.cs.

public void ConfigureServices(IServiceCollection services)
{ 
    services.AddCors(options =>
    {
          options.AddPolicy("AllowAllHeaders",
                builder =>
            {
                    builder.AllowAnyOrigin()
                           .AllowAnyHeader()
                           .AllowAnyMethod();
                });
    });
    .
    .
    .
}

i

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{


    // Shows UseCors with named policy.
    app.UseCors("AllowAllHeaders");
    .
    .
    .
}

i wprowadzenie [EnableCors("AllowAllHeaders")]kontrolera.

Rajkumar Peter
źródło
18
To dobra odpowiedź, jeśli chcesz wbudować luki w skryptach między witrynami! Proszę, nigdy tego nie róbcie! Określ domeny, do których możesz uzyskać dostęp, aby uniknąć problemów z bezpieczeństwem. CORS jest z jakiegoś powodu.
paqogomez
2
Aby to wyjaśnić @paqogomez, w metodzie ConfigureServices: services.AddCors (options => {options.AddPolicy („AllowSpecificOrigin”, builder => {builder.WithOrigins („ localhost” ) .AllowAnyOrigin () .AllowAnyHeader (). AllowAnyMethod ();});}); oraz w metodzie Configure: app UseCors („AllowSpecificOrigin”);
Francisco Tena
28

Istnieją pewne zastrzeżenia, jeśli chodzi o CORS. Po pierwsze, nie pozwala na używanie symboli wieloznacznych, *ale nie trzymaj mnie tego, gdzieś go przeczytałem i nie mogę teraz znaleźć artykułu.

Jeśli wysyłasz żądania z innej domeny, musisz dodać nagłówki zezwolenia na początek.

 Access-Control-Allow-Origin: www.other.com 

Jeśli dokonujesz wnioski, które wpływają na zasoby serwera jak POST / PUT / patch, a jeśli MIME typu jest inny niż poniżej application/x-www-form-urlencoded, multipart/form-datalub text/plainprzeglądarka będzie automatycznie dokonać OPCJE przed lotem zażądać, aby skontaktować się z serwerem, jeśli byłoby to pozwolić .

Tak więc Twój interfejs API / serwer musi odpowiednio obsłużyć żądania OPCJI, musisz odpowiedzieć access control headersodpowiednim kodem stanu odpowiedzi HTTP 200.

Nagłówki powinny wyglądać mniej więcej tak: dostosuj je do swoich potrzeb:

   Access-Control-Allow-Methods: GET, POST, PUT, PATCH, POST, DELETE, OPTIONS
   Access-Control-Allow-Headers: Content-Type
   Access-Control-Max-Age: 86400

Nagłówek maksymalnego wieku jest ważny, w moim przypadku nie działałby bez niego, myślę, że przeglądarka potrzebuje informacji o tym, jak długo ważne są „prawa dostępu”.

Ponadto, jeśli składasz np. POSTŻądanie za pomocą application/jsonmima z innej domeny, musisz również dodać wspomniany wcześniej nagłówek zezwolenia na początek, aby wyglądało to tak:

   Access-Control-Allow-Origin: www.other.com 
   Access-Control-Allow-Methods: GET, POST, PUT, PATCH, POST, DELETE, OPTIONS
   Access-Control-Allow-Headers: Content-Type
   Access-Control-Max-Age: 86400

Gdy lot przed lotem zakończy się powodzeniem i otrzyma wszystkie potrzebne informacje, zostanie wysłane aktualne żądanie.

Ogólnie rzecz biorąc, Access-Controlw odpowiedzi należy podać wszelkie nagłówki w żądaniu początkowym lub przed lotem, aby zadziałało.

Jest dobry przykład w dokumentach MDN tutaj na ten link , i powinieneś również sprawdzić ten post SO

Sasa Blagojevic
źródło
1
Oto artykuł Mozilli mówiący o tym, jak nie można używać symboli wieloznacznych do pochodzenia corsa: Link Najwyraźniej dotyczy to tylko sytuacji, w których używane są dane uwierzytelniające (o ile dobrze rozumiem)
Helzgate
Korzystam z symboli wieloznacznych i przesyłam token nośny w celu autoryzacji żądania i działa poprawnie, więc nie jestem pewien, do jakiego linka podałem powyżej w odniesieniu do poświadczeń. Mój problem polegał na tym, że gdy dodałem zasady CORS do .Net Core, nie dodałem .AllowCredentials(). Po dodaniu .AllowCredentials()wszystko działało.
Helzgate
15

JavaScript XMLHttpRequest i Fetch są zgodne z zasadami tego samego pochodzenia. Tak więc aplikacja internetowa korzystająca z XMLHttpRequest lub Fetch mogła wysyłać żądania HTTP tylko do własnej domeny.

Źródło: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

Musisz wysłać nagłówek HTTP Access-Control-Allow-Origin: * ze strony serwera.

Jeśli używasz Apache jako serwera HTTP, możesz dodać go do pliku konfiguracyjnego Apache w następujący sposób:

<IfModule mod_headers.c>
    Header set Access-Control-Allow-Origin "*"
</IfModule>

Mod_headers jest domyślnie włączony w Apache, jednak możesz chcieć upewnić się, że jest włączony, uruchamiając:

 a2enmod headers
Tadej
źródło
Gdzie mogę znaleźć mój plik konfiguracyjny Apache?
Shubham Arya
@ShubhamArya na Linuksie Debian domyślna lokalizacja to:/etc/apache2/apache2.conf
Tadej
gdzie mogę to znaleźć w systemie Windows?
Shubham Arya
10

Jeśli piszesz rozszerzenie chrome

Musisz dodać manifest.jsonuprawnienia do swojej domeny (domen).

"permissions": [
   "http://example.com/*",
   "https://example.com/*"
]
freedev
źródło
1
Sprawdź także, czy masz przedrostek www
Vlas Bashynskyi
8

Jeśli używasz serwera IIS przez przypadek. możesz ustawić poniżej nagłówków w opcji nagłówków żądań HTTP.

Access-Control-Allow-Origin:*
Access-Control-Allow-Methods: 'HEAD, GET, POST, PUT, PATCH, DELETE'
Access-Control-Allow-Headers: 'Origin, Content-Type, X-Auth-Token';

z tym wszystkim postem, get itp. będzie działać dobrze.

Sunil Kumar
źródło
5

W PHP możesz dodać nagłówki:

<?php
header ("Access-Control-Allow-Origin: *");
header ("Access-Control-Expose-Headers: Content-Length, X-JSON");
header ("Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS");
header ("Access-Control-Allow-Headers: *");
...
atiruz
źródło
dzięki, zadziałało dla mnie! w środowisku testowym i produkcyjnym. Nawet używając https: //
Jose Seie
1
@atiruz Dzięki za rozwiązanie. Działa to, gdy dodałem linięheader ("Access-Control-Expose-Headers: Content-Length, X-JSON");
Silambarasan RD
5

Aby rozwiązać problemy z żądaniami krzyżowania pochodzenia w aplikacji Node JS:

npm i cors

I po prostu dodaj poniższe linie do app.js

let cors = require('cors')
app.use(cors())
Rohit Parte
źródło
3
działa to tylko w aplikacjach ekspresowych js, nie we wszystkich aplikacjach węzłowych
DrCord
3

W moim pliku konfiguracyjnym Apache VirtualHost dodałem następujące linie:

Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Max-Age "1000"
Header always set Access-Control-Allow-Headers "x-requested-with, Content-Type, origin, authorization, accept, client-security-token"

RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]
hugsbrugs
źródło
3

Dla tych, którzy używają Lambda Integrated Proxy z API Gateway . Musisz skonfigurować swoją funkcję lambda tak, jakbyś przesyłał do niej swoje żądania bezpośrednio, co oznacza, że ​​funkcja powinna poprawnie skonfigurować nagłówki odpowiedzi. (Jeśli korzystasz z niestandardowych funkcji lambda, będzie to obsługiwane przez bramę API).

//In your lambda's index.handler():
exports.handler = (event, context, callback) => {
     //on success:
     callback(null, {
           statusCode: 200,
           headers: {
                "Access-Control-Allow-Origin" : "*"
           }
     }
}
Xu Chen
źródło
1
Chcę również włączyć się i wspomnieć o jednym wielkim gotcha Nie sądzę, żeby dokumenty AWS. Załóżmy, że używasz bramy API do proxy funkcji lambda i używasz API w tej funkcji lambda. Jeśli ten interfejs API zwróci kod powodzenia inny niż 200, a kod odpowiedzi inny niż 200 nie został dodany do odpowiedzi metody w bramce API, pojawi się błąd i nie zobaczysz swojej pomyślnej odpowiedzi . Przykłady tego: Sendgrid i Twilio mają kody sukcesu inne niż 200.
Stephen Tetreault
3

Myślę, że wyłączenie CORS z Chrome nie jest dobrym sposobem , ponieważ jeśli używasz go w trybie jonowym, z pewnością w Mobile Build problem znów się pojawi.

Więc lepiej naprawić w swoim backend.

Po pierwsze W nagłówku należy ustawić-

  • nagłówek („Access-Control-Allow-Origin: *”);
  • nagłówek („Zestaw nagłówków Kontrola dostępu - Zezwól na nagłówki:„ Pochodzenie, zapytanie o X, typ zawartości, akceptacja ””);

A jeśli API zachowuje się zarówno jako GET, jak i POST, ustaw także w nagłówku

if ($ _SERVER ['REQUEST_METHOD'] == 'OPCJE') {if (isset ($ _ SERVER ['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) nagłówek („Metody kontroli dostępu - Allow: GET, POST, OPCJE”);
if (isset ($ _ SERVER ['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) nagłówek ("Access-Control-Allow-Headers:
{$ _SERVER ['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}"); wyjście (0); }

Shubham Pandey
źródło
3

Bardzo częstą przyczyną tego błędu może być to, że interfejs API hosta zamapował żądanie na metodę http (np. PUT), a klient API wywołuje interfejs API przy użyciu innej metody http (np. POST lub GET)

Christian Nwafor
źródło
Poprawnie implementowałem CORS na moim serwerze, ale zapomniałem dodać PUTmetodę
fguillen,
3

Nasz zespół czasami widzi to za pomocą Vue, axios i C # WebApi. Dodanie atrybutu trasy w punkcie końcowym, który próbujesz trafić, naprawia go dla nas.

[Route("ControllerName/Endpoint")]
[HttpOptions, HttpPost]
public IHttpActionResult Endpoint() { }
w00ngy
źródło
Nie jesteśmy pewni, dlaczego. Lol. Jeśli ktoś mnie powiadomi!
w00ngy
1

Napotkałem ten problem, gdy serwer DNS był ustawiony na 8.8.8.8 (Google). W rzeczywistości problem tkwił w routerze, moja aplikacja próbowała połączyć się z serwerem za pośrednictwem google, a nie lokalnie (w moim konkretnym przypadku). Usunąłem 8.8.8.8 i to rozwiązało problem. Wiem, że to problemy rozwiązane przez ustawienia CORS, ale może ktoś będzie miał takie same problemy jak ja

Kirill Gusyatin
źródło
1

Używam AWS SDK do przesyłania, po spędzeniu czasu na wyszukiwaniu w Internecie natknąłem się na ten wątek. dzięki @lsimoneau 45581857 okazuje się, że działo się dokładnie to samo. Po prostu skierowałem swój adres URL żądania do regionu na moim wiadrze, dołączając opcję regionu i zadziałało.

 const s3 = new AWS.S3({
 accessKeyId: config.awsAccessKeyID,
 secretAccessKey: config.awsSecretAccessKey,
 region: 'eu-west-2'  // add region here });
davyCode
źródło
0

Autonomiczne dystrybucje GeoServer obejmują serwer aplikacji Jetty. Włącz udostępnianie zasobów między źródłami (CORS), aby umożliwić aplikacjom JavaScript spoza własnej domeny korzystanie z GeoServer.

Odkomentuj następujące <filter>i <filter-mapping>od webapps / geoserver / WEB-INF / web.xml:

<web-app>
  <filter>
      <filter-name>cross-origin</filter-name>
      <filter-class>org.eclipse.jetty.servlets.CrossOriginFilter</filter-class>
  </filter>
  <filter-mapping>
      <filter-name>cross-origin</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>
Yassine Ech-Charafi
źródło
To nie dodało antyhinga do nagłówka odpowiedzi, więc nie zadziałało
JollyRoger
1
nie korzystam z GeoServera, ale ten klip pomógł mi poznać ustawienia, których powinienem użyć w aplikacji odbierającej połączenie.
Matt Felzani,
0

Łatwo jest rozwiązać ten problem zaledwie kilkoma krokami, nie martwiąc się o nic. Prosimy postępować zgodnie z instrukcjami, aby go rozwiązać.

  1. otwarte ( https://www.npmjs.com/package/cors#enabling-cors-pre-flight )
  2. przejdź do instalacji i skopiuj polecenie npm install cors, aby zainstalować przez terminal węzła
  3. przejdź do Prostego użycia (Włącz wszystkie żądania CORS) przewijając. następnie skopiuj i wklej całą deklinację w swoim projekcie i uruchom ją ... to na pewno zadziała .. skopiuj kod komentarza i wklej w pliku ur.j.j lub innym projekt i spróbuj ... to zadziała. to odblokuje każde współdzielenie zasobów pochodzących z różnych źródeł .. więc możemy przełączać się między serwisami do użytku
Rahul Sah
źródło
1
var ekspres = wymaga („ekspres”) var cors = wymaga („cors”) var app = ekspres () app.use (cors ()) app.get ('/ products /: id', funkcja (req, res, next) {res.json ({msg: 'Ta funkcja obsługuje CORS dla wszystkich źródeł!'})}) app.listen (80, function () {console.log ('Serwer WWW z obsługą CORS nasłuchuje na porcie 80' ' )})
Rahul sah,
-1

Coś, co bardzo łatwo przeoczyć ...

W eksploratorze rozwiązań kliknij prawym przyciskiem myszy projekt api. W oknie właściwości ustaw „Anonimowe uwierzytelnianie” na Włączone !!!

Wes
źródło
-8

Wyłącz chromowane zabezpieczenie. Utwórz chromowane kliknięcie prawym przyciskiem myszy -> właściwości -> cel, wklej to „C: \ Program Files (x86) \ Google \ Chrome \ Application \ chrome.exe” - wyłącz-web-bezpieczeństwo - użytkownik -data-dir = "c: / chromedev"

Nithin
źródło