Dlaczego mój kod JavaScript otrzymuje błąd "Brak nagłówka 'Access-Control-Allow-Origin' na żądanym zasobie", podczas gdy listonosz nie?

MOD note: to pytanie dotyczy tego, dlaczego listonosz nie podlega ograniczeniom CORS w taki sam sposób jak XMLHttpRequest. To pytanie jest NIE o tym, jak naprawić "brak' kontroli dostępu-Zezwalaj na pochodzenie'..."błąd.

Proszę przestać pisać :


Próbuję wykonać autoryzację używając JavaScript {[15] } łącząc się z RESTful API wbudowane Flask. Jednak, kiedy składam wniosek, dostaję następujący błąd:

XMLHttpRequest nie może załadować http://myApiUrl/login . Nie ma nagłówka' Access-Control-Allow-Origin ' na żądany zasób. Origin 'null' nie ma zatem dostępu.

Wiem, że API lub zdalny zasób musi ustawić nagłówek, ale dlaczego to działało, gdy złożyłem żądanie przez rozszerzenie Chrome Postman?

To jest kod zapytania:

$.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);
    });
Author: Ian Kemp, 2013-11-17

11 answers

Jeśli dobrze zrozumiałem robisz XMLHttpRequest do innej domeny niż Twoja strona jest na. Tak więc przeglądarka blokuje ją, ponieważ zwykle zezwala na żądanie w tym samym miejscu pochodzenia ze względów bezpieczeństwa. Musisz zrobić coś innego, jeśli chcesz wykonać żądanie między domenami. Tutorial o tym jak to osiągnąć jest Korzystanie z CORS.

Kiedy korzystasz z listonosza, nie są one ograniczone przez tę politykę. Cytowany z Cross-Origin XMLHttpRequest:

Zwykłe strony internetowe mogą używać obiektu XMLHttpRequest do wysyłania i odbierania danych ze zdalnych serwerów, ale są one ograniczone tą samą Polityką origin. Rozszerzenia nie są tak ograniczone. Rozszerzenie może rozmawiać ze zdalnymi serwerami spoza swojego źródła, o ile najpierw zażąda uprawnień cross-origin.

 1429
Author: MD. Sahib Bin Mahboob,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-23 00:46:57

WARNING: Korzystanie z Access-Control-Allow-Origin: *może sprawić, że Twój API/strona internetowa będzie podatna na ataki cross-site request forgery (CSRF). Upewnij się, że rozumiesz ryzyko przed użyciem tego kodu.

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

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

Jeśli używasz node-red musisz zezwolić CORS w pliku node-red/settings.js nie komentując następujących linijek:

// 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"
},

Jeśli używasz Flask to samo co pytanie; musisz najpierw zainstalować flask-cors

$ pip install -U flask-cors

Następnie dołącz Cors kolby do aplikacji.

from flask_cors import CORS

Prosta aplikacja będzie wyglądać następująco:

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

@app.route("/")
def helloWorld():
  return "Hello, cross-origin-world!"

Więcej szczegółów można znaleźć w dokumentacji kolby .

 279
Author: Shady Mohamed Sherif,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-27 03:06:55

Ponieważ
$.ajax({type: "POST" - calls OPTIONS
$.post ( - wywołania POST

Oba są różne. Listonosz prawidłowo nazywa "POST", ale kiedy go wywołamy, będzie to "opcje".

Dla C# web services- Web API

Proszę dodać poniższy kod w swojej stronie.plik config W tag. To zadziała:

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

Upewnij się, że nie robisz żadnego błędu w Ajaxie call

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");
    }
});

Uwaga: Jeśli szukasz pobierania zawartości z zewnętrznej strony internetowej, to to Ci nie pomoże. Możesz wypróbować następujący kod, ale nie JavaScript.

System.Net.WebClient wc = new System.Net.WebClient();
string str = wc.DownloadString("http://mysite.microsoft.sample.xyz.com/api/mycall");
 72
Author: George Livingston,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

W poniższym dochodzeniu jako API używam http://example.com zamiast http://myApiUrl/login z twojego pytania, bo to pierwsze działa.

Zakładam, że Twoja strona jest na http://my-site.lokalne:8088.

Powodem, dla którego widzisz różne wyniki, Jest to, że listonosz:

  • set header Host=example.com (twoje API)
  • nie ustawia nagłówka Origin

Jest to podobne do sposobu wysyłania żądań przez przeglądarki gdy strona i API mają tę samą domenę (przeglądarki ustawiają również element nagłówka Referer=http://my-site.local:8088, jednak nie widzę go w Postmanie). gdy Origin nagłówek jest ustawiony , a nie, zazwyczaj serwery domyślnie zezwalają na takie żądania.

Tutaj wpisz opis obrazka

Jest to standardowy sposób, w jaki Listonosz wysyła żądania. Ale przeglądarka wysyła żądania inaczej, gdy Twoja strona i API mają różne domeny , a następnie CORS i przeglądarka automatycznie:

  • ustawia nagłówek Host=example.com (twój jako API)
  • ustawia nagłówek Origin=http://my-site.local:8088 (Twoja strona)

(nagłówek Referer ma taką samą wartość jak Origin). A teraz w zakładce Chrome ' A Console & Networks zobaczysz:

Tutaj wpisz opis obrazka

Tutaj wpisz opis obrazka

Kiedy masz Host != Origin jest to CORS, a gdy serwer wykryje takie żądanie, zazwyczaj blokuje je domyślnie.

Origin=null jest ustawiony, gdy Otwórz zawartość HTML z lokalnego katalogu i wyśle żądanie. Podobnie jest w przypadku wysłania żądania wewnątrz <iframe>, jak w poniższym fragmencie (ale tutaj nagłówek Host nie jest w ogóle ustawiony) - ogólnie, wszędzie tam, gdzie Specyfikacja HTML mówi o nieprzezroczystym pochodzeniu, można to przetłumaczyć na Origin=null. Więcej informacji na ten temat można znaleźć tutaj .

fetch('http://example.com/api', {method: 'POST'});
Look on chrome-console > network tab

Jeśli nie korzystasz z prostego żądania CORS, zazwyczaj przeglądarka automatycznie również wysyła żądanie opcji przed wysłaniem głównego żądania-więcej informacji znajduje się tutaj . Poniższy fragment pokazuje to:

fetch('http://example.com/api', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json'}
});
Look in chrome-console -> network tab to 'api' request.
This is the OPTIONS request (the server does not allow sending a POST request)

Możesz zmienić konfigurację serwera, aby zezwolić na żądania CORS.

Jest to bardzo proste i łatwe w obsłudze narzędzie, które pozwala na szybkie i łatwe uruchamianie aplikacji.plik conf) - bądź bardzo ostrożny z ustawieniem always/"$http_origin" dla nginx i "*" dla Apache - odblokuje to CORS z dowolnego domena.

location ~ ^/index\.php(/|$) {
   ...
    add_header 'Access-Control-Allow-Origin' "$http_origin" always;
    add_header 'Access-Control-Allow-Credentials' 'true' always;
    if ($request_method = OPTIONS) {
        add_header 'Access-Control-Allow-Origin' "$http_origin"; # DO NOT remove THIS LINES (doubled with outside 'if' above)
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Max-Age' 1728000; # cache preflight value for 20 days
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'My-First-Header,My-Second-Header,Authorization,Content-Type,Accept,Origin';
        add_header 'Content-Length' 0;
        add_header 'Content-Type' 'text/plain charset=UTF-8';
        return 204;
    }
}

Oto przykładowa konfiguracja, która włączaCORS na Apache (.plik htaccess)

# ------------------------------------------------------------------------------
# | Cross-domain Ajax requests                                                 |
# ------------------------------------------------------------------------------

# Enable cross-origin Ajax requests.
# http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity
# http://enable-cors.org/

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

# Header set Header set Access-Control-Allow-Origin "*"
# Header always set Access-Control-Allow-Credentials "true"

Access-Control-Allow-Origin "http://your-page.com:80"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Allow-Headers "My-First-Header,My-Second-Header,Authorization, content-type, csrf-token"
 20
Author: Kamil Kiełczewski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-26 19:09:53

Stosowanie ograniczenia CORS jest funkcją bezpieczeństwa zdefiniowaną przez serwer i zaimplementowaną przez przeglądarkę .

Przeglądarka patrzy na politykę Kors serwera i szanuje ją.

Jednak Narzędzie Postman nie przejmuje się polityką CORS serwera.

Dlatego błąd CORS pojawia się w przeglądarce, ale nie w Postmanie.

 14
Author: Gopinath,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-08 18:09:04

Napotkał ten sam błąd w różnych przypadkach użycia.

Przypadek użycia: w chrome, gdy próbowano wywołać Spring REST punkt końcowy w kącie.

Tutaj wpisz opis obrazka

Rozwiązanie: Add @ CrossOrigin("*") adnotacja na górze odpowiedniej klasy kontrolera.

Tutaj wpisz opis obrazka

 9
Author: Kms,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-05-25 05:45:54

Jeśli chcesz ominąć to ograniczenie podczas pobierania zawartości za pomocą API fetch lub XMLHttpRequest w javascript, możesz użyć serwera proxy, aby ustawić nagłówek Access-Control-Allow-Origin na *.

const express = require('express');
const request = require('request');

const app = express();

app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  next();
});

app.get('/fetch', (req, res) => {
  request(
    { url: req.query.url },
    (error, response, body) => {
      if (error || response.statusCode !== 200) {
        return res.status(500).send('error');
      }
      res.send(body);
    }
  )
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`listening on ${PORT}`));

Powyżej znajduje się przykładowy kod (wymagany węzeł Js), który może działać jako serwer proxy. Na przykład: jeśli chcę pobrać https://www.google.com normalnie błąd CORS jest wyrzucany, ale teraz, ponieważ żądanie jest wysyłane przez serwer proxy hostowany lokalnie na porcie 3000, serwer proxy dodaje nagłówek Access-Control-Allow-Origin w odpowiedzi i nie będzie żadnego problemu.

Wyślij zapytanie GET do http://localhost:3000/fetch?url = Your URL here, zamiast bezpośrednio wysyłać żądanie na adres URL, który chcesz pobrać.

Your URL here oznacza adres URL, który chcesz pobrać np: https://www.google.com

 6
Author: Adwaith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-21 17:06:46

Tylko dla projektu. NET Core Web API, dodaj następujące zmiany:

  1. Dodaj następujący kod po linii services.AddMvc() w metodzie ConfigureServices() uruchamiania.plik cs:
services.AddCors(allowsites=>{allowsites.AddPolicy("AllowOrigin", options => options.AllowAnyOrigin());
            });
  1. Dodaj następujący kod po linii app.UseMvc() w metodzie Configure() uruchamiania.plik cs:
app.UseCors(options => options.AllowAnyOrigin());
  1. Otwórz kontroler, do którego chcesz uzyskać dostęp poza domeną i dodaj następujący atrybut na poziomie kontrolera:
[EnableCors("AllowOrigin")]
 2
Author: Shakti Srivastav,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-04-18 17:24:00

Otrzymany błąd wynika ze standardu CORS, który określa pewne ograniczenia dotyczące sposobu wykonywania żądań ajax przez JavaScript.

Standard CORS jest Standardem po stronie klienta, zaimplementowanym w przeglądarce. Tak więc to przeglądarka uniemożliwia zakończenie połączenia i generuje komunikat o błędzie - Nie serwer.

Listonosz nie implementuje ograniczeń Kors, dlatego nie widzisz tego samego błędu podczas wykonywania tego samego połączenia od listonosza.

 1
Author: JacquesB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-01-09 21:37:06

Jeśli używasz. NET jako warstwy środkowej, sprawdź wyraźnie atrybut trasy, na przykład

Miałem problem, kiedy to było tak,

[Route("something/{somethingLong: long}")] //Space.

Naprawiłem to przez to,

[Route("something/{somethingLong:long}")] //No space
 -1
Author: Sai Vaibhav Medavarapu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-09 17:08:51

Czy używasz Webfontów z Google, Typekit, itp? Istnieje wiele sposobów, w jakie można użyć metod Webfontów, takich jak @font-face lub CSS3, niektóre przeglądarki, takie jak Firefox i IE, mogą odmówić osadzenia czcionki, gdy pochodzi ona z niestandardowego adresu URL strony trzeciej (np.

Aby rozwiązać problem na swoim blogu WordPress, po prostu umieść poniżej w swoim .plik htaccess.

<IfModule mod_headers.c>
  <FilesMatch "\.(ttf|ttc|otf|eot|woff|woff2|font.css|css|js)$">
  Header set Access-Control-Allow-Origin "*"
  </FilesMatch>
</IfModule>

Źródło : https://crunchify.com/how-to-fix-access-control-allow-origin-issue-for-your-https-enabled-wordpress-site-and-maxcdn/

 -1
Author: Mizhar Raja,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-12-06 01:02:37