La risposta alla richiesta di verifica preliminare non supera il controllo del controllo di accesso


458

Ricevo questo errore utilizzando ngResource per chiamare un'API REST su Amazon Web Services:

XMLHttpRequest non può caricare http://server.apiurl.com:8000/s/login?login=facebook . La risposta alla richiesta di verifica preliminare non supera il controllo del controllo di accesso: non è presente alcuna intestazione "Access-Control-Allow-Origin" sulla risorsa richiesta. L'origine ' http: // localhost ' non è quindi consentito l'accesso. Errore 405

Servizio:

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'}
            });
}]);

controller:

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

Sto usando Chrome e non so cos'altro fare per risolvere questo problema. Ho persino configurato il server per accettare le intestazioni dall'origine localhost.


confuso: hai "configurato il server" o questo è un "api di riposo sul servizio web di Amazon"?
dandavis,

3
Chiaramente non hai fatto abbastanza per abilitare CORS sul lato server. Pubblica campione di header di risposta
charlietfl

4
In ogni caso i tuoi voti negativi sono sbagliati. Ospita i suoi file sul suo computer locale. Non importa che tipo di conf faccia sul back-end. Angolare non consentirà questo pre-volo.
E. Maggini,

3
Grazie per i commenti, ha funzionato quando ho impostato il browser per girare di sicurezza
Andre Mendes

1
@Andre Ma disattivare la sicurezza è solo una brutta soluzione in cui stai compromettendo la sicurezza, non risolve il tuo problema ...
shivi

Risposte:


241

Si verificano problemi con CORS.

Esistono diversi modi per risolvere questo problema.

  1. Disattiva CORS. Ad esempio: come disattivare cors in cromo
  2. Usa un plugin per il tuo browser
  3. Utilizzare un proxy come nginx. esempio di come impostare
  4. Passa attraverso la configurazione necessaria per il tuo server. Questo è più un fattore del server web che hai caricato sulla tua istanza EC2 (presumendo che questo sia ciò che intendi per "servizio web Amazon"). Per il tuo server specifico puoi fare riferimento al sito Web di abilitazione CORS.

Più verbalmente, stai provando ad accedere a api.serverurl.com da localhost. Questa è la definizione esatta di richiesta tra domini.

O spegnendolo solo per completare il tuo lavoro (OK, metti scarsa sicurezza per te se visiti altri siti e butti la lattina lungo la strada) puoi usare un proxy che fa pensare al tuo browser che tutte le richieste provengano dall'host locale quando davvero hai un server locale che poi chiama il server remoto.

quindi api.serverurl.com potrebbe diventare localhost: 8000 / api e il tuo nginx locale o altro proxy invierà alla destinazione corretta.


Ora a grande richiesta, informazioni CORS al 100% in più .... stesso grande gusto!


E per i downvoter .... bypassare CORS è esattamente ciò che viene mostrato per coloro che semplicemente imparano il front-end. https://codecraft.tv/courses/angular/http/http-with-promises/


776
lasciato fuori quello ovvio di implementare correttamente CORS
charlietfl

40
È facile votare in negativo. Meno facile correre il rischio, amico mio. E tutti questi funzionano esattamente in un ambiente di sviluppo.
E. Maggini,

3
In realtà ha funzionato. Ho aggiunto la bandiera per disabilitare la sicurezza Web. Per lo sviluppo va bene.
Andre Mendes,

15
@charlietfl How?
GreenAsJade,

3
Grazie mi hai salvato la giornata. Utilizzato solo per la prima opzione: C: \ Programmi (x86) \ Google \ Chrome \ Application> chrome.exe --user-data-dir = "C: \ Chrome dev session" --dable-web-security. Da: stackoverflow.com/questions/3102819/...
Harsimer

169

Il mio "API Server" è un'applicazione PHP, quindi per risolvere questo problema ho trovato la seguente soluzione che funziona:

Posiziona le linee in 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');

3
Sono d'accordo, questo è meglio della risposta accettata anche se fai attenzione quando copi queste righe, assicurati di modificare i metodi e l'origine.
Amir Savand,

11
Dove inserirlo in un progetto Angular 6?
whatthefish

@CodyBugstein e whatthefish hanno messo prima di ogni uscita
Garet Claborn il

La mia app client ha smesso di funzionare quando ho aggiunto un'intestazione richiesta solo da alcuni server. Se la richiesta include intestazioni personalizzate, dovranno essere elencate in Access-Control-Allow-Headers.
z0r

47

In api web AspNetCore, questo problema è stato risolto aggiungendo "Microsoft.AspNetCore.Cors" (versione 1.1.1) e aggiungendo le seguenti modifiche su Startup.cs.

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

e

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


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

e indossare [EnableCors("AllowAllHeaders")]il controller.


18
Questa è una buona risposta se si desidera creare vulnerabilità di scripting tra siti! Per favore, non farlo mai! Specifica i tuoi domini a cui puoi accedere per evitare problemi di sicurezza. CORS è lì per un motivo.
paqogomez,

2
Giusto per chiarire @paqogomez, nel metodo ConfigureServices: services.AddCors (options => {options.AddPolicy ("AllowSpecificOrigin", builder => {builder.WithOrigins (" localhost" ) .AllowAnyOrigin () .AllowAnyHeader (). AllowAnyMethod ();});}); e nel tuo metodo Configure: app.UseCors ("AllowSpecificOrigin");
Francisco Tena,

28

Ci sono alcuni avvertimenti quando si tratta di CORS. Innanzitutto, non consente i caratteri jolly, *ma non mi trattenere su questo, l'ho letto da qualche parte e non riesco a trovare l'articolo ora.

Se stai effettuando richieste da un dominio diverso, devi aggiungere le intestazioni di origine consentite.

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

Se si stanno facendo le richieste che riguardano le risorse del server come POST / PUT / PATCH, e se il tipo MIME è diverso da quello seguente application/x-www-form-urlencoded, multipart/form-datao text/plainil browser automaticamente fare un OPZIONI pre-volo richiedono di verificare con il server se lo permetterebbe .

Pertanto, l'API / il server deve gestire tali richieste OPTIONS di conseguenza, è necessario rispondere con l'appropriato access control headerse deve essere il codice di stato della risposta http 200.

Le intestazioni dovrebbero essere qualcosa del genere, adattale alle tue esigenze:

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

L'intestazione max-age è importante, nel mio caso, non funzionerebbe senza di essa, suppongo che il browser abbia bisogno delle informazioni per quanto tempo sono validi i "diritti di accesso".

Inoltre, se stai realizzando ad es. A POST richiesta con application/jsonmime da un dominio diverso, devi anche aggiungere l'intestazione di origine consentita precedentemente menzionata, quindi sarebbe simile a questa:

   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

Quando il pre-volo ha successo e ottiene tutte le informazioni necessarie verrà effettuata la tua richiesta effettiva.

In generale, qualunque sia l' Access-Controlintestazione richiesta nella richiesta iniziale o pre-volo, dovrebbe essere data nella risposta affinché funzioni.

C'è un buon esempio nei documenti MDN qui su questo link e dovresti anche dare un'occhiata a questo post SO


1
Ecco l'articolo di Mozilla che parla di come non puoi usare i caratteri jolly per l'origine del cors: Link Quindi apparentemente questo vale solo quando si usano le credenziali (se ho capito bene)
Helzgate,

Sto usando i caratteri jolly e invio un token al portatore per autorizzare la richiesta e funziona correttamente, quindi non sono sicuro di cosa si riferisca il link che ho fornito sopra per quanto riguarda le credenziali. Il mio problema era che quando ho inserito la mia politica CORS in .Net Core non l'ho aggiunto .AllowCredentials(). Dopo aver aggiunto .AllowCredentials()tutto ha funzionato.
Helzgate,

15

JavaScript XMLHttpRequest e Fetch seguono la stessa politica di origine. Pertanto, un'applicazione Web che utilizza XMLHttpRequest o Fetch potrebbe solo inviare richieste HTTP al proprio dominio.

Fonte: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

Devi inviare l' intestazione Access-Control-Allow-Origin: * HTTP dal tuo server.

Se si utilizza Apache come server HTTP, è possibile aggiungerlo al file di configurazione di Apache in questo modo:

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

Mod_headers è abilitato di default in Apache, tuttavia, potresti voler assicurarti che sia abilitato eseguendo:

 a2enmod headers

Dove posso trovare il mio file di configurazione di Apache?
Shubham Arya,

@ShubhamArya su Linux Debian la posizione predefinita è:/etc/apache2/apache2.conf
Tadej

dove posso trovarlo in windows?
Shubham Arya,

10

Se stai scrivendo un'estensione di Chrome

Devi aggiungere manifest.jsonle autorizzazioni per i tuoi domini.

"permissions": [
   "http://example.com/*",
   "https://example.com/*"
]

1
Controlla anche se hai il prefisso www
Vlas Bashynskyi,

8

Se si utilizza il server IIS per caso. puoi impostare le intestazioni seguenti nell'opzione Intestazioni richieste 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';

con questo tutto post, get etc., funzionerà bene.



5

In PHP puoi aggiungere le intestazioni:

<?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: *");
...

grazie, ha funzionato per me! in ambiente di test e produzione. Anche usando https: //
Jose Seie il

1
@atiruz Grazie per la soluzione. Funziona quando ho aggiunto la rigaheader ("Access-Control-Expose-Headers: Content-Length, X-JSON");
Silambarasan RD

5

Per risolvere i problemi relativi alle richieste di origine incrociata in un'applicazione NS JS:

npm i cors

E aggiungi semplicemente le righe sottostanti a app.js

let cors = require('cors')
app.use(cors())

3
funziona solo con le app js express, non con tutte le app nodo
DrCord,

3

Nel mio file di configurazione di Apache VirtualHost, ho aggiunto le seguenti righe:

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]

3

Per quelli stanno usando Lambda Integrated Proxy con API Gateway . È necessario configurare la funzione lambda come se si inoltrasse direttamente le richieste, il che significa che la funzione dovrebbe impostare correttamente le intestazioni di risposta. (Se si utilizzano funzioni lambda personalizzate, questo verrà gestito dal gateway API.)

//In your lambda's index.handler():
exports.handler = (event, context, callback) => {
     //on success:
     callback(null, {
           statusCode: 200,
           headers: {
                "Access-Control-Allow-Origin" : "*"
           }
     }
}

1
Voglio anche parlare e menzionare un grande gotcha che non penso documenti AWS. Supponi di utilizzare il gateway API per eseguire il proxy della tua funzione lambda e di utilizzare alcune API in quella funzione lambda. Se tale API restituisce un codice di successo non 200 e non hai aggiunto il codice di successo non 200 alla risposta del metodo nel gateway API , riceverai un errore e non vedrai la tua risposta riuscita . Esempi per questo: Sendgrid e Twilio hanno codici di successo non 200.
Stephen Tetreault,

3

Penso che disabilitare CORS da Chrome non sia un buon modo , perché se lo stai usando in modalità ionica, sicuramente in Mobile Build il problema aumenterà di nuovo.

Quindi meglio risolvere nel tuo backend.

Prima di tutto nell'intestazione, devi impostare-

  • header ('Access-Control-Allow-Origin: *');
  • header ('Header set Access-Control-Allow-Headers: "Origin, X-Requested-With, Content-Type, Accept"');

E se l'API si sta comportando come GET e POST entrambi, imposta anche l'intestazione-

if ($ _SERVER ['REQUEST_METHOD'] == 'OPTIONS') {if (isset ($ _ SERVER ['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) header ("Accesso-Controllo-Consenti-Metodi: OTTIENI, POST, OPZIONI");
if (isset ($ _ SERVER ['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) header ("Access-Control-Allow-Headers:
{$ _SERVER ['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}"); exit (0); }


3

Una causa molto comune di questo errore potrebbe essere che l'API host avesse mappato la richiesta a un metodo http (ad esempio PUT) e che il client API stesse chiamando l'API utilizzando un metodo http diverso (ad esempio POST o GET)


Stavo implementando CORS correttamente nel mio server ma ho dimenticato di aggiungere il PUTmetodo
fguillen,

3

Il nostro team lo vede occasionalmente usando Vue, axios e un WebApi C #. L'aggiunta di un attributo route sull'endpoint che si sta tentando di raggiungere risolve per noi.

[Route("ControllerName/Endpoint")]
[HttpOptions, HttpPost]
public IHttpActionResult Endpoint() { }

Non siamo davvero sicuri del perché. Lol. Se qualcuno me lo fa sapere!
w00ngy,

1

Ho riscontrato questo problema quando il server DNS era impostato su 8.8.8.8 (google's). In realtà, il problema era nel router, la mia applicazione ha cercato di connettersi con il server tramite Google, non localmente (per il mio caso particolare). Ho rimosso 8.8.8.8 e questo ha risolto il problema. So che questo problema è stato risolto dalle impostazioni CORS, ma forse qualcuno avrà lo stesso problema


1

Sto usando AWS sdk per i caricamenti, dopo aver trascorso un po 'di tempo a cercare online mi sono imbattuto in questo thread. grazie a @lsimoneau 45581857 si scopre che stava succedendo esattamente la stessa cosa. Ho semplicemente indirizzato la mia richiesta Url alla regione sul mio bucket allegando l'opzione region e ha funzionato.

 const s3 = new AWS.S3({
 accessKeyId: config.awsAccessKeyID,
 secretAccessKey: config.awsSecretAccessKey,
 region: 'eu-west-2'  // add region here });

0

Le distribuzioni standalone di GeoServer includono il server delle applicazioni Jetty. Abilita la condivisione di risorse tra origini (CORS) per consentire alle applicazioni JavaScript esterne al tuo dominio di utilizzare GeoServer.

Rimuovi dal commento quanto segue <filter>e <filter-mapping>da 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>

Ciò non ha aggiunto nulla all'intestazione della risposta, quindi non ha funzionato
JollyRoger

1
non usando GeoServer, ma questa clip mi ha aiutato a conoscere le impostazioni che dovrei usare sull'app che riceve la chiamata.
Matt Felzani,

0

È facile risolvere questo problema con pochi passaggi facilmente, senza preoccuparsi di nulla. Si prega di seguire i passaggi per risolverlo.

  1. aperto ( https://www.npmjs.com/package/cors#enabling-cors-pre-flight )
  2. vai all'installazione e copia il comando npm install cors per installare tramite il nodo terminale
  3. vai su Uso semplice (Abilita tutte le richieste CORS) scorrendo.quindi copia e incolla la dichiarazione completa nel tuo progetto ed eseguila ... che funzionerà di sicuro .. copia il codice di commento e incolla in ur.s. o qualsiasi altro progetto e provare .. questo funzionerà. Questo sbloccherà ogni condivisione di risorse tra le origini .. così possiamo passare da un servizio all'altro

1
var express = richiedono ('express') var cors = richiedono ('cors') var app = express () app.use (cors ()) app.get ('/ products /: id', function (req, res, successivo) {res.json ({msg: 'Abilita CORS per tutte le origini!'})}) app.listen (80, function () {console.log ('Server Web abilitato per CORS in ascolto sulla porta 80' )})
Rahul sah,

-1

Qualcosa che è molto facile perdere ...

IN Esplora soluzioni, fai clic con il pulsante destro del mouse su api-project. Nella finestra delle proprietà impostare "Autenticazione anonima" su Abilitato !!!


-8

Disabilita la sicurezza di Chrome. Crea un collegamento di Chrome facendo clic con il tasto destro -> proprietà -> destinazione, incolla questo "C: \ Programmi (x86) \ Google \ Chrome \ Application \ chrome.exe" --disable-web-security --user -data-dir = "c: / chromedev"

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.