Pytanie Dlaczego mój JavaScript otrzymuje "Nie" nagłówek "Access-Control-Allow-Origin" pojawia się w żądanym zasobie ", gdy Postman nie?


Próbuję wykonać autoryzację za pomocą JavaScript łącząc się z Spokojny  API wbudowany Kolba. Jednak po zgłoszeniu żądania pojawia się następujący błąd:

XMLHttpRequest nie można załadować http: // myApiUrl / login. Na żądanym zasobie nie ma nagłówka "Access-Control-Allow-Origin". Pochodzenie "null" jest zatem niedozwolone.

Wiem, że interfejs API lub zdalny zasób musi ustawić nagłówek, ale dlaczego zadziałał, gdy wysłałem żądanie przez rozszerzenie przeglądarki Chrome Listonosz?

To jest kod żądania:

$.ajax({
    type: "POST",
    dataType: 'text',
    url: api,
    username: 'user',
    password: 'pass',
    crossDomain : true,
    xhrFields: {
        withCredentials: true
    }
})
    .done(function( data ) {
        console.log("done");
    })
    .fail( function(xhr, textStatus, errorThrown) {
        alert(xhr.responseText);
        alert(textStatus);
    });

1869
2017-11-17 19:29


pochodzenie


Czy robisz żądanie z hosta lokalnego lub bezpośrednio wykonujesz kod HTML? - MD. Sahib Bin Mahboob
@ MD.SahibBinMahboob Jeśli rozumiem twoje pytanie, robię żądanie z localhost - mam stronę na moim komputerze i po prostu ją uruchomię. Kiedy wdrażam witrynę na serwerze, daje to ten sam rezultat. - Mr Jedi
czy domena twojej wykonanej strony i żądanej nazwy domeny jest taka sama czy inna? - MD. Sahib Bin Mahboob
wiele związanych: stackoverflow.com/questions/10143093/... - cregox
Dla każdego, kto szuka więcej czytania, MDN ma dobry artykuł na temat wszystkich zapytań ajaxowych i krzyżowych: developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS - Sam Eaton


Odpowiedzi:


Jeśli dobrze to zrozumiałem, robisz XMLHttpRequest do innej domeny niż jest włączona. Tak więc przeglądarka blokuje je, ponieważ zwykle pozwala na żądanie z tego samego źródła ze względów bezpieczeństwa. Musisz zrobić coś innego, gdy chcesz wykonać żądanie między domenami. Samouczek o tym, jak to osiągnąć Korzystanie z CORS.

Kiedy używasz listonosza, nie są one ograniczone przez tę zasadę. Cytowane z XMLHttpRequest Cross-Origin:

Zwykłe strony internetowe mogą używać obiektu XMLHttpRequest do wysyłania i odbierania danych ze zdalnych serwerów, ale są ograniczone przez tę samą zasadę pochodzenia. Rozszerzenia nie są tak ograniczone. Rozszerzenie może rozmawiać ze zdalnymi serwerami spoza jego źródła, o ile najpierw zażąda uprawnień z różnych źródeł.


1008
2017-11-17 19:49



Masz rację. Robię żądanie do innej domeny niż moja strona. API jest na serwerze i uruchamiam żądanie z localhost. Zanim zaakceptuję odpowiedź, możesz wyjaśnić mi, co oznacza "bezpośrednie wykonanie żądania"? POSTMAN nie używa domeny? - Mr Jedi
Przeglądarka nie blokuje żądania. Jedynymi przeglądarkami, które jawnie blokują żądania ajaxowe dla różnych źródeł, jest IE7 lub starszy. Wszystkie przeglądarki, inne niż IE7 i starsze, implementują specyfikację CORS (częściowo IE8 i IE9). Wystarczy, że zalogujesz się na żądanie CORS na swoim serwerze API, zwracając odpowiednie nagłówki na podstawie żądania. Powinieneś przeczytać o koncepcjach CORS na stronie mzl.la/VOFrSz. Listonosz wysyła również żądania za pośrednictwem XHR. Jeśli nie widzisz tego samego problemu podczas korzystania z listonosza, oznacza to, że nieświadomie nie wysyłasz tego samego żądania za pośrednictwem listonosza. - Ray Nicholus
@ MD.SahibBinMahboob Listonosz NIE wysyła zapytania "z twojego java / pythona" kodu. Wysyła żądanie bezpośrednio z przeglądarki. XHR w rozszerzeniach Chrome działa nieco inaczej, zwłaszcza jeśli chodzi o żądania różnych źródeł. - Ray Nicholus
@Tak to przeglądarka faktycznie narzuciła regułę. Dlatego też żądanie uruchomienia z dowolnego miejsca zamiast przeglądarki powinno działać - MD. Sahib Bin Mahboob
@SuhailGupta, jeśli zezwolisz na pochodzenie na serwerze, będzie można wykonać żądanie, które jest znane jako CORS. - MD. Sahib Bin Mahboob


Nie jest to poprawka do produkcji lub gdy aplikacja ma być pokazywana klientowi, jest to przydatne tylko w przypadku interfejsu użytkownika i zaplecza rozwój  są na innym serwery a podczas produkcji są na tym samym serwerze. Na przykład: Podczas tworzenia interfejsu użytkownika dla dowolnej aplikacji, jeśli istnieje potrzeba przetestowania go lokalnie, kierując go na serwer zaplecza, w tym scenariuszu jest to idealna poprawka. W przypadku poprawki produkcyjnej nagłówki CORS muszą zostać dodane do serwera zaplecza, aby umożliwić dostęp z krzyżowym początkiem.

Prostym sposobem jest dodanie rozszerzenia w Google Chrome, aby umożliwić dostęp za pomocą CORS.

(https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=en)

Po prostu włącz to rozszerzenie, gdy chcesz zezwolić na dostęp do numeru "access-control-allow-origin" żądanie nagłówka.

Lub 

W systemie Windows wklej to polecenie w biegać okno

chrome.exe --user-data-dir="C:/Chrome dev session" --disable-web-security

to otworzy nowe chrom przeglądarka, która umożliwia dostęp do nr "access-control-allow-origin" żądanie nagłówka.


450
2018-03-04 06:42



To jest świetne, ale klienci nie mogą zostać poproszeni o uruchomienie Chrome w ten sposób, aby wymusić wewnętrzny wymóg wywołania usługi sieciowej. - Taersious
to nie powinno być akceptowane jako odpowiedź, instalowanie wtyczki innej firmy w celu naprawienia aplikacji, zamiast zrozumienia CORS i naprawienia aplikacji, w jaki sposób inne osoby będą korzystały z twojego interfejsu API? sprawisz, że wszystkie zainstalują tę wtyczkę - James Kirkby
Zainstalowałem to rozszerzenie i wykonałem żądanie, niż sprawdziłem żądanie w skrzypku, podano następujące -> Pochodzenie: evil.com . Wygląda na to, że to rozszerzenie zmienia Origin na evil.com - wagwanJahMan
To rozszerzenie działa jak urok. Ale naprawdę, co robią wewnętrznie? Czy istnieje sposób, aby zrobić to samo w JavaScript lub sposób Jquery zamiast korzystania z wtyczki? - sms
Myślę, że to naprawdę świetna odpowiedź jeśli nie potrzebujesz stałej poprawki lub potrzebujesz tymczasowo wyłączenia CORS. Tego właśnie potrzebowałem i to rozwiązanie działało świetnie. Oczywiście nie można tego nigdy uznać za rozwiązanie trwałe. - jtcotton63


Jeśli możesz sobie z tym poradzić JSON w zamian, a następnie spróbuj użyć JSONP (zanotuj P na końcu) do mówienia między domenami:

$.ajax({
  type: "POST",
  dataType: 'jsonp',
  ...... etc ......

Dowiedz się więcej o pracy z JSONP tutaj:

Pojawienie się JSONP - w zasadzie zgodnego z regułami cross-site scripting - otworzyło drzwi do potężnych mashupów treści. Wiele znanych witryn zapewnia usługi JSONP, umożliwiając dostęp do ich treści za pośrednictwem predefiniowanego interfejsu API.


312
2018-02-22 00:42



Należy pamiętać, że jsonp nie działa w przypadku treści POST. Więcej dyskusji tutaj. - Prabu Raja
Jak to ma tak wiele głosów w górę, kiedy nie można używać jsonp z żądaniami POST?!?! - fatlog
Kiedy używasz JSONP, $ .ajax zignoruje type, więc to zawsze GET co oznacza, że ​​ta odpowiedź zawsze będzie działać. - noob
Wygląda na to, że ponad 200 osób po prostu tego nie robi - cs01
Zauważ też, że JSONP nie jest bezpośrednio wymienny z JSON. Potrzebujesz serwer również zwrócić dane w formacie JSONP. Po prostu zmieniając dataType w samych ustawieniach żądania AJAX nie będzie działać. - Rory McCrossan


Jest bardzo prosty do rozwiązania, jeśli używasz PHP. Wystarczy dodać następujący skrypt na początku swojej strony PHP, która obsługuje żądanie:

<?php header('Access-Control-Allow-Origin: *'); ?>

Ostrzeżenie: Zawiera problem bezpieczeństwa dla twojego pliku PHP, który może zostać wywołany przez napastników. musisz użyć sesji i plików cookie do uwierzytelnienia, aby zapobiec twojemu plikowi / usłudze przed tym atakiem. Twoja usługa jest podatna na ataki fałszywe zapytanie o witrynę (CSRF).

Jeśli używasz Węzeł-czerwony musisz zezwolić CORS na node-red/settings.js plik przez nie komentowanie następujących wierszy:

// The following property can be used to configure cross-origin resource sharing
// in the HTTP nodes.
// See https://github.com/troygoode/node-cors#configuration-options for
// details on its contents. The following is a basic permissive set of options:
httpNodeCors: {
 origin: "*",
 methods: "GET,PUT,POST,DELETE"
},

185
2017-12-03 20:24



W ogóle nie chodziło o PHP. - mknaf
i to nie jest bezpieczne - llazzaro
Nie powinieneś wyłączyć CORS, bo nie wiesz, po co to jest. To jest straszna odpowiedź. - meagar♦
Chociaż może nie być to bezpieczne, pytanie nie dotyczyło bezpieczeństwa, ale sposobu wykonania tego zadania. Jest to jedna z opcji, które musi wybrać programista w przypadku żądań AJAX w wielu domenach. Pomogło mi to rozwiązać problem, a dla mojej aplikacji nie obchodzi mnie, skąd pochodzą dane. Usuwam wszystkie dane wejściowe za pomocą PHP w domenie docelowej, więc jeśli ktoś chce wysłać do niego trochę śmieci, niech spróbuje. Główną kwestią jest to, że AJAX między domenami może być dozwolona z domeny docelowej. +1 za odpowiedź. - ZurabWeb
Chociaż zgadzam się z ogólnym przesłaniem, które przekazuje Piero, nie chodzi tu konkretnie o bezpieczeństwo, ale bezpieczeństwo to problem. Myślę, że powinno to przynajmniej powiedzieć coś w rodzaju: "Ogólnie jest źle! Nie rób tego, chyba że wiesz, co robisz. Oto więcej dokumentacji na ten temat: ..." i może krótko wyjaśnić dlaczego. Nie chciałbym, żeby ktoś tu przychodził i pomyślał: "Och, mogę po prostu dodać / dostosować ten nagłówek i jestem dobry!" i nie zna pełnych konsekwencji. Mam na myśli, że to na nich polega badanie i wszystko, ale wciąż. - Thomas F.


Chciałbym, żeby ktoś już dawno temu udostępnił mi tę stronę http://cors.io/ zaoszczędziłoby to mnóstwo czasu w porównaniu do budowy i polegania na moim własnym proxy. Jednak w miarę przechodzenia do produkcji najlepsze jest posiadanie własnego serwera proxy, ponieważ wciąż kontrolujesz wszystkie aspekty danych.

Wszystko czego potrzebujesz:

https://cors.io/?http://HTTP_YOUR_LINK_HERE


143
2017-07-21 22:08



Jakie są wady tego? Czy to oni przechwytują moje dane? - Sebastialonso
cors.io/?u=HTTP_YOUR_LINK_HERE     (mała korekta) - jkpd
Nie sądzę, żeby wysyłanie twoich danych przez proxy pośredniczące było dobrym pomysłem - Daniel Alexandrov
Jedną wadą jest to, że czasami są przeciążone, tak jak teraz. This application is temporarily over its serving quota. Please try again later. - Daniel Hickman
spróbuj też https://crossorigin.me/http://example.com - KingRider


Wystąpił problem z wieloma domenami za pomocą Ajax. Musisz mieć pewność, że uzyskujesz dostęp do swoich plików na tym samym http:// ścieżka bez www. (lub dostęp z http://www. i opublikuj na tej samej ścieżce, w tym www.), które przeglądarka uważa za inną domenę podczas uzyskiwania dostępu poprzez www. ścieżkę, aby zobaczyć, gdzie jest problem. Publikujesz w innej domenie, a przeglądarka blokuje przepływ z powodu problemu pochodzenia.

Jeśli API nie jest umieszczony na tym samym hoście, z którego żądasz, przepływ jest zablokowany i musisz znaleźć inny sposób komunikacji z interfejsem API.


61
2018-03-12 08:53



Tak, byłem zmuszony do tego w mojej aplikacji do gry w telefon, var app_url = location.protocol + '//' + location.host + '/ api /. problemem była strona z www. przedłożony spowodowałby ten błąd. - Sir Lojik


Jeśli używasz Node.js, Spróbuj:

app.use(function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    next();
});

Więcej informacji: CORS na ExpressJS


55
2018-02-12 16:27



Daję wam prawo głosu, ponieważ jest to dokładnie to, czego potrzebowałem. Ale myślę, że promowanie "*" nie jest dobrym pomysłem bez wyjaśnienia, że ​​pozwoli to na jakiekolwiek połączenie i nie powinno być używane w produkcji. Zostało to wyjaśnione na łączu MDN developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS. - rob
@rob dzięki za komentarz. Masz rację, powinniśmy określić, które pochodzenie może wykorzystywać zasoby. Ale na wszelki wypadek, zasoby wykorzystywane do celów publicznych i nie znamy konsumentów, myślę, że powinniśmy pójść z "*", jeśli się nie mylę. - Nguyen Tran
Użyłem tej koncepcji i mój problem został rozwiązany w nodejs. Dzięki - Deepak Bhatta
app.use (function (req, res, next) {res.setHeader ('Access-Control-Allow-Origin', '*'); res.setHeader ('Access-Control-Allow-Methods', 'GET, POST , OPCJE, PUT, PATCH, DELETE "); res.setHeader (" Access-Control-Allow-Headers "," X-Requested-With, typ zawartości, autoryzacja "); res.setHeader ('Access-Control-Allow -Credentials ", true); if (" OPCJE "=== req.method) {res.send (204);} else {next ();}}); - Ricky sharma
Dotyczące niebezpieczeństw użytkowania "Access-Control-Allow-Origin", "*", widzieć security.stackexchange.com/a/45677. tldr: Specyfikacja W3 precyzuje, że: Zasób, który jest publicznie dostępny, bez kontroli kontroli dostępu, zawsze może bezpiecznie zwrócić nagłówek Access-Control-Allow-Origin o wartości "*" - CODE-REaD


Bo
$ .ajax ({type: "POST"  - Połączenia OPCJE 
$ .post ( - Połączenia STANOWISKO 

obydwa są różne wywołania listonoszy "POST", ale kiedy zadzwonimy, będą to "OPCJE"

Dla usług internetowych c # - webapi 

Dodaj następujący kod do pliku web.config w tagu <system.webServer>. To zadziała

<httpProtocol>
    <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
    </customHeaders>
</httpProtocol>

Upewnij się, że nie robisz żadnego błędu w wywołaniu ajax

jQuery

$.ajax({
    url: 'http://mysite.microsoft.sample.xyz.com/api/mycall',
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
    },
    type: "POST", /* or type:"GET" or type:"PUT" */
    dataType: "json",
    data: {
    },
    success: function (result) {
        console.log(result);    
    },
    error: function () {
        console.log("error");
    }
});

Zagadka kątowa 4 proszę odnieść się: http://www.hubfly.com/blog/solutions/how-to-fix-angular-4-api-call-issues/

Uwaga: Jeśli szukasz treści do pobrania ze strony internetowej osoby trzeciej następnie to ci nie pomoże. Możesz wypróbować poniższy kod, ale nie JavaScript.

System.Net.WebClient wc = new System.Net.WebClient();
string str = wc.DownloadString("http://mysite.microsoft.sample.xyz.com/api/mycall");

41
2017-12-13 13:02



Ta konfiguracja rozwiązała ten sam błąd w Wordpressie w Usługach Azure. Dzięki. - Andre Mesquita
Sugerowałbym użycie określonej wartości początkowej, aby uniknąć żądań z zewnętrznych domen. Na przykład zamiast * posługiwać się https://www.myotherdomain.com - pechar