Perché Postman non visualizza un errore "Nessuna intestazione 'Accesso-Controllo-Consenti-Origine' presente sulla risorsa richiesta" quando viene visualizzato il mio codice JavaScript?


2503

Nota Mod : questa domanda riguarda il motivo per cui Postman non è soggetto alle restrizioni CORS allo stesso modo di un XMLHttpRequest. Questa domanda non riguarda come correggere l'errore "No 'Access-Control-Allow-Origin' ...".

Si prega di interrompere la pubblicazione :


Sto provando a fare l'autorizzazione usando JavaScript collegandomi al pallone integrato RESTful API . Tuttavia, quando invio la richiesta, viene visualizzato il seguente errore:

XMLHttpRequest non può caricare http: // myApiUrl / login . Nessuna intestazione 'Access-Control-Allow-Origin' è presente sulla risorsa richiesta. L'origine 'null' non è quindi consentita l'accesso.

So che l'API o la risorsa remota deve impostare l'intestazione, ma perché ha funzionato quando ho effettuato la richiesta tramite l'estensione Postman di Chrome ?

Questo è il codice di richiesta:

$.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);
    });

32
Stai facendo la richiesta da localhost o stai eseguendo direttamente HTML?
MD. Sahib Bin Mahboob,

@ MD.SahibBinMahboob Se capisco la tua domanda, faccio richiesta da localhost - Ho una pagina sul mio computer e la eseguo. Quando distribuisco il sito sull'hosting ha dato lo stesso risultato.
Mr Jedi,


8
Per tutti coloro che sono alla ricerca di ulteriori letture, MDN ha un buon articolo su ajax e richieste di origine incrociata: developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
Sam Eaton,

1
Una nota importante per questo tipo di errore nel nodo js. DEVI impostare le intestazioni di accesso all'avvio del file server.js PRIMA di iniziare a configurare i percorsi. Altrimenti, tutto funzionerà alla grande, ma otterrai questo errore quando effettui richieste dalla tua app.
Alex J,

Risposte:


1346

Se ho capito bene, stai facendo un XMLHttpRequest a un dominio diverso da quello della tua pagina. Quindi il browser lo sta bloccando poiché di solito consente una richiesta nella stessa origine per motivi di sicurezza. Devi fare qualcosa di diverso quando vuoi fare una richiesta tra domini. Un tutorial su come raggiungere questo obiettivo è l' utilizzo di CORS .

Quando si utilizza postino non sono limitati da questa politica. Citato da XMLHttpRequest Cross-Origin :

Le pagine Web normali possono utilizzare l'oggetto XMLHttpRequest per inviare e ricevere dati da server remoti, ma sono limitate dalla stessa politica di origine. Le estensioni non sono così limitate. Un'estensione può comunicare con server remoti al di fuori della sua origine, purché richieda per la prima volta autorizzazioni di origine incrociata.


7
Hai ragione. Sto facendo richiesta a un dominio diverso rispetto alla mia pagina. L'API è sul server ed eseguo la richiesta da localhost. Prima di accettare la risposta puoi spiegarmi cosa significa "eseguire direttamente la richiesta"? POSTMAN non usa il dominio?
Mr Jedi,

181
Il browser non sta bloccando la richiesta. L'unico browser che blocca completamente le richieste Ajax tra le origini è IE7 o precedente. Tutti i browser, tranne IE7 e precedenti, implementano le specifiche CORS (IE8 e IE9 in parte). Tutto quello che devi fare è attivare le richieste CORS sul tuo server API restituendo le intestazioni appropriate in base alla richiesta. Dovresti leggere i concetti di CORS su mzl.la/VOFrSz . Postman invia anche richieste tramite XHR. Se non si riscontra lo stesso problema durante l'utilizzo di postman, ciò significa che inconsapevolmente non si sta inviando la stessa richiesta tramite postman.
Ray Nicholus,

10
@ MD.SahibBinMahboob Postman NON sta inviando una richiesta "dal tuo codice java / python". Sta inviando la richiesta direttamente dal browser. XHR nelle estensioni di Chrome funziona in modo leggermente diverso, specialmente quando sono coinvolte richieste di origine incrociata .
Ray Nicholus,

250

ATTENZIONE: l' uso Access-Control-Allow-Origin: *può rendere la tua API / sito Web vulnerabile agli attacchi di falsificazione delle richieste tra siti (CSRF). Assicurati di comprendere i rischi prima di utilizzare questo codice.

È molto semplice da risolvere se si utilizza PHP . Aggiungi il seguente script all'inizio della tua pagina PHP che gestisce la richiesta:

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

Se si utilizza Nodo-rosso, è necessario consentire CORS nel node-red/settings.jsfile annullando il commento delle seguenti righe:

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

Se stai usando Flask come la domanda; devi prima installareflask-cors

$ pip install -U flask-cors

Quindi includere il corsetto Flask nella propria applicazione.

from flask_cors import CORS

Una semplice applicazione sarà simile a:

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

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

Per ulteriori dettagli, è possibile controllare la documentazione di Flask .


93
e non è sicuro
llazzaro il

153
Non dovresti disattivare CORS perché non sai a cosa serve. Questa è una risposta terribile.
meagar

124
Anche se potrebbe non essere sicuro, la domanda non riguardava la sicurezza, ma come eseguire l'operazione. Questa è una delle opzioni tra le quali uno sviluppatore deve scegliere per gestire le richieste AJAX tra domini. Mi ha aiutato a risolvere il problema e, per la mia applicazione, non mi interessa da dove provengono i dati. Igienizzo tutti gli input con PHP sul dominio di destinazione, quindi, se qualcuno vuole postare un po 'di spazzatura, lasciali provare. Il punto principale qui è che AJAX tra domini può essere consentito dal dominio di destinazione. +1 per la risposta.
ZurabWeb,

23
Mentre sono d'accordo con il messaggio generale che Piero sta dando, non si tratta specificamente di sicurezza, ma la sicurezza è una preoccupazione. Penso che questo avrebbe dovuto almeno dire qualcosa del tipo "Questo è generalmente negativo! Non farlo a meno che tu non sappia cosa stai facendo! Ecco più documentazione su di esso: ...", e forse spiegare brevemente perché. Odio che qualcuno venga qui e pensi semplicemente "Oh, posso solo aggiungere / regolare questa intestazione e sto bene!" e non conosco le ramificazioni complete. Voglio dire, è un po 'su di loro per la ricerca e tutto, ma ancora.
Thomas F.

4
Mi piace questa risposta ... Ho lo stesso problema e lo risolve ... Ha spiegato che ci sono alcuni problemi di sicurezza, ma questo è un altro problema e lascia che ognuno pensi e risolva quel problema ...
Ari Waisberg

64

Perché
$ .ajax ({type: "POST" - chiama OPTIONS
$ .post ( - Chiama POST

Entrambi sono diversi. Il postino chiama correttamente "POST", ma quando lo chiamiamo, sarà "OPZIONI".

Per i servizi Web C # - API Web

Aggiungi il seguente codice nel tuo file web.config nel tag <system.webServer>. Questo funzionerà:

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

Assicurati di non commettere errori nella chiamata 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");
    }
});

Nota: Se siete alla ricerca di download di contenuti da un sito web di terze parti , allora questo non vi aiuterà . Puoi provare il seguente codice, ma non JavaScript.

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

Questa configurazione ha risolto lo stesso errore su Wordpress nei servizi di Azure. Grazie.
Andre Mesquita,

9
Suggerirei di utilizzare un valore di origine specifico per evitare richieste da domini esterni. Quindi, per esempio invece di *usarehttps://www.myotherdomain.com
pechar


8

L'applicazione di una limitazione CORS è una funzione di sicurezza definita da un server e implementata da un browser .

Il browser esamina la politica CORS del server e la rispetta.

Tuttavia, lo strumento Postman non si preoccupa della politica CORS del server.

Ecco perché l'errore CORS appare nel browser, ma non in Postman.


1
Sì, non posso sottolineare abbastanza perché questo piccolo dettaglio meriti qualche attenzione. Quando si parla di sicurezza, è fondamentale menzionare che CORS è forte quanto il client che lo implementa. Quindi immagina di prendere un semplice HttpClient (codice lato server) e creare un proxy, che poi fa le tue richieste ... La sicurezza può essere completamente aggirata, lasciando davvero lo standard CORS come una soluzione scadente
Christopher Bonitz

7

Nell'indagine di seguito come API, utilizzo http://example.com invece di http: // myApiUrl / login dalla tua domanda, perché questa prima funziona.

Presumo che la tua pagina sia su http: //my-site.local: 8088 .

Il motivo per cui vedi risultati diversi è che Postman:

  • imposta intestazione Host=example.com(la tua API)
  • NON impostare l'intestazione Origin

Questo è simile al modo in cui i browser inviano le richieste quando il sito e l'API hanno lo stesso dominio (i browser impostano anche l'elemento di intestazione Referer=http://my-site.local:8088, tuttavia non lo vedo in Postman). Quando l' Originintestazione non è impostata, generalmente i server consentono tali richieste per impostazione predefinita.

Inserisci qui la descrizione dell'immagine

Questo è il modo standard in cui Postman invia le richieste. Ma un browser invia richieste in modo diverso quando il sito e l'API hanno domini diversi , quindi si verifica CORS e il browser automaticamente:

  • imposta l'intestazione Host=example.com(la tua come API)
  • imposta l'intestazione Origin=http://my-site.local:8088(il tuo sito)

(L'intestazione Refererha lo stesso valore di Origin). E ora nella scheda Console e reti di Chrome vedrai:

Inserisci qui la descrizione dell'immagine

Inserisci qui la descrizione dell'immagine

Quando hai Host != Originquesto è CORS, e quando il server rileva tale richiesta, di solito lo blocca per impostazione predefinita .

Origin=nullviene impostato quando si apre contenuto HTML da una directory locale e invia una richiesta. La stessa situazione è quando si invia una richiesta all'interno di un <iframe>, come nello snippet di seguito (ma qui l' Hostintestazione non è impostata affatto) - in generale, ovunque la specifica HTML dice origine opaca, è possibile tradurla in Origin=null. Ulteriori informazioni al riguardo sono disponibili qui .

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

Se non si utilizza una semplice richiesta CORS, in genere il browser invia automaticamente anche una richiesta OPTIONS prima di inviare la richiesta principale: ulteriori informazioni sono disponibili qui . Lo snippet di seguito lo mostra:

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)

È possibile modificare la configurazione del server per consentire le richieste CORS.

Ecco una configurazione di esempio che attiva CORS su nginx (file nginx.conf) - fai molta attenzione alle impostazioni always/"$http_origin"per nginx e "*"per Apache - questo sbloccherà CORS da qualsiasi dominio.

Ecco una configurazione di esempio che attiva CORS su Apache (file .htaccess)


2

Si è verificato lo stesso errore in un caso d'uso diverso.

Caso d'uso: in chrome quando si tenta di chiamare il punto finale REST Spring in angolare.

inserisci qui la descrizione dell'immagine

Soluzione: aggiungere l' annotazione @CrossOrigin ("*") in cima alla rispettiva classe del controller.

inserisci qui la descrizione dell'immagine


Uso localhost invece di * per sicurezza
neo7bf

-1

Se usi .NET come livello intermedio, controlla chiaramente l'attributo route, ad esempio,

Ho avuto un problema quando era così,

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

Risolto da questo,

[Route("something/{somethingLong:long}")] //No space

-1

Solo per il progetto API Web .NET Core, aggiungi le seguenti modifiche:

  1. Aggiungere il seguente codice dopo la services.AddMvc()riga nel ConfigureServices()metodo del file Startup.cs:
services.AddCors(allowsites=>{allowsites.AddPolicy("AllowOrigin", options => options.AllowAnyOrigin());
            });
  1. Aggiungere il seguente codice dopo la app.UseMvc()riga nel Configure()metodo del file Startup.cs:
app.UseCors(options => options.AllowAnyOrigin());
  1. Apri il controller a cui desideri accedere al di fuori del dominio e aggiungi questo attributo seguente a livello di controller:
[EnableCors("AllowOrigin")]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.